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

# Rate Limiting Guide

> Understand how TitanX API rate limiting works, when limits reset, and how to handle rate limit responses

## Overview

Rate limiting protects our API infrastructure by controlling how many requests you can make within specific time periods. Think of it like having three different speed limits on the same road - you need to respect all of them to keep moving smoothly.

Our system uses **three-tier rate limiting** to ensure fair usage and optimal performance for all developers:

<CardGroup cols={3}>
  <Card title="Per-Second Limits" icon="clock">
    Prevents burst traffic spikes
  </Card>

  <Card title="Per-Minute Limits" icon="hourglass-half">
    Controls sustained request rates
  </Card>

  <Card title="Daily Limits" icon="calendar-day">
    Manages overall daily usage
  </Card>
</CardGroup>

## How Rate Limiting Works

### Three-Tier Protection

Every API request must pass through all three rate limiting tiers:

1. **Second-level**: Allows quick bursts of requests (typically 5-50 per second)
2. **Minute-level**: Permits sustained usage (typically 100-3000 per minute)
3. **Daily-level**: Sets overall usage bounds (typically 10,000-100,000 per day)

<Note>
  Your specific limits depend on your TitanX plan. Use the `/api/public/quota` endpoint to see your current limits.
</Note>

### Fixed Time Windows

Our rate limits use **fixed time windows** that reset at exact intervals:

<Tabs>
  <Tab title="Per-Second">
    Resets every second at the exact second boundary.

    **Example**: If it's currently `14:23:45.750`, your second quota will reset at `14:23:46.000`
  </Tab>

  <Tab title="Per-Minute">
    Resets every minute at the exact minute boundary.

    **Example**: If it's currently `14:23:45`, your minute quota will reset at `14:24:00`
  </Tab>

  <Tab title="Daily">
    Resets every day at midnight UTC.

    **Example**: If it's currently `2024-01-15 14:23:45`, your daily quota will reset at `2024-01-16 00:00:00 UTC`
  </Tab>
</Tabs>

### How Quotas Are Consumed

Each successful API request consumes **1 quota** from all three tiers simultaneously. Failed requests (4xx/5xx errors) still consume quota to prevent abuse.

<Warning>
  If ANY tier is exceeded, your request will be blocked with a `429 Too Many Requests` response, even if the other tiers have remaining quota.
</Warning>

## Rate Limit Headers

Every API response includes detailed information about your current rate limit status through HTTP headers:

### Complete Headers Reference

| Header                         | Description                               | Example      |
| ------------------------------ | ----------------------------------------- | ------------ |
| `X-RateLimit-Limit-Second`     | Maximum requests allowed per second       | `10`         |
| `X-RateLimit-Remaining-Second` | Remaining requests this second            | `7`          |
| `X-RateLimit-Reset-Second`     | When second quota resets (Unix timestamp) | `1704110401` |
| `X-RateLimit-Limit-Minute`     | Maximum requests allowed per minute       | `300`        |
| `X-RateLimit-Remaining-Minute` | Remaining requests this minute            | `287`        |
| `X-RateLimit-Reset-Minute`     | When minute quota resets (Unix timestamp) | `1704110460` |
| `X-RateLimit-Limit-Day`        | Maximum requests allowed per day          | `50000`      |
| `X-RateLimit-Remaining-Day`    | Remaining requests today                  | `49713`      |
| `X-RateLimit-Reset-Day`        | When daily quota resets (Unix timestamp)  | `1704153600` |

### Special Headers

When you're rate limited, additional headers help you retry effectively:

| Header        | Description                     | Example |
| ------------- | ------------------------------- | ------- |
| `Retry-After` | Seconds to wait before retrying | `1`     |

<Tip>
  Convert Unix timestamps to readable dates: `new Date(timestamp * 1000)` in JavaScript
</Tip>

### Example Response Headers

```http theme={null}
HTTP/1.1 200 OK
X-RateLimit-Limit-Second: 10
X-RateLimit-Remaining-Second: 7
X-RateLimit-Reset-Second: 1704110401
X-RateLimit-Limit-Minute: 300
X-RateLimit-Remaining-Minute: 287
X-RateLimit-Reset-Minute: 1704110460
X-RateLimit-Limit-Day: 50000
X-RateLimit-Remaining-Day: 49713
X-RateLimit-Reset-Day: 1704153600
```

## Checking Your Quota

Use the `/api/public/quota` endpoint to check your current limits without consuming quota:

