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

# Rate Limits

> API rate limits and quotas

# Rate Limits

The Voicy API enforces rate limits to ensure fair usage and protect service stability.

## Limits by Plan

| Plan       | Requests/minute | Concurrent calls | Max call duration |
| ---------- | --------------- | ---------------- | ----------------- |
| Standard   | 60              | 10               | 30 minutes        |
| Enterprise | 600             | 100              | 60 minutes        |

## Rate Limit Headers

Rate limit information is included in response headers:

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

## Handling Rate Limits

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

```json theme={null}
{
  "error": "Rate limit exceeded. Please retry after 30 seconds."
}
```

### Best Practices

<AccordionGroup>
  <Accordion title="Implement exponential backoff">
    When you receive a 429 response, wait before retrying:

    ```javascript theme={null}
    async function requestWithBackoff(fn, maxRetries = 5) {
      for (let i = 0; i < maxRetries; i++) {
        try {
          return await fn();
        } catch (error) {
          if (error.status === 429 && i < maxRetries - 1) {
            const waitTime = Math.pow(2, i) * 1000; // 1s, 2s, 4s, 8s, 16s
            await new Promise(r => setTimeout(r, waitTime));
            continue;
          }
          throw error;
        }
      }
    }
    ```
  </Accordion>

  <Accordion title="Check rate limit headers">
    Monitor your usage by checking the response headers:

    ```javascript theme={null}
    const response = await fetch('https://api.voicy.co/functions/v1/call-list', {
      headers: { 'Authorization': `Bearer ${apiKey}` },
    });

    const remaining = response.headers.get('X-RateLimit-Remaining');
    const resetTime = response.headers.get('X-RateLimit-Reset');

    if (parseInt(remaining) < 10) {
      console.warn(`Only ${remaining} requests remaining until ${new Date(resetTime * 1000)}`);
    }
    ```
  </Accordion>

  <Accordion title="Queue requests">
    For bulk operations, implement a request queue:

    ```javascript theme={null}
    class RateLimitedQueue {
      constructor(requestsPerMinute = 60) {
        this.queue = [];
        this.interval = 60000 / requestsPerMinute;
        this.processing = false;
      }

      async add(fn) {
        return new Promise((resolve, reject) => {
          this.queue.push({ fn, resolve, reject });
          this.process();
        });
      }

      async process() {
        if (this.processing || this.queue.length === 0) return;
        this.processing = true;

        while (this.queue.length > 0) {
          const { fn, resolve, reject } = this.queue.shift();
          try {
            resolve(await fn());
          } catch (error) {
            reject(error);
          }
          await new Promise(r => setTimeout(r, this.interval));
        }

        this.processing = false;
      }
    }
    ```
  </Accordion>
</AccordionGroup>

## Concurrent Call Limits

The concurrent call limit applies to active calls (calls in `initiated`, `ringing`, or `in_progress` status).

If you try to create a call when at the limit:

```json theme={null}
{
  "error": "Concurrent call limit reached. Please wait for existing calls to complete."
}
```

## Increasing Limits

Need higher limits? Contact us at [support@voicy.co](mailto:support@voicy.co) to discuss Enterprise plans.
