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 viaGET /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 | 1× |
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(altrimenti402 payment_required) -
template.html_templatenon 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.