The HTTP status always matches the code.
Two responses carry no JSON body: a request with the wrong method for its path gets
405 Method Not Allowed, and a request to /v1/stream without WebSocket upgrade headers gets a plain-text 4xx.
Error codes
Validation details
Only two codes carrydetails: UNSUPPORTED_CHAIN carries {chain}, and VALIDATION_ERROR carries a list of {field, message}, one per problem, as in the example at the top of this page. field is the parameter’s name as you sent it, or path, query or body when the problem is not tied to one field.
Limits
The limits exist to stop runaway clients, not to ration normal use. They sit far above what a working integration needs. If you meet one, your client is most likely looping or leaking connections.
Every key, evaluation or production, has the same limits.
A key’s request budget refills evenly over each minute, and a full minute’s budget can be spent at once, so a backfill can burst and then settle to the steady rate. The IP limit sits above the key limit, so a fleet of your servers behind one outbound IP still gets its full key budget. Treat every number as a ceiling to stay well under, not as an exact quota to run at.
A stream connection counts against your key from its handshake until it closes, and requests over the socket spend no request budget. One connection holds up to 100 subscriptions, so most integrations need only a few.
GET /openapi.json needs no key, spends no budget, and carries no X-RateLimit-Remaining header.
Response headers
X-RateLimit-Remaining reports your key’s budget. It reports your IP address’s budget instead on a 401, on a 429 from the IP limit, and on a 503 when the key could not be checked.
Pace your client on X-RateLimit-Remaining to slow down before you reach the limit.
Retry strategy
- Honour
Retry-After. Wait at least that long. - Back off exponentially on
500and503, with jitter, so parallel workers do not retry in step. - Cap your retries. Three to five attempts are enough. Past that, the problem needs attention.
- Never retry a
4xxother than429. It fails the same way every time.
Request IDs
Every response carries anX-Request-ID header. You can also send your own X-Request-ID: up to 128 visible ASCII characters, with no spaces. The API echoes it back. It replaces any other value with a generated ID rather than rejecting the request.
When you contact support about a failed request, include its X-Request-ID.
Errors on streams
A refused stream frame gets anerror frame with the same code, message and details. See Connecting to streams.