Skip to content

Aggregate cost across a time window

View as Markdown
GET
/v1/cost/aggregate
curl --request GET \
--url 'https://example.com/v1/cost/aggregate?groupBy=example&limit=1000&includeDescendants=false&scopeKind=tenant&inherit=true' \
--header 'Authorization: Bearer <token>'

Primary consumer path for dashboards. groupBy is required (comma-separated dimensions from the closed set); time range is required (both from and to, or both omitted for the default last-30-days window echoed back in timeRange). Filters compose on top of the time window. ?scopeKind + ?scopeId narrow the aggregate to a scope: org covers every project in the org, so one call sums an org’s spend. It needs read on the scope, and across projects (no scope, the tenant, or an org) it counts only the projects the caller may read, and records with no project; a tenant admin’s counts every project. Each group, and the total, carries its cost and its token sums (tokens). groups is ordered by totalUsd, highest first (ties by key), and capped at limit (default 1000): truncated and totalGroups say when there were more, and the totals still cover every record. For every record, page through /v1/cost/records. inherit has no effect on cost records, which always belong to a project.

groupBy
required
string

Comma-separated list of dimensions to aggregate over. Each value must be one of agentId | runId | category | providerId | day | month | tenant | conversationId | model | servedModel | projectId | orgId | rootRunId | flowId. model is the model actually called; servedModel the exact version the vendor reported; orgId the org of the record’s project. Duplicates collapse.

limit
integer
default: 1000 >= 1 <= 10000

The most groups to return: the most expensive ones (groups is ordered by totalUsd, highest first). 1 to 10000, default 1000. When there were more, truncated is true and totalGroups says how many; the totals still cover every record.

from
string format: date-time

ISO 8601 timestamp; records with occurredAt >= from. Required on /v1/cost/aggregate (or both endpoints omitted for default last-30-days window).

to
string format: date-time

ISO 8601 timestamp; records with occurredAt < to (exclusive). Required on /v1/cost/aggregate (or both endpoints omitted for default last-30-days window).

category
string

Filter to a specific category (llm.inference, tool.invocation, storage.write, sandbox.exec, …). Exact match.

providerId
string

Filter records to this provider id (exact match).

agentId
string

Filter records to this agent id (exact match).

runId
string format: uuid

Filter records to this run id (exact match).

conversationId
string format: uuid

Filter records to this conversation id (exact match).

model
string

Filter model calls to this model, the one actually called (exact match).

servedModel
string

Filter model calls to the exact model version the vendor reported (exact match).

rootRunId
string format: uuid

Every record of the run tree whose root is this run: a flow run and the agent turns and sub-flows it started.

includeDescendants
boolean

With runId: the run’s records and those of every run it started, at any depth. true or false (default).

scopeKind

Discriminator for the ?scopeKind + ?scopeId + ?inherit triplet. Tenant carries no id (implicit from session); org/project require scopeId.

string
Allowed values: tenant org project

Optional scope discriminator. If absent, no scope filter is applied.

scopeId
string
>= 1 characters

Required IF scopeKind is org or project. MUST be absent if scopeKind=tenant (tenant is implicit from the session). Malformed combinations return 400 scope-invalid.

inherit
boolean
default: true

Default true. false = literal-at-this-scope only (admin/audit view). Load-bearing for policy/config-scoped resources (mcp-endpoints); documented no-op for content-scoped resources (agents/flows/tools/…).

Aggregate rollup.

Media typeapplication/json
object
groups
required

The most expensive groups first (totalUsd descending, ties by key), at most limit.

Array<object>
object
key
required

One entry per requested groupBy dimension. null = distinct “unattributed” bucket (records had no value for that dimension).

object
key
additional properties
string | null
count
required
integer
totalUsd
required
number
tokens
required
object
prompt
required
integer
completion
required
integer
cacheRead
required
integer
cacheWrite
required
integer
reasoning
required
integer
totalGroups

How many groups there were before the limit cap. Absent from a runtime before 0.1.5.

integer
truncated

true when there were more groups than limit: groups holds the most expensive ones, and totalUsd / totalRecords / tokens still cover every record. Absent from a runtime before 0.1.5.

boolean
totalUsd
required
number
totalRecords
required
integer
tokens
required
object
prompt
required
integer
completion
required
integer
cacheRead
required
integer
cacheWrite
required
integer
reasoning
required
integer
timeRange
required
object
from
required
string format: date-time
to
required
string format: date-time
groupBy
required

The dimensions the server actually grouped by — echoed so callers can round-trip the response without re-parsing the request URL.

Array<string>
Allowed values: agentId runId category providerId day month tenant conversationId model servedModel projectId orgId rootRunId flowId
Example
{
"groupBy": [
"agentId"
]
}

Missing / malformed groupBy, unknown dimension, missing one endpoint of the time range, or from > to.

Media typeapplication/json
object
error
required
object
code
required

Stable machine-readable discriminant. Values match domain error codes (see docs/API-ROUTE-CONVENTIONS.md §4.3).

string
message
required
string
details

Optional, kind-specific.

object
key
additional properties
any
requestId
required

Server-assigned request id; also echoed via X-Request-Id header.

string
Examplegenerated
{
"error": {
"code": "example",
"message": "example",
"details": {},
"requestId": "example"
}
}

Missing / malformed / expired / revoked bearer token.

Media typeapplication/json
object
error
required
object
code
required

Stable machine-readable discriminant. Values match domain error codes (see docs/API-ROUTE-CONVENTIONS.md §4.3).

string
message
required
string
details

Optional, kind-specific.

object
key
additional properties
any
requestId
required

Server-assigned request id; also echoed via X-Request-Id header.

string
Examplegenerated
{
"error": {
"code": "example",
"message": "example",
"details": {},
"requestId": "example"
}
}

See also