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 detailcode 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.