Delegated access to Zev products
Rate limits
How many delegated-access calls your app can make, what happens when it goes over, and how to stay under.
Limits are per environment, live and test separately, so all the connections of one environment share them.
| Call | Limit |
|---|---|
| Token (code exchange and refresh together) | 100 per minute |
| Revoke | 50 per minute |
| Authorize (browser link) | 30 per minute, per user IP address |
Authorize URL (POST …/authorize-url, server) | 300 per minute |
Every call also counts against your environment’s overall API budget, the
same requestsPerMinute every ZevAuth endpoint shares.
Over a limit, the token and revoke endpoints return 429 with a
Retry-After header in seconds:
{
"error": "rate_limited",
"error_description": "Over 100 token requests per minute for this environment. Retry in 23s.",
"reason": "rate_limited",
"error_reason": "rate_limited"
}
A browser authorize over the limit redirects back to your callback with
error=temporarily_unavailable&error_reason=rate_limited. The server call
answers 429 with Retry-After and the same JSON shape.
A 429 always carries Retry-After. Wait at least that long before the next
call.
Staying under
- Reuse access tokens. They last 10 minutes. Refresh shortly before
expires_inruns out, not on every call. - Serialise refreshes per connection. One refresh at a time per
grant_id. Two at once with the same token look like theft and revoke the connection’s refresh tokens. See Refresh tokens. - Back off on 429. Wait for
Retry-After, then retry. Sustained 429s are usually a loop in your code. - Do not retry
invalid_grant. It will not succeed without the user.
Updated at, Wednesday, October 21, 2026