---
title: "Error Handling | 0xArchive Docs"
description: "Handle 0xArchive HTTP status codes, JSON error bodies, retries, rate limits, auth failures, and recoverable client conditions."
canonical_url: "https://www.0xarchive.io/docs/errors/"
markdown_url: "https://www.0xarchive.io/docs/errors.md"
route: "/docs/errors"
robots: "index, follow"
generated_from: "prerendered_html"
---

# Error Handling

HTTP status, JSON error bodies, and retry rules for client code and automation.

Errors HTTP plus JSON bodies Recovery Retry and fail-fast rules Request IDs Included in responses

Treat errors as part of the API contract, not as a fallback path.

Every failed request returns a structured JSON body and a request identifier.

## Failure classes

Use these buckets first.

| Class | What to do |
| --- | --- |
| Retry | Use bounded backoff for 429, 500, 502, 503, and transient network failures. |
| Do not retry | Fail fast on 400 and other validation errors until the request is corrected. |
| Check permissions | Use 401 and 403 to verify the API key, account state, or wallet-based access flow. |
| Check plan gate | When the route exists but access is denied, confirm whether the endpoint is gated by plan or depth level. |

## Error body

Capture the response body and request identifier together.

Error response

JSON

```
{
  "error": "Invalid API key",
  "code": 401,
  "request_id": "req_abc123xyz"
}
```

## HTTP status codes

| Code | Name | What it means |
| --- | --- | --- |
| `400` | Bad Request | Invalid request parameters or malformed request body |
| `401` | Unauthorized | Missing or invalid API key |
| `403` | Forbidden | API key lacks permission for this resource or tier limit exceeded |
| `404` | Not Found | Endpoint or resource does not exist |
| `429` | Too Many Requests | Rate limit exceeded. Check X-RateLimit-Reset header |
| `500` | Internal Server Error | Server error. Retry with exponential backoff |
| `503` | Service Unavailable | Service temporarily unavailable. Retry later |

## Rate-limit headers

Read the headers so 429 handling is deterministic.

Rate-limit headers

HTTP

```
X-RateLimit-Limit: 50          # Requests per second allowed
X-RateLimit-Remaining: 47      # Requests remaining this second
X-RateLimit-Reset: 1704067200  # Unix timestamp when limit resets
X-Credits-Limit: 10000000      # Monthly credit limit
X-Credits-Used: 500000         # Credits used this month
X-Credits-Remaining: 9500000   # Credits remaining this month
X-Credits-Reset: 1706745600    # Unix timestamp for credit reset
```

## Retry strategy

Retry transient failures. Fail fast on auth, permissions, and validation issues.

Exponential backoff

Python

```
import time
import requests

def request_with_retry(url, headers, max_retries=3):
    for attempt in range(max_retries):
        response = requests.get(url, headers=headers)

        if response.status_code == 200:
            return response.json()

        if response.status_code == 429:
            # Rate limited - wait and retry
            reset_time = int(response.headers.get('X-RateLimit-Reset', 0))
            wait = max(reset_time - time.time(), 1)
            time.sleep(wait)
        elif response.status_code >= 500:
            # Server error - exponential backoff
            time.sleep(2 ** attempt)
        else:
            # Client error - don't retry
            response.raise_for_status()

    raise Exception("Max retries exceeded")
```

## Common issues

### I get 403 when querying ETH but BTC works fine

The free tier only allows BTC (and km:US500 for HIP-3). All other symbols require Build tier or higher. Upgrade at /pricing or start a free 14-day Build trial.

### I get 403 on HIP-3 orderbook endpoints

HIP-3 orderbook and orderbook history require Pro tier or higher. Other HIP-3 endpoints (trades, candles, funding, OI) work on Build tier. Free tier is limited to km:US500.

### I get 400 "Maximum request range is 30 days on your plan"

Free tier limits each request to a 30-day time window. Split large queries into 30-day chunks with cursor pagination, or upgrade to Build+ for unlimited per-request ranges.

### I get 429 but I'm well under 15 requests/second

You may be hitting the concurrent query limit (3 for Free, 10 for Build). This limits how many requests can be in-flight at the same time. Wait for pending requests to complete before sending new ones, or reduce parallelism.

### My WebSocket connection keeps disconnecting

The server sends ping frames every 30 seconds. Your client must respond with pong frames (most libraries do this automatically). Connections without a pong response within 60 seconds are terminated. If your library doesn't handle pings, send {"op": "ping"} periodically.

### WebSocket replay says "Channel does not support historical replay"

The ticker, all_tickers, l4_diffs, l4_orders, hip3_l4_diffs, and hip3_l4_orders channels are real-time only and cannot be replayed. Use the REST API for historical L4 data.

### Candles data returns empty for dates before March 2025

Hyperliquid candles are available from March 2025 onwards. For earlier price history, use the /prices endpoint or orderbook-derived series instead of candle replay.

### Lighter orderbook data returns only checkpoint granularity

Free tier only gets checkpoint-level snapshots. Paid tiers unlock finer L2 granularity, and tick reconstruction is Enterprise-only. The granularity parameter is tier-restricted, not credit-restricted.

### My monthly credits reset but I'm still getting 429

Credits and rate limits are separate. Credits reset monthly, but rate limits (requests/second) and concurrent query limits apply continuously. Check the X-RateLimit-Remaining header to distinguish between credit exhaustion and rate limiting.

### Pre-March 2025 trades are missing maker addresses

Fills before March 2025 were backfilled from Hyperliquid's REST API which only returns taker-side data. Maker/taker attribution with both addresses is available from March 2025 onward (S3 source data).

### I get 404 when calling /v1/hyperliquid/spot/orderbook/@107

The 0xArchive API never accepts the raw @<index> form in URLs. Use the named dashed pair instead (e.g., /v1/hyperliquid/spot/orderbook/PURR-USDC). The server resolves the wire format (PURR/USDC, @107) internally; @-prefixed identifiers are only useful as documentation references.

### Spot trades have a tx_hash of all zeros for some rows

Roughly 31% of spot fills carry a zero tx_hash; the remaining ~69% carry a real EVM hash. Treat tx_hash as optional on spot fills. Perp fills are all-zero by design — only spot trades surface the on-chain hash.

### fee_token is not always USDC for spot fills

Spot fee_token is open-set: USDC, PURR, HYPE, KHYPE, USOL, and others. Validate the token rather than assuming USDC. Perp fills are always USDC-denominated.

### /v1/hyperliquid/spot/candles/{symbol} returns 501 Not Implemented

Spot candles are arriving soon. In the meantime, build OHLCV client-side from /v1/hyperliquid/spot/trades/{symbol}. Hyperliquid does not publish spot candles upstream, so 0xArchive is rolling its own aggregation.

### Spot orderbook history returns 404 before May 2026

Hyperliquid does not publish historical spot orderbook data. /v1/hyperliquid/spot/orderbook and /v1/hyperliquid/spot/orderbook/{symbol}/l4* are live-only from 2026-05-05 forward. Spot trades are backfilled to 2025-03-22; older data is unrecoverable from any free public archive.
