Query Bills
Returns usage quantities, amounts, and distinct request counts grouped by time and optional dimensions.
POST /v1/projects/:project_id/usage/bills/queryAuthentication
Section titled “Authentication”Authorization: Bearer <api-key>Content-Type: application/jsonRequires analytics read access. Results are always scoped to the authenticated tenant and path project.
Path Parameters
Section titled “Path Parameters”| Field | Required | Description |
|---|---|---|
project_id |
Yes | Project that owns the usage events. |
Request Body
Section titled “Request Body”| Field | Required | Description |
|---|---|---|
start_time |
Yes | Inclusive start time as Unix seconds. |
end_time |
Yes | Exclusive end time as Unix seconds. Must be after start_time; the range cannot exceed 31 days. |
metrics |
Yes | One to 10 metric names to include. Select them explicitly; there is no implicit all-metrics mode. |
billing_account_id |
No | One billing account ID. This is a single string, not an array, and filters the system-owned billing account column. If omitted, the query includes all accounts in the project. |
subject_type |
No | Filter by usage subject type. A non-empty top-level value overrides filters.subject_type. |
subject_id |
No | Filter by usage subject ID. A non-empty top-level value overrides filters.subject_id. |
filters |
No | Dimension and label filters, for example { "model": "gpt-5" }. Generic subject filters remain supported when the matching top-level field is omitted. billing_account_id is not allowed here. |
group_by |
No | Up to four subject or label dimensions. day, bucket, metric, and billing_account_id are not allowed. |
bucket_size |
No | 1m, 5m, 1h, or day. Defaults to day. |
timezone |
No | IANA timezone used by day, for example Asia/Shanghai. Defaults to UTC. |
cursor |
No | Opaque next_cursor from the previous page. Keep all other request fields unchanged. |
limit |
No | Number of grouped rows. Defaults to 100; maximum is 1000. |
billing_account_id is an account selector, not a dynamic label. Passing an array for this field returns 400 Bad Request. Currency is not a request field in the current contract. Query bills always use an explicit metrics list.
Example
Section titled “Example”curl 'http://127.0.0.1:8080/v1/projects/proj_gateway/usage/bills/query' \ -H 'Authorization: Bearer <api-key>' \ -H 'Content-Type: application/json' \ -d '{ "billing_account_id": "acct_org_001", "bucket_size": "day", "timezone": "Asia/Shanghai", "start_time": 1785081600, "end_time": 1785686400, "metrics": ["input_tokens", "output_tokens"], "group_by": ["model"], "limit": 100 }'Response
Section titled “Response”| Field | Description |
|---|---|
rows |
Grouped bill rows. |
rows[].dimensions |
Time dimension plus requested group_by dimensions. Daily queries use day; minute and hour queries use the Unix-second string bucket. |
rows[].request_count |
Distinct raw request count in the group. |
rows[].metrics |
Requested metrics keyed by name, each with decimal quantity and amount. |
rows[].amount |
Sum of the metric amounts in this row. |
next_cursor |
Opaque cursor for the next page. Present only when another page exists. |
has_more |
Whether another page exists. |
{ "rows": [ { "dimensions": { "day": "2026-07-27", "model": "gpt-5" }, "request_count": 10, "metrics": { "input_tokens": { "quantity": "1000", "amount": "0.01" }, "output_tokens": { "quantity": "200", "amount": "0.004" } }, "amount": "0.014" } ], "next_cursor": "<opaque-cursor>", "has_more": true}All selected metrics must use the same currency because the response currently returns a row-level amount without a currency field. Use Aggregate Usage for general-purpose measure aggregation.