Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.auriko.ai/llms.txt

Use this file to discover all available pages before exploring further.

Every error response includes a machine-readable code, a canonical type, and the request_id for support correlation.

Prerequisites

  • An Auriko API key
  • Python 3.10+ with the OpenAI SDK (pip install openai) or the auriko SDK (pip install auriko)
    • OR Node.js 18+ with the OpenAI SDK (npm install openai) or @auriko/sdk (npm install @auriko/sdk)

Error types

All Auriko errors extend AurikoAPIError. The envelope is canonical (see Errors):
FieldTypeDescription
messagestrHuman-readable error message
status_codeintHTTP status code
codestrMachine-readable error code
typestrCanonical error type (one of six values)
paramstr | NoneParameter that caused the error
request_id / requestIdstrValue of x-request-id on the failing response
retry_after_seconds / retryAfterSecondsint | NoneRetry-After header value (429 / 503 only)
doc_url / docUrlstr | NoneLink to the error’s docs page
providerstr | NoneUpstream provider that generated the error, when attributable
The SDK provides these typed exception classes:
ExceptionHTTPtype
BadRequestError400 / 413 / 422invalid_request_error
AuthenticationError401authentication_error
PermissionDeniedError403permission_error
NotFoundError404not_found_error
ConflictError409invalid_request_error
RateLimitError429rate_limit_error
InternalServerError500api_error
APIStatusError502 / 503 / 504api_error
APIConnectionErrornetwork failure before any response
Dispatch on type + HTTP status for exception class, then on code for precise handling within a class. Never branch on message text; see Errors for retry policy by code.
See the Python SDK Reference or TypeScript SDK Reference for complete error class fields and hierarchy.

Handle errors

Catch typed exceptions:
import os
import openai

client = openai.OpenAI(
    api_key=os.environ["AURIKO_API_KEY"],
    base_url="https://api.auriko.ai/v1",
)

try:
    response = client.chat.completions.create(
        model="gpt-4o",
        messages=[{"role": "user", "content": "Hello!"}],
    )
    print(response.choices[0].message.content)

except openai.AuthenticationError as e:
    print(f"Check your API key (status={e.status_code})")
except openai.RateLimitError as e:
    print(f"Rate limited (status={e.status_code})")
except openai.NotFoundError as e:
    print(f"Not found: {e.message}")
except openai.BadRequestError as e:
    print(f"Bad request: {e.message}")
except openai.PermissionDeniedError as e:
    print(f"Not allowed: {e.message}")
except openai.InternalServerError as e:
    print(f"Server error (status={e.status_code})")
except openai.APIStatusError as e:
    print(f"API error ({e.status_code}): {e.message}")
except openai.APIConnectionError as e:
    print(f"Network error: {e}")

Use built-in retries

The SDK automatically retries transient errors with exponential backoff:
SettingValue
Max retries2 (default)
Initial interval500ms
Max interval30 seconds
BackoffExponential (1.5 exponent) + random jitter
Retried status codes429, 500, 502, 503, 504
Connection/timeout errorsRetried
Retry-After headerRespected (overrides backoff when present)
import os
from openai import OpenAI

# Default: 2 retries with exponential backoff
client = OpenAI(
    api_key=os.environ["AURIKO_API_KEY"],
    base_url="https://api.auriko.ai/v1",
)

# More retries
client = OpenAI(
    api_key=os.environ["AURIKO_API_KEY"],
    base_url="https://api.auriko.ai/v1",
    max_retries=5,
)

# Disable retries
client = OpenAI(
    api_key=os.environ["AURIKO_API_KEY"],
    base_url="https://api.auriko.ai/v1",
    max_retries=0,
)
When the server returns a Retry-After header (common with 429 responses), the SDK uses that value instead of the calculated backoff interval.

Retry manually

For request-level control over backoff or error filtering, implement custom retry logic:
import os
import time
import openai

client = openai.OpenAI(
    api_key=os.environ["AURIKO_API_KEY"],
    base_url="https://api.auriko.ai/v1",
    max_retries=0,
)

def make_request_with_retry(messages, max_retries=3):
    last_error = None

    for attempt in range(max_retries):
        try:
            return client.chat.completions.create(
                model="gpt-4o",
                messages=messages,
            )
        except openai.RateLimitError as e:
            last_error = e
            retry_after = e.response.headers.get("Retry-After")
            wait_time = float(retry_after) if retry_after else min(2 ** attempt, 60)
            time.sleep(wait_time)

        except openai.APIStatusError as e:
            last_error = e
            retry_after = e.response.headers.get("Retry-After")
            wait_time = float(retry_after) if retry_after else 2 ** attempt
            time.sleep(wait_time)

    raise last_error

# Usage
response = make_request_with_retry([{"role": "user", "content": "Hello!"}])

Retry asynchronously

Retry with async/await:
import os
import asyncio
import openai

client = openai.AsyncOpenAI(
    api_key=os.environ["AURIKO_API_KEY"],
    base_url="https://api.auriko.ai/v1",
    max_retries=0,
)

