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

# Rate limits

> Per-API-key request limits by plan, and how to handle 429s.

Rate limits apply to Cloud API endpoints for customers, licenses, devices, functions, and saved SQL.

Limits are **per API key**. Each key has its own counter. The ceiling (requests per minute) comes from the **account plan** that owns the key. Creating multiple keys does **not** share one quota — each key is limited independently at that plan’s rate.

When you upgrade or downgrade the account plan, Orquestr updates the rate limit on every non-revoked API key for that account.

## Requests per minute

| Plan       | Requests / minute (per API key) |
| ---------- | ------------------------------- |
| Free       | 100                             |
| Pro        | 500                             |
| Platform   | 1000                            |
| Enterprise | 2000                            |

The window is **one minute**. An account with no active paid plan uses the Free limit.

## Response headers

Every rate-limited response includes your current state:

```http theme={"system"}
X-RateLimit-Limit: 500
X-RateLimit-Remaining: 487
```

When you exceed the limit, Orquestr returns `429` with:

```http theme={"system"}
X-RateLimit-Limit: 500
X-RateLimit-Remaining: 0
Retry-After: 60
```

```json theme={"system"}
{
  "error": {
    "code": "rate_limited",
    "message": "You have exceeded the rate limit. Please try again later."
  }
}
```

Read `X-RateLimit-Remaining` and back off before you hit zero, rather than waiting for the 429.

## Handling 429

Retry with exponential backoff, honoring `Retry-After`:

```typescript theme={"system"}
async function callWithRetry(url: string, options: RequestInit, attempt = 0) {
  const res = await fetch(url, options);

  if (res.status !== 429 || attempt >= 5) return res;

  const wait = Number(res.headers.get("Retry-After") ?? 60) * 1000;
  await new Promise((r) => setTimeout(r, wait * 2 ** attempt));

  return callWithRetry(url, options, attempt + 1);
}
```
