GET /v1/usage

Balance and usage for the current period

The credits available to the key's account and the scans made in the current usage period, counted by status. Every settled scan is counted, whether or not its result was stored, so the figures do not decay as retention windows pass. A key with no account behind it (the public sandbox key) reports a null balance and zero counters.

Reports the balance in credits and the counters for the current period. One credit is one US cent, and one recognized document draws one, so the balance is also the number of documents left.

A sandbox key reads its own account's real figures. Its own scans are never charged, so they move the counters and not the balance.

Request

Method GET
Path /v1/usage
Authentication Authorization: Bearer <api key>

Responses

200

Balance and counters.

Body: Usage.

Field Type Description
balance_credits integer | null Credits currently available to the account; null for keys without a balance.
period object Bounds of the current usage period (UTC calendar month).
scans object
credits_spent integer Credits charged within the period.
{
  "balance_credits": 11,
  "period": {
    "start": "2026-09-01T00:00:00Z",
    "end": "2026-10-01T00:00:00Z"
  },
  "scans": {
    "total": 12,
    "billed": 9,
    "by_status": {
      "recognized": 9,
      "no_document_found": 1,
      "unreadable": 1,
      "unsupported_document": 1,
      "rejected": 0
    }
  },
  "credits_spent": 9
}

401

Missing or malformed Authorization: Bearer <api key> header, or an unknown key.

Body: ErrorResponse.

{
  "error": {
    "code": "unauthorized",
    "message": "Send your API key as `Authorization: Bearer <key>`.",
    "docs_url": "https://doc.cheap/docs/errors/unauthorized",
    "request_id": "req_9e6b1f7c-2d4a-4b83-9c51-7f0ad3e8b642",
    "event_id": null
  }
}

429

Rate limit exceeded for this key or IP.

Body: ErrorResponse.

{
  "error": {
    "code": "rate_limited",
    "message": "Sandbox limit of 10 requests per hour per IP reached.",
    "docs_url": "https://doc.cheap/docs/errors/rate_limited",
    "request_id": "req_9e6b1f7c-2d4a-4b83-9c51-7f0ad3e8b642",
    "event_id": null
  }
}

500

Unexpected failure on the server; the scan was not charged.

Body: ErrorResponse.

{
  "error": {
    "code": "internal_error",
    "message": "Unexpected error.",
    "docs_url": "https://doc.cheap/docs/errors/internal_error",
    "request_id": "req_9e6b1f7c-2d4a-4b83-9c51-7f0ad3e8b642",
    "event_id": null
  }
}

503

Temporarily unable to serve the request: a store this service depends on is unreachable. Nothing was charged and it may be retried, after the Retry-After seconds where that header is present.

Body: ErrorResponse.

{
  "error": {
    "code": "service_unavailable",
    "message": "The service is temporarily unable to handle this request; nothing was charged. Retry shortly.",
    "docs_url": "https://doc.cheap/docs/errors/service_unavailable",
    "request_id": "req_9e6b1f7c-2d4a-4b83-9c51-7f0ad3e8b642",
    "event_id": null
  }
}

Error codes reachable here

Code When Page
internal_error The service failed in a way it does not model. internal_error
rate_limited The caller is over the rate limit for its key kind. rate_limited
service_unavailable A store this endpoint reads from is unreachable, so the answer could not be produced. Nothing was charged; retry after the Retry-After seconds. service_unavailable
unauthorized The Authorization header is missing, malformed or names an unknown key. unauthorized

Every error body carries the same shape; the full list is on Errors.