Skip to main content
GET
/
v0
/
flow
Get session-scoped user-flow transitions (Sankey)
curl --request GET \
  --url https://api.formo.so/v0/flow \
  --header 'Authorization: Bearer <token>'
{
  "meta": [
    {
      "name": "step",
      "type": "UInt32"
    },
    {
      "name": "source",
      "type": "String"
    },
    {
      "name": "target",
      "type": "String"
    },
    {
      "name": "transitions",
      "type": "UInt64"
    },
    {
      "name": "percentage",
      "type": "Float64"
    }
  ],
  "data": [
    {
      "step": 1,
      "source": "/",
      "target": "/swap",
      "transitions": 412,
      "percentage": 47.83
    },
    {
      "step": 1,
      "source": "/",
      "target": "/earn",
      "transitions": 248,
      "percentage": 28.79
    },
    {
      "step": 2,
      "source": "/swap",
      "target": "connect",
      "transitions": 198,
      "percentage": 38.6
    },
    {
      "step": 3,
      "source": "connect",
      "target": "swap__END_MATCH__",
      "transitions": 112,
      "percentage": 56.57
    }
  ],
  "rows": 4,
  "rows_before_limit_at_least": 4
}

Documentation Index

Fetch the complete documentation index at: https://docs.formo.so/llms.txt

Use this file to discover all available pages before exploring further.

Returns the same Sankey transitions the dashboard renders on the Flows chart. For each session that fires the start step inside [dateFrom, dateTo], the pipe rebuilds the ordered sequence of subsequent events within the conversion window, normalises them into flow-node labels, and emits one row per (step, source, target) transition with counts and per-step percentages. When end_step is set, only sessions that reached the end event within the conversion window are kept (converter-only mode), and the matched event is suffixed with __END_MATCH__.

Defining start and end steps

Both start_step and end_step are JSON-encoded objects of shape {type, event, resolved_event, filters?: [...], status_type?, status_value?}:
  • type - event type (event, track, transaction, signature, decoded_log).
  • event - the event name.
  • resolved_event - the value matched against the events table. Use the sentinel "__ALL_PAGE_VIEWS__" to match any page view, or the page path / event name otherwise.
  • filters - optional [{operand, operator, value, values?}]. Use values for the in / notIn operators.
Pass global_filters as a JSON-encoded array to apply additional {operand, operator, value, values?} constraints to both the start-session scan and the relevant-events scan.

Conversion window and depth

window_seconds (default 1209600, i.e. 14 days) bounds how long after the start event the path is allowed to extend. max_steps (default 4, clamped to 2..10) caps the Sankey depth.

Example

curl -G "https://api.formo.so/v0/flow" \
  -H "Authorization: Bearer $FORMO_API_KEY" \
  --data-urlencode "dateFrom=2026-04-01" \
  --data-urlencode "dateTo=2026-04-30" \
  --data-urlencode "window_seconds=1209600" \
  --data-urlencode "max_steps=4" \
  --data-urlencode 'start_step={"type":"event","event":"page","resolved_event":"__ALL_PAGE_VIEWS__","filters":[]}' \
  --data-urlencode 'end_step={"type":"track","event":"swap","resolved_event":"swap","filters":[]}'

Authorizations

Authorization
string
header
required

Workspace API key (e.g. formo_xxx). Create one in the Formo dashboard under Team Settings > API Keys.

Query Parameters

dateFrom
string<date>
required

Inclusive ISO date for the start of the start-event window (YYYY-MM-DD).

dateTo
string<date>
required

Inclusive ISO date for the end of the start-event window (YYYY-MM-DD).

start_step
string
required

JSON-encoded start-step spec of shape {type, event, resolved_event, filters?: [...], status_type?, status_value?}. Use "resolved_event":"__ALL_PAGE_VIEWS__" to match any page view; pass a page path for a specific landing page; or pass an event name for track/decoded_log start events. filters use {operand, operator, value, values?} (use values for in/notIn).

Filter operators: equals, notEquals, in, notIn, gt, lt, gte, lte, startsWith, endsWith, includes. Standard columns (device, browser, os, location, referrer, utm_*, page_path, etc.) are read directly; everything else is read from properties via JSONExtractString (or JSONExtractFloat for numeric comparators).

end_step
string

Optional JSON-encoded end-step spec, same shape as start_step. When present, paths are truncated at the first end-event match (suffixed __END_MATCH__) and only converting sessions are returned.

global_filters
string

Optional JSON-encoded array of {operand, operator, value, values?} filters applied to both the start-session scan and the relevant-events scan. Useful for restricting the entire flow to a specific cohort (e.g. desktop visitors, a UTM source, a wallet provider).

window_seconds
integer
default:1209600

Conversion window length in seconds. Defaults to 1,209,600 (14 days). Mirrors the window_seconds parameter on /v0/funnel.

Required range: x >= 1
max_steps
integer
default:4

Maximum number of transitions per session (Sankey depth). Clamped to 2..10.

Required range: 2 <= x <= 10

Response

Per-step Sankey transitions

Analytics endpoint response. The data array contains the rows; the exact row shape depends on the endpoint. meta carries column type information for rendering, rows is the row count, and statistics holds query timing metadata.

data
object[]
meta
object[]
rows
integer
rows_before_limit_at_least
integer
statistics
object