Skip to main content
The usage endpoints expose usage, spend, rate-limit, and balance data programmatically. Each authenticates with an rsk_ API key, so anything you can see in the console you can also pull from your own code. Full request/response schemas and an interactive explorer are in the API Reference tab. This page is the guide. For the usage block on each completion response, see Usage Object.
CSV export (GET /v1/usage/events/export) is dashboard-only — it authenticates the signed-in session and is not callable with an API key. Forecasting / usage prediction is not part of this API yet.

Authentication & scoping

On POST /v1/usage, POST /v1/usage/events, and the request lookups, an API key reads only the usage of the key it authenticated with. The server sets that scope, and request parameters cannot widen it. The dashboard’s own views are org-scoped instead, which is why the org / team / member scopes appear in these schemas. GET /v1/usage/spend-trend does not narrow to the key. Any member’s rsk_ key gets the whole org’s spend, or one team’s spend with team_id (the key’s owner must belong to that team). org_id is required on POST /v1/usage, POST /v1/usage/events, and GET /v1/usage/spend-trend. Leave it out and the call fails with 422. The usage and events endpoints ignore its value for an API key, so any placeholder works. Spend trend needs the key’s real organization ID; read it as org_id from GET /v1/keys, which takes an admin key ($MESH_ADMIN_KEY), not an rsk_ key.

Usage summary — POST /v1/usage

Aggregate requests, tokens, and spend, plus a per-model breakdown. Filters are a JSON body (the array filters are more natural as a body than query params).
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.
Retried “waste” attempts are collapsed — each request appears once (the served attempt). A cross-provider routing fallback surfaces as the boolean routing_fallback.

One request — GET /v1/usage/requests/{request_id}

Look up a single request by the id returned in its X-Request-Id response header: the model and provider that served it, status, latency, tokens, cost, and every attempt made. A request refused before any model was called (rate limit, spend cap, empty balance, model access) has no usage row and comes back with outcome: "rejected".
Ids resolve for 90 days — see How far back data goes, which is the one place on this page where a window applies. An older id, or one made by a different key, returns 404. Requests to /v1/chat/compare and /v1/batches are not resolvable here. Use GET /v1/batches/{batch_id} for a batch.

Per-attempt timeline — GET /v1/usage/events/{event_id}/attempts

When a request was retried or rerouted, this returns every attempt that shares its request_id — the served row plus each retried row, oldest first. It is how you see every model that was tried behind one collapsed event.
Authorization mirrors the events list: an API-key caller sees only events made by that key. The same scrubbing applies — no admin fields — and a failed attempt’s error_message may name the provider that answered it.

Spend trend — GET /v1/usage/spend-trend

Historical spend for the key’s whole org, not only the key, bucketed by granularity. The response adds a trailing 3-bucket moving average and the window’s total.

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

Live RPM / RPD / TPM counters vs. the effective limits (always fresh, never cached). For an API-key caller only the key scope is populated.
Each metric carries current, the effective limit, pct (0–100), and resets_in_seconds. A limit the key does not explicitly set is shown as the system default with is_default_limit: true (the TPM default is display-only — keys with no explicit tpm_limit are not TPM-throttled). Use pct to draw a usage bar and warn as it nears 100. The dashboard sees the org / team / member scopes instead of the single key scope.

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.
With an org context the org owner’s balance is returned — all org members share 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.

How far back data goes

Not every endpoint on this page reaches back the same distance, and the difference is deliberate: usage and spend are billing records, while prompts and completions are your content. Spend and usage history has no cutoff. You can pull last quarter or last year from POST /v1/usage and POST /v1/usage/events — requests, tokens, cost, model, status and latency, per request, for as far back as your account goes. If you are reconciling an invoice or charting a year of spend, these are the endpoints to use. Two things are capped at 90 days: looking up one request by its id, and refused requests. Past that the lookup returns 404 whether or not the request existed, and request and response bodies are not available at all. Refused requests — the ones rejected before reaching a model — have the same cap, so they age out of POST /v1/usage/rejections while the served requests around them stay in POST /v1/usage/events indefinitely. 90 days is a ceiling, not a floor. It is the furthest these two will reach, and today they reach less: the request log holds data from 6 August 2026 onward, because it was re-partitioned by month with 30 days of history carried over and the older partition retired. Anything before that is archived and not available through the API. The reachable window grows day by day until it meets the 90-day cap in early November 2026, after which it is a rolling 90 days. Treat a 404 or an absent body as “not available”, never as “this request did not happen”. The cap on the lookup is not an accident of storage — it is why the response carries retention_days:
Read that field rather than hard-coding 90, so a change to the window does not silently break your integration.
Only the bodies and the single-request lookup stop being available. The per-request metadata — model, tokens, cost, status, latency, your request_tags — stays available from POST /v1/usage/events for as long as your account exists, so it needs no archiving on your side. If you need the request and response bodies beyond the window, capture them inside it.These windows describe what this API will return, not a deletion schedule, and they are not a data-retention commitment. Bodies are also returned only where the key that served the request had body logging enabled.

Notes

  • Money is always a decimal string (never a float).
  • Caching: API-key reads are computed fresh; the dashboard’s org-scoped summary/events reads are cached ~60s (?refresh=true bypasses). Rate-limits and balance are never cached.
  • Errors use the standard envelope — 401 (bad credential), 403 (not an org member), 429 (rate limited).