Skip to main content
Call ratelimit.limit to rate limit a public API by user id, customer id, or IP address. Unkey keeps the counters, so you don’t run Redis. You send the limit and the window on each call, and you return HTTP 429 when data.success is false. ratelimit.multiLimit runs up to 100 checks in one call, and counts them only if they all pass. The rules live in your code. To change the rule for particular identifiers without a deploy, use overrides. A monthly total on an API key is credits, not this window. See Key and identity rate limits.
The endpoint returns HTTP 200 either way. data.reset is Unix milliseconds. Retry-After is in seconds, which is what RFC 6585 allows on a 429. Unkey doesn’t set Retry-After or X-RateLimit-* on this endpoint. The full header list, including what the Compute gateway sends, is on Rate limiting.
Create a root key with the permissions listed on this page under Root Keys in the dashboard sidebar. CLI commands can instead use a session from unkey login with the required permissions. See Permission reference for every permission.
The root key needs unkey:v1:<workspace_id>:projects/<project_id>/ratelimits/namespaces/<namespace_id>#limit for every namespace checked. Use * for the namespace ID to cover all namespaces in a project. The first call with a new namespace name creates it in the workspace’s default project. This also needs unkey:v1:<workspace_id>:projects/<project_id>/ratelimits/namespaces/*#write for that project and #limit permission for each created namespace.

Namespaces

A namespace names what you’re limiting, such as email.send or api.requests. Identifiers are counted separately in each namespace. Refer to a namespace by name (1 to 512 characters, case-sensitive) or ID (rlns_...). A new name is created on first use. Rename or delete namespaces in the dashboard under Ratelimit. A check against a deleted namespace fails with HTTP 410 err:unkey:data:ratelimit_namespace_gone.

ratelimit.limit

string
required
Namespace name or ID, 1 to 512 characters.
string
required
Who or what you’re counting, 1 to 512 characters: a user ID, IP address, tenant, or any stable string.
integer
required
Maximum tokens per window, 1 or more. A matching override replaces it.
integer
required
Window length in milliseconds, 1000 (one second) to 2592000000 (30 days). A matching override replaces it.
integer
default:"1"
Tokens this request spends, 0 or more. 0 checks without counting.

Response

boolean
required
Whether the request fit within the limit. The endpoint returns HTTP 200 either way, so read this field.
integer
required
The limit that applied, from the request or from a matching override.
integer
required
Tokens left in the current window, as a close estimate. 0 on denial.
integer
required
Unix milliseconds when the current window ends.
string
The override that was applied, when one matched.
Every check is recorded in rate limit analytics and writes a ratelimit.limit audit event. To keep a ratelimit.limit call out of analytics and your API request logs, send the header X-Unkey-Metrics: disabled. ratelimit.multiLimit ignores this header.

ratelimit.multiLimit

Send an array of 1 to 100 objects with the same fields as ratelimit.limit. Use it when one action must pass several limits, for example a per-user and a per-organization limit, or a request count and a token budget. Each check must have a different combination of namespace, identifier and duration. A repeated combination returns a 400 error with invalid_input before any namespace is created.
If any check fails, none of them count. A request that passes counts against every limit. Overrides apply per check. A deleted namespace in any check fails the whole call with err:unkey:data:ratelimit_namespace_gone.

Response

boolean
required
true only when every check passed.
object[]
required
One result per check, in request order, each with namespace, identifier, passed, limit, remaining, reset, and overrideId.
Nothing was counted, so remaining on the passing checks doesn’t include this request.

Choosing limits

  • Pick the window for the job. Short windows, such as 20 per 10 seconds, stop bursts. Longer windows, such as 1,000 per hour, work as quotas. Windows of a minute or more are more accurate across regions.
  • Use cost for expensive operations instead of a second namespace.
  • Keep identifiers stable. An identifier with a timestamp or request ID in it is never seen twice, so it limits nothing.
  • Send plan limits per call. To raise limits when a user upgrades, send the new limit with the same identifier and duration. Usage already counted in the window carries over. See Change a limit mid-window.
  • Use an override when one customer needs a different number, instead of a code path.
Last modified on November 13, 2026