Skip to content

OP-MERGE-DOCUMENTS: Merge documents

Merges a set of input documents into one output document, converting any non-PDF inputs to PDF first, and optionally producing PDF/A output.

Field Value
Operation ID OP-MERGE-DOCUMENTS
Trigger Client submits POST v1/merge with a MergeRequest body
Entry endpoint POST v1/merge
Owning component MergeController.Merge(MergeRequest) → IPdfService.Merge(request)
Inputs MergeRequest body (Documents array, Options)
Outputs PdfResult (Status, Message, Document, TrackingId); a PDFTracking row created/updated
Failure response A null body fails as a framework error; other caught exceptions are logged and returned as Ok(new PdfResult(message)) — HTTP 200

Steps

  1. Enforce.ArgumentNotNull(request, "request") runs before the try block (BR-PDFAPI-001).
  2. On failure (request == null): the exception escapes to the framework — not caught by the action, so no PdfResult envelope is produced; the framework produces exception detail (IncludeErrorDetailPolicy.Always) before ApiResponseHandler runs, and the final client-visible envelope is unknown** (see Endpoints: Error response shape).
  3. request.Options ??= new PdfOptions() substitutes a default (non-PDF/A) options object when the caller omitted Options (BR-PDFAPI-002).
  4. The remaining call is wrapped in try/catch (BR-PDFAPI-017).
  5. On any exception: _logService.LogException("pdfapi", "Merge", "<detail>", ex), then Ok(new PdfResult(ex.Message, request: request)) — HTTP 200.
  6. If tracking is enabled (default, or forced on by SendHeatEmailOnFailure, BR-PDFAPI-010), PdfTrackingService.CreateTrackingRecord inserts a PDFTracking row.
  7. Each non-PDF input document is converted to PDF first; if any pre-conversion fails, a PdfException is thrown and the entire merge is abandoned — no partial output is produced (BR-PDFAPI-006).
  8. PdfMerger.Merge (Syncfusion.Pdf.PdfDocument.Merge) combines the converted/validated documents into one output.

This merge logic is implemented in PdfApi.SyncFusionCore (PdfMerger.Merge), documented in full at Merge document ranges into one PDF (OP-SFC-012); its behavior is summarized here only as observed on this request path.

Origin: The document-merge behavior described in this step is implemented in PdfApi.SyncFusionCore, not in PdfAPI. See the linked operation page for the full delegated logic. 7. If Options.IsPdfa and the merged output fails ValidatePdfA, OutputFormat is silently downgraded to PdfFormat.Pdf rather than failing the request (BR-PDFAPI-007). 8. On the ActivePDF processor: a PDF/A production failure is retried as plain PDF, and configured pdfApi.ErrorsToRetry error codes trigger a whole-operation retry (BR-PDFAPI-020). 9. FinalizeResult stamps TrackingId, PdfProcessorType, FilePath, then persists the terminal tracking status via PdfTrackingService.UpdateTrackingRecord. 10. If the result failed and SendHeatEmailOnFailure is set, an incident email is sent (BR-PDFAPI-015). 11. The controller returns Ok(result) — HTTP 200 regardless of whether the merge succeeded or failed.

Process flow

The following diagram shows the pre-conversion, merge, PDF/A-downgrade, and incident-email sequence for a merge request.

flowchart TD
    A["POST v1/merge"] --> B{"request null?"}
    B -->|Yes| C["Framework 500 error, no PdfResult"]
    B -->|No| D["Substitute default Options if null"]
    D --> E["Create tracking record"]
    E --> F["Convert non-PDF inputs to PDF"]
    F -->|Any pre-conversion fails| G["PdfException: merge abandoned"]
    F -->|All succeed| H["PdfMerger.Merge combines documents"]
    H --> I{"IsPdfa requested and<br>validation fails?"}
    I -->|Yes| J["Silently downgrade to Pdf"]
    I -->|No| K["Keep requested format"]
    J --> L["FinalizeResult: persist terminal status"]
    K --> L
    L --> M{"Result failed and<br>SendHeatEmailOnFailure?"}
    M -->|Yes| N["Send incident email"]
    M -->|No| O["Ok result"]
    N --> O

Transaction and side effects

Aspect Finding
Unit of work IUnitOfWorkFactory("oracle"), InstancePerRequest
Commit point PdfTrackingService.CreateTrackingRecord and UpdateTrackingRecord, each bracketed by _uow.Begin()/_uow.Commit()
Records written PDFTracking (data model)
Downstream calls Outbound SMTP email on failure when SendHeatEmailOnFailure is set
Repeat-call behavior Each call creates a new tracking record; not idempotent

Logging

Surface Written content
ILogService.LogException "pdfapi", "Merge", and exception detail, on any caught failure

Error handling

  • Null request body: escapes to the framework before the try block, producing framework exception detail before ApiResponseHandler runs; the final client-visible envelope is unknown**, and no PdfResult is produced (BR-PDFAPI-001).
  • Pre-conversion failure on any input: PdfException, caught, logged, entire merge abandoned, 200 with a failure PdfResult (BR-PDFAPI-006).
  • PDF/A requested but not achieved: not an error — silent downgrade (BR-PDFAPI-007).

Note: Statements marked with ** could not be confirmed; treat as unknown until verified.

Sources

  • PdfAPI\Controllers\v1\MergeController.cs
  • PdfAPI\Services\PdfService.cs
  • PdfAPI\Services\PdfTrackingService.cs
  • PdfAPI\Services\Syncfusion\SyncfusionPdfService.cs
  • PdfAPI\Services\ActivePdf\ActivePdfService.cs
  • PdfAPI.Core\Request\MergeRequest.cs