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

# Rate limits

> Fixed per-minute and per-day windows per key, by tier — read the X-RateLimit-* headers rather than hardcoding.

- Source: https://www.dropfans.io/developers/concepts/rate-limits
- Section: Concepts
- OpenAPI: https://www.dropfans.io/developers/openapi.json

## Tiers

| Tier | Per minute | Per day | Who |
| --- | --- | --- | --- |
| Personal | 60 | 5,000 | Personal keys. The budget is shared across **all** personal keys of the same creator — minting more keys does not multiply it. |
| App | 300 | 50,000 | Keys bound to an [approved app](https://www.dropfans.io/developers/concepts/apps-and-approval.md), per key. Higher per-app overrides on request. |
| First party | unlimited | unlimited | Dropfans-operated integrations are exempt. |

Windows are fixed, not rolling: the minute window is the current clock minute, the day window is the current UTC day. Both reset on the boundary.

> [!TIP]
> Always read `X-RateLimit-Limit` off the response instead of assuming a number — env-level and per-app overrides mean the live limit can differ from the defaults printed here.

## Headers on every response

| Header | Meaning |
| --- | --- |
| `X-RateLimit-Tier` | `personal`, `app` or `first_party`. |
| `X-RateLimit-Limit` | Requests allowed in the current minute window. |
| `X-RateLimit-Remaining` | Requests left in the current minute window. |
| `X-RateLimit-Reset` | Unix seconds when the minute window resets. |
| `X-RateLimit-Limit-Day` | Requests allowed in the current UTC-day window. |
| `X-RateLimit-Remaining-Day` | Requests left in the current UTC-day window. |
| `X-RateLimit-Reset-Day` | Unix seconds when the day window resets. |
| `Retry-After` | On `429` only — seconds to wait before retrying. |

First-party responses carry only the tier header; limited tiers carry the full set.

## When you hit the limit

```json
{ "error": "Rate limit exceeded", "code": "rate_limited" }
```

Status `429`, with `Retry-After` in seconds. Wait that long, then resume — do not hammer the boundary.

## The separate posting cap

Creating feed posts has its own cap, independent of the request budget: **5 posts per creator per rolling 24 hours** — the same cap the dashboard composer enforces. Exceeding it also returns `429` with `Retry-After`, but the body is prose without a `code`:

```json
{ "error": "You’ve reached the posting limit (5 per day). Try again in 3 hours." }
```

Tell the two apart by the `code` field: `rate_limited` means request volume; no code on a posts `429` means the daily posting cap.

## Retry wrapper

```javascript tab="Node"
async function callApi(url, options = {}, attempt = 0) {
  const res = await fetch(url, {
    ...options,
    headers: {
      Authorization: 'Bearer ' + process.env.DROPFANS_API_KEY,
      ...(options.headers || {}),
    },
  });
  if (res.status === 429 && attempt < 3) {
    const wait = parseInt(res.headers.get('Retry-After') || '60', 10);
    await new Promise((r) => setTimeout(r, wait * 1000));
    return callApi(url, options, attempt + 1);
  }
  return res;
}
```

```python tab="Python"
import os, time, requests

def call_api(method, url, attempt=0, **kwargs):
    headers = kwargs.pop("headers", {})
    headers["Authorization"] = f"Bearer {os.environ['DROPFANS_API_KEY']}"
    res = requests.request(method, url, headers=headers, **kwargs)
    if res.status_code == 429 and attempt < 3:
        wait = int(res.headers.get("Retry-After", "60"))
        time.sleep(wait)
        return call_api(method, url, attempt + 1, **kwargs)
    return res
```

## Capacity planning

Most throttling comes from polling too much, not from real traffic. Budget it: polling [check-status](https://www.dropfans.io/developers/reference/check-drop-status.md) once a minute costs 1,440 requests a day — well inside the app tier, but over a quarter of a personal day budget. Use the batch endpoints (one call covers up to 200 drops), follow the [polling patterns](https://www.dropfans.io/developers/webhooks/overview.md), and watch that page for webhooks, which will replace most polling.

Next: [Errors](https://www.dropfans.io/developers/concepts/errors.md) or [Webhooks & polling](https://www.dropfans.io/developers/webhooks/overview.md).

---

Previous: [Apps & approval](https://www.dropfans.io/developers/concepts/apps-and-approval.md) · Next: [Errors](https://www.dropfans.io/developers/concepts/errors.md) · All pages: [llms.txt](https://www.dropfans.io/developers/llms.txt)
