:::endpoint GET /v1/admin/dashboard/traders

New traders and how many of them bought, pass rates per phase, funded accounts
gained and lost, why accounts failed, and every account by status right now.
The Traders panel of the dashboard on the website.

It has two halves, each behind its own permission, as on the website:
`registrations` needs `view_traders`, and `phases`, `breaches` and `statuses`
need `view_accounts`. Either one opens the endpoint, and the half this person
may not see is `null`. Accounts of our own staff never count.

Needs a firm. Our own staff name one with the `Propper-Workspace` header.

## Request

| Parameter | Description                                                    |
| --------- | -------------------------------------------------------------- |
| `period`  | `today`, `7d`, `30d`, `90d` or `12m`. Left out means `30d`     |

```bash
curl "https://api.proppertrading.com/v1/admin/dashboard/traders?period=7d" \
  -H "Authorization: Bearer ptat_9f2c1a44_3b8e7d2f5c9a1b4e6d8f0a2c4e6b8d1f" \
  -H "Propper-Workspace: acme"
```

## Response

```json
{
    "data": {
        "object": "dashboard_traders",
        "period": {
            "range": "7d",
            "from": "2026-10-09T00:00:00+00:00",
            "to": "2026-10-15T19:05:32+00:00",
            "previous_from": "2026-10-02T00:00:00+00:00",
            "previous_to": "2026-10-08T19:05:32+00:00",
            "granularity": "day",
            "timezone": "UTC"
        },
        "buckets": ["2026-10-09", "2026-10-10", "2026-10-11", "2026-10-12", "2026-10-13", "2026-10-14", "2026-10-15"],
        "registrations": {
            "current": 1,
            "previous": 92,
            "series": [0, 0, 0, 0, 0, 1, 0],
            "previous_series": [8, 18, 16, 16, 5, 16, 13],
            "conversion": {
                "registered": 1,
                "purchased": 0,
                "rate": 0,
                "previous_rate": 0.3587
            }
        },
        "phases": {
            "evaluation": [
                {
                    "phase": 1,
                    "passed": 0,
                    "failed": 2,
                    "previous_passed": 4,
                    "previous_failed": 18,
                    "rate": 0,
                    "previous_rate": 0.1818
                }
            ],
            "funded": {
                "active": 258,
                "new": 0,
                "previous_new": 22,
                "series": [0, 0, 0, 0, 0, 0, 0],
                "lost": 0,
                "previous_lost": 8
            }
        },
        "breaches": {
            "current": 2,
            "previous": 26,
            "reasons": [
                { "key": "time_limit", "count": 2 },
                { "key": "daily_loss", "count": 0 },
                { "key": "max_drawdown", "count": 0 },
                { "key": "other", "count": 0 }
            ]
        },
        "statuses": {
            "active": 72,
            "passed": 149,
            "failed": 80,
            "funded": 258,
            "suspended": 0,
            "breached": 725
        }
    },
    "meta": {
        "request_id": "req_01m50f94fs4xaxvde1v5e80hyg"
    }
}
```

| Field                          | Description                                                                                                  |
| ------------------------------ | ------------------------------------------------------------------------------------------------------------ |
| `buckets`                      | The points of the series                                                                                     |
| `registrations.current`, `previous` | New traders in the period and in the one before                                                         |
| `registrations.conversion`     | Of those who registered in the period, how many bought a challenge since, and the `rate` as a fraction. Null `rate` when nobody registered. A free account is not a purchase |
| `phases.evaluation`            | Per evaluation phase, the accounts that passed and failed in the period, and the pass `rate` as a fraction. An account still running is not in it |
| `phases.funded.active`         | Funded accounts now                                                                                          |
| `phases.funded.new`            | Accounts that started on a funded phase in the period, by passing or bought as instant funding              |
| `phases.funded.lost`           | Funded accounts that failed in the period                                                                    |
| `breaches.reasons`             | Accounts that failed in the period by reason, most first: `daily_loss`, `max_drawdown`, `time_limit` or `other` |
| `statuses`                     | Every account by status now                                                                                  |

## The period

`period` is `today`, `7d`, `30d` (the default), `90d` or `12m`. Each runs up to
this moment, in the firm's timezone, and is compared with the stretch of the
same length right before it, so `today` is set against yesterday up to the same
hour. The points of a series are an hour for `today`, a week for `12m`, and a
day otherwise: `buckets` names them, oldest first, and every series has one
value per bucket.

| Field                    | Description                                                        |
| ------------------------ | ------------------------------------------------------------------ |
| `period.range`           | The period asked for                                               |
| `period.from`, `to`      | The period, local to the firm. `to` is now                         |
| `period.previous_from`, `previous_to` | The stretch it is compared with                       |
| `period.granularity`     | `hour`, `day` or `week`: how wide one bucket is                    |
| `period.timezone`        | The firm's timezone, which the buckets are in                      |

## Errors

| Status | Code                      | Meaning                                                                         |
| ------ | ------------------------- | ------------------------------------------------------------------------------- |
| 400    | `workspace_required`      | Asked by our own staff without naming a firm                                    |
| 400    | `invalid_period`          | `period` is not one of the five                                                 |
| 401    | `invalid_token`           | Not a token, or the secret does not match                                       |
| 401    | `revoked_token`           | Signed out here or from another device                                          |
| 401    | `expired_token`           | Ninety days without use, or a set expiry passed                                 |
| 403    | `admin_access_required`   | This account no longer helps run the environment                                |
| 403    | `insufficient_scope`      | This device does not hold `admin:read`                                          |
| 403    | `workspace_not_permitted` | The `Propper-Workspace` header names an environment this account cannot act in |
| 403    | `forbidden`               | With neither `view_traders` nor `view_accounts`                                 |