Account
Errors
Every error code the api14 gateway returns, what causes it, how the OpenAI error shape is structured and how to handle each failure in code.
Errors use the OpenAI error shape, so the official SDKs turn them into their normal exceptions (APIError, RateLimitError, AuthenticationError and so on). Branch on code; message is a human-readable explanation in English.
{
"error": {
"message": "This request may cost up to $0.0123 but your balance is $0.0040. Add funds at /pricing.",
"type": "insufficient_quota",
"code": "insufficient_balance"
}
}
Failed requests are not charged. Any response with a 4xx or 5xx status costs nothing.
Gateway error codes
| Status | code | type | Meaning |
|---|---|---|---|
| 400 | model_required | invalid_request_error | The model field is missing. |
| 400 | invalid_json | invalid_request_error | The body is not a JSON object. |
| 400 | invalid_body | invalid_request_error | The multipart body could not be read. |
| 400 | max_tokens_too_large | invalid_request_error | A playground trial request asked for too many output tokens. |
| 401 | invalid_api_key | authentication_error | The key is missing, malformed or revoked. |
| 402 | insufficient_balance | insufficient_quota | Your USD balance is $0 or below the estimated maximum cost of the request (input, output cap, images or video duration). The request is not sent. |
| 403 | model_not_allowed | permission_error | The key's model allowlist does not include this model. |
| 403 | plan_required | permission_error | Your plan does not include this model category. |
| 404 | model_not_found | not_found_error | The model id is unknown, disabled or removed. |
| 404 | not_found | not_found_error | Unknown endpoint, or a video job or generation that is not yours. |
| 413 | payload_too_large | invalid_request_error | The request body exceeds the size limit (25 MB by default). |
| 429 | rate_limited | rate_limit_error | Requests per minute exceeded. Comes with Retry-After: 60. |
| 409 | idempotency_conflict | api_error | A request with this Idempotency-Key was already sent. Use a new key to send another request. See Rate limits. |
| 429 | daily_limit_reached | rate_limit_error | The key reached its daily USD spend limit. |
| 403 | site_not_allowed | permission_error | Widgets only: the page's site is not in your allowed widget sites. See Widgets. |
| 429 | widget_daily_limit | rate_limit_error | Widgets only: the widget, or all widgets together, reached the daily USD spend limit. |
| 429 | visitor_daily_limit | rate_limit_error | Widgets only: this visitor reached the daily request limit set in Widget controls. |
| 502 | upstream_unavailable | api_error | The upstream provider could not be reached. |
| 4xx/502 | content_unavailable | varies | A video's content could not be fetched yet (status mirrors the upstream, 502 if none). |
| 503 | maintenance | service_unavailable | Maintenance mode, generation endpoints are paused, GET endpoints still work. |
| 503 | not_configured | service_unavailable | The gateway is not configured yet. |
Upstream errors
Errors returned by the upstream provider, for example an invalid parameter for a specific model, a context length overflow, a content-policy refusal or a provider's own 429, are passed through with their original status code and the same { error: {... } } shape.
What to do
| Status | Retry? | Action |
|---|---|---|
| 400 | No | Fix the request body. |
| 401 | No | Check the key and the Authorization: Bearer header. See Authentication. |
| 402 | No | Add funds or turn on auto top-up. |
| 403 | No | Use an allowed model, edit the key's allowlist, or upgrade your plan. |
| 404 | No | Check the model id on the models page. |
| 413 | No | Send a smaller body, or pass files by URL instead of base64. |
| 429 | Later | rate_limited: wait for Retry-After. daily_limit_reached: wait for the next UTC day or raise the key limit. See Rate limits. |
| 502 | Yes | Retry with backoff, or add model fallbacks. |
| 503 | Yes | Retry later. |
Handling errors in code
import OpenAI from 'openai'
const client = new OpenAI({ baseURL: 'https://api14.com/api/v1', apiKey: process.env.API14_API_KEY })
try {
await client.chat.completions.create({ model: 'openai/gpt-5-mini', messages: [{ role: 'user', content: 'Hi' }] })
} catch (err) {
if (err instanceof OpenAI.APIError) {
console.error(err.status, err.code, err.message)
if (err.code === 'insufficient_balance') {
// prompt the user to add funds
}
} else {
throw err
}
}
from openai import OpenAI, APIStatusError
client = OpenAI(base_url="https://api14.com/api/v1", api_key="sk-api14-...")
try:
client.chat.completions.create(model="openai/gpt-5-mini", messages=[{"role": "user", "content": "Hi"}])
except APIStatusError as e:
print(e.status_code, e.code, e.message)
Errors that occur after a stream has started arrive inside the stream. See Streaming.