Rate limits
| Limit | Default | Applies to |
|---|---|---|
| Requests per day | 1,000 | Every request except GET /me, per account, reset at midnight UTC |
| AI answers per day | 50 | POST /answers, the answer GraphQL field, and answer_question over MCP |
| Requests per minute | 60 | Per account |
Headers
Every response tells you where you stand:
| Header | Meaning |
|---|---|
RateLimit-Limit | Requests allowed per day |
RateLimit-Remaining | Requests left today |
RateLimit-Reset | Seconds until the daily limit resets |
X-AI-Calls-Limit, X-AI-Calls-Remaining | The same for AI answers |
Retry-After | On a 429: seconds to wait before retrying |
Handling 429
When you get a 429, wait Retry-After seconds. A short wait means the per-minute limit; a long one means the daily limit is used up, so stop until it resets. Over the daily AI limit, data and search endpoints keep working.
import time
def get(url, **kwargs):
for attempt in range(5):
r = session.get(url, **kwargs)
if r.status_code != 429:
r.raise_for_status()
return r.json()
wait = int(r.headers.get("Retry-After", "60"))
if wait > 120: # daily limit: retrying today won't help
raise RuntimeError(r.json()["detail"])
time.sleep(wait)
raise RuntimeError("still rate limited after 5 tries")
Need higher limits for a newsroom, class, or research project? Email hello@chicagopolitics.org with what you're building.