FX Formulas
FX formulas are how you reference dynamic data in workflow nodes. Every text field marked with the FX icon supports formulas, allowing you to pull in data from triggers, previous nodes, and built-in functions.

Basic syntax
Wrap variable references in double curly braces:
{{trigger.body.email}}
You can mix static text with variables:
Hello {{trigger.body.name}}, your order #{{trigger.body.order_id}} has been received.
Variable sources
Trigger variables
Data from the event that started the workflow:
{{trigger.body}} → full request body (webhook)
{{trigger.body.email}} → specific field
{{trigger.body.items[0]}} → first item in an array
{{trigger.query.utm_source}} → URL query parameters
{{trigger.headers.content-type}} → request headers
{{trigger.timestamp}} → when the trigger fired
Node output variables
Data from any previous node in the workflow:
{{http_request.body}} → response body from HTTP Request
{{tinygpt.result.category}} → AI classification result
{{find_one.record.email}} → database lookup result
{{transformer.result}} → transformer output
{{slack.message.ts}} → Slack message timestamp
{{jira.issue.key}} → created Jira ticket key
The variable name matches the node's type (or its custom name if you renamed it).
System variables
Built-in values available in any node:
{{NOW()}} → current timestamp
{{TODAY()}} → today's date (midnight)
{{YESTERDAY()}} → yesterday's date
{{WEEK_START()}} → start of current week
{{MONTH_START()}} → start of current month
{{WORKFLOW_ID}} → current workflow's ID
{{EXECUTION_ID}} → current execution's ID
{{WORKSPACE_ID}} → workspace ID
The FX editor
Click the FX button on any field to open the formula editor:
Variable picker
The left panel shows all available variables organized by source:
- Trigger: all trigger output fields
- Node 1: first node's output
- Node 2: second node's output
- etc.
Click any variable to insert it.
Autocomplete
Type {{ to trigger autocomplete. As you type a node name or field, matching options appear.
Preview
The editor shows a live preview of what the formula evaluates to, using the last test run's data.
Functions
FX supports built-in functions for data manipulation:
Text functions
| Function | Description | Example |
|---|---|---|
UPPER(text) | Convert to uppercase | UPPER({{name}}) → "ALICE" |
LOWER(text) | Convert to lowercase | LOWER({{email}}) → "alice@co.com" |
TRIM(text) | Remove leading/trailing whitespace | TRIM({{input}}) |
LEFT(text, n) | First n characters | LEFT({{name}}, 1) → "A" |
RIGHT(text, n) | Last n characters | RIGHT({{phone}}, 4) → "1234" |
REPLACE(text, old, new) | Replace substring | REPLACE({{url}}, "http://", "https://") |
CONCAT(a, b, ...) | Join strings | CONCAT({{first}}, " ", {{last}}) |
LENGTH(text) | Character count | LENGTH({{message}}) |
CONTAINS(text, search) | Check if text contains substring | Returns true/false |
Number functions
| Function | Description | Example |
|---|---|---|
ROUND(n, decimals) | Round to decimal places | ROUND({{price}}, 2) |
FLOOR(n) | Round down | FLOOR(4.7) → 4 |
CEIL(n) | Round up | CEIL(4.2) → 5 |
ABS(n) | Absolute value | ABS(-5) → 5 |
MIN(a, b) | Smaller of two values | MIN({{score}}, 100) |
MAX(a, b) | Larger of two values | MAX({{score}}, 0) |
SUM(array) | Sum of array values | SUM({{items.*.price}}) |
AVG(array) | Average of array values | AVG({{scores}}) |
Date functions
| Function | Description | Example |
|---|---|---|
NOW() | Current timestamp | NOW() |
TODAY() | Today's date (midnight) | TODAY() |
DATE_ADD(date, n, unit) | Add time | DATE_ADD(NOW(), 7, "days") |
DATE_DIFF(a, b, unit) | Difference between dates | DATE_DIFF({{due}}, NOW(), "hours") |
FORMAT_DATE(date, fmt) | Format a date | FORMAT_DATE(NOW(), "MMM DD, YYYY") |
YEAR(date) | Extract year | YEAR({{created_at}}) |
MONTH(date) | Extract month (1-12) | MONTH({{created_at}}) |
Logic functions
| Function | Description | Example |
|---|---|---|
IF(cond, then, else) | Conditional value | IF({{score}} > 80, "Hot", "Cold") |
AND(a, b) | Both true | AND({{active}}, {{verified}}) |
OR(a, b) | Either true | OR({{email}}, {{phone}}) |
NOT(a) | Negate | NOT({{deleted}}) |
ISEMPTY(val) | Check if null/empty | ISEMPTY({{phone}}) |
COALESCE(a, b, c) | First non-null value | COALESCE({{nickname}}, {{first_name}}, "User") |
Array functions
| Function | Description | Example |
|---|---|---|
COUNT(array) | Number of items | COUNT({{items}}) |
FIRST(array) | First item | FIRST({{results}}) |
LAST(array) | Last item | LAST({{results}}) |
JOIN(array, sep) | Join into string | JOIN({{tags}}, ", ") |
UNIQUE(array) | Remove duplicates | UNIQUE({{emails}}) |
FLATTEN(array) | Flatten nested arrays | FLATTEN({{nested}}) |
Nested access
Access deeply nested data with dot notation:
{{trigger.body.customer.address.city}}
{{http_request.body.data.results[0].name}}
{{find_all.records[2].metadata.source}}
Array indexing uses [0] for first item, [1] for second, etc.
Wildcard array access
Use * to access a field from all items in an array:
{{find_all.records.*.email}} → ["a@b.com", "c@d.com", "e@f.com"]
{{items.*.price}} → [29.99, 49.99, 99.99]
This is useful with aggregate functions: SUM({{items.*.price}}).
Common formula patterns
| Pattern | Formula |
|---|---|
| Full name | CONCAT({{first_name}}, " ", {{last_name}}) |
| Default value | COALESCE({{phone}}, "Not provided") |
| Days until due | DATE_DIFF({{due_date}}, NOW(), "days") |
| Percentage | ROUND({{completed}} / {{total}} * 100, 1) |
| Conditional greeting | IF({{hour}} < 12, "Good morning", "Good afternoon") |
| Truncate long text | IF(LENGTH({{text}}) > 100, CONCAT(LEFT({{text}}, 100), "..."), {{text}}) |
Use the FX editor's preview to verify your formula evaluates correctly. If the preview shows "undefined" or an error, the variable path is wrong; check the node output in the test results.
Formulas referencing a node's output will fail if that node hasn't run yet (e.g., referencing a node on a different If-Else branch). Always ensure the referenced node is in the execution path before the current node.