Skip to content

Data & references

A flow's nodes share one running scratchpad — the refs object. Nodes write named values into it, and later nodes read those values back with dotted paths and ${...} placeholders. This page explains exactly how that works.

The refs object

Think of refs as the flow's memory while it runs. It's a set of named buckets, and each bucket is itself a small object of fields:

refs = {
  start:    { email: "sam@acme.com", amount: 42 },   // the request inputs
  response: { status: 200, ok: true, body: {...} },  // an HTTP node's output
  error:    { message: "...", nodeId: "..." }         // set when a node fails
}

When the flow is triggered, the request's inputs (path, query, headers, and JSON body — see Data & references for triggers) are placed in a bucket named after your Start node. A Start named "Start" gives you start; a Start named "New order" gives you new-order (names are lower-cased and hyphenated).

How a node names its output

Every working node writes one bucket into refs. The bucket's name comes from a field in the node's config — resultVar on most nodes, var on Set and Template — and each has a sensible default:

NodeConfig fieldDefault nameShape of the bucket
HTTPresultVarresponse{ status, ok, body }
MongoDBresultVarresultthe document (or { value })
EmailresultVaremail{ sent, reason }
Setvarvaluethe copied/literal value
Templatevartext{ value: "<rendered text>" }
ForEachitemVaritemthe current element each pass

NOTE

A bucket is always an object. If a node produces a plain value (a number, a string, an array), it's wrapped as { value: ... } — so you read it as response.value, not response. Objects are stored as-is.

Referencing upstream values

There are two ways to read from refs, and which one you use depends on the field.

Dotted paths (bucket.field) — used by fields that take a reference directly, such as a Set node's source, a ForEach collection, or a Switch source. The first segment is the bucket name, the rest walks into it:

start.email          → the email from the request
response.body.id     → the id inside an HTTP response body
order.items          → an array to loop over with ForEach

${bucket.field} placeholders — used inside free text such as a Template body or an Email subject. Each placeholder is replaced with the referenced value (objects and arrays are serialised to JSON):

Hi ${start.name}, your order ${order.id} is confirmed.

Unknown paths resolve to an empty string rather than erroring, so a typo blanks out instead of crashing the run.

Environment and secret placeholders

Two special namespaces resolve from outside the flow, and they work in any text field:

  • ${env.NAME} — a server environment variable, read from process.env.
  • ${secrets.NAME} — a value from your workspace's encrypted secrets vault.
Authorization: Bearer ${secrets.STRIPE_KEY}
Base URL: ${env.API_BASE_URL}

Names must be uppercase letters, digits, and underscores.

WARNING

Secrets are fail-closed. An unresolved ${secrets.MISSING} becomes an empty string — it never falls back to an environment variable — so a missing secret can't accidentally leak an unrelated env var into a request.

Order of resolution

In a text field, resolution happens in a defined order:

${env.X} and ${secrets.X} are substituted first, then the remaining ${bucket.field} placeholders are read from refs. This is why a secret can't be overwritten by a same-named ref, and why you can safely mix both in one string.

See also

FlowRunner — the no-code platform for small businesses.