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

# Rate limits

> Read request budgets and retry Canary API calls safely

# Rate limits

Canary applies a one-minute request budget per API key. Separate keys have separate budgets.

| Key prefix | Requests per minute |
| ---------- | ------------------: |
| `sk_live_` |               1,000 |
| `sk_test_` |                 100 |

## Successful response headers

Rate limit headers appear on successful authenticated responses:

```text theme={"theme":"github-light"}
X-RateLimit-Limit: 1000
X-RateLimit-Remaining: 998
X-RateLimit-Reset: 1788333600
```

`X-RateLimit-Reset` is a Unix timestamp in seconds. Authentication, validation, and other error responses may omit these three headers, so clients should treat them as optional.

## Handle 429

A depleted budget returns `429 Too Many Requests` with `Retry-After` in seconds:

```http theme={"theme":"github-light"}
HTTP/1.1 429 Too Many Requests
Content-Type: application/problem+json
X-Request-ID: req_01JAY8FVDM6CH4R3X9Q2T7K5NP
Retry-After: 45
```

```json theme={"theme":"github-light"}
{
  "type": "https://api.oncanary.com/errors/rate_limit_exceeded",
  "title": "Rate Limit Exceeded",
  "status": 429,
  "detail": "Rate limit exceeded. Retry after 45 seconds.",
  "request_id": "req_01JAY8FVDM6CH4R3X9Q2T7K5NP",
  "code": "rate_limit_exceeded"
}
```

Honor `Retry-After`, add a small random delay, and retry within a bounded attempt count.

```javascript theme={"theme":"github-light"}
const sleep = (milliseconds) => new Promise((resolve) => setTimeout(resolve, milliseconds));

async function fetchCanary(url, options, attempts = 4) {
  for (let attempt = 0; attempt < attempts; attempt += 1) {
    const response = await fetch(url, options);
    if (response.status !== 429) return response;

    const retryAfter = Number(response.headers.get('Retry-After') ?? 60);
    const jitter = Math.floor(Math.random() * 500);
    await sleep(retryAfter * 1000 + jitter);
  }

  throw new Error('Canary API remained rate limited');
}
```

## Stay within the budget

* Request the largest useful page size: up to 100 for native lists and 200 for work requests or portals.
* Cache slow-changing records such as locations and custom-field definitions.
* Process changes in a queue with bounded concurrency.
* Use `X-RateLimit-Remaining` as an early signal when the header is present.
* Use one key per independent workload so ownership and budget usage stay observable.

For sustained workloads near the published limit, contact [support@oncanary.com](mailto:support@oncanary.com) with the organization, use case, expected volume, and visible key prefix.
