# Queries API

Five analytical query endpoints power the dashboard: segmentation, funnel, retention, flows, and sessions. All are POST /api/query/*, require the admin Bearer key (Authorization: Bearer $API_KEY - superadmin key or a Firebase ID token), and take an optional projectId in the body (defaulting to the caller's oldest project). Dates from and to are YYYY-MM-DD strings.

These are the stable v0 wrapper endpoints every dashboard screen already
speaks. `POST /api/query` runs `trend` and `funnel` analyses through the
newer Query IR pipeline instead and is the forward path,
but is not yet documented here - it takes a free-form IR document rather
than a fixed shape, so it does not fit a parameter table the way these
five do. All five below are subject to the `/api/query/*` analytics rate
limit (default 30 requests / 60s per authenticated user, or per source IP
for the superadmin key).

## Segmentation

POST /api/query/segmentation Time-bucketed event trend, optionally split by a property and filtered.

event string Event name, or the $all\_events sentinel to match every event.

from string (date) YYYY-MM-DD, inclusive.

to string (date) YYYY-MM-DD, inclusive.

unit "hour" | "day" | "week" | "month" Bucket size.

type "total" | "unique" Count every occurrence, or count distinct users.

breakdown string Property key to split the series by; one series per observed value.

filters PropertyFilter\[] Up to 20 property filters, ANDed together.

filters\[].key string Property key to filter on.

filters\[].op "eq" | "neq" | "contains" | "set" | "not\_set" Comparison operator.

filters\[].value string Required for eq/neq/contains; omitted for set/not\_set.

projectId string Defaults to the caller's oldest project.

```bash
curl -X POST https://cohorly-service.velloalabs.com/api/query/segmentation \
  -H "Authorization: Bearer $API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "event": "Page Viewed",
    "from": "2026-07-01",
    "to": "2026-07-31",
    "unit": "day",
    "type": "unique",
    "breakdown": "plan",
    "filters": [{ "key": "path", "op": "contains", "value": "/pricing" }]
  }'
```

```js
await fetch("https://cohorly-service.velloalabs.com/api/query/segmentation", {
  method: "POST",
  headers: {
    Authorization: `Bearer ${API_KEY}`,
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    event: "Page Viewed",
    from: "2026-07-01",
    to: "2026-07-31",
    unit: "day",
    type: "unique",
  }),
});
```

```json
{
  "buckets": ["2026-07-01", "2026-07-02"],
  "series": [
    {
      "name": "Signed Up",
      "data": [
        { "bucket": "2026-07-01", "value": 12 },
        { "bucket": "2026-07-02", "value": 18 }
      ]
    }
  ]
}
```

```json
{ "error": "invalid date range" }
```

```json
{ "error": "unauthorized" }
```

```json
{ "error": "forbidden" }
```

```json
{ "status": 0, "error": "rate limited" }
```

## Funnel

POST /api/query/funnel Measure how many users complete an ordered sequence of steps within a conversion window.

steps string\[] 2 to 10 ordered event names.

from string (date) YYYY-MM-DD, inclusive.

to string (date) YYYY-MM-DD, inclusive.

windowDays integer 30 Max elapsed days from step 0 for a user to still count as converting at a later step (1-366).

breakdown string Property key to split each step's segments by.

filters PropertyFilter\[] Up to 20 property filters, ANDed together (same shape as segmentation).

projectId string Defaults to the caller's oldest project.

```bash
curl -X POST https://cohorly-service.velloalabs.com/api/query/funnel \
  -H "Authorization: Bearer $API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "steps": ["Viewed Pricing", "Signed Up", "Upgraded"],
    "from": "2026-07-01",
    "to": "2026-07-31",
    "windowDays": 14
  }'
```

```js
await fetch("https://cohorly-service.velloalabs.com/api/query/funnel", {
  method: "POST",
  headers: {
    Authorization: `Bearer ${API_KEY}`,
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    steps: ["Viewed Pricing", "Signed Up", "Upgraded"],
    from: "2026-07-01",
    to: "2026-07-31",
    windowDays: 14,
  }),
});
```

```json
[
  {
    "event": "Signed Up",
    "count": 340,
    "conversionFromPrevious": 0.62,
    "conversionFromStart": 0.62,
    "droppedCount": 208,
    "dropoffRate": 0.38,
    "convertedUserIds": ["user-42"],
    "droppedUserIds": ["user-7"],
    "segments": [],
    "meanSecondsToConvert": 145.2,
    "medianSecondsToConvert": 98
  }
]
```

```json
{ "error": "invalid date range" }
```

```json
{ "error": "unauthorized" }
```

```json
{ "error": "forbidden" }
```

```json
{ "status": 0, "error": "rate limited" }
```

## Retention

POST /api/query/retention Track how many users who performed a bornEvent came back to perform a returnEvent in later periods.

bornEvent string Event name, or the $all\_events sentinel.

returnEvent string Event name, or the $all\_events sentinel.

from string (date) YYYY-MM-DD, inclusive.

to string (date) YYYY-MM-DD, inclusive.

unit "day" | "week" week Cohort bucket size.

buckets integer 8 Number of return periods to compute (1-16).

projectId string Defaults to the caller's oldest project.

```bash
curl -X POST https://cohorly-service.velloalabs.com/api/query/retention \
  -H "Authorization: Bearer $API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "bornEvent": "Signed Up",
    "returnEvent": "$all_events",
    "from": "2026-05-01",
    "to": "2026-07-31",
    "unit": "week",
    "buckets": 8
  }'
```

```js
await fetch("https://cohorly-service.velloalabs.com/api/query/retention", {
  method: "POST",
  headers: {
    Authorization: `Bearer ${API_KEY}`,
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    bornEvent: "Signed Up",
    returnEvent: "$all_events",
    from: "2026-05-01",
    to: "2026-07-31",
    unit: "week",
    buckets: 8,
  }),
});
```

```json
[{ "cohort": "2026-07-06", "size": 120, "counts": [120, 54, 40, 31] }]
```

```json
{ "error": "invalid date range" }
```

```json
{ "error": "unauthorized" }
```

```json
{ "error": "forbidden" }
```

```json
{ "status": 0, "error": "rate limited" }
```

Bucket boundaries (day, week, month) are computed in your workspace's time
zone, so daily numbers match what you see in the dashboard. `counts[0]` is
the cohort's own period (same-bucket return); `counts[i]` is bucket `i`
after that.

## Flows

POST /api/query/flows Top user paths before or after an anchor event.

event string Anchor event name - a concrete name, not the $all\_events sentinel.

direction "after" | "before" Walk the path forward or backward from the anchor.

steps integer 3 Path length to walk from the anchor (1-5).

from string (date) YYYY-MM-DD, inclusive.

to string (date) YYYY-MM-DD, inclusive.

limit integer 20 Max number of distinct paths to return (1-100).

projectId string Defaults to the caller's oldest project.

```bash
curl -X POST https://cohorly-service.velloalabs.com/api/query/flows \
  -H "Authorization: Bearer $API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "event": "Signed Up",
    "direction": "after",
    "steps": 3,
    "from": "2026-07-01",
    "to": "2026-07-31",
    "limit": 20
  }'
```

```js
await fetch("https://cohorly-service.velloalabs.com/api/query/flows", {
  method: "POST",
  headers: {
    Authorization: `Bearer ${API_KEY}`,
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    event: "Signed Up",
    direction: "after",
    steps: 3,
    from: "2026-07-01",
    to: "2026-07-31",
    limit: 20,
  }),
});
```

```json
{
  "paths": [{ "path": ["Signed Up", "Viewed Dashboard", "Upgraded"], "count": 88 }],
  "total": 340
}
```

```json
{ "error": "invalid date range" }
```

```json
{ "error": "unauthorized" }
```

```json
{ "error": "forbidden" }
```

```json
{ "status": 0, "error": "rate limited" }
```

## Sessions

POST /api/query/sessions Session counts and average duration over time.

Sessions are computed at query time (30 minute inactivity timeout by
default, `COHORLY_SESSION_TIMEOUT_MS`) and bucketed the same way as
segmentation.

from string (date) YYYY-MM-DD, inclusive.

to string (date) YYYY-MM-DD, inclusive.

unit "hour" | "day" | "week" | "month" Bucket size.

projectId string Defaults to the caller's oldest project.

```bash
curl -X POST https://cohorly-service.velloalabs.com/api/query/sessions \
  -H "Authorization: Bearer $API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "from": "2026-07-01", "to": "2026-07-31", "unit": "day" }'
```

```js
await fetch("https://cohorly-service.velloalabs.com/api/query/sessions", {
  method: "POST",
  headers: {
    Authorization: `Bearer ${API_KEY}`,
    "Content-Type": "application/json",
  },
  body: JSON.stringify({ from: "2026-07-01", to: "2026-07-31", unit: "day" }),
});
```

```json
{ "series": [{ "bucket": "2026-07-01", "sessions": 40, "avgDurationSec": 212.5 }] }
```

```json
{ "error": "invalid date range" }
```

```json
{ "error": "unauthorized" }
```

```json
{ "error": "forbidden" }
```

```json
{ "status": 0, "error": "rate limited" }
```
