Copy these queries to answer common questions. Send each as the query string of analytics.getVerifications or analytics.getRatelimits. You don’t need a workspace filter.
Some of these reach back seven days or a calendar month, which is longer than some plans keep data. Check your retention first. If a query fails with err:user:bad_request:query_range_exceeds_retention, shorten the window.
Verifications
Total verifications in the last 24 hours
The per-hour rollup already sums verifications, so read sum(count) rather than count().
Outcomes per hour for the last day
Valid versus rejected, per day
sumIf lets you split one scan into several totals. Per-day time is a Date, so compare with today().
Usage per customer this month
external_id is your ID for the identity behind each key, so it’s a good way to bill.
Keys hitting rate limits or running out of credits
Latency percentiles from the raw table
Latency stats have to come from the raw table. Raw time is in milliseconds, so convert the bound.
Verifications per tag
Tags are an array on each row. arrayJoin gives one row per tag, and has keeps rows with a specific tag.
Hourly buckets from the raw table
When you need a dimension the rollups don’t carry, such as region, bucket the raw rows yourself.
Gateway-verified versus API-verified
Keys verified by a Compute gateway key-auth policy carry source = 'gateway' and the app_id of the app that fronted them. Direct keys.verifyKey calls carry source = 'api' and an empty app_id.
Rate limits
Pass rate per namespace over the last day
Most rejected identifiers
Checks that used an override
Combining tables
Use a CTE to answer a two-step question.
If a query is rejected, the troubleshooting page maps each error to its fix. Last modified on September 29, 2026