Expressions
Expressions let you compute values directly inside your templates. Instead of calculating totals or formatting data before sending it to the API, you can do it right in the template using simple functions and operators.
Arithmetic operators
You can use standard math operators inside any {{ }} variable block:
| Operator | Example | Result |
|---|---|---|
+ | {{price + tax}} | Addition |
- | {{total - discount}} | Subtraction |
* | {{items.qty * items.price}} | Multiplication |
/ | {{amount / 2}} | Division |
For example, to show the line total in an invoice table row:
{{items.qty * items.unit_price}}This multiplies quantity by unit price for each row automatically.
Built-in functions
Row-level functions
These functions work on individual values. When used with array fields (like items.qty), they repeat automatically for each row.
| Function | Syntax | What it does |
|---|---|---|
mul | {{mul(a, b)}} | Multiply two values |
add | {{add(a, b, c)}} | Add multiple values |
sub | {{sub(a, b)}} | Subtract b from a |
div | {{div(a, b)}} | Divide a by b |
Example — calculate a line total with a discount:
{{sub(mul(items.qty, items.unit_price), items.discount)}}Aggregate functions
These functions operate on an entire array and return a single value. They do not trigger row repetition.
| Function | Syntax | What it does |
|---|---|---|
sum | {{sum(items.amount)}} | Sum all values of a field |
sumproduct | {{sumproduct(items.qty, items.price)}} | Multiply two fields row by row, then sum the results |
count | {{count(items)}} | Number of items in a list |
avg | {{avg(items.price)}} | Average of a field |
min | {{min(items.price)}} | Smallest value |
max | {{max(items.price)}} | Largest value |
Example — show the invoice total:
{{sum(items.amount)}}Sumproduct
sumproduct multiplies two fields row by row, then sums the results — just like SUMPRODUCT in a spreadsheet.
{{sumproduct(items.qty, items.price)}}For each item, this computes qty × price, then sums all the line totals. This is typically how you compute an invoice subtotal when your data only contains quantity and unit price.
Filters
Filters transform a value after it has been computed. Use the | symbol to apply a filter.
Formatting numbers
| Filter | Example | Output |
|---|---|---|
round(n) | {{total | round(2)}} | 19.57 |
int | {{value | int}} | 42 |
float | {{value | float}} | 3.14 |
abs | {{value | abs}} | 5 (from -5) |
You can chain filters:
{{items.qty * items.unit_price | round(2)}}Formatting text
| Filter | Example | Output |
|---|---|---|
upper | {{name | upper}} | JOHN DOE |
lower | {{name | lower}} | john doe |
capitalize | {{name | capitalize}} | John doe |
title | {{name | title}} | John Doe |
Working with lists
| Filter | Example | What it does |
|---|---|---|
length | {{items | length}} | Number of items |
first | {{items | first}} | First item |
last | {{items | last}} | Last item |
join(", ") | {{tags | join(", ")}} | Join items into a string |
sort | {{items | sort}} | Sort items |
reverse | {{items | reverse}} | Reverse order |
Conditionals
You can show or hide content based on conditions:
{% if payment_status == "paid" %}
Paid ✓
{% else %}
Payment pending
{% endif %}You can also use elif for multiple conditions:
{% if total > 1000 %}
Premium order
{% elif total > 500 %}
Standard order
{% else %}
Small order
{% endif %}Available comparison operators: ==, !=, <, >, <=, >=
Logical operators: and, or, not
Practical examples
Invoice subtotal, tax, and total
Subtotal: {{sumproduct(items.qty, items.unit_price) | round(2)}}
Tax (10%): {{sumproduct(items.qty, items.unit_price) * 0.1 | round(2)}}
Total: {{sumproduct(items.qty, items.unit_price) * 1.1 | round(2)}}Item count
{{count(items)}} items in this orderConditional message
{% if count(items) > 10 %}
Bulk order — thank you!
{% endif %}Good to know
- Missing variables render as empty — no error is shown in the generated PDF.
- Division by zero returns empty instead of crashing.
- Floating-point rounding is handled automatically (e.g.
48.18000000000001becomes48.18). - Aggregate functions (
sum,avg,min,max,count) never trigger row repetition. Row-level functions (mul,add,sub,div) do when referencing array fields.
Next steps
- Data Binding — How to define variables and pass data to your templates
- Tables — Dynamic tables that grow with your data
- System Variables — Built-in variables for dates and page numbers