GoRunner docs
Search or askSearch⌘K

Expressions

What you can write between {{ and }}, and what you get back.

Cloud, Self-hosted and Embed

Any field can take an expression. GoRunner fills it in when the step runs. To insert one without typing, see Use data from earlier steps.

Where data comes from

{{trigger.body.email}}
The trigger’s data, such as a form’s field. {{steps.trigger.body.email}} is the same.
{{steps.step_1.id}}
An earlier step’s output, by the step’s name.
{{steps.step_2.result}}
What a Code step returned.
{{steps.step_3.item}}
Inside a loop: the current item. .index is its place from 0, .total the count.
{{steps.step_4.resumeData}}
What was sent to a held step’s resume link, such as an approval’s answer.
{{steps.step_1.error}}
In an error step: why the step failed.
{{$vars.API_URL}}
A workflow variable, plain or sensitive.
{{$execution.id}}
This run’s ID. Also $execution.mode and $execution.startedAt.
{{$workflow.id}}
This workflow’s ID. {{$workspace.id}} is its workspace’s.
Where do I find a step’s name?

Insert a value with the data picker, then point at it: the full path shows, such as {{steps.step_1.id}}.

Paths

Dots go into an object; a number in brackets picks from a list: {{steps.step_1.body.items[0].name}}. A path that leads nowhere gives nothing, and the field is empty.

What you get back

Only an expression
It keeps its type. {{steps.step_1.body}} passes the object itself, a number stays a number.
Mixed with text
Each expression becomes text: a string as it is, anything else as JSON. Order {{trigger.body.id}} received.

Warning In a JSON body you write yourself, put an object as the whole value, unquoted: {"order": {{trigger.body}}}. Inside quotes, the first quote in the data breaks the JSON.

JavaScript

Anything that isn’t a plain path runs as JavaScript, with the same data:

js
{{ steps.step_1.body.items.length > 3 ? "big" : "small" }}
{{ $json.body.email.split("@")[1] }}
{{ $ifEmpty(trigger.body.name, "friend") }}
$json
The trigger’s data. $trigger is the same, and $steps is steps.
$('step_1')
A step’s output, by name.
$if(test, a, b)
a when the test is true, else b.
$ifEmpty(value, other)
other when the value is missing or empty.
$now
Now, as a date. $today is the same.

An expression may run for 100 ms and return up to 16 MB. One that throws gives nothing. One that runs too long or uses too much memory fails the step, and says which expression.

Numbers and dates for people

Intl.NumberFormat, Intl.DateTimeFormat and toLocaleString work in expressions and Code steps:

js
{{ new Intl.NumberFormat("de-DE", { style: "currency", currency: "EUR" }).format(1234.5) }}
// 1.234,50 €

They know about 1,100 locales and write them as Node does, with each locale’s own digits and calendar. A locale GoRunner doesn’t have falls back as in Node, to its language, then to en-US: sv-XX is written as sv, and xx as en-US. en-CA is one it has, so it gives 2026-10-26:

js
{{ new Intl.DateTimeFormat("en-CA", { timeZone: "Europe/Berlin", year: "numeric", month: "2-digit", day: "2-digit" }).format(new Date("2026-10-26T02:00:00Z")) }}
// 2026-10-26

From v2026.10.18 to v2026.10.29, only 11 locales were known, and others wrote like their language or en-US: en-CA gave 10/26/2026.

Test data while you build

Before anything has run, the data picker offers each trigger’s and step’s sample, so the names are real. After a test, it offers what the test returned. You can pin a step’s output so test runs reuse it; production always runs the step.