Skip to content

Business rules

Every rule below was traced to an enforcement point in source. Rules marked (delegated) are implemented in a referenced library (PdfAPI.Core or PdfApi.SyncFusionCore) but are enforced on this API's request path, so they are catalogued here with their true location.

Rule catalog

ID Rule Origin Reached from
BR-PDFAPI-001 Null merge request bypasses the error envelope api POST v1/merge
BR-PDFAPI-002 Default merge options substitution api POST v1/merge
BR-PDFAPI-003 Processor selection by configuration api Every controller construction
BR-PDFAPI-004 Extraction requires PDF validation api POST v1/extract
BR-PDFAPI-005 PDF validity by file signature library (delegated) Multiple endpoints
BR-PDFAPI-006 Merge aborts entirely on pre-conversion failure api POST v1/merge
BR-PDFAPI-007 PDF-A output silently downgraded api POST v1/merge
BR-PDFAPI-008 Unsupported extension leaves status at default library (delegated) POST v1/convert, POST v1/convert/{fileExtension}
BR-PDFAPI-009 Plain text double conversion library (delegated) POST v1/convert, POST v1/convert/{fileExtension}
BR-PDFAPI-010 Tracking forced on with heat email library (delegated) Convert/merge/extract
BR-PDFAPI-011 Tracking status lifecycle api All tracked endpoints
BR-PDFAPI-012 Tracking degrades gracefully without a unit of work api All tracking operations
BR-PDFAPI-013 Download requires succeeded status and output path api GET v1/legacy/download/{trackingId}
BR-PDFAPI-014 Status check polling loop api GET v1/info/track/{trackingId}
BR-PDFAPI-015 Incident email on failure api Convert/merge/extract on failure
BR-PDFAPI-016 Save input to temp storage api Convert/merge/extract
BR-PDFAPI-017 Processing failures return 200 with a PdfResult api Convert/extract/merge/download
BR-PDFAPI-018 Page range clamping and reversal library (delegated) POST v1/extract
BR-PDFAPI-019 Skip conversion when input is already PDF api POST v1/convert, POST v1/convert/{fileExtension}
BR-PDFAPI-020 ActivePDF retry behavior api Convert/merge (ActivePDF processor only)
BR-PDFAPI-021 Form field inspection client selection api POST v1/info/fields/exist, POST v1/info/fields/flatten

BR-PDFAPI-001 Null merge request bypasses the error envelope

Field Value
Statement A merge request body must not be null; the guard runs before the action's error envelope, so a null body fails as a framework error rather than a PdfResult
Trigger POST v1/merge invoked with a null request body
Enforcement Enforce.ArgumentNotNull(request, "request"), called outside the surrounding try block
Origin api
Reached from POST v1/merge
Outcome Framework-level error response, not the per-action PdfResult envelope used by every other failure on this action
Source PdfAPI\Controllers\v1\MergeController.cs

BR-PDFAPI-002 Default merge options substitution

Field Value
Statement When a merge request omits Options, a default PdfOptions is substituted (output format Pdf, not PDF/A)
Trigger POST v1/merge invoked with Options == null
Enforcement request.Options ??= new PdfOptions()
Origin api
Reached from POST v1/merge
Outcome Merge proceeds with default (non-PDF/A) options rather than failing
Source PdfAPI\Controllers\v1\MergeController.cs

BR-PDFAPI-003 Processor selection by configuration

Field Value
Statement The PDF processor is selected per request from configuration: pdfapi.pdfservicetype == "activepdf" selects ActivePDF; any other value, including missing, selects Syncfusion
Trigger Every controller constructor call to pdfServiceFactory.Create()
Enforcement PdfServiceFactory.Create() lower-cases the configured value and switches on it; no validation, no failure path for an unrecognized value
Origin api
Reached from Every endpoint (constructor-time)
Outcome Silent fallback to Syncfusion for any value other than the literal "activepdf"
Source PdfAPI\Services\PdfServiceFactory.cs:43

BR-PDFAPI-004 Extraction requires PDF validation

