> ## Documentation Index
> Fetch the complete documentation index at: https://www.orwel.io/docs/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

Limits are counted per key, in one minute windows shared by every Orwel server, for the REST API (`/api/v1`) and the [MCP server](https://www.orwel.io/docs/agents/mcp.md).

| Key | Limit |
| - | - |
| API key (`orwel_sk_`) | **1,000 requests per minute** |

The production and development keys of the SDK only send data to the ingest endpoints, which are not part of this limit. See [API keys and authentication](https://www.orwel.io/docs/authentication.md).

> [!NOTE]
>
> The limit belongs to the key, not to the workspace. An integration and an agent on separate keys never slow each other down.

## 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
```

**X-RateLimit-Limit** `integer`

Maximum number of requests allowed in the current window

**X-RateLimit-Remaining** `integer`

Number of requests remaining in the current window

**X-RateLimit-Reset** `integer`

Unix timestamp when the rate limit resets

## 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

> [accordion] 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] 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] 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] 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;
> }
> ```

## Monitoring Usage

**Settings, API keys** shows when each key was last used and from which origin. To see how close a client is to the limit, read the `X-RateLimit-Remaining` header of its responses.

## Increasing Limits

If you need higher rate limits for your production workload:

**1. Contact Support**

Email [support@orwel.io](mailto:support@orwel.io) with your use case (see [Support](https://www.orwel.io/docs/support.md))

**2. Provide Details**

Include your workspace ID and expected request volume

**3. Review**

Our team will review your request within 24 hours

> [!NOTE]
>
> Enterprise plans include higher rate limits by default. [Contact us](https://www.orwel.io/docs/support.md) to learn more.

## 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);
}
```


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.