Archive API docs
    Jump to

    Narrow by kind with a prefix — q: queries, m: mutations, t: types, g: guides, f: fields and arguments.

    Rate limits & plans

    The Archive API applies two independent limits to /api/v2. The request rate limit is the same on every plan. The weighted cost limit is sized by your plan. 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. That is the default; Archive can tune it per environment. 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 the work it asks for. The price is drawn from a token bucket. The bucket holds up to its capacity, refills at a steady rate, and each request withdraws its cost.

    Each workspace has its own bucket. A workspace in an organization takes its capacity from the organization’s plan. It 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 at least 5. The floor covers the fixed work of authenticating and loading workspace context. A refund never takes your net cost below it.
    • A post-execution refund. A connection’s cost is estimated up front from the page size you request. After execution, the estimate is reconciled. If a page returns fewer records than you asked for, the unused per-record cost is refunded. Your actual cost never exceeds 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 names the limit you hit, and Retry-After is authoritative in both cases.

    Rate limits by plan

    The table lists each plan’s bucket capacity and refill rate.

    Weighted rate-limit bucket by plan. The request rate limit is 5 requests per second on every plan.
    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.

    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.

    A mutation costs a base of 50, plus 1 for each field you select in its payload, nested fields included. For example, createCollection(input: …) { collection { id } userErrors { message } } selects four fields (collection, id, userErrors, message) and costs 54. Select only the payload fields you read.

    38 weighted cost per request

    search_base
    30
    ceil(0.3 × 20)
    +6
    edges { node } wrappers
    +2
    What this buys on each plan
    Trial 7 req/min
    Startup 78 req/min
    Growth 300 req/min *
    Enterprise 300 req/min *
    Agency 300 req/min *

    * capped by the request rate limit, not by the bucket.

    The calculator opens on a real request — this one:

    query.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
        }
      }
    }
    variables.json
    {
      "first": 10
    }
    Headers
    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 RateLimit-Policy and RateLimit headers, modeled on the IETF RateLimit header fields draft. They are the source of truth for your current quota. Read them; don’t hard-code a capacity from the table above:

    Rate-limit headers
    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 timestamp) 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.