Skip to content

Render a document

Render one or more documents from one of your templates. You send the template’s id and a JSON data object; Pagr renders the latest published version and returns a JSON envelope describing the outcome — optionally with the PDF bytes inline.

This is the endpoint every official SDK wraps as its render call. The examples below use the SDKs; for the raw HTTP shape, see Request body and Response.

POST /v1/render/{templateId}
POST /v1/render/{templateId}/versions/{version}

The first form renders the latest published version; the second renders a specific version by number. Every request must carry a bearer API key — see Authentication.

Terminal window
curl -X POST "https://pagr-prd-api-public.azurewebsites.net/v1/render/8bec66ff-6f3d-4c1e-9a2b-1f0e5d7c4a90" \
-H "Authorization: Bearer pagr_prod_xxxxxxxx" \
-H "Content-Type: application/json" \
-d '{
"documents": [
{ "Title": "Acme Q3 Invoice", "Amount": 42 }
],
"includeDocument": true
}'
Parameter Type Required Description
templateId string (UUID) Yes The template to render.
version integer Only for the specific-version form The template version number to render. Omit the whole path segment to render the latest published version.
Parameter Type Default Description
persist boolean true Whether to store the rendered document. When true, the document’s id and viewUrl are populated and it appears in Renders; when false, both are null and the PDF is returned inline instead (see the note under Response).
language string Language variant to render, for multilingual templates. A value the template version doesn’t define is rejected with 400 ValidationError.

A JSON object with the documents to render. Even for a single document, documents is an array — the same endpoint renders a synchronous batch when you pass more than one.

Field Type Default Description
documents array of objects — (required) One object per document. Each object is your template’s data; each document is limited to 50 MB of JSON, nested at most 32 levels deep. A test key caps the array at 10 entries.
includeDocument boolean false When true, each rendered document carries its PDF inline as Base64 in documentBase64. The SDKs decode this for you.
{
"documents": [
{ "Title": "Acme Q3 Invoice", "Amount": 42 }
],
"includeDocument": true
}

Every render returns HTTP 200 with a JSON envelope — any outcome, any batch size. Inspect status and issues rather than relying on the status code: a document that fails validation, or a job stopped for credit, is a normal outcome reported here, not an HTTP error.

{
"status": "ok", // "ok" | "partial" | "failed" | "insufficient_credit"
"message": "1 document(s) rendered.",
"requestedCount": 1, // documents submitted
"renderedCount": 1, // documents actually rendered
"missingCount": 0, // requestedCount − renderedCount
"issues": [], // per-document validation & render issues
"documents": [
{
"id": "f61aeff4-2c9d-4b7a-8e10-3a5b9c2d1e00", // null when persist=false
"documentName": "Acme Q3 Invoice",
"templateId": "8bec66ff-6f3d-4c1e-9a2b-1f0e5d7c4a90",
"versionNumber": 3,
"environment": "production",
"fileSizeBytes": 24815,
"pageCount": 1,
"renderedAt": "2026-07-24T09:46:01Z",
"renderDuration": 412.7, // milliseconds
"viewUrl": "https://…", // null when persist=false
"documentType": "Template",
"language": null,
"documentBase64": null, // populated only when includeDocument=true (or persist=false)
"documentIndex": 0 // zero-based position in the documents array
}
]
}
Field Type Description
status string ok, partial, failed, or insufficient_credit.
message string Human-readable summary of the outcome.
requestedCount number Documents submitted.
renderedCount number Documents that actually rendered.
missingCount number requestedCount − renderedCount — everything not rendered, whatever the reason.
issues array RenderIssue objects explaining why a document is missing. Each carries documentIndex, type, severity, and description.
documents array The rendered documents (see below). Blocked documents leave gaps, so correlate by documentIndex, never by list position.
Field Type Description
id string (UUID) or null Stored document id. null when persist=false.
documentName string The document’s name (no extension; output is always PDF).
templateId string (UUID) The template it was rendered from.
versionNumber number The template version used.
environment string production or test, decided by the API key.
fileSizeBytes number Size of the rendered PDF.
pageCount number Number of pages.
renderedAt string (ISO 8601) When it rendered.
renderDuration number Render time in milliseconds.
viewUrl string or null Signed download URL. null when persist=false.
documentType string Template or Invoice.
language string or null The language variant rendered, or null.
documentBase64 string or null The PDF bytes, Base64-encoded. Populated only when includeDocument=true or persist=false.
documentIndex number Zero-based position in the request’s documents array.
SDK Method
Python await client.render(template_id, json_data, *, version=None, include_document=False, language=None, persist=True, timeout=None)
TypeScript await client.render(templateId, jsonData, options?)
Java client.render(templateId, data) / client.render(templateId, data, RenderOptions)
C# await client.RenderAsync(templateId, data, version, includeDocument, language, persist, timeout, cancellationToken)
Ruby client.render(template_id, json_data, version:, include_document:, language:, persist:, timeout:)
C++ client.render(template_id, json_data, RenderOptions) / client.render_async(…)

For more than one document, use the batch form of the same call — render_batch / renderBatch / RenderBatchAsync. See Render a batch.

Transport and protocol failures come back as HTTP error statuses with a { "error": { "code", "message" } } body — 400 (test-key batch over 10 documents, or an unknown language), 401 (bad key), 403 (not allowed), 404 (template or version not found), 413 (a document over 50 MB), 422 (couldn’t bind the body), 429 (rate limited). The SDKs map each to a typed exception. See Errors for the full table.