POST /generate alongside a separate data object; Tipar walks the template, substitutes your data, and lays out the page.
Two rules
Everything about the template language follows from two deliberate constraints.No expressions, no math, no eval
No expressions, no math, no eval
Templates only do
{{path}} substitution against data. There is no arithmetic, no formatting helpers, no conditionals (beyond repeating table rows). Compute subtotals, totals, dates, and currency strings in your code and pass the finished values in data. This keeps templates safe to accept from anywhere and keeps rendering fast and predictable.Nodes mirror layout, not meaning
Nodes mirror layout, not meaning
Nodes are layout primitives —
column, row, text, table — not semantic components like invoice or lineItem. You compose a document the way you’d compose a layout. It’s a little more verbose than a purpose-built invoice block, but it’s fully general: the same handful of nodes build invoices, certificates, contracts, and reports.Anatomy of a template
A template has exactly one top-level key,page:
| Field | Type | Required | Notes |
|---|---|---|---|
size | "A4" · "A3" · "Letter" · "Legal" | no | Default A4. |
margin | number (points) | no | Default 30. Applied uniformly to all four sides. |
defaultTextStyle | Style | no | Page-wide text defaults. See the propagation note below. |
header | Node | no | Repeats at the top of every page. |
content | Node | yes | The page body — the only required field. |
footer | Node | no | Repeats at the bottom of every page. |
All measurements are in points (1 point = 1/72 inch), the standard PDF unit.
A4 is 595 × 842 pt; Letter is 612 × 792 pt.The node catalog
Every node carries a"type" discriminator. There are seven node types:
column
Vertical stack of child nodes.
row
Horizontal band of sized cells.
text
A single styled string.
richText
Mixed-style runs and page-number tokens.
spacer
A fixed vertical gap.
image
A base64-embedded image.
table
A grid with a
forEach-driven body.row cell can hold a column, which holds text and a table, and so on.
Interpolation
Anywhere atext value or rich-text span appears, you can interpolate data with double braces:
- Dotted paths walk objects:
{{invoice.billTo.name}}readsdata.invoice.billTo.name. - Whitespace inside the braces is fine:
{{ invoice.number }}is the same as{{invoice.number}}. - Inside a table body, the current row element is bound to
item—{{item.description}}. See Tables. - Values must be scalars — strings, numbers, booleans. A path that points at an object or array renders as empty.
Missing data is an error
If a template references a path that isn’t present indata, the request fails with 422 Unprocessable Entity and lists every missing path — so you fix them all in one round trip rather than one at a time.
Next
Layout
Stack and arrange content with
column, row, and spacer.Text & styling
Typography, colour, alignment, and page numbers.
Tables
Repeat rows over your data.
Full schema
The exhaustive node-by-node reference.