codai docs
Gateway

Gateway FAQ

Quick answers — 401, 402 and 429 errors, which model served a request, spend caps and refunds.

Short answers to the questions support hears most. Each one links to the page with the full detail.

Why do I get 401 invalid_api_key?

The key is missing, malformed, or no longer valid. The message says which:

messageWhat to do
Missing or invalid API keyNo Authorization: Bearer codai_… header reached the gateway. Check the header name and that your client sends it on every request.
Invalid API keyThe key does not exist. Copy it again from hub.codai.ro → Keys — a key is shown in full only once, when it is created.
API key is disabledThe key was revoked or disabled in the hub. Create a new one.
API key was rotated and its grace period has endedUse the new key the rotation produced.
API key is paused until …The key is paused until that time.
API key has expired / API key expired after a period of inactivity; sign in againCreate a new key, or sign in again in the app that issued it.

Also check the base URL: it is https://ai.codai.ro/v1. A wrong path returns 404 not_found, not 401. Opening https://ai.codai.ro/ in a browser also answers 404: it is an API, not a web page — the dashboard is hub.codai.ro and these docs are the place to start.

Why do I get 402?

402 means "this needs money or a plan you do not have right now". The code tells you which:

codeWhereWhat to do
subscription_inactiveAny request, when the key belongs to a subscription that is not active.Renew or change the plan in the hub under Billing.
insufficient_balanceStarting a managed environment (the wallet must cover one hour) or using sandboxes with unpaid sandbox usage.Top up the wallet in the hub; the body carries the amounts.
insufficient_fundsAccepting a Resolve quote with too little wallet balance.The body has a topup_url for the exact shortfall.

Running out of plan tasks is not a 402 — it is 429 quota_exceeded (below).

Why do I get 429?

Two different walls share the status code. Tell them apart by error.code:

  • rate_limit_exceeded — slow down. Either the per-minute / per-hour request window or the input / output token window is full, or your daily or monthly spend cap is reached. Retry-After is the exact number of seconds to wait.
  • quota_exceeded — the plan's task allowance is used up and nothing else (wallet, prepaid credits, overage) pays for a new task. Conversations you already started keep working; only brand-new tasks wait. Retry-After points at the reset (next UTC month, or 00:00 UTC on a daily cap).

Both carry type: "rate_limit_error", so an OpenAI SDK raises RateLimitError for both. Details in limits & pricing and tasks and spend.

Which model actually served my request?

You always call codai; the gateway picks the upstream model. Every chat, messages and audio response says which one in the response headers:

HeaderMeaning
x-codai-routed-toThe concrete upstream model that served the request.
x-codai-providerThe provider adapter, e.g. vertex-anthropic.
x-codai-generatorcodai/<upstream model>, sent with x-codai-ai-generated: true on every response that carries model output.
curl -sD - -o /dev/null https://ai.codai.ro/v1/chat/completions \
  -H "Authorization: Bearer $CODAI_API_KEY" -H "Content-Type: application/json" \
  -d '{"model":"codai","messages":[{"role":"user","content":"Hello"}]}' | grep -i x-codai-routed-to

Per-model totals over a time window are in GET /v1/receipt (by_upstream). All headers: request headers.

How do spend caps work?

You can set a daily and a monthly cap in the hub; it is summed across all your keys, and per-key budgets sit under it, never above it. While caps are on, each response carries x-codai-spend-day-usd, x-codai-spend-day-cap-usd, x-codai-spend-month-usd and x-codai-spend-month-cap-usd. When a cap is reached the gateway answers 429 rate_limit_exceeded, with a message naming the window: daily caps reset at midnight UTC, monthly caps on the 1st (UTC). The cap is compared with the upstream cost the gateway measures, which is in USD — hence the -usd names. More in limits & pricing.

Do I get my money back when something fails?

  • A failed request costs nothing. It is recorded with is_task_start = 0, so it never bills a task, and a prepaid credit or metered task reserved before dispatch is refunded automatically when the upstream never served the request.
  • Tasks are billed on outcome. Tasks from an IDE, the API or the CLI wait for your confirmation in the hub under Tasks: No closes the task as fail and nothing is charged; a task left unconfirmed for 24 hours is not billed as a success. On wallet plans, confirming Yes refunds the token cost already charged against the flat success price. See tasks and spend.
  • Resolve refunds the whole hold when a job ends without a verified fix (pricing and limits).
  • Usage already consumed is not refundable, because the model cost is incurred at the moment of the request. EU consumers may withdraw from a purchase of prepaid credit or a subscription within 14 days: the unused part is refunded, the part already used is not. Use codai.ro/withdrawal. The binding text is in the Terms.

Where do I get help?

Write to [email protected], or reply to any e-mail codai sent you. Live service status is at codai.ro/status. When you report a problem, include the x-codai-trace-id (or your own X-Request-Id) of a failing request — it lets us find the exact request without seeing your prompt.

On this page