Quire PDFDocumentation

Render API reference

The API lives at https://api.quirepdf.dev. Every request and error body is JSON, except rendered files, which come back as raw PDF or PNG bytes.

Authentication

curl https://api.quirepdf.dev/v1/usage \
  -H "Authorization: Bearer $QUIRE_API_KEY"

Send your key as a Bearer token on render, validate, usage, keys and billing calls. Health, the template catalog and sign-in need no key. Keys start with qk_live_; get one with npx quirepdf-cli login [email protected] (see Accounts and billing).

A missing, revoked or mistyped key returns 401 unauthorized.

Endpoints

Method Path Key What it does
POST /v1/render yes Render data; the template is optional
POST /v1/render/{name} yes Render with a named template
POST /v1/validate yes Check data without rendering (free)
GET /v1/templates no List templates
GET /v1/templates/{name} no One template’s metadata, JSON Schema and sample data
GET /v1/health no Engine status
GET /v1/usage yes Plan and renders used this month
GET, POST /v1/keys yes List or create API keys
DELETE /v1/keys/{id} yes Revoke a key
POST /v1/login no Start a sign-in (email link + code)
POST /v1/billing/checkout yes Get a hosted checkout URL for a paid plan

Render

curl "https://api.quirepdf.dev/v1/render?template=invoice" \
  -H "Authorization: Bearer $QUIRE_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "number": "INV-2026-0142",
    "issued": "1 Oct 2026",
    "due": "15 Oct 2026",
    "seller": { "name": "Northwind Studio", "address": ["221 Market Street", "San Francisco, CA 94105"] },
    "customer": { "name": "Ravi Kumar", "address": ["14 Residency Road", "Bengaluru 560025"] },
    "items": [{ "description": "Pro plan", "qty": 1, "unit_price": 49 }]
  }' \
  -D - -o invoice.pdf
HTTP/1.1 200 OK
content-type: application/pdf
x-render-ms: 6.1
x-pages: 1
x-template: invoice
x-template-source: explicit
x-quota-limit: 100
x-quota-remaining: 99

The request body is the document data: one JSON object, at most 1 MB. POST /v1/render/invoice does the same as POST /v1/render?template=invoice.

Query parameters

Parameter Values Default Notes
template a template name, e.g. invoice none Omit it to auto-detect. Naming one validates strictly against its schema.
format pdf, png pdf png returns a single page
page 1, 2, … 1 PNG only. Sending page without format=png is a 400 bad_request.

How the template is chosen

  1. Explicit: you named a template. Your data must pass its schema, or you get 422 invalid_data with every problem listed.
  2. Detected: your data passes one or more gallery schemas. The template with the most required fields wins.
  3. Fallback: the generic document layout, which renders any JSON object.

When the result is a fallback but a template almost matched (two problems or fewer), x-template-hint names it and says what’s missing. Templates and layout explains detection and the generic layout in detail.

Response headers

Header Example Meaning
content-type application/pdf application/pdf or image/png
x-template invoice The template that rendered the document
x-template-source detected explicit, detected or fallback
x-template-hint invoice (seller is required) Only on fallback, when a template almost matched. Non-ASCII characters show as ?; /v1/validate returns the exact text.
x-pages 3 Page count of the whole document, also for PNG
x-render-ms 6.1 Time spent rendering on the server
x-quota-limit 2000 Your plan’s monthly render limit
x-quota-remaining 1873 Renders left this month, after this one

PDF or PNG

curl "https://api.quirepdf.dev/v1/render?format=png&page=2" \
  -H "Authorization: Bearer $QUIRE_API_KEY" \
  -H "Content-Type: application/json" \
  -d @report.json -o report-p2.png

Use PNG for previews, thumbnails and visual tests. Each call returns one page at 2× scale (an A4 page is 1190 × 1684 pixels). Read x-pages from the first response to know how many pages there are. Asking for a page that doesn’t exist returns 400 bad_request. A PNG render counts against your quota the same as a PDF.

