Generate

Templates & variables

Reusable templates with variables, conditions and tables.

Store the HTML once as a template, then generate PDFs by sending only the data. Templates use Handlebars syntax: {{variable}}, {{#if}}, {{#each}}.

Create a template

curl -X POST https://api.pdf-forge.dev/v1/templates \
  -H "Authorization: Bearer $PDFFORGE_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Invoice",
    "slug": "invoice",
    "html": "<h1>Invoice {{number}}</h1><table>{{#each items}}<tr><td>{{label}}</td><td>{{fmtMoney price \"XOF\"}}</td></tr>{{/each}}</table>",
    "schema": { "required": ["number", "items"] }
  }'

Returns 201 with the template (id, slug, version, ...).

const template = await client.templates.create({
  name: "Invoice",
  slug: "invoice",
  html: `<h1>Invoice {{number}}</h1>
    <table>{{#each items}}
      <tr><td>{{label}}</td><td>{{fmtMoney price "XOF"}}</td></tr>
    {{/each}}</table>`,
  schema: { required: ["number", "items"] },
});

name and html are required. Optional: slug (derived from the name if omitted), description, css, schema (validation of the data you send at generation time), testData, pdfOptions.

Manage templates with GET /v1/templates, GET /v1/templates/:id, PUT /v1/templates/:id (versioned — the previous version is kept) and DELETE /v1/templates/:id. The SDK mirrors these as client.templates.list(), .get(id), .update(id, params), .delete(id).

Generate from a template

POST /v1/generate/template accepts the template id or slug plus your data, and returns the PDF binary:

curl -X POST https://api.pdf-forge.dev/v1/generate/template \
  -H "Authorization: Bearer $PDFFORGE_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "template": "invoice",
    "data": {
      "number": "2026-001",
      "items": [{ "label": "Consulting", "price": 250000 }]
    },
    "options": { "format": "A4" }
  }' \
  --output invoice.pdf
const pdf = await client.template("invoice", {
  number: "2026-001",
  items: [{ label: "Consulting", price: 250000 }],
});

If data violates the template schema, the API returns 400 schema_validation_failed with the failing fields.

Helpers

Beyond standard Handlebars ({{#if}}, {{#each}}, {{else}}), pdfforge registers formatting helpers:

HelperExampleOutput
fmtMoney{{fmtMoney total "XOF"}}250 000 FCFA (FR formatting)
fmtNumber{{fmtNumber qty}}thousands-separated number
fmtDate{{fmtDate issued_at}}ISO date → dd/MM/yyyy
colTotal{{colTotal items "price" "money" "XOF"}}sum of a column, formatted
uppercase{{uppercase client.name}}ACME SARL
eq{{#if (eq status "paid")}}...{{/if}}equality test

Preview without consuming quota

POST /v1/templates/:id/preview renders the template with data and returns a watermarked, disposable PDF that does not count against your quota or appear in your logs — ideal for a live editor preview.

Print-perfect engine (Typst)

Templates built as block documents in the visual editor can be rendered with "options": { "engine": "typst" } — a deterministic print engine that also supports ISO output standards via pdfStandard: "a-2b" / "a-3b" (PDF/A archival) and "ua-1" (PDF/UA accessible). Chrome cannot produce those.

Next steps

On this page