Errors
Error codes, formats, and handling for the Sansa API
Error Formats
OpenAI-compatible endpoints such as Chat Completions, Responses, and Transcriptions use Sansa's OpenAI-shaped error object. If your code already handles OpenAI errors, it can handle these endpoints unchanged.
{
"error": {
"code": "invalid_request",
"message": "Human-readable description of what went wrong.",
"request_id": "a3f2c1d0-8b4e-4f9a-b2d1-7c5e3a1f0e9b"
}
}The Anthropic-compatible Messages endpoints use Anthropic's error envelope instead:
{
"type": "error",
"error": {
"type": "invalid_request_error",
"message": "What went wrong and how to fix it."
},
"request_id": "req_..."
}This applies to /v1/messages, /v1/messages/count_tokens, /v1/mcp_servers, and Claude Code model-discovery errors. See Messages errors for its status mapping, request IDs, and terminal SSE error events.
OpenAI-compatible error fields
| Field | Type | Description |
|---|---|---|
code | string | Machine-readable error identifier. See the reference below. |
message | string | What went wrong and how to fix it. |
request_id | string | Present on errors that occur after the request is accepted. Use this when contacting support. Not present on auth errors. |
HTTP Status Codes
| Status | Meaning |
|---|---|
400 | Bad request: invalid body, unsupported parameter, or value out of range |
401 | Unauthorized: missing or invalid API key |
402 | Payment required: insufficient credits or spend cap exceeded |
403 | Forbidden: key scope, model policy, or abuse policy rejected the request |
404 | Not found: route or optional capability is unavailable |
413 | Request too large |
429 | Rate limited: too many requests |
500 / 502 | Internal or upstream provider error |
503 | Upstream provider unavailable |
504 | Upstream timeout |
529 | Upstream provider overloaded |
Error Code Reference
invalid_request
HTTP 400. The request body is structurally invalid or a value is out of range.
Common causes:
messagesis missing or empty- A field type is wrong (e.g.,
content: 123instead of a string) temperatureis not between 0 and 2top_pis not between 0 and 1frequency_penaltyorpresence_penaltyis not between -2 and 2reasoning.effortisn't a value the endpoint acceptsreasoning_effort: "none"onsansa-autowhen no model can serve the request without reasoningmax_tokensormax_completion_tokensis less than 1stopcontains more than 4 sequencesmetadatahas more than 16 key-value pairs, a key over 64 characters, or a value over 512 charactersresponse_format.typeis"json_schema"but nojson_schemaobject was provided- A
toolmessage is missingtool_call_id - Malformed JSON body
- On
/v1/audio/transcriptions,sansaormetadataform fields that are not valid JSON objects
invalid_model
HTTP 400. The model value isn't "sansa-auto", null, or a known model ID from the catalog.
Pass "sansa-auto" to use intelligent routing, or a specific model ID (e.g. "openai/gpt-5.4") to call it directly. The full list of supported IDs lives on the Models page in your dashboard. See Models for details.
invalid_call_name
HTTP 400. A call_name value is invalid: empty, whitespace-only, or exceeds 64 characters. Applies to sansa.call_name, metadata.call_name, and the top-level call_name field on transcriptions.
invalid_end_user_id
HTTP 400. An end_user_id value is invalid: empty, whitespace-only, or exceeds 512 characters. Applies to sansa.end_user_id and metadata.end_user_id on chat completions and transcriptions.
unsupported_parameter
HTTP 400. A parameter was provided that Sansa does not support.
| Parameter | Why rejected |
|---|---|
audio | Audio output is not supported |
modalities (with "audio") | Only text modality is supported |
web_search_options | Web search is not supported |
n > 1 | Only one completion per request |
functions | Deprecated; use tools |
function_call | Deprecated; use tool_choice |
logprobs, top_logprobs | Log probabilities aren't returned yet |
On sansa-auto, some fields also return unsupported_parameter; see What sansa-auto accepts.
unauthorized
HTTP 401. The API key is missing, malformed, or invalid.
- No
Authorizationheader - Missing
Bearerprefix (must beAuthorization: Bearer <api-key>) - API key is revoked or does not exist
insufficient_credits
HTTP 402. Your account balance is zero or insufficient for the request.
Add credits from your dashboard.
SDK note: HTTP 402 is not part of OpenAI's standard error set. The OpenAI SDK surfaces it as a generic APIStatusError. Catch it by checking error.status === 402 or the code field.
spend_cap_exceeded
HTTP 402. The request would exceed a configured spend cap in block mode.
The message names the cap's scope and window, for example This request would exceed the 30-day spend cap for this organization. See Spend caps.
This isn't running out of credits: check error.code (spend_cap_exceeded vs insufficient_credits).
rate_limit_exceeded
HTTP 429. Your API key has exceeded its rate limit, or the upstream provider returned a rate limit error. Retry with exponential backoff.
model_rejected_request
HTTP 400. The request passed Sansa's local validation but was rejected by the upstream model. Do not retry unchanged. If the guidance does not identify a fix, contact support with the request_id.
provider_unavailable
HTTP 503. The upstream model is temporarily unavailable. Retry with backoff.
model_error
HTTP 502. The upstream model returned a server-side error. Retry with backoff.
invalid_model_response
HTTP 502. The model answered with output Sansa couldn't read. Retry the request.
model_timeout
HTTP 504. The model stopped responding, or never started. Retry the request.
invalid_file_format
HTTP 400. The uploaded audio file has an unsupported format. Supported formats for /v1/audio/transcriptions: mp3, wav, m4a, webm, ogg, flac, opus.
file_too_large
HTTP 400. The uploaded audio file exceeds the maximum allowed size (25 MB).
unsupported_response_format
HTTP 400. The response_format value is not supported by the transcriptions endpoint.
internal_error
HTTP 500. An unexpected error in the Sansa API. Contact support with the request_id.
Errors in Streaming Responses
Pre-stream errors
If validation, auth, or credits fail before streaming begins, the response is a normal JSON error with the endpoint's error format and status code, not an SSE stream.
HTTP/1.1 400 Bad Request
Content-Type: application/json
{"error":{"code":"invalid_request","message":"..."}}Chat Completions mid-stream errors
See Streaming: the error arrives in a data: event with finish_reason: "error", followed by [DONE].
Responses mid-stream errors
A failure after streaming begins arrives as a terminal response.failed event. See Responses streaming.
Messages mid-stream errors
A failure after streaming begins arrives as a terminal event: error. See Messages streaming.
Handling OpenAI-compatible Errors
Python
import openai
client = openai.OpenAI(
api_key="sk-sansa-...",
base_url="https://api.sansaml.com/v1",
)
try:
response = client.chat.completions.create(
model="sansa-auto",
messages=[{"role": "user", "content": "Hello"}],
)
except openai.AuthenticationError as e:
# 401
print(e.body["error"]["message"])
except openai.BadRequestError as e:
# 400
print(e.body["error"]["code"], e.body["error"]["message"])
except openai.RateLimitError as e:
# 429
print("Retry after a short delay")
except openai.APIStatusError as e:
# 402, 500, etc.
request_id = e.body.get("error", {}).get("request_id")
print(f"Error {e.status_code}. Request ID: {request_id}")TypeScript
import OpenAI from "openai";
const client = new OpenAI({
apiKey: "sk-sansa-...",
baseURL: "https://api.sansaml.com/v1",
});
try {
const response = await client.chat.completions.create({
model: "sansa-auto",
messages: [{ role: "user", content: "Hello" }],
});
} catch (err) {
if (err instanceof OpenAI.AuthenticationError) {
console.error(err.error.message);
} else if (err instanceof OpenAI.BadRequestError) {
console.error(err.error.code, err.error.message);
} else if (err instanceof OpenAI.RateLimitError) {
console.error("Rate limited; retry with backoff");
} else if (err instanceof OpenAI.APIError) {
const requestId = (err.error as any)?.request_id;
console.error(`Error ${err.status}. Request ID: ${requestId}`);
}
}Retry Strategy
| Error code | Retryable? | Action |
|---|---|---|
invalid_request | No | Fix the request |
invalid_model | No | Use sansa-auto or a valid model ID |
invalid_call_name | No | Fix the call_name value |
invalid_end_user_id | No | Fix the end_user_id value |
unsupported_parameter | No | Remove the unsupported field |
invalid_file_format | No | Use a supported audio format |
file_too_large | No | Reduce file size below 25 MB |
unsupported_response_format | No | Use a supported response format |
unauthorized | No | Check your API key |
insufficient_credits | No | Add credits, then retry |
spend_cap_exceeded | No | Raise the cap or wait for the rolling window to pass |
rate_limit_exceeded | Yes | Exponential backoff |
model_rejected_request | No | Contact support |
provider_unavailable | Yes | Exponential backoff |
model_error | Yes | Exponential backoff |
invalid_model_response | Yes | Retry the request |
model_timeout | Yes | Retry the request |
internal_error | Rarely | Retry once; contact support if it persists |