CORE
Templates
Keep your markup in one place and pass only the data each call — inline, or saved as a reusable stored template.
Inline templates
Pass a template string containing {{ }}placeholders and a data object. The values in dataare merged into the placeholders before the HTML is rendered.
{
"template": "<h1>Invoice {{number}}</h1><p>Bill to: {{billTo.name}}</p><p>Total: {{total}}</p>",
"data": {
"number": "INV-1024",
"billTo": { "name": "Globex LLC" },
"total": "€1,240.00"
},
"pdf": { "format": "A4", "printBackground": true }
}Placeholder syntax
{{ value }}inserts a value, HTML-escaped— safe for untrusted data.{{{ value }}}inserts a value raw (no escaping) — use only for trusted HTML fragments.- Dotted paths reach into nested objects, e.g.
{{ billTo.name }}or{{ user.address.city }}.
Provide either html or template — if html is sent, template and data are ignored.
Stored templates
Save a named template once inDashboard → Templates, then render it by id: pass its tpl_… id as template and just thedata each call. The same field accepts either an inline string or a stored id — the API resolves a tpl_ id you own first, and otherwise treats the value as inline markup.
{
"template": "tpl_8sJ2kQ...",
"data": {
"number": "INV-1024",
"billTo": { "name": "Globex LLC" },
"total": "€1,240.00"
}
}Stored templates are owner-scoped: only ids your account owns resolve. A tpl_… id you don't own returns404 template_not_found (see Errors).
Template limits
How many stored templates you can keep depends on your plan:
- Trial — 1 stored template
- Starter — 10 stored templates
- Pro — unlimited
See pricing for the full plan comparison. Inline templates have no limit — they don't count against this.