Error handling
Errors use a consistent JSON shape with a machine-readable code — over HTTP for REST, and as inline frames on an open stream connection.
REST errors
HTTP responses include a status code and a JSON body:
{
"error": {
"code": "unauthorized",
"message": "Invalid or missing API key.",
"status": 401
}
}| Status | Code | Meaning |
|---|---|---|
| 400 | bad_request | Malformed request or filters. |
| 401 | unauthorized | Invalid or missing API key. |
| 403 | forbidden | Plan doesn't include this feature. |
| 429 | rate_limited | Too many requests. Back off. |
| 500 | internal | Something went wrong on our end. |
Stream errors
Subscription rejections and protocol errors arrive as JSON frames on the WebSocket without closing the connection (unless the error is fatal, such as an invalid API key on connect):
{
"type": "error",
"code": "forbidden",
"channel": "trades",
"message": "Your plan doesn't include this stream."
}| Code | Meaning |
|---|---|
| bad_request | Malformed subscribe message or filters. |
| unauthorized | Invalid or missing API key on connect. |
| forbidden | Plan doesn't include this stream or feature. |
| rate_limited | Too many subscribe/unsubscribe messages. |
Connection-level failures use WebSocket close codes — see Close codes on the Streams page.