Field Value
Statement Page extraction validates that the source document is a real PDF before any extraction work
Trigger POST v1/extract
Enforcement PdfClientService.ValidatePdf called before PdfExtractor.Extract
Origin api
Reached from POST v1/extract
Outcome Non-PDF input raises PdfException before any extraction occurs
Source PdfAPI\Services\Syncfusion\SyncfusionPdfService.cs

BR-PDFAPI-005 PDF validity by file signature

Field Value
Statement PDF validity is determined by the %PDF- file signature; failure raises a PdfException reporting that the file is not a valid PDF document (exact message text is not visible in this repository — delegated to PdfAPI.Core\Services\PdfClientService.cs)
Trigger Any operation that calls PdfClientService.ValidatePdf or IsPdf
Enforcement Byte-signature check in PdfClientService
Origin library (delegated — PdfAPI.Core\Services\PdfClientService.cs)
Reached from POST v1/extract, POST v1/info/pages/count, POST v1/info/validate, POST v1/info/version
Outcome PdfException on a non-PDF payload wherever this validation path is used; POST v1/info/validate alone returns false instead of throwing (BR-PDFAPI-005 via IsPdf)
Source PdfAPI.Core\Services\PdfClientService.cs

BR-PDFAPI-006 Merge aborts entirely on pre-conversion failure

Field Value
Statement In a merge, every non-PDF input is converted to PDF first; if any pre-conversion fails, a PdfException is thrown and the whole merge is abandoned — no partial output is produced
Trigger POST v1/merge with one or more non-PDF input documents
Enforcement Pre-conversion loop in SyncfusionPdfService.Merge
Origin api
Reached from POST v1/merge
Outcome A single failing input document fails the entire merge request; no documents are merged
Source PdfAPI\Services\Syncfusion\SyncfusionPdfService.cs

BR-PDFAPI-007 PDF-A output silently downgraded

Field Value
Statement When PDF/A output is requested but the produced document fails PDF/A validation, the result is silently downgraded to PdfFormat.Pdf rather than failing the request
Trigger POST v1/merge with Options.IsPdfa == true and the merged output fails ValidatePdfA
Enforcement Conditional downgrade in SyncfusionPdfService.Merge
Origin api
Reached from POST v1/merge
Outcome Caller receives a plain PDF with 200 OK and no explicit failure signal that PDF/A was not honored
Source PdfAPI\Services\Syncfusion\SyncfusionPdfService.cs

BR-PDFAPI-008 Unsupported extension leaves status at default

Field Value
Statement An unrecognized source file extension yields a failure result with message "Unsuppported extension ({ext})" (spelling as in source). The result's Status is left at the enum default NotTracked, not Failed — a caller checking Status == Failed will not detect this case
Trigger POST v1/convert / POST v1/convert/{fileExtension} with an unrecognized extension
Enforcement Extension dispatch switch in ConverterFactory.Convert
Origin library (delegated — PdfApi.SyncFusionCore\Convert\ConverterFactory.cs)
Reached from POST v1/convert, POST v1/convert/{fileExtension}
Outcome PdfResult with a failure message but Status == NotTracked, not Failed — a caller inspecting only Status == Failed misses this case
Source PdfApi.SyncFusionCore\Convert\ConverterFactory.cs

BR-PDFAPI-009 Plain text double conversion

Field Value
Statement Plain-text input is converted twice: txt → intermediate document → PDF, re-entering the PDF conversion path
Trigger POST v1/convert / POST v1/convert/{fileExtension} with a .txt source
Enforcement Two-stage dispatch in ConverterFactory.Convert
Origin library (delegated — PdfApi.SyncFusionCore\Convert\ConverterFactory.cs)
Reached from POST v1/convert, POST v1/convert/{fileExtension}
Outcome Text input incurs two conversion passes rather than one direct conversion
Source PdfApi.SyncFusionCore\Convert\ConverterFactory.cs

BR-PDFAPI-010 Tracking forced on with heat email

Field Value
Statement Tracking is enabled by default and is forced on whenever SendHeatEmailOnFailure is set, regardless of the caller's TrackingEnabled value
Trigger Any convert/merge/extract request with SendHeatEmailOnFailure = true
Enforcement TrackingEnabled getter override in PdfRequest
Origin library (delegated — PdfAPI.Core\Request\PdfRequest.cs)
Reached from POST v1/convert, POST v1/convert/{fileExtension}, POST v1/merge, POST v1/extract
Outcome A caller cannot disable tracking while also requesting incident email notification
Source PdfAPI.Core\Request\PdfRequest.cs

