Skip to content
Documentation menu

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 /api prefix of the API host: /v1/render means https://api.prynt.it/api/v1/render.
  • Headers: Authorization: Bearer prynt_live_… on every call except document links, Content-Type: application/json for bodies, optionally Prynt-Workspace: <workspaceId> and your own X-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.

Members of the render request
FieldTypeDescription
templaterequiredstringThe template code (for example INVOICE).
versionintegerA published version; omitted = the current one.
environmentstringEnvironment key (development, staging, production…); omitted = the key's default environment.
parametersobjectParameter 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.
asyncbooleantrue: answer 202 with a render job instead of waiting for the document.
fileNamestringFile name of the document (Content-Disposition, stored document).
contextobjectOptional 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:

200 OK
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-2f0a8e6b1d23
  • X-Template-Version: the version rendered; X-Page-Count (PDF) or X-Label-Count (ZPL).
  • X-Document-Format, X-Environment and X-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).

RenderJobResponse
{  "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.

GET /v1/templates/INVOICE
{  "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.

Request
{  "parameters": { "DOCUMENT_ID": 18425 },  "environment": "production",  "maxRows": 500}
Response
{  "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.

400 Bad Request
{  "type": "about:blank",  "title": "Invalid parameter",  "status": 400,  "detail": "Parameter DOCUMENT_ID must be an integer.",  "errorCode": "PARAMETER_INVALID",  "correlationId": "4bf92f3577b34da6a3ce929d0e0e4736"}
Error codes of the public API
StatuserrorCodeMeaning
400VALIDATION_FAILEDThe body is malformed or a member is invalid; errors lists the members.
400PARAMETER_INVALIDA parameter is missing or does not match its declared type.
401API_KEY_INVALIDNo key, a malformed key or an unknown key.
401API_KEY_REVOKEDThe key was revoked.
401API_KEY_EXPIREDThe key expired.
403SCOPE_MISSINGThe key lacks the endpoint's scope.
403ENVIRONMENT_NOT_ALLOWEDA test key asked for a production environment.
403WORKSPACE_MISMATCHPrynt-Workspace names another workspace than the key's.
404TEMPLATE_NOT_FOUNDNo template with this code in the workspace.
404TEMPLATE_NOT_PUBLISHEDThe template has no published version.
404VERSION_NOT_FOUNDThe requested version does not exist.
404ENVIRONMENT_NOT_FOUNDNo environment with this key in the workspace.
404JOB_NOT_FOUNDNo render job with this id for the key's workspace.
404DOCUMENT_NOT_FOUNDThe document link is invalid, expired, or the document was deleted.
404DATASET_NOT_FOUNDThe template has no dataset with this code.
409TEMPLATE_DISABLEDThe template is disabled in the workspace.
422FORMAT_MISMATCHThe requested format is not the template's (pdf for a ZPL label, or the reverse).
422RENDER_FAILEDThe data was read but the document could not be produced.
422RENDER_LIMIT_EXCEEDEDThe document exceeds a limit (pages, size or rows).
422DATASET_FAILEDA dataset could not be read from the data source.
429RATE_LIMITEDToo many requests: wait for Retry-After seconds.
503DATA_SOURCE_UNAVAILABLEThe data source or its Gateway cannot be reached right now.
503RENDER_BUSYThe render capacity is saturated. Retry with backoff, or render asynchronously.

What to retry

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.