Errors
All error responses follow the same JSON format:
{
"error": {
"message": "Description of what went wrong"
}
}
HTTP status codes
| Status | Meaning | When |
|---|---|---|
400 |
Bad Request | Invalid request parameters (missing fields, wrong types), or a rejection forwarded from the provider |
401 |
Unauthorized | Missing, invalid, or expired API key / JWT token |
402 |
Payment Required | Valid authentication but insufficient credit balance |
404 |
Not Found | Requested resource does not exist (e.g., unknown model) |
422 |
Unprocessable Entity | Unsupported parameter or invalid field structure |
503 |
Service Unavailable | Upstream provider error (timeout, rate limit, connection failure) |
Who validates the model
Quantized does not keep a gate in front of the providers. A model id we cannot resolve
in the catalog is forwarded to the provider exactly as you sent it, and the provider
decides whether it exists. The status code and the message you get back are the
provider’s, not ours.
This matters because the same mistake gets a different answer depending on who serves
the endpoint. On the two single-provider endpoints it is at least consistent:
POST /v1/aws-bedrock/embeddings {"model": "amazon.titan-embed-text-v99:0"}
400 The provided model identifier is invalid.
POST /v1/gemini/embeddings {"model": "gemini-embedding-9999"}
404 models/gemini-embedding-9999 is not found for API version v1beta, or is not
supported for embedContent.
Both are the same class of error. AWS calls it a 400, Google calls it a 404.
Where an endpoint has several eligible providers it is not stable even across repeated
calls, because an unresolved model gives the router nothing to route on. Eight identical
requests to POST /v1/chat/completions with {"model": "nonexistent-model"} produced
four wordings and two status codes, one from each of the four chat providers:
404 nonexistent-model is not a valid model ID
404 The model `nonexistent-model` does not exist or you do not have access to it.
404 model: nonexistent-model
400 The provided model identifier is invalid.
Treat any 4xx naming the model as “this model is not usable”. Do not match on message
text, do not assume 404, and do not expect two identical requests to fail identically.
Call GET /v1/models and match on id. That is the list of ids the
catalog resolves; anything else depends on the provider accepting it.
The router still answers for itself in two cases, because no provider could give a
useful reply: when your X-Quantized-Provider pin leaves no usable provider, and when
the model resolves but cannot serve the modality you asked for. Both are covered below.
Error types
Bad Request (400)
Returned when the request payload is invalid. The message describes the specific issue.
{
"error": {
"message": "field required: 'model'"
}
}
Model modality mismatch
A 400 is also returned when a chat-completion request contains a content part (image_url, input_audio, video_url) that no provider serving the model can accept. This check runs before the request reaches the provider.
{
"error": {
"message": "No available provider for model 'openai/gpt-4.1-nano' supports audio input"
}
}
The message names providers rather than the model because a model’s hosts can differ: one may accept video where another does not. The router skips a provider that cannot serve the request and only fails when every reachable one refuses.
The same check runs on /v1/images/generations for output modality:
{
"error": {
"message": "No available provider for model 'openai/gpt-4.1-nano' supports image output"
}
}
Pick a model that declares the required modality in input_modality / output_modality (see Models). file (PDF) parts are exempt from this check — OpenRouter’s universal PDF parser handles them on every model.
Provider pin with nothing behind it
Pinning X-Quantized-Provider to a provider that cannot serve the endpoint leaves the router with an empty pool, and it says so rather than silently ignoring your header:
{
"error": {
"message": "No provider available for endpoint 'chat_completions' under the current pins"
}
}
All request bodies use strict validation — unknown or unsupported fields are rejected with 422. This prevents typos from being silently ignored and ensures you only use documented parameters.
Unprocessable Entity (422)
Returned when the request contains an unsupported parameter, an invalid field structure, or an unknown content type. The response includes details about which field was rejected.
{
"detail": [
{
"type": "extra_forbidden",
"loc": ["body", "logprobs"],
"msg": "Extra inputs are not permitted",
"input": true
}
]
}
Common causes:
- Using an unsupported parameter (e.g.,
top_k,modalities,audio) - Adding unknown fields to messages (e.g.,
images) - Using an unknown content part
typevalue (supported types aretext,image_url,input_audio,video_url,file) - Invalid structure for
tools,response_format, orreasoning
Unauthorized (401)
Returned when the API key is missing, invalid, deactivated, or expired.
{
"error": {
"message": "Invalid API key"
}
}
Payment Required (402)
Returned when your license has insufficient credits to process the request.
{
"error": {
"message": "Insufficient credits"
}
}
Check your balance with GET /v1/license and contact your institution to top up.
Not Found (404)
Returned when a requested resource (e.g., a model ID) does not exist at the provider. The message comes from the provider, so it varies between providers and is not part of the contract:
{
"error": {
"message": "The model `nonexistent-model` does not exist or you do not have access to it."
}
}
See Who validates the model — an unknown model is not always a 404, and on a multi-provider endpoint the same request can return either a 404 or a 400.
Service Unavailable (503)
Returned when the upstream provider encounters an error. The actual error details are masked for security:
{
"error": {
"message": "Service temporarily unavailable"
}
}
This covers:
- Timeouts — the provider did not respond in time
- Rate limits — the provider is throttling requests
- Connection errors — network issues reaching the provider
- Authentication errors — issues with the upstream API key (not your Quantized key)
503 errors always return “Service temporarily unavailable” regardless of the underlying cause. This prevents leaking internal infrastructure details.
Handling errors
import httpx
response = httpx.post(
"https://api.quantized.us/v1/chat/completions",
headers={"Authorization": "Bearer sk-quantized-YOUR-KEY"},
json={"model": "openai/gpt-4.1-mini", "messages": [...]},
)
if response.status_code == 200:
data = response.json()
print(data["choices"][0]["message"]["content"])
elif response.status_code == 402:
print("Out of credits — contact your institution")
elif response.status_code == 422:
details = response.json()["detail"]
for d in details:
print(f"Unsupported field: {'.'.join(str(x) for x in d['loc'])}")
elif response.status_code == 503:
print("Provider unavailable — retry after a moment")
else:
error = response.json()
print(f"Error {response.status_code}: {error['error']['message']}")