API Documentation

Integrate PDFEx into your application — or let an AI agent design templates and generate PDFs programmatically.

Authentication

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>
1

Generate Token

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

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 YOUR_KEY" \
  -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.

Agent Template Guide

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.

Endpoints

GET/api/templates
POST/api/templates
GET/api/templates/:id
PUT/api/templates/:id
DELETE/api/templates/:id
POST/api/templates/preview
POST/api/pdf/token
GET/api/pdf/:token

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

Preview example

/api/templates/preview
{
  "engine": "html",
  "html_template": "<html><body><h1>Hello {{name}}</h1></body></html>",
  "sampleData": { "name": "World" }
}

Engine: pdfme (coordinate-based)

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

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.
  • textfontSize (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.

Create example

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

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.