Skip to main content

Query rate limit analytics

Query rate limit requests and token usage with the analytics.getRatelimits endpoint.
4 min read

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.

For the request and response schemas, see the API reference.

Authenticate the request#

Use a root key with one of these permissions:

  • ratelimit.*.read_analytics to query every rate limit namespace in the workspace
  • ratelimit.<namespaceId>.read_analytics to query a specific namespace

Unkey always restricts queries to the root key's workspace. A namespace-scoped permission also adds a namespace_id filter to every table in the query. You can grant a root key access to multiple namespaces by adding one scoped permission for each namespace.

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. Use a namespace_id filter to select one or more namespaces when the root key has wildcard access:

You can omit this filter. A wildcard root key then queries every namespace in the workspace, while a namespace-scoped root key returns only data permitted by its ratelimit.<namespaceId>.read_analytics permissions. A query cannot bypass these automatic workspace and namespace filters.

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.

Public tableGranularityRetentionBest for
ratelimits_v1Individual request1 monthRecent request details and exact request times
ratelimits_per_minute_v1Minute7 daysRecent dashboard charts
ratelimits_per_hour_v1Hour30 daysDaily and weekly trends
ratelimits_per_day_v1Day100 daysLonger reports
ratelimits_per_month_v1Month3 yearsLong-term trends

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. Unkey automatically filters workspace_id, so you don't need to include it in a query.

ColumnTypeDescription
request_idStringUnique request ID
timeInt64Request time as a Unix timestamp in milliseconds
workspace_idStringWorkspace ID, automatically filtered
namespace_idStringRate limit namespace ID
identifierStringIdentifier that was limited
passedBoolWhether the request passed the rate limit
latencyFloat64Time spent on the rate limit check in milliseconds
override_idStringApplied override ID, when an override matched
limitUInt64Applied token limit
remainingUInt64Tokens remaining after the request
reset_atInt64Reset time as a Unix timestamp in milliseconds
tokensUInt64Tokens requested

The minute, hour, day, and month tables contain pre-aggregated rows.

ColumnTypeDescription
timeDateTime or DateStart of the aggregation interval
workspace_idStringWorkspace ID, automatically filtered
namespace_idStringRate limit namespace ID
identifierStringIdentifier that was limited
passedInt64Number of requests that passed the rate limit
totalInt64Number of requests
total_tokensInt64Number of requested tokens
passed_tokensInt64Number of tokens from passed requests
latency_avgAggregateFunctionState for calculating average latency with avgMerge
latency_p75AggregateFunctionState for calculating p75 latency with quantilesTDigestMerge(0.75)
latency_p99AggregateFunctionState for calculating p99 latency with quantilesTDigestMerge(0.99)

Use ClickHouse aggregate merge functions when selecting latency from an aggregated table:

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.