Read your workspace's usage
const url = 'https://example.com/v1/usage?from=2026-04-15T12%3A00%3A00Z&to=2026-04-15T12%3A00%3A00Z';const options = {method: 'GET', headers: {Authorization: 'Bearer <token>'}};
try { const response = await fetch(url, options); const data = await response.json(); console.log(data);} catch (error) { console.error(error);}curl --request GET \ --url 'https://example.com/v1/usage?from=2026-04-15T12%3A00%3A00Z&to=2026-04-15T12%3A00%3A00Z' \ --header 'Authorization: Bearer <token>'Your workspace’s usage records aggregated by the dimensions in groupBy: each group’s count, the sum of its quantities, and its first and last times. Never a record’s content. Over the projects you may read: a tenant admin’s covers every project and the records with none; anyone else’s, only the projects they may read, and one they can’t read is absent rather than an error. watermark: every record at or before it is in the answer, so re-read a window until its watermark is past the window’s end; every page of one read carries the same watermark. A runtime that doesn’t count usage (KINDGI_USAGE_METERING unset or off) answers 404. Model-call cost is on /v1/cost.
Authorizations
Section titled “Authorizations”Parameters
Section titled “Parameters”Query Parameters
Section titled “Query Parameters”Records at or after this time: a time with a zone, such as 2026-11-01T00:00:00Z.
Records before this time. At most 92 days after from.
Comma-separated, each once: project, agent, kind, class, state, day (the UTC date). Default project,kind.
Only these kinds, comma-separated (run.started, run.ended, approval.requested, approval.decided, llm.inference, llm.embedding, project.production).
Only these run classes, comma-separated (production, staging, dry-run, replay, eval, child).
Only these states, comma-separated: on, off (project.production); completed, failed, cancelled (run.ended); escalation (approval.requested, an escalation’s next tier); approved, rejected, withdrawn, escalated, expired (approval.decided).
Groups a page: 1 to 10000, default 1000.
The previous page’s nextCursor.
Only this project. One you can’t read gives an empty answer.
Responses
Section titled “Responses”A page of groups.
object
One group: the dimensions it’s grouped by (only those), then its count, the sum of its quantities, and its first and last times.
object
The tenant, on the operator’s read across tenants.
Absent for a record with no project; a tenant admin’s read includes those, and the CLI shows them as (none).
Absent for a record with no agent; the CLI shows those as (none).
What was counted: run.started, run.ended, approval.requested, approval.decided, llm.inference, llm.embedding, project.production. A runtime may count more kinds later: show one you don’t know as it is.
The class of the run a record counts or belongs to, fixed when the run was created: production, staging, dry-run, replay, eval, child. A record with no counted run has none. A runtime may add classes later: show one you don’t know as it is.
The record’s state, by kind: on, off (project.production); completed, failed, cancelled (run.ended); escalation (approval.requested, an escalation’s next tier); approved, rejected, withdrawn, escalated, expired (approval.decided). Other kinds have none.
The UTC date, YYYY-MM-DD.
Records in the group.
The sum of their quantities: milliseconds for run.ended, tokens for model calls, and 1 for every other record, so a group of those has a quantity equal to its count.
Every record at or before this time is in the answer; a later one may not be yet. Re-read a window until its watermark is past the window’s end. Every page of one read carries the same watermark.
More groups: pass it as cursor. Absent on the last page.
Examplegenerated
{ "data": [ { "tenantId": "2489E9AD-2EE2-8E00-8EC9-32D5F69181C0", "projectId": "example", "agentId": "example", "kind": "example", "class": "example", "state": "example", "day": "example", "count": 1, "quantity": 1, "firstAt": "2026-04-15T12:00:00Z", "lastAt": "2026-04-15T12:00:00Z" } ], "watermark": "2026-04-15T12:00:00Z", "nextCursor": "example"}A window, filter, limit or cursor this route can’t read (bad-input), naming which.
object
object
Stable machine-readable discriminant. Values match domain error codes (see docs/API-ROUTE-CONVENTIONS.md §4.3).
Optional, kind-specific.
object
Server-assigned request id; also echoed via X-Request-Id header.
Examplegenerated
{ "error": { "code": "example", "message": "example", "details": {}, "requestId": "example" }}Missing / malformed / expired / revoked bearer token.
object
object
Stable machine-readable discriminant. Values match domain error codes (see docs/API-ROUTE-CONVENTIONS.md §4.3).
Optional, kind-specific.
object
Server-assigned request id; also echoed via X-Request-Id header.
Examplegenerated
{ "error": { "code": "example", "message": "example", "details": {}, "requestId": "example" }}The projects you may read can’t be listed on this deployment, so usage across projects can’t be limited to them (permission-denied): ask for one with projectId.
object
object
Stable machine-readable discriminant. Values match domain error codes (see docs/API-ROUTE-CONVENTIONS.md §4.3).
Optional, kind-specific.
object
Server-assigned request id; also echoed via X-Request-Id header.
Examplegenerated
{ "error": { "code": "example", "message": "example", "details": {}, "requestId": "example" }}