# Get daily user XP and coin changes

Get the net XP and coin change for up to 100 traders on one UTC day.

- Endpoint: `POST https://api.returning.ai/v1/users/activity/daily`
- Section: Gamification / General
- Authentication: `Authorization: Bearer <API_KEY>` (Community API key)
- Permission: `getUserStats` (Shown in the dashboard as "Get User Stats")
- 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/get-daily-user-xp-and-coin-changes

## When to use this

- Pay out or report on what traders earned yesterday, in one request per day.
- Check a trader's XP and coin movement on the day they raised a support case.
- Reconcile your own reward records against Returning.AI for a given date.

**Instead:** Use [Search user gamification logs](https://docs.returning.ai/api-reference/gamification/search-user-gamification-logs.md) instead to see each change behind a day's total for one trader.

## Authentication

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

Use a Community API key with `getUserStats`, shown in the dashboard as Get User Stats, and keep it on your server. The key decides the community: totals only count XP and coins earned in your community.

## Behaviour

This read changes nothing. Each total is the sum of every XP and coin change the trader had in your community between 00:00 and 23:59:59 UTC on `date`, positive and negative. It is not the trader's balance; read that with Get User Data.

An `overwrite` that sets a trader's balance directly can be counted as the full new balance for that day rather than the difference. For example, a trader who earned 150 XP, was set to 200 XP, then had 200 XP subtracted on the same day shows `xp: 150`, although their balance moved from 0 back to 0. Check days with overwrites against Search user gamification logs.

## Request

### Headers

| Name | Type | Required | Description |
| --- | --- | --- | --- |
| `Authorization` | `string` | Yes | Community API key with `getUserStats`. (`Bearer <API_KEY>`) |
| `Content-Type` | `string` | Yes | Request body format. (`application/json`) |

### Body

Send `identifier`, `identifier_type` and `date`. Email lookups ignore case. Platform user IDs match any account; a trader from outside your community comes back with `0` for both totals. A trader with no changes that day also returns `0`, which is a real result, not a missing trader.

To check more than 100 traders, send separate requests. `page` and `limit` only split the identifiers you send in one request.

| Name | Type | Required | Description |
| --- | --- | --- | --- |
| `identifier` | `string \| string[]` | Yes | One email or platform user ID, or an array of up to 100. Every value must be the kind named in `identifier_type`. (String, or array of 1-100 strings) |
| `identifier_type` | `string` | Yes | What the identifiers are: `email` or `userId` (platform user ID). `userID` is rejected. |
| `date` | `string` | Yes | The day, in UTC. A date that doesn't exist, such as `31/02/2026`, returns `500`. (`DD/MM/YYYY`) |
| `page` | `integer` | No | Which slice of your identifier list to process, starting at 1. Only needed when you send more identifiers than `limit`. (JSON number, 1 or more; default 1) |
| `limit` | `integer` | No | Identifiers processed per page. (Default 100) |

### Example request

```bash
curl --request POST \
  --url https://api.returning.ai/v1/users/activity/daily \
  --header 'Authorization: Bearer <API_KEY>' \
  --header 'Content-Type: application/json' \
  --data '{
    "identifier": ["trader@example.com"],
    "identifier_type": "email",
    "date": "26/09/2026"
  }'
```

## Response

A `200` returns one row per matched identifier in `data.results`. Compare `data.pagination.found` with the number of identifiers you sent to spot ones that matched no trader. This endpoint has no top-level `code`; branch on the HTTP status.

### Response fields

| Field | Type | Presence | Description |
| --- | --- | --- | --- |
| `status` | `string` | always | Result of the request. (`success`) |
| `message` | `string` | always | Human-readable summary. Do not branch on it. (`User gamification stats fetched successfully`) |
| `data` | `object` | always | The day's totals. |
| `data.date` | `string` | always | The date you sent. (`^\d{2}/\d{2}/\d{4}$`) |
| `data.pagination` | `object` | always | Paging over the identifiers you sent, not over results. |
| `data.pagination.page` | `integer` | always | The page of identifiers processed. (Min 1) |
| `data.pagination.limit` | `integer` | always | Identifiers per page. (1-100) |
| `data.pagination.total` | `integer` | always | Identifiers you sent, counting repeats. (Min 0) |
| `data.pagination.total_pages` | `integer` | always | Pages needed for all your identifiers at this `limit`. (Min 0) |
| `data.pagination.found` | `integer` | always | Identifiers on this page that matched a trader. (Min 0) |
| `data.results` | `object[]` | always | One row per matched identifier on this page, in the order you sent them. Identifiers that match no trader are left out; a repeated identifier appears again. |
| `data.results.identifier` | `string` | always | The identifier as you sent it. |
| `data.results.user_id` | `string` | always | The trader's internal user record ID, not the platform user ID. (`^[a-fA-F0-9]{24}$`) |
| `data.results.date` | `string` | always | The date you sent. (`^\d{2}/\d{2}/\d{4}$`) |
| `data.results.coins` | `number` | always | Net coin change on that day, rounded to 2 decimals. Can be negative. |
| `data.results.xp` | `number` | always | Net XP change on that day, rounded to 2 decimals. Can be negative. |

### Example response (200)

```json
{
  "status": "success",
  "message": "User gamification stats fetched successfully",
  "data": {
    "date": "26/09/2026",
    "pagination": {
      "page": 1,
      "limit": 100,
      "total": 1,
      "total_pages": 1,
      "found": 1
    },
    "results": [
      {
        "identifier": "trader@example.com",
        "user_id": "<userObjectId>",
        "date": "26/09/2026",
        "coins": 25,
        "xp": 150
      }
    ]
  }
}
```

## Errors

401 and 403 responses, and the authentication errors `404 COMMUNITY_NOT_FOUND` and `500 AUTHENTICATION_FAILED`, carry the code in `meta.code`. Other errors have no code: a validation `400` names each field in `detail`, and a `500` carries the reason in `detail`.

### Fix the request

| Status | Code | What to do |
| --- | --- | --- |
| 400 | - | A field is missing or invalid: `identifier_type` isn't `email` or `userId`, `date` isn't `DD/MM/YYYY`, more than 100 identifiers, or `page` or `limit` out of range or sent as a string. `detail` names each field. An empty `identifier` returns `400` with `message` `At least one identifier is required` and no `detail`. |
| 401 | `AUTHENTICATION_REQUIRED` | The key is missing, invalid or expired. Send `Authorization: Bearer <API_KEY>` with a current Community API key. |
| 403 | `API_KEY_PERMISSION_DENIED` | The key lacks `getUserStats`, or it is a personal key. Use a Community API key and add Get User Stats in Settings > Integration > API Keys. |

### Fix the data

| Status | Code | What to do |
| --- | --- | --- |
| 404 | `COMMUNITY_NOT_FOUND` | The community this key belongs to no longer exists. Contact Returning.AI support. |

### Retry with backoff

| Status | Code | What to do |
| --- | --- | --- |
| 500 | - | The totals could not be read. If `detail` mentions `Invalid Date`, the date doesn't exist; fix it rather than retrying. Otherwise retry the same request with exponential backoff. |
| 500 | `AUTHENTICATION_FAILED` | The key could not be checked. Retry with backoff; nothing was read. |

**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. 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

- [Search user gamification logs](https://docs.returning.ai/api-reference/gamification/search-user-gamification-logs.md): `POST /v1/gamifications/logs`. List the individual changes behind a trader's total for the day.
- [Read a trader's current XP and coin balance with Get User Data](https://docs.returning.ai/api-reference/users/get-user-data.md): `POST /v1/users/info`.
