---
title: "List Usage"
method: GET
path: "/v1/usage"
tags: ["usage"]
---

# List Usage

`GET /v1/usage`

List usage logs ordered by timestamp (most recent first).

Supports optional filters for time range, user, status, failure status code,
model, endpoint, provider, source, session (``source_label``), and request
group (``request_group_id``, repeatable, which returns a routed request's
whole attempt plan). Paginated via skip/limit. The return shape is a bare JSON array; external
billing/analytics consumers depend on this, so the total row count for a
paginated UI is served separately by ``GET /v1/usage/count`` rather than
wrapped in an envelope here. Timestamps accept either ISO 8601 strings or
Unix epoch seconds (numeric).

## Query parameters

- `start_date` string, date-time, nullable — Return logs with timestamp >= start_date (ISO 8601 or Unix epoch seconds)
- `end_date` string, date-time, nullable — Return logs with timestamp < end_date (ISO 8601 or Unix epoch seconds)
- `user_id` string[], nullable — Filter to one or more users; repeatable (user_id=a&user_id=b). Several values match any of them. At most 50 per call.
- `status` string, nullable — Filter to a single status: 'success', 'error', or 'absorbed' (an attempt a routing policy recovered from, excluded from error_count and request_count)
- `status_code` integer, nullable — Filter to a single failure status code (e.g. 429 for provider rate limits, 402 for missing-pricing rejections). Only error rows carry one, so this filter also restricts to status='error' unless 'status' is given explicitly
- `model` string[], nullable — Filter to one or more models; repeatable (model=a&model=b). Several values match any of them. At most 50 per call.
- `endpoint` string, nullable — Filter to a single endpoint (e.g. '/v1/chat/completions')
- `provider` string, nullable — Filter to a single provider (e.g. 'openai')
- `source` string, nullable — Filter to a single provenance source (e.g. 'gateway' or 'claude_code')
- `source_label` string, nullable — Filter to a single session/project label (the source_label carried by imported usage)
- `api_key_id` string[], nullable — Filter to one or more API key ids; repeatable (api_key_id=a&api_key_id=b). Several values match any of them. At most 50 per call.
- `priced` boolean, nullable — Filter by token-pricing state: true = only rows whose model tokens were priced, false = only rows that still need pricing (no cost at all, or tokens that were never metered because the model had no rate). A row charged only for gateway-run tool calls still counts as needing pricing.
- `tool` 'any' | 'web_search' | 'code_execution', nullable — Filter to requests that ran a gateway-run tool. 'any' matches any tool; a tool name (web_search, code_execution) matches that tool specifically.
- `counts_toward_budget` boolean, nullable — Filter by budget participation: true = only enforced gateway rows, false = only imported rows that never touch a budget
- `request_group_id` string[], nullable — Filter to the rows of one or more request groups; repeatable (request_group_id=a&request_group_id=b). A routed request writes one row per attempt, all sharing a request_group_id, so this returns a request's whole plan: its absorbed attempts and the attempt that served it. Ignore ordering by timestamp and read attempt_position to reconstruct the plan. At most 1000 ids per call.
- `skip` integer
- `limit` integer

## Response `200`

Successful Response

- UsageEntry[]
  - `api_key_id` string, nullable, required
  - `api_key_name` string, nullable
  - `attempt_count` integer, nullable
  - `attempt_position` integer, nullable
  - `billing_meters` union, required
    - BillingMeters — The meters a request was billed on. Token meters sit flat (``{"input": 1200}``), which is why extra keys are allowed: the names come from the provider and the endpoint, so the map is genuinely open. Gateway-run tool counts are the one reserved key, nested under ``tools`` because an MCP server can advertise a tool named after a token meter and a flat collision would corrupt the billed-token aggregates for the whole window (see ``gateway.services.tool_usage``). A TypedDict for the reason above, and for one that cost a round trip to learn: a model that suppressed its defaults with a ``model_serializer`` published an *empty* schema, because that serializer replaces the serialization JSON schema and that is the one FastAPI puts in the spec. The properties below are the whole point, so they have to survive into docs/public/openapi.json; ``tests/unit/test_billing_schemas.py`` asserts they do.
      - `tools` object
    - object
  - `cache_read_tokens` integer, nullable, required
  - `cache_write_1h_tokens` integer, nullable, required
  - `cache_write_tokens` integer, nullable, required
  - `completion_tokens` integer, nullable, required
  - `cost` number, nullable, required
  - `counts_toward_budget` boolean, required
  - `endpoint` string, required
  - `error_message` string, nullable, required
  - `id` string, required
  - `latency_ms` integer, nullable, required
  - `model` string, required
  - `policy_name` string, nullable
  - `pricing_breakdown` union[], nullable, required
    - union
      - TokenChargeLine — A charge line billed per million tokens. ``rate_per_million`` is the discriminator: its presence (rather than ``unit_rate``) is what tells a reader, and a renderer, which unit convention applies. See ``gateway.services.pricing_service``.
        - `cost` number, required — USD charged for this line.
        - `meter` string, required — What was metered, e.g. 'input' or 'cache_read'.
        - `rate_per_million` number, required — USD per million units.
        - `units` union, required — Tokens billed on this meter.
          - integer
          - number
      - UnitChargeLine — A charge line billed per call, for gateway-run tools and per-request routes. ``unit_rate`` is the discriminator, in the same sense as :class:`TokenChargeLine`'s ``rate_per_million``.
        - `cost` number, required — USD charged for this line.
        - `meter` string, required — What was metered, e.g. 'request' or 'web_search_calls'.
        - `unit_rate` number, required — USD per call.
        - `units` union, required — Calls billed on this meter.
          - integer
          - number
      - object
  - `prompt_tokens` integer, nullable, required
  - `provider` string, nullable, required
  - `request_group_id` string, nullable
  - `selection_reason` string, nullable
  - `source` string, required
  - `source_label` string, nullable, required
  - `status` string, required
  - `status_code` integer, nullable, required
  - `timestamp` string, required
  - `total_tokens` integer, nullable, required
  - `user_alias` string, nullable
  - `user_id` string, nullable, required

## Other responses

- `422` — Validation Error

---

[API](https://skmtc.net/mozilla-ai/apis/otari.md) · [All operations](https://skmtc.net/mozilla-ai/apis/otari/llms.txt) · [OpenAPI document](https://skmtc-service-staging.skmtc.workers.dev/v1/apis/mozilla-ai/otari/revisions/dbc01f217b03/schema)
