API
API Reference
Every endpoint of the public API: sync and async renders, jobs, document links, templates, datasets and error codes.
Every endpoint of the public Prynt API, authenticated with a workspace API key. To build a request for one of your templates with real parameter names, open Developers → API explorer in the web app: it writes the cURL, C#, JavaScript and Python code for you.
Base URL and conventions
- Base URL:
https://api.prynt.it/api/v1. The paths below omit the/apiprefix of the API host:/v1/rendermeanshttps://api.prynt.it/api/v1/render. - Headers:
Authorization: Bearer prynt_live_…on every call except document links,Content-Type: application/jsonfor bodies, optionallyPrynt-Workspace: <workspaceId>and your ownX-Correlation-ID. - JSON members are camelCase, dates ISO 8601 in UTC, and errors are problem details (see Errors).
- Every response carries
X-Correlation-ID: the same id appears in the Logs page of the workspace and in the error body.
POST /v1/render
Renders the published version of a template with your parameters. Scope render.
| Field | Type | Description |
|---|---|---|
templaterequired | string | The template code (for example INVOICE). |
version | integer | A published version; omitted = the current one. |
environment | string | Environment key (development, staging, production…); omitted = the key's default environment. |
parameters | object | Parameter values by name, typed as declared by the template (GET /v1/templates/{code}). |
format | "pdf" | "zpl" | Expected output; must match the template (documents render PDF, labels ZPL). Omitted = the template's. |
async | boolean | true: answer 202 with a render job instead of waiting for the document. |
fileName | string | File name of the document (Content-Disposition, stored document). |
context | object | Optional caller context: company, user, language (system values of the template). |
Synchronous render
The default. The answer is 200 OK with the document as body (application/pdf, or application/zpl for labels) and these headers:
HTTP/1.1 200 OKContent-Type: application/pdfContent-Disposition: attachment; filename="INVOICE_18425.pdf"X-Correlation-ID: 4bf92f3577b34da6a3ce929d0e0e4736X-Template-Version: 7X-Page-Count: 2X-Document-Format: pdfX-Environment: productionX-Run-ID: 0199c2f1-5a7e-7b31-9c4d-2f0a8e6b1d23X-Template-Version: the version rendered;X-Page-Count(PDF) orX-Label-Count(ZPL).X-Document-Format,X-EnvironmentandX-Run-ID: the run recorded in the Logs page.
Asynchronous render
With "async": true the API answers at once 202 Accepted with a render job, and its statusUrl in the Location header. Poll the job (or listen to the document.generated webhook) until its status is succeeded or failed.
curl -X POST https://api.prynt.it/api/v1/render \ -H "Authorization: Bearer prynt_live_..." \ -H "Content-Type: application/json" \ -d '{ "template": "INVOICE", "parameters": { "DOCUMENT_ID": 18425 }, "async": true }'GET /v1/jobs/{jobId}
The state of a render job: queued, running, succeeded or failed. Scope render. A succeeded job has a documentUrl to download the document; a failed one an error with code and message (codes of the render, plus RENDER_TIMEOUT and JOB_ABANDONED).
{ "jobId": "0199c2f1-7c10-7d2e-8f61-1b9a4c3e5d77", "status": "succeeded", "statusUrl": "https://api.prynt.it/api/v1/jobs/0199c2f1-7c10-7d2e-8f61-1b9a4c3e5d77", "template": "INVOICE", "version": 7, "environment": "production", "format": "pdf", "attempts": 1, "createdAt": "2026-10-08T09:12:03.120Z", "startedAt": "2026-10-08T09:12:03.410Z", "completedAt": "2026-10-08T09:12:04.020Z", "pageCount": 2, "outputBytes": 48213, "documentUrl": "https://api.prynt.it/api/v1/documents/eyJhbGciOi…", "documentUrlExpiresAt": "2026-10-08T09:27:04.020Z", "documentExpiresAt": "2026-10-09T09:12:04.020Z", "error": null, "correlationId": "4bf92f3577b34da6a3ce929d0e0e4736"}Poll every one or two seconds at first, then less often; the job keeps its result after completion.
GET /v1/documents/{token}
Downloads a stored document. The documentUrl of a job is a signed, short-lived link (documentUrlExpiresAt): it needs no API key, so it can be handed to a browser or a printer service, but it expires quickly. The document itself is kept until documentExpiresAt; read the job again for a fresh link. An expired or invalid link answers 404 DOCUMENT_NOT_FOUND.
GET /v1/templates
Lists the published, active templates of the workspace; GET /v1/templates/{code} returns one. Scope templates.read. Each template has its parameters, a JSON Schema (2020-12) of the parameters object you can validate against, and its datasets with their fields.
{ "code": "INVOICE", "description": "Sales invoice", "documentType": "FATTURA", "format": "document", "version": 7, "updatedAt": "2026-10-01T15:40:00Z", "parameters": [ { "name": "DOCUMENT_ID", "type": "integer", "required": true, "defaultValue": null, "description": "Invoice id" }, { "name": "LANGUAGE", "type": "string", "required": false, "defaultValue": "it", "description": "" } ], "parameterSchema": { "$schema": "https://json-schema.org/draft/2020-12/schema", "type": "object", "…": "…" }, "datasets": [ { "code": "HEADER", "description": "Invoice header", "cardinality": "single", "fields": [{ "name": "NUMBER", "type": "string" }] } ]}POST /v1/datasets/{template}/{dataset}/execute
Runs one dataset of a template's published version with your parameters and returns its rows as JSON: useful to show the data of a document in your application before printing. Scope datasets.execute. The query itself is never exposed, and you cannot send SQL. maxRows defaults to 1,000 and may go up to 10,000; truncated tells whether rows were left out.
{ "parameters": { "DOCUMENT_ID": 18425 }, "environment": "production", "maxRows": 500}{ "template": "INVOICE", "version": 7, "dataset": "LINES", "environment": "production", "columns": [{ "name": "ITEM", "type": "string" }, { "name": "QTY", "type": "decimal" }], "rows": [{ "ITEM": "A-100", "QTY": 2 }], "rowCount": 1, "truncated": false, "elapsedMs": 38}Errors
Errors follow RFC 9457 (application/problem+json). Besides the standard members, every problem carries a stable errorCode to branch on and the correlationId of the request; validation errors add errors (member → messages). Do not parse title or detail: they are for people.
{ "type": "about:blank", "title": "Invalid parameter", "status": 400, "detail": "Parameter DOCUMENT_ID must be an integer.", "errorCode": "PARAMETER_INVALID", "correlationId": "4bf92f3577b34da6a3ce929d0e0e4736"}| Status | errorCode | Meaning |
|---|---|---|
| 400 | VALIDATION_FAILED | The body is malformed or a member is invalid; errors lists the members. |
| 400 | PARAMETER_INVALID | A parameter is missing or does not match its declared type. |
| 401 | API_KEY_INVALID | No key, a malformed key or an unknown key. |
| 401 | API_KEY_REVOKED | The key was revoked. |
| 401 | API_KEY_EXPIRED | The key expired. |
| 403 | SCOPE_MISSING | The key lacks the endpoint's scope. |
| 403 | ENVIRONMENT_NOT_ALLOWED | A test key asked for a production environment. |
| 403 | WORKSPACE_MISMATCH | Prynt-Workspace names another workspace than the key's. |
| 404 | TEMPLATE_NOT_FOUND | No template with this code in the workspace. |
| 404 | TEMPLATE_NOT_PUBLISHED | The template has no published version. |
| 404 | VERSION_NOT_FOUND | The requested version does not exist. |
| 404 | ENVIRONMENT_NOT_FOUND | No environment with this key in the workspace. |
| 404 | JOB_NOT_FOUND | No render job with this id for the key's workspace. |
| 404 | DOCUMENT_NOT_FOUND | The document link is invalid, expired, or the document was deleted. |
| 404 | DATASET_NOT_FOUND | The template has no dataset with this code. |
| 409 | TEMPLATE_DISABLED | The template is disabled in the workspace. |
| 422 | FORMAT_MISMATCH | The requested format is not the template's (pdf for a ZPL label, or the reverse). |
| 422 | RENDER_FAILED | The data was read but the document could not be produced. |
| 422 | RENDER_LIMIT_EXCEEDED | The document exceeds a limit (pages, size or rows). |
| 422 | DATASET_FAILED | A dataset could not be read from the data source. |
| 429 | RATE_LIMITED | Too many requests: wait for Retry-After seconds. |
| 503 | DATA_SOURCE_UNAVAILABLE | The data source or its Gateway cannot be reached right now. |
| 503 | RENDER_BUSY | The render capacity is saturated. Retry with backoff, or render asynchronously. |
What to retry
429 (after Retry-After), 503 and network failures with exponential backoff. Other 4xx errors need a change in the request, the key or the template; 422 errors carry the reason in detail.