async def make_request_with_backoff(messages, max_retries=3):
    for attempt in range(max_retries):
        try:
            return await client.chat.completions.create(
                model="gpt-4o",
                messages=messages,
            )
        except (openai.RateLimitError, openai.APIStatusError) as e:
            if attempt == max_retries - 1:
                raise
            retry_after = e.response.headers.get("Retry-After")
            wait_time = float(retry_after) if retry_after else 2 ** attempt
            await asyncio.sleep(wait_time)
TypeScript is inherently async. See the TypeScript tabs in Retry manually.
Side effects and retries: When using tools or multi-step workflows, consider whether retries are safe. A retried request that triggers a tool call may execute the tool twice. For idempotency-sensitive operations, either disable automatic retries (max_retries=0) or implement your own deduplication logic.

Fall back to another model

Catch the error from your primary model and retry with a different one:
import os
import openai

client = openai.OpenAI(
    api_key=os.environ["AURIKO_API_KEY"],
    base_url="https://api.auriko.ai/v1",
)

def chat_with_fallback(messages):
    try:
        return client.chat.completions.create(
            model="gpt-4o",
            messages=messages,
            extra_body={"gateway": {"routing": {"max_ttft_ms": 1000}}},
        )
    except openai.APIError as e:
        print(f"Primary failed ({e}), trying fallback...")

        return client.chat.completions.create(
            model="gpt-4o-mini",
            messages=messages,
        )

Use circuit breakers

A circuit breaker stops sending requests after repeated failures and re-tests after a timeout:
import os
from datetime import datetime, timedelta, timezone
import openai

client = openai.OpenAI(
    api_key=os.environ["AURIKO_API_KEY"],
    base_url="https://api.auriko.ai/v1",
)

class CircuitBreaker:
    def __init__(self, failure_threshold=5, reset_timeout=60):
        self.failures = 0
        self.failure_threshold = failure_threshold
        self.reset_timeout = reset_timeout
        self.last_failure = None
        self.is_open = False

    def record_failure(self):
        self.failures += 1
        self.last_failure = datetime.now(timezone.utc)
        if self.failures >= self.failure_threshold:
            self.is_open = True

    def record_success(self):
        self.failures = 0
        self.is_open = False

    def can_proceed(self):
        if not self.is_open:
            return True
        if datetime.now(timezone.utc) - self.last_failure > timedelta(seconds=self.reset_timeout):
            self.is_open = False
            return True
        return False

# Usage
breaker = CircuitBreaker()

def safe_request(messages):
    if not breaker.can_proceed():
        raise Exception("Circuit breaker open, try later")

    try:
        response = client.chat.completions.create(
            model="gpt-4o",
            messages=messages,
        )
        breaker.record_success()
        return response
    except openai.APIStatusError as e:
        breaker.record_failure()
        raise

Set timeouts

import os
import openai

client = openai.OpenAI(
    api_key=os.environ["AURIKO_API_KEY"],
    base_url="https://api.auriko.ai/v1",
    timeout=30.0,
)

try:
    response = client.chat.completions.create(
        model="gpt-4o",
        messages=[{"role": "user", "content": "Write a long essay..."}],
    )
except openai.APIConnectionError as e:
    print(f"Connection failed: {e}")

Log errors

Log errors for debugging:
import os
import logging
import openai

logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)

client = openai.OpenAI(
    api_key=os.environ["AURIKO_API_KEY"],
    base_url="https://api.auriko.ai/v1",
)

try:
    response = client.chat.completions.create(
        model="gpt-4o",
        messages=[{"role": "user", "content": "Hello!"}],
    )
except openai.APIStatusError as e:
    logger.exception("Chat completion failed", extra={
        "error_type": type(e).__name__,
        "status_code": e.status_code,
        "request_id": e.response.headers.get("x-request-id"),
        "model": "gpt-4o",
    })
    raise

Map OpenAI SDK errors

If you use the OpenAI SDK directly (with base_url pointed at Auriko), you can convert OpenAI errors to typed Auriko errors using map_openai_error():
import os
import openai
from auriko import map_openai_error
from auriko.errors import RateLimitError, PermissionDeniedError

client = openai.OpenAI(
    api_key=os.environ["AURIKO_API_KEY"],
    base_url="https://api.auriko.ai/v1"
)

try:
    response = client.chat.completions.create(
        model="gpt-4o",
        messages=[{"role": "user", "content": "Hello!"}]
    )
except openai.APIStatusError as e:
    auriko_error = map_openai_error(e)
    if isinstance(auriko_error, RateLimitError):
        # budget_exhausted and insufficient_quota surface as RateLimitError too;
        # branch on auriko_error.code for code-level retry decisions.
        print(f"Rate limited. Retry after: {auriko_error.retry_after_seconds}s (code={auriko_error.code})")
    elif isinstance(auriko_error, PermissionDeniedError):
        print(f"Permission denied: {auriko_error.message}")
    else:
        raise auriko_error
You get typed error fields (status_code, code, response_headers) and fine-grained isinstance checks, even when using the OpenAI client. map_openai_error() is Python-only. TypeScript users should use the Auriko SDK directly for typed errors. See OpenAI Compatibility for OpenAI SDK error mapping.