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

# Rate Limits and Throttling in the Cano Analytics API

> Understand Cano Analytics per-endpoint rate limits, how to read the limit headers on every response, and how to handle 429 errors with exponential backoff.

Cano enforces rate limits to ensure fair usage and platform stability across all customers — understanding them helps you design resilient integrations that degrade gracefully under load rather than failing hard. Limits are applied per API key and reset on a rolling window basis.

## Limits by Endpoint Group

Different endpoint groups have different limits reflecting their relative cost to the platform. High-volume event ingestion supports far higher throughput than administrative actions.

| Endpoint Group                      | Requests / sec | Requests / min |
| ----------------------------------- | :------------: | :------------: |
| Event ingestion (`POST /v1/events`) |      1,000     |     50,000     |
| User identify (`POST /v1/identify`) |       500      |     25,000     |
| Query / Dashboards                  |       100      |      3,000     |
| Admin (workspace, team, billing)    |       10       |       300      |

<Note>
  Customers on the **Pro** and **Enterprise** plans receive significantly higher rate limits. Enterprise plans also support custom limits tailored to your ingestion volume. Reach out to your account manager or visit **Settings → Billing** to upgrade.
</Note>

## Rate Limit Headers

Every API response — including successful ones — includes three headers that tell you exactly where you stand within the current window. Read these headers to implement proactive throttling before you hit a `429`.

| Header                  | Description                                                                        |
| ----------------------- | ---------------------------------------------------------------------------------- |
| `X-RateLimit-Limit`     | Your total request allowance for the current window                                |
| `X-RateLimit-Remaining` | How many requests you have left in the current window                              |
| `X-RateLimit-Reset`     | Unix timestamp (seconds) when the current window resets and your allowance refills |

A typical response header set looks like this:

```
X-RateLimit-Limit: 50000
X-RateLimit-Remaining: 49812
X-RateLimit-Reset: 1730470860
```

## Handling 429 Errors

When you exceed a rate limit, the API returns an HTTP `429 Too Many Requests` response. The `X-RateLimit-Reset` header tells you exactly when you can retry, but the most robust strategy is **exponential backoff with jitter** — each successive retry waits longer, and a small random offset prevents synchronized retry storms when multiple clients hit the limit simultaneously.

```javascript Retry with Exponential Backoff theme={null}
async function trackWithRetry(payload, retries = 3) {
  for (let i = 0; i < retries; i++) {
    const res = await fetch("https://api.canoanalytics.io/v1/events", {
      method: "POST",
      headers: {
        "Authorization": "Bearer YOUR_API_KEY",
        "Content-Type": "application/json",
      },
      body: JSON.stringify(payload),
    });

    if (res.status !== 429) return res;

    const delay = Math.pow(2, i) * 100 + Math.random() * 50;
    await new Promise((resolve) => setTimeout(resolve, delay));
  }

  throw new Error("Exceeded maximum retries due to rate limiting.");
}

// Usage
await trackWithRetry({ event: "page_viewed", user_id: "usr_123", properties: { page: "/pricing" } });
```

This gives you wait times of roughly **100 ms → 200 ms → 400 ms** across three attempts, with up to 50 ms of random jitter applied each time. Adjust the base multiplier and retry count to match the criticality of your workload.

<Tip>
  Use the **batch events endpoint** (`POST /v1/events/batch`) to send up to 500 events in a single request. Batching is the single most effective way to reduce your request count — it cuts API calls by orders of magnitude for high-volume producers without sacrificing delivery guarantees.
</Tip>

## Best Practices

<Accordion title="Monitor remaining headroom proactively">
  Read `X-RateLimit-Remaining` on every response and begin throttling your outbound request rate when it drops below 10–15% of `X-RateLimit-Limit`. This prevents hitting the wall entirely and keeps your integration running smoothly during traffic spikes.
</Accordion>

<Accordion title="Use test keys during load testing">
  Rate limits apply per API key. Use a `cano_test_sk_...` key in your staging and load-testing environments so test traffic does not consume production quota.
</Accordion>

<Accordion title="Distribute load across multiple keys">
  If your architecture runs multiple independent services, give each one its own API key. Each key receives its own rate limit allowance, so you effectively multiply your total throughput capacity.
</Accordion>
