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

# Rate limits

> Each installation of your app gets a leaky bucket of 40 requests that drains 2 a second. Read the call limit header, and back off on 429 for the seconds Retry-After gives.

## How the limit works

Every installation of your app (your app on one store) has its own **bucket** of **40 requests**.
Each API call adds one request to the bucket, and the bucket **leaks 2 requests a second**.

* You can make up to 40 calls in a burst.
* After that you can keep going at 2 calls a second (120 a minute).
* A call that would overflow the bucket is refused with **`429 Too Many Requests`**.

The bucket belongs to the installation, not to your app as a whole. Calls on one store never use
up your budget on another store, and another app on the same store has its own bucket.

> [!NOTE]
>
> This limit applies to calls made with an `app_` token. A few actions have their own daily or
> hourly caps on top of it: [sending a notification](https://docs.salesive.com/apps-api/endpoint/notifications/send-notification.md)
> (5 a day) and sending email (10 requests an hour). A call has to fit both.

## Read the call limit header

Every response to your app, a 429 included, carries:

```http theme={null}
X-Salesive-Api-Call-Limit: 32/40
```

The first number is how full your bucket is after this call, the second is its size. When the
first number gets close to the second, slow down.

## When you get a 429

```http theme={null}
HTTP/1.1 429 Too Many Requests
Retry-After: 1
X-Salesive-Api-Call-Limit: 40/40
```

```json theme={null}
{
  "status": 429,
  "success": false,
  "message": "This app has exceeded the API rate limit for this store. Retry after 1 second(s).",
  "data": { "limit": 40, "leakPerSecond": 2, "retryAfter": 1 }
}
```

`Retry-After` is the number of whole seconds until there is room for one more call. Wait that
long, then retry. A refused call did nothing: it is safe to send again, and it never triggers a
webhook.

## Staying under the limit

* **Use webhooks instead of polling.** Let Salesive tell you when something changed, then fetch
  just that record. See [Webhooks](https://docs.salesive.com/apps-api/webhooks.md).
* **Pace bulk work.** If you need to page through a large list, aim for about 2 calls a second per
  store instead of firing everything at once.
* **Retry with the header, not a fixed sleep.** Read `Retry-After` and wait at least that long.

```js theme={null}
async function callSalesive(url, token, attempt = 0) {
  const res = await fetch(url, { headers: { Authorization: `Bearer ${token}` } });
  if (res.status === 429 && attempt < 5) {
    const wait = Number(res.headers.get("retry-after") || 1);
    await new Promise((r) => setTimeout(r, wait * 1000));
    return callSalesive(url, token, attempt + 1);
  }
  return res;
}
```


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