Error Handling
The Conduit API uses consistent error responses with machine-readable error codes to help you handle failures gracefully.
Error Response Format
All API errors return a JSON object with the following structure:
{
"error": {
"message": "Invalid API key",
"code": "API_KEY_INVALID",
"details": {},
"timestamp": "2026-03-09T12:00:00.000Z",
"requestId": "req_abc123"
}
}| Field | Type | Description |
|---|---|---|
| message | string | A human-readable description of the error |
| code | string | A machine-readable error code (e.g., API_KEY_INVALID) |
| details | object? | Optional additional context (e.g., field-level validation errors) |
| timestamp | string | ISO 8601 timestamp of when the error occurred |
| requestId | string | Unique request identifier for support and debugging |
The requestId is also returned in the X-Request-Id response header. Include it when contacting support.
HTTP Status Codes
The API uses standard HTTP status codes to indicate the outcome of a request.
| Status | Meaning | Retryable |
|---|---|---|
| 400 | Bad Request — Invalid parameters or malformed request body | No |
| 401 | Unauthorized — Missing or invalid API key | No |
| 402 | Payment Required — Insufficient account balance | No |
| 403 | Forbidden — Valid key but insufficient permissions | No |
| 404 | Not Found — Resource or endpoint does not exist | No |
| 409 | Conflict — Resource already exists or state conflict | No |
| 422 | Unprocessable Entity — Request understood but cannot be processed | No |
| 429 | Too Many Requests — Rate limit or spending limit exceeded | Yes |
| 500 | Internal Server Error — Unexpected server-side failure | Yes |
| 503 | Service Unavailable — Upstream service temporarily down | Yes |
| 504 | Gateway Timeout — Request to upstream service timed out | Yes |
Error Codes
The code field provides a specific, machine-readable identifier you can use to programmatically handle errors.
Authentication & Authorization
| Code | HTTP | Description |
|---|---|---|
| API_KEY_INVALID | 401 | The API key provided is not valid |
| API_KEY_EXPIRED | 401 | The API key has expired — generate a new one from your dashboard |
| AUTH_UNAUTHORIZED | 401 | Authentication is required but no valid credentials were provided |
| AUTH_FORBIDDEN | 403 | You do not have permission to perform this action |
Validation
| Code | HTTP | Description |
|---|---|---|
| VALIDATION_ERROR | 400 | Request body failed validation — check the details.fields object for specifics |
| BAD_REQUEST | 400 | The request is malformed or contains invalid parameters |
Validation errors include a details.fields object mapping field names to error messages:
{
"error": {
"message": "Validation failed",
"code": "VALIDATION_ERROR",
"details": {
"fields": {
"model": "Required",
"messages": "Expected array, received string"
}
},
"timestamp": "2026-03-09T12:00:00.000Z",
"requestId": "req_abc123"
}
}Billing
| Code | HTTP | Description |
|---|---|---|
| BILLING_INSUFFICIENT_FUNDS | 402 | Your account balance is too low — add credits from your dashboard to continue |
Rate Limiting
| Code | HTTP | Description |
|---|---|---|
| RATE_LIMIT_EXCEEDED | 429 | Too many requests — wait and retry with exponential backoff |
| API_KEY_LIMIT_EXCEEDED | 429 | This API key's spending limit has been reached — increase it in your dashboard |
Resource
| Code | HTTP | Description |
|---|---|---|
| NOT_FOUND | 404 | The requested resource does not exist |
| CHAT_MODEL_NOT_FOUND | 404 | The specified model does not exist or is not available |
Server
| Code | HTTP | Description |
|---|---|---|
| INTERNAL_SERVER_ERROR | 500 | An unexpected error occurred on the server |
| SERVICE_UNAVAILABLE | 503 | An upstream service is temporarily unavailable |
| SERVICE_TIMEOUT | 504 | The request timed out — safe to retry |
Handling Errors
We recommend implementing retry logic with exponential backoff for retryable errors (429, 500, 503, 504).
JavaScript / TypeScript
async function callConduit(messages, retries = 3) {
for (let attempt = 0; attempt < retries; attempt++) {
const res = await fetch("https://api.conduit.im/v1/chat/completions", {
method: "POST",
headers: {
"Authorization": `Bearer ${API_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify({ model: "gpt-4", messages }),
});
if (res.ok) return await res.json();
const { error } = await res.json();
console.error(`[${error.code}] ${error.message} (request: ${error.requestId})`);
// Don't retry client errors (except rate limits)
if (res.status < 500 && res.status !== 429) {
throw new Error(error.message);
}
// Exponential backoff: 1s, 2s, 4s
await new Promise((r) => setTimeout(r, 1000 * 2 ** attempt));
}
throw new Error("Max retries exceeded");
}Python
import time, requests
def call_conduit(messages, retries=3):
for attempt in range(retries):
res = requests.post(
"https://api.conduit.im/v1/chat/completions",
headers={
"Authorization": f"Bearer {API_KEY}",
"Content-Type": "application/json",
},
json={"model": "gpt-4", "messages": messages},
)
if res.ok:
return res.json()
error = res.json()["error"]
print(f"[{error['code']}] {error['message']} (request: {error['requestId']})")
# Don't retry client errors (except rate limits)
if res.status_code < 500 and res.status_code != 429:
raise Exception(error["message"])
# Exponential backoff: 1s, 2s, 4s
time.sleep(2 ** attempt)
raise Exception("Max retries exceeded")Important: Never retry
401 or 402 errors automatically. These require user action — check your API key or add funds to your account.Next Steps
- Authentication — Learn how to authenticate your API requests
- Chat Completions API — Start making requests to the Chat Completions endpoint
- Quickstart Guide — Get up and running in minutes