A flow is an automation made of steps: read a record, branch on a value, send an email, publish to a channel, call another service, return a response. You build flows visually in the dashboard, and anyone on your team can read and change them without a deploy. Your app starts a flow that has an HTTP trigger by calling it by name.

Run a flow

Your input arrives in the flow as input. The call waits for the flow to finish and returns its response. run and invoke are the same method (Python also accepts run).

What comes back

A flow’s response is whatever its response.return block sends. If the flow has no such block, you get its result wrapped as { "data": … }.
Design flows the way you design a function in code: take one object, return a small object.

Who may run it

The flow’s HTTP trigger has an access rule: public, any signed-in user, a role, and so on. It runs before the first step. A refused call throws AuthenticationError or PermissionError / ForbiddenError. Steps inside the flow run with the authority you configured for the flow, which can be more than the caller has. That is the point: a flow can write to a table the user cannot write to directly, after checking that this specific action is allowed. Keep that in mind when you design the first step: validate who is asking and what they ask for.

Flows with a path are routes

A flow whose HTTP trigger has a path and method (for example POST /orders/{id}/pay) is reached as a route, not through flows.run. flows.run is for flows with a name only.

Call options

The options are listed under Call options: signal, timeoutMs, headers, and idempotent to allow retrying a POST after a network failure when running twice is harmless.

Waiting for a long flow

A call waits for the flow, and a browser request should not wait minutes. For anything slow, split the work:
  1. The flow you call starts the work in the background (a queued job) and returns at once with an id.
  2. The background work finishes later and records its result, or publishes to a channel.
  3. Your app watches the record or the channel.
See patterns.

Errors from inside a flow

A flow can stop and return an error on purpose, with a status and a code. Your app sees it as the matching error type, with the code available as error.code and any details in error.details.
Agree the codes with whoever builds the flow and treat them as part of the API.

Call options

Every call accepts options as a last argument.

Retries and double-running

The client retries safe failures by itself: rate limits, 502, 503, 504, and network errors on requests that are safe to repeat. A POST is not repeated after a network failure unless you set idempotent: true, because the first attempt may have succeeded. If your flow charges a card or sends an email, make it idempotent on the server (accept a unique key and return the earlier result for a repeat) before you set the flag.

Build and test a flow in Studio

Flows are built in Logic → Flows. Click a flow (or New flow) to open the editor:
  • Blocks (search with Search blocks…) are the steps you drag onto the canvas. Arrange tidies them top to bottom.
  • Click a block to set its Label and configuration. The first block is the trigger (HTTP, event, schedule…).
  • Validate checks the flow’s graph and lists problems node by node.
  • Test run runs it without a caller: fill Input (JSON), optionally Run as (an auth context, to see what a particular person would get), pick Start from a trigger, and set a Timeout (seconds). The Result, Trace (step by step, with each block’s input and output) and Logs appear below.
  • Save stores it; Run saved flow runs the stored version. Last run shows the most recent real run.
Test with the same input your app will send, then call it from your app with flows.run against development.

Routes

Flows with their own URLs.

Patterns

Real-world designs.