market
Errors
One table for the whole API. /assets, /quotes, /trending, /exchanges and /global
answer with the same statuses, the same codes and the same message_keys, with two
endpoint-specific parts: which query parameter can earn you a 400 (the BAD_REQUEST row
says which is which), and the 404 row, which only /global can return.
Every error carries the same envelope as a success response, with result set to {}:
{
"code": 40100,
"message": "the supplied API key is missing, unknown or disabled",
"message_key": "INVALID_API_KEY",
"result": {}
}
| HTTP status | code |
message_key |
Cause |
|---|---|---|---|
| 401 | 40100 | INVALID_API_KEY |
X-Api-Key header missing, or the key is unknown. |
| 401 | 40101 | API_KEY_EXPIRED |
The key's expiry date has passed. Contact us for a new one — nothing about your request was wrong. |
| 401 | 40102 | API_KEY_REVOKED |
The key was revoked, or the account holding it was disabled. It will not start working again. |
| 400 | 40000 | BAD_REQUEST |
A query parameter failed validation. On /assets and /quotes: a non-integer page/size/limit/offset, page < 1, offset < 0, size or limit above 100, a non-integer value in id, more than 100 values in id/symbol/slug — or in fields, which only /assets reads — a sort naming a key outside id/name/symbol/slug or a direction other than asc/desc, or an offset (or the offset a page implies) above 100000. On /exchanges: the same, except the sort keys are id/name/slug/volume — sort=symbol is a 400 there, and ?symbol= is ignored rather than rejected. On /trending: a by value other than gainers, the only parameter it reads. The response does not name the offending parameter — check it against that endpoint's parameter table. |
| 404 | 40400 | NOT_FOUND |
/global only. We have not produced a market-wide snapshot yet — the upstream job that writes them has not run against this database. It is not a wrong path and not a server fault: the URL is right and there is simply nothing to return. Retrying will work once the snapshot exists; if it persists, tell us with the X-Request-Id. No other endpoint returns this code — a 404 from them is the text/plain one described below. |
| 429 | 42900 | RATE_LIMITED |
Retryable. You went over your per-minute ceiling, or over the shared per-address one. Carries Retry-After in whole seconds — back off for at least that long. Rate limiting explains how to tell the two apart. |
| 503 | 50300 | SERVICE_BUSY |
Retryable. We could not complete the request in time, or your account has no rate-limit allowance on record. The last of those is a misconfiguration on our side, not something you can fix — tell us, quoting the X-Request-Id. Your request was fine; retry it shortly. Deliberately distinct from 50000 so you can retry one and not the other. |
| 500 | 50000 | INTERNAL_ERROR |
A server-side error that is not a timeout. Not caused by your request; retry later or contact support with the X-Request-Id if it persists. |
Two kinds of request do not get this envelope. A path we do not serve, and a method the path does not accept, are both answered
404astext/plain(Not Found) by the HTTP framework, before any of our code runs — an unroutable method is not distinguished from an unknown path, so we never return405. A client that assumes every response body is JSON will fail to parse these. Both still carryX-Request-Id.So a
404means one of two different things, and the body tells them apart. A JSON body with"code": 40400is/globalsaying the snapshot does not exist yet; atext/plainbody is the framework saying the path or method does not exist. Branch on the content type or on the presence ofcode, never on the status alone.