All errors share a consistent envelope:

{
  "error": {
    "code": "<machine-readable code>",
    "message": "<human-readable explanation>",
    "request_id": "<uuid>"
  }
}

The request_id matches the X-Request-Id response header — quote it when reporting a bug.

Error codes

HTTP error.code When
400 bad_request Missing or malformed required parameter (as_of not ISO 8601, resource_type not in the allowed enum, etc.)
401 unauthorized Missing, malformed, unknown, or revoked Bearer token
404 not_found Unknown state abbreviation, unknown version number, no as_of snapshot before that date, no ESA program for that state
429 rate_limit_exceeded Per-key or per-IP rate limit triggered; includes a retry_after (seconds) field and a Retry-After header

Error responses do not count against your rate limit budget the same way

401s and 400s are throttled aggressively at the IP level to discourage probing — see Rate limits.