# 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.

```python
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.

---
Source: https://www.chicagopolitics.org/developers/rate-limits · Chicago Politics, an independent, nonpartisan tracker of the Chicago City Council. Guide for agents: https://www.chicagopolitics.org/llms.txt
