Rate limits
Every API request is counted against two hourly budgets. Both are enforced, both scale with your plan, and every response tells you where you stand.
Two windows
| Window | Counts | Keyed on |
|---|---|---|
| Account | Every request from every key you own, combined | The account owner |
| Per key | One key's own requests | The key |
The account window is checked first. It is keyed on the owner rather than the key, so issuing more keys does not buy more requests. The per-key window sits underneath and contains the damage when one key runs away or leaks.
Both are rolling windows, not a counter that empties on the hour. Requests age out gradually as the hour moves.
The MCP server authenticates the same way and draws on the same budgets. A tool call from an AI client and a curl against /query cost the same.
How much you get
Both budgets rise with your plan, and an account with no active paid plan sits on the entry-tier floor.
The exact ceilings are not published, because they are tuned server-side without a release and any number printed here would go stale silently. Your own limit is on every response you make:
Read it once at startup rather than hard-coding a figure, and your client stays correct through a plan change or a retune.
Reading the headers
Every response carries the window that applies to it:
| Header | Meaning |
|---|---|
X-RateLimit-Limit | The hourly ceiling for the reported window |
X-RateLimit-Remaining | Requests left in it |
X-RateLimit-Reset | Seconds until the window frees, not a timestamp |
Normally these describe the per-key window. On an account-level rejection they describe the account window instead, which is how you tell the two apart without parsing the message.
X-RateLimit-Reset counts seconds forward from now. Add it to the current time rather than reading it as an epoch.
When you hit the limit
The response is 429 with Retry-After in seconds:
HTTP/1.1 429 Too Many Requests
Retry-After: 1800
X-RateLimit-Limit: 600
X-RateLimit-Remaining: 0
X-RateLimit-Reset: 1800
The message names which budget ran out: account rate limit exceeded or api key rate limit exceeded. Wait Retry-After seconds before trying again. Retrying sooner spends the request and gets another 429.
Staying under
- Watch
X-RateLimit-Remainingand slow down as it falls, rather than waiting for the429. It is on every response, so this costs nothing. - Ask for more per request. One breakdown with
limit: 100beats a hundred single-row queries, and counts as one request. - Do not poll faster than your data changes. Outside realtime, numbers move on the order of minutes, so a query every few seconds spends budget to receive the same answer.
- Give each job its own key. The account budget is shared either way, but separate keys keep one runaway job from starving the rest through the per-key window.
Next steps
- Query reference: fetch more per request
- Errors: the other failures, and which are worth retrying
Ready to take control of your web analytics? Try Statable free for 30 days. No credit card required, full feature access, built for GDPR. Start your free trial or view a live demo.