Variable references
Reference data between steps with template expressions, using the roots that resolve at run time, such as input, steps, secrets and trigger.
A step's config can contain {{ … }} expressions. Loopfour resolves them just before the step runs, using the run input, the outputs of steps that already ran and a few run-level values. In Studio the same thing appears as a field you pick from a list; the guide Use results from earlier steps shows it there.
Roots
| Expression | Resolves to |
|---|---|
{{input.<path>}} | The run input. What it contains depends on the trigger; see Where trigger data lands |
{{steps.<stepId>.<path>}} | A field of an earlier step's output. The step must have run before the step that reads it |
{{variables.<name>}} | Loop bindings only. Inside a Loop step: the item variable, the index variable and variables.loop. Empty outside a loop |
{{connections.<provider>}} | The id of the connection the run uses for that provider, for example {{connections.quickbooks}} |
{{trigger.connectionId}} | The connection that fired the trigger, when the trigger came from a connected account. It is the only field under trigger |
{{run.id}} | The current run id |
{{secrets.KEY}} | A secret stored on this workflow. KEY is UPPER_SNAKE_CASE |
Any other root resolves to an empty value. There is no server-environment root and no clock value such as now: pass a date in the run input, or read one from a trigger payload.
Fixed values that differ per company, such as an account code or an approval limit, go into the step's config as plain text. Values that change per run come in through input. Credentials go in {{secrets.KEY}}.
Paths
- Separate keys with dots:
{{input.customer.billing.email}}. - Use a plain number for an array position:
{{steps.fetch_invoices.invoices.0.total}}. Brackets such as[0]do not resolve. - A step's output is stored as it is, so the path starts straight after the step id. Do not add an
outputsegment between the step id and the field; that older form, still found in some workflows built in Studio, resolves to an empty value. Validation warns about it withREFERENCE_OUTPUT_SEGMENT.
Types
The whole value is one expression:
{ "lines": "{{steps.fetch_invoices.invoices}}" }Arrays and objects arrive as they are. Strings, numbers and booleans arrive as text, so "{{steps.calc.total}}" gives "42". The field that reads it must accept a numeric string.
An expression inside longer text always produces text:
{ "memo": "Invoice {{input.invoiceNumber}} for {{input.customer.name}}" }An expression that resolves to nothing is left empty. In longer text it becomes an empty string.
Filters and fallbacks
{{path | json}}writes the value as formatted JSON text.{{path | parseJson}}turns a JSON string into a value.{{path | size}}gives the length of an array or string.{{path || fallback}}usesfallbackwhen the value is missing,nullor an empty string. The fallback is another path, or quoted text:{{input.currency || 'USD'}}.- Filters combine with a fallback:
{{input.metadata | parseJson || steps.defaults.metadata}}. {{path | multiply: 100}},{{path | divide: 100}},{{path | add: 5}}and{{path | subtract: 5}}do arithmetic with a number.multiplyrounds the result to a whole number, which suits converting an amount to cents.
Text fields also accept Handlebars blocks such as {{#if input.isUrgent}}URGENT: {{/if}} and {{#each steps.fetch_invoices.invoices}}…{{/each}}.
Secrets
{{secrets.KEY}} reads a secret stored on the workflow (see the Workflow Secrets API). The value is put in only when the step runs, and it is masked in saved step input and output, error messages and logs.
- A run fails before its first step with
Missing required secrets: KEYwhen a referenced secret does not exist on the workflow. - Sub-Workflow step config cannot reference a secret. Store the secret on the child workflow instead.
- A Code step (including the code agent and a code template inside a Parallel step) cannot reference a secret: saving it fails, and a stored one stops the run before it starts. Call the API in an API Request step and pass its output to the Code step.
- A
{{secrets.KEY}}token that arrives inside run input or a step output is not resolved; it is replaced with[secrets reference removed].
Where trigger data lands
Each trigger puts its payload in a different place under input.
| Trigger | Read it from |
|---|---|
API (POST /workflows/:id/run) | {{input.<field>}}: the input object you posted |
| Webhook | {{input.webhookEvent.payload.<field>}}; also input.webhookEvent.eventType and input.webhookEvent.provider |
| HubSpot or Airwallex event | {{input.webhookEvent.payload.data.<field>}}; see App event triggers |
| Schedule | {{input._schedule.scheduledTime}}, {{input._schedule.timezone}} |
| Inbound email | {{input.inboundEmail.<field>}}, for example {{input.inboundEmail.attachments.0.fileId}} |
| Slack | {{input.slackEvent.payload.<field>}}; also input.slackEvent.source |
Inside loops and parallel branches
Steps inside a Loop step read the current element as {{variables.item}} and its position as {{variables.index}}. The names come from the loop's itemVariable and indexVariable.
A Parallel step with forEach works differently: it replaces the exact text {{item}} and {{itemIndex}} (named after as) in each copy of the step template before the copy runs. Paths such as {{item.id}} are not replaced there. See the Loop block and Parallel block.
Example
A step that creates a QuickBooks invoice from the run input and an earlier customer lookup:
{
"id": "create_invoice",
"type": "action",
"name": "Create invoice",
"action": "quickbooks.createInvoice",
"config": {
"customerId": "{{steps.get_customer.id}}",
"lines": "{{input.lines}}",
"invoiceNumber": "{{input.invoiceNumber}}",
"dueDate": "{{input.dueDate || steps.defaults.dueDate}}",
"customerMemo": "Invoice {{input.invoiceNumber}}, run {{run.id}}"
}
}lines is one whole expression, so the array arrives as an array. customerMemo mixes text and expressions, so it arrives as text. The config fields an action accepts are listed on its integration page, for example QuickBooks actions.
Workflow definition format
Read the workflow definition format: the trigger, the steps and their types, how steps connect, and the portable export used for import.
Errors, retries and timeouts
Configure how a step behaves when it fails, how retries and timeouts work, and the shape of the error responses the Loopfour API returns.
Loopfour