# https://compresr.ai/docs/api-reference/rate-limits

> Human-readable page: https://compresr.ai/docs/api-reference/rate-limits

Compresr applies tier-based rate limits per API key, enforced per-minute and per-day, with separate quotas for request count and token volume. Every authenticated response carries headers that tell you exactly how much budget you have left. Read those instead of guessing.

## Tiers

The table below is live; it fetches from [`GET /billing/tiers`](/docs/api-reference/billing-tiers) at page-load time, so the numbers are always current.

## Response headers

Every authenticated response includes these headers. Read them on every request to track remaining budget in your own observability stack.

| Header | Meaning |
|---|---|
| `X-RateLimit-Limit-Minute` | Requests-per-minute ceiling for your tier. |
| `X-RateLimit-Remaining-Minute` | Requests left in the current 60-second window. |
| `X-RateLimit-Limit-Day` | Requests-per-day ceiling for your tier. |
| `X-RateLimit-Remaining-Day` | Requests left in the current 24-hour window. |
| `X-RateLimit-Tier` | Tier identifier currently applied to your key (e.g. `tier2`). |
| `Retry-After` | **429 responses only.** Number of seconds to wait before retrying. |

## Handling 429

When you exceed your per-minute or per-day request budget, the API returns `429 Too Many Requests` with a `Retry-After` header. The right pattern is exponential backoff that respects `Retry-After` as a floor.

> If you're hitting 429 routinely under normal load, the right fix is moving to a higher tier, not aggressive client-side retry. Retry handles spikes; tiers handle sustained throughput.

```python
import os
import time
import httpx

def compress_with_retry(payload, *, max_attempts=4):
    url = "https://api.compresr.ai/api/compress/question-specific/"
    headers = {
        "X-API-Key": os.environ["COMPRESR_API_KEY"],
        "Content-Type": "application/json",
    }

    for attempt in range(max_attempts):
        response = httpx.post(url, json=payload, headers=headers, timeout=60)

        if response.status_code != 429:
            response.raise_for_status()
            return response.json()

        retry_after = int(response.headers.get("Retry-After", "1"))
        backoff = max(retry_after, 2 ** attempt)
        time.sleep(backoff)

    raise RuntimeError("Exceeded retry budget")
```

**TypeScript**

```typescript
const sleep = (ms: number) =>
  new Promise<void>((resolve) => setTimeout(resolve, ms));

interface CompressPayload {
  context: string;
  query: string;
  compression_model_name: '{{DEFAULT_MODEL}}';
}

async function compressWithRetry(
  payload: CompressPayload,
  { maxAttempts = 4 }: { maxAttempts?: number } = {},
) {
  const apiKey = process.env.COMPRESR_API_KEY!;

  for (let attempt = 0; attempt < maxAttempts; attempt += 1) {
    const response = await fetch(
      'https://api.compresr.ai/api/compress/question-specific/',
      {
        method: 'POST',
        headers: { 'X-API-Key': apiKey, 'Content-Type': 'application/json' },
        body: JSON.stringify(payload),
      },
    );

    if (response.status !== 429) {
      if (!response.ok) throw new Error(`Failed: ${response.status}`);
      return response.json();
    }

    const retryAfter = Number(response.headers.get('Retry-After') ?? '1');
    const backoff = Math.max(retryAfter, 2 ** attempt);
    await sleep(backoff * 1000);
  }

  throw new Error('Exceeded retry budget');
}
```

**cURL**

```bash
# cURL's built-in retry honours Retry-After on 429/5xx.
curl --retry 3 --retry-delay 2 --retry-all-errors \
  -X POST https://api.compresr.ai/api/compress/question-specific/ \
  -H "X-API-Key: $COMPRESR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "context": "...",
    "query": "...",
    "compression_model_name": "{{DEFAULT_MODEL}}"
  }'
```

  response={

```text
HTTP/1.1 429 Too Many Requests
Retry-After: 12
X-RateLimit-Limit-Minute: 30
X-RateLimit-Remaining-Minute: 0
X-RateLimit-Tier: tier1

{
  "success": false,
  "error": {
    "code": "rate_limit_exceeded",
    "message": "Rate limit hit. Retry in 12 seconds."
  }
}
```
