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

# Rate limits

> How many requests you can send and how to handle 429 responses.

> [!NOTE]
>
> The GetQR API is in beta and is available to selected workspaces. Details may change before the general release.

The GetQR API limits how many requests each API key can send, so one integration can't slow down the API for everyone.

## Limits

| Limit | Value |
| - | - |
| Requests per API key | 600 per minute |

The limit is counted over a sliding one-minute window and applies to all endpoints together. The [health check](https://docs.getqr.com/api/endpoints/health.md) doesn't need a key and doesn't count.

## Rate limit headers

Responses to requests with a valid API key carry these headers, error responses included:

| Header | Description |
| - | - |
| `X-RateLimit-Limit` | Maximum number of requests per window. |
| `X-RateLimit-Remaining` | Requests left in the current window. |
| `X-RateLimit-Reset` | When the window resets, as a Unix timestamp in milliseconds. |
| `Retry-After` | Seconds until the window resets, rounded up. Wait this long before retrying. |

## When you go over the limit

Over the limit, the API answers `429` with the `rate_limit_exceeded` code and the same headers:

```http theme={null}
HTTP/1.1 429 Too Many Requests
X-RateLimit-Limit: 600
X-RateLimit-Remaining: 0
X-RateLimit-Reset: 1792764060000
Retry-After: 37

{
  "error": {
    "code": "rate_limit_exceeded",
    "message": "Too many requests.",
    "doc_url": "https://getqr.com/account/api-docs#error-rate_limit_exceeded"
  }
}
```

Wait until the reset time before sending more requests. Add jitter so several workers don't retry at the same moment, and back off exponentially on `5xx` errors:

```javascript theme={null}
async function getqrFetch(url, options = {}, maxRetries = 5) {
  for (let attempt = 0; ; attempt++) {
    const res = await fetch(url, {
      ...options,
      headers: {
        Authorization: `Bearer ${process.env.GETQR_API_KEY}`,
        ...options.headers,
      },
    });

    const retryable = res.status === 429 || res.status >= 500;
    if (!retryable || attempt >= maxRetries) return res;

    // On 429, wait for Retry-After (seconds). Otherwise back off: 1s, 2s, 4s…
    const retryAfter = Number(res.headers.get("Retry-After"));
    const wait =
      res.status === 429 && retryAfter > 0
        ? retryAfter * 1000
        : 1000 * 2 ** attempt;
    const jitter = Math.random() * 250;

    await new Promise((r) => setTimeout(r, wait + jitter));
  }
}
```

> [!TIP]
>
> Only retry `POST /api/v1/qrs` with an `Idempotency-Key` header. Then a retry never creates a second QR code. See [Idempotency](https://docs.getqr.com/api/introduction.md#idempotency).

## Stay under the limit

* Watch `X-RateLimit-Remaining` and slow down before it reaches 0.
* Use [bulk QR creations](https://docs.getqr.com/api/endpoints/bulk-qr-creations.md) instead of one request per QR code.
* Fetch up to 100 results per page with `pageSize=100`. See [Pagination](https://docs.getqr.com/api/introduction.md#pagination).
* Cache QR images: downloads return an `ETag`, so you can send `If-None-Match` and get `304 Not Modified` when nothing changed.

## What's next

> [card] [Errors](https://docs.getqr.com/api/errors.md)

> [card] [QR codes](https://docs.getqr.com/api/endpoints/qr-codes.md)


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.