# Gateway FAQ (/docs/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`? [#why-do-i-get-401-invalid_api_key]

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

| `message`                                                                             | What to do                                                                                                                                         |
| ------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------- |
| `Missing or invalid API key`                                                          | No `Authorization: Bearer codai_…` header reached the gateway. Check the header name and that your client sends it on every request.               |
| `Invalid API key`                                                                     | The key does not exist. Copy it again from [hub.codai.ro](https://hub.codai.ro) → **Keys** — a key is shown in full only once, when it is created. |
| `API key is disabled`                                                                 | The key was revoked or disabled in the hub. Create a new one.                                                                                      |
| `API key was rotated and its grace period has ended`                                  | Use 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 again` | Create 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](https://hub.codai.ro) and these docs are the place to start.

## Why do I get `402`? [#why-do-i-get-402]

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

| `code`                  | Where                                                                                                                                                                        | What to do                                                  |
| ----------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------- |
| `subscription_inactive` | Any request, when the key belongs to a subscription that is not active.                                                                                                      | Renew or change the plan in the hub under **Billing**.      |
| `insufficient_balance`  | Starting a [managed environment](../environments/billing.mdx) (the wallet must cover one hour) or using [sandboxes](../api/gateway/sandboxes.mdx) with unpaid sandbox usage. | Top up the wallet in the hub; the body carries the amounts. |
| `insufficient_funds`    | Accepting a [Resolve](../resolve/pricing-and-limits.mdx) 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`? [#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](./limits-pricing.mdx) and [tasks and spend](../agents/tasks-and-spend.mdx).

## Which model actually served my request? [#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:

| Header              | Meaning                                                                                                       |
| ------------------- | ------------------------------------------------------------------------------------------------------------- |
| `x-codai-routed-to` | The concrete upstream model that served the request.                                                          |
| `x-codai-provider`  | The provider adapter, e.g. `vertex-anthropic`.                                                                |
| `x-codai-generator` | `codai/<upstream model>`, sent with `x-codai-ai-generated: true` on every response that carries model output. |

```bash
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](./headers.mdx#response-headers).

## How do spend caps work? [#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](./limits-pricing.mdx#spend-caps).

## Do I get my money back when something fails? [#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](../agents/tasks-and-spend.mdx#outcome-billing-and-confirmation).
- **Resolve** refunds the whole hold when a job ends without a verified fix ([pricing and limits](../resolve/pricing-and-limits.mdx)).
- **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](https://codai.ro/withdrawal). The binding text is in the [Terms](https://codai.ro/terms).

## Where do I get help? [#where-do-i-get-help]

Write to **support@codai.ro**, or reply to any e-mail codai sent you. Live service status is at [codai.ro/status](https://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.
