---
title: Rate limits
description: Clipia API rate limits — 120 requests per minute per key and 600 per account, RateLimit-* headers, the 429 response, concurrency limits and LLM limits.
icon: Gauge
---

API requests are limited by two counters: **120 requests per minute per key** and **600 requests per minute per account** across all its keys. The window is a calendar minute: counters reset at the start of each minute. Exceeding either one rejects the request with `429 rate_limit_exceeded`.

## Default limits

| Limit | Value | Response when exceeded |
|-------|-------|------------------------|
| Requests per minute per key | 120 | `429 rate_limit_exceeded` |
| Requests per minute per account | 600 across all keys | `429 rate_limit_exceeded` |
| Requests per minute for an MCP connection via OAuth (no key) | 60 | `429 rate_limit_exceeded` |
| Concurrent generations | unlimited | — |
| Requests per minute for an MCP connection through OAuth (no key) | 60 | `429 rate_limit_exceeded` |
| MCP protocol messages per minute per key | 600 | `429 rate_limit_exceeded` |
| Requests per second from one IP address | 30, bursts up to 60 | `429 rate_limit_exceeded`, `Retry-After` header |

Custom per-key limits are set by the Clipia team on request; you can't change them in the Developer Console. A key's expiry and credit budget are set by its owner in the console — see [Managing keys](/en/docs/api-reference/keys).

The 60 requests per minute limit applies to [MCP](/en/docs/mcp) connections authorized through OAuth (Claude, ChatGPT, Cursor and other clients where you sign in to your Clipia account instead of entering a key): such a session has no key of its own, so its limit is lower than a key's. An MCP connection that uses an API key follows the key's limits. These limits count tool calls (`tools/call`). Protocol methods (`initialize`, `tools/list`, `resources/read` and others) are counted separately: 600 units per minute per key or OAuth connection, one JSON-RPC message being one unit. A JSON-RPC batch containing anything other than protocol methods is rejected with `400 invalid_request`: send each `tools/call` as its own request.

The per-IP limit protects the service from request floods and is checked before the key limits, so it doesn't show in the `RateLimit-*` headers. It covers `/v1/`, `/api/v1/` and `/mcp`; its `429` comes in the usual error format with a `Retry-After` header. This limit arrives with a separate infrastructure update: until then you won't see this response.

## Response headers

Every response to a keyed request carries the per-key limit headers:

<TypeTable
  type={{
    'RateLimit-Limit': { type: 'integer', description: 'Requests per minute allowed for this key' },
    'RateLimit-Remaining': { type: 'integer', description: 'Requests this key has left in the current minute' },
    'RateLimit-Reset': { type: 'integer', description: 'When the counter resets — a Unix timestamp in seconds, not a number of seconds until reset' },
    'x-ratelimit-remaining-requests': { type: 'integer', description: 'Same as RateLimit-Remaining, for OpenAI-compatible clients' },
    'Retry-After': { type: 'integer', description: 'Only on 429: how many seconds to wait before retrying' }
  }}
/>

<Callout type="warn" title="The account limit isn't in the headers">
`RateLimit-Remaining` counts only the current key's requests. If several keys on one account together exceed 600 requests per minute, you'll get `429` even though an individual key still has headroom.
</Callout>

## The 429 response

```http
HTTP/1.1 429 Too Many Requests
RateLimit-Limit: 120
RateLimit-Remaining: 0
RateLimit-Reset: 1760011260
Retry-After: 37
```

```json
{
  "error": {
    "type": "rate_limit_error",
    "code": "rate_limit_exceeded",
    "message": "API rate limit exceeded. Slow down and retry after the reset window."
  }
}
```

Wait for the number of seconds in `Retry-After`, then retry. That's more reliable than a fixed delay. If `Retry-After` is missing, compute the pause as `RateLimit-Reset` minus the current Unix time.

## Concurrent generations

By default, the number of simultaneous generations is unlimited. If a limit is set for the key or the account, a submit beyond it returns `429` with a `Retry-After: 5` header:

```json
{
  "error": {
    "type": "rate_limit_error",
    "code": "concurrency_limit_exceeded",
    "message": "Too many concurrent generations in flight for this API key (limit 5). Wait for one to finish, then retry.",
    "retry_after_seconds": 5
  }
}
```

Wait for one of your jobs to finish and retry. A slot is released when its job finishes; a stuck slot is released automatically after 30 minutes. When a limit is set and concurrency control is temporarily unavailable, submit returns `503 service_unavailable` — retry in a few seconds.

The concurrency limit applies to generation submits and LLM chat. Status and result polling don't count toward it.

## Key tokens and budget

A key can carry extra limits:

| Limit | Set by | Response when exceeded |
|-------|--------|------------------------|
| LLM tokens per minute, for the [AI Gateway](/en/docs/llm-gateway) | the Clipia team | `429 rate_limit_exceeded`, with `x-ratelimit-remaining-tokens` and `x-ratelimit-limit-tokens` headers |
| Credit budget, see [Managing keys](/en/docs/api-reference/keys) | the key owner, in the console | `402 insufficient_quota` |

These limits aren't set by default.
