Four words show up everywhere in the Flows editor — Flow, Stage, Block, Action. Once you see how they nest, everything else slots into place.
The four words
Section titled “The four words”- Flow — the ordered set of steps for one authentication event. Your tenant has a Login flow, a Registration flow, a Password Reset flow, and so on. Each Flow runs end-to-end every time that event happens.
- Stage — a labelled section inside a Flow. The Login flow has stages like Pre-Login, Post-Auth, Post-Login. Stages give you a place to insert your own logic without rewriting the platform's steps.
- Block — one step inside a Stage. Blocks are the LEGO pieces — Password Check, MFA, Risk Evaluate, Issue Session, Run Custom Action, and so on. The platform ships ~46 blocks; you compose them.
- Action — JavaScript you write that runs inside a Run Custom Action block. This is where you put logic the built-in blocks don't cover.
Put together: a Flow contains Stages, a Stage contains Blocks, and a Block (specifically the Run Custom Action block) can contain one of your Actions.
How a Flow runs
Section titled “How a Flow runs”The platform walks the Flow top to bottom, stage by stage, block by block. Each block reads from a shared state map, does its job, and writes its outputs back. The next block reads what was written and so on.
If any block returns deny or hits an unrecoverable error, the Flow halts. Otherwise it runs to a terminal block — Issue Session on a successful login, Allow on a permitted operation, or Deny if a policy rejected the request.
A simplified Login flow:
Login flow ├─ Stage: Pre-Login │ ├─ Block: Identity Lookup │ └─ Block: Password Check ├─ Stage: Post-Auth │ ├─ Block: Risk Evaluate │ ├─ Block: Decision (route on risk) │ ├─ Block: MFA (only if the decision routed here) │ └─ Block: Run Custom Action — "tag-corporate-vs-self-serve" └─ Stage: Post-Login ├─ Block: Run Custom Action — "welcome-new-user" └─ Block: Issue SessionThree stages. Six blocks. Two custom actions slot into Run Custom Action containers.
Block vs Action — which do I reach for?
Section titled “Block vs Action — which do I reach for?”A Block is a built-in capability. The platform owns its code, audits it, and stays accountable for it. You configure it through form fields in the editor.
An Action is JavaScript you author. You write a few lines, hit save, and your code runs server-side inside a sandbox the platform manages. Actions are how you handle anything the built-in blocks don't cover — domain allowlists, tagging users by company, calling your own webhook, injecting custom claims, denying disposable email signups.
Rule of thumb: if a Block does what you need, use the Block. If not, drop in a Run Custom Action block and write an Action. Don't write JavaScript for things blocks already handle.
Flow types
Section titled “Flow types”The platform ships system Flows for the events that happen on every tenant:
- Login — verifying a returning user. Lifts the session to AAL1 (and AAL2 if MFA verified).
- Registration — creating a new account.
- Password Reset — emailing a recovery link and accepting a new password.
- MFA Enrollment — adding a second factor to an existing account.
- MFA Step-up — re-verifying a factor for a sensitive operation.
- Logout — invalidating sessions.
Each system Flow has its own default stages and a sensible default block layout. You edit the layout from Flows → pick a flow → Edit.
State — event, step, session
Section titled “State — event, step, session”Three top-level state namespaces. You'll see them every time you pop open the {} picker in the editor.
event.*— everything the platform knew when this Flow started, plus what it's learned since. The user's email and ID; the application calling in; the request's IP, country, user-agent, VPN/Tor flags; the transaction's OAuth scope and locale. Read-only.step.<block-name>.*— outputs of an earlier block in the same Flow.step.password-check.verifiedis whether Password Check passed;step.fraud-signal.body.scoreis the score your webhook block returned. Read-only.session.*— the session that gets minted at a terminal block. Read it afterIssue Sessionruns; not before.
Phase 2 will add secrets.* for outbound API keys. Today, secrets in webhooks go in your block config (and pipe through the {} picker the same way).
The {} picker
Section titled “The {} picker”Click the curly-braces icon next to any text field — URL, header, body, or a Decision block's when expression — and the picker opens. It groups everything you can reference:
- Event context — 50-plus paths under
event.*, grouped by category (user, request, transaction, client, tenant, authentication). - Step outputs — fields from each upstream block, keyed by the block's label.
- Session — fields available after the terminal block runs (grey until then).
The picker is the discovery surface. The reference pages below are the contract.
Where to go next
Section titled “Where to go next”- Building your first Flow — When to reach for Flows explains the value framing, then Test and publish walks the editor end-to-end.
- Picking a Block — Built-in blocks reference groups all 46 by job and links to per-category detail pages.
- Writing an Action — Custom actions overview explains the sandbox, then Your first action is a 10-minute end-to-end tutorial.
- Solving a specific problem — Recipes is a catalogue of finished Flows for common goals: step-up MFA on risk, block disposable emails, sync new users to a CRM, and more.