Templates
Templates are reusable documents you build once in the visual editor and fire off as many times as you want through the API, sending only the data. It is the recommended path for any recurring document: invoices, contracts, receipts, certificates, posts.
The lifecycle of a template
1. Create
Build the layout in the visual editor and add {{...}} variables where the data goes.
2. Save
Saving in the editor immediately gives the template a stable slug — the identifier the API uses.
3. Use
Call /v1/render with the slug in template and your data in data.
1. Create in the editor
In the Renderly visual editor you design the document like in a design app: text blocks, images, tables, QR codes and charts. Where the content should change with each issuance, you place a variable in the format {{caminho.do.valor}}. This model is saved as a DocumentModel — a structured representation of the document, not just HTML.
2. Save and the slug
As soon as you save it in the editor, the template gets a slug — a short, stable string (e.g. fatura, recibo, post-instagram). The slug is what you pass in the template field of the API, and it works right away — no separate publish step. It is scoped to your organization: two different customers can each have a fatura template with no conflict.
| Concept | What it is | Where it appears |
|---|---|---|
| slug | Stable, readable identifier of the template | In the body: "template": "fatura" |
| DocumentModel | Structured representation of the document | Generated by the editor, compiled on the server |
| variável | Injection point {{...}} | In the layout, filled by data |
3. Use via the API
With the template saved, the call is minimal: the slug and the data. There is no need to resend the layout each time.
curl -X POST https://api.renderly.dev/v1/render \
-H "Authorization: Bearer rndr_live_YOUR_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"template": "invoice",
"data": {
"customer": "Acme Inc",
"issued_at": "2026-06-15",
"items": [
{ "description": "Pro plan (monthly)", "qty": 1, "amount": "$99.00" },
{ "description": "Extra user", "qty": 3, "amount": "$45.00" }
],
"total": "$234.00"
}
}' --output invoice.pdfconst res = await fetch("https://api.renderly.dev/v1/render", {
method: "POST",
headers: {
"Authorization": `Bearer ${process.env.RENDERLY_API_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
template: "invoice", // slug of the published template
data: invoice, // your data; fills {{...}} and tables
format: "pdf",
}),
})Minimal example
Simple templates need only the scalars their variables reference:
{
"template": "receipt",
"data": { "amount": "$50.00", "payer": "John" }
}404 template_not_found. If it exists but has no content, it is 422 template_empty. Check the slug in the Dashboard.Variables in the template
Variables follow the same syntax everywhere in Renderly. In the template path, beyond scalar substitution, they feed tables (via a data-source field), QR codes and charts.
| Syntax | Effect |
|---|---|
{{cliente}} | Inserts the value, with HTML escaping (safe). |
{{{cliente}}} | Inserts the raw value, without escaping (for trusted HTML). |
{{cliente.nome}} | Accesses a nested path inside data. |
{{status|pendente}} | Uses “pending” as a fallback if the value is missing. |
Tables iterate over an array from data (via a source field, the dataField), and each row references the columns of that item. The full reference for syntax, tables, QR and charts is in Data & variables.
Template or raw HTML?
| Use template when… | Use html when… |
|---|---|
| The document repeats (invoices, receipts) | It is a one-off layout or a prototype |
| There are data-driven tables, QR or charts | You already generate the HTML elsewhere |
| You want to version the layout outside your code | You want full control of the markup on that call |
| You want the native engine when possible | You need arbitrary CSS/JS rendered by Chromium |
Versioning and best practices
| Practice | Why |
|---|---|
| Short, stable slug | The slug becomes a contract with your code — avoid renaming it. |
| Fallbacks on optional variables | Avoids holes in the document when a value is missing. |
| Validate the data on your side | The API trusts the shape you send to the template. |
| Test with real data before relying on it | Tables and charts only reveal problems with real volume. |
Renderly