usage

Aggregate spend, tokens, and request volume for the dashboard Usage page.

Range-bounded (default last 30 days, hard-capped): unlike the raw /api/v1/usage list, every aggregate is scoped to a bounded window so it stays served by the timestamp index. Returns grand totals, breakdowns by model / user / API key / source / session (source_label) / endpoint / provider (top rows plus a reconciling other fold, billed token counts), the error taxonomy grouped by failure status code, and a UTC-bucketed time series carrying each bucket's error count and billed token composition (input incl. cache, cache read/write, output).

Each breakdown is its own GROUP BY pass, so a caller that reads only the totals or the series should narrow dimensions rather than pay for all eight (the dashboard's tiles, timeline context, and model typeahead all do). Omitting the parameter keeps the full set.

model, user_id, and api_key_id are repeatable: several values match any of them, so one chart can compare a handful of models, users, or keys.

get/api/v1/usage/summary

Request

  • The document declares no server URL.
  • Auth: one of:
    • API key in header Otari-Key
    • API key in header x-api-key

Query parameters

start_datestring date-time nullable

Return logs with timestamp >= start_date (ISO 8601 or Unix epoch seconds)

end_datestring date-time nullable

Return logs with timestamp < end_date (ISO 8601 or Unix epoch seconds)

user_idstring[] 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.

statusstring 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_codeinteger 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

modelstring[] nullable

Filter to one or more models; repeatable (model=a&model=b). Several values match any of them. At most 50 per call.

endpointstring nullable

Filter to a single endpoint (e.g. '/v1/chat/completions')

providerstring nullable

Filter to a single provider (e.g. 'openai')

sourcestring nullable

Filter to a single provenance source (e.g. 'gateway' or 'claude_code')

source_labelstring nullable

Filter to a single session/project label (the source_label carried by imported usage)

tagstring[] nullable

Filter by a request tag (what a request sent in its metadata), as key:value. Repeatable: values for the same key match any of them, and different keys must all match. At most 50 per call.

api_key_idstring[] 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.

pricedboolean 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' | 'web_fetch' | 'code_execution' nullable

Filter to requests that ran a gateway-run tool. 'any' matches any tool; a tool name (web_search, web_fetch, code_execution) matches that tool specifically.

counts_toward_budgetboolean nullable

Filter by budget participation, which is not the same question as provenance: true = only enforced gateway rows, false = every row that never touches a budget, meaning imported usage and also gateway traffic on a budget-exempt key

workspace_idstring uuid nullable

Only usage recorded in this workspace.

bucket'hour' | 'day'

Time-series granularity: 'hour' or 'day'

dimensionsstring[] nullable

Which breakdowns to compute; repeatable (dimensions=model&dimensions=user). Each value names the 'by_<value>' response field it fills, except 'status_code', which fills the failure taxonomy in 'errors_by_status_code'. Omit for every breakdown (the default); pass 'none' for a totals-and-series-only response. Each dimension left out skips one GROUP BY scan, so a caller that reads only the tiles or the time series should say so. Fields that were not requested come back empty.

group_by_tagstring nullable

A tag key to break spend down by, returned as by_tag. Rows that do not carry the tag group under a null key.

Response

Successful Response

bucket'hour' | 'day' required
end_datestring required
start_datestring required

Changes

    • info

      added the optional property to the response with the status

    • info

      added the new optional query request parameter group_by_tag

    • info

      added the new optional query request parameter tag

    • info

      added the optional property to the response with the status