Error Handling

Understand API error codes and how to handle them gracefully.

Error Response Format

CheapAI errors are not fully uniform across every endpoint, but you will usually receive either a simple service error or a structured error payload.

json
{
  "success": false,
  "error": "Human-readable error description"
}
json
{
  "error": {
    "message": "Human-readable error description",
    "type": "error_type"
  }
}

HTTP Status Codes

400Bad Request

Invalid request body, missing required fields, or invalid parameter values.

Fix: Check your request body matches the API spec.

401Unauthorized

Missing, invalid, or expired API key.

Fix: Verify the key and bearer header. Replace expired keys in the dashboard.

402Insufficient Balance

Your account balance is too low for this request.

Fix: Top up your balance at /billing.

403Forbidden

The key is not allowed to access a specific action or model.

Fix: Check the request and key configuration.

429Rate Limited

Too many requests or the API key reached its daily spend limit.

Fix: Back off and inspect the key settings in the dashboard.

500Internal Error

Something went wrong on our end.

Fix: Retry after a short delay. If persistent, check /status.

502Processing Error

The generation service returned an error while handling the request.

Fix: Retry after a short delay or try a different route if the issue persists.

503Service Unavailable

The service is temporarily overloaded or under maintenance.

Fix: Retry with exponential backoff. Check /status for maintenance windows.

Retry Strategy (Python)

python
import time
import requests

API_KEY = "sk_your_api_key"

def fetch_with_retry(url, method="GET", payload=None, max_retries=3):
    for attempt in range(max_retries):
        try:
            response = requests.request(
                method,
                url,
                headers={
                    "Authorization": f"Bearer {API_KEY}",
                    "Content-Type": "application/json",
                },
                json=payload,
            )
            if response.status_code < 400:
                return response.json()

            if response.status_code in (429, 500, 502, 503):
                wait = 2 ** attempt
                time.sleep(wait)
                continue

            response.raise_for_status()
        except requests.RequestException:
            time.sleep(2 ** attempt)

    raise RuntimeError("Max retries exceeded")

Retry Strategy (Node.js)

javascript
const API_KEY = 'sk_your_api_key';

async function fetchWithRetry(url, options = {}, maxRetries = 3) {
  for (let attempt = 0; attempt < maxRetries; attempt++) {
    try {
      const response = await fetch(url, {
        ...options,
        headers: {
          Authorization: `Bearer ${API_KEY}`,
          'Content-Type': 'application/json',
          ...(options.headers || {}),
        },
      });

      if (response.ok) {
        return await response.json();
      }

      if ([429, 500, 502, 503].includes(response.status)) {
        const wait = 2 ** attempt * 1000;
        await new Promise(r => setTimeout(r, wait));
      } else {
        throw new Error(`Request failed: ${response.status}`);
      }
    } catch (err) {
      const wait = 2 ** attempt * 1000;
      await new Promise(r => setTimeout(r, wait));
    }
  }

  throw new Error('Max retries exceeded');
}

Common Mistakes

  • Sending Authorization: sk-key instead of Authorization: Bearer sk-key
  • Polling the wrong task endpoint after creation
  • Assuming all generation routes are synchronous
  • Using an expired key or one that already hit its daily spend cap
  • Sending route-specific fields to the wrong route family (/v1, /v1m, /v1e, or /v1i)