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

# Rate Limits

> Understand Day Copilot API rate limits and best practices

## Overview

Day Copilot implements rate limiting to ensure fair usage and maintain service quality for all users. Rate limits vary by subscription tier and are applied per authenticated user.

<Note>
  Rate limit information is included in every API response via headers, allowing you to track your usage in real-time.
</Note>

## Rate Limit Tiers

| Tier           | Requests per Minute | Requests per Hour | Requests per Day |
| -------------- | ------------------- | ----------------- | ---------------- |
| **Free**       | 60                  | 1,000             | 10,000           |
| **Pro**        | 300                 | 10,000            | 100,000          |
| **Enterprise** | Custom              | Custom            | Custom           |

## Rate Limit Headers

Every API response includes rate limit information in the headers:

```http theme={null}
X-RateLimit-Limit: 60
X-RateLimit-Remaining: 45
X-RateLimit-Reset: 1699564800
```

| Header                  | Description                                        |
| ----------------------- | -------------------------------------------------- |
| `X-RateLimit-Limit`     | Maximum requests allowed in the current window     |
| `X-RateLimit-Remaining` | Number of requests remaining in the current window |
| `X-RateLimit-Reset`     | Unix timestamp when the rate limit resets          |

## Checking Rate Limits

<CodeGroup>
  ```javascript JavaScript theme={null}
  const response = await fetch('https://app.daycopilot.ai/api/v1/tasks', {
    headers: {
      'Authorization': `Bearer ${token}`
    }
  });

  const rateLimit = {
    limit: response.headers.get('X-RateLimit-Limit'),
    remaining: response.headers.get('X-RateLimit-Remaining'),
    reset: new Date(parseInt(response.headers.get('X-RateLimit-Reset')) * 1000)
  };

  console.log(`Requests remaining: ${rateLimit.remaining}/${rateLimit.limit}`);
  console.log(`Resets at: ${rateLimit.reset}`);
  ```

  ```python Python theme={null}
  import requests
  from datetime import datetime

  response = requests.get(
      'https://app.daycopilot.ai/api/v1/tasks',
      headers={'Authorization': f'Bearer {token}'}
  )

  rate_limit = {
      'limit': response.headers.get('X-RateLimit-Limit'),
      'remaining': response.headers.get('X-RateLimit-Remaining'),
      'reset': datetime.fromtimestamp(
          int(response.headers.get('X-RateLimit-Reset'))
      )
  }

  print(f"Requests remaining: {rate_limit['remaining']}/{rate_limit['limit']}")
  print(f"Resets at: {rate_limit['reset']}")
  ```
</CodeGroup>

## 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 retry after the rate limit resets.",
  "status": 429,
  "retryAfter": 45
}
```

The response includes:

* `retryAfter`: Seconds until you can retry the request
* `X-RateLimit-Reset` header: Unix timestamp when limits reset

## Best Practices

<AccordionGroup>
  <Accordion title="Implement Exponential Backoff">
    When you hit rate limits, implement exponential backoff:

    ```javascript theme={null}
    async function makeRequestWithBackoff(url, options, maxRetries = 3) {
      for (let i = 0; i < maxRetries; i++) {
        const response = await fetch(url, options);

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

        // Exponential backoff: 1s, 2s, 4s
        const delay = Math.pow(2, i) * 1000;
        await new Promise(resolve => setTimeout(resolve, delay));
      }

      throw new Error('Max retries exceeded');
    }
    ```
  </Accordion>

  <Accordion title="Cache Responses">
    Reduce API calls by caching responses locally:

    ```javascript theme={null}
    const cache = new Map();
    const CACHE_TTL = 5 * 60 * 1000; // 5 minutes

    async function getCachedTasks(token) {
      const now = Date.now();
      const cached = cache.get('tasks');

      if (cached && now - cached.timestamp < CACHE_TTL) {
        return cached.data;
      }

      const response = await fetch('https://app.daycopilot.ai/api/v1/tasks', {
        headers: { 'Authorization': `Bearer ${token}` }
      });

      const data = await response.json();
      cache.set('tasks', { data, timestamp: now });

      return data;
    }
    ```
  </Accordion>

  <Accordion title="Batch Operations">
    When possible, batch multiple operations into a single request to reduce API calls.
  </Accordion>

  <Accordion title="Use Webhooks">
    Instead of polling for changes, use webhooks (when available) to receive real-time updates without making repeated API calls.
  </Accordion>

  <Accordion title="Monitor Usage">
    Track your rate limit usage and set up alerts before you hit limits:

    ```javascript theme={null}
    function checkRateLimitUsage(response) {
      const remaining = parseInt(response.headers.get('X-RateLimit-Remaining'));
      const limit = parseInt(response.headers.get('X-RateLimit-Limit'));
      const usagePercent = ((limit - remaining) / limit) * 100;

      if (usagePercent > 80) {
        console.warn(`Warning: ${usagePercent.toFixed(1)}% of rate limit used`);
      }
    }
    ```
  </Accordion>
</AccordionGroup>

## Handling 429 Responses

Proper error handling for rate limit responses:

<CodeGroup>
  ```javascript JavaScript theme={null}
  async function makeRequest(url, options) {
    const response = await fetch(url, options);

    if (response.status === 429) {
      const retryAfter = response.headers.get('Retry-After') || 60;
      console.log(`Rate limited. Retrying in ${retryAfter} seconds...`);

      await new Promise(resolve =>
        setTimeout(resolve, parseInt(retryAfter) * 1000)
      );

      return makeRequest(url, options); // Retry
    }

    return response;
  }
  ```

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

  def make_request(url, headers):
      response = requests.get(url, headers=headers)

      if response.status_code == 429:
          retry_after = int(response.headers.get('Retry-After', 60))
          print(f"Rate limited. Retrying in {retry_after} seconds...")
          time.sleep(retry_after)
          return make_request(url, headers)  # Retry

      return response
  ```
</CodeGroup>

## Rate Limit Increases

Need higher rate limits? Contact our sales team to discuss Enterprise plans with custom limits tailored to your needs.

<Card title="Contact Sales" icon="envelope" href="mailto:sales@daycopilot.ai">
  Discuss custom rate limits for your use case
</Card>

## Next Steps

<CardGroup cols={2}>
  <Card title="Authentication" icon="key" href="/authentication">
    Learn about API authentication
  </Card>

  <Card title="Quick Start" icon="rocket" href="/quickstart">
    Make your first API call
  </Card>
</CardGroup>
