---
title: "Rate limits"
description: "Per-key limits, the 429 response, and how caching keeps you under them."
canonical: "https://docs.nimbusmint.bot/rate-limits/"
---
> Index: https://docs.nimbusmint.bot/llms.txt

# Rate limits

Each private key has its own limit, applied as a token bucket:

| Setting | Default |
| --- | --- |
| Sustained rate | **60 requests per minute** |
| Burst | **20 requests** |

The bucket holds up to 20 requests and refills at one per second, so short bursts are fine as long as the
average stays under 60 a minute. If you need more, ask us; limits are set per key. A service-wide
cap also protects the API as a whole.

## When you hit the limit

The API returns `429` with a `Retry-After` header (seconds) and `{"code": "rate_limited", ...}`. Wait at least that
long before the next request from that key.

### curl

```sh
# -i shows the Retry-After header on a 429
curl -i https://api.nimbusmint.bot/partner/v1/health \
  -H "Authorization: Bearer $NIMBUS_PRIVATE_KEY"
```

### Node

```js
async function nimbusGet(url, attempt = 0) {
  const res = await fetch(url, {
    headers: { Authorization: `Bearer ${process.env.NIMBUS_PRIVATE_KEY}` },
  });
  if (res.status === 429 && attempt < 3) {
    const wait = Number(res.headers.get('Retry-After') ?? '1');
    await new Promise((r) => setTimeout(r, wait * 1000));
    return nimbusGet(url, attempt + 1);
  }
  return res;
}
```

### Python

```python
import time

def nimbus_get(url, params=None, attempt=0):
    res = requests.get(url, headers=HEADERS, params=params, timeout=10)
    if res.status_code == 429 and attempt < 3:
        time.sleep(int(res.headers.get("Retry-After", "1")))
        return nimbus_get(url, params, attempt + 1)
    return res
```

> **The limit is per key, not per user:** Every request made with a key counts against that key's bucket, however many of your users caused it. A bot
> that calls the API once per user command will hit the limit as soon as it gets busy, which is exactly when you
> least want it to. Design for the number of collections you track, not the number of people using your product.

## Stay under the limit

- **Cache responses yourself.** `/hits` returns `cache_ttl_s` (currently 30): reuse the answer for that many seconds
  instead of calling again; the API caches for that long anyway. Every response is sent with `Cache-Control: no-store`,
  so HTTP caches and proxies will not do this for you.
- **Key the cache by the question, not the user.** Use `contract`, `chain_id`, `since` and `until` (and `top`) as the
  key. A thousand users asking about the same collection are one cache entry.
- **Coalesce concurrent requests.** When ten commands arrive before the first answer comes back, send one request
  and give all ten the same result (a "single-flight" lock per cache key).
- **Share one cache** across your bot's processes or shards, for example in Redis, so each process does not fetch the
  same answer separately.
- **Do not poll `/hits`.** Call it when a user asks (for example on `/gas`), not on a timer per collection.
- **Sync `/mints` incrementally.** Run it as a background job, not per user request: page with `limit=500`, store
  `next_cursor`, and resume from it on the next run instead of re-reading the whole window. Every few minutes is
  plenty.
- **Call `/health` rarely.** Once at startup and once a day is enough to watch your key's expiry.
- **Show something useful on a `429`.** Serve the last cached answer (and say how old it is) or your own data, rather
  than failing the command.

> **Tip:** With a 30-second cache, one busy collection costs at most two calls a minute no matter how many people run
> `/gas`.

## Retrying safely

- Retry only `429` and `503`. Never retry `400`, `401` or `403`: they will fail the same way and still use your limit.
- Wait at least `Retry-After` seconds, add a little random jitter, and cap the number of attempts (three is plenty).
  Retrying immediately, or from every shard at once, keeps you limited for longer.
- Log every `429` with the endpoint and parameters. Repeated `429`s on the same question usually mean a missing cache.

## Planning for growth

- **Ask before you need it.** Limits are set per key, and we can raise yours. Tell us before a launch, a big drop or a
  marketing push, with the requests per minute you expect after caching.
- **Use separate keys for separate jobs** (for example one for your bot and one for a `/mints` sync), so a busy job
  cannot starve the other. A service-wide cap still applies to all keys together.

> **Do not work around the limit:** Spreading traffic over extra keys, rotating keys or rotating IP addresses to avoid `429`s breaks the
> [Terms](https://nimbusmint.bot/terms/) and can get your keys revoked. If the limit is too low for honest, cached use, ask us to raise it.
