API
Error Handling
AICredits error codes, formats, and retry guidance. HTTP 400–503 reference table with retry matrix and exponential backoff examples.
Use this page with an AI assistant
Opens a new chat with this docs URL and the correct AICredits base URLs.
AICredits returns errors in an OpenAI-compatible format. Here's how to handle them.
Error Format
All errors are returned as JSON with a consistent structure:
{
"error": {
"message": "Human-readable description of the error",
"type": "error_type",
"code": 400
}
}Error Codes
| Status | Type | Description |
|---|---|---|
400 | invalid_request_error | Malformed request body, missing required fields, validation failure |
401 | authentication_error | Invalid, missing, or deactivated API key |
402 | insufficient_funds | Wallet balance too low or API key budget exceeded |
403 | forbidden | Account deactivated or API key expired |
413 | request_too_large | Request body exceeds 10MB limit |
429 | rate_limit_error | RPM limit or concurrency limit exceeded |
500 | internal_server_error | Unexpected server error; safe to retry with exponential backoff |
502 | upstream_error | All providers in the fallback chain failed |
503 | service_unavailable | No providers configured for the requested model |
504 | gateway_timeout | Provider response timed out; retry-able |
402 vs 403: A 402 means you have insufficient funds (add credits). A 403 means your account or key is disabled (contact support or check your key settings).
Retry Strategy
Not all errors should be retried. Here's a guide:
| Status | Retry? | Action |
|---|---|---|
400 | No | Fix the request payload |
401 | No | Check/rotate your API key |
402 | No | Add credits to your wallet |
429 | Yes | Exponential backoff with jitter |
500 | Yes | Retry with exponential backoff |
502 | Yes | Retry after short delay (provider issue) |
503 | No | Use a different model |
504 | Yes | Retry after short delay (timeout) |
Example implementation with exponential backoff:
import time
import random
from openai import OpenAI, APIError, RateLimitError
client = OpenAI(
base_url="https://api.aicredits.in/v1",
api_key="sk-your-key-here",
)
RETRYABLE_CODES = {429, 500, 502, 504}
def make_request(messages, max_retries=5):
for attempt in range(max_retries):
try:
return client.chat.completions.create(
model="openai/gpt-4o-mini",
messages=messages,
)
except APIError as e:
if e.status_code not in RETRYABLE_CODES:
raise # Don't retry non-retryable errors
if attempt == max_retries - 1:
raise # Exhausted retries
wait = (2 ** attempt) + random.uniform(0, 1)
print(f"Error {e.status_code}. Retrying in {wait:.1f}s...")
time.sleep(wait)import OpenAI from "openai";
const client = new OpenAI({
baseURL: "https://api.aicredits.in/v1",
apiKey: "sk-your-key-here",
});
const RETRYABLE_CODES = new Set([429, 500, 502, 504]);
async function makeRequest(
messages: OpenAI.ChatCompletionMessageParam[],
maxRetries = 5,
) {
for (let attempt = 0; attempt < maxRetries; attempt++) {
try {
return await client.chat.completions.create({
model: "openai/gpt-4o-mini",
messages,
});
} catch (error: any) {
const status = error?.status;
if (!RETRYABLE_CODES.has(status) || attempt === maxRetries - 1) {
throw error;
}
const wait = 2 ** attempt + Math.random();
console.log(`Error ${status}. Retrying in ${wait.toFixed(1)}s...`);
await new Promise((r) => setTimeout(r, wait * 1000));
}
}
}Guardrails Errors
When guardrails are enabled, requests may be rejected for policy violations:
- Blocked keywords: The request contains prohibited terms. Returns 400.
- PII masking: When enabled, personally identifiable information is automatically masked before being sent to the LLM provider. No error is returned — the request proceeds with masked content.
{
"error": {
"message": "Request blocked: contains prohibited content",
"type": "invalid_request_error",
"code": 400
}
}