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.