# Rate limits

> Each plan sets a rate in requests per minute: 20, 40 or 120. amodb counts requests in a sliding 60 second window. Every response carries X-RateLimit-Limit, X-RateLimit-Remaining and X-RateLimit-Reset. Over the limit you get HTTP 429 with status_code 25 and a Retry-After header in seconds. Cached responses still count.

## Limits by plan

| Requests per minute | Requests per day at full rate |
| ------------------- | ----------------------------- |
| 20                  | 28,800                        |
| 40                  | 57,600                        |
| 120                 | 172,800                       |

Every plan includes the same endpoints and data. See [pricing](https://amodb.dev/pricing/) for the plan names and prices.

## How the window works

amodb counts the requests of each key over the last 60 seconds. The window slides: a request made at 12:00:30 stops counting at 12:01:30. There is no reset at the top of the minute, so a steady rate works better than bursts.

The key check and the rate limit run before the edge cache. A response served from cache still counts as one request.

## Response headers

Every call made with a key returns these headers:

| Header                  | Meaning                                                     |
| ----------------------- | ----------------------------------------------------------- |
| `X-RateLimit-Limit`     | Requests allowed per 60 seconds for this key.               |
| `X-RateLimit-Remaining` | Requests left in the current window.                        |
| `X-RateLimit-Reset`     | Seconds until the oldest counted request leaves the window. |
| `Retry-After`           | On 429 only: seconds to wait before the next call.          |

## When you hit the limit

The response is HTTP 429 with the TMDB error body:

```json
{
  "success": false,
  "status_code": 25,
  "status_message": "Your request count (41) is over the allowed limit of (40)."
}
```

Wait for `Retry-After` seconds, then retry. Do not retry in a tight loop.

```js
async function amodb(path) {
  for (let attempt = 0; attempt < 3; attempt++) {
    const res = await fetch(`https://api.amodb.dev${path}`, {
      headers: { Authorization: `Bearer ${process.env.AMODB_KEY}` },
    });
    if (res.status !== 429) return res.json();
    const wait = Number(res.headers.get("Retry-After") ?? 1);
    await new Promise((r) => setTimeout(r, wait * 1000));
  }
  throw new Error("amodb: still rate limited after 3 attempts");
}
```

```python
import os
import time
import requests

def amodb(path):
    for _ in range(3):
        res = requests.get(
            f"https://api.amodb.dev{path}",
            headers={"Authorization": f"Bearer {os.environ['AMODB_KEY']}"},
            timeout=10,
        )
        if res.status_code != 429:
            return res.json()
        time.sleep(int(res.headers.get("Retry-After", "1")))
    raise RuntimeError("amodb: still rate limited after 3 attempts")
```

## Stay under the limit

- Cache responses on your side. Details change rarely; 6 hours is a safe default.
- Use `append_to_response` to get details, credits and images in one request instead of three.
- Spread batch jobs: at 40 requests per minute, send one request every 1.5 seconds.
- Read `X-RateLimit-Remaining` and slow down before it reaches 0.

## Questions and answers

### Do all my keys share one limit?

Each key is counted on its own window, and every key gets the rate of your plan. Use one key per app so a busy app cannot slow down another.

### Is there a daily cap?

No. The only limit is the per minute rate. At 40 requests per minute a key can make up to 57,600 requests a day.

### Do image requests count?

No. Images on img.amodb.dev need no key and do not count toward your rate.

## Related pages

- [Pricing](https://amodb.dev/pricing/): amodb plans differ only in requests per minute: 20, 40 or 120. Every plan includes all TMDB v3 and OMDb compatible data. Prepaid, no renewal, no trial.
- [Errors](https://amodb.dev/errors/): Every amodb error with its HTTP status, TMDB status_code and message, plus the OMDb error shape. What each one means and what your client should do next.
- [Authentication](https://amodb.dev/authentication/): How to send your amodb key: api_key in the query, an Authorization Bearer header, or apikey for OMDb calls. Key format, storage, rotation and the 401 errors.
- [Quickstart](https://amodb.dev/quickstart/): Make your first amodb call: get a key, request movie details in curl, JavaScript, Python, PHP or Go, then load the poster from img.amodb.dev. Under 2 minutes.

Updated: 2026-10-18. Source: https://amodb.dev/rate-limits/
