Error handling

All errors return JSON with a standard envelope:

{
  "error": {
    "message": "Human-readable description",
    "type": "error_category",
    "code": "specific_error_code"
  }
}

Full error catalogue

HTTP Type Common codes What it means Recovery
400 invalid_request_error model_not_found, tos_required, email_not_verified Bad parameters in request body Fix client code, don't retry
401 authentication_error authentication_error Missing / invalid / revoked API key Check Authorization header; create new key if revoked
402 insufficient_quota insufficient_quota Account credit balance is Rp0 Top up via dashboard (email hello@epithre.com)
402 insufficient_quota monthly_cap_exceeded This key hit its monthly_idr_cap for the month Raise the cap on this key in dashboard, or use a different key
403 permission_error account_suspended, email_not_verified, permission_error Account suspended OR endpoint needs admin OR email not verified Check email inbox or contact support
413 request_too_large request_too_large Body exceeds limit: 1MB default, 25MB on /v1/embeddings (image), 50MB on /v1/images/* + /v1/files Reduce payload, split into batches
422 invalid_request_error invalid_request_error Stricter validation: oversize text with truncate: NONE, instruction + image, invalid pgvector content Fix specific constraint cited in message
429 rate_limit_error rpm_exceeded, rpd_exceeded, concurrency_exceeded, backend_busy Various rate limits hit Exponential backoff (1s, 2s, 4s, ...). Raise limits in dashboard if persistent.
500 backend_error backend_error Internal failure Retry once with backoff
502 backend_error backend_error Inference backend returned 5xx Retry once
503 backend_unavailable backend_unavailable Backend not reachable (maintenance or outage) Retry with longer backoff
504 backend_timeout backend_timeout Backend slow / hung Retry with shorter prompt
import time, random
from openai import APIError, RateLimitError, APITimeoutError, APIConnectionError

def call_with_retry(call_fn, max_retries=4):
    for attempt in range(max_retries):
        try:
            return call_fn()
        except RateLimitError:
            wait = (2 ** attempt) + random.uniform(0, 1)
            time.sleep(wait)
        except (APITimeoutError, APIConnectionError):
            if attempt == max_retries - 1:
                raise
            time.sleep(1 + attempt)
        except APIError as e:
            if e.status_code >= 500 and attempt < max_retries - 1:
                time.sleep(2 ** attempt)
            else:
                raise   # 4xx (except 429): don't retry
    raise Exception("retry exhausted")

What NOT to retry

Reporting bugs

Include in your report:

Email: hello@epithre.com with subject "API issue".

See also