# PDF4.dev: Complete API Documentation > PDF generation API: Create HTML templates with Handlebars variables, preview them live, and render PDFs via REST API from any language. ## IMPORTANT: Base URL and HTTP methods - **Base URL: `https://pdf4.dev`**. There is NO `api.pdf4.dev` subdomain. It does not exist. Always use `https://pdf4.dev/api/v1/...`. - **Supported HTTP methods: GET, POST, PUT, DELETE only.** PATCH is NOT supported on any endpoint. - **Do NOT invent endpoints.** There is no `/update`, `/edit`, or similar path. To update a template, use `PUT /api/v1/templates/{id}`. - **Template body field is `html`**, not `content`, `body`, or `template`. ## Overview PDF4.dev lets you: 1. Create HTML templates in a visual dashboard with Handlebars `{{variables}}` 2. Generate PDFs via REST API by passing template ID + data 3. Use 24 free browser-based PDF tools (compress, merge, split, etc.) Base URL: `https://pdf4.dev` (NOT `api.pdf4.dev`) OpenAPI Spec: `https://pdf4.dev/api/v1/openapi.json` --- ## Authentication All API requests require a Bearer token. Create an API key in the dashboard Settings page. ``` Authorization: Bearer p4_live_xxx ``` API keys have two permission scopes: - `full_access`: all endpoints (render, templates CRUD, logs, stats) - `render_only`: only `POST /api/v1/render` Keys are hashed with SHA-256 server-side. The full token is shown only once at creation. --- ## Endpoints ### POST /api/v1/render Generate a PDF from a saved template or raw HTML. **Request:** ```bash curl -X POST https://pdf4.dev/api/v1/render \ -H "Authorization: Bearer p4_live_xxx" \ -H "Content-Type: application/json" \ -d '{ "template_id": "invoice", "data": { "company_name": "Acme Corp", "invoice_number": "INV-2025-001", "total": "$4,500.00" } }' \ --output invoice.pdf ``` **Parameters:** | Field | Type | Required | Description | |-------|------|----------|-------------| | template_id | string | One of template_id or html | Template ID (tmpl_xxx) or slug | | html | string | One of template_id or html | Raw HTML with {{handlebars}} variables | | data | object | No | Data to replace {{variables}}. Supports nested objects and arrays for `{{#each}}` blocks | | format | PdfFormat | No | Page format override (see below) | **Response:** `application/pdf` binary (Content-Type: application/pdf) **Example with raw HTML:** ```bash curl -X POST https://pdf4.dev/api/v1/render \ -H "Authorization: Bearer p4_live_xxx" \ -H "Content-Type: application/json" \ -d '{ "html": "
Your order #{{order_id}} is confirmed.
", "data": { "name": "John", "order_id": "12345" } }' \ --output document.pdf ``` **Example with custom format:** ```json { "html": "Amount: {{total}}
", "sample_data": { "invoice_number": "INV-001", "total": "$1,000.00" }, "pdf_format": { "preset": "a4", "margins": { "top": "20mm", "bottom": "20mm", "left": "15mm", "right": "15mm" } } }' ``` **Parameters:** | Field | Type | Required | Description | |-------|------|----------|-------------| | name | string | Yes | Template display name | | html | string | No | HTML content with {{variables}} | | sample_data | object | No | Default values for preview | | pdf_format | PdfFormat | No | Page format configuration | | header_component_id | string | No | Header component ID (comp_xxx) | | footer_component_id | string | No | Footer component ID (comp_xxx) | **Response:** 201: Template object. --- ### GET /api/v1/templates/{id} Get a single template by ID (tmpl_xxx) or slug. Requires `full_access` scope. ```bash curl https://pdf4.dev/api/v1/templates/invoice \ -H "Authorization: Bearer p4_live_xxx" ``` --- ### PUT /api/v1/templates/{id} Update a template. Only provided fields are updated. Requires `full_access` scope. ```bash curl -X PUT https://pdf4.dev/api/v1/templates/tmpl_abc123 \ -H "Authorization: Bearer p4_live_xxx" \ -H "Content-Type: application/json" \ -d '{ "html": "