Skip to main content
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