Skip to content

Errors

Every non-success response — refused authentication, a missing resource, a bad parameter, a spent allowance, a fault on our side — is a JSON object with a single error member:

{
"error": {
"code": "range_too_large",
"message": "A single request may span at most 365 days.",
"max_days": 365
}
}
  • code is machine-readable and drawn from the set below. Branch on it, not on message.
  • message is for a human reading a log. Its wording may change.
  • Some codes add members beside those two, such as required_scope or max_days. New members are always additive.

Request validation failures use this envelope too, with the code invalid_request. You will never receive a framework-shaped validation body.

HTTP code Meaning Extra members
401 missing_credentials No bearer token was sent. WWW-Authenticate: Bearer is set.
401 invalid_key The token matches no live key. Revoked keys land here.
401 key_expired The key’s expiry has passed.
403 tier_not_entitled The workspace’s plan has no API access.
403 insufficient_scope The key lacks the scope this endpoint requires. required_scope
404 not_found No such resource in this key’s workspace, or no such endpoint.
405 method_not_allowed That method is not allowed here. Allow lists what is.
422 invalid_request A parameter could not be understood — a bad cursor, a malformed timestamp, after not earlier than before.
422 range_too_large A telemetry window wider than the plan allows. See History window. max_days
429 rate_limited The workspace’s allowance is spent. Retry-After says how long to wait. See Rate limits.
500 internal_error Something went wrong on our side. The message says nothing about the cause; we have the details.

A resource that exists but belongs to another workspace is a 404 not_found, indistinguishable from one that does not exist.

Within a version, a code is never repurposed and its HTTP status never changes. The set may grow. Treat an unrecognised code as a generic failure at its HTTP status rather than as a parse error.