Skip to main content
Use ratelimit.limit to check one identifier against one limit. Use ratelimit.multiLimit to run up to 100 checks in one call, counted only if they all pass. You send the limit and duration with each call, so the rules live in your code. To change the rule for particular identifiers without a deploy, use overrides.
You need a root key with the permissions listed on this page. Create one in the dashboard under Settings > Root Keys, and pass it as Authorization: Bearer <root key>. See Permission reference for every permission.
The root key needs ratelimit.*.limit or ratelimit.<namespace_id>.limit for every namespace checked. The first call with a new namespace name creates it, which also needs ratelimit.*.create_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.
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.
  • Use an override when one customer needs a different number, instead of a code path.
Last modified on September 29, 2026