Errors
Every error body carries a stable machine-readable code alongside the human-readable error message. Branch on code, not on the message text or the HTTP status alone (one status can map to more than one code).
Two things are deliberately not errors: owning every item in a selection (a 200 with subset_exhausted: true on /items?exclude_owned=true) and re-downloading an item you already own (a 200 with charged: false). Neither returns an error code.
| Status | Code | Meaning |
|---|---|---|
| 400 | invalid_param | An unknown value for a fixed dimension; the response gives param + allowed. |
| 400 | invalid_cursor | The cursor passed for keyset paging is malformed or expired. |
| 400 | ambiguous_benchmark | Benchmark omitted while the key sees more than one; the response lists available. |
| 400 | unsupported_filter | A filter combination the endpoint cannot serve (e.g. exclude_owned combined with an attribute-backed filter). |
| 401 | unauthorized | Missing, invalid, or revoked API key. Copy a current key from the portal. |
| 402 | insufficient_credits | Out of credits (live tier). Top up in the portal. |
| 402 | insufficient_scoped_credits | You hold credit, but none of it is valid for this item (a restricted allocation). Carries balance, eligible_balance and request_access. |
| 403 | forbidden_tier | Key not permitted (a test key requesting a live-tier item or benchmark). Create a live key in the portal. |
| 403 | forbidden_scope | The item is outside this key's content scope (a scoped/siloed key requested content it may not pull). Carries request_access with a portal link. |
| 403 | forbidden_benchmark | The benchmark exists but this key is not scoped to it. This is a permission, not a bad id. Carries request_access with a portal link. |
| 404 | not_found | Item not found, or held out. Sequestered items return this rather than 403 so their existence stays unconfirmable. |
| 404 | unknown_benchmark | No benchmark with that id exists at all. A benchmark you simply lack access to returns 403 forbidden_benchmark instead; the response lists available. |
| 429 | rate_limited | Per-key rate limit exceeded. |
| 500 | server_error | Unexpected server error. |
| 503 | service_unconfigured | The API is temporarily not configured to serve; retry shortly. |