Skip to main content

Status codes

Error body shape

Every error returns a JSON body with an error object carrying a type and a message. On the Anthropic endpoint it is Anthropic-shaped:
Anthropic-shaped (/v1/messages)
On the OpenAI endpoints it is OpenAI-shaped:
OpenAI-shaped (/v1/chat/completions, /v1/responses, ...)

Retries and backoff

The retry recipe every production agent should ship:
  • Retry only what can succeed429 with type rate_limit_error and 5xx. A 429 with type allowance_exhausted won’t clear until the month resets (or you upgrade), and a 4xx will fail identically on every attempt; fix the request instead.
  • Honor retry-after exactly — on 429 it is the number of seconds until capacity opens. Waiting less just burns attempts.
  • Exponential backoff with jitter everywhere else — e.g. 1s, 2s, 4s, 8s with ±20% jitter, capped around five attempts.
  • Fail loud after the cap — surface the final error.message; it is written to be actionable.
Minimal backoff loop
The official OpenAI and Anthropic SDKs already do all of this — including honoring retry-after — with no configuration. Hand-rolled HTTP clients are where retries usually go missing.

Streaming failures

If a stream cannot complete, it ends with a protocol-shaped error event rather than silently returning an empty response — your client always learns the turn failed. Treat a mid-stream error like a 5xx: retry the whole request with backoff. See Streaming.