> ## Documentation Index
> Fetch the complete documentation index at: https://docs.square1.dev/llms.txt
> Use this file to discover all available pages before exploring further.

# Profile and usage

> Your account snapshot, your own metrics, and your recent requests

Three read endpoints plus one toggle, all on `https://dash.square1.dev` and
all accepting either the `ws-session` cookie or a Bearer API key.

<Note>
  If all you need is "does this key work, and where do I stand on quota",
  use [`GET /v1/me`](/api-reference) and
  [`GET /v1/usage`](/api-reference) instead. They are stable, whitelisted
  projections on the documented API host. Everything below is the
  dashboard's own surface.
</Note>

## Account snapshot — `GET /api/user/me`

The dashboard's session-of-record call. One request returns the profile,
quota-pool standing, per-model usage, recent requests, and leaderboard
position.

```bash theme={null}
curl https://dash.square1.dev/api/user/me \
  -H "Authorization: Bearer $SQUARE1_API_KEY"
```

<Warning>
  This response is **not** wrapped in `{success, data}` — it is a bare
  object. And its `403` is a bare string, not the usual envelope:
  `{"error": "User not found (legacy key)"}`. Unwrapping `error.message`
  here yields `undefined`.
</Warning>

### The eleven top-level keys

| Key              | Casing               | What it is                                                                          |
| ---------------- | -------------------- | ----------------------------------------------------------------------------------- |
| `profile`        | camelCase            | 19 fields of account identity and state                                             |
| `rebindRequest`  | camelCase            | Pending community-identity change request, or `null`                                |
| `display_id`     | **snake\_case**      | Your stable integer for the masked public leaderboard (`user-N`). `null` for guests |
| `plan`           | mixed                | Session and weekly pool standing — see below                                        |
| `contributor`    | camelCase            | GPU-contributor standing, or `null` if you aren't one                               |
| `modelUsage`     | camelCase            | Per-model 24 h aggregates                                                           |
| `recentRequests` | **snake\_case rows** | Your last 20 requests — see below                                                   |
| `totals`         | camelCase            | `totalRequests` / `totalTokens` over 24 h                                           |
| `rpm`            | camelCase            | `{ "current": n }`                                                                  |
| `rank`           | —                    | Your position on today's leaderboard, or `null`                                     |
| `today_self`     | **snake\_case**      | `{rank, tokens, requests, attempted, leader_tokens}` for the "★ you" card           |

<Warning>
  Casing is mixed **within this single response**, as marked above. This is
  a historical wart, not a rule you can derive. Copy field names exactly.
</Warning>

### `profile`

Nineteen camelCase fields. The ones with surprises:

* **`createdAt` and `lastUsedAt` are epoch milliseconds** (numbers). Every
  *other* timestamp in `profile` — `livenessBlockedAt`, `nextLivenessAt`,
  `passwordChangedAt`, `lastNickChangedAt`, `nicknameCooldownUntil` — is an
  ISO 8601 string or `null`. The two epoch fields are a frozen older
  contract.
* **`email` is the full address, unmasked.** It is your own address on your
  own account, so the API returns it in full; the dashboard is what masks it
  for display. If you log this response, you are logging an email address.
* `emailVerified` is a boolean derived from a timestamp, not the timestamp.
* `passkeyCount` is `0` whenever the passkey feature is off, regardless of
  what is stored.
* `nicknameCooldownUntil` is `null` whenever self-service nickname change is
  off.

