Errors
Every non-2xx response from /v1 returns Content-Type: application/problem+json per RFC 9457 Problem Details:
{
"type": "https://developers.exayard.com/concepts/errors#insufficient_scope",
"title": "Forbidden",
"status": 403,
"detail": "Token does not grant scope \"write:projects\".",
"instance": "/v1/projects",
"code": "insufficient_scope",
"param": "write:projects",
"doc_url": "https://developers.exayard.com/concepts/errors#insufficient_scope",
"request_id": "req_01H..."
}
Branch on code, not detail — code is stable across minor versions, detail is human-readable and may be edited. Both type and doc_url point at the anchor on this page for the specific code, so following the URL from a log line drops you at the right section.
Codes
unauthenticated (401)
Missing or invalid Authorization header. Pass a valid API key (Bearer sk_live_...) or OAuth token. 401 responses also carry a WWW-Authenticate header pointing at the protected-resource metadata for OAuth clients.
insufficient_scope (403)
The token authenticated successfully, but doesn't grant the scope the endpoint requires. The missing scope is surfaced as param on the problem response. Create a new API key with the scope, or use a token that has it. See Scopes.
not_found (404)
Resource not found — or not accessible to this caller. We do not distinguish "doesn't exist" from "exists but you can't see it" because the distinction would leak existence.
invalid_request (400)
Request body failed validation. The offending field (if any) is surfaced as param. Most commonly: missing required fields, wrong types, or values outside an enum.
invalid_idempotency_key (400)
The Idempotency-Key header is malformed. Must be 1–255 URL-safe characters (alphanumeric, underscore, hyphen). See Idempotency.
idempotency_key_reused (409)
The same Idempotency-Key was submitted with a different request body. Pick a new key. This guards against the client mixing up keys and accidentally applying the wrong state.
rate_limited (429)
You've hit the rate limit. Response includes Retry-After (seconds) and the RateLimit / RateLimit-Policy headers. See Rate limits.
internal_error (500)
Unexpected server error. Include request_id in any bug report — it's indexed on our side and gets support to the right request immediately.
transport_error
Emitted by the SDK when the response wasn't JSON (e.g. a CDN error page during an outage). The status field reflects what we actually received.