Using the API

Errors

Errors use the OpenAI envelope, so existing error handling keeps working. An extra provider field tells you which upstream was involved.

The envelope

{
  "error": {
    "message": "Insufficient credits to serve this request",
    "type": "insufficient_quota",
    "code": "insufficient_credits",
    "provider": null
  }
}

Status codes

StatusTypeWhat to do
400invalid_request_errorFix the request body. Retrying will not help.
401authentication_errorCheck the key exists, is active and is sent as a bearer token.
402insufficient_quotaTop up the balance, or raise the monthly limit on the key.
404invalid_request_errorThe model slug is unknown or currently disabled. Check the catalog.
429rate_limit_errorBack off and retry. The limit is per key.
500api_errorA gateway fault. Safe to retry with backoff.
502api_errorEvery provider for that model failed. Retry, or pin a different provider.

Common codes

CodeCause
model_not_foundThe slug does not exist in the catalog.
model_unavailableThe model exists but no provider is currently able to serve it.
insufficient_creditsThe balance cannot cover the estimated cost of the request.
rate_limit_exceededThe key exceeded its requests-per-minute allowance.
invalid_api_keyThe key is unknown, disabled or revoked.
provider_errorAn upstream returned an error that was not worth retrying elsewhere.

Failed requests are free

A request that never produced tokens is not billed, including every failed attempt made before a successful failover.

Retrying well

Retry on 429, 500 and 502 with exponential backoff and jitter. Do not retry 400, 401, 402 or 404, since the outcome will be identical.

import time
from openai import OpenAI, APIStatusError

RETRYABLE = {429, 500, 502, 503}

def with_retries(fn, attempts=4):
    for attempt in range(attempts):
        try:
            return fn()
        except APIStatusError as error:
            if error.status_code not in RETRYABLE or attempt == attempts - 1:
                raise
            time.sleep(2 ** attempt * 0.5)