Overview
A flow gets far more powerful when it can read the data that started it and reuse the output of every step. The Flow Builder now ships a set of data and mapping features: the webhook/API body becomes a variable, the response of any earlier node is available to the next ones, the outbound webhook can store its response, and two new nodes β Loop items and Transform data β let you walk through lists and manipulate data without leaving the canvas.
Everything is optional and backward compatible: existing flows keep working exactly as before.
Prerequisites
- The Flow Builder module enabled for your account.
- Administrator to edit and publish the flow. Agents can follow the runs.
- For the trigger-data features: a Webhook or API trigger in the flow.
- Basic grasp of variables: in the editor, the variables button (
{ }) and typing{{open the list of available tokens. Insert a token by writing it in double braces, e.g.{{ trigger.body.email }}.
Step by step
Example: an order arrives via webhook and you want to use the order number in a message.
- On the trigger node (Webhook or API), open the Sample payload section.
- Click Fetch last event (or Paste JSON) to bring in a real example of the body.
- In the tree that appears, click the value you want (e.g.
order.id). That creates a variable β path mapping (e.g.id β body.order.id). - Optional: Pin the sample to keep it on the flow and feed the editor's variable list.
- In any later node, use the mapped variable (
{{ vars.id }}) β or go straight to the body with{{ trigger.body.order.id }}. - Publish the flow.
Settings & options
Trigger data
- Webhook/API body as a variable: the body that started the flow is available in
{{ trigger.body.field }}β for example{{ trigger.body.order.id }}or{{ trigger.body.items[0].sku }}. It works for JSON and for form posts; unstructured content arrives in{{ trigger.body.raw }}. - Size limit: the body is stored up to 64 KB. Larger payloads are truncated (top-level fields are kept and a warning is flagged).
- Direct mapping on the trigger: besides reading the body, you can map paths into named variables right on the trigger (variable β path). This mapping works for all trigger families, not just webhooks β paths are relative to the data that started the flow.
Sample payload in the editor
Available on the Webhook and API triggers:
| Action | What it does |
|---|---|
| Fetch last event | Brings in the last real call received by that trigger. |
| Listening | If there's no event yet, the editor keeps listening and checks every few seconds (up to 60s). Send a test call to capture it. |
| Paste JSON | Paste an example manually when there's no real traffic yet. |
| Clickable tree | Renders the sample; clicking a value creates a variable β path mapping. |
| Pin | Keeps the sample on the flow. The pinned sample feeds the editor's variable list and travels with the export (you can unpin anytime). |
The "Available data" panel in the inspector
When you select any node, the inspector shows the Available data panel β a catalog of everything you can insert, organized into four tabs:
- Trigger β the trigger payload tree (pinned sample or the real last run). Click a value to insert
{{ trigger.β¦ }}. No sample yet? Use Fetch last event. - Steps β the output of each earlier node, with the real values from the last run. Steps with no output yet show "no output yet"; renamed or removed steps are greyed out.
- Variables β the variables the flow produces (
vars.*), with the last-run value when there is one. - Standard β the standard contact, conversation, agent, inbox, account, CRM, flow, and Account Brain fields.
Each field shows an example value (from the last run) next to the token when available β the same chip
appears in the variables button ({ }) list. Click a field and it is inserted where the cursor is. The
values reflect the last run and may be outdated; use Refresh to fetch the latest.
Auto-map fields
On the mapping surfaces (the HTTP request test, the trigger sample, and the Outbound webhook),
when a response sample is present the Auto-map fields button creates one row per top-level field:
the variable name is normalized (lowercase with _) and the path points at the field. Repeated names get
a suffix (_2, _3), already-mapped fields are skipped, and the cap is 20 per click. The path field
also suggests paths from the sample as you type.
Insert variables in actions
The action nodes (create contact, CRM actions, tasks, WhatsApp, etc.) now offer the variables button
too. Typing {{ in a text field opens the list, and the header carries Insert variable for actions
made only of selectors. The variable lands in the focused field, exactly like in messages.
Step outputs
- The response of any earlier node is available to the next ones in
{{ steps.step_name.field }}. - The step name is the node label in lowercase with
_replacing spaces/symbols (or the node id when the label is empty). Rename the node to get a predictable name. - Common fields:
statuson any node; the HTTP request node also exposesbodyandhandle(e.g.{{ steps.lookup.body.total }},{{ steps.lookup.status }}).
Outbound webhook: capture the response
- The Outbound webhook node can optionally store the response in a variable and map fields from
it into named variables (dot paths, e.g.
data.id). - It is off by default: with no variable and no mappings, the behavior is identical to before.
New nodes: Loop items and Transform data
Loop items β walks a list one item at a time:
- Point at the list (e.g.
{{ vars.orders }},{{ steps.lookup.body }}, or a dotted path). - Each pass exposes the current item and the index in variables (e.g.
{{ vars.item }},{{ vars.loop_index }}). - Wire the item output back into the node to loop; the done output fires when finished.
- Limits: up to 100 items per loop; each pass spends the body's steps within the session step budget (so very large loops can exhaust it β the editor warns).
Transform data β manipulates data into a variable, with success / error outputs:
- Template: renders text from a template.
- JSON: produces structured data (the text must be valid JSON).
- Array operation: applies one operation over a list β
pick,filter,first,last,count,sum,unique,sort,join. - String: splits text into a list or extracts values with a regular expression.
Use cases
- Turn an order received by webhook into a chained contact, deal, charge and task.
- Iterate over HTTP response items and run one controlled action for each item.
- Map provider IDs and statuses into waits, conditions and later messages.
Mapping at scale (large, nested payloads)
Mapping was hardened for real-world payloads β large, deep and full of nested objects:
- Auto-map fields now descends 6 levels and maps every leaf (nested objects like
utm{}andcontact{}included), deriving names from the last segment (utm.utm_sourceβutm_source) and disambiguating collisions automatically (contact.idandorder.idβidandorder_id). When there are more fields than the 100-per-click cap, the toast says exactly "Mapped X of Y". - Search everywhere: the variable picker and the data panel gained search β including fields beyond the display cap (the footer tells you how many stayed hidden).
- Huge trees under control: each branch renders 50 items at a time ("Show more"), with a size
badge (
~N KB), hover copy-path/copy-value, and navigation over EVERY array index (you can mapitems.3.sku, not just the first element). - Nothing disappears silently: when the server must prune an oversized response, the dropped branches show up in an amber banner (with the exact paths); a mapped path that doesn't exist in the payload becomes a "path not found" chip in the trace β the variable stays empty, but you know.
- Negative index:
items.-1.skugrabs the last element. Bracket form (items[0].sku) is accepted as you type and converted automatically. - Richer conditions: 14 new operators (ends with, is in list, is empty, is a number, is true/false, date before/after/within N days, length greater/less, list contains) plus condition groups with ALL/ANY between groups.
- Transform data gained new operations (min, max, average, slice, reverse, flatten, compact, to JSON) and a string mode (split into list and extract with regex).
Tips, limits & best practices
- No parallel branches: a flow moves one step at a time β there's no simultaneous execution of two paths and no join nodes. Loop items processes the list in sequence (which also lets waits inside the loop work naturally).
- Large payloads are truncated: the trigger body (64 KB) and step outputs have limits; when they're exceeded, the data is truncated and a warning is flagged so you notice.
Troubleshooting
- Path not found: refresh the sample and verify the complete path, including array indexes.
- Missing output: confirm the step ran and check the trace for truncation or eviction markers.
- Publish refused: fix the variable, handle or out-of-schema field identified by validation.
- Unsupported transform mode: choose Template, JSON, Array, or String. The run error shows the
received value and the valid identifiers:
template,json,array,string.