BR-PDFAPI-011 Tracking status lifecycle

Field Value
Statement A tracked request moves SCHED → PROC → terminal (SUCC / ERROR / CANCE / ABORT); these persisted codes map onto the PdfStatus enum
Trigger Any tracked convert/merge/extract request
Enforcement Status transitions in PdfTrackingService
Origin api
Reached from All tracked endpoints
Outcome Consistent status vocabulary between the persisted tracking row and PdfStatus returned to callers
Source PdfAPI\Services\PdfTrackingService.cs

BR-PDFAPI-012 Tracking degrades gracefully without a unit of work

Field Value
Statement When tracking is unavailable (no unit of work), every tracking operation degrades gracefully and returns a non-tracked result instead of failing the request
Trigger _uow == null at the point a tracking operation is invoked
Enforcement if (_uow == null) guard on every method in PdfTrackingService
Origin api
Reached from All tracking operations
Outcome Requests continue to succeed functionally even when tracking persistence is unavailable
Source PdfAPI\Services\PdfTrackingService.cs

BR-PDFAPI-013 Download requires succeeded status and output path

Field Value
Statement A tracked document is downloadable only when its status is Succeeded and a non-null output file path is recorded; otherwise an explanatory failure result is returned with HTTP 200
Trigger GET v1/legacy/download/{trackingId}
Enforcement Status/path check in PdfTrackingService.DownloadByTrackingId
Origin api
Reached from GET v1/legacy/download/{trackingId}
Outcome Callers must inspect PdfResult.Status/Message; HTTP status alone never signals a missing or not-yet-ready document
Source PdfAPI\Services\PdfTrackingService.cs

BR-PDFAPI-014 Status check polling loop

Field Value
Statement A status check polls while the status is Scheduled or Processing, sleeping retryIntervalMilliseconds between reads, up to retryCount attempts; the default retryCount = 0 makes it a single read
Trigger GET v1/info/track/{trackingId}
Enforcement Polling loop in PdfTrackingService.CheckPdfTrackingStatus
Origin api
Reached from GET v1/info/track/{trackingId}
Outcome Caller-controlled synchronous wait for a still-processing tracked request
Source PdfAPI\Services\PdfTrackingService.cs

BR-PDFAPI-015 Incident email on failure

Field Value
Statement A failed request sends an incident email only when the caller set SendHeatEmailOnFailure; the subject is taken from the tracking record's ApplicationError.HeatEmailSubject
Trigger Convert/merge/extract failure with SendHeatEmailOnFailure = true
Enforcement PdfService.SendIncidentEmail, invoked from FinalizeResult
Origin api
Reached from POST v1/convert, POST v1/convert/{fileExtension}, POST v1/merge, POST v1/extract
Outcome Conditional outbound SMTP email on failure, addressed and subjected from configuration/tracking data
Source PdfAPI\Services\PdfService.cs

BR-PDFAPI-016 Save input to temp storage

Field Value
Statement When pdfapi.saveInputToTemp is enabled, the inbound source document is written to temporary storage before processing
Trigger Any convert/merge/extract request when the setting is true
Enforcement Conditional write in PdfService and its use sites
Origin api
Reached from POST v1/convert, POST v1/convert/{fileExtension}, POST v1/merge, POST v1/extract
Outcome Extra disk I/O and a temporary copy of every submitted document when enabled
Source PdfAPI\Services\PdfService.cs:30

BR-PDFAPI-017 Processing failures return 200 with a PdfResult

Field Value
Statement For convert, extract, merge, and download, a processing failure is not an HTTP failure: the exception is logged and returned as a PdfResult carrying a message, with status code 200. Callers must inspect the payload
Trigger Any handled exception inside the per-action try/catch on these four controllers
Enforcement try/catch + ILogService.LogException + Ok(new PdfResult(ex.Message, request: request))
Origin api
Reached from POST v1/convert, POST v1/convert/{fileExtension}, POST v1/extract, POST v1/merge, GET v1/legacy/download/{trackingId}
Outcome HTTP status code alone never signals failure on these five endpoints
Source PdfAPI\Controllers\v1\ConvertController.cs, ExtractController.cs, MergeController.cs, LegacyController.cs

