Skip to main content
The POST /v2/analytics.getRatelimits endpoint runs SQL queries against your rate limit analytics. Use it from a trusted backend with a root key. Never expose a root key in browser code.

Send a query

Send a JSON object with a query string. The response uses the same shape as analytics.getVerifications: meta.requestId identifies the API request, and data contains an array of result objects.
Queries follow the shared SQL and resource limits described in Query restrictions. CTEs, subqueries, UNION, and EXCEPT are supported. The query must contain a positive literal filter in one of these forms. You can optionally qualify namespace_id with a table alias:
You can name at most 10 unique namespace IDs. Every named namespace must exist and your root key must be authorized to access it. The root key needs ratelimit.<namespaceId>.read_analytics for each namespace, or the ratelimit.*.read_analytics wildcard permission.

Choose a table

Choose the least granular table that supports the chart or report. Aggregated tables scan fewer rows, while the raw table exposes individual requests and fields such as the applied limit, remaining tokens, and reset time. Your workspace retention setting controls the time range that a query can request. If you omit a time filter, Unkey automatically constrains results to your workspace retention range. A query that stays within your workspace quota can request a range beyond a table’s retention, but it returns only the rows that remain in that table. For example, a 30-day query against the minute table can contain partial data because that table retains 7 days. Select the hour table when you need the complete 30-day range.

Reference available columns

The raw table contains one row for each rate limit request. The minute, hour, day, and month tables contain pre-aggregated rows.

Build a zero-filled time series

Use WITH FILL to return every minute, including intervals without requests. This query produces passed, blocked, and total metrics for both requests and tokens, which supports a dashboard chart without client-side gap filling.

Combine multiple identifiers

Filter with IN and omit identifier from GROUP BY to combine several identifiers into one result. This example returns daily totals for three customers.

Paginate an identifier breakdown

Group by identifier to build a table with usage totals and the last request time. The secondary identifier sort makes ordering stable when multiple rows have the same request count. Keep the same ordering while changing OFFSET for subsequent pages.
Last modified on July 23, 2026