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

# Rate limits

> How request quotas work, how to read the rate limit headers, and how to back off when you hit a 429

Every request is checked against two windows: a per-minute limit and a per-day limit. A request must fit both. Quotas are tracked per user and per API surface, so heavy list traffic never starves your campaign calls. All of your keys share one pool; each teammate has their own. Each window starts at the first request it counts, not at midnight, and a request that is refused costs nothing.

<Note>
  These limits apply to the REST API. The [MCP server](/mcp/tools#rate-limits) has its own limits, counted per user: 60 requests a minute and 5,000 a day.
</Note>

## Quotas by surface

| Surface | Endpoints | Per minute | Per day |
| - | - | - | - |
| Lists, folders, imports & exports | `/business/lists*`, `/business/folders*`, `/business/imports*`, `/business/exports*`, `/business/jobs*` | 120 | 10,000 |
| Campaigns & knowledge hubs | `/business/campaigns*`, `/business/campaign-templates*`, `/business/scheduled-sends*`, `/business/knowledge-hubs*` | 30 | 1,000 |
| Account & reference reads | `/business/me`, `/business/credits*`, `/business/accounts`, `/business/team/*`, `/business/writing-styles`, `/business/integrations`, `/business/prospects/filter-options` | 120 | 10,000 |
| Contacts | `/business/contacts*` | 120 | 10,000 |
| Prospect search | `/business/prospects/search*` | 20 | 1,000 |
| Company search | `/business/companies/search*` | 20 | 1,000 |
| Vocabulary reads | `/business/prospects/autocomplete`, `/business/companies/autocomplete`, `/business/companies/filter-options` | 60 | 5,000 |
| Saved searches | `/business/saved-searches*` | 60 | 5,000 |
| Agents | `/business/agents*` | 30 | 2,000 |
| Research | `/business/research*` | 30 | 1,000 |
| Analytics | `/business/analytics*` | 20 | 1,000 |
| Website intent | `/business/website-visitors`, `/business/website-tracking` | 30 | 2,000 |

<Note>
  Prospect search is also gated by [credits](/concepts/credits). In practice your credit balance bounds search throughput before the rate limit does, so budget credits first and treat the 20/minute ceiling as a burst cap. The same applies to agent deliveries, research runs, and enrichment riding on imports — the spend, not the request quota, is usually the binding constraint. The research per-minute quota is sized for polling `GET /business/research/runs/{runId}/events`.
</Note>

## Reading the headers

Every response that reaches a quota check, success or 429, carries three headers:

| Header | Meaning |
| - | - |
| `RateLimit-Limit` | Quota of the binding window |
| `RateLimit-Remaining` | Requests remaining in the binding window |
| `RateLimit-Reset` | Seconds until the binding window resets |

The binding window is whichever of the two windows has fewer remaining requests — the one that will stop you first. If both have the same number remaining, the headers bind to whichever resets later. This is why `RateLimit-Limit` can appear to jump between values like 120 and 10,000 across consecutive responses: you are seeing the minute window and the day window trade places as the tighter constraint.

You can watch the headers on any call:

```bash theme={null}
curl -i https://api.tryfuse.ai/api/v1/business/me \
  -u "af_YOUR_KEY:"
```

```text theme={null}
HTTP/2 200
RateLimit-Limit: 120
RateLimit-Remaining: 87
RateLimit-Reset: 22
```

## Handling 429s

When you exceed a limit, the API returns `429` with the standard [error envelope](/concepts/errors) and a `Retry-After` header giving the seconds to wait. A `429` passed through from the agents service can arrive without `Retry-After`, so fall back to a short wait:

```json theme={null}
{
  "error": {
    "code": "RATE_LIMITED",
    "message": "You have exceeded the rate limit. Please retry after the window resets.",
    "param": null,
    "doc_url": "https://docs.fuseai.com/concepts/errors#rate_limited",
    "request_id": "req_8fK2mQ4x"
  }
}
```

Honor `Retry-After`. When both windows are exhausted at once, it reflects the window that resets last, so sleeping for `Retry-After` seconds is always sufficient — you will never wake up still rate limited by the other window.

A minimal backoff pattern:

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

def request_with_backoff(method, url, **kwargs):
    while True:
        response = requests.request(
            method, url, auth=("af_YOUR_KEY", ""), **kwargs
        )
        if response.status_code != 429:
            return response
        time.sleep(int(response.headers.get("Retry-After", "5")))

response = request_with_backoff(
    "GET", "https://api.tryfuse.ai/api/v1/business/lists"
)
```

For long-running jobs, it is cheaper to avoid the 429 entirely: check `RateLimit-Remaining` as you go and pause for `RateLimit-Reset` seconds when it approaches zero.

<Warning>
  A `500` is never a quota signal. If the rate limiter itself fails, you get `500 UNEXPECTED_ERROR`, not a 429 — retry it like any other server error rather than treating it as exhaustion. See [Errors](/concepts/errors).
</Warning>

## Staying under the limits

* Batch where the API lets you. Building a list from a saved search moves rows server-side in one call instead of paging results through prospect search — see [Build a list from search](/guides/build-a-list-from-search).
* Use [pagination](/concepts/pagination) cursors at the largest page size that fits your processing, rather than many small pages.
* Exports are asynchronous by design: one call starts the job, and polling the job status is far cheaper against your quota than re-fetching list contents — see [Export a list](/guides/export-a-list).


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