PDF Generation
Generate PDF documents from HTML content, a live URL, or a saved template.
The default render timeout is 30 seconds. For complex pages with many external resources, you can increase this up to 60 seconds using the timeout option. See the options table below.
Endpoint
POST https://pixdoc.dev/api/v1/pdf
Request Body
Provide exactly one content source (html, url, or template_id) along with an optional options object.
Input Modes
| Field | Type | Description |
|---|---|---|
html | string | Raw HTML to render as a PDF |
url | string | URL of a page to render |
template_id | string (UUID) | ID of a saved template |
template_version | integer | Pin a specific template version. If omitted, the latest version is used. Versions auto-increment when template HTML is updated. |
variables | object | Key-value pairs to inject into the template (used with template_id) |
options | object | Rendering options (see below) |
metadata | object | Arbitrary JSON metadata (max 1KB) attached to the render. Returned in the polling endpoint and webhook payloads. Useful for reconciling renders with your own system (e.g., order IDs, customer references). |
You must provide exactly one of html, url, or template_id. Sending more than one or none returns a 400 error.
Options Reference
| Option | Type | Default | Description |
|---|---|---|---|
format | "A4" | "Letter" | "Legal" | {width, height} | "A4" | Page size. Use a preset or custom dimensions like {"width": "210mm", "height": "297mm"} |
landscape | boolean | false | Render in landscape orientation |
margin | object | {top: "20mm", right: "20mm", bottom: "20mm", left: "20mm"} | Page margins. Each side accepts CSS units (mm, cm, in, px) |
printBackground | boolean | true | Include background colors and images |
displayHeaderFooter | boolean | false | Show header and footer on each page |
headerTemplate | string | — | HTML template for the page header. Supports classes: date, title, url, pageNumber, totalPages |
footerTemplate | string | — | HTML template for the page footer. Same classes as header |
scale | number | 1 | Scale of the content, between 0.1 and 2.0 |
enableJavaScript | boolean | false | Execute JavaScript before rendering (useful for charts and dynamic content) |
waitForSelector | string | null | null | CSS selector to wait for before rendering |
waitForTimeout | number | null | null | Milliseconds to wait before rendering |
timeout | number | 30000 | Maximum render time in milliseconds (1000–60000) |
Code Examples
Basic HTML to PDF
curl -X POST https://pixdoc.dev/api/v1/pdf \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"html": "<h1>Invoice #1042</h1><p>Amount: $250.00</p>",
"metadata": {"order_id": "ORD-1042", "customer": "acme"},
"options": {
"format": "Letter",
"margin": {"top": "25mm", "bottom": "25mm", "left": "20mm", "right": "20mm"}
}
}' \
-o invoice.pdfRender a URL
curl -X POST https://pixdoc.dev/api/v1/pdf \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"url": "https://example.com/reports/q4-2025",
"options": {
"format": "A4",
"landscape": true,
"printBackground": true,
"enableJavaScript": true,
"waitForSelector": "#chart-loaded"
}
}' \
-o report.pdfTemplate with Variables
curl -X POST https://pixdoc.dev/api/v1/pdf \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"template_id": "d4e5f6a7-b8c9-0123-4567-89abcdef0123",
"template_version": 3,
"variables": {
"customer_name": "Acme Corp",
"invoice_number": "INV-2025-042",
"total": "$1,250.00"
}
}' \
-o invoice.pdfCommon Patterns
Headers and Footers
Enable displayHeaderFooter and provide HTML templates. Use special CSS classes to insert dynamic values:
{
"html": "<h1>Contract</h1><p>Terms and conditions...</p>",
"options": {
"displayHeaderFooter": true,
"headerTemplate": "<div style='font-size:10px; text-align:center; width:100%;'>CONFIDENTIAL</div>",
"footerTemplate": "<div style='font-size:10px; text-align:center; width:100%;'>Page <span class='pageNumber'></span> of <span class='totalPages'></span></div>",
"margin": { "top": "30mm", "bottom": "30mm" }
}
}
When using headers and footers, increase the top and bottom margins to prevent content from overlapping with the header/footer area.
Multi-Page Reports
Generate paginated, multi-page reports with running headers and footers. The multi-page-report seed template is a great starting point — it includes a cover page, executive summary, data tables, and multiple sections that flow naturally across 3+ pages.
curl -X POST https://pixdoc.dev/api/v1/pdf \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"template_id": "multi-page-report",
"variables": {
"company_name": "Acme Corp",
"report_title": "Q1 Performance Report",
"author": "Jane Smith",
"date": "March 2026",
"quarter": "Q1 2026"
},
"options": {
"format": "A4",
"displayHeaderFooter": true,
"headerTemplate": "<div style=\"font-size:9px;width:100%;padding:0 20mm;display:flex;justify-content:space-between\"><span>Acme Corp</span><span>Q1 Performance Report</span></div>",
"footerTemplate": "<div style=\"font-size:9px;width:100%;text-align:center\">Page <span class=\"pageNumber\"></span> of <span class=\"totalPages\"></span></div>",
"margin": {"top": "25mm", "bottom": "20mm", "left": "20mm", "right": "20mm"}
}
}' \
-o report.pdfAvailable CSS classes for header/footer templates:
pageNumber— current page numbertotalPages— total page countdate— formatted print datetitle— document titleurl— document URL
Header and footer templates render inside the page margins. Set margin.top to at least 20mm to make room for headers, and margin.bottom to at least 15mm for footers. If text is clipped, increase the corresponding margin.
Custom Page Size
Pass a {width, height} object instead of a preset name:
{
"html": "<div>Custom sized document</div>",
"options": {
"format": { "width": "100mm", "height": "150mm" }
}
}
Waiting for Dynamic Content
If your page loads data asynchronously, use enableJavaScript with waitForSelector or waitForTimeout:
{
"url": "https://app.example.com/dashboard",
"options": {
"enableJavaScript": true,
"waitForSelector": ".charts-loaded",
"timeout": 45000
}
}
Response
A successful request returns the PDF as a binary stream.
Response Headers
| Header | Description |
|---|---|
Content-Type | application/pdf |
X-Render-Duration-Ms | Time taken to render, in milliseconds |
X-Renders-Remaining | Number of renders left in your monthly quota |
Error Responses
Errors return JSON with a status code and error details:
{
"error": "INVALID_INPUT",
"message": "Exactly one of 'html', 'url', or 'template_id' must be provided"
}
| Status | Error Code | Meaning |
|---|---|---|
| 400 | INVALID_INPUT | Missing or invalid fields in the request body |
| 401 | UNAUTHORIZED | Invalid or missing API key |
| 429 | RATE_LIMITED | Monthly render limit exceeded |
| 500 | RENDER_FAILED | The renderer encountered an error (e.g., page timeout, invalid HTML) |
Async Rendering
For long-running or high-volume PDF generation, use async mode by setting "async": true. The API returns immediately with a 202 Accepted response and a request_id. Optionally add a webhook_url to have the result delivered to your endpoint, or poll for it using the poll_url.
curl -X POST https://pixdoc.dev/api/v1/pdf \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"html": "<h1>Invoice #1234</h1>",
"async": true,
"webhook_url": "https://example.com/hooks/render",
"webhook_secret": "whsec_your_secret"
}'This returns a 202 Accepted response with a request_id you can use to poll for status. See the Webhooks documentation for the full setup guide, payload format, and signature verification.
Poll-Only (No Webhook)
Set "async": true without a webhook_url to poll for the result. The response is the same 202 with a request_id — poll GET /api/v1/renders/{request_id} for the result.
curl -X POST https://pixdoc.dev/api/v1/pdf \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"html": "<h1>Invoice #1234</h1>",
"async": true
}'Async rendering requires a paid plan (Starter or above).