DocuForge logoDocuForge

blog

PDF Generation for E-commerce: Receipts, Packing Slips, and Returns

When your PDF pipeline cracks at 2 AM and customers are waiting on invoices, debugging headless Chromium is the last thing you want to do. This guide cuts to what actually matters for document automation API in production: templates that render the same way every time, render jobs that survive queue spikes, and an API surface with clear failure modes so on-call is boring.

Updated 2026-02-24

Problem

A product team wants customer-specific PDF output without forking layouts for every customer account.

Model each use case with a dedicated template contract, then standardize payload mapping from upstream systems.

Typst playground

A product team wants customer-specific PDF output without forking layouts for every customer account.

Customer handoff Typst template

Sample JSON payload

#set page(paper: "a4", margin: 18mm)
#set text(font: "Inter", size: 10pt)

#let data = sys.inputs

#text(size: 22pt, weight: "bold")[#data.title]
#v(4pt)
#text(fill: rgb("#64748b"))[#data.reference + " - " + data.date]

#v(12pt)
#block(
  fill: rgb("#f8fafc"),
  stroke: 0.5pt + rgb("#e2e8f0"),
  inset: 12pt,
  radius: 4pt,
)[
  #text(weight: "semibold")[#data.customer]
  #linebreak()
  #text(fill: rgb("#64748b"))[#data.status]
]

#v(12pt)
#table(
  columns: (1fr, auto, auto),
  inset: 7pt,
  stroke: 0.5pt + rgb("#e2e8f0"),
  [*Item*], [*Qty*], [*Amount*],
  ..data.line_items.map(item => (
    item.name,
    str(item.qty),
    "$" + str(item.amount),
  )).flatten(),
)

Customer document

Tenant branded

Customer document

Tenant branded

CustomerAtlas Logistics
ReferenceDOC-2026-219
Date2026-06-16
Rows2
POST /v1/render

Solution & copyable API code

Keep branding and tenant-specific values in data, not forked layouts. This preserves consistency while supporting customization. Design a minimal document schema and transform source events into it at ingestion boundaries. Stable schemas simplify multi-team ownership.

const response = await fetch(`${process.env.DOCUFORGE_API_URL}/v1/render`, {
  method: "POST",
  headers: {
    "X-API-Key": process.env.DOCUFORGE_API_KEY,
    "Content-Type": "application/json",
  },
  body: JSON.stringify({ template_id: "tpl_pdf_generation_for_ecommerce_receipts_packing_slips_and_returns", data: payload }),
});

const pdf = Buffer.from(await response.arrayBuffer());

Customization tips

  • Start with the smallest layout that proves the document contract.
  • Use real customer-shaped sample data before publishing a new version.
  • Keep brand colors, spacing, and repeated footer copy in shared template variables.
  • Pass customer-specific values through JSON data instead of forking the template.
  • Store one approved sample payload per template so preview regressions are easy to catch.

Puntos clave

  • One template family per document intent scales better than per-customer forks.
  • Normalization layers prevent upstream system changes from breaking layout logic.
  • Webhooks and retries should be signed and auditable.
  • Security and compliance requirements should be encoded in routing and key scope.

Why teams choose DocuForge for this workflow

  • API-key and JWT paths are separated by endpoint intent.
  • Webhook signatures and HTTPS validation are enforced in production paths.
  • Version promotion supports controlled rollout across customer segments.

Recursos relacionados

FAQ

How do we handle per-customer branding without template sprawl?

Store brand variables in payload data and keep the underlying template shared per document class.

What is the safest rollout strategy?

Publish new versions behind a subset of traffic, compare outputs, then promote globally once parity checks pass.

Recursos relacionados

Entrega mas rapido con una API orientada a plantillas

Prueba plantillas en el playground y reutiliza la misma solicitud en produccion.