REST API reference

Create and manage PDF templates programmatically — ideal for automation and AI agents: draft a template, preview it, fix validation errors, save it, then generate PDFs on demand.

Authentication

All API requests require an API key. Create and manage keys in the dashboard at 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_...
1

Generate Token

Send your data and template ID to generate a single-use token. This operation is non-blocking and instantaneous.

Endpoint

POST/api/pdf/token

Request Body

  • template_id (string) Required
  • data (object) Required JSON data
curl -X POST https://pdfex.io/api/pdf/token \
 -H "Authorization: Bearer pdfex_..." \
 -H "Content-Type: application/json" \
  -d '{
    "template_id": "651...",
    "data": { "name": "Alice" }
  }'

Success Response (200 OK)

{
  "success": true,
  "token": "65eb...",
  "url": "/api/pdf/65eb..."
}
2

Retrieve PDF

Use the returned URL or Token to fetch the generated PDF file.

Endpoint

GET/api/pdf/:token
curl -O https://pdfex.io/api/pdf/65eb...

PDF links expire 15 minutes after the token is issued.

Endpoints

GET/api/capabilities
GET/api/templates
POST/api/templates
GET/api/templates/:id
PUT/api/templates/:id
DELETE/api/templates/:id
GET/api/templates/:id/export
POST/api/templates/import
GET/api/templates/samples
POST/api/templates/validate
POST/api/templates/preview
POST/api/pdf/token
GET/api/pdf/:token
GET /api/schema returns the same contract as /api/capabilities but is public — no API key. Useful for discovery before you have a key.

The design loop

  1. Draft a template (pdfme JSON or html — see engines below).
  2. POST /api/templates/preview with sample data → returns pdf_base64.
  3. Inspect the result; fix validation errors in details.
  4. POST /api/templates to save → returns template id.
  5. POST /api/pdf/token with template_id + data, then GET the returned url.

Engine: html (recommended for agents)

HTML templates use Handlebars placeholders, rendered by headless Chromium. Write ordinary HTML + CSS; use {{variable}} for data and {{#each items}}...{{/each}} for repeating rows.

  • JavaScript is disabled; external network requests are blocked.
  • Images must be inline data: URIs.
  • Default page size is US Letter; use CSS @page and page-break-* for pagination.
  • Variables are auto-extracted from placeholders — no need to list them.

Create example

/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"
  }
}

Engine: pdfme (coordinate-based)

pdfme templates place fields at exact positions on the page. All units are millimetres.

Template structure

{
  "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.
  • Supported types: 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.

For export/import via the dashboard, see Export & import templates. The API uses the same bundle format with GET /api/templates/:id/export and POST /api/templates/import.

Common validation errors

  • 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 mm

    Every pdfme field needs numeric position and size.

  • html_template failed to compile: ...

    Malformed Handlebars syntax (e.g. unclosed {{#each}}).

  • HTTP 401 / 404

    Missing or revoked API key; or template not found / not visible to your key.