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

# Rate Limits

> Understanding API rate limits and how to handle them

The RouteMCP API uses a **sliding window** rate limiting model to ensure fair usage and platform stability.

## Limits by Plan

| Plan         | Requests per Minute |
| ------------ | ------------------- |
| Individual   | 100                 |
| Team         | 500                 |
| Organization | 2,000               |

Rate limits are applied **per API key**. Each key has its own counter.

## Rate Limit Headers

Every API response includes rate limit headers:

| Header                  | Description                              |
| ----------------------- | ---------------------------------------- |
| `X-RateLimit-Limit`     | Maximum requests allowed per window      |
| `X-RateLimit-Remaining` | Requests remaining in the current window |
| `X-RateLimit-Reset`     | Unix timestamp when the window resets    |

```
HTTP/1.1 200 OK
X-RateLimit-Limit: 500
X-RateLimit-Remaining: 498
X-RateLimit-Reset: 1709913600
```

## Handling 429 Responses

When you exceed the rate limit:

```json theme={null}
{
  "success": false,
  "statusCode": 429,
  "message": "Rate limit exceeded. Try again in 45 seconds."
}
```

The response includes a `Retry-After` header with the number of seconds to wait.

### Retry with Backoff

```javascript theme={null}
async function requestWithRetry(url, headers, maxRetries = 3) {
  for (let attempt = 0; attempt <= maxRetries; attempt++) {
    const response = await fetch(url, { headers });

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

    const retryAfter = parseInt(response.headers.get("Retry-After") || "60");
    const delay = retryAfter * 1000 * Math.pow(2, attempt);

    await new Promise(resolve => setTimeout(resolve, delay));
  }
  throw new Error("Max retries exceeded");
}
```

```python theme={null}
import time
import requests

def request_with_retry(url, headers, max_retries=3):
    for attempt in range(max_retries + 1):
        response = requests.get(url, headers=headers)
        if response.status_code != 429:
            return response

        retry_after = int(response.headers.get("Retry-After", 60))
        time.sleep(retry_after * (2 ** attempt))

    raise Exception("Max retries exceeded")
```

## Provider Rate Limits

Connected CRM providers have their own rate limits. When a provider limit is hit:

```json theme={null}
{
  "success": false,
  "statusCode": 429,
  "code": "PROVIDER_RATE_LIMITED",
  "message": "Provider rate limit exceeded"
}
```

This is separate from the RouteMCP API's own rate limit. The `Retry-After` value reflects the provider's reset time.

## Best Practices

1. **Use cursor pagination** — fetch pages of data instead of individual records
2. **Cache responses** where appropriate
3. **Monitor `X-RateLimit-Remaining`** — slow down before hitting the limit
4. **Respect `Retry-After`** — always wait the indicated time before retrying
5. **Use `sk_test_` keys** during development — same limits, no production impact
