The file is not the whole problem

A PDF generation API receives data, applies a template and returns a document. That description is accurate but incomplete. In production, you also need to know which template version ran, why a generation failed, how long the output remains available and how duplicate documents are prevented.

The right starting point is therefore a traceable job, not a single blocking conversion call.

A reliable flow

  1. Your server selects a template or exact version.
  2. It builds a payload containing only document data.
  3. The API validates the request and creates a job.
  4. A worker renders the document in the background.
  5. Your application polls state or receives a webhook.
  6. The file is downloaded through a short-lived URL.
{
  "templateVersionId": "tv_01JDC12",
  "data": {
    "invoice": { "number": "INV-2048", "date": "2026-09-08" },
    "customer": { "name": "Acme Labs" },
    "total": 4850,
    "currency": "EUR"
  }
}

This boundary protects business logic. The template owns presentation; your application owns the meaning and correctness of the data.

Why asynchronous jobs help

Rendering time depends on template weight, images, fonts and the rendering engine. Holding an HTTP request open increases timeout risk and makes recovery harder.

A job can expose four simple states: pending, processing, completed and failed. Keep the job identifier next to your business reference. When an incident occurs, you can connect the output to the exact call that produced it.

Retry without creating duplicates

Blind retries can produce two copies of the same invoice. Use an idempotency key or a stable fingerprint derived from the business reference, template version and normalized payload.

Retry transient failures such as temporary network errors or service saturation. Invalid input does not become valid after five attempts.

Minimum security controls

Production checklist

Frequently asked questions

Should the API return the PDF directly?

That can work for a small, non-critical document. For a business pipeline, an asynchronous job usually provides better observability and safer recovery.

Should every request upload the template?

Not necessarily. A stored template referenced by identifier reduces transfer and supports version management. Pinning an exact version makes output more reproducible.

Where should the output live?

Use private object storage and a short signed URL. Retention should match document sensitivity and the obligations of your business.