Olava
Concepts

Error catalogue

Every error the public API emits, the shape of the body, and what to do about each.

We use HTTP status codes for the broad category and a stable error.code (or detail) string for the specific reason. Codes are stable for the same condition.

Envelopes

Most errors return one of two envelopes.

Plain detail (auth failures, validation):

{ "detail": "invalid_api_key" }

Structured error (billing, rate-limit, request-size):

{
  "error": {
    "type": "billing_error",
    "code": "spend_cap_exceeded",
    "message": "...",
    "docs_url": "https://docs.olava.dev/billing/spend_cap_exceeded",
    "resolution_url": "https://console.olava.dev/billing",
    "portal_url": "https://console.olava.dev/billing"
  }
}

Branch on error.code (or the equivalent error.reason alias) — do not branch on error.message, which is human copy and may change.

4xx

400 Bad Request

detail / codeCause
invalid_json_bodyBody could not be parsed as JSON.
body_must_be_objectBody parsed but isn't a JSON object.

401 Unauthorized

detailCause
missing_bearer_tokenNo Authorization: Bearer ... header.
invalid_api_keyKey not found, malformed, or revoked.

402 Payment Required

All carry the structured error envelope. The code (and reason alias) is one of:

CodeCauseRecovery
onboarding_incompleteNo spend cap set, or onboarding not finished.Finish onboarding in the console.
spend_cap_exceededCall would exceed monthly cap.Raise the cap from the console, or wait for the period rollover. Retry-After header is set.
payment_failedLast invoice failed to charge.Update payment method via the console's Manage billing flow.
subscription_canceledSubscription has been cancelled.Resubscribe via the console.

413 Payload Too Large

codeCause
input_too_largeChat input above 32,768 tokens.
(no code, plain 413)Request body above 32 MB.

429 Too Many Requests

Always carries Retry-After (seconds).

CodeCause
api_key_rate_limitedPer-key request limit exhausted. Honor Retry-After.

5xx

503 Service Unavailable

The service is temporarily unavailable. The response carries a Retry-After header; back off and retry.

Streaming errors

For POST /v1/chat/completions with stream: true, errors after the response has started are delivered as SSE event: error chunks rather than HTTP status codes:

event: error
data: {"code":"spend_cap_exceeded","message":"...","docs_url":"..."}

The stream closes immediately after. Chunks emitted before the error are still billable.

If the service hits an internal error after streaming has started:

data: {"error":"service_unavailable","status":500}
data: [DONE]

In that case you are not billed — only fully-completed calls produce a usage record.

On this page