> ## Documentation Index
> Fetch the complete documentation index at: https://docs.codzen.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Authentication and rate limits

> Authenticate every request with a cz_ API key from the console, keep the key on your server, and stay within 300 requests per minute per key and 10 concurrent generations per account.

## API keys

Every request sends an API key in the `Authorization` header:

```bash theme={null}
curl https://codzen.ai/api/v1/balance \
  -H "Authorization: Bearer $CODZEN_API_KEY"
```

`GET /models` is the only endpoint that works without an API key.

* **Create API keys in the console.** An API key starts with `cz_`. Give each key a name, such as the app or environment that uses it; an account can have up to 10 API keys.
* **The full key is shown only once**, when you create it. Codzen stores only a hash, so a lost key cannot be shown again: create a new one and revoke the old one.
* **Revoking a key** in the console removes it for good. Requests with a revoked key fail with `401 invalid_api_key`.
* API keys do not expire, and every key can call every endpoint for its account.

> [!WARNING]
>
> Use API keys only on your server. The API does not allow cross-origin (CORS) requests from browsers, and a key shipped in a web page or mobile app can be copied and spent by anyone. Call Codzen from your backend, and keep the key in an environment variable or secret store, never in source control.

## Authentication errors

| HTTP | `code` | Meaning |
| - | - | - |
| 401 | `invalid_api_key` | The `Authorization` header is missing, or the key is wrong or revoked. |
| 403 | `api_key_disabled` | Codzen has disabled this key. Contact support. |
| 403 | `account_suspended` | The account is suspended. Its API keys work again once the suspension is lifted. |

Generations submitted before a suspension still finish, are charged and send their webhooks. See [Errors](https://docs.codzen.ai/guides/errors.md) for the error format.

## Rate limits

| Limit | Default | Error |
| - | - | - |
| Requests per API key | 300 per minute | `429 rate_limited` |
| Concurrent generations per account | 10 `queued` or `processing` at a time | `429 concurrency_limit` |
| `GET /models` without an API key | Limited per IP address | `429 rate_limited` |

* **Every request with an API key counts** toward its rate limit, including `GET` requests that poll a generation.
* **The concurrency limit is per account**, across all of its API keys. A generation stops counting once it succeeds or fails.
* **The API does not queue for you.** A request over a limit fails right away with `429` and a `Retry-After` header: the number of seconds to wait before trying again.
* Responses carry no `X-RateLimit-*` headers. Rely on `429` and `Retry-After`.

A simple strategy: on `429`, wait for `Retry-After` seconds, then send the same request again. To stay under the concurrency limit, keep your own queue of pending work and submit a new generation when one finishes.

```javascript theme={null}
async function codzen(path, init = {}) {
  for (;;) {
    const res = await fetch(`https://codzen.ai/api/v1${path}`, {
      ...init,
      headers: {
        Authorization: `Bearer ${process.env.CODZEN_API_KEY}`,
        'Content-Type': 'application/json',
        ...init.headers,
      },
    });
    if (res.status !== 429) return res;
    const seconds = Number(res.headers.get('Retry-After') ?? 1);
    await new Promise((resolve) => setTimeout(resolve, seconds * 1000));
  }
}
```

If your workload needs higher limits, contact Codzen.

## Request IDs

Every response carries an `x-request-id` header, and every error body repeats it as `request_id`. Quote it when you contact support about a request.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.