Skip to content

Quickstart

PageKiln is in private beta. Join the waitlist to get an API key — until then you can read along; every example below runs unchanged once you have a key.

All requests authenticate with a bearer token:

Terminal window
export PAGEKILN_API_KEY="pk_live_..."

Templates are Typst documents. Each top-level key of the request’s data is available in sys.inputs as a typed value. Save this as invoice.typ:

#import sys: inputs
= Invoice #inputs.invoice_no
Amount due: #inputs.amount EUR

POST /v1/templates validates the template by rendering it once, so pass validation_data with sample inputs — without it, a template that references sys.inputs is rejected with a 422.

Terminal window
curl -X POST https://api.pagekiln.dev/v1/templates \
-H "authorization: Bearer $PAGEKILN_API_KEY" \
-H "content-type: application/json" \
-d "{\"name\": \"invoice\", \"source\": $(jq -Rs . < invoice.typ), \"validation_data\": {\"invoice_no\": \"INV-000\", \"amount\": 0}}"

The jq call JSON-encodes invoice.typ into the request body.

Terminal window
curl -X POST https://api.pagekiln.dev/v1/render \
-H "authorization: Bearer $PAGEKILN_API_KEY" \
-H "content-type: application/json" \
-d '{"template_id": "tpl_...", "data": {"invoice_no": "INV-001", "amount": 120}, "output": "url"}'
# → {"url": "https://...", "pages": 1, ...}

One request, many documents — with status tracking, partial-failure handling and signed URLs per item:

Terminal window
curl -X POST https://api.pagekiln.dev/v1/batches \
-H "authorization: Bearer $PAGEKILN_API_KEY" \
-H "content-type: application/json" \
-d '{"template_id": "tpl_...", "items": [{"data": {"invoice_no": "INV-001", "amount": 120}}, {"data": {"invoice_no": "INV-002", "amount": 80}}]}'
# → {"batch_id": "job_...", "total": 2, "status": "queued"}
curl https://api.pagekiln.dev/v1/batches/job_... \
-H "authorization: Bearer $PAGEKILN_API_KEY"
# → {"status": "completed", "counts": {"total": 2, "done": 2, "failed": 0}, ...}

To get notified instead of polling, register a webhook for batch.completed — see the API Reference.