> ## Documentation Index
> Fetch the complete documentation index at: https://orwel-22af1265.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# Rate Limiting

> Understand rate limits and how to handle them

## Overview

To ensure fair usage and system stability, Orwel implements rate limiting on all API requests. Rate limits are applied per API key.

## Rate Limits

<CardGroup cols={2}>
  <Card title="Production Keys" icon="rocket">
    **1,000 requests per minute**

    Suitable for production workloads and high-traffic applications
  </Card>

  <Card title="Development Keys" icon="flask">
    **100 requests per minute**

    Perfect for testing and development environments
  </Card>
</CardGroup>

## Rate Limit Headers

Every API response includes rate limit information in the headers:

```http theme={null}
X-RateLimit-Limit: 1000
X-RateLimit-Remaining: 999
X-RateLimit-Reset: 1642252800
```

<ResponseField name="X-RateLimit-Limit" type="integer">
  Maximum number of requests allowed in the current window
</ResponseField>

<ResponseField name="X-RateLimit-Remaining" type="integer">
  Number of requests remaining in the current window
</ResponseField>

<ResponseField name="X-RateLimit-Reset" type="integer">
  Unix timestamp when the rate limit resets
</ResponseField>

## Rate Limit Exceeded

When you exceed the rate limit, you'll receive a `429 Too Many Requests` response:

```json theme={null}
{
  "error": "rate_limit_exceeded",
  "message": "Too many requests. Please try again later.",
  "retry_after": 60
}
```

The response also includes a `Retry-After` header indicating how many seconds to wait before retrying.

## Best Practices

<AccordionGroup>
  <Accordion icon="clock" title="Monitor Rate Limit Headers">
    Always check the `X-RateLimit-Remaining` header to know how many requests you have left. Implement logic to slow down requests as you approach the limit.

    ```javascript theme={null}
    const response = await fetch('https://api.orwel.io/api/v1/leads');
    const remaining = response.headers.get('X-RateLimit-Remaining');

    if (remaining < 10) {
      console.warn('Approaching rate limit!');
    }
    ```
  </Accordion>

  <Accordion icon="arrows-rotate" title="Implement Exponential Backoff">
    When you receive a 429 response, wait before retrying. Use exponential backoff to gradually increase wait times.

    ```javascript theme={null}
    async function fetchWithRetry(url, options, maxRetries = 3) {
      for (let i = 0; i < maxRetries; i++) {
        const response = await fetch(url, options);
        
        if (response.status !== 429) {
          return response;
        }
        
        const retryAfter = response.headers.get('Retry-After');
        const delay = retryAfter ? parseInt(retryAfter) * 1000 : Math.pow(2, i) * 1000;
        
        await new Promise(resolve => setTimeout(resolve, delay));
      }
      
      throw new Error('Max retries exceeded');
    }
    ```
  </Accordion>

  <Accordion icon="layer-group" title="Batch Requests">
    Instead of making many individual requests, batch your operations when possible. For example, use pagination to fetch multiple items in a single request.

    ```javascript theme={null}
    // ❌ Bad: Multiple requests
    for (let i = 0; i < 100; i++) {
      await fetch(`/api/v1/leads/${ids[i]}`);
    }

    // ✅ Good: Single paginated request
    const response = await fetch('/api/v1/leads?limit=100');
    ```
  </Accordion>

  <Accordion icon="cache" title="Cache Responses">
    Cache API responses when appropriate to reduce the number of requests. Use ETags or implement your own caching strategy.

    ```javascript theme={null}
    const cache = new Map();

    async function fetchWithCache(url) {
      if (cache.has(url)) {
        return cache.get(url);
      }
      
      const response = await fetch(url);
      const data = await response.json();
      cache.set(url, data);
      
      return data;
    }
    ```
  </Accordion>
</AccordionGroup>

## Monitoring Usage

Track your API usage in the Orwel dashboard:

1. Navigate to **Settings** → **API Keys**
2. View usage metrics for each key
3. Monitor rate limit violations
4. Set up alerts for high usage

## Increasing Limits

If you need higher rate limits for your production workload:

<Steps>
  <Step title="Contact Support">
    Email [support@orwel.io](mailto:support@orwel.io) with your use case
  </Step>

  <Step title="Provide Details">
    Include your workspace ID and expected request volume
  </Step>

  <Step title="Review">
    Our team will review your request within 24 hours
  </Step>
</Steps>

<Note>
  Enterprise plans include higher rate limits by default. [Contact sales](mailto:sales@orwel.io) to learn more.
</Note>

## Example Implementation

Here's a complete example with rate limit handling:

```javascript theme={null}
class OrwelClient {
  constructor(apiKey) {
    this.apiKey = apiKey;
    this.baseUrl = 'https://api.orwel.io/api/v1';
  }
  
  async request(endpoint, options = {}) {
    const url = `${this.baseUrl}${endpoint}`;
    const headers = {
      'Authorization': `Bearer ${this.apiKey}`,
      'Content-Type': 'application/json',
      ...options.headers
    };
    
    const response = await fetch(url, { ...options, headers });
    
    // Check rate limit
    const remaining = parseInt(response.headers.get('X-RateLimit-Remaining'));
    if (remaining < 10) {
      console.warn(`Rate limit warning: ${remaining} requests remaining`);
    }
    
    // Handle rate limit exceeded
    if (response.status === 429) {
      const retryAfter = parseInt(response.headers.get('Retry-After'));
      throw new Error(`Rate limit exceeded. Retry after ${retryAfter} seconds`);
    }
    
    return response.json();
  }
  
  async getLeads(params = {}) {
    const queryString = new URLSearchParams(params).toString();
    return this.request(`/leads?${queryString}`);
  }
}

// Usage
const client = new OrwelClient('your_api_key');

try {
  const leads = await client.getLeads({ limit: 50 });
  console.log(leads);
} catch (error) {
  console.error(error.message);
}
```
