Quickstart
This guide takes you from a published template to a rendered PDF using nothing
but curl.
1. Publish a template and issue an API key
Section titled “1. Publish a template and issue an API key”- Design a document in the studio and publish it — publishing freezes the current draft as an immutable version. The API always renders the published version, never your work-in-progress draft.
- Issue an API key under Settings → API keys. Keys can be scoped to a single workspace and revoked independently, so issue one key per integration.
Store the key server-side. It is a bearer credential — anyone holding it can render and download documents in its scope.
2. Find your canvas
Section titled “2. Find your canvas”curl https://composepdf.com/v1/canvases \ -H "x-api-key: $COMPOSEPDF_API_KEY"The response lists the published canvases your key can reach, with their ids.
To see what data a template expects, fetch its data contract:
curl https://composepdf.com/v1/canvases/{canvasId}/schema \ -H "x-api-key: $COMPOSEPDF_API_KEY"3. Render a PDF
Section titled “3. Render a PDF”curl -X POST https://composepdf.com/v1/canvases/{canvasId}/pdf \ -H "x-api-key: $COMPOSEPDF_API_KEY" \ -H "content-type: application/json" \ -d '{ "data": { "customer": { "name": "Acme Inc." }, "items": [ { "name": "Design work", "price": 1200 }, { "name": "Hosting", "price": 90 } ] } }' \ --output invoice.pdfThe response body is the PDF. If the payload does not match the template’s
declared variables, you get a 400 listing the violating paths instead of a
silently wrong document.
Where to go next
Section titled “Where to go next”- TypeScript instead of curl —
pnpm add composepdf, and generate the payload types from your own templates. See TypeScript. - Many records, one file — pass
dataList(an array of payloads) to collate one document per record into a single PDF. See Render API. - Long-running renders — add
Prefer: respond-asyncto get a202and a job id instead of holding the connection. See Render API. - Live preview in your product — embed the template as an iframe and stream your form state to it. See Embedded live preview.