Skip to main content
Errors are JSON with a stable machine-readable code. Trigger one against staging right now:

The error envelope

Every error response has the same shape: There is no hint or retryable field — retryability is conveyed by HTTP status alone. Error envelopes never include the access block; the X-RateLimit-* headers are set on every response that reaches the rate limiter, including 400/404/429/5xx errors — but 401/403 authentication errors are rejected before the rate limiter runs and carry no X-RateLimit-* headers.

Error codes

These are the codes the API emits today, exhaustively:
The two 404 codes are ownership-scoped: on /v1/feedback they mean the target does not belong to your account, not necessarily that it never existed.
Authentication and permissions are separate: invalid or missing credentials return 401, while an authenticated key without the required capability returns 403 insufficient_scope. A valid key can therefore authenticate successfully without being authorized for every endpoint or MCP tool.

Warnings

Warnings are the API degrading gracefully instead of failing. They share the error shape — code, message, optional details — and arrive in a warnings array on search and document responses (/v1/feedback has no warnings field):
Warnings never invalidate the response. A 200 with warnings is a complete answer: the status stays 200, the payload is valid and usable, and warnings survives every verbosity preset and budget shed. Missing passage IDs and over-restrictive source policies are deliberately warnings, not errors — your agent gets whatever is available plus a signal about what it did not get.

Retrying

Retry 429 and 5xx with backoff; treat 4xx (other than 429) as bugs in the request, not transient failures.
  • There is no Retry-After header. On 429, read X-RateLimit-Reset (RFC3339) — limits use fixed one-second windows, so the reset is at most about a second away. Exponential backoff also works fine.
  • Rate-limit tokens are spent before validation, so retry loops sending invalid bodies still burn budget.
  • The SDKs and CLI retry automatically: the CLI retries 429 and 500+ up to 3 times with exponential backoff capped at 8 seconds (--no-retry disables).

CLI exit codes

caesar-search maps outcomes to exit codes so scripts branch on status, not output parsing. See CLI automation. With --json, CLI errors go to stderr as {"error":{"code","message","hint"}} — the code is taken from the API envelope’s error.code when one exists. Exit code 1 is not part of the contract.