Rate limits and quotas
Agent access is metered per token and per workspace, in fixed UTC windows. Limits depend on your plan.
On this page
Quotas by plan
| Limit | Team | Business |
|---|---|---|
| Requests per UTC minute, per token | 60 | 120 |
| Requests per UTC day, per token | 5,000 | 20,000 |
| Requests per UTC day, per workspace (all tokens together) | 15,000 | 60,000 |
| List page size (default and maximum) | 50 | 50 |
| Row budget per report query call | 1,000 | 5,000 |
The Growth plan does not include agent access. To compare plans, see pricing.
How the windows work
Windows are fixed, not sliding. The minute window resets at the start of each UTC minute, and the day windows reset at 00:00 UTC. A request must fit within all three limits: the token's minute, the token's day and the workspace's day.
Counting is shared. If you run several agents or processes on the same token at once, they draw on the same counters.
What counts
Each authorized operation call counts as one request:
- each REST request to an operation;
- each MCP
tools/call; - each page of a list. Fetching three pages costs three requests.
These don't count:
- MCP
initializeandtools/list; - the discovery documents,
/api/v1/openapi.jsonand/llms.txt; - requests rejected before they are authorized, such as a bad token (
401), agent access being off (403 not_enabled), invalid arguments (404) or a missing scope (403 forbidden).
The 429 response
When a request goes over a quota, REST returns 429:
HTTP/1.1 429 Too Many Requests
retry-after: 12
content-type: application/json; charset=utf-8
cache-control: no-store
x-request-id: …
{
"error": {
"code": "rate_limited",
"message": "The rate limit for this credential was exceeded. Retry later."
},
"request_id": "…",
"retry_after_seconds": 12
}Retry-After and retry_after_seconds carry the same whole number of seconds, always at least 1. Over MCP the same body arrives as a tool result with isError: true at HTTP 200. See Errors over MCP.
The API does not send X-RateLimit-* or RateLimit-* headers, and it doesn't report how many requests remain. Use Retry-After as your signal.
Backing off
- On a
429, wait at leastretry_after_secondsbefore the next call on that token. Retrying sooner usually fails again. - If you run several workers on one token, pause all of them, since they share the counters.
- A long wait usually means a daily quota is spent. Resume after 00:00 UTC rather than polling.
- For
500 internal_error, retry with exponential backoff and jitter, and cap the number of attempts. - Page through large lists steadily instead of in bursts. At 50 items a page, 60 requests a minute is up to 3,000 items a minute on one token.
Rows per report query
Report queries (run_semantic_query and run_saved_query) return aggregate rows. Two limits apply to each call:
- The query's own
limit: from 1 to 1,000, with a default of 100. - Your plan's row budget per call: 1,000 on Team and 5,000 on Business.
A call returns at most the smaller of the two. Every plan's row budget is at least 1,000, so in practice a query returns up to its own limit, and never more than 1,000 rows.
Results are never cut silently. When more rows exist than the call returned, the result has truncated: true and truncatedBy says which limit applied. With today's limits that is "query_limit":
- If
limitis below 1,000, raise it and run the query again. - If you are already at 1,000, split the question into narrower queries, for example one per quarter, or add filters or drop a dimension. Each query counts as one request.
truncatedBy can also be "row_budget", meaning your plan's row budget ended the result. Handle it the same way.
Details of the query shape are on the Reports page.