<CodeGroup>
  ```bash cURL theme={null}
  curl -H "Authorization: Bearer YOUR_JWT_TOKEN" \
       https://app.titanx.io/api/public/quota
  ```

  ```javascript JavaScript theme={null}
  const response = await fetch('https://app.titanx.io/api/public/quota', {
    headers: {
      'Authorization': 'Bearer YOUR_JWT_TOKEN'
    }
  });

  const data = await response.json();
  console.log('Rate limit status:', data);
  ```

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

  headers = {'Authorization': 'Bearer YOUR_JWT_TOKEN'}
  response = requests.get('https://app.titanx.io/api/public/quota', headers=headers)
  quota_info = response.json()
  print(f"Rate limit status: {quota_info}")
  ```
</CodeGroup>

## Handling Rate Limits

### When You Hit a Limit

When any rate limit is exceeded, you'll receive a `429 Too Many Requests` response:

```json theme={null}
{
  "error": "Rate limit exceeded",
  "message": "Too many requests. Rate limit exceeded for second tier.",
  "tier": "second",
  "retryAfter": 1704110401
}
```

### Best Practices for Retries

<Steps>
  <Step title="Check the Retry-After Header">
    Always respect the `Retry-After` header value before making another request.
  </Step>

  <Step title="Implement Exponential Backoff">
    If you don't receive a `Retry-After` header, use exponential backoff starting with 1 second.
  </Step>

  <Step title="Monitor All Tiers">
    Watch the remaining quota for all three tiers, not just the one that was exceeded.
  </Step>

  <Step title="Spread Your Requests">
    Avoid sending bursts of requests. Distribute them evenly across time.
  </Step>
</Steps>

### Example Retry Logic

<CodeGroup>
  ```javascript JavaScript theme={null}
  async function makeRequestWithRetry(url, options, maxRetries = 3) {
    for (let attempt = 1; attempt <= maxRetries; attempt++) {
      try {
        const response = await fetch(url, options);
        
        if (response.status === 429) {
          const retryAfter = response.headers.get('Retry-After');
          const waitTime = retryAfter ? parseInt(retryAfter) * 1000 : Math.pow(2, attempt) * 1000;
          
          console.log(`Rate limited. Waiting ${waitTime}ms before retry ${attempt}/${maxRetries}`);
          await new Promise(resolve => setTimeout(resolve, waitTime));
          continue;
        }
        
        return response;
      } catch (error) {
        if (attempt === maxRetries) throw error;
        await new Promise(resolve => setTimeout(resolve, Math.pow(2, attempt) * 1000));
      }
    }
  }
  ```

  ```python Python theme={null}
  import time
  import requests
  from requests.adapters import HTTPAdapter
  from urllib3.util.retry import Retry

  def make_request_with_retry(url, headers, max_retries=3):
      for attempt in range(1, max_retries + 1):
          try:
              response = requests.get(url, headers=headers)
              
              if response.status_code == 429:
                  retry_after = response.headers.get('Retry-After')
                  wait_time = int(retry_after) if retry_after else 2 ** attempt
                  
                  print(f"Rate limited. Waiting {wait_time}s before retry {attempt}/{max_retries}")
                  time.sleep(wait_time)
                  continue
                  
              return response
          except requests.RequestException as e:
              if attempt == max_retries:
                  raise e
              time.sleep(2 ** attempt)
  ```
</CodeGroup>

### Monitoring Your Usage

Proactively monitor your rate limits to avoid hitting them:

```javascript theme={null}
// Check if you're approaching any limits
function checkRateLimitStatus(headers) {
  const secondRemaining = parseInt(headers.get('X-RateLimit-Remaining-Second'));
  const minuteRemaining = parseInt(headers.get('X-RateLimit-Remaining-Minute'));
  const dayRemaining = parseInt(headers.get('X-RateLimit-Remaining-Day'));
  
  // Warn when approaching limits
  if (secondRemaining <= 1) {
    console.warn('⚠️ Very low second-tier quota remaining');
  }
  if (minuteRemaining <= 10) {
    console.warn('⚠️ Low minute-tier quota remaining');
  }
  if (dayRemaining <= 100) {
    console.warn('⚠️ Low daily quota remaining');
  }
}
```

## Common Integration Patterns

### Batch Processing

When processing multiple items, respect rate limits:

```javascript theme={null}
async function processBatch(items, apiCall) {
  const results = [];
  
  for (const item of items) {
    const response = await makeRequestWithRetry(apiCall, item);
    results.push(response);
    
    // Check remaining quotas and pace accordingly
    const remaining = parseInt(response.headers.get('X-RateLimit-Remaining-Second'));
    if (remaining <= 2) {
      // Slow down when approaching limits
      await new Promise(resolve => setTimeout(resolve, 1000));
    }
  }
  
  return results;
}
```

### Real-time Applications

For real-time apps, check quotas before making requests:

```javascript theme={null}
async function smartApiCall(endpoint, payload) {
  // Check quota first
  const quotaResponse = await fetch('/api/public/quota', { 
    headers: { 'Authorization': `Bearer ${token}` }
  });
  
  const secondRemaining = parseInt(quotaResponse.headers.get('X-RateLimit-Remaining-Second'));
  
  if (secondRemaining <= 1) {
    console.log('Quota low, waiting for reset...');
    const resetTime = parseInt(quotaResponse.headers.get('X-RateLimit-Reset-Second'));
    const waitTime = (resetTime * 1000) - Date.now();
    await new Promise(resolve => setTimeout(resolve, waitTime));
  }
  
  return fetch(endpoint, {
    method: 'POST',
    body: JSON.stringify(payload),
    headers: { 'Authorization': `Bearer ${token}` }
  });
}
```

## Troubleshooting

### Common Issues

<AccordionGroup>
  <Accordion title="Getting 429 errors despite low usage">
    **Cause**: Sending requests in tight loops can exceed per-second limits even with low overall volume.

    **Solution**: Add small delays between requests or implement proper retry logic.
  </Accordion>

  <Accordion title="Inconsistent rate limit behavior">
    **Cause**: Rate limits are enforced per client ID. Using multiple API keys may have different limits.

    **Solution**: Check your client configuration and ensure you're using the correct authentication token.
  </Accordion>

  <Accordion title="Daily limits resetting at unexpected times">
    **Cause**: Daily limits reset at midnight UTC, which may differ from your local timezone.

    **Solution**: Convert the `X-RateLimit-Reset-Day` timestamp to your local timezone to see the actual reset time.
  </Accordion>
</AccordionGroup>

### Getting Help

If you're experiencing persistent rate limiting issues:

1. **Check your plan limits** in the TitanX dashboard
2. **Review your request patterns** for burst behavior
3. **Verify your authentication** tokens are correct
4. **Contact support** with your client ID and example requests

<Note>
  Need higher limits? Upgrade your plan in the TitanX dashboard or contact our sales team for enterprise options.
</Note>
