# List user streak logs

List streak history entries for one trader or your whole community, newest first, one page at a time.

- Endpoint: `GET https://api.returning.ai/v1/streak-logs`
- Section: Gamification / Streaks and mini games
- Authentication: `Authorization: Bearer <API_KEY>` (Community API key)
- Permission: `getStreakLogs` (Shown in the dashboard as "Get Streak Logs")
- Retries: Read-only; exact retries are safe
- Guide: hand-written
- Verified: live, 2026-09-27
- Last updated: 26 Sep 2026
- Web page: https://docs.returning.ai/api-reference/gamification-streaks-and-mini-games/list-user-streak-logs

## When to use this

- A trader says their streak reset, and support needs to see when it happened and what they missed.
- Copy streak activity into your CRM or data warehouse, one day at a time.
- Find which traders completed or broke a streak on a given day.

**Instead:** Use [Get mini-game and streak state](https://docs.returning.ai/api-reference/gamification-streaks-and-mini-games/get-mini-game-and-streak-state.md) instead to read a trader's streak counts and spins right now.

## Authentication

- Header: `Authorization: Bearer <API_KEY>`
- Permission: `getStreakLogs`

Use a Community API key with `getStreakLogs`, shown in the dashboard as Get Streak Logs, and keep it on your server. The key decides the community: you only see entries from your own community, and `user` only matches traders in it. Personal API keys are rejected with `401`.

## Behaviour

This read changes nothing. Every action that counts toward one of your streaks adds an entry, even when the count doesn't move, so an active trader can have many entries a day. A reset is dated at the end of the period the trader missed, not when it was recorded. Admin and bulk edits show `streak_activity` `0` with the new count in `total_streak`; the `unchanged` filter doesn't return them, and no `streak_action` value selects them.

Filters combine, and every date and time is UTC. `date[...]` takes whole days as `DD/MM/YYYY`. `time[...]` compares the time of day on every date, so `time[gte]=22:00&time[lte]=02:00` matches nothing. A date that doesn't exist, such as `31/02/2026`, isn't rejected; it may be ignored or moved to a nearby day, so check dates before you send them. Brackets can be sent as they are or encoded as `%5B` and `%5D`; with curl, add `--globoff` or encode them.

Entries have no ID, and new ones push older ones down while you page. To copy history, page through one finished day at a time, sorted by `date`. A reset can be written some time after the period it closes, with that earlier date, so read a recent day again before you treat it as final.

## Request

### Query parameters

| Name | Type | Required | Description |
| --- | --- | --- | --- |
| `user` | `string` | No | The trader's email or platform user ID. Only traders in your community match, and emails ignore case. Omit it, or send it empty, to list entries for every trader. (Email or platform user ID) |
| `streak_name` | `string` | No | Only entries for streaks whose name contains this text, ignoring case. A name no streak contains returns an empty list. Keep to letters, digits and spaces: characters such as `(`, `[` or `*` are read as a pattern and can match more than you expect. (Text) |
| `streak_action` | `string` | No | Only entries caused by this action: `Daily Visit`, `Total XP`, `Total Coins`, `Messages Sent`, `Replies Sent`, `Reactions Sent`, `Delete Message`, `Delete Reply`, `Removed Reaction`, `Timeframe Expired` (streak resets), or the name of one of your custom user fields. Not case-sensitive. (Action name) |
| `streak_activity` | `string` | No | Only entries with this change: `increase` (the count went up), `decrease` (it went down), `unchanged` (progress that didn't move the count) or `streak broken` (reset to 0). (`increase`, `decrease`, `unchanged` or `streak broken`) |
| `date[gte]` | `string` | No | Only entries on or after this day, in UTC. (`DD/MM/YYYY`) |
| `date[lte]` | `string` | No | Only entries on or before this day, in UTC. The whole day is included. (`DD/MM/YYYY`) |
| `date[gt]` | `string` | No | Only entries after this day, in UTC. (`DD/MM/YYYY`) |
| `date[lt]` | `string` | No | Only entries before this day, in UTC. (`DD/MM/YYYY`) |
| `time[gte]` | `string` | No | Only entries at or after this time of day, in UTC, on any date. (`HH:MM`, 24-hour) |
| `time[lte]` | `string` | No | Only entries at or before this minute of the day, in UTC, on any date. (`HH:MM`, 24-hour) |
| `time[gt]` | `string` | No | Only entries after this minute of the day, in UTC. (`HH:MM`, 24-hour) |
| `time[lt]` | `string` | No | Only entries before this time of day, in UTC. (`HH:MM`, 24-hour) |
| `sortBy` | `string` | No | What to sort by. `date` is the default. `time` sorts by time of day only, ignoring the date. `streak_name` groups entries by streak; it doesn't sort names alphabetically. (`date`, `time`, `total_streak`, `streak_activity` or `streak_name`) |
| `sortOrder` | `string` | No | Sort direction. `desc`, the default, puts the newest or highest first. (`desc` or `asc`) |
| `page` | `number` | No | Page number, starting at 1. (Whole number, 1 or more; default 1) |
| `limit` | `number` | No | Entries per page. Omit to use 100. (Default 100; max 100) |

### Headers

| Name | Type | Required | Description |
| --- | --- | --- | --- |
| `Authorization` | `string` | Yes | Community API key with `getStreakLogs`. (`Bearer <API_KEY>`) |

### Example request

```bash
curl --request GET \
  --url 'https://api.returning.ai/v1/streak-logs?user=trader@example.com&limit=20' \
  --header 'Authorization: Bearer <API_KEY>'
```

## Response

A `200` returns the page in `data.data` and the totals in `data.pagination`. The body has no `message` or `code`; branch on the HTTP status. An empty `data.data` for a trader in your community means nothing matched. Unlike Get mini-game and streak state, the `user` lookup here is limited to your community: an email or ID from outside it returns `404`, never another community's history.

### Response fields

| Field | Type | Presence | Description |
| --- | --- | --- | --- |
| `status` | `string` | always | Result of the request. (`success`) |
| `data` | `object` | always | The page of entries and the paging totals. |
| `data.success` | `boolean` | always | `true` on every `200`. |
| `data.pagination` | `object` | always | Paging totals for everything that matches your filters. |
| `data.pagination.total` | `integer` | - | Entries that match, across all pages. |
| `data.pagination.currentPage` | `integer` | - | The page you asked for. |
| `data.pagination.totalPages` | `integer` | - | Pages at this `limit`. `0` when nothing matches. |
| `data.pagination.hasNextPage` | `boolean` | - | `true` when a later page has entries. |
| `data.pagination.hasPrevPage` | `boolean` | - | `true` when `page` is above 1. |
| `data.data` | `object[]` | always | Entries on this page, newest first unless you set `sortBy`. Empty when nothing matches. |
| `data.data.user` | `object` | - | The trader the entry belongs to. |
| `data.data.user.id` | `string` | - | The trader's platform user ID, as a string. |
| `data.data.user.email` | `string` | - | The trader's email. Empty when the account can't be found. |
| `data.data.streak_action` | `string` | - | What caused the entry, such as `Daily Visit`, `Sent Message: 3/5`, `Timeframe expired` for a reset, `Updated by Admin`, or the name of a bulk update. Shows a short action key, such as `messages`, when no description was recorded. |
| `data.data.action_details` | `string` | - | More detail, such as `Visited the community`, the text of the message that counted, or `Action not cleared: Daily Visit` for a reset. Can hold the trader's own message text, so treat it as personal data. Empty when there is none. |
| `data.data.streak_name` | `string` | - | The streak's name as set up in your community, or `Deleted Streak` if the streak was removed. |
| `data.data.streak_activity` | `number or string` | - | How the count changed: `1` up, `-1` down (a counted action was undone, such as a deleted message), `0` no change, or the string `streak broken` when the count reset to 0. Admin and bulk edits also show `0`. |
| `data.data.total_streak` | `integer` | - | The trader's count for this streak after this entry. |
| `data.data.date` | `string` | - | Day of the entry in UTC, as `DD/MM/YYYY`. |
| `data.data.time` | `string` | - | Time of the entry in UTC, as `HH:MM`. |

### Example response (200)

```json
{
  "status": "success",
  "data": {
    "success": true,
    "pagination": {
      "total": 2,
      "currentPage": 1,
      "totalPages": 1,
      "hasNextPage": false,
      "hasPrevPage": false
    },
    "data": [
      {
        "user": {
          "id": "3247779",
          "email": "trader@example.com"
        },
        "streak_action": "Daily Visit",
        "action_details": "Visited the community",
        "streak_name": "Login Streak",
        "streak_activity": 1,
        "total_streak": 1,
        "date": "26/09/2026",
        "time": "08:30"
      },
      {
        "user": {
          "id": "3247779",
          "email": "trader@example.com"
        },
        "streak_action": "Timeframe expired",
        "action_details": "Action not cleared: Daily Visit",
        "streak_name": "Login Streak",
        "streak_activity": "streak broken",
        "total_streak": 0,
        "date": "26/09/2026",
        "time": "00:00"
      }
    ]
  }
}
```

## Errors

Errors on this endpoint have no machine-readable code; branch on the HTTP status. A key without `getStreakLogs` gets `401`, not `403`, with only a `message`. A validation `400` names the parameter in `detail`.

### Fix the request

| Status | Code | What to do |
| --- | --- | --- |
| 400 | - | A query value is invalid: `limit` outside 1-100, `page` below 1, a date not in `DD/MM/YYYY`, a time not in `HH:MM`, or an unknown `streak_activity`, `sortBy` or `sortOrder`. `detail` names the parameter. An unrecognised `streak_action` also returns `400`, with `Invalid streak action: <value>` in `message` and no `detail`. |
| 401 | - | The key is missing, invalid or expired, it's a personal key, its community no longer exists, or it lacks `getStreakLogs` (`message` is then `Your api key does not have permission to access this action`). Send `Authorization: Bearer <API_KEY>` with a current Community API key, and add Get Streak Logs in Settings > Integration > API Keys. |

### Fix the data

| Status | Code | What to do |
| --- | --- | --- |
| 404 | - | `user` matches no trader in your community. Check the email or platform user ID, or look the trader up with Get User Data. A trader with no entries returns `200` with an empty list, not `404`. |

### Retry with backoff

| Status | Code | What to do |
| --- | --- | --- |
| 500 | - | The entries could not be read, or the key could not be checked (`Authentication failed`). Retry the same request with exponential backoff. |

**Retries:** This endpoint is read-only and doesn't accept an `Idempotency-Key`. Retrying the exact same request is safe after a network error or a `500`; use bounded exponential backoff. Don't retry a `404` without changing `user`. Over the [rate limit](https://docs.returning.ai/how-it-works.md#rate-limits), requests return `429`; wait for the window to reset, then retry.

## Next step

- [Get mini-game and streak state](https://docs.returning.ai/api-reference/gamification-streaks-and-mini-games/get-mini-game-and-streak-state.md): `POST /v1/users/mini-game-streak-stats`. Read the same trader's streak counts and spins as they are right now.
- [Find a trader's platform user ID or email with Get User Data](https://docs.returning.ai/api-reference/users/get-user-data.md): `POST /v1/users/info`.
