# Report a conversion funnel over events

`POST /v1/reports/funnel`

Requires an API key with the `reports:read` scope. [About keys and scopes](/docs/api/authentication)

How many contacts did each event in order. A contact enters with the first step's earliest event in the window (calendar days in the workspace timezone, default the last 30), and reaches a later step with an event after the previous step's, within `withinDays` of entering. Each contact counts once per step, however many times they repeat it. Events past retention are no longer held.

## Request body

- `startDate` (string, optional, date) — First day, inclusive, in the workspace timezone. Give with `endDate`.
- `endDate` (string, optional, date) — Last day, inclusive, no later than today. Give with `startDate`; a window is at most 366 days. Omit both for the last 30 days.
- `steps` (object[], required, at least 2 items, at most 5 items) — The events, in order.
  - `eventName` (string, required, 1–128 characters) — The event that completes the step.
  - `where` (object[], optional, at least 1 item, at most 5 items) — Every condition must hold for an event to count as this step.
    - `property` (string, required, 1–64 characters) — The event property key.
    - `operator` (string, required, one of `equals`, `notEquals`, `gt`, `gte`, `lt`, `lte`)
    - `value` (string | number | boolean, required)
- `withinDays` (integer, optional, min 1, max 90, default `7`) — How long after the first step a contact has to finish the rest.

## Returns

Returns `200 OK` with a `FunnelReport` in `data`. Otherwise returns an error; [Errors](/docs/api/errors) lists every code and which to retry.

- `timezone` (string, required) — The workspace timezone the dates are calendar days in.
- `startDate` (string, required, date) — First day of the window (inclusive).
- `endDate` (string, required, date) — Last day of the window (inclusive).
- `withinDays` (integer, required, min -9007199254740991, max 9007199254740991) — The window each contact had to finish in.
- `steps` (object[], required)
  - `eventName` (string, required)
  - `contacts` (integer, required, min 0, max 9007199254740991) — Contacts who reached this step, in order, within `withinDays` of the first.
  - `conversionRate` (number | null, required, min 0) — Fraction of those who started; null when nobody did.
  - `stepRate` (number | null, required, min 0) — Fraction of those who reached the step before; null for the first, or when nobody did.
  - `dropOff` (integer, required, min 0, max 9007199254740991) — Contacts who reached the step before but not this one; 0 for the first.

## Example

```bash
curl -X POST https://api.kirora.io/v1/reports/funnel \
  -H "Authorization: Bearer $KIRORA_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "steps": [
      {
        "eventName": "Order Completed"
      }
    ]
  }'
```

Response `200`:

```json
{
  "data": {
    "timezone": "Europe/London",
    "startDate": "2030-03-14",
    "endDate": "2030-03-14",
    "withinDays": -9007199254740991,
    "steps": [
      {
        "eventName": "Order Completed",
        "contacts": 0,
        "conversionRate": 0,
        "stepRate": 0,
        "dropOff": 0
      }
    ]
  }
}
```
