Skip to main content

Error Response Format

All errors return a JSON object with this structure:
type ErrorResponse = {
  error: {
    message: string;
    type: string;
    code?: string;
    metadata?: Record<string, unknown>;
  };
};
The HTTP status code matches the error type. Request validation errors return non-200 status codes. Errors occurring during generation may be returned in the response body or as SSE events (for streaming).

HTTP Status Codes

400 Bad Request

Invalid request parameters, malformed JSON, or missing required fields.
{
  "error": {
    "message": "Invalid request: model is required",
    "type": "invalid_request_error"
  }
}
Common causes:
  • Missing required fields (model, messages)
  • Invalid parameter values (e.g., temperature > 2.0)
  • Malformed JSON
  • Invalid message format

401 Unauthorized

Invalid, expired, or missing API key.
{
  "error": {
    "message": "Authentication required",
    "type": "authentication_error"
  }
}

402 Payment Required

Insufficient credits or account balance.
{
  "error": {
    "message": "Insufficient credits",
    "type": "insufficient_quota_error"
  }
}

403 Forbidden

Content moderation failure. Input was flagged by safety systems.
{
  "error": {
    "message": "Content flagged by moderation",
    "type": "content_filter_error",
    "metadata": {
      "reasons": ["violence", "harassment"],
      "flagged_input": "...",
      "provider_name": "openai",
      "model_slug": "gpt-5-mini"
    }
  }
}

408 Request Timeout

Request exceeded timeout limit.
{
  "error": {
    "message": "Request timeout",
    "type": "timeout_error"
  }
}

429 Too Many Requests

Rate limit exceeded.
{
  "error": {
    "message": "Rate limit exceeded",
    "type": "rate_limit_error"
  }
}
Check rate limits via GET /v1/key. See Limits documentation.

502 Bad Gateway

Model provider error or invalid response.
{
  "error": {
    "message": "Provider error",
    "type": "provider_error",
    "metadata": {
      "provider_name": "openai",
      "raw": {...}
    }
  }
}

503 Service Unavailable

No available provider meets routing requirements.
{
  "error": {
    "message": "No available provider",
    "type": "service_unavailable_error"
  }
}

Error Types

invalid_request_error

Request validation failed. Check parameter types and required fields.

authentication_error

API key authentication failed. Verify key is valid and active.

insufficient_quota_error

Account lacks sufficient credits. Add credits to continue.

rate_limit_error

Request rate exceeds limits. Implement exponential backoff.

content_filter_error

Input flagged by content moderation. Review input content.

timeout_error

Request exceeded timeout. Retry with shorter context or simpler request.

provider_error

Model provider returned an error. May be transient - retry request.

service_unavailable_error

No providers available matching routing requirements. Adjust provider preferences or retry later.

Error Metadata

Some errors include metadata for debugging:

Moderation Errors

type ModerationErrorMetadata = {
  reasons: string[];        // Flag categories
  flagged_input: string;     // Flagged content
  provider_name: string;     // Provider that flagged
  model_slug: string;        // Model identifier
};

Provider Errors

type ProviderErrorMetadata = {
  provider_name: string;     // Provider identifier
  raw: unknown;              // Raw provider response
};

Error Handling Examples

Python

import requests

try:
  response = requests.post(
    "https://api.anannas.ai/v1/chat/completions",
    headers={"Authorization": f"Bearer {api_key}"},
    json={"model": "openai/gpt-5-mini", "messages": [...]}
  )
  response.raise_for_status()
  data = response.json()
except requests.HTTPError as e:
  if e.response.status_code == 401:
    print("Invalid API key")
  elif e.response.status_code == 402:
    print("Insufficient credits")
  elif e.response.status_code == 429:
    print("Rate limit exceeded - retry after delay")
  else:
    error_data = e.response.json()
    print(f"Error: {error_data['error']['message']}")

TypeScript

try {
  const response = await fetch("https://api.anannas.ai/v1/chat/completions", {
    method: "POST",
    headers: {
      "Authorization": `Bearer ${apiKey}`,
      "Content-Type": "application/json",
    },
    body: JSON.stringify({
      model: "openai/gpt-5-mini",
      messages: [...]
    }),
  });

  if (!response.ok) {
    const error = await response.json();
    switch (response.status) {
      case 401:
        console.error("Invalid API key");
        break;
      case 402:
        console.error("Insufficient credits");
        break;
      case 429:
        console.error("Rate limit exceeded");
        break;
      default:
        console.error(error.error.message);
    }
    return;
  }

  const data = await response.json();
} catch (error) {
  console.error("Request failed:", error);
}

Retry Logic

Implement exponential backoff for transient errors:
import time
import random

def retry_with_backoff(func, max_retries=3):
  for attempt in range(max_retries):
    try:
      return func()
    except requests.HTTPError as e:
      if e.response.status_code in [429, 502, 503]:
        wait = (2 ** attempt) + random.uniform(0, 1)
        time.sleep(wait)
        continue
      raise
  raise Exception("Max retries exceeded")

Streaming Errors

In streaming responses, errors are sent as SSE events:
data: {"error": {"message": "Rate limit exceeded", "type": "rate_limit_error"}}
Parse and handle errors in your SSE event loop.

Best Practices

  1. Check Status Codes: Always verify HTTP status before parsing JSON
  2. Handle 429: Implement exponential backoff for rate limits
  3. Log Metadata: Include error metadata in logs for debugging
  4. User-Friendly Messages: Translate technical errors to user-friendly messages
  5. Retry Transient Errors: Retry 502, 503, and 408 errors
  6. Monitor Credits: Track 402 errors and alert when credits are low

See Also