Overview
Errors
Every code you can receive, what it means, and whether retrying helps.
Two rules make the rest of this page readable.
Every error carries a code. The HTTP status says what kind of problem it is; the code says which one. Branch on the code — statuses are shared, codes are not.
{
"error": "QUOTA_EXCEEDED",
"detail": "this organisation does not have enough credits for that call",
"context": { "balance": "0", "needed": "1", "limit": "20", "used": "20", "plan": "free" },
"request_id": "01J…"
}| Field | Meaning |
|---|---|
error |
The code. Stable — safe to branch on |
detail |
Plain language. Not stable; do not match on it |
context |
Whatever is useful for this code. Shape varies |
request_id |
Quote this when you ask us about a call |
A refusal is not an error. An oracle that ran and refused answers
200 with "status": "invalid". See Verdicts.
Codes
| Status | Code | Meaning | Retry? |
|---|---|---|---|
| 401 | KEY_MISSING |
No bearer token was sent | After fixing the header |
| 401 | KEY_UNKNOWN |
The token is not recognised | No — check for a truncated paste |
| 401 | KEY_REVOKED |
The key was revoked | Never. Mint a new one |
| 401 | KEY_EXPIRED |
The key passed its expiry | Never. Mint a new one |
| 403 | ORG_DISABLED |
The key is fine; its organisation is not active | No. Keep the key and contact support |
| 400 | SIGNATURE_INVALID |
A figure token is malformed, altered or expired | No — draw from a fresh answer |
| 402 | QUOTA_EXCEEDED |
The allowance is spent | When the window turns, or on a bigger plan |
| 404 | NOT_FOUND |
No such oracle, or no organisation for this key | No — read GET /v1/oracles |
| 422 | VALIDATION_FAILED |
The request is malformed, or the format is one this oracle cannot produce | After correcting it. context.available lists the formats |
| 422 | DATA_REQUIRED |
A chart request does not give the values to draw | After putting them in the intent, or with allow_generated_data |
| 500 | INTERNAL |
Something failed that we did not anticipate | Yes, once. Then send us the request_id |
| 501 | UNSUPPORTED |
Nothing draws this figure's target | No |
| 503 | UPSTREAM_UNAVAILABLE |
A service the call depends on is briefly unavailable | Yes, after a short wait |
| 200 | — | "status": "error" — our fault |
Yes. Nothing was billed |
That is the whole list. A request that fails validation names the field in
context.parameter. Each endpoint's page lists exactly which of these it can
return.
The distinctions worth honouring
402 is not 401. Your credential is fine; the allowance is spent. A client
that treats a spent quota as an auth failure re-prompts for a key that was never
the problem — often to a human, in the middle of the night.
ORG_DISABLED is 403, not 401. The key is fine; the organisation behind
it is not active. A client that throws the key away and asks for a new one gets
the same answer with the new one. Keep it, and tell a person.
KEY_REVOKED and KEY_EXPIRED are permanent. No amount of backoff will
help. A client that retries these forever is a client that never tells anyone it
is broken.
A 200 can still be a failure. "status": "error" is ours, and unbilled.
Branch on status, not only on the status line.
See Handle every verdict for the client code.