Skip to main content
GET
/
v0
/
funnel
Get multi-step conversion funnel
curl --request GET \
  --url https://api.formo.so/v0/funnel \
  --header 'Authorization: Bearer <token>'
{
  "meta": [
    {
      "name": "step",
      "type": "UInt64"
    },
    {
      "name": "event",
      "type": "String"
    },
    {
      "name": "users",
      "type": "UInt64"
    },
    {
      "name": "total",
      "type": "UInt64"
    },
    {
      "name": "conversion_from_start",
      "type": "Nullable(Float64)"
    },
    {
      "name": "conversion_from_previous",
      "type": "Nullable(Float64)"
    },
    {
      "name": "dropoff_from_previous",
      "type": "Nullable(Float64)"
    },
    {
      "name": "median_seconds_from_previous",
      "type": "Nullable(Float64)"
    },
    {
      "name": "median_seconds_from_start",
      "type": "Nullable(Float64)"
    }
  ],
  "data": [
    {
      "step": 1,
      "event": "page::0",
      "users": 1240,
      "total": 1240,
      "conversion_from_start": 1,
      "conversion_from_previous": null,
      "dropoff_from_previous": null,
      "median_seconds_from_previous": null,
      "median_seconds_from_start": null
    },
    {
      "step": 2,
      "event": "connect::1",
      "users": 482,
      "total": 482,
      "conversion_from_start": 0.3887,
      "conversion_from_previous": 0.3887,
      "dropoff_from_previous": 0.6113,
      "median_seconds_from_previous": 38,
      "median_seconds_from_start": 38
    },
    {
      "step": 3,
      "event": "swap::2",
      "users": 187,
      "total": 187,
      "conversion_from_start": 0.1508,
      "conversion_from_previous": 0.388,
      "dropoff_from_previous": 0.612,
      "median_seconds_from_previous": 124,
      "median_seconds_from_start": 162
    }
  ],
  "rows": 3,
  "rows_before_limit_at_least": 3
}

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 funnel data the dashboard renders on the Funnels page. For an ordered list of step specs, you get one row per step with the unique-user count, conversion ratios against step 1 and the previous step, drop-off ratio, and median time-to-convert. Use funnel_type=closed (default) for ordered, in-window conversions (the default that powers the dashboard) or funnel_type=open to count whoever fired step k regardless of order - open mode also returns a dropped_off_users column. Set breakdown to a dimension (device, browser, os, location, referrer, or any UTM column) to group each step by first-touch attribution; breakdown_top_n controls how many categories are kept before bucketing the rest as Others.

Defining steps

The steps query parameter is a JSON-encoded array of 2–10 step specs. Each step is {type, event, name, filters?: [...]}:
  • type - event type (event for page views, track for custom events, transaction, signature, decoded_log).
  • event - the event name to match.
  • name - a unique step id. Use <event>::<index> (e.g. "connect::1") so the same event re-used at multiple steps can be told apart in the response.
  • filters - optional [{operand, operator, value}].
    • Operators:
      • equals
      • notEquals
      • in
      • notIn
      • gt
      • lt
      • gte
      • lte
      • startsWith
      • endsWith
      • includes
    • operand may target a standard event column or a JSON property on properties.

Example

curl -G "https://api.formo.so/v0/funnel" \
  -H "Authorization: Bearer $FORMO_API_KEY" \
  --data-urlencode "dateFrom=2026-04-01" \
  --data-urlencode "dateTo=2026-04-30" \
  --data-urlencode "window_seconds=86400" \
  --data-urlencode 'steps=[
    {"type":"event","event":"page","name":"page::0","filters":[]},
    {"type":"track","event":"connect","name":"connect::1","filters":[]},
    {"type":"track","event":"swap","name":"swap::2","filters":[{"operand":"chain","operator":"equals","value":"ethereum"}]}
  ]'

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 funnel window (YYYY-MM-DD). The events scan extends past dateTo by window_seconds so a user who fires step 1 just before dateTo can still complete the funnel inside their conversion window.

dateTo
string<date>
required

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

steps
string
required

JSON-encoded array of 2-10 step specs. Each step is {type, event, name, filters?: [{operand, operator, value}]}. type is the event type (e.g. event for page views, track for custom events, transaction, signature, decoded_log). event is the event name. name is the unique step id (use "<event>::<index>" to disambiguate repeated events).

Filter operators: equals, notEquals, in, notIn, gt, lt, gte, lte, startsWith, endsWith, includes. For in/notIn, pass the values as a |-separated string in value (e.g. "ethereum|polygon|base").

Standard columns (rendered via direct column access): origin, device, browser, os, location, referrer, direct, ref, utm_source, utm_medium, utm_campaign, utm_content, utm_term, builder_codes, version, locale, timezone, page_path. Anything else is treated as a JSON property and read from properties via JSONExtractString (or JSONExtractFloat for numeric comparators).

window_seconds
integer
required

Conversion window length in seconds. For closed funnels this is the windowFunnel cap; for both variants the events scan is extended by this amount past dateTo.

Required range: x >= 1
funnel_type
enum<string>
default:closed

closed (default) - ordered, in-window via windowFunnel. open - unordered per-step minIf; emits an extra dropped_off_users column.

Available options:
closed,
open
breakdown
enum<string>

Optional dimension to break each step down by (first-touch attribution). When set, the response gains a breakdown column.

Available options:
device,
browser,
os,
location,
referrer,
utm_source,
utm_medium,
utm_campaign,
utm_content,
utm_term
breakdown_top_n
integer
default:8

Top-N breakdown categories to keep (by user count). Remaining categories are bucketed as Others. Defaults to 8.

Required range: x >= 1

Response

Per-step funnel results

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