---
title: "Get multi-step conversion funnel"
method: GET
path: "/v0/funnel"
tags: ["Query"]
---

# Get multi-step conversion funnel

`GET /v0/funnel`

## Request

- Base URL: `https://api.formo.so`
- URL: `https://api.formo.so/v0/funnel`
- Auth: HTTP bearer

Multi-step conversion funnel. For an ordered list of step specs, returns 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 (from-previous and from-start, in seconds).

**Closed vs open:** `funnel_type=closed` (default) requires the user to fire the steps in order within `window_seconds`. `funnel_type=open` counts whoever fired step k regardless of order, and adds a `dropped_off_users` column for each step.

**Breakdown:** when `group_by` is set to a column from the breakdown allowlist (`device`, `browser`, `os`, `location`, `referrer`, `ref`, `utm_source`, `utm_medium`, `utm_campaign`, `utm_content`, `utm_term`, `builder_codes`), the response gains a `breakdown` column and is grouped per (step, top-N category + 'Others', up to `limit` which defaults to 5). First-touch attribution is used by default; pass `attribution=last_touch` to bucket by each user's latest value.

**Steps:** the `steps` query param is a JSON-encoded array of 2 to 10 step specs of shape `{type, event, name, filters?: [{field, op, value}]}`. Use `name` (e.g. `"page::0"`) as a unique step id so the same event re-used at different steps can be disambiguated in the response. `op` accepts `eq | neq | in | nin | gt | lt | gte | lte | startsWith | endsWith | contains | notEmpty | isEmpty` (canonical tokens only; the retired long-form spellings are rejected, `notEmpty`/`isEmpty` are value-less existence checks, rejected on the numeric event columns `volume`/`revenue`/`points`). `field` may target a standard event column or a JSON property on `properties`.

## Query parameters

- `date_from` string, date, required
- `date_to` string, date, required
- `steps` string, required
- `window_seconds` integer
- `funnel_type` 'closed' | 'open'
- `group_by` 'device' | 'browser' | 'os' | 'location' | 'referrer' | 'ref' | 'utm_source' | 'utm_medium' | 'utm_campaign' | 'utm_content' | 'utm_term' | 'builder_codes'
- `limit` integer
- `attribution` 'first_touch' | 'last_touch'

## Response `200`

Per-step funnel results

- AnalyticsResponse: 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[]
    - `name` string
    - `type` string
  - `rows` integer
  - `rows_before_limit_at_least` integer
  - `statistics` object

## Other responses

- `400`: Invalid `steps`, `window_seconds`, or other query parameters
- `401`: Invalid API key
- `403`: Insufficient permissions

---

[API](https://skmtc.dev/formo/apis/formo-public-api.md) · [All operations](https://skmtc.dev/formo/apis/formo-public-api/llms.txt) · [OpenAPI document](https://skmtc.dev/formo/apis/formo-public-api/revisions/67ada57df63c?raw)
