PDF templates
Render via API
POST /v1/pdf-templates/:id/render with your data.
Once a PDF is imported as a template,
filling it is a single call: POST /v1/pdf-templates/:id/render with your
values. The response is the finished PDF binary — same design, new data.
Render
Send a variables object mapping each variable name to its value:
curl -X POST https://api.pdf-forge.dev/v1/pdf-templates/$TEMPLATE_ID/render \
-H "Authorization: Bearer $PDFFORGE_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"variables": {
"client_name": "ACME Corp",
"total": "250,000 FCFA"
}
}' \
--output invoice.pdfimport { PdfForge } from "@pdfforge/core";
const client = new PdfForge({ apiKey: process.env.PDFFORGE_API_KEY });
const pdf = await client.pdfTemplates.render(templateId, {
client_name: "ACME Corp",
total: "250,000 FCFA",
});
await pdf.save("invoice.pdf");The response is the PDF itself
Like the generation endpoints, render answers with the application/pdf
binary (Content-Disposition: attachment; filename="filled.pdf"), not a
JSON payload. Save the response body directly.
How values are applied
- Any variable omitted from
variableskeeps its stored default — so you only send what changes. - Each value replaces its span in place: the original text is masked and your value is redrawn with the span's recorded colour, size and font. This works on vector, Type3 and OCR/scanned text alike.
- Values are strings. A table variable takes an array instead — see Dynamic tables.
- A template with no variables to fill returns
400.
Find the template id
Don't have the id handy? List your templates:
const templates = await client.pdfTemplates.list();
// each: { id, name, slug, variables, page_count, size_bytes, updated_at }The variables array on each item tells you exactly which names render
expects.
Next steps
- Import a PDF — create the template you render here.
- Dynamic tables — fill a table from an array of rows.
- n8n — trigger a render from a no-code workflow.