OpenModelOpenModel
API Reference

Errors

Error response format and common error codes

Error Response Format

When an API request fails, OpenModel returns a JSON error response with the following structure:

Web API Errors

All /web/v1 endpoints return errors in OpenModel's standard format:

{
  "success": false,
  "data": null,
  "error": {
    "code": "UNAUTHORIZED",
    "msg": "API key is invalid or has been revoked",
    "detail": "optional additional detail"
  }
}
FieldTypeDescription
successbooleanAlways false for error responses.
datanullAlways null for error responses.
error.codestringA string error code for programmatic error handling (e.g., "BAD_REQUEST", "UNAUTHORIZED").
error.msgstringA human-readable error message describing what went wrong.
error.detailstringOptional additional detail (e.g., validation error specifics). Omitted when empty.

Proxy API Errors

Proxy endpoints (/v1/responses, /v1/messages, /v1beta/models/*) return errors in the format matching the requested API, so that SDK error handling works as expected.

OpenAI format (/v1/responses):

{
  "error": {
    "message": "Invalid API key provided",
    "type": "invalid_request_error",
    "code": "invalid_api_key"
  }
}

Anthropic format (/v1/messages):

{
  "type": "error",
  "error": {
    "type": "authentication_error",
    "message": "Invalid API key provided"
  }
}

Gemini format (/v1beta/models/*):

{
  "error": {
    "code": 401,
    "message": "Invalid API key provided",
    "status": "UNAUTHENTICATED"
  }
}

Error Codes

Error codes are string identifiers used in the error.code field of Web API responses.

Common Errors

CodeHTTP StatusDescription
BAD_REQUEST400The request body is malformed or missing required fields.
UNAUTHORIZED401Authentication failed — invalid or missing credentials.
FORBIDDEN403Permission denied — insufficient access rights.
NOT_FOUND404The requested endpoint does not exist.
METHOD_NOT_ALLOWED405The HTTP method is not supported for this endpoint.
CONFLICT409A conflict occurred (e.g., concurrent modification).
TOO_MANY_REQUESTS429Rate limit exceeded. Wait and retry with exponential backoff.
INTERNAL_ERROR500An unexpected internal error occurred.
SERVICE_UNAVAIL503The service is temporarily unavailable.
CONFIG_NOT_READY503A required system configuration is not yet initialized.

Authentication Errors

CodeHTTP StatusDescription
INVALID_TOKEN401The access token is invalid or malformed.
TOKEN_EXPIRED401The access token has expired. Use the refresh token to obtain a new one.
INVALID_CREDENTIALS401The provided email or password is incorrect.
PASSWORD_NOT_SET401No password has been set for this account (e.g., OAuth-only accounts).

Resource Errors

CodeHTTP StatusDescription
RESOURCE_NOT_FOUND404The requested resource (model, API key, user, etc.) does not exist.
RESOURCE_EXISTS409A resource with the same identifier already exists.
MODEL_IN_USE409The model cannot be deleted because it is bound to active channels.
PROVIDER_HAS_MODELS409The provider cannot be deleted because it still has associated models.

Validation Errors

CodeHTTP StatusDescription
VALIDATION_FAILED422Request parameter validation failed. Check the error.detail field for specifics.
INVALID_BODY400The request body is invalid or cannot be parsed.
INVALID_QUERY400One or more query parameters are invalid.
INVALID_PARAMETER400A specific parameter value is invalid.
MISSING_PARAMETER400A required parameter is missing.
EMPTY_UPDATE400The update request contains no fields to modify.
PAYLOAD_TOO_LARGE413The request payload exceeds the maximum allowed size.

Business Errors

CodeHTTP StatusDescription
INSUFFICIENT_BALANCE400 (Web API) / 402 (Proxy)Your account balance is too low to process this request. Top up your balance in the Console. Web API endpoints return HTTP 400; proxy endpoints (/v1/responses, /v1/messages, /v1beta/models/*) return HTTP 402.
SELF_OPERATION400You cannot perform this operation on your own account (e.g., an admin cannot delete themselves).
CAPTCHA_FAILED400The CAPTCHA verification failed. Please try again.
OTP_INVALID400The provided one-time password (OTP) code is invalid or expired.

Proxy Gateway Errors

When using the proxy endpoints (/v1/responses, /v1/messages, /v1beta/models/*), errors are returned in the provider-specific format rather than the standard Web API format. The HTTP status codes indicate the error type:

HTTP StatusMeaningOpenAI Error TypeAnthropic Error TypeGemini Error Status
400Bad requestinvalid_request_errorinvalid_request_errorINVALID_ARGUMENT
401Invalid API keyinvalid_request_errorauthentication_errorUNAUTHENTICATED
402Insufficient balancebilling_errorbilling_errorRESOURCE_EXHAUSTED
403Quota exceededinvalid_request_errorpermission_errorPERMISSION_DENIED
404Not foundinvalid_request_errornot_found_errorNOT_FOUND
429Rate limit exceededrate_limit_errorrate_limit_errorRESOURCE_EXHAUSTED
5xxServer errorapi_errorapi_errorINTERNAL

HTTP Status Codes

OpenModel uses standard HTTP status codes:

StatusMeaning
200OK -- Request succeeded.
400Bad Request -- Invalid request parameters.
401Unauthorized -- Invalid or missing API key.
402Payment Required -- Insufficient balance.
403Forbidden -- Permission denied.
404Not Found -- Resource does not exist.
405Method Not Allowed -- HTTP method not supported for this endpoint.
409Conflict -- Resource conflict (e.g., duplicate or in use).
413Payload Too Large -- Request body exceeds the size limit.
422Unprocessable Entity -- Validation failed.
429Too Many Requests -- Rate limit exceeded.
500Internal Server Error -- Unexpected server error.
502Bad Gateway -- Upstream provider error.
504Gateway Timeout -- Upstream provider timeout.

Handling Errors

Retry Strategy

For transient errors (429, 500, 502, 503, 504), implement exponential backoff with jitter:

import time
import random
from openai import OpenAI, APIError, RateLimitError

client = OpenAI(
    base_url="https://api.openmodel.ai/v1",
    api_key="your-api-key",
)

def create_with_retry(max_retries=3):
    for attempt in range(max_retries):
        try:
            return client.responses.create(
                model="gpt-5.4",
                input="Hello, world!",
            )
        except RateLimitError:
            if attempt == max_retries - 1:
                raise
            wait = (2 ** attempt) + random.random()
            print(f"Rate limited, retrying in {wait:.1f}s...")
            time.sleep(wait)
        except APIError as e:
            if e.status_code in (500, 502, 503, 504) and attempt < max_retries - 1:
                wait = (2 ** attempt) + random.random()
                print(f"Provider error, retrying in {wait:.1f}s...")
                time.sleep(wait)
            else:
                raise

response = create_with_retry()

Best Practices

  • Check error codes programmatically -- Use error.code (Web API) or the format-specific error types (Proxy API) for control flow, not the human-readable message.
  • Implement exponential backoff -- For rate limits (429) and server errors (500, 502, 503, 504), wait with increasing delays between retries.
  • Set reasonable timeouts -- Configure client-side timeouts to handle slow upstream providers gracefully.
  • Monitor your usage -- Use the Dashboard to track your API key usage and set up alerts before hitting rate limits or running out of balance.
  • Log error responses -- Record the full error response for debugging purposes, especially for intermittent issues.

On this page