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

# Rate Limiting

> Learn about API rate limit tiers, response headers, and how to handle 429 errors with retry logic

# Rate Limiting

The API uses in-memory rate limiting keyed by API key ID to protect service quality.

## Tiers

| Tier         | Limit        | Window   |
| ------------ | ------------ | -------- |
| **Standard** | 100 requests | 1 minute |
| **Elevated** | 500 requests | 1 minute |

Your rate limit tier is determined by your subscription plan.

## Response headers

Every API response (including `429` errors) 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 (seconds) when the window resets |

## Example headers

```http theme={null}
HTTP/1.1 200 OK
X-RateLimit-Limit: 100
X-RateLimit-Remaining: 87
X-RateLimit-Reset: 1711234560
```

## Handling rate limits

When you exceed the limit, the API returns a `429 Too Many Requests` response. Use the `X-RateLimit-Reset` header to determine when to retry.

<CodeGroup>
  ```javascript Node.js theme={null}
  async function fetchWithRetry(url, options, maxRetries = 3) {
    for (let attempt = 0; attempt < maxRetries; attempt++) {
      const response = await fetch(url, options);

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

      const resetAt = Number(response.headers.get('X-RateLimit-Reset'));
      const waitMs = Math.max(0, resetAt * 1000 - Date.now()) + 100;

      console.log(`Rate limited. Waiting ${Math.ceil(waitMs / 1000)}s...`);
      await new Promise(resolve => setTimeout(resolve, waitMs));
    }

    throw new Error('Max retries exceeded');
  }
  ```

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

  def fetch_with_retry(url, headers, max_retries=3):
      for attempt in range(max_retries):
          response = requests.get(url, headers=headers)

          if response.status_code != 429:
              return response

          reset_at = int(response.headers.get('X-RateLimit-Reset', 0))
          wait_seconds = max(0, reset_at - time.time()) + 0.1

          print(f'Rate limited. Waiting {wait_seconds:.0f}s...')
          time.sleep(wait_seconds)

      raise Exception('Max retries exceeded')
  ```
</CodeGroup>

<Tip>
  To avoid hitting rate limits, add small delays between requests when iterating through paginated results, and cache responses where possible.
</Tip>
