Skip to content

This is the staging environment's documentation. It is a draft and may change at any time.

Rate limits

Direct API access is limited per organization. A program should read its limits from the response headers rather than hard-code them, because plans and their numbers can change.

Quota Window
Burst 60 seconds
Daily The calendar day, in UTC
Monthly The calendar month, in UTC
  • The quotas belong to the organization. All of its machine clients share them. There is no separate quota per client.
  • The size of each quota depends on the organization’s plan, which is one of free, small, medium, or large. A plan’s quotas are the ones this environment enforces.
  • A plan change reaches API clients within 10 minutes. A client picks it up when it next gets an access token. This needs the urn:zitadel:iam:user:metadata scope in the token request. See Authentication.
  • A request that the API refuses for its scope, role, subscription, or kind of client still counts, so probing isn’t free. Once a quota is used up, such a request gets 429 instead of its 403. A request that fails authentication is not counted.
  • Some operations have their own limits as well. AI operations (askOpportunities) also count against the organization’s AI spending budget and its premium units for the day. A search that ranks by meaning uses a premium unit too. The API counts premium units itself, so the gateway’s quotas don’t include them. See the API’s answer.

A call can be refused in front of the API or by the API itself. The two answers look different, so read the response by what it carries.

Refused by Body Headers
The gateway, for machine clients Empty X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Reset
The API A Problem (rate-limited) Retry-After, RateLimit-Policy, RateLimit

For a machine client’s calls the gateway refuses first. Its 429 has no body. It has no Retry-After, no RateLimit headers, and no Problem.

HTTP/1.1 429 Too Many Requests
X-RateLimit-Limit: 3000, 3000;w=2592000
X-RateLimit-Remaining: 0
X-RateLimit-Reset: 1203400
Header Meaning
X-RateLimit-Limit The exhausted rule’s limit and its window w in seconds, such as 3000, 3000;w=2592000.
X-RateLimit-Remaining What is left in that window. It is 0 on a 429.
X-RateLimit-Reset Seconds until that window resets.

The same headers also appear on the gateway’s successful responses. The example is a free plan organization that has used its 3,000 requests for the month.

The response doesn’t name the quota. Read it from the window w and the limit:

w (seconds) Quota
60 Burst.
86400 Daily.
2592000 Monthly. The calendar month is reported as 30 days. X-RateLimit-Reset is exact.

Wait X-RateLimit-Reset seconds before you retry. Refused requests still count. A client that keeps calling after a 429 keeps adding to the counter, so it doesn’t regain budget inside the window.

For everything the gateway doesn’t cover, the API refuses with a 429, a Problem of type rate-limited, and Retry-After.

HTTP/1.1 429 Too Many Requests
Content-Type: application/problem+json
Retry-After: 41000
RateLimit-Policy: "org-burst";q=20;w=60, "org-day";q=100;w=86400
RateLimit: "org-burst";r=7;t=40, "org-day";r=0;t=41000
{
"type": "https://fedwright.com/problems/rate-limited",
"title": "Too Many Requests",
"status": 429,
"traceId": "4bf92f3577b34da6a3ce929d0e0e4736",
"limit": "org-day",
"resetsAt": "2026-11-08T00:00:00Z"
}
  • Retry-After is the number of seconds until the used-up limit’s window resets. If several limits are used up, it is the latest.
  • limit names the quota that is used up, and resetsAt says when it starts again.
  • A request the API refuses with rate-limited uses no quota.

Two refusals carry their own problem types:

Type When
ai-budget-exceeded An ask that the organization’s AI spending budget can’t cover. Retry-After is the end of the budget’s window. The budget counts what asks cost, not how many there are.
premium-quota-exceeded An ask that the organization’s premium units for the day can’t cover. limit is org-premium-day, and resetsAt is the next midnight UTC. A refused ask uses no units.

A search that ranks by meaning is not refused when the premium units run out. It runs as a search by words instead, and its semantic.reason is premiumQuota.

The RateLimit-Policy and RateLimit headers

Section titled “The RateLimit-Policy and RateLimit headers”

Where the API applies a limit it reports the caller’s own limits on the response, successful or not. They follow the IETF HTTPAPI rate-limit header fields, which are still a draft. Parse them leniently and ignore anything you don’t recognize.

Header Contents
RateLimit-Policy Each limit’s name, its quota q, and its window w in seconds.
RateLimit For each limit in the policy, the requests r still allowed and the seconds t until reset.
RateLimit-Policy: "org-burst";q=20;w=60, "org-day";q=100;w=86400
RateLimit: "org-burst";r=7;t=40, "org-day";r=62;t=41000
  1. Don’t retry at once. Wait the number of seconds the response gives: X-RateLimit-Reset for an empty-bodied 429, Retry-After for a Problem.
  2. If the wait is longer than your program can hold, such as hours for a daily quota, stop and report it instead of sleeping inside the call.
  3. A 429 is returned before the operation runs, so retrying any operation, including a POST, can’t repeat its effect.
  4. Spread calls out to stay under the burst quota. A client that checks RateLimit or X-RateLimit-Remaining can slow down before it is refused.

See Errors for the Problem format.