Integrate PDFEx into your application — or let an AI agent design templates and generate PDFs programmatically.
All API requests require an API key. Manage keys in the dashboard under API Keys. Include the key in the Authorization header. All responses use the envelope { "success": boolean, ... }. Errors include error and often details — field-level messages agents can act on.
Authorization: Bearer pdfex_<YOUR_API_KEY>Send your data and template ID to generate a single-use token. This operation is non-blocking and instaneous.
curl -X POST https://pdfex.io/api/pdf/token \ -H "Authorization: Bearer YOUR_KEY" \ -H "Content-Type: application/json" \ -d '{
"template_id": "651...",
"data": { "name": "Alice" }
}'{
"success": true,
"token": "65eb...",
"url": "/api/pdf/65eb..."
}Use the returned URL or Token to fetch the generated PDF file.
curl -O https://pdfex.io/api/pdf/65eb...PDF links expire 15 minutes after the token is issued.
Create and manage PDF templates programmatically. Designed for AI agents and automation: draft a template, preview it, fix validation errors, save it, then generate PDFs on demand.
HTML templates use Handlebars placeholders, rendered by headless Chromium. Write ordinary HTML + CSS; use {{variable}} for data and {{#each items}}...{{/each}} for repeating rows.
data: URIs.@page and page-break-* for pagination./api/templates{
"name": "Invoice",
"engine": "html",
"html_template": "<html><head><style>body{font-family:Helvetica,Arial,sans-serif;margin:40px} h1{color:#334} table{width:100%;border-collapse:collapse} td,th{border-bottom:1px solid #ddd;padding:8px}</style></head><body><h1>Invoice {{invoice_number}}</h1><p>Billed to: {{customer_name}}</p><table><tr><th>Item</th><th>Amount</th></tr>{{#each items}}<tr><td>{{description}}</td><td>{{amount}}</td></tr>{{/each}}</table><h2>Total: {{total}}</h2></body></html>",
"sample_data": {
"invoice_number": "INV-001",
"customer_name": "Acme Corp",
"items": [{ "description": "Widget", "amount": "$100.00" }],
"total": "$100.00"
}
}/api/templates/preview{
"engine": "html",
"html_template": "<html><body><h1>Hello {{name}}</h1></body></html>",
"sampleData": { "name": "World" }
}pdfme templates place fields at exact positions on the page. All units are millimeters.
{
"basePdf": { "width": 215.9, "height": 279.4, "padding": [0, 0, 0, 0] },
"schemas": [
[
{ "name": "title", "type": "text", "position": { "x": 20, "y": 20 }, "width": 170, "height": 12, "fontSize": 24, "alignment": "center" },
{ "name": "body", "type": "text", "position": { "x": 20, "y": 40 }, "width": 170, "height": 60, "fontSize": 11 }
]
]
}basePdf — page dimensions in mm. A4 = 210×297, Letter = 215.9×279.4, Legal = 215.9×355.6. Omit to default to A4.schemas — array of pages; each page is an array of fields with unique name, type, position, width, height.text, image, svg, line, rectangle, ellipse, table.text — fontSize (pt), alignment, fontColor (hex).image — value is a data:image/... URI or http(s) URL (fetched server-side).table — value is an array of row arrays; set head and headWidthPercentages on the field./api/templates{
"name": "Certificate",
"engine": "pdfme",
"pdfme_schema": {
"basePdf": { "width": 297, "height": 210, "padding": [0, 0, 0, 0] },
"schemas": [[
{ "name": "recipient", "type": "text", "position": { "x": 48.5, "y": 80 }, "width": 200, "height": 15, "fontSize": 28, "alignment": "center" },
{ "name": "date", "type": "text", "position": { "x": 48.5, "y": 150 }, "width": 200, "height": 10, "fontSize": 12, "alignment": "center" }
]]
},
"sample_data": { "recipient": "Jane Doe", "date": "June 10, 2026" }
}schemas[0][2] ("logo") has unsupported type "qrcode"Only the listed field types are enabled.
schemas[0][1] requires position {x: number, y: number} in mmEvery pdfme field needs numeric position and size.
html_template failed to compile: ...Malformed Handlebars syntax (e.g. unclosed {{#each}}).
HTTP 401 / 404Missing or revoked API key; or template not found / not visible to your key.