Docs Developer API Errors Errors The API error format, which follows OpenAI’s, the full list of codes with their status and what to do about each, and how to read errors with the SDKs.
API errors follow the OpenAI API format: the OpenAI SDKs read them with no extra setup. Every error has an HTTP status, a type , a stable code to test in your code, and a message in English meant for developers.
Example: insufficient balance Copy {
"error" : {
"message" : "insufficient credits" ,
"type" : "insufficient_quota" ,
"code" : "insufficient_credits" ,
"param" : null ,
"required_credits" : 5200 ,
"balance_credits" : 310
}
} Field Type Description message string A readable explanation, in English. Don’t test it in your code: it can change. type string The error family (see below). code string or null A precise, stable code. null for a few errors without a dedicated code (unreadable JSON body, malformed parameter). param string or null The parameter at fault, when there is one (model , messages , input …). other fields Some errors add details: required_credits , balance_credits , window , scope , held_credits , cap_credits , spent_credits .
type values:
type Statuses Meaning invalid_request_error 400, 404, 405, 409, 410, 411, 413, 422 The request needs fixing. authentication_error 401, 403 Key missing, refused, or used outside its rules. permission_error 403 Your organization’s rules refuse the request. insufficient_quota 402 Balance or spend cap. rate_limit_error 429 Too many requests for now: retry. server_error 500, 502, 503, 504 An outage on our side or the model’s: retry.
When an error carries a Retry-After header, wait that many seconds before retrying. An error returned by the chat model also carries the request’s X-Moon-Request-Id header.
import os
import openai
from openai import OpenAI
client = OpenAI (base_url = "https://api.realmoon.ai/v1" , api_key = os.environ[ "MOONAI_API_KEY" ])
try :
client . chat . completions . create (
model = "anthropic/claude-haiku-4.5" ,
messages = [{ "role" : "user" , "content" : "Hello" }],
)
except openai . APIStatusError as e :
print (e.status_code, e.type, e.code, e.param)
print (e.body) # the "error" object, with its extra fields
print (e.response.headers. get ( "retry-after" ))
if e . code == "insufficient_credits" :
print ( "Top up the workspace:" , e.body. get ( "required_credits" ), "credits needed" )
except openai . APIConnectionError :
print ( "Could not reach the server." ) import OpenAI from 'openai' ;
const client = new OpenAI ({ baseURL : 'https://api.realmoon.ai/v1' , apiKey : process . env . MOONAI_API_KEY });
try {
await client . chat . completions .create ({
model : 'anthropic/claude-haiku-4.5' ,
messages : [{ role : 'user' , content : 'Hello' }] ,
});
} catch (err) {
if (err instanceof OpenAI . APIError ) {
console .log ( err .status , err .type , err .code , err .param);
console .log ( err .error); // the "error" object, with its extra fields
if ( err .code === 'insufficient_credits' ) {
console .log ( 'Top up the workspace:' , err . error ?.required_credits , 'credits needed' );
}
} else {
throw err;
}
} curl -i https://api.realmoon.ai/v1/chat/completions \
-H "Authorization: Bearer sk-moon-wrong-key" \
-H "Content-Type: application/json" \
-d '{"model": "anthropic/claude-haiku-4.5", "messages": [{"role": "user", "content": "Hello"}]}' SDK retries
The OpenAI SDKs automatically retry 408, 409, 429 and 5xx errors (twice by default), following Retry-After . Each retry is a new request, with its own hold and its own cost: see Limits .
These errors can happen on any endpoint.
HTTP code Meaning What to do 401 invalid_api_key Key missing, unknown, revoked or expired, workspace deleted, or workspace owner suspended. Check the Authorization: Bearer sk-moon-... header and the key’s status in the “API keys” tab. 403 ip_not_allowed The calling address is not in the key’s IP allowlist. Add the address to a new key, or call from an allowed server. 403 missing_scope The key does not have the inference scope. Create a key from the portal. 403 org_policy Your organization’s rules refuse the API or this model (type: permission_error ). Choose an allowed model, or check with the organization’s administrator. 404 null not found : the API is not enabled for this workspace.Contact support. 429 rate_limit_exceeded More than 600 requests per minute with this key, too many refused requests with this key, or too many authentication failures from this address. Wait for Retry-After . See Limits . 503 service_unavailable Authentication is temporarily unavailable. Retry after Retry-After (5 seconds). 503 org_policy_unavailable Your organization’s rules are temporarily unreadable. Try again in a moment.
HTTP code Meaning What to do 400 null invalid JSON body , body must be a JSON object , invalid base64, unreadable multipart form, or a malformed value (param names it).Fix the request body. 400 missing_required_parameter A required parameter is missing; param names it. Add it. 400 invalid_value , invalid_request A URL parameter of the wrong type (for example limit=abc ), or a malformed request. Fix the value. 400 unknown_parameter A parameter unknown to a media endpoint. Remove it. 400 unsupported_parameter A parameter rejected by the API or by the model; param names it when possible. Remove it or change its value. 400 unsupported_value A value outside what the model accepts (size, duration, format…). See the endpoint’s page. 400 unsupported_content Message content not accepted (unknown part type, file by ID, video…). See Messages . 400 n_not_supported n is not 1.Send one request per response you want. 400 string_above_max_length Text longer than the endpoint’s limit. Shorten it. 404 unknown_url Invalid URL (POST / v1/ ...) : this endpoint does not exist.Check the path; the list is in the overview . 405 method_not_allowed An HTTP method this path does not support. Use the documented method. 411 length_required Multipart upload without a Content-Length header. Let your client compute the size (no chunked upload). 413 request_too_large , file_too_large Body or file too large. See the sizes in Limits .
HTTP code Meaning What to do 404 model_not_found The model does not exist, is not public, or does not serve this endpoint. Read GET / v1/ models (with ?type= for media). 400 or 413 context_length_exceeded The request is too long for the model’s context window (param: "messages" ). Shorten the messages or lower max_tokens . 400 or 413 no_available_route The model cannot serve this request as is (tool, format or size not supported). Switch models or simplify the request. 400 or 413 invalid_request The model rejected the request, with an explanation. Fix the request based on the message. 400 invalid_request_error A media model rejected the request without further detail. Change the parameters or the model. 400 content_policy_violation The model’s safety system rejected the requested content (images, videos). Rephrase the request. 503 pricing_unavailable The model’s price is temporarily unknown: the request is refused rather than billed incorrectly. Try again a little later.
Model refusals (400, 413, 429) are passed on without the provider’s name, links or internal IDs.
HTTP code Meaning What to do 402 insufficient_credits The balance does not cover the request’s hold, or it is negative. required_credits and balance_credits give the amounts. Top up the workspace, or shrink the hold with max_tokens . See Costs . 402 spend_cap_exceeded A spend cap has been reached. scope is workspace or key , window is hour , day or month . Wait for the window to slide, or raise the cap. 402 hold_exceeds_cap The hold of this single request exceeds what the cap leaves. Details: required_credits , cap_credits , spent_credits , scope , window . Lower max_tokens , or raise the cap. 429 credits_held_in_progress The balance or the cap would be enough, but in-flight requests are holding the rest (held_credits ). Retry after Retry-After (2 seconds); set max_tokens when many requests run at the same time. 503 billing_unavailable The balance could not be read or charged. Try again later.
HTTP code Meaning What to do 429 rate_limit_exceeded The key’s rate limit, see Key and access . Wait for Retry-After . 429 model_rate_limited The chat model is getting too many requests right now. Nothing is charged. Wait for Retry-After , or switch models. 429 too_many_concurrent Too many media requests in flight for this workspace. Wait for a request to finish (Retry-After : 5 seconds, 30 for videos). 429 upstream_rate_limited The media model is overloaded. Wait for Retry-After (10 seconds).
HTTP code Meaning What to do 413 moon_blur_payload_too_large A text exceeds 500,000 characters, too long to be scanned (param: "messages" ). Nothing is sent or charged. Split the text, or turn off Moon Blur on the key. 503 moon_blur_unavailable Personal data protection could not be applied: the request is not sent to the model and nothing is charged. Retry after Retry-After (5 seconds).
See Privacy .
HTTP code Meaning What to do 502 (or another 5xx) upstream_error The model failed, returned an unreadable response, or could not be reached. Retry, or switch models. 503 upstream_unavailable or null The model or the media service is temporarily unreachable. Try again later. 504 upstream_timeout The model did not respond in time. For chat, the hold is kept (see Settlement ). Retry with a shorter request, or with streaming.
Once the stream has started, the HTTP status has already been sent (200). A cut on the model side arrives as a final event:
Last event of an interrupted stream Copy { "error" : { "message" : "upstream stream interrupted" , "type" : "server_error" , "code" : "upstream_error" }} The SDKs raise it as an error during iteration. See Streaming .
code HTTP Endpoints Page audio_too_long 400 Transcription Audio billing_unavailable 503 All billed endpoints Credits and caps content_policy_violation 400 Images, videos Model context_length_exceeded 400, 413 Chat Chat completions credits_held_in_progress 429 All billed endpoints Credits and caps encrypted_document 400 OCR OCR file_too_large 413 Images, videos, transcription, OCR Request hold_exceeds_cap 402 All billed endpoints Credits and caps insufficient_credits 402 All billed endpoints Credits and caps invalid_api_key 401 All Key and access invalid_content_type 400 Transcription Audio invalid_document 400 OCR OCR invalid_image 400 Images, videos, OCR Images invalid_request 400, 413 Chat Model invalid_request_error 400 Media Model invalid_value 400 All Request ip_not_allowed 403 All Key and access job_not_recorded 503 Videos Videos length_required 411 Multipart uploads Request method_not_allowed 405 All Request missing_required_parameter 400 All Request missing_scope 403 All Key and access model_not_found 404 All that take a model Model model_rate_limited 429 Chat Too many requests moon_blur_payload_too_large 413 Chat, embeddings Moon Blur moon_blur_unavailable 503 Chat, embeddings Moon Blur n_not_supported 400 Chat Request no_available_route 400, 413 Chat Model ocr_busy 503 OCR OCR ocr_timeout 504 OCR OCR org_policy 403 All that take a model Key and access org_policy_unavailable 503 All that take a model , model list Key and access pricing_unavailable 503 Chat Model rate_limit_exceeded 429 All Key and access request_too_large 413 Media Request service_unavailable 503 All Key and access spend_cap_exceeded 402 All billed endpoints Credits and caps string_above_max_length 400 Images, videos, speech Request too_many_concurrent 429 Media Too many requests too_many_images 400 Image editing Images too_many_pages 400 OCR OCR unknown_parameter 400 Media Request unknown_url 404 All Request unreadable_document 422 OCR OCR unsupported_content 400 Chat Chat completions unsupported_format 400 Transcription, OCR Request unsupported_model 400 Image editing Images unsupported_parameter 400 All Request unsupported_value 400 Media Request upstream_error 502, other 5xx All that call a model Model outages and service upstream_rate_limited 429 Media Too many requests upstream_timeout 504 All that call a model Model outages and service upstream_unavailable 503 Media Model outages and service url_not_supported 400 OCR OCR video_expired 410 Video download Videos video_not_found 404 Video status and download Videos video_not_ready 409 Video download Videos
A failed video also carries an error.code in its object (generation_failed , content_policy_violation , timeout , not_found ): see The video object .