Get current step (re-render)
Returns the current capability step without advancing the state machine. Useful for page reloads or re-rendering after a network error.
Returns the current capability step without advancing the state machine. Useful for page reloads or re-rendering after a network error.
Path Parameters
Flow ID returned by POST /flow or the latest POST /flow/{id}/submit.
Used to look up the correct flow state from the encrypted cookie,
which can hold multiple concurrent flows. May change between responses
when a flow pivot or pop occurs — always use the id from the latest response.
Cookie Parameters
Response Body
application/json
application/json
application/json
application/json
curl -X GET "https://example.com/flow/flow_01H8Z" \ --cookie "_zflow=string"{ "id": "flow_01H8Z", "session_id": "string", "session_token": "string", "step": { "name": "login", "texts": { "title_key": "login.title", "description_key": "login.description" }, "fields": [ { "name": "email", "type": "email", "text_key": "login.field.email", "required": true }, { "name": "password", "type": "password", "text_key": "login.field.password", "required": true } ], "actions": [ { "name": "submit", "kind": "submit", "text_key": "login.action.submit", "primary": true }, { "name": "register", "kind": "navigate", "text_key": "login.action.register" }, { "name": "recover", "kind": "navigate", "text_key": "login.action.recover" } ], "gates": { "captcha": { "kind": "captcha", "provider": "altcha", "config": { "algorithm": "SHA-256", "challenge": "abc123", "salt": "xyz789", "max_number": 100000 } } }, "sso_providers": [ { "id": "google-1", "name": "Google", "template": "google" }, { "id": "entra-1", "name": "Microsoft", "template": "entraid" } ] }, "branding": { "layout": "centered", "liquid_template": "string", "logo_url": "http://example.com", "font_url": "http://example.com", "hero_url": "http://example.com" }, "redirect_uri": "http://example.com", "handoff_token": "string", "handoff_token_expires_at": "2019-08-24T14:15:22Z"}{ "code": "string", "message": "string", "details": {}}{ "code": "string", "message": "string", "details": {}}{ "code": "string", "message": "string", "details": {}}Start a new flow POST
Resolves a flow definition based on purpose + audience context and returns the first capability step. Creates a new session implicitly unless `session_id` is provided (for step-up / reauth on an existing session). The response contains an `id` field — the flow handle. Use it as the path parameter for all subsequent `/flow/{id}/submit` and `/flow/{id}/event` calls. The response also sets an encrypted `HttpOnly` cookie (`_zflow`) containing the flow's orchestration state (current step, collected data, history). The server is stateless between requests — all flow state lives in this cookie. The browser sends it automatically on subsequent requests.
Submit step data and advance POST
Submits user input for the current step. The server validates, processes (e.g., verifies a credential), advances the state machine through any invisible steps, and returns the next visible step. The response sets an updated encrypted `HttpOnly` cookie (`_zflow`) with the new flow state. The server is stateless — all orchestration state is carried in this cookie between requests. **Important:** The `id` in the response may differ from the `id` used in the request. This happens when a flow pivots (pushes a new flow onto the stack) or when a stacked flow completes (auto-pops to the parent flow). Always use the `id` from the latest response for the next request. ## Flow completion When `step.type` is `complete`, the flow is terminal. The `step.behavior` field tells the frontend what to do: | `behavior` | Action | |------------- |------------------------------------------------------------| | `redirect` | Navigate to `redirect_uri` (OIDC/SAML auth request done). | | `show` | Render the step as a success screen (e.g., registration). | A `complete` step is only returned when the **entire flow stack** is done. If a stacked flow (e.g., recovery pivoted from login) finishes, the server auto-pops to the parent flow and returns the parent's next step — the frontend never sees a `complete` for intermediate flows.