Expressions

Expressions let you pull data out of triggers, steps, secrets, and run metadata.

Interpolation

Use {{ expression }} inside any string:

"Bearer {{ secrets.STRIPE_KEY }}"
"https://api.example.com/orders/{{ steps.create.response.body.id }}"

A bare {{ }} returns the raw value (map, list, whatever). If you mix it into a longer string, you get a string back.

Path (default)

Dot-paths, plus comparisons:

steps.validate.response.body.total
steps.validate.response.status == 200
status == 200 and total > 100
status in [200, 201, 202]

Operators: ==, !=, >, <, >=, <=, in, and, or, not

JSONPath

Set lang: "jsonpath" when you need a real query:

$.steps.validate.response.body.items[0].sku
$.items[?(@.price > 100)]

Lua

Set lang: "lua" when you need to transform data. Sandboxed, with a 5-second timeout:

acc.total = acc.total + result.amount
return acc

when conditions

when accepts either a bare string or an expression block { "expr": "...", "lang": "..." }.

A bare string dispatches by prefix — anything starting with return runs as Lua, everything else runs as a path expression:

"when": "steps.validate.response.body.valid == true"
"when": "trigger.body.email != null"
"when": "return crypto.hmac('sha256', secrets.KEY, trigger.raw_body) == trigger.headers['x-signature']"

Block form without lang defaults to the path runtime, same as bare strings.

Context

Path Description
trigger.body.* Request body
trigger.headers.* Request headers
steps.<id>.response.status HTTP status
steps.<id>.response.body.* Response body
secrets.<NAME> Tenant secret
run.id Run ID
run.session Run-scoped session token (24h TTL)