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

# Rate Limits

> Request limits, concurrency caps, and how to handle throttling.

## Credit model

PDFBase uses a simple credit-based billing model:

* **1 credit = 1 output PDF** (or image, or extraction result).
* **Failed requests = 0 credits.** You only pay for successful outputs.
* **Batch of N items = N credits.** A batch request that produces 50 PDFs costs 50 credits.

<Info>
  Specific rate limits and pricing tiers will be finalized at launch. The mechanics below (headers, concurrency, size limits) are stable.
</Info>

## Rate limit headers

Every response includes headers showing your current usage:

```
X-RateLimit-Limit: 300
X-RateLimit-Remaining: 287
X-RateLimit-Reset: 1716120000
X-RateLimit-Concurrent: 3
X-RateLimit-Concurrent-Limit: 20
```

| Header                         | Description                              |
| ------------------------------ | ---------------------------------------- |
| `X-RateLimit-Limit`            | Max requests per minute for your plan    |
| `X-RateLimit-Remaining`        | Requests remaining in the current window |
| `X-RateLimit-Reset`            | Unix timestamp when the window resets    |
| `X-RateLimit-Concurrent`       | Active concurrent renders right now      |
| `X-RateLimit-Concurrent-Limit` | Max concurrent renders for your plan     |

## When you hit a limit

A `429` response includes a `Retry-After` header (in seconds):

```json theme={null}
HTTP/1.1 429 Too Many Requests
Retry-After: 3
X-RateLimit-Limit: 60
X-RateLimit-Remaining: 0
X-RateLimit-Reset: 1716120003

{
  "error": {
    "type": "rate_limit_error",
    "code": "too_many_requests",
    "message": "Rate limit exceeded. Retry after 3 seconds.",
    "param": null
  }
}
```

<Warning>
  Ignoring `Retry-After` and hammering the API will result in progressively longer cooldowns. Respect the header.
</Warning>

## Concurrency limits

PDF rendering is resource-intensive. Your plan has a cap on how many PDFs can be rendered simultaneously. If all slots are occupied, new requests queue for up to 30 seconds before returning `429`.

This is separate from the per-minute rate limit. You can be within your request limit but at your concurrency cap.

### How to stay under concurrency limits

1. **Use batch endpoints** for bulk operations. One batch request uses one concurrency slot regardless of item count.
2. **Use `output: "url"` instead of `output: "base64"`** — URL mode frees the rendering slot as soon as the file is written to storage.
3. **Set reasonable timeouts.** A stuck page (waiting for a broken asset) holds a slot. Use `resource_timeout` to cap it.

## Size limits

| Resource                            | Limit  |
| ----------------------------------- | ------ |
| HTML body                           | 10 MB  |
| Template HTML                       | 5 MB   |
| Uploaded file (for merge/watermark) | 50 MB  |
| Batch items                         | 2,000  |
| Request body (total)                | 50 MB  |
| Generated PDF                       | 100 MB |

Exceeding size limits returns `413`:

```json theme={null}
{
  "error": {
    "type": "invalid_request",
    "code": "html_too_large",
    "message": "HTML body exceeds the 10MB limit. Current size: 12.4MB.",
    "param": "html"
  }
}
```

## Timeout limits

| Operation                | Default timeout | Maximum |
| ------------------------ | --------------- | ------- |
| HTML-to-PDF render       | 30s             | 120s    |
| Template render          | 30s             | 120s    |
| Merge/split/watermark    | 60s             | 300s    |
| Office-to-PDF conversion | 60s             | 300s    |
| OCR extraction           | 120s            | 600s    |
| Batch job (total)        | 30min           | 2hr     |

Pass `timeout` in the request to override the default (up to the maximum):

```json theme={null}
{
  "html": "<h1>Complex report</h1>...",
  "timeout": 60000
}
```
