> For clean Markdown of any page, append .md to the page URL.
> For a complete documentation index, see https://developers.meshapi.ai/llms.txt.
> For AI client integration (Claude Code, Cursor, etc.), connect to the MCP server at https://developers.meshapi.ai/_mcp/server.

# Usage & Monitoring API

> Pull your usage, spend, rate-limit, and balance data programmatically — the same numbers the dashboard shows.

The usage endpoints expose **usage, spend, rate-limit, and balance data
programmatically** with your `rsk_` API key, so anything you can see in the
console you can also pull from your own code.

| What                                               | Endpoint                    |
| -------------------------------------------------- | --------------------------- |
| Requests / tokens / spend aggregates               | `POST /v1/usage`            |
| Per-request history                                | `POST /v1/usage/events`     |
| Live RPM / RPD / TPM vs limits                     | `GET /v1/usage/rate-limits` |
| Remaining credit balance (with reserved breakdown) | `GET /v1/balance`           |

Full request/response schemas and an interactive explorer are in the
[API Reference](/api-reference). This page is the guide.

Spend-trend charts and CSV export are part of the dashboard only — they are not
callable with an API key. Forecasting / usage prediction is not part of this API
yet.

## Authentication & scoping

| Credential  | Header                            | Scope                                                                         |
| ----------- | --------------------------------- | ----------------------------------------------------------------------------- |
| **API key** | `Authorization: Bearer rsk_<key>` | Only that key's own usage. `org_id` / `team_id` / member filters are ignored. |

An API key can only ever read the usage of the key it authenticated with — the
scope is derived server-side and cannot be widened by request parameters.

## Usage summary — `POST /v1/usage`

Aggregate requests, tokens, and spend, plus a per-model breakdown.

```bash
curl https://api.meshapi.ai/v1/usage \
  -H "Authorization: Bearer rsk_<key>" \
  -H "Content-Type: application/json" \
  -d '{"since": "2026-07-01", "until": "2026-07-14", "limit": 10}'
```

| Body field         | Notes                                              |
| ------------------ | -------------------------------------------------- |
| `since` / `until`  | ISO 8601. Bare dates cover the whole day.          |
| `model`            | `string[]` — filter by model ids.                  |
| `status`           | `string[]`, e.g. `success`, `error`.               |
| `limit` / `offset` | Paginate the `by_model` breakdown (`limit` ≤ 200). |

```json
{
  "total_requests": 1284,
  "successful_requests": 1270,
  "error_requests": 14,
  "prompt_tokens": 482913,
  "completion_tokens": 197233,
  "total_tokens": 680146,
  "total_cost_usd": "12.4832100",
  "by_model_total": 3,
  "by_model": [
    {
      "model": "openai/gpt-4o-mini",
      "requests": 900,
      "total_tokens": 420000,
      "cost_usd": "6.1200000"
    }
  ]
}
```

Totals span the full range; `by_model` is one page (`by_model_total` is the full
distinct-model count). Monetary values are strings to preserve decimal
precision.

## Per-request history — `POST /v1/usage/events`

Paginated list of individual requests, newest first. Same filters as the
summary, plus `limit` (≤ 200) / `offset`.

```bash
curl https://api.meshapi.ai/v1/usage/events \
  -H "Authorization: Bearer rsk_<key>" \
  -H "Content-Type: application/json" \
  -d '{"status": ["success"], "limit": 20}'
```

```json
{
  "events": [
    {
      "id": "0190a1c0-0000-7000-8000-00000000e1e1",
      "request_id": "req_01ARZ3NDEKTSV4RRFFQ69G5FAV",
      "model": "openai/gpt-4o-mini",
      "prompt_tokens": 128,
      "completion_tokens": 64,
      "total_tokens": 192,
      "cost_usd": "0.0000480",
      "latency_ms": 812,
      "status": "success",
      "created_at": "2026-07-14T10:15:30+00:00"
    }
  ],
  "total": 1284,
  "limit": 50,
  "offset": 0
}
```

Retried "waste" attempts are collapsed — each request appears once (the served
attempt). Which upstream provider served a request is never exposed; a
cross-provider routing fallback surfaces only as the boolean `routing_fallback`.

## Rate limits — `GET /v1/usage/rate-limits`

Live RPM / RPD / TPM counters vs. the effective limits (always fresh, never
cached). Only the `key` scope is populated; `org` / `team` / `member` are always
`null`.

```bash
curl https://api.meshapi.ai/v1/usage/rate-limits \
  -H "Authorization: Bearer rsk_<key>"
```

```json
{
  "as_of": "2026-07-14T10:20:00+00:00",
  "org": null,
  "team": null,
  "member": null,
  "key": {
    "rpm": { "current": 42, "limit": 60, "is_default_limit": false, "pct": 70.0, "resets_in_seconds": 37 },
    "rpd": { "current": 5120, "limit": 10000, "is_default_limit": false, "pct": 51.2, "resets_in_seconds": 49200 },
    "tpm": { "current": 18000, "limit": 1000000, "is_default_limit": true, "pct": 1.8, "resets_in_seconds": 37 }
  }
}
```

Each metric carries `current`, the effective `limit`, `pct` (0–100), and
`resets_in_seconds`. RPM and TPM are per-minute windows; RPD resets at midnight
UTC. A limit the key does not explicitly set is shown as the system default with
`is_default_limit: true`. Use `pct` to draw a usage bar and warn as it nears 100.

## Balance — `GET /v1/balance`

Current credit balance, plus how much is **reserved** by in-flight operations
(realtime sessions, async background jobs, video generation) and therefore not
spendable.

```bash
curl https://api.meshapi.ai/v1/balance \
  -H "Authorization: Bearer rsk_<key>"
```

```json
{
  "balance_usd": "42.5000000",
  "reserved_usd": "15.0000000",
  "available_usd": "27.5000000",
  "reserved_breakdown": [
    { "kind": "realtime", "reserved_usd": "5.0000000" },
    { "kind": "video", "reserved_usd": "10.0000000" }
  ],
  "updated_at": "2026-07-14T10:15:30+00:00"
}
```

If your key belongs to an organization, the organization's shared balance is
returned — all members draw from one billing pool; a personal key with no org
gets its own balance. `available_usd` = `max(0, balance_usd − reserved_usd)`;
`reserved_breakdown` lists only the categories currently holding funds and sums
to `reserved_usd`.

## Notes

* **Money** is always a decimal string (never a float).
* **Caching:** API-key reads are computed fresh (never cached).
* **Errors** use the standard envelope — `401` (bad credential), `422` (bad
  UUID / invalid filter), `429` (rate limited).