Render statelessly
Render a document from a template you pass in the request body, instead of one stored in your workspace. Nothing is persisted — no template, no document, no entry in Renders — and the response is the raw PDF binary rather than a JSON envelope.
Useful for one-off documents that don’t belong in your template catalogue, and for iterating on a template’s DSL before publishing it.
Endpoint
Section titled “Endpoint”POST /v1/renderNo template id in the path — the template travels in the body. Every request must carry a bearer API key; the key’s prefix still decides test vs. production behaviour (a test key watermarks the output).
Example
Section titled “Example”curl -X POST "https://pagr-prd-api-public.azurewebsites.net/v1/render" \ -H "Authorization: Bearer pagr_prod_xxxxxxxx" \ -H "Content-Type: application/json" \ -d '{ "template": { "…": "the template DSL" }, "data": { "Title": "Acme Q3 Invoice", "Amount": 42 } }' \ --output invoice.pdfimport asyncio, jsonfrom pagr import PagrApiClient
async def main(): with open("invoice-template.json") as f: template_dsl = json.load(f)
async with PagrApiClient("pagr_prod_xxxxxxxx") as client: pdf_bytes = await client.render_stateless( template=template_dsl, # dict or JSON string data={"Title": "Acme Q3 Invoice", "Amount": 42}, ) with open("out.pdf", "wb") as f: f.write(pdf_bytes)
asyncio.run(main())import { readFile, writeFile } from 'node:fs/promises';import { PagrApiClient } from 'pagr';
const client = new PagrApiClient('pagr_prod_xxxxxxxx');const templateDsl = JSON.parse(await readFile('invoice-template.json', 'utf8'));
const pdfBytes = await client.renderStateless( templateDsl, // object or JSON string { Title: 'Acme Q3 Invoice', Amount: 42 },);await writeFile('out.pdf', pdfBytes);import org.example.PagrApiClient;import java.nio.file.Files;import java.nio.file.Path;
try (PagrApiClient client = new PagrApiClient("pagr_prod_xxxxxxxx")) {
String templateDsl = Files.readString(Path.of("invoice-template.json"));
byte[] pdf = client.renderStateless( templateDsl, // JSON string, JsonObject or Map "{\"Title\": \"Acme Q3 Invoice\", \"Amount\": 42}");
Files.write(Path.of("out.pdf"), pdf);}using Pagr.Sdk;
using var client = new PagrApiClient("pagr_prod_xxxxxxxx");
var templateJson = await File.ReadAllTextAsync("invoice-template.json");
byte[] pdf = await client.RenderStatelessAsync( templateJson, // JSON string or JsonElement """{ "Title": "Acme Q3 Invoice", "Amount": 42 }""");
await File.WriteAllBytesAsync("out.pdf", pdf);require "json"require "pagr"
client = Pagr::Client.new("pagr_prod_xxxxxxxx")template_dsl = JSON.parse(File.read("invoice-template.json"))
pdf = client.render_stateless( template_dsl, # Hash or JSON String { "Title" => "Acme Q3 Invoice", "Amount" => 42 },)File.binwrite("out.pdf", pdf)#include <fstream>#include "pagr/PagrApiClient.hpp"
pagr::PagrApiClient client("pagr_prod_xxxxxxxx");
std::ifstream in("invoice-template.json");nlohmann::json template_dsl = nlohmann::json::parse(in);
auto pdf = client.render_stateless( template_dsl, // nlohmann::json or JSON string nlohmann::json{{"Title", "Acme Q3 Invoice"}, {"Amount", 42}});
std::ofstream out("out.pdf", std::ios::binary);out.write(reinterpret_cast<const char*>(pdf.data()), pdf.size());A render_stateless_async form returning std::future<std::vector<std::uint8_t>> is also available.
Path parameters
Section titled “Path parameters”None.
Query parameters
Section titled “Query parameters”| Parameter | Type | Default | Description |
|---|---|---|---|
language |
string | — | Language variant to render. Only meaningful together with translations in the body. |
There is no persist parameter — a stateless render never stores anything.
Request body
Section titled “Request body”| Field | Type | Required | Description |
|---|---|---|---|
template |
object | Yes | The template DSL itself. It doesn’t need to exist in Pagr. |
data |
object | Yes | The document data the template binds to. Same limits as a normal render: 50 MB of JSON, nested at most 32 levels deep. |
translations |
object | No | Translation strings, for rendering a language variant. |
{ "template": { "…": "the template DSL" }, "data": { "Title": "Acme Q3 Invoice", "Amount": 42 }, "translations": null}Response
Section titled “Response”200 OK with Content-Type: application/pdf — the response body is the PDF
itself. No headers carry metadata (unlike
Render a raw PDF), because there is no
stored document to describe.
Every SDK returns the bytes directly:
| SDK | Return type |
|---|---|
| Python | bytes |
| TypeScript | Uint8Array |
| Java | byte[] |
| C# | byte[] |
| Ruby | String (binary) |
| C++ | std::vector<std::uint8_t> |
SDK reference
Section titled “SDK reference”| SDK | Method |
|---|---|
| Python | await client.render_stateless(template, data, translations=None, *, language=None, timeout=None) |
| TypeScript | await client.renderStateless(template, data, { translations, language, timeoutMs }) |
| Java | client.renderStateless(template, data) / client.renderStateless(template, data, translations, language) |
| C# | await client.RenderStatelessAsync(templateJson, jsonData, translationsJson, language, timeout, cancellationToken) |
| Ruby | client.render_stateless(template, data, translations = nil, language:, timeout:) |
| C++ | client.render_stateless(template, data, translations, language, timeout) / render_stateless_async(…) |
Errors
Section titled “Errors”| Status | code |
When |
|---|---|---|
413 |
PayloadTooLarge |
The payload exceeds 50 MB. |
422 |
BindingError |
template or data couldn’t be parsed or bound — malformed JSON, wrong types, an invalid DSL. |
500 |
RenderTimeout |
The render exceeded its 60-second budget. |
See Errors for the full table.
Related articles
Section titled “Related articles”- Choose a rendering shape — how stateless compares to the other three.
- Render a document — render a stored template instead.
- Template structure — the DSL you pass in
template. - Templates & versions — fetch an existing version’s
templateJsonas a starting point.
