# Session replays

> Find recordings by user, traits, events, and dates, then load them in your own dashboard


Use the replay API to find recorded sessions and load their playback data in your own application. These are the same reads used by the Databuddy dashboard.

Send an [API key](/docs/api/authentication) with `read:data` and access to the website in the `x-api-key` header. Keep the key on your server. Replay routes use `https://api.databuddy.cc/replays`, and the website must have session replay enabled.

## Find recordings

`POST /replays/list` returns recording metadata, newest first. Combine user identity, current traits, dates, and behavior in one request:

```bash
curl https://api.databuddy.cc/replays/list \
  -H "x-api-key: $DATABUDDY_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "websiteId": "YOUR_WEBSITE_ID",
    "email": "person@example.test",
    "traits": [
      { "key": "role", "value": "editor" },
      { "key": "region", "value": "eu" }
    ],
    "event": "report_exported",
    "startedAfter": "2026-10-28T00:00:00Z",
    "startedBefore": "2026-10-29T00:00:00Z",
    "limit": 50
  }'
```

Use trait keys, values, and event names that your site actually sends. Omit any filter you do not need. All supplied filters must match.

| Field | Meaning |
| --- | --- |
| `websiteId` | Required website ID. |
| `person` | Case-insensitive partial match on an identified user's email, name, or profile ID. |
| `email` | Exact identified-user email, case-insensitive. |
| `profileId` | The stable user ID supplied with identification. |
| `traits` | Up to 10 `{ "key": "…", "value": "…" }` conditions on the user's current profile. Supply numbers and booleans as strings, such as `"42"` or `"true"`. |
| `startedAfter` | Inclusive recording start timestamp, with a timezone. |
| `startedBefore` | Exclusive recording start timestamp, with a timezone. |
| `event` | A custom event that fired in the recorded session. |
| `segment` | `all` (default), `identified`, `long`, `frustrated`, or `worth_watching`. The last sorts by watch score. |
| `category` | `browsing`, `evaluating`, `signing_up`, `using`, `buying`, `support`, or `other`. |
| `issue` | An unanswered-click issue key returned by `/replays/issues`. |
| `limit` | Number of recordings to return, from 1 to 200; defaults to 50. |

Each `sessions` entry includes `sessionId`, identified-user `profileId`, `email` and `displayName` when available, current `traits` as text values, start and end timestamps in milliseconds, entry page, device, browser, country, custom events, and detected friction. The response also includes segment counts and the available event/category counts for the searched candidates.

Check both coverage flags:

- `hasMore` means the searched candidates contain more matches than `limit`. Increase the limit or narrow your filters.
- `truncated` means the bounded candidate search may have omitted recordings. Narrow your user or date filters before treating the result as exhaustive.

The list currently has no pagination cursor. Recordings are retained for 30 days.

## Load playback data

`POST /replays/events` returns one session's metadata, custom-event timestamps, and short-lived download URLs for its recording chunks:

```bash
curl https://api.databuddy.cc/replays/events \
  -H "x-api-key: $DATABUDDY_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "websiteId": "YOUR_WEBSITE_ID", "sessionId": "SESSION_ID" }'
```

The response contains:

- `session`: the recording's analytics metadata.
- `chunks`: URLs for gzip-compressed rrweb event chunks, in recording order. Fetch and decode these when loading your player.
- `customEvents`: `{ "at": 1793145600000, "name": "report_exported" }` entries, with timestamps in milliseconds.
- `truncated`: whether the recording exceeded the 1,000-chunk playback limit.

Chunk URLs expire after 60 seconds. Request fresh URLs when loading the recording again. You can return the signed URLs from your server to your player without exposing your API key. A session without recording chunks returns `404`.

## Check recording availability

`POST /replays/recorded` accepts `websiteId` and up to 200 `sessionIds`. It returns the IDs with processed recordings, so another page can link to them. Sessions still being recorded or processed may not appear yet. A website with replay disabled returns an empty list after its access checks.

## Find recorded issues

`POST /replays/issues` accepts `websiteId` and groups unanswered clicks from the last week by page and element. Pass an issue's `key` as the `issue` filter in `/replays/list` to find its recordings.

## Rate limits and failures

Replay API calls use the normal [API-key rate limits](/docs/api/rate-limits). Cache list metadata where useful and request playback URLs when a recording is opened. Chunk downloads use the signed storage URLs. Reading an existing recording does not collect another recording.

Missing authentication returns `401`; insufficient scopes or website access returns `403`. Invalid filters return `400`. Disabled replay or unavailable replay storage returns `402` for list, playback, and issue reads. For `429`, wait for `Retry-After` before retrying. See [error handling](/docs/api/errors) for the shared API error format.
