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

# Rate Limits

> Each connection can make 100 requests per 60 seconds through BundleUp. How the limit works and how to handle it.

BundleUp limits each **connection** to **100 requests per 60 seconds**. The limit protects your users’ accounts (and your OAuth app’s standing with the provider) from runaway loops, and stops one busy account from crowding out the rest.

## How the limit is counted

* **Per connection.** Every connection has its own budget. A thousand connections can each make 100 requests a minute at the same time.
* **Across all three APIs.** Proxy, Unified API and MCP requests on the same connection share one budget.
* **Per request, not per attempt.** Automatic [retries](/docs/guides/proxy/retries) happen inside one request and don’t use extra budget. (They do count toward [usage](/docs/concepts/requests#what-counts-toward-usage).)
* **Every MCP message counts.** `initialize`, `tools/list` and each `tools/call` are separate requests.

## When you go over

```mermaid theme={null}
sequenceDiagram
    participant B as Your backend
    participant X as BundleUp
    participant P as Provider

    Note over B,X: 100 requests in the last 60 s on conn_abc123
    B->>X: Request #101
    X-->>B: 429 Too Many Requests<br/>Retry-After: 60
    Note over X,P: Nothing is sent to the provider

    B->>X: Request on conn_xyz789
    X->>P: Forwarded normally
    P-->>X: 200
    X-->>B: 200
```

Once a connection has made 100 requests in 60 seconds, the next request is rejected with `429` and never reaches the provider. Other connections aren’t affected.

On the Proxy and MCP the response is:

```http theme={null}
HTTP/1.1 429 Too Many Requests
Retry-After: 60
Content-Type: application/json

{"status": 429, "code": "rate_limit", "message": "Too many requests"}
```

On the Unified API, the status is also `429`, with the Unified API’s [error envelope](/docs/api-reference/errors#unified-api-errors).

## BundleUp’s limit vs the provider’s

Providers have their own rate limits, often per user, per app, or per workspace. You can get a `429` from either side:

| `429` from | How to tell | What to do |
| - | - | - |
| **BundleUp** | JSON body with `"code": "rate_limit"` (Proxy, MCP) or the Unified API error envelope. `Retry-After: 60`. | Slow down on this connection. Wait before retrying. |
| **The provider** | The provider’s own body and headers. Often includes its own `Retry-After` or rate-limit headers. | BundleUp already retried idempotent requests for you. If it still failed, back off according to the provider’s headers. |

## Staying under the limit

* **Spread out bulk work.** For a sync over many records, queue the work and process it at a steady rate per connection (for example, one request every 700 ms) instead of all at once.
* **Use bigger pages.** Fetch 100 items per request instead of 10.
* **Cache stable data.** User profiles, channel lists and project lists rarely change between requests.
* **Don’t poll faster than you need to.** Prefer the provider’s webhooks where it offers them.

## Handling 429 in code

```typescript theme={null}
async function withBackoff(call: () => Promise<Response>) {
  for (let attempt = 0; attempt < 5; attempt++) {
    const response = await call();
    if (response.status !== 429) return response;

    const retryAfter = Number(response.headers.get('Retry-After') ?? 1);
    await new Promise((r) => setTimeout(r, retryAfter * 1000));
  }
  throw new Error('Still rate limited after 5 attempts');
}

const response = await withBackoff(() =>
  client.proxy('conn_abc123').get('/user/repos'),
);
```


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