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

# Rate Limiting

> Understand and work with API rate limits

Every API key has configurable rate limits to protect the platform and ensure fair usage.

## How It Works

<Note>
  Rate limiting uses a **sliding window** algorithm tracked per API key. The window continuously rolls forward — it is not reset at fixed intervals.
</Note>

* **Per-minute limit** - Maximum requests in any rolling 60-second window
* **Per-day limit** - Maximum requests in any rolling 24-hour window

Both limits are enforced independently. If either is exceeded, requests return `429 Too Many Requests`.

## Rate Limit Headers

<Info>
  Every response includes these headers so you can proactively monitor usage without making extra API calls.
</Info>

| Header                  | Description                                     |
| ----------------------- | ----------------------------------------------- |
| `X-RateLimit-Limit`     | Maximum requests per minute for this key        |
| `X-RateLimit-Remaining` | Remaining requests in the current minute window |
| `X-RateLimit-Reset`     | Unix timestamp when the minute window resets    |

## Handling Rate Limits

<Warning>
  When the limit is exceeded, the API returns `429 Too Many Requests` with a `Retry-After` header. Your integration **must** respect this header — continuing to send requests will extend the backoff period.
</Warning>

When you exceed the limit, you'll receive:

```json theme={"theme":{"light":"github-light","dark":"github-dark"}}
{
  "error": {
    "code": "rate_limit_exceeded",
    "message": "Rate limit exceeded. Retry after 12 seconds.",
    "details": {
      "retry_after": 12
    }
  }
}
```

The response also includes a `Retry-After` header with the number of seconds to wait.

### Best Practices

<CardGroup cols={2}>
  <Card title="Respect Retry-After" icon="clock">
    Always wait the number of seconds specified in the `Retry-After` header before retrying.
  </Card>

  <Card title="Exponential Backoff" icon="arrow-up-right-dots">
    If you continue hitting limits, implement exponential backoff with jitter.
  </Card>

  <Card title="Use Batch Endpoints" icon="layer-group">
    For bulk operations, use batch endpoints (`/ideaclouds/batch`, `/content/batch`) to reduce request count.
  </Card>

  <Card title="Monitor Headers" icon="chart-line">
    Track `X-RateLimit-Remaining` and throttle proactively before hitting the limit.
  </Card>
</CardGroup>

## Default Limits

| Plan    | Per Minute | Per Day       |
| ------- | ---------- | ------------- |
| Default | 60         | 10,000        |
| Custom  | Up to 500  | Up to 100,000 |

Rate limits are configured per API key when creating the key in the Dealership Manager.

## Example: Retry Logic

<CodeGroup>
  ```bash cURL theme={"theme":{"light":"github-light","dark":"github-dark"}}
  # Retry with Retry-After header
  MAX_RETRIES=3
  ATTEMPT=0

  while [ "$ATTEMPT" -le "$MAX_RETRIES" ]; do
    HTTP_CODE=$(curl -s -o response.json -w "%{http_code}" \
      -D headers.txt \
      -X POST "https://api.app.hrizn.io/v1/public/content/batch" \
      -H "X-API-Key: $API_KEY" \
      -H "Content-Type: application/json" \
      -d @batch.json)

    if [ "$HTTP_CODE" -ne 429 ]; then
      break
    fi

    RETRY_AFTER=$(grep -i 'retry-after' headers.txt | tr -d '\r' | awk '{print $2}')
    RETRY_AFTER=${RETRY_AFTER:-5}
    echo "Rate limited. Retrying in ${RETRY_AFTER}s..."
    sleep "$RETRY_AFTER"
    ATTEMPT=$((ATTEMPT + 1))
  done
  ```

  ```typescript TypeScript theme={"theme":{"light":"github-light","dark":"github-dark"}}
  async function apiCallWithRetry(url: string, options: RequestInit, maxRetries = 3) {
    for (let attempt = 0; attempt <= maxRetries; attempt++) {
      const response = await fetch(url, options);

      if (response.status === 429) {
        const retryAfter = parseInt(response.headers.get('Retry-After') || '5');
        console.log(`Rate limited. Retrying in ${retryAfter}s...`);
        await new Promise(r => setTimeout(r, retryAfter * 1000));
        continue;
      }

      return response;
    }
    throw new Error('Max retries exceeded');
  }
  ```

  ```python Python theme={"theme":{"light":"github-light","dark":"github-dark"}}
  import requests
  import time

  def api_call_with_retry(url: str, headers: dict, payload: dict, max_retries: int = 3):
      for attempt in range(max_retries + 1):
          resp = requests.post(url, json=payload, headers=headers)

          if resp.status_code != 429:
              return resp

          retry_after = int(resp.headers.get("Retry-After", 5))
          print(f"Rate limited. Retrying in {retry_after}s...")
          time.sleep(retry_after)

      raise Exception("Max retries exceeded")
  ```

  ```php PHP theme={"theme":{"light":"github-light","dark":"github-dark"}}
  function apiCallWithRetry(string $url, array $headers, array $payload, int $maxRetries = 3) {
      for ($attempt = 0; $attempt <= $maxRetries; $attempt++) {
          $ch = curl_init($url);
          curl_setopt_array($ch, [
              CURLOPT_POST => true,
              CURLOPT_HTTPHEADER => $headers,
              CURLOPT_POSTFIELDS => json_encode($payload),
              CURLOPT_RETURNTRANSFER => true,
              CURLOPT_HEADER => true,
          ]);
          $response = curl_exec($ch);
          $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);

          if ($httpCode !== 429) {
              $headerSize = curl_getinfo($ch, CURLINFO_HEADER_SIZE);
              return json_decode(substr($response, $headerSize), true);
          }

          preg_match('/Retry-After:\s*(\d+)/i', $response, $matches);
          $retryAfter = (int) ($matches[1] ?? 5);
          echo "Rate limited. Retrying in {$retryAfter}s...\n";
          sleep($retryAfter);
      }

      throw new Exception("Max retries exceeded");
  }
  ```
</CodeGroup>

<Tip>
  For generating large volumes of content across multiple sites, see the [Bulk Content Generation](/guides/bulk-content-generation) guide for a complete throttling and parallelization strategy.
</Tip>
