# Rate limits

> Per-key, per-account and per-IP limits, the rate limit headers and other usage limits.

Requests are counted in fixed windows. When a limit is reached the API answers `429 RATE_LIMIT`:

```json
{
  "error": {
    "code": "RATE_LIMIT",
    "message": "Rate limit exceeded. Retry after the indicated delay.",
    "retryable": true,
    "retry_after_seconds": 17
  }
}
```

The answer also carries a `Retry-After` header with the same number of seconds. Wait that long, then retry.

## Headers

Answers that went through a limit carry:

| Header | Meaning |
|---|---|
| `X-RateLimit-Limit` | Requests allowed in the current window. |
| `X-RateLimit-Remaining` | Requests left in the current window. |
| `X-RateLimit-Reset` | Seconds until the window resets. |

Several limits apply to each request (below); the headers describe the last one checked.

## The limits

Every `/v1` request, polls included, counts against all of these:

| Limit | Window | Notes |
|---|---|---|
| Per key | 60 s | The default per-key allowance, or the lower `rate_limit_per_min` set on the key under profile menu > **API keys**. |
| Per account | shared with the AITOPIA MCP server | All keys of the account and its MCP connections share it, so adding keys does not raise the total. |
| Per client IP | 60 s | Checked before the key, at ten times the default per-key allowance. |

The actual numbers are returned in `X-RateLimit-Limit`; build against the headers rather than a fixed value. `GET /v1/openapi.json` is not limited.

## Other limits

| Limit | Value | Answer |
|---|---|---|
| Waiting calls (`?wait=N`) per account | 3 at a time, shared with the MCP server | Further waits check once and answer at once ([Polling](../../guides/polling/index.md)). |
| `wait` | 0 to 60 seconds | `400 INVALID_INPUT` |
| Edit planning (`POST /v1/edit`, dry runs included) | 10 per minute, 100 per day | refused; see `error.code` and `retryable` |
| Items per batch | 1 to 12 | `400 INVALID_INPUT` |
| Active runs per account | a few at once | `429 QUEUE_LIMIT_EXCEEDED`: wait for running jobs to finish |
| Account generation limits | set by AITOPIA | `429 RUN_LIMITED`: see `message` and `retry_after_seconds` |
| JSON request body | 25 MB | `413 FILE_TOO_LARGE` |
| Upload link file | 95 MB | see [File uploads](../../guides/uploads/index.md) |
| Monthly credits per key | optional cap | `402 KEY_CREDIT_CAP_REACHED` ([Billing](../../guides/billing/index.md#monthly-credit-cap)) |

## Tips

- Prefer [webhooks](../../guides/webhooks/index.md) or `?wait=30` long-polls to frequent short polls.
- Use one `POST /v1/batch` for up to 12 independent generations instead of 12 separate submits.
- On `429`, honour `retry_after_seconds` instead of retrying immediately.
