Direct answer
This page explains how Australia-based teams use NextModel's OpenAI-compatible gateway. Every gateway error code, the JSON envelope, billing semantics, and retry guidance. It adds the practical steps, configuration notes, and common questions.
The error envelope
Every error the gateway generates is JSON the OpenAI-shaped SDKs can parse: an error object with code and message, plus a billing_status field, and an X-NextModel-Billing-Status response header. (The Anthropic-native /v1/messages ingress returns the Anthropic error envelope instead, with the same billing headers.) Use the code field for programmatic handling and the message for logs; treat any code not listed here as a plain failure and retry per the guidance at the end of this page.
HTTP/1.1 429 Too Many Requests
X-NextModel-Billing-Status: not_charged
{
"error": {
"code": "rate_limited",
"message": "Account rate limit exceeded."
},
"billing_status": "not_charged"
}Errors never bill — verified per request
A reservation is taken before the upstream call and settled only after the model's response is delivered in full. Every failure path — provider error, mid-stream failure, even your own client disconnect — rolls the reservation back, so a failed request costs nothing. The X-NextModel-Billing-Status header on every response tells you which happened: settled (delivered and charged), rolled_back (failed, nothing charged), or not_charged (rejected before any upstream call). Usage that a stream already delivered before a later failure would have been settled at actual tokens; in practice the gateway rolls back whenever the stream did not complete cleanly.
Authentication and account
Fix the key or the account state before retrying — these never resolve on their own.
| 401 · missing_api_key | No Authorization header. Send: Authorization: Bearer $NEXTMODEL_API_KEY |
| 401 · invalid_api_key | Key unknown, disabled, or deleted. Create a new key in the dashboard. |
| 403 · account_not_found | The key's account no longer exists. Contact support. |
| 402 · insufficient_credits | Prepaid credit check failed. Top up, then retry. |
| 404 · anthropic_ingress_disabled | Anthropic-native endpoints are disabled on this deployment. |
| 404 · embeddings_ingress_disabled | Embeddings ingress is disabled on this deployment. |
| 404 · tts_ingress_disabled | Text-to-speech ingress is disabled on this deployment. |
| 404 · transcription_ingress_disabled | Audio transcription is not open yet — the route exists but the deployment has not switched it on. |
Request validation
The request never reached a model. Fix the payload; do not retry as-is.
| 400 · invalid_request_body | Body is not valid JSON or has the wrong shape. |
| 400 · missing_message | messages array missing or empty. |
| 400 · missing_input | Input field missing (responses, embeddings, audio). |
| 400 · missing_prompt | Prompt field missing (image or audio endpoints). |
| 400 · model_not_supported | Model id is not in the live catalog. Fetch GET /v1/models and use an id from it. |
| 400 · prompt_too_long | Input exceeds the model's context window. |
| 400 · message_too_long | A single message exceeds the per-message limit. |
| 400 · n_too_large | The n (number of choices) parameter exceeds the allowed maximum. |
| 400 · invalid_image_url | Image URL failed fetch or validation (multimodal input). |
| 400 · unsupported_video_rate | Requested frame rate is not supported for the video model. |
| 400 · audio_file_required | Audio endpoint needs a file upload. |
| 400 · speech_input_too_long | TTS input text exceeds the character limit. |
| 413 · request_body_too_large | Request body exceeds the size cap. Trim attachments or context. |
| 409 · idempotency_replay_conflict | Same idempotency key reused with a different request body. Use a fresh key per distinct request. |
Rate limits
Back off and retry. Respect the Retry-After header when present.
| 429 · rate_limited | Generic rate limit (Anthropic-ingress paths report this code too). |
| 429 · account_rate_limited | Per-account request rate exceeded — slow down across all keys of the account. |
| 429 · api_key_rate_limited | This key exceeded its own per-minute limit. |
Upstream and platform availability
Transient by nature — safe to retry with exponential backoff. If a 503 persists across minutes, check the status page before filing a report.
| upstream_error (provider's own status) | The provider returned a non-2xx; its status and message are relayed under this code. |
| 502 · egress_translation_failed | Provider response could not be translated to the ingress protocol. |
| 503 · channel_retries_exhausted | Every channel for the model failed; routing gave up. Retry after a delay. |
| 503 · provider_network_error | Network failure while calling the provider. |
| 503 · gateway_not_ready | Gateway storage or upstream is still initializing. |
| 503 · media_busy | Image generation is at its concurrency cap. Honor Retry-After and retry. |
| 503 · storage_not_configured / billing_store_unavailable | Gateway storage hiccup — retry. |
| 500 · internal_error | Unexpected gateway fault. Retry once, then report with the request id. |
| 500 · council_orchestration_failed | A council run failed mid-quorum. Retry; partial calls are rolled back. |
| 404 · job_not_found | Video job id unknown or already expired. |
| 404 · not_found | Unknown API path. Check the path against this docs section. |
| 405 · method_not_allowed | Wrong HTTP verb; the Allow header lists what the path accepts. |
| 501 · protocol_runtime_not_routed | Vendor-native protocol paths (gemini/mistral/cohere/dashscope/bedrock) are not open yet — call the same model through the OpenAI-compatible endpoints. |
Retry guidance
Retry 429 and 5xx with exponential backoff and jitter, up to a small maximum; honor the Retry-After header when it is present. Never blindly retry 4xx — validation and auth errors fail identically forever. Requests accept an idempotency_key field in the JSON body: replaying the same request under the same key returns the original result instead of charging twice, and reusing a key with a different body is the 409 conflict above. When contacting support, include the request id, timestamp, model, and the error code — never the API key itself.