Errors use standard HTTP status codes and a consistent body: { "error": { "code", "message", "details?" } }. The code is stable and safe to branch on; message is human-readable and may change.
Validation failures (400 invalid_request) include a details array of { path, message } entries pinpointing each offending field.
Every response carries an X-Request-Id header — include it when contacting support.
400 invalid_request — The request body, query, or path parameters failed validation. details lists each offending field.
401 invalid_api_key — The Authorization header is missing, malformed, or the key does not exist.
401 revoked_api_key — The key was revoked. Create a new key in the Developer portal.
401 expired_api_key — The key is past its expiry date (rolled keys expire 24 hours after rolling).
403 insufficient_scope — The key is valid but lacks the scope this endpoint requires.
403 module_not_enabled — The endpoint belongs to a module that is not active for this organization.
403 sandbox_unavailable — A test-mode key was used but the organization has no sandbox. Create one from the portal, then retry.
404 not_found — Unknown route, or the resource does not exist in your organization.
405 method_not_allowed — The path exists but not for this HTTP method. The Allow header lists valid methods.
409 idempotency_conflict — This Idempotency-Key was already used with a different request payload.
409 idempotency_in_progress — The original request with this Idempotency-Key is still processing. Retry shortly.
409 conflict — The request conflicts with the current state of the resource.
429 rate_limited — Rate limit exceeded. Honor Retry-After and the X-RateLimit-* headers.
500 internal_error — Something went wrong on our side. The X-Request-Id header identifies the request for support.