---
title: "Billed usage over a window, broken down by one dimension"
method: GET
path: "/v1/usage"
tags: ["Usage"]
---

# Billed usage over a window, broken down by one dimension

`GET /v1/usage`

## Request

- Base URL: `https://api.spicrawl.com`
- URL: `https://api.spicrawl.com/v1/usage`
- Auth: HTTP bearer

Reads the durable billing rollup (`usage_daily`) for the key's organization. `totals` is the billed
quantity; `groups` plus `unattributed` equals `totals` per metric. If they do not, a `warnings` entry
says so; trust `totals`.

Pitfalls:
- `to` is EXCLUSIVE. One day 2026-08-01 is `from=2026-08-01&to=2026-08-02`. Days are UTC.
- Default window: the last 30 UTC days including today. Maximum 400 days per call.
- A key filed under a project is pinned to it: `project_id` naming another project is 404, and
  omitting it reads only the key's project. A key with no project may name any project in the org.
- `group_by=key` returns a different body, `UsageByKey`: per API key (`key_id`, `name`, `prefix`,
  `project_id`, `revoked`), counters per metric per UTC day, from the per-key rollup. Requests made
  without a key (the dashboard) are not in it. No caller IPs or countries are returned.
- `group_by=engine`: the per-engine table is often empty today, so the whole quantity may appear in
  `unattributed` with a warning. That is missing attribution, not missing usage.
- `group_by=feature` cannot attribute `requests`, `engine_ms`, byte counters or the non-batch part of
  `credits`; they land in `unattributed`. Batch spend is attributed to the `batch` group.
- `credits` is total credit spend, batch items included, in every grouping.
- Check `stale_seconds`: a large value means the rollup is behind.

## Query parameters

- `from` string, date
- `to` string, date
- `group_by` 'day' | 'project' | 'engine' | 'feature' | 'key'
- `project_id` string
- `metrics` UsageMetric[]

## Response `200`

The breakdown.

- union
  - UsageBreakdown
    - `period` UsagePeriod, required: Half-open range of UTC days.
      - `start` string, date, required: First day, inclusive.
      - `end` string, date, required: End day, EXCLUSIVE. The last included day is the day before this.
      - `days` integer, required: Number of days in the period.
      - `bounds` '[start, end)', required: Always `[start, end)`, a reminder that `end` is exclusive.
    - `group_by` 'day' | 'project' | 'engine' | 'feature' | 'key', required: The dimension used.
    - `groups` UsageGroup[], required: Buckets. Can be empty while `totals` is non-zero (e.g. `group_by=engine` without attribution data).
      - `key` string, required: Bucket key: a `YYYY-MM-DD` day, a project id, a rendering tier (`fetch`, `js` or `browser`), or a feature (`extract`, `ai_extract`, `proxy_datacenter`, `proxy_residential`, `batch`). Groups are sorted by key.
      - `label` string: Human label for rendering-tier groups (for example "JavaScript rendering"). Absent for other dimensions and unknown tiers.
      - `metrics` UsageMetricMap, required: Metric name to quantity. Keys are UsageMetric values.
    - `totals` UsageMetricMap, required: Metric name to quantity. Keys are UsageMetric values.
    - `unattributed` UsageMetricMap, required: Metric name to quantity. Keys are UsageMetric values.
    - `usage_as_of` string, date-time, nullable, required: Freshness of the newest rollup row in the window. Null when the window has no rows.
    - `stale_seconds` integer, nullable, required: Age of `usage_as_of` in seconds. Null when there are no rows (not "fresh"). Large values mean the rollup is behind.
    - `warnings` string[]: Caveats a chart would otherwise hide, such as missing engine attribution or a breakdown that does not reconcile. Omitted when empty.
  - UsageByKey: `GET /v1/usage?group_by=key`. Only the caller's organization's keys, and only the key's own project for a project-scoped key. The dashboard route `GET /v1/orgs/{orgID}/usage?group_by=key` returns the same `keys` array with inclusive `from`/`to` dates instead of `period`.
    - `period` UsagePeriod, required: Half-open range of UTC days.
      - `start` string, date, required: First day, inclusive.
      - `end` string, date, required: End day, EXCLUSIVE. The last included day is the day before this.
      - `days` integer, required: Number of days in the period.
      - `bounds` '[start, end)', required: Always `[start, end)`, a reminder that `end` is exclusive.
    - `group_by` 'key', required
    - `keys` object[], required
      - `key_id` string, required
      - `name` string, required
      - `prefix` string, required: Display prefix of the key, never the secret.
      - `project_id` string, required
      - `revoked` boolean, required
      - `days` object[], required
        - `day` string, date, required
        - `metrics` UsageMetricMap, required: Metric name to quantity. Keys are UsageMetric values.
      - `totals` UsageMetricMap, required: Metric name to quantity. Keys are UsageMetric values.

## Other responses

- `400`: The request is invalid. Not retryable; fix the request using `code` and `diagnostics.hint`.
- `401`: Missing, invalid, revoked or expired key. Not retryable with the same key.
- `403`: The key lacks the scope this route requires (`ERR::AUTH::INSUFFICIENT_SCOPE`), or the action is not permitted.
- `500`: Internal error. Retryable when `retryable` is true.

---

[API](https://skmtc.dev/spicrawl/apis/spicrawl-api.md) · [All operations](https://skmtc.dev/spicrawl/apis/spicrawl-api/llms.txt) · [OpenAPI document](https://skmtc.dev/spicrawl/apis/spicrawl-api/revisions/c4b4c6f97219?raw)
