Skip to content

Subject Usage Query

Aggregate this subject’s usage into flat grouped rows. Prefer Analysis Query for new chart integrations.

POST /v1/subject/usage/query

Use a Subject Token with the analysis rule. Tenant, project, subject type and subject ID come from the token. Obtain it through Grant Subject Token. Missing, invalid or expired tokens return 401; missing analysis returns 403.

Authorization: Bearer <subject-token>
Content-Type: application/json

Omit subject_type and subject_id to use the token identity. If supplied, they must match the token or the request returns 403. Subject constraints override generic subject filters. A billing-account filter can only narrow this subject’s data.

Field Contract
start_time Required inclusive start, Unix seconds.
end_time Required exclusive end, Unix seconds; must exceed start.
measures Required non-empty array: quantity, amount, quantity_avg, amount_avg, item_count, usage_event_count, event_count.
metrics Explicit metric-name array for metric measures. metrics takes precedence over metric.
metric Optional legacy single-metric selector.
billing_account_id Optional persisted billing-account ownership filter; never widens subject access.
subject_type / subject_id Optional; must match token identity.
filters Optional string equality map for dimensions/labels, e.g. {"model":"gpt-4.1-mini"}. billing_account_id is forbidden here.
group_by Optional array, up to 4 dimensions: bucket, metric, subject_type, subject_id, or label keys. Cannot group by billing_account_id.
limit Optional row limit; default 100, maximum 1000. Zero uses default; negative or above 1000 is invalid. No cursor pagination.
bucket_size Required for bucket grouping. Positive Nm, Nh, Nd durations or day (= 1d); fixed Unix Epoch-aligned buckets. No timezone field.
report_id Optional saved report ID in this project; supplies omitted bucket, metrics, measures and groups, and default filters. Explicit query filters override report filters; token scope still applies.

The half-open range [start_time,end_time) is at most 31 × 24 hours.

Metric selectors are intersected with the token allowlist. A wholly unauthorized selector returns an empty result. Omission does not mean “all metrics” for metric aggregation: select metrics explicitly. Event counts need no metric selector, cannot mix with metric measures, and cannot filter or group by metric. Event counts remain subject to token visibility. Unknown JSON fields are rejected.

Most queries filter occurred_at and exclude revoked usage. Pure event-count queries with fixed minute/hour buckets (or no bucket), subject-only grouping and event-index-compatible filters use successful processing time (processed_at); later revocation does not remove those successful-event counts. Queries needing labels, metrics, billing-account ownership or calendar-day analysis use occurrence time.

quantity and amount sum the selected metric quantities and amounts. item_count counts matching metric items; quantity_avg and amount_avg divide their totals by that count (zero when the count is zero). usage_event_count and event_count are aliases for event count. Filter to comparable data using metrics, labels or account ownership before combining different units or currencies.

Terminal window
curl 'http://127.0.0.1:8080/v1/subject/usage/query' \
-H 'Authorization: Bearer <subject-token>' \
-H 'Content-Type: application/json' \
-d '{"start_time": 1781222400, "end_time": 1781308800, "metrics": ["input_tokens"], "measures": ["quantity", "amount"], "group_by": ["model"], "limit": 100}'

200 OK

{
"rows": [
{
"dimensions": {
"model": "gpt-4.1-mini"
},
"measures": {
"quantity": "1200",
"amount": "0.00024"
}
}
]
}
Field Contract
rows Array of grouped rows; empty when no data matches.
rows[].dimensions String map of group names to values; bucket values are Unix-second strings.
rows[].measures Map of requested measure names to decimal strings.

Errors use {"error":"message"}.

401: invalid or expired token. 403: missing rule or subject mismatch. 400: invalid query. Query cancellation returns 408, timeout 504, and other query failures 500.