This guide walks you through generating a PDF document end-to-end.
Prerequisites
- A Platendoc account (sign up free)
- A published template with at least one version
- An API key with
generations:trigger and generations:read scopes
1. Get your template ID
In the portal, open your template and copy the ID from the URL or the template settings. It looks like tpl_01j8z....
2. Create a generation
curl -X POST https://api.platendoc.com/v1/generations \
-H "Authorization: Bearer pdc_live_YOUR_KEY" \
-H "Content-Type: application/json" \
-d '{
"templateId": "tpl_01j8z...",
"format": "pdf",
"variables": {
"customerName": "Acme Corp",
"invoiceNumber": "INV-0042",
"amount": "1,250.00"
}
}'
The API responds immediately with a PENDING generation:
{
"id": "gen_01j8z...",
"status": "PENDING",
"format": "PDF",
"outputUrl": null,
...
}
3. Poll for completion
Fetch the generation by ID until status is COMPLETED:
curl https://api.platendoc.com/v1/generations/gen_01j8z... \
-H "Authorization: Bearer pdc_live_YOUR_KEY"
{
"id": "gen_01j8z...",
"status": "COMPLETED",
"outputUrl": "https://...",
...
}
Most generations complete in 2–5 seconds. Poll with a 1-second interval and a 30-second timeout.
4. Download the document
The outputUrl is a pre-signed URL valid for 1 hour. Download it directly:
curl -L "https://..." -o invoice.pdf
Full example (Node.js)
import fetch from 'node-fetch'
const API_KEY = process.env.PLATENDOC_API_KEY
const BASE = 'https://api.platendoc.com/v1'
async function generateDocument(templateId: string, variables: Record<string, unknown>) {
// 1. Create generation
const createRes = await fetch(`${BASE}/generations`, {
method: 'POST',
headers: {
Authorization: `Bearer ${API_KEY}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({ templateId, format: 'pdf', variables }),
})
const { id } = await createRes.json()
// 2. Poll until complete
let generation
for (let i = 0; i < 30; i++) {
await new Promise((r) => setTimeout(r, 1000))
const res = await fetch(`${BASE}/generations/${id}`, {
headers: { Authorization: `Bearer ${API_KEY}` },
})
generation = await res.json()
if (generation.status === 'COMPLETED' || generation.status === 'FAILED') break
}
if (generation.status !== 'COMPLETED') {
throw new Error(`Generation failed: ${generation.error}`)
}
return generation.outputUrl
}
Error handling
If the generation fails, status will be FAILED and the error field describes what went wrong:
{
"status": "FAILED",
"error": "Template rendering failed: unknown variable 'customerNme'."
}
Common causes:
- Typo in a variable name
- Template has no published version
- Template was archived after the generation was created