# Get usage

> GET /v1/usage: Get usage. Noptcha API reference.

Source: https://noptcha.com/docs/api-reference/get-usage/

GET https://api.noptcha.com/v1/usage

Native API (v1). [Guide](https://noptcha.com/docs/native-api.md). Operation ID `getUsage`.

Task counts and amounts per hour or day, by task type or by key (needs `usage:read`). Amounts are what was actually taken from the balance, after corrections. Only periods with data are returned (no zero rows), ordered by time and then type or key; the rows always add up to `totals`.

`from` is rounded down and `to` up to period boundaries (`to` is exclusive). Without `to`: the end of the current period; without `from`: 24 hours (hourly) or 30 days (daily) before `to`. Ranges: hourly at most 7 days, daily at most 92 days; `from` not before 2026-01-01 and not in the future. `group_by=key` covers the last 90 days only: an earlier `from` is moved to the first available day (the response shows the effective `from`), a range entirely before that is `400`. Results over 10,000 rows (or over the query's resource limits) are `400` instead of being truncated; narrow the range or use `granularity=day`. Each parameter may be given once.

Rate limit per organization: 20 per minute, bursts of 5 (test keys counted separately), with `RateLimit-Policy: "usage";q=20;w=60`. `503` when usage is temporarily unavailable (or only the per-key breakdown is, then with `Retry-After: 30`; `group_by=type` still works) and when too many usage queries are running (`Retry-After: 5`).

Test keys get an empty report with `"sandbox": true` (parameters are still checked and rate limited).

## Request

Authentication: `Authorization: Bearer <key>` ([Keys](https://noptcha.com/docs/authentication.md)).

| Parameter | In | Description |
| --- | --- | --- |
| `from`  optional  | query |  Start, RFC 3339 or `YYYY-MM-DD` (UTC).  string · e.g. 2026-11-01  |
| `to`  optional  | query |  End (exclusive), RFC 3339 or `YYYY-MM-DD` (UTC).  string  |
| `granularity`  optional  | query |  string  |
| `group_by`  optional  | query |  string  |

## Responses

### 200

Usage.

Headers: `Noptcha-Request-Id`, `RateLimit` (optional), `RateLimit-Policy` (optional).

Content: `application/json`

| Field | Type | Description |
| --- | --- | --- |
| `currency`  required  | `const "USD"` |  |
| `data`  required  | `array of UsageRow` |  |
| `data.[item]`  optional  | `object` |  One period and type (`group_by=type`) or key (`group_by=key`).  |
| `data.[item].amount`  required  | `string` |  cash + promo.  pattern: ^-?\[0-9\]+\\.\[0-9\]{6}$  |
| `data.[item].billed`  required  | `integer` |  Tasks charged.  |
| `data.[item].cash`  required  | `string` |  Decimal US dollars with 6 places.  pattern: ^-?\[0-9\]+\\.\[0-9\]{6}$  |
| `data.[item].promo`  required  | `string` |  Decimal US dollars with 6 places.  pattern: ^-?\[0-9\]+\\.\[0-9\]{6}$  |
| `data.[item].unbilled`  required  | `integer` |  Tasks not charged (unsolvable, timed out, cancelled).  |
| `data.[item].end`  required  | `string` |  format: date-time · pattern: ^\[0-9\]{4}-\[0-9\]{2}-\[0-9\]{2}T\[0-9\]{2}:\[0-9\]{2}:\[0-9\]{2}\\.\[0-9\]{3}Z$  |
| `data.[item].key`  optional  | `one of | null` |  With `group_by=key`. `null` is the unattributed remainder (the difference between the ledger and the per-key task log; usually zero, briefly non-zero while events are being processed).  one of: `object`  |
| `data.[item].start`  required  | `string` |  format: date-time · pattern: ^\[0-9\]{4}-\[0-9\]{2}-\[0-9\]{2}T\[0-9\]{2}:\[0-9\]{2}:\[0-9\]{2}\\.\[0-9\]{3}Z$  |
| `data.[item].type`  optional  | `string` |  With `group_by=type`.  |
| `data.[item].variant`  optional  | `string` |  With `group_by=type`.  |
| `from`  required  | `string` |  Effective start (after rounding and the 90-day limit of `group_by=key`).  format: date-time · pattern: ^\[0-9\]{4}-\[0-9\]{2}-\[0-9\]{2}T\[0-9\]{2}:\[0-9\]{2}:\[0-9\]{2}\\.\[0-9\]{3}Z$  |
| `granularity`  required  | `enum` |  one of "hour", "day"  |
| `group_by`  required  | `enum` |  one of "type", "key"  |
| `object`  required  | `const "usage"` |  |
| `sandbox`  required  | `boolean` |  True for test keys (always an empty report).  |
| `to`  required  | `string` |  Effective end (exclusive).  format: date-time · pattern: ^\[0-9\]{4}-\[0-9\]{2}-\[0-9\]{2}T\[0-9\]{2}:\[0-9\]{2}:\[0-9\]{2}\\.\[0-9\]{3}Z$  |
| `totals`  required  | `object` |  |
| `totals.amount`  required  | `string` |  cash + promo.  pattern: ^-?\[0-9\]+\\.\[0-9\]{6}$  |
| `totals.billed`  required  | `integer` |  Tasks charged.  |
| `totals.cash`  required  | `string` |  Decimal US dollars with 6 places.  pattern: ^-?\[0-9\]+\\.\[0-9\]{6}$  |
| `totals.promo`  required  | `string` |  Decimal US dollars with 6 places.  pattern: ^-?\[0-9\]+\\.\[0-9\]{6}$  |
| `totals.unbilled`  required  | `integer` |  Tasks not charged (unsolvable, timed out, cancelled).  |

### 400

`invalid_request`: the body is not valid JSON or misses a field, a parameter is wrong, `callback_url` is not a string, the result would be too large (usage). `unsupported_type`: the task type does not exist or is not available.

Headers: `Noptcha-Request-Id`, `RateLimit` (optional), `RateLimit-Policy` (optional).

Content: `application/problem+json`

| Field | Type | Description |
| --- | --- | --- |
| `code`  required  | `string` |  Machine-readable error code (see the table).  |
| `detail`  optional  | `string` |  Human-readable explanation of this occurrence.  |
| `request_id`  required  | `string` |  Same as the `Noptcha-Request-Id` header.  |
| `status`  required  | `integer` |  The HTTP status code.  |
| `title`  required  | `string` |  |
| `type`  required  | `string` |  format: uri  |

### 401

`unauthorized`: the key is malformed, unknown, revoked or expired.

Headers: `Noptcha-Request-Id`, `RateLimit` (optional), `RateLimit-Policy` (optional).

Content: `application/problem+json`

| Field | Type | Description |
| --- | --- | --- |
| `code`  required  | `string` |  Machine-readable error code (see the table).  |
| `detail`  optional  | `string` |  Human-readable explanation of this occurrence.  |
| `request_id`  required  | `string` |  Same as the `Noptcha-Request-Id` header.  |
| `status`  required  | `integer` |  The HTTP status code.  |
| `title`  required  | `string` |  |
| `type`  required  | `string` |  format: uri  |

### 403

`forbidden`: the key lacks the scope this endpoint needs, the client IP is not in the key's allowlist, the key may not use this task type, or the organization is suspended (`detail` says which). Also returned, without `detail`, when the request did not pass through our edge network.

Headers: `Noptcha-Request-Id`, `RateLimit` (optional), `RateLimit-Policy` (optional).

Content: `application/problem+json`

| Field | Type | Description |
| --- | --- | --- |
| `code`  required  | `string` |  Machine-readable error code (see the table).  |
| `detail`  optional  | `string` |  Human-readable explanation of this occurrence.  |
| `request_id`  required  | `string` |  Same as the `Noptcha-Request-Id` header.  |
| `status`  required  | `integer` |  The HTTP status code.  |
| `title`  required  | `string` |  |
| `type`  required  | `string` |  format: uri  |

### 413

`request_too_large`: the body exceeds the limit (1 MB for image types, 64 KB otherwise). Any request with a body over 1 MB gets this, GET requests included.

Headers: `Noptcha-Request-Id`, `RateLimit` (optional), `RateLimit-Policy` (optional).

Content: `application/problem+json`

| Field | Type | Description |
| --- | --- | --- |
| `code`  required  | `string` |  Machine-readable error code (see the table).  |
| `detail`  optional  | `string` |  Human-readable explanation of this occurrence.  |
| `request_id`  required  | `string` |  Same as the `Noptcha-Request-Id` header.  |
| `status`  required  | `integer` |  The HTTP status code.  |
| `title`  required  | `string` |  |
| `type`  required  | `string` |  format: uri  |

### 429

`rate_limited`: too many tasks created per second by this key, the same task polled too often, the sandbox's per-organization rate, usage queried too often, the catalog fetched too often from this IP, or this IP sent too many invalid keys. `concurrency_limited`: the organization has too many tasks in flight for this captcha family (or, with a test key, too many sandbox tasks still processing). Wait `Retry-After` seconds.

Headers: `Noptcha-Request-Id`, `RateLimit` (optional), `RateLimit-Policy` (optional), `Retry-After`.

Content: `application/problem+json`

| Field | Type | Description |
| --- | --- | --- |
| `code`  required  | `string` |  Machine-readable error code (see the table).  |
| `detail`  optional  | `string` |  Human-readable explanation of this occurrence.  |
| `request_id`  required  | `string` |  Same as the `Noptcha-Request-Id` header.  |
| `status`  required  | `integer` |  The HTTP status code.  |
| `title`  required  | `string` |  |
| `type`  required  | `string` |  format: uri  |

### 500

`internal`: an error on our side.

Headers: `Noptcha-Request-Id`, `RateLimit` (optional), `RateLimit-Policy` (optional).

Content: `application/problem+json`

| Field | Type | Description |
| --- | --- | --- |
| `code`  required  | `string` |  Machine-readable error code (see the table).  |
| `detail`  optional  | `string` |  Human-readable explanation of this occurrence.  |
| `request_id`  required  | `string` |  Same as the `Noptcha-Request-Id` header.  |
| `status`  required  | `integer` |  The HTTP status code.  |
| `title`  required  | `string` |  |
| `type`  required  | `string` |  format: uri  |

### 503

`service_unavailable`: no capacity right now (all solvers busy or failing, the gateway is overloaded, a dependency is unavailable). For `POST /v1/tasks` nothing was created or charged. Wait `Retry-After`.

Headers: `Noptcha-Request-Id`, `RateLimit` (optional), `RateLimit-Policy` (optional), `Retry-After`.

Content: `application/problem+json`

| Field | Type | Description |
| --- | --- | --- |
| `code`  required  | `string` |  Machine-readable error code (see the table).  |
| `detail`  optional  | `string` |  Human-readable explanation of this occurrence.  |
| `request_id`  required  | `string` |  Same as the `Noptcha-Request-Id` header.  |
| `status`  required  | `integer` |  The HTTP status code.  |
| `title`  required  | `string` |  |
| `type`  required  | `string` |  format: uri  |

Header descriptions and every schema: [Schemas](https://noptcha.com/docs/api-reference/schemas.md). Machine-readable: [openapi.json](https://noptcha.com/openapi.json), [openapi.yaml](https://noptcha.com/openapi.yaml).
