Subject Usage Details
List this subject’s events with aggregated metrics and cursor pagination.
GET /v1/subject/usage/events/detailsAuthentication
Section titled “Authentication”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>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.
Request Body
Section titled “Request Body”The request body is empty. All supported query parameters are listed below.
Query Parameters
Section titled “Query Parameters”| Field | Contract |
|---|---|
raw_event_id |
Optional exact raw event ID. |
billing_account_id |
Optional persisted payer ownership filter. |
subject_type / subject_id |
Optional; must match the token. |
metric |
Optional single metric; prefer metrics. |
metrics |
Optional metric names, repeated or comma-separated. Takes precedence over metric. |
filter.<key> |
Optional dimension/label equality, e.g. filter.model=gpt-4.1-mini. filter.billing_account_id is rejected; use the top-level parameter. Subject filters cannot override the token identity. |
start_time |
Optional inclusive occurrence time, Unix seconds. |
end_time |
Optional exclusive occurrence time, Unix seconds. |
after_id |
Optional opaque cursor from next_after_id; retain all other filters. |
limit |
Optional integer 1–1000. Default 100; values ≤ 0 or > 1000 fall back to 100. |
include_revoked |
Optional 1 or true includes revoked events; omitted or other values exclude them. |
This uses the same detail query as the project endpoint, with token subject and metric constraints applied. Metric selectors intersect with the token allowlist; with no selector, only allowed metrics are visible. Events containing only hidden metrics do not appear. Fully unauthorized selectors return {"usage_events":[],"total":0}.
For the next page, send after_id=<next_after_id> with the same token, time range and filters. Stop when the cursor is absent. This is an analytics view; newly ingested usage may not be visible immediately.
Example
Section titled “Example”curl 'http://127.0.0.1:8080/v1/subject/usage/events/details?start_time=1781222400&end_time=1781308800&limit=100' \ -H 'Authorization: Bearer <subject-token>'Response
Section titled “Response”200 OK
{ "total": 1, "usage_events": [ { "tenant_id": "tenant_123", "project_id": "proj_demo", "event_date": "2026-06-12", "occurred_at": 1781222400, "raw_event_id": "raw_evt_01", "source": "llm_gateway", "subject_type": "user", "subject_id": "user_123", "billing_account_id": "acct_001", "labels": { "model": "gpt-4.1-mini" }, "metrics": { "input_tokens": { "value": "1200", "unit": "token", "currency": "USD", "amount": "0.00024", "unit_price": "0.0000002" } }, "ingested_at": 1781222401, "processed_at": 1781222402 } ]}| Field | Contract |
|---|---|
usage_events |
Event array, empty when no matching authorized usage exists. |
total |
Total visible events matching all subject, metric, account, time, label and revocation filters, independent of limit and after_id; 0 when no events match. |
next_after_id |
Optional next-page cursor: the last raw event ID on this page. Returned only if another event matches the same filters and authorization; omitted on the last page. |
usage_events[].tenant_id / project_id |
Owning tenant and project. |
usage_events[].raw_event_id |
Event identity. |
usage_events[].event_date |
UTC date of business occurrence, YYYY-MM-DD. |
usage_events[].occurred_at |
Business occurrence, Unix seconds; time-filter source. |
usage_events[].ingested_at |
Original Kafka ingress time, Unix seconds; preserved on retries. |
usage_events[].processed_at |
Successful persistence time, Unix seconds. Historical unknown timestamps can be 0. |
usage_events[].source |
Event source. |
usage_events[].external_event_id |
Optional external correlation ID. |
usage_events[].subject_type / subject_id |
Optional subject identity fields; scoped to token. |
usage_events[].billing_account_id |
Optional actual payer snapshot. |
usage_events[].extractor_rule_set_id / extractor_version |
Optional applied extractor ID and version for audit. |
usage_events[].labels |
Optional string map of event labels. |
usage_events[].metrics |
Optional map keyed by logical metric name, sorted by name; only selected, authorized metrics are returned. Dotted names remain intact. |
usage_events[].metrics.<name> |
value: quantity string; optional unit, currency, amount, unit_price, matched_rule_id, analytics_only. Money values are decimal strings. analytics_only: true identifies non-billable analytical usage. |
usage_events[].revoked_at |
Optional revocation time, Unix seconds. |
Errors
Section titled “Errors”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, including failures while counting results or checking the next page. Error messages are public English strings; internal causes are retained only in server logs.
Related Endpoints
Section titled “Related Endpoints”Count, page and next-page checks are separate queries, not a cross-page snapshot. Concurrent ingestion or revocation can change totals and page contents.