Analysis Query
Returns grouped analysis series that can be rendered directly by dashboard charts.
POST /v1/projects/:project_id/analysis/queryAuthentication
Section titled “Authentication”Authorization: Bearer <api-key>Content-Type: application/jsonRequires analytics read access.
Path Parameters
Section titled “Path Parameters”| Field | Required | Description |
|---|---|---|
project_id |
Yes | Project that owns the analysis data. |
Request Body
Section titled “Request Body”This endpoint has its own Analysis request contract: start_time, end_time, measures, metrics, optional filters, subject_type, subject_id, group_by, timezone, and required bucket_size.
timezone defaults to UTC and accepts standard IANA names such as Asia/Shanghai and America/Los_Angeles. Local is not accepted. bucket_size supports positive durations such as 1m, 2h, and 3d, plus the legacy day alias, which normalizes to 1d. Nm and Nh are fixed Unix Epoch-aligned buckets; Nd uses calendar-day boundaries in timezone, anchored to midnight of the date containing start_time. For Nd buckets, send start_time already aligned to local midnight in timezone — the server buckets from that midnight but still filters rows using the raw start_time, so a mid-day start_time produces a partial first bucket.
The maximum range is 31 local calendar days, measured as the local calendar-date difference between start_time and end_time (not a fixed number of seconds). Since Nd buckets are anchored to start_time’s local date, a 31-day range can produce up to 32 buckets. Minimum buckets are 1m through 1 hour, 15m above 1 hour and below 1 local day, 1h from 1 through 10 local calendar days, 2h above 10 through 21 days, and 4h above 21 days. A smaller bucket returns an analysis_bucket_too_small: error.
{ "start_time": 1778544000, "end_time": 1779148800, "timezone": "Asia/Shanghai", "bucket_size": "1d", "metrics": ["tokens.input"], "group_by": ["bucket", "model"], "measures": ["quantity", "amount"], "limit": 1000}For chart use, include bucket in group_by or let the chart layer add it for you. The service always returns grouped series with bucket as the time axis.
Pure usage_event_count / event_count series using fixed minute or hour buckets, index-backed event filters, and only subject grouping read the successful-event index. Their range and buckets use processed_at, and later revocation does not remove a successfully processed event from the count. Calendar-day buckets and queries requiring metrics, labels, billing-account ownership, or other dimensions continue to read usage detail rows using occurred_at.
Response
Section titled “Response”{ "group_by": ["bucket", "model"], "measures": ["quantity", "amount"], "series": [ { "key": "series_bW9kZWw9Z3B0LTQuMXxtZWFzdXJlPXF1YW50aXR5", "label": "model=gpt-4.1 · Quantity", "measure": "quantity", "dimensions": { "model": "gpt-4.1" }, "points": [ { "bucket": "1778580000", "value": "1500" } ] } ], "meta": { "timezone": "Asia/Shanghai", "bucket_size": "1d", "start_time": 1778544000, "end_time": 1779148800 }}series[].keyis stable and chart-safe.series[].labelis the human-readable series name.series[].points[].bucketis the Unix-second instant of the bucket start inmeta.timezone.metarecords the server-normalized timezone, bucket size, and half-open query range.- Use Aggregate Usage when you want flat grouped rows instead of chart-ready series.