Data API
Errors
Every failure returns the same shape, so one handler covers all of them.
Error response
{
"detail": "Invalid or missing API key. Get a key at hexio.trade/account"
}The HTTP status is what your code should branch on; detail is written for a human reading a log.
Status codes
| Code | Meaning | What to do |
|---|---|---|
| 200 | Fine | — |
| 400 | A parameter is malformed | Read detail. Retrying will not help. |
| 401 | Key missing, wrong, or revoked | Check the X-API-Key header. Confirm with /v1/usage. |
| 402 | Out of credits | Top up, or wait for period_resets_at. Not retryable. |
| 403 | Your plan does not include this | Signals, streaming and bulk are plan-gated. Upgrade or add the add-on. |
| 404 | No such path, or no such wallet | Check the path. An unknown address is a 404, not an empty 200. |
| 429 | Too many requests per minute | Back off and retry — see Rate limits. |
| 5xx | Our problem | Retry with backoff. If it persists, tell us. |
401 and 402 look alike and are not. One means the key is not valid, the other means the key is valid and the account has run out. Retrying a 402 forever is the most common way to burn a worker.
WebSocket close codes
A stream that is refused closes with a code rather than an HTTP status. These are in the private-use range, so they will not collide with the standard ones.
| Code | Meaning | Reconnect? |
|---|---|---|
| 4401 | Key missing, wrong, or revoked | No — fix the key |
| 4402 | Out of credits | No — top up first |
| 4429 | Too many concurrent streams for the plan | Close an existing one first |
| 1006 | Connection dropped (network, deploy, idle) | Yes — with backoff |
A handshake refused before the socket opens surfaces as an HTTP 403 in most clients rather than a close code.
One handler
JavaScript
class HexioError extends Error {
constructor(status, detail) { super(detail); this.status = status; }
// 402 and 403 are decisions, not blips — retrying them wastes the budget.
get retryable() { return this.status === 429 || this.status >= 500; }
}
async function call(path) {
const res = await fetch(BASE + path, { headers: { 'X-API-Key': KEY } });
if (res.ok) return res.json();
const { detail } = await res.json().catch(() => ({ detail: res.statusText }));
throw new HexioError(res.status, detail);
}