The remaining fields — `arcaId`, `arcaType`, `displayName`, `status`,
`isAdmin`, `isLegacy`, `username`, `sfwMode`, `needsMigration` — are what
their names suggest. `status` values are covered in
[Authentication](/authentication#account-states).

### `plan`

```json theme={null}
{
  "plan": {
    "session": {
      "used": 812000, "limit": 4000000, "remaining": 3188000,
      "used_pct": 20.3,
      "resets_at": "2026-08-30T04:00:00.000Z",
      "resets_in_seconds": 7412,
      "active": true,
      "by_model": [
        { "model_id": "deepseek-v4-pro", "weighted": 610000, "request_count": 18, "pct_of_total": 75.1 }
      ]
    },
    "weekly": {
      "used": 9100000, "limit": 40000000, "remaining": 30900000,
      "used_pct": 22.8,
      "resets_at": "2026-09-02T00:00:00.000Z",
      "resets_in_seconds": 264000,
      "anchor_at": "2026-08-26T00:00:00.000Z",
      "by_model": []
    }
  }
}
```

Both buckets share `used` / `limit` / `remaining` / `used_pct` /
`resets_at` / `resets_in_seconds` / `by_model`. `session` additionally has
`active`; `weekly` additionally has `anchor_at`.

* **`used`, `limit`, and `remaining` can all three be `null` at once.** The
  operator can hide absolute figures; `used_pct` is always present. Treat
  `null` as "hidden", not as zero.
* `by_model` counts **successful** requests only, so its `weighted` values
  can sum to slightly less than the bucket's `used` while requests are still
  in flight. `pct_of_total` is a proportion *within* `by_model`, so the
  percentages still add up.
* `by_model[].weighted` is `null` when absolutes are hidden.

<Note>
  There is no field telling you *whether* absolutes are hidden — the flag
  exists internally but is not included in this response. Infer it from
  `weighted` (or `used`) being `null`.
</Note>

The same standing is available in a stable, documented form from
[`GET /v1/usage`](/api-reference) — prefer that if you only need quota.

### `recentRequests`

Your last 20 request rows, straight from storage and therefore snake\_case:
`id`, `model_id`, `status`, `created_at`, `input_tokens`, `output_tokens`,
`tps`, `error`.

<Warning>
  **`error` here is a free-form diagnostic string, not an enumerated code.**
  Its wording is unstable and not part of any contract. If you are branching
  on failures, use `GET /api/user/me/requests` below, whose `error_code`
  values come from the documented [error code](/concepts/errors) set.
</Warning>

## Your metrics — `GET /api/user/me/metrics`

Aggregated statistics over your own request log.

```bash theme={null}
curl "https://dash.square1.dev/api/user/me/metrics?range=7d&model=deepseek-v4-pro" \
  -H "Authorization: Bearer $SQUARE1_API_KEY"
```

**Rate limit: 120 requests/minute, shared with
`GET /api/user/me/requests`.**

### Query parameters

| Parameter | Values                             | Default            |
| --------- | ---------------------------------- | ------------------ |
| `range`   | `1h` · `4h` · `24h` · `7d` · `30d` | `24h`              |
| `model`   | A model id to filter by            | unset (all models) |

An unrecognized `range` is a `400` whose message lists the allowed values.

<Note>
  `model` is **not** validated against the catalog — it is truncated to 128
  characters and used as-is. A model id you can't call, or one that doesn't
  exist, returns an empty result rather than an error. That is deliberate:
  validating would turn this parameter into an oracle for models you can't
  see.
</Note>

### Response

A bare object (no `{success, data}` wrapper), **entirely snake\_case**:

`range` · `model` · `since` · `until` · `bucket_seconds` · `totals` ·
`latency` · `tps` · `tokens` · `tools` · `errors` · `by_model` · `byok` ·
`series`

Points worth knowing:

* **Ratios are `null` when the sample is empty, never `0`.**
  `totals.success_rate`, `tokens.cache_rate`, `tools.with_tools_rate`, and
  every `latency.*` percentile follow this rule — zero activity must not
  read as total failure.
* `latency` reports `ttfb_p50` / `ttfb_p95` / `duration_p50` /
  `duration_p95` over successful rows only.
* `errors.by_code` is `{code, tier, count}` per code, and `errors.by_tier`
  aggregates by the same three tiers described in
  [Errors](/concepts/errors).
* `tools.choices` is a truncated top-N distribution of `tool_choice` values,
  with unset folded into `unset`. It is client-supplied free text, so
  entries are length-limited.
* `byok` is a **subset** of `totals`, not a separate population, and carries
  a `by_provider` breakdown of your own registered providers. It is all
  zeroes with an empty `by_provider` when you have no BYOK traffic.

## Recent requests — `GET /api/user/me/requests`

Row-level access to your own request log.

```bash theme={null}
curl "https://dash.square1.dev/api/user/me/requests?limit=50" \
  -H "Authorization: Bearer $SQUARE1_API_KEY"
```

```json theme={null}
{
  "requests": [
    {
      "id": 918233,
      "created_at": "2026-08-29T11:04:02.000Z",
      "model_id": "kimi-k2.6",
      "status": "success",
      "error_code": null,
      "input_tokens": 3120,
      "output_tokens": 812,
      "reasoning_tokens": 0,
      "prompt_cached_tokens": 2048,
      "duration_ms": 9840,
      "tps": 61.2,
      "had_tools": false,
      "byok": false,
      "fell_back": false
    }
  ],
  "limit": 50
}
```

* `limit` defaults to **20** and is capped at **50**.
* **Invalid `limit` values do not error.** A non-number, a negative, or an
  empty string silently becomes the default; anything above the cap is
  clamped. Check the echoed `limit` if it matters.
* This is a ceiling, not pagination — there is no cursor.
* `error_code` is `null` on success and otherwise one of the documented
  [error codes](/concepts/errors).
* `byok` and `fell_back` are booleans only: whether the request used one of
  your own credentials, and whether it fell back to the pool. The provider
  itself is not on the row — per-provider figures come from the `byok` block
  of the metrics endpoint above.

**Rate limit: 120 requests/minute, shared with
`GET /api/user/me/metrics`.**

## SFW toggle — `POST /api/user/sfw`

Turns the account-level safe-mode blur on or off for generated images.

<Warning>
  The path is `/api/user/sfw` — **not** `/api/user/me/sfw`. And the body and
  response are snake\_case, unlike its `/api/user/*` siblings.
</Warning>

```bash theme={null}
curl -X POST https://dash.square1.dev/api/user/sfw \
  -H "Authorization: Bearer $SQUARE1_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"sfw_mode": false}'
```

```json theme={null}
{ "success": true, "sfw_mode": false }
```

The response is flat — `sfw_mode` sits next to `success`, not inside a
`data` object. Any body value other than the boolean `true` is read as
`false`, so the endpoint never rejects a malformed body; it just turns the
mode off. The current value is also in `profile.sfwMode` on
`GET /api/user/me`.
