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

# Rate limiting

> Understand API rate limits, response headers, and how to handle throttled requests.

The Ayliea API enforces rate limits to ensure consistent performance for all customers. Limits are applied per API key.

## Limits

| Endpoint category                                                         | Limit                  |
| ------------------------------------------------------------------------- | ---------------------- |
| All read endpoints (`/v1/scores`, `/v1/recommendations`, `/v1/discovery`) | 60 requests per minute |

The rate limit window is a sliding 60-second window. Once you exceed 60 requests in any 60-second period, subsequent requests receive a `429` response until the window resets.

## Rate limit headers

When a request is rate limited, the `429` response includes headers to help you determine when to retry:

| Header                  | Description                                                    |
| ----------------------- | -------------------------------------------------------------- |
| `Retry-After`           | Seconds until the current window resets                        |
| `X-RateLimit-Limit`     | Maximum requests allowed per window                            |
| `X-RateLimit-Remaining` | Requests remaining in the current window (always `0` on a 429) |
| `X-RateLimit-Reset`     | Unix timestamp (seconds) when the window resets                |

## Example `429` response

```bash theme={null}
HTTP/1.1 429 Too Many Requests
Retry-After: 23
X-RateLimit-Limit: 60
X-RateLimit-Remaining: 0
X-RateLimit-Reset: 1742054423
Content-Type: application/json
```

```json theme={null}
{
  "error": "Too many requests. Please try again later."
}
```

## Handling rate limits

<AccordionGroup>
  <Accordion title="Respect the Retry-After header">
    When you receive a `429`, wait the number of seconds specified in `Retry-After` before retrying. Do not retry immediately.
  </Accordion>

  <Accordion title="Use exponential backoff">
    If you are making many requests in sequence, add exponential backoff with jitter. Start with a 1-second delay, double it on each retry, and add a random component to avoid thundering herd effects.

    ```python theme={null}
    import time, random

    def request_with_backoff(url, headers, max_retries=5):
        for attempt in range(max_retries):
            response = requests.get(url, headers=headers)
            if response.status_code != 429:
                return response
            wait = (2 ** attempt) + random.uniform(0, 1)
            time.sleep(wait)
        raise Exception("Max retries exceeded")
    ```
  </Accordion>

  <Accordion title="Reduce request frequency">
    If you consistently hit rate limits, consider caching responses on your side. Assessment scores and recommendations change infrequently — polling once every 5-15 minutes is sufficient for most integrations.
  </Accordion>
</AccordionGroup>
