Every API key is subject to two independent limits: a daily quota and a short burst limit. Both scale with your plan, and every response tells you exactly where you stand.
The total number of requests you can make per calendar day (UTC). It resets at midnight UTC — the exact moment is given by the X-RateLimit-Reset header.
A cap on how many requests you can fire in a short rolling window, to keep traffic smooth. Hitting it returns a Retry-After telling you how long to wait.
| Plan | Requests / day | Burst limit |
|---|---|---|
| Free | 100 | 1 req / 3s |
| Starter | 2,500 | 1 req / 2s |
| Pro | 10,000 | 2 req / s |
| Business | 100,000 | 3 req / s |
See pricing for what each plan includes. Need more than 100,000 requests a day? Contact us about higher limits.
Read these from every response to track your usage without guessing.
| Header | Sent | Meaning |
|---|---|---|
X-RateLimit-Limit | Every response | Your plan's total requests per day. |
X-RateLimit-Remaining | Every response | Requests left in the current daily window. |
X-RateLimit-Reset | Every response | Unix epoch seconds when the daily window resets (next midnight UTC). |
Retry-After | On a burst 429 | Seconds to wait before retrying after a burst-limit hit. |
X-RateLimit-Burst-Limit | On a burst 429 | Max requests allowed inside the short burst window. |
X-RateLimit-Burst-Remaining | On a burst 429 | Requests left in the burst window (0 when throttled). |
Both limits return HTTP 429 with a JSON body. The daily limit returns Daily request limit exceeded; the burst limit returns Rate limit exceeded along with a Retry-After (in seconds).
// HTTP/1.1 429 Too Many Requests
// X-RateLimit-Limit: 2500
// X-RateLimit-Remaining: 0
// X-RateLimit-Reset: 1771200000
{ "error": "Daily request limit exceeded" }Honor Retry-After when it's present, and otherwise back off exponentially with a cap. The official SDKs do this for you.
async function getJson(url, key, attempt = 0) {
const res = await fetch(url, { headers: { "X-API-Key": key } });
if (res.status === 429) {
"js-comment">// Respect Retry-After when present (burst), else back off exponentially.
const retryAfter = Number(res.headers.get("Retry-After"));
const waitMs = retryAfter
? retryAfter * 1000
: Math.min(30_000, 2 ** attempt * 1000);
await new Promise((r) => setTimeout(r, waitMs));
return getJson(url, key, attempt + 1);
}
return res.json();
}/v1/cards/search?ids= to fetch many cards in a single request.X-RateLimit-Remaining.