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

# Rate limits

> 100 requests per minute per authenticated user on /api. Visitor-facing beacons are not rate-limited. Fails open on rate-limiter errors.

## The one to remember

**100 requests per minute per authenticated user** on `/api/*`.

That is it. Every other endpoint is either unauthenticated (visitor
beacons) or has its own limit (see below).

## What counts

Any request under `/api/*` that carries a valid Clerk bearer token
or an API key. Counted per user, not per IP.

## Headers

Every rate-limited response includes:

* `X-RateLimit-Limit`, the ceiling (100).
* `X-RateLimit-Remaining`, how many are left in the current window.
* `Retry-After`, on a 429, how many seconds until you can try
  again.

## When you hit it

`429 Too Many Requests`. Wait `Retry-After` seconds and try again.

## Fails open

The rate limiter runs on a Durable Object. If the DO is unreachable
for a moment, the request goes through anyway. We would rather
occasionally miss enforcement than block legitimate dashboard traffic
during a Cloudflare incident.

## What is *not* rate-limited

* **`POST /e`**, the exposure beacon. Not rate-limited. This is the
  visitor-facing hot path; a rate limit would drop real data.
* **`POST /err`**, snippet errors. Not rate-limited (uses
  first-occurrence-per-session dedup instead).
* **`POST /m`**, library telemetry. Not rate-limited.
* **`GET /g`**, edge geo. Not rate-limited.
* **`GET /s/*`**, the snippet download. Not rate-limited (served
  from Cloudflare's CDN).
* **`GET /a/*`**, asset downloads. Not rate-limited.
* **`/webhooks/*`**, signature-verified, not rate-limited.

## API keys vs Clerk

Rate limits are per authenticated identity, not per credential type.
A user with two API keys shares the 100/minute across them; a user
with a Clerk session and an API key shares across both.

## For a serious integration

100 requests per minute is enough for a dashboard, a scripted export,
or a small automation. It is not enough for a real product built on
top of the API.

If you are building a real integration:

* **Batch reads.** Most list endpoints support pagination, grab 100
  items at a time.
* **Cache.** The digest endpoints are designed to be pollable and
  cheap.
* **Talk to us.** Higher limits are available on a case-by-case
  basis for legitimate integrations. Email support with the shape
  of your integration and the request rate you actually need.

## Egress

There is no separate egress limit. If your integration downloads
large exports, the download itself is not counted against the API
rate limit (the download URL is a separate endpoint served by R2).

## What we do *not* do

* **Per-IP rate limiting.** Legitimate offices behind a shared IP
  would otherwise share a 100/minute budget.
* **Per-endpoint sub-limits.** All `/api/*` share the same 100/minute
  bucket.
* **Retry with jitter guidance.** Do it. We do not enforce or
  penalize retries beyond the `Retry-After` header.
