Guide
Fields and bindings
A field is a piece of text that comes from your data instead of being typed as fixed wording. "Invoice no. 1044" has one fixed word ("Invoice no.") and one field (the number) — change the data, and only the field changes when the document is generated.
What "your data" is
Think of a template as a printed form and your data as the information filled in for one copy: the customer's name, the invoice number, the amounts. Each time you generate a document you give the template a fresh set of that information, and every field takes its value from it.
Data is organised the way you would describe it. A customer has a name and a city; an invoice has a number and a date. Each piece has a path — the route to it, such as customer › name or invoice › number. A list is a group of records of the same shape — the lines of an invoice, the rows of a statement — and is what tables, lists and repeating sections are built from.
Where the data comes from depends on how you generate. While you design, it is the sample
data in the editor, so the page shows realistic content. When you generate for real, it is a
spreadsheet you upload (one document per row), data you edit in the preview, or data your own
software sends through the API. In every case the only thing that has to agree is the path. If
the template reads invoice › number and your system calls it invoiceNo, the field prints blank.
Data bindings in the toolbar lists the paths your sample data really has.
Data is not the same as translations. Data is what differs from one document (names, amounts, dates); translations are the fixed wording that differs from one language. See Translations.
Advanced syntax — how a field is written
Behind the scenes a field is a {{ }} token that points at a path under $data, your document's
data: $data.customer.name, $data.invoice.total. You almost never type one — the dialogs below
build it for you — but you will see it in the few boxes that take text (a QR code's Value, a
picture's "Write an expression instead", a Label + value block) and when you want to format a
value. The editor's sample data supplies a value for every field so the canvas can show what the
document will look like while you edit it.
Typing a path
Wherever the editor lets you type a path — the Path box under a list chooser, the Repeat dialog's "Or type a path", or a picture's "Write an expression instead" — it suggests paths from your sample data as you type. The Down and Up arrow keys highlight a suggestion; Enter or Tab takes the highlighted one in place of the path you are typing; Escape closes the list. Nothing is highlighted until you press an arrow key, so Tab with nothing highlighted simply moves on and never changes what the box holds. A path the box already holds is not suggested again. Clicking a suggestion takes it too, and the cursor stays in the box. Leaving the box — clicking elsewhere or moving to another field — closes the list straight away, so the next Escape or letter you press goes where you now are.
Picking a field from the Data pane
Open Data bindings from the toolbar to see every field of your sample data. Any box in the side panel that takes a field — a text box such as a QR code's Value, or a Path box — takes one from the pane: click in the box, then click the field. From the keyboard, press Shift+Tab from the box until you reach the field in the pane, and press Enter. Either way the field goes in where your cursor was, and the cursor is back in the box so you can carry on typing. Tabbing past another box on the way does not move the field there; typing or clicking in it does. Doing anything else on the way — another key, a click elsewhere, moving on past the pane — lets go of the box, and the pane then says that nothing was inserted.
Editing sample data
Open Manage data from the toolbar. The Fields tab lets you add fields and lists, type values, add records to a list and change a value's type with ordinary controls — no JSON needed. The JSON tab shows the same data as text, for anything the Fields tab cannot show (a list that mixes records and plain values, for example). An edit that is not valid is never saved: the last valid data keeps showing, and the tab says what is wrong.
The template's default sample is what the canvas shows unless you choose otherwise, and what an API call that sends no data renders.
Ristmark is for business use and excludes payment-card numbers, health records and other sensitive personal data — in sample data as everywhere else.
Test scenarios
A scenario is a named set of sample data saved with the template — "No line items", "Sixty line items", "Customer email missing" — so you can see how the document behaves with data that is short, long or incomplete, without changing the default sample.
- The switcher at the top of Manage data chooses which data set the canvas shows and the tabs below edit: the default sample or one scenario. Choosing one is not an edit — the template does not change and nothing is added to undo. This browser remembers your choice for the template.
- New scenario starts from a copy of the default sample or from nothing. Duplicate, Rename and Delete work on the scenario you are viewing; Delete asks first and can be undone.
- Use as default sample is the only way a scenario's data becomes the default. It asks first, because API calls that send no data will render it from then on.
- Add missing fields from default copies in fields the default sample has and the scenario lacks. It never overwrites a value the scenario already has, and an empty list stays empty.
- While a template has scenarios, the toolbar shows which data is on screen ("Sample: Default" or "Sample: No line items"). If the scenario you were viewing disappears — undone, restored from an older version, or deleted elsewhere — the editor goes back to the default sample and says so.
- A template keeps at most 20 scenarios, one scenario holds at most 256 KiB, and all of a template's sample data together at most 1 MiB. Scenarios are saved with the template, its published versions and its exports, so use made-up values.
Checking every scenario
In Preview, Check scenarios lays the template out with the default sample and every scenario, in your browser, and lists what it finds scenario by scenario: fields with no value, empty lists and what they print, rules that hid a block, blocks that no longer fit or now run across more pages, and values an output cannot print. Open block shows that scenario and selects the block. Problems that would stop the template saving are listed separately from data warnings. The check uses no generation credits. It checks data and layout, not every export detail, and its results go out of date as soon as you edit the template.
Download final in Preview says which data it will use — the default sample, the scenario you are viewing, or data you edited in the preview — before you spend a credit on it.
The three ways to make one
- The review screen. When a document is first recognized, the reviewer already proposes fields with a confidence band — accept, correct, or reject each one before it ever reaches the editor.
- The ⋮ menu (or right-click). Select some text — inside a Text block, a table cell, or a list item — and choose Make this a field from the block's ⋮ menu. It opens the same dialog every other entry point uses: name the field, and it replaces your selection with a token bound to that name.
- The block bar. While editing a Text block, table cell or list item in place, the block's toolbar grows a second row with a Field… button that does the identical thing — for whichever text you have selected right now.
A Label + value block's whole value is the thing to bind — since it has no meaningful range to select inside a single value like "€1,931.00", its own ⋮ menu offers Make this a field for the whole value in one step instead.
Existing fields
The dialog also offers Bind to… — pick an already-bound field instead of creating a new one,
so a document's fields stay in one vocabulary (sellerEmail, not a second seller.email meaning
the same thing).
Formatting a value
Data usually arrives as plain values — 1234.5, 2026-10-01. You decide how it prints by wrapping
the field in a function (advanced syntax), inside the same {{ }}:
| You write | You get (for an en-GB, EUR template) |
|---|---|
{{ format($data.invoice.total, 'currency') }} |
€1,234.50 |
{{ format($data.item.rate, 'percent') }} |
19% for 0.19 |
{{ format($data.item.qty, 'integer') }} |
a whole number |
{{ formatDate($data.invoice.date, 'long') }} |
1 October 2026 for 2026-10-01 |
{{ formatDate($data.invoice.date, 'iso') }} |
2026-10-01 |
{{ default($data.customer.phone, '—') }} |
a dash when there is no phone |
{{ upper($data.customer.country) }} |
LATVIA |
{{ concat($data.customer.first, ' ', $data.customer.last) }} |
Jane Doe |
{{ sum($data.items, 'amount') }} |
the total of the amount field over every line |
{{ round($data.x, 2) }} |
rounded to two decimals |
format also takes 'number' (the default), 'money' and 'decimal'; formatDate also takes
'medium' (the default) and 'short'. How numbers and dates are written — comma or period,
day first or month first — follows the Date/number locale and Currency on the Document tab
(see Document settings). A value a function cannot make sense of prints as it is, or blank,
never as an error.
Showing or hiding content
Any block, and a whole section (see Sections), can carry a visibility condition — a rule
that decides whether it appears at all. Turn on "Only show when…" in the block's Visibility
control (or a section's, on the Section tab) and build the rule from the same binding vocabulary
fields come from: pick a field, a comparison (is empty, is not empty, equals, does not equal,
greater than, less than, at least, at most), and a value. Inside a repeating section, the field
list also offers the current record's own fields (e.g. item.qty), not just the top-level ones.
The status line under the controls always distinguishes shown, hidden, a field that wasn't found in the sample data, a comparison that doesn't fit the value's type, and a plain typo — never lumping a broken condition in with a legitimate "false" result. Anything the structured builder can't express opens as a plain expression instead — switching between the two never rewrites what's saved, and a single Undo change restores the condition you started with.
Worked examples
Each one: select the block, turn on Only show when… in its Visibility control, and choose Field, Condition and Value as shown.
- A "Reverse charge" notice, only for customers abroad. Field
customer › country, Condition does not equal, ValueLatvia. The notice appears for every other country. - A discount line, only when there is a discount. Field
invoice › discount, Condition greater than, Value0. - An optional "Notes" paragraph. Field
invoice › notes, Condition is not empty. When the notes are empty, the paragraph disappears and its space closes up — nothing prints, and no blank gap is left. - A "PAID" stamp. Field
invoice › paid, Condition equals, Value True. - Inside a repeating section or table row. The field list offers the current record's own
fields (
item › qty), so a single line can show a "Back-ordered" note only when its own quantity is zero.
Before you rely on a rule, flip the sample: change the value in Manage data, or switch to a test scenario, and watch the line under the controls change between Shown and Hidden.
For anything the builder cannot say, switch to Advanced and write the rule as an expression, for
example $data.invoice.total > 0 && $data.customer.country != 'Latvia'. Use && for "and", ||
for "or", and == or != to compare. A rule that does not make sense hides the block: the safe
default is to leave it out rather than print something wrong. Whole sections can be hidden the same
way (see Sections), and a template whose every section is hidden produces no document.
Finding hidden content again
A hidden block has nothing on the page to click. Open the Outline tab in the left panel: every hidden block is still listed there, marked Hidden with the reason — its own condition is false, its condition has an error, or a block or section containing it is hidden (named, so you know which condition to change). Selecting it selects the block, so this Visibility control opens in the inspector, and a note under the row says why the page did not scroll. Turn on Show hidden content on the canvas at the top of the outline to see a marker on the page wherever hidden content sits; clicking a marker selects it the same way. Neither changes anything about what prints (see The outline).
Not supported: "contains" (matching part of a value) isn't offered as a comparison, because the underlying rule language has no way to check it exactly — offering it would mean either quietly approximating it or letting it fail later, and neither is the deal this product makes on data trust.
If something looks wrong
- A field prints blank. Its path is not in your data. Compare the field's path with the paths in Data bindings; a typo, a different spelling or a field your system does not send all print blank. The preview and the download report how many fields had no value.
- A table or repeating section prints nothing. The path it reads is not a list, or the list is empty. The block's side panel says which.
- A block disappeared. Check its Visibility. The line under the controls says whether the rule is currently shown or hidden for your sample data, and the Outline tab lists hidden blocks with the reason.
- A number or date prints raw (
1234.5,2026-10-01). It has no format. Wrap it informat(…)orformatDate(…)as above. - A date prints in the wrong order or a number with the wrong separator. That follows the Date/number locale on the Document tab.
- A condition I typed says "Syntax error". The expression is not valid; the block is hidden until it is. Rebuild it in the builder, or press Undo change.