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 | Code | Meaning |
|---|---|---|
| 400 | invalid_request | Bad mint, param, source, batch size, or cursor. |
| 401 | unauthorized | Missing or invalid API key. |
| 404 | not_found | Unknown token or no price for mint. |
| 429 | rate_limited | Per-key burst limit exceeded. |
| 429 | quota_exceeded | Per-user monthly request quota exceeded. |
| 500 | internal | Unexpected server failure. |
| 503 | upstream_unavailable | Dependency unavailable (e.g. metadata resolve). |
Stream errors
Subscription rejections and protocol errors arrive as versioned JSON frames on the WebSocket. Most codes leave the connection open; unauthorized and slow_consumer close the socket after the error frame:
{
"v": 1,
"type": "error",
"code": "plan_restricted",
"message": "Your plan doesn't include this stream.",
"id": "trades-1",
"ts": 1783259497400
}| Code | Meaning |
|---|---|
| invalid_message | Client frame is not a recognized control message |
| invalid_filters | Filters fail schema or channel-specific rules |
| unknown_channel | subscribe.channel is not a v1 channel |
| subscription_limit | Active subscriptions on that channel would exceed the account-wide connectionsPerStream cap |
| duplicate_id | subscribe.id already active on this connection |
| unknown_subscription | unsubscribe.id is not active |
| unauthorized | Auth failed or revoked (closes socket) |
| slow_consumer | Client outbound buffer exceeded (closes socket) |
| plan_restricted | Plan does not include the requested channel |
| internal_error | Unexpected server failure handling the message |
Fatal closes use WebSocket codes 1008 (unauthorized), 1013 (slow consumer), and 1011 (internal) — see Close codes on the Streams page.