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

# Rate limits

> 120 requests a minute, a 429 with Retry-After, and no quota headers.

The Customer API allows **120 requests per minute**. That's the production setting today, and it's generous enough that most integrations never notice it.

The window slides. It isn't a bucket that resets on the minute — the server counts requests made in the last 60 seconds, continuously.

## What counts toward the limit?

One shared budget covers three surfaces:

* every `/api/public/v1/*` route
* the [MCP server](/mcp/introduction) at `/api/mcp`
* both `POST` agent-ingest endpoints

So an assistant querying through MCP and a nightly export job spend from the same 120.

<Warning>
  The limit is counted **per client IP address, not per API key**. Two services sharing one NAT gateway or one Kubernetes egress IP share one budget, even with separate keys. Creating another key does not buy you more throughput.
</Warning>

## What happens when you go over?

You get `429 Too Many Requests` with this body:

```json theme={null}
{ "error": "rate limit exceeded, try again later" }
```

and one header:

```http theme={null}
Retry-After: 12
```

`Retry-After` is a whole number of seconds, at least `1` and never more than `60`. It's the real wait — the time until your oldest request ages out of the window, not a fixed penalty. Sleep for that long and your next call goes through.

## Are there quota headers?

<Note>
  `Retry-After` on a `429` is the rate-limit signal the API sends. Successful responses don't carry `X-RateLimit-Limit`, `X-RateLimit-Remaining` or `X-RateLimit-Reset`, so track your own call count if you need to know where you stand before you hit the limit.
</Note>

## How should you handle it?

Retry on `429`, and honour `Retry-After` rather than guessing.

```python theme={null}
import time, requests

def get(url, key, attempts=4):
    for i in range(attempts):
        r = requests.get(url, headers={"Authorization": f"Bearer {key}"})
        if r.status_code != 429:
            r.raise_for_status()
            return r.json()
        time.sleep(int(r.headers.get("Retry-After", 5)))
    raise RuntimeError("still rate limited after retries")
```

Two habits keep you well clear of the ceiling:

* **Widen the range instead of looping over days.** One call with `range=90d` beats 90 calls with a date filter. See [Filters and time ranges](/api/filters).
* **Prefer the endpoints that answer in one request.** `/industry/metrics` returns the ranking, the time series and per-competitor sentiment together.

<Tip>
  A daily sync of a five-brand workspace is roughly 30 requests. You'd have to run it every 15 seconds to trouble the limit.
</Tip>

## Do you need more than 120?

Email [nitish@fixaeo.com](mailto:nitish@fixaeo.com) with the shape of your workload. The limit is a server setting, not something baked into the build, so it can be raised for an account that needs it.

## Related

<CardGroup cols={2}>
  <Card icon="key" title="Authentication" href="/api/authentication">
    Keys, rotation, and what a `401` means.
  </Card>

  <Card icon="filter" title="Filters and time ranges" href="/api/filters">
    Fetch wider windows in fewer calls.
  </Card>

  <Card icon="code" title="Customer API" href="/api/introduction">
    The full error table and what each status means.
  </Card>

  <Card icon="plug" title="MCP server" href="/mcp/introduction">
    Shares this budget — worth knowing if you run both.
  </Card>
</CardGroup>
