API Reference
Render templates, manage assets, and integrate PDF generation into any stack.
api.pdfs.build Overview
The pdfs.build API lets you render templates to PDFs, manage your template library, and retrieve generation logs — all over HTTPS with JSON request bodies and standard HTTP status codes.
https://api.pdfs.build application/pdf Authentication
All API requests require a bearer token. Create and manage API keys from Settings → API Keys in your dashboard. Keys are shown once on creation — store them securely.
The public REST API is versioned under /v1/* and accepts API keys only. The web app uses separate internal /api/* routes backed by app sessions, so API keys authenticate the public REST surface only.
Key format
Keys are prefixed with prs_ and scoped to your organization.
curl https://api.pdfs.build/v1/templates \
-H "Authorization: Bearer prs_your_api_key" /v1/templates Create template
Creates a draft template owned by the user that minted the API key. Drafts are not visible to the render endpoint until they are published. The request body submits ready-to-render template code, schema, and example data — no lint or transformation is applied, so payloads should be valid template code with a top-level #let render(...) = { ... } function whose named parameters match the schema fields.
Request body
| Field | Type | Description |
|---|---|---|
| name | string | Display name. Required. |
| description | string | Optional one-line summary. |
| code | string | Template source. Should define #let render(...). Required (empty string allowed for blank drafts). |
| schema | object | JSON Schema describing the data payload accepted by /v1/render. |
| sampleData | object | Example data that satisfies the schema. |
| pageSettings | object | Page size, margins, and other layout settings. |
Returns 201 with the full template detail, including the generated id. Save that id; you will need it to publish and render the template.
/v1/templates/:id/publish Publish template
Promotes a draft template to published so it becomes visible to your organization and callable via the render endpoint. The caller must own the template or be an organization admin/owner. Enforces your plan's published-template limit.
Request body (optional)
| Field | Type | Description |
|---|---|---|
| name | string | Rename the template on publish. |
| description | string | Update the description on publish. |
Returns the updated template detail. Returns 402 template_limit_reached if the org's plan does not allow another published template.
/v1/templates/:id/unpublish Unpublish template
Moves a published template back to draft. Once unpublished, the template can no longer be rendered via /v1/render and is removed from organization template listings. Existing generation log entries are preserved.
Returns the updated template detail.
/v1/render Render PDF
Compiles the specified template with the provided data payload and returns a binary PDF. Data is validated against the template's schema before rendering.
Request body
| Field | Type | Description |
|---|---|---|
| templateId | string | Template ID to render. Required. |
| data | object | Key-value pairs matching the template's schema. |
Response
Returns Content-Type: application/pdf on success. On error, returns JSON with an error object.
const response = await fetch(
'https://api.pdfs.build/v1/render',
{
method: 'POST',
headers: {
'Authorization': `Bearer ${API_KEY}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
templateId: 'tmpl_abc123',
data: {
company: 'Acme Corp',
items: [
{ name: 'Consulting', qty: 3, price: 150 },
],
due_date: '2025-06-01',
}
}),
}
);
const pdf = await response.arrayBuffer(); /v1/templates List templates
Returns all templates visible to the authenticated user — their own drafts and their organization's published templates.
[
{
"id": "tmpl_abc123",
"name": "Invoice v3",
"description": "Standard invoice with line items",
"status": "published",
"createdAt": "2025-03-12T10:24:00Z",
"updatedAt": "2025-04-01T08:15:00Z"
}
] /v1/templates/:id Get template
Returns a single template's metadata, schema definition, and sample data. Use the schema field to know which keys your data payload must include when rendering.
{
"id": "tmpl_abc123",
"name": "Invoice v3",
"status": "published",
"schema": {
"type": "object",
"properties": {
"company": { "type": "string" },
"due_date": { "type": "string", "format": "date" },
"items": { "type": "array" }
}
},
"sampleData": { /* ... */ }
} /v1/logs Generation logs
Returns a paginated list of PDF generation events for your organization. Useful for auditing, debugging, and tracking usage.
Query parameters
| Parameter | Type | Description |
|---|---|---|
| limit | integer | Max results to return (default: 50) |
| offset | integer | Pagination offset |
| status | string | Filter by status: success or error |
| source | string | Filter by source: api, ui, or mcp |
| templateId | string | Filter by specific template |
| search | string | Full-text search on template name |
| from | string (ISO 8601) | Start of time range |
| to | string (ISO 8601) | End of time range |
MCP server (for AI agents)
The same authentication layer also serves a Model Context Protocol endpoint. Agents that connect to it can design, publish, and exercise the public render API end-to-end inside a single conversation — without the user touching the dashboard.
https://backend.pdfs.build/mcp Tool surface
The MCP server exposes the entire template lifecycle plus an API-key admin surface so an agent can self-serve a key, test the render API, and clean up afterwards.
| Tool | Purpose |
|---|---|
| list_templates / get_template / browse_templates | Discover templates and load their code, schema, and sample data. |
| create_template / duplicate_template | Start a fresh draft or clone an existing template. |
| write_document / edit_document / write_schema / write_sample_data | Author the template code, schema, and data. |
| compile_document | Compile the active template against default edge fixtures and optional custom fixtures, returning per-fixture diagnostics. |
| save_template | Persist the active session's changes after the compile gate passes; draft WIP saves can explicitly skip the gate. |
| publish_template / unpublish_template | Move templates between draft and published. Publishing requires the compile gate to pass. |
| create_api_key / list_api_keys / delete_api_key | Mint, audit, and revoke public REST API keys. |
| document_reference | Look up template code reference inline. |
| list_fonts / upload_font / confirm_font_upload | Browse org fonts and upload custom TTF/OTF files. |
| search_google_fonts / install_google_font | Browse Google Fonts and install a family into the org. |
Connect from Claude Desktop, Cursor, or any MCP-compatible client. See the MCP integration guide for an end-to-end example.
Errors
All errors return a JSON body with a top-level error object.
{
"error": {
"code": "schema_validation_failed",
"message": "Missing required field: company"
}
} | Status | Code | Description |
|---|---|---|
| 400 | invalid_request | Missing or malformed request parameters |
| 400 | already_published | Trying to publish a template that is already published |
| 400 | already_draft | Trying to unpublish a template that is already a draft |
| 401 | unauthorized | Missing or invalid API key |
| 403 | forbidden | Caller does not have permission to publish/unpublish this template |
| 404 | not_found | Template not found or not accessible |
| 402 | template_limit_reached | Org plan's published-template limit is reached. Unpublish a template or upgrade the plan. |
| 402 | api_renders_not_allowed_on_free | Render API is not available on the Free plan. Upgrade to Starter or higher. |
| 422 | schema_validation_failed | Data payload doesn't match the template schema |
| 429 | rate_limited | Request rate exceeded — see Rate Limits |
| 500 | render_failed | Internal rendering error |
Rate limits
Rate limits apply per API key, per minute. When a limit is exceeded, the API returns a 429 status. Check the response headers to determine when you can retry.
| Plan | Requests / min |
|---|---|
| Free | 10 |
| Pro | 300 |
| Enterprise | Custom |
Rate limit headers
| Header | Description |
|---|---|
| X-RateLimit-Limit | Maximum requests allowed per minute |
| X-RateLimit-Remaining | Requests remaining in the current window |
| X-RateLimit-Reset | Unix timestamp when the window resets |
API keys
API keys are scoped to your organization and grant access to all templates your organization can see. Keys are prefixed with prs_ and displayed only once on creation — copy them immediately and store them in a secret manager or environment variable.
Manage your API keys from Settings → API Keys in the dashboard. You can create multiple keys for different environments and revoke them individually.