Pages are A4. The certificate template is landscape A4 and always one page.

Validate (free)

curl "https://api.quirepdf.dev/v1/validate?template=invoice" \
  -H "Authorization: Bearer $QUIRE_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"number":"INV-1","issued":"1 Oct 2026","due":"15 Oct 2026","customer":{"name":"Ravi Kumar","address":[]},"items":[]}'
{
  "valid": false,
  "template": "invoice",
  "source": "explicit",
  "hint": null,
  "errors": [
    { "path": "seller", "message": "seller is required" },
    { "path": "items", "message": "items needs at least 1 item" }
  ]
}

/v1/validate resolves the template exactly as /v1/render would and checks the data against it, without rendering. It returns 200 whether or not the data is valid, so read valid. Without ?template=, it tells you which template auto-detection would pick, plus any near-miss hint.

Validation is free: it never counts against your quota. It still needs an API key.

Templates

curl https://api.quirepdf.dev/v1/templates/receipt
{
  "template": {
    "name": "receipt",
    "title": "Receipt",
    "category": "billing",
    "description": "Proof-of-payment receipt with an amount-paid panel and PAID badge, …",
    "tags": ["receipt", "payment", "billing", "saas", "ecommerce"],
    "version": "1.0.0"
  },
  "schema": {
    "$schema": "https://json-schema.org/draft/2020-12/schema",
    "type": "object",
    "required": ["number", "paid_on", "seller", "customer", "payment", "items"],
    "properties": {
      "number": { "type": "string", "minLength": 1, "description": "Receipt number, e.g. RCPT-2026-0388" }
    }
  },
  "sample": { "number": "RCPT-2026-0388", "paid_on": "3 Oct 2026" }
}

This response is trimmed: the real one lists every property in schema and a complete sample.

GET /v1/templates returns {"templates": [...]} with the metadata of all seven templates. GET /v1/templates/{name} adds the full JSON Schema (draft 2020-12) and a complete, valid sample you can render as is. An unknown name returns 404 unknown_template.

Health

curl https://api.quirepdf.dev/v1/health
{ "ok": true, "templates": 7, "accounts": true, "version": "0.1.0" }

Limits

Limit Value Error
Request body 1 MB 413 payload_too_large
Render time 5 seconds 504 timeout
Document length 200 pages 422 too_many_pages
Field errors per response 50 (the list is cut at 50)

For scale: a 14-page invoice with 300 line items renders in about 48 ms (measured on a laptop, October 2026), so the time limit only stops runaway documents.

Quotas and rate limits

Each plan has a monthly render quota, counted per account in calendar months (UTC):

Plan Renders per month
Free 20
Starter 2,000
Pro 10,000
Scale 50,000

Only successful renders count. A request that fails with any error, every /v1/validate call, and every test render is free. When the quota runs out, renders return 429 quota_exceeded until the next month or until you upgrade.

Test renders

Add test=true to /v1/render or /v1/render/{name} for a free test render: the same document with a “TEST RENDER · quirepdf.dev” watermark on every page. Test renders are unlimited on every plan, aren’t counted, and keep working after the quota runs out, so use them while you build. The response carries x-quire-test: true and no quota headers. Renders made with the playground’s demo key are always watermarked.

curl "https://api.quirepdf.dev/v1/render?test=true" \
  -H "Authorization: Bearer $QUIRE_API_KEY" \
  -H "Content-Type: application/json" \
  -d @order.json -o order-test.pdf

Each API key can make 10 render or validate calls a second, with bursts of up to 20. Past that you get 429 rate_limited with a Retry-After header in seconds. Rate-limited calls don’t count against your quota. The shared demo key that powers the website playground allows 20 renders an hour per visitor.

Account endpoints

Usage, keys, sign-in and checkout are covered in Accounts and billing. Every error type is listed in Errors.

View this page as Markdown