# Errors & HTTP Codes

- **200** — Success
- **400** — Bad request (invalid params)
- **401** — Unauthorized (API key issue)
- **402** — Payment required
- **403** — Forbidden (endpoint not in plan)
- **404** — Not found
- **429** — Rate limit exceeded
- **500** — Server error

Error responses follow this format:

```json
{ "error": "description" }
```

## Common Errors

  `"error validating API key"` (401)
  Check key, use `API-Key` header (not `Authorization`)

  `"not allowed to access endpoint"` (403)
  Contact api@arkm.com for plan upgrade

  `"cannot use timeLast and timeGte together"`
  Use one or the other, not both

  `"limit must be between 1 and 1000"`
  Reduce limit (counterparties max: 1000)

## Rate Limit Handling (429)

When you receive a 429, implement backoff:

```python
import time
import requests

def request_with_backoff(url, headers, max_retries=5):
    for attempt in range(max_retries):
        resp = requests.get(url, headers=headers)
        if resp.status_code == 429:
            time.sleep(int(resp.headers.get('Retry-After', 60)))
            continue
        return resp
```

## WebSocket Errors

WebSocket errors are returned in this format:

```json
{
    "type": "error",
    "payload": {
        "code": "INVALID_FILTER",
        "message": "..."
    }
}
```

### Error Codes

- **`INVALID_PAYLOAD`** — Malformed request
- **`INVALID_FILTER`** — Invalid filter parameters
- **`INSUFFICIENT_CREDITS`** — Out of credits
- **`TIER_RATE_LIMITED`** — Rate limit for your tier

### Credit Exhaustion

When credits are exhausted:

```json
{
    "type": "error",
    "payload": {
        "code": "INSUFFICIENT_CREDITS",
        "limitType": "hourly",
        "resetIn": 1800
    }
}
```

- **`code`** — `INSUFFICIENT_CREDITS` or `TIER_RATE_LIMITED`
- **`limitType`** — Which limit: `minutely`, `hourly`, or `monthly`
- **`resetIn`** — Seconds until the limit resets
