Errors

All errors use the same JSON envelope. Match on code rather than message — messages may change.

Error format

{
  "error": {
    "code": "rate_limited",       // machine-readable, stable
    "message": "Rate limit exceeded. Limit: 5 req/s (burst: 10).",
    "request_id": "req_4f2a9b"   // include this when contacting support
  }
}

Error codes

HTTPCodeWhen it firesHow to handle
400invalid_requestRequest body is malformed JSON, or a required field is missing or wrong type.Fix the request body. Check field names and types.
400invalid_addressThe address format does not match the specified chain (e.g., not a valid EVM or Tron address).Validate address format before sending. See chain-specific format rules.
401unauthorizedAuthorization header is missing, malformed, or the key is invalid/revoked.Check that the header is "Authorization: Bearer <key>". Verify the key is active in the dashboard.
402quota_exceededMonthly request quota is exhausted.Upgrade your plan or wait for the quota to reset on the 1st of next month.
403forbiddenThe API key is valid but belongs to a Free-tier org, which does not include API access.Upgrade to Starter or higher.
429rate_limitedRequests per second exceeded the plan limit.Retry with exponential backoff. See Rate Limits.
500internal_errorUnexpected server-side error.Retry once after a short delay. If persistent, contact support.

Error handling pattern

response = requests.post(url, headers=headers, json=body, timeout=10)

if response.status_code == 200:
    result = response.json()
    # handle result

elif response.status_code in (400, 401, 402, 403):
    # Don't retry — fix the request or auth
    error = response.json()["error"]
    raise ValueError(f"{error['code']}: {error['message']}")

elif response.status_code == 429:
    # Retry with backoff
    time.sleep(backoff_delay)

elif response.status_code == 500:
    # Retry once, then alert
    time.sleep(2)
    # retry...