BR-PDFAPI-018 Page range clamping and reversal

Field Value
Statement Page ranges are clamped to the document's page count, out-of-range ranges are skipped rather than erroring, descending ranges extract pages in reverse order, and a single IsOriginal range returns the original file untouched
Trigger POST v1/extract with one or more page ranges
Enforcement Range-handling logic in PageRange and PdfExtractor.Extract
Origin library (delegated — PdfAPI.Core\Extract\PageRange.cs + PdfApi.SyncFusionCore\Extract\PdfExtractor.cs)
Reached from POST v1/extract
Outcome Tolerant range handling — no error for out-of-range or descending page ranges
Source PdfAPI.Core\Extract\PageRange.cs, PdfApi.SyncFusionCore\Extract\PdfExtractor.cs

BR-PDFAPI-019 Skip conversion when input is already PDF

Field Value
Statement When SkipPdf is set (the default) and the input is already a PDF, conversion is short-circuited and the input is returned as the output
Trigger POST v1/convert / POST v1/convert/{fileExtension} with a PDF source and SkipPdf at its default true
Enforcement Short-circuit check in ActivePdfService
Origin api
Reached from POST v1/convert, POST v1/convert/{fileExtension}
Outcome No conversion work is performed for an already-PDF source under the ActivePDF processor
Source PdfAPI\Services\ActivePdf\ActivePdfService.cs, PdfAPI.Core\Request\ConvertRequest.cs

BR-PDFAPI-020 ActivePDF retry behavior

Field Value
Statement On the ActivePDF processor, a PDF/A production failure is retried as plain PDF, and configured error codes (pdfApi.ErrorsToRetry) trigger a retry of the whole operation
Trigger ActivePDF processor conversion/merge failure matching a configured retryable error code, or a PDF/A production failure
Enforcement Retry logic in ActivePdfService
Origin api
Reached from POST v1/convert, POST v1/convert/{fileExtension}, POST v1/merge (ActivePDF processor only)
Outcome Transient ActivePDF failures are retried automatically; PDF/A failures fall back to plain PDF
Source PdfAPI\Services\ActivePdf\ActivePdfService.cs

BR-PDFAPI-021 Form field inspection client selection

Field Value
Statement Form-field inspection and flattening default to the iTextSharp client implementation (useClient = true) and use the Syncfusion helper only when the caller explicitly opts out
Trigger POST v1/info/fields/exist or POST v1/info/fields/flatten
Enforcement useClient parameter branch in InfoController and PdfService
Origin api
Reached from POST v1/info/fields/exist, POST v1/info/fields/flatten
Outcome Two independent code paths (iTextSharp vs Syncfusion) can produce the inspection/flattening result depending on the useClient value
Source PdfAPI\Controllers\v1\InfoController.cs, PdfAPI\Services\PdfService.cs

Note: Statements marked with * were inferred from code structure, naming conventions, or contextual evidence where direct confirmation was not available in source artifacts. Statements marked with ** could not be confirmed; treat as unknown until verified.

Sources

  • PdfAPI\Controllers\v1\ConvertController.cs
  • PdfAPI\Controllers\v1\ExtractController.cs
  • PdfAPI\Controllers\v1\MergeController.cs
  • PdfAPI\Controllers\v1\LegacyController.cs
  • PdfAPI\Controllers\v1\InfoController.cs
  • PdfAPI\Services\PdfServiceFactory.cs
  • PdfAPI\Services\PdfService.cs
  • PdfAPI\Services\PdfTrackingService.cs
  • PdfAPI\Services\Syncfusion\SyncfusionPdfService.cs
  • PdfAPI\Services\ActivePdf\ActivePdfService.cs
  • PdfAPI.Core\Request\PdfRequest.cs
  • PdfAPI.Core\Request\ConvertRequest.cs
  • PdfAPI.Core\Extract\PageRange.cs
  • PdfAPI.Core\Services\PdfClientService.cs
  • PdfApi.SyncFusionCore\Convert\ConverterFactory.cs
  • PdfApi.SyncFusionCore\Extract\PdfExtractor.cs