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

# Rate limits

> Cactal API rate limits: token buckets per API key, capacities and refill rates, the Retry-After header, and 429 handling.

Rate limits protect the platform while staying far above normal usage. They apply identically to REST requests and MCP tool calls.

## The buckets

Limits are token buckets: each bucket has a capacity (burst headroom) and a refill rate (sustained throughput). A request that finds its bucket empty gets `429`.

| Bucket               | Scope       | Capacity | Refill         |
| -------------------- | ----------- | -------- | -------------- |
| Standard operations  | Per API key | 2,000    | 100 per second |
| Expensive operations | Per API key | 200      | 20 per second  |

**Expensive operations** are the build-heavy endpoints: `POST /v1/websiteSourceCode/head/check`, `POST /v1/websiteSourceCode/head/publish`, `POST /v1/websiteSourceCode/deployment/ensure`, and `POST /v1/websiteSourceCode/published/rollback-version`. Everything else is standard.

Additional IP-based abuse protections apply before authentication. Repeated authentication failures may be temporarily blocked. These protections apply to the REST API and MCP, not hosted website traffic.

## Handling 429

A rate-limited response tells you exactly how long to wait:

```http theme={null}
HTTP/1.1 429 Too Many Requests
Retry-After: 2
```

```json theme={null}
{
  "kind": "rate_limited",
  "message": "Rate limit exceeded",
  "retryAfterSeconds": 2
}
```

Recommended client behavior:

1. Honor `Retry-After` — sleep that many seconds, then retry the same request. Retrying a read or an idempotent write is always safe.
2. Pace bulk work below the refill rate — for example, keep sustained traffic under 100 requests per second per key, and under 20 per second for publishes and exports.
3. Queue, don't fan out. If you operate many websites (an agency sweep, a bulk content update), run a worker pool with a global pace rather than firing per-site requests concurrently without bounds.

<Warning>
  Publishing in a loop across many websites hits the expensive bucket first. Batch your edits per site, `head/check` once, publish once — not once per file.
</Warning>

## Scope details

* Per-key buckets are keyed to the key's principal, so two keys in one organization have independent budgets.
* MCP tool calls consume the same buckets as their REST equivalents — an agent and a script sharing one key share one budget. Give busy agents their own keys.
* Limits are enforced before your handler runs; a `429` never partially applies an operation.
