Skip to main content
Account variables let you stop hard-coding the same configuration values into every Flow Definition. Define a value once — a department’s email address, a campaign’s hours of operation, a company-wide sender name — reference it from any flow with {{ account.<set>.<key> }}, and change it later by updating one place. The next execution picks up the new value with no definition edits. Account variables carry plain configuration only. They are not for secrets — credentials belong in Connections, which handlers consume by reference so secret values never enter a flow’s data. See Variables vs. Connections below.

Two scopes: var and account

There are two variable scopes, addressed by two different expression roots. They solve different problems: A flow-scope var is declared inline on the definition and resolves to its literal value every run. An account-scope account value is stored once at the account level and resolved fresh at the start of each execution, so editing it changes what the next run sees.
Rule of thumb: if a value varies per run, make it a definition input. If it varies per department, per campaign, or per environment — but is stable within a run — make it an account variable. If it’s a secret, make it a Connection.

The model: sets and versions

Account variables use one model — sets with versions — that covers both the “many variants” case and the flat “one value everywhere” case.
  • A Variable Set is a named, typed schema your account owns. It declares keys, each with a ValueType (string, number, boolean, object, array, or datetime) and an optional default value. An account can hold many sets — for example department, company, and campaign — each modeling a different kind of configurable thing.
  • A Version is a named instance of a set’s schema — concrete values for its keys. The department set might have versions sales, support, and billing. A version is validated against the set’s schema when you save it: every key that has no default must be supplied, and every value must match its key’s declared type.
Expressions always address values by set name, never by version name: {{ account.department.email }}. Which version fills in the value is chosen separately (see Selecting a version). A set with a single version is the flat case — one support_email everywhere — with no separate concept to learn.
Here support omits hours, so it resolves to the key default "9-5 ET". Resolution order is always version value → key default. Adding a new key with a default to a set with a dozen versions is a single edit.

Selecting a version

Which version supplies the values for a set is chosen in two places, per set and independently:
1

Definition default (variable_bindings)

A definition declares a default version for each set its expressions reference, via its variable_bindings map (set_name → version_name). For example {"department": "sales"} binds the department set to its sales version for that flow.
2

Trigger override (variable_overrides)

The manual trigger (POST /definitions/{id}/trigger) may override the version per set with a variable_overrides map on the trigger request. {"department": "support"} runs that one execution with the support version instead of the bound default. Selection is per-set and independent: you can override department while leaving campaign on its default. Non-manual triggers — schedule, webhook, and event — use the definition’s bound defaults.
Values are snapshotted once at the start of each execution. A mid-run edit never half-applies within a single run, and every execution takes its own snapshot — so the next run always reflects the current stored values.

Fail-early validation

Account variables are validated up front so a flow never starts half-resolvable:
  • At definition save (D-08): every {{ account.<set>.<key> }} an expression references must resolve — the set must exist, the key must exist, and the definition must bind a default version for that set. Otherwise the create/update is rejected with 422.
  • At trigger time: a variable_overrides entry naming a version that doesn’t exist is rejected with 400 before any workflow starts.

Referential safety (409 guard)

Adding sets, keys, and versions is always free. But removing or renaming something a live definition references is blocked so you can’t silently break a flow. Deleting or renaming a set, deleting or renaming a version a definition binds, or removing/renaming a key a definition’s expressions use returns 409 Conflict with the referencing definition IDs:
Update or delete the referencing definitions first, then retry.

Managing account variables

All endpoints operate only on your organization’s variable store. Reads require authentication; every mutating endpoint requires an admin-role caller. Set, key, and version names must be expression-path-safe — they must match ^[a-zA-Z_][a-zA-Z0-9_]*$ (a leading letter or underscore, then letters, digits, or underscores) so a name can never contain a . or break the account.<set>.<key> path. Storage caps apply: up to 200 sets per account, 100 keys and 100 versions per set, and 16 KB per individual value. Creating a set:

Variables vs. Connections

Account-variable values are configuration, and by design they flow into step payloads, execution events, and logs — that is what makes them useful to reference from a flow. That same visibility is exactly why they must never hold a secret.
If it’s a secret, it’s a Connection. Account variables have no secret flag and never will — their values appear in payloads, events, and logs by design. Store any credential in a Connection, where handlers consume it by reference and the secret never enters the expression context.

Next steps

Expressions

The {{ }} language and every context root, including account and var.

Connections

Where credentials belong — referenced, never embedded.