Get aggregated usage for a project
GET/api/v1/usage/aggregate
Returns a project's usage rolled up over an optional [from, to] time window, optionally bucketed by a single dimension and narrowed by any combination of sixteen filters — session, actor, agent, AI provider, orchestration run, orchestration, generation, trace, tool, publisher project, meter type, model, source, trigger, action and outcome. That is how "what did this conversation cost", "what has this end user cost" and "what did this agent cost" are answered. Each group and the grand total carry an event_count, summed token counts, a measured quantity per component (so infra meters report their real amount, not zeros), and cost_usd (null when no event in the bucket was priced). This is the per-project cost-by-range/by-category query — a monthly figure without scanning raw usage events client-side.
Narrowings intersect and apply to the whole rollup — every bucket, totals and totals.distinct alike — so each composes with any group_by, and all sixteen are echoed back under filters. The ten naming a resource match the id the event recorded, so a deleted resource's spend stays selectable; an id no event recorded empties the rollup rather than being dropped: a mistyped id must never read back as the project's whole spend. orchestration_id is the exception — the event records no orchestration, so a deleted one empties the rollup. The other six are matched against the value the event recorded.
groups is paginated. Its buckets include a null bucket for the events the dimension does not apply to, so they are never a count of entities. To count entities, send include=distinct and read totals.distinct. totals always describes the whole window — never the page above it, and never the bucketing: omit group_by and totals is unchanged while groups is empty.
Request
Responses
- 200
- 400
- 401
- 403
- 429
- 500
The aggregated usage rollup
Bad Request (missing project_id, invalid group_by or timestamp, or a query parameter this endpoint does not declare — an unrecognised filter is rejected rather than ignored, since ignoring one returns the project-wide total in answer to a narrower question)
Unauthorized
Forbidden
QUOTA_EXCEEDED — a requests quota on the calling API key or its project is spent for the window; Retry-After says when it reopens
Response Headers
Seconds until the quota window admits a request again
Unexpected server error — INTERNAL_ERROR, with the raw message never forwarded