# Rate limits & plans

The Archive API applies two independent limits to `/api/v2`: a **request rate limit**, which is the same on every plan, and a **weighted cost limit**, which your plan sizes. Compare the plans below, then price your own query with the calculator.

## The request rate limit

Each workspace can send up to **5 requests per second** to `POST /api/v2`, on every plan (the default; it is environment-tunable). This limit counts requests, not cost: a cheap query and an expensive one each count as one request. Requests over the limit are rejected with HTTP 429 and a `Retry-After` header:

```json
{
  "errors": [
    {
      "message": "Rate limit exceeded for this workspace. Retry in 1 second(s).",
      "extensions": { "code": "RATE_LIMIT_EXCEEDED" }
    }
  ]
}
```

A rate-limit 429 also carries `X-RateLimit-Limit`, `X-RateLimit-Remaining`, and `X-RateLimit-Reset` headers.

## The weighted cost limit

The second limit prices each request by how much work it asks for and draws that price from a **token bucket**: the bucket has a capacity, refills at a steady rate, and each request withdraws its cost. Each workspace has its own bucket. A workspace that belongs to an organization gets its capacity from the organization’s plan, but never shares a balance with the organization’s other workspaces. Two rules affect the cost of a request:

- **A per-request floor.** Every request costs a minimum of **5**, covering the fixed overhead of authenticating and loading workspace context. A refund never takes your net cost below this floor.
- **A post-execution refund.** A connection’s cost is estimated up front from the page size you request, then reconciled after execution: if a page returns fewer records than you asked for, the unused per-record cost is refunded. Your actual cost is never more than the estimate.

A request that asks for more than the bucket has left is rejected before any field is resolved, with HTTP 429 and a `Retry-After` header:

```json
{
  "errors": [
    {
      "message": "Rate limit exceeded. Retry after 3 seconds.",
      "extensions": { "code": "RATE_LIMIT_EXCEEDED" }
    }
  ]
}
```

A rejected request costs nothing and doesn’t drain the bucket further. Both limits return `RATE_LIMIT_EXCEEDED`; the message identifies which one you hit, and `Retry-After` is authoritative in both cases.

## Rate limits by plan

Each workspace draws from a token bucket: the bucket holds up to its **capacity**, refills at a steady **rate**, and every request withdraws its weighted cost.

| Plan       | Bucket capacity | Refill rate | Full refill | Bucket                                                     |
| ---------- | --------------- | ----------- | ----------- | ---------------------------------------------------------- |
| Trial      | 500             | 5 / s       | 100 s       | Own bucket — never pooled, even inside an organization     |
| Startup    | 5,000           | 50 / s      | 100 s       | Per workspace                                              |
| Growth     | 15,000          | 250 / s     | 60 s        | Per workspace                                              |
| Enterprise | 60,000          | 1,000 / s   | 60 s        | Per workspace                                              |
| Agency     | 15,000          | 250 / s     | 60 s        | Each org workspace drains its own bucket at Growth numbers |

The request rate limit — **5 requests per second** (300 per minute) — is the same on every plan and is not raised by any of them. Negotiated overrides replace these numbers per workspace or per organization, so read your live quota from the `RateLimit-Policy` header rather than hard-coding a capacity.

> **Plan labels in RateLimit-Policy**
>
> `RateLimit-Policy` quotes a short plan label rather than the name above: `demo` for Trial, and `base` for a workspace with no recognised current-lineup subscription, which draws the same bucket as Startup. Treat the label as an opaque string for correlating the two headers.

## Query cost calculator

A connection’s page cost is `search_base + ceil(per_edge × first)`, plus what you select inside it and any operation surcharge. Every request costs at least **5**; every mutation costs a flat **50**.

> **Estimates only — the response headers are the source of truth**
>
> The calculator prices the connection and its wrapper selection. Fields nested deeper inside `node` add to the real cost, and pages that return fewer records than requested are partially refunded. Because the per-record term grows with `first`, smaller pages cost less. Page with the cursor loop and request only the fields you need, per the [Pagination guide](/api/v2/docs/guides/pagination).

The calculator opens on a real request — this one:

```graphql
query ItemsDefault($first: Int, $after: String) {
  items(first: $first, after: $after) {
    totalCount
    edges {
      node {
        id
        provider
        type
        caption
        takenAt
        originalUrl
        archivePublicUrl
        currentEngagement {
          likes
          comments
          views
          earnedMediaValue
        }
      }
    }
    pageInfo {
      hasNextPage
      endCursor
    }
  }
}
```

```json
{
  "first": 10
}
```

```http
Authorization: Bearer docs_demo_token_0000000000000000000000
WORKSPACE-ID: 6ccefa76-e8ba-5ab0-9c60-e48a9e235a4a
```

## Reading the RateLimit headers

Every `/api/v2` response that carries rate-limit state includes the standard IETF `RateLimit-Policy` and `RateLimit` headers. These are the source of truth for your current quota. Read them rather than hard-coding any capacity from the table above:

```http
RateLimit-Policy: "<plan>";q=<capacity>;w=<window>
RateLimit: "<plan>";r=<remaining>;t=<reset-epoch>
```

In `RateLimit-Policy`, `q` is the bucket capacity and `w` is the number of seconds to refill the full bucket. In `RateLimit`, `r` is how much you have remaining and `t` is the epoch second at which the bucket is full again.

## Backing off

- On a 429, honor the `Retry-After` header: wait the stated number of seconds before retrying.
- Watch the `RateLimit` header’s `r` (remaining) and `t` (reset) values to pace your weighted-cost spend and avoid draining the bucket.
- Prefer smaller pages and request only the fields you need; both reduce cost.

> **Extended cost telemetry**
>
> More detailed per-request cost telemetry is available under the alpha program. See the [Alpha features guide](/api/v2/docs/guides/alpha-features).
