Template data and helpers

The placeholders, linked records and formatting helpers available inside a PDF template.

A template mixes fixed layout with {{placeholders}} that are filled in when the document is made. This page lists the data and helpers you can use.

How placeholders work

  • Placeholders use double curly braces, for example {{.org.name}}.
  • Conditions and loops use {{if …}}…{{end}} and {{range …}}…{{end}}.
  • Values are always escaped. A company called R&D <Ltd> prints exactly like that and can never break your layout.
  • A placeholder that is not written correctly is refused when you save, with a message from the template language.

Data you can use

Placeholder What it holds
{{.org.name}} Your workspace name.
{{.org.default_currency}} The workspace default currency code, for example INR.
{{.now}} The moment the document is made. Use it with {{date .now}}.
{{.record.values.<field>}} A field of the record, by its field key, for example {{.record.values.number}}.
{{.record.id}}, {{.record.type}}, {{.record.created_at}} The record's id, type key and creation time.
{{.refs.<field>.values.<field>}} A record linked through a reference field, for example {{.refs.customer.values.name}}.
{{.data}} Extra data passed in by a function. Empty when you generate from the Documents tab.

.record and .refs exist only when a record is used. Guard them with {{if .record}} and {{if .refs.customer}} so the template also works without one.

Linked records

  • Each reference field on the record type is resolved one level deep. A field that links to many records (refs) gives a list you loop over with {{range .refs.items}}.
  • A linked record you are not allowed to read, or one that no longer exists, is skipped. Guard with {{if}}.
  • Up to 50 linked records are loaded for one document.

Permissions and masked fields

Documents are built with the permissions of the person generating them. A field that person cannot see is not available to the template, so it does not appear on the PDF.

Helpers

Helper Example Result
money {{money .record.values.total .org.default_currency}} 1,234.50 INR. Thousands separators, two decimals (extra decimals are cut, not rounded), currency code appended. Text that is not a number is printed as it is, with the currency code after it.
date {{date .record.created_at}} Jan 2, 2026.
datetime {{datetime .now}} Jan 2, 2026 15:04.
upper {{upper .record.values.name}} Upper case.
lower {{lower .record.values.name}} Lower case.

date and datetime understand stored date values; anything they cannot read is printed unchanged. The standard template tools such as printf, index, and, or, eq and len also work.

Page numbers

{page} and {pages} (single braces) work only inside <header> and <footer>. Example: Page {page} of {pages}.

Images

Images must be embedded as base64 data: addresses (PNG, JPEG or GIF). Web links are not fetched. See Layout reference.

Example: line items

{{range $k, $v := .record.values}}
<tr><td>{{$k}}</td><td>{{$v}}</td></tr>
{{end}}

This prints one table row per field of the record. It is the loop in the starter layout.