Airpdf docs

Airpdf — API Reference

API pubblica per la generazione di PDF a partire da template.

Machine-readable spec: openapi.yaml (OpenAPI 3.1) · Postman: postman.json (one-click import)

  • Base URL: https://{tenant}.airpdf.app.zoonect.com/api/v1
  • Auth: header Authorization: Bearer airpdf_live_xxxxxxxxxxxxx
  • Content-Type: application/json

Le API key sono emesse dal pannello tenant (sezione "API Keys"). Il prefisso airpdf_live_ indica chiavi produzione, airpdf_test_ chiavi sandbox (facoltativo).


POST /api/v1/render

Richiede la generazione di un PDF. Supporta due modalità:

  • sync: response body contiene direttamente il PDF (application/pdf). Consigliata per payload piccoli e tempi di rendering brevi.
  • async: restituisce un render_id; il PDF viene caricato su storage S3-compatibile e recuperato via GET /api/v1/render/:id.

Request body

{
  "template": "invoice-v2",
  "data": {
    "customer": { "name": "Acme Srl", "vat": "IT01234567890" },
    "items": [
      { "sku": "SKU-1", "qty": 2, "price": 19.90 }
    ]
  },
  "mode": "sync",
  "options": {
    "page_size": "A4",
    "orientation": "portrait"
  }
}
Campo Tipo Descrizione
template string Codice del template (snake/kebab). Richiesto.
data object Payload conforme al variables_schema del template. Richiesto.
engine string "react_pdf" (default) o "html". Override del template engine. HTML richiede plan.html_engine_enabled = true. Vedi sezione Render engines.
mode string "sync" (default) oppure "async".
options object Override runtime: page_size, orientation, margin, filename.

Render engines

Airpdf supporta due pipeline di rendering, selezionabili per template o overridable per request:

Engine Quando usarlo Latency tipica Quota cost (multiplier)
react_pdf (default) API ad alto volume, layout standard 100-500 ms
html Brand-perfect HTML+CSS, web fonts, CSS Grid/Flex 1-3 s plan.html_engine_render_multiplier (typical 25×)

Il template carica il default engine via template.engine. Aggiungendo "engine": "html" nella request override quello del template (utile per A/B test o migrazione). L'engine HTML richiede:

  • plan.html_engine_enabled = true (altrimenti 402 payment_required)
  • template.html_template non vuoto

Quota: 1 render react_pdf = 1 unità contro render_limit_monthly. 1 render html = plan.html_engine_render_multiplier unità (default 1, tipicamente 25 per piani enterprise).

Rate limit HTML è un bucket separato da rate_limit_per_minute: plan.html_rate_limit_per_minute (default 10/min). Esaurito → 429 html_rate_limit_exceeded.

Per dettagli su template HTML, Mustache placeholders, opzioni PDF (headers/footers, margin, page size), e modello di sicurezza, vedi HTML render engine.

Response — mode: sync

200 OK con body binario application/pdf e header:

X-Airpdf-Render-Id: 01JHZ...
X-Airpdf-Render-Ms: 820

Response — mode: async

202 Accepted:

{
  "render_id": "01JHZ34567890ABCDEFG",
  "status": "queued",
  "poll_url": "/api/v1/render/01JHZ34567890ABCDEFG"
}

Esempio curl — sync

curl -sS -X POST "https://acme.airpdf.app.zoonect.com/api/v1/render" \
  -H "Authorization: Bearer airpdf_live_xxx" \
  -H "Content-Type: application/json" \
  -d @payload.json \
  -o invoice.pdf

Esempio curl — async + polling

render=$(curl -sS -X POST "https://acme.airpdf.app.zoonect.com/api/v1/render" \
  -H "Authorization: Bearer airpdf_live_xxx" \
  -H "Content-Type: application/json" \
  -d '{"template":"invoice-v2","data":{...},"mode":"async"}' | jq -r .render_id)

curl -sS "https://acme.airpdf.app.zoonect.com/api/v1/render/$render" \
  -H "Authorization: Bearer airpdf_live_xxx"

GET /api/v1/render/:id

Status di un render asincrono. Finché status != "succeeded" non c'è pdf_url.

{
  "render_id": "01JHZ34567890ABCDEFG",
  "template": "invoice-v2",
  "status": "succeeded",
  "pdf_url": "https://s3.wasabisys.com/airpdf-tenant-acme/renders/...",
  "pdf_size_bytes": 183042,
  "created_at": "2026-04-24T09:12:33Z",
  "finished_at": "2026-04-24T09:12:34Z"
}

Stati possibili: queued, running, succeeded, failed.


GET /api/v1/templates

Elenca i template pubblicati dell'account chiamante.

{
  "templates": [
    {
      "code": "invoice-v2",
      "name": "Fattura v2",
      "version": 7,
      "variables_schema": { "type": "object", "properties": {...} }
    }
  ]
}

Supporta paginazione: ?page=1&per_page=50.


Error codes

Tutte le risposte di errore hanno schema:

{ "error": { "code": "TEMPLATE_NOT_FOUND", "message": "..." } }
HTTP Code Descrizione
400 INVALID_PAYLOAD JSON mal formato o body mancante.
401 UNAUTHORIZED API key assente/invalida.
402 PAYMENT_REQUIRED Subscription non attiva o quota esaurita.
404 TEMPLATE_NOT_FOUND Template non esiste per il tenant.
422 VALIDATION_FAILED data non conforme a variables_schema.
429 RATE_LIMITED Rate limit superato (vedi header Retry-After).
500 INTERNAL_ERROR Errore rendering non recuperabile.
503 RENDER_UNAVAILABLE Nodi render temporaneamente irraggiungibili.

Rate limits

Default per API key:

  • 60 richieste / minuto sync
  • 600 richieste / minuto async
  • 10 MB per payload JSON

Header di risposta:

X-RateLimit-Limit: 60
X-RateLimit-Remaining: 58
X-RateLimit-Reset: 1714050000

Limiti custom sono configurabili per tenant dal pannello super-admin.

Spotted a typo or stale claim? Open an issue or ping us in the workspace — docs are versioned with the product.