Errors & status codes
Every error uses OpenAI's error envelope, so existing OpenAI SDK error handling works unmodified.
Error shape
{
"error": {
"message": "This model does not exist or is not available",
"type": "invalid_request_error",
"code": "model_not_found"
}
}Rate limits
Every API key has a requests/minute cap — 60/min by default. Every response carries your current standing, so you can slow down before you are refused rather than after:
x-ratelimit-limit-requests— the cap, requests per minutex-ratelimit-remaining-requests— how many are left in the current windowx-ratelimit-reset-requests— seconds until the window resets
A 429 for rate_limit_exceeded adds Retry-After — wait that many seconds before retrying. The older X-RateLimit-Limit and X-RateLimit-Remaining headers are still sent on 429s for anything already parsing them. Need a higher limit? Contact support with your key name.
Codes
| HTTP | code | Meaning |
|---|---|---|
| 400 | invalid_request | Malformed body, or a required field (model, messages, input, prompt) is missing. |
| 401 | missing_api_key | No Authorization header was sent. |
| 401 | invalid_api_key | The key is malformed, unrecognized, or the secret doesn't match. |
| 401 | revoked_api_key | The key was revoked from the console and can no longer be used. |
| 402 | insufficient_quota | Your account balance can't cover the estimated cost of this request. Add credits. |
| 403 | account_not_active | The account is suspended or banned. |
| 403 | spend_limit_exceeded | This specific API key has a configured spend limit and has hit it. |
| 404 | model_not_found | The model slug doesn't exist, isn't active, or doesn't support this endpoint (e.g. calling /embeddings with a chat-only model). |
| 405 | method_not_allowed | Wrong HTTP method for this endpoint. |
| 503 | tool_unavailable | A requested viro:* server tool is temporarily unavailable. Retry, or drop the tool. |
| 429 | rate_limit_exceeded | You've exceeded this API key's requests/minute limit (60/min by default). See Retry-After. |
| 429 | upstream_rate_limited | The upstream model provider rate-limited this request. Retry with backoff. |
| 500 | server_error | Internal error on Viro's side. Safe to retry; contact support if persistent. |
| 502 | provider_auth_error | Viro failed to authenticate with the upstream provider. Not your fault — contact support. |
| 502 | provider_error | The upstream provider returned an unexpected 5xx. Safe to retry. |
Handling with the SDK
from openai import OpenAI, APIStatusError
client = OpenAI(api_key="viro_sk_live_...", base_url="https://api.viro.app/v1")
try:
client.chat.completions.create(model="viro/gpt-oss-120b", messages=[...])
except APIStatusError as e:
if e.code == "insufficient_quota":
... # prompt the user to add credits
elif e.code == "rate_limit_exceeded":
... # retry with backoff
else:
raise