Skip to main content

Query Examples

Common SQL query patterns for Unkey Analytics including daily verification counts, per-key usage, billing aggregations, and error rates.
5 min read

This guide provides SQL query examples for common analytics scenarios covering all the use cases from the legacy API and more. All examples use ClickHouse SQL syntax and work with the /v2/analytics.getVerifications endpoint.

Using Queries in API Requests#

When making API requests, you need to format the SQL query as a JSON string on a single line. Here's how:

Tip

Each example below shows both the readable multi-line SQL and the single-line JSON format you can copy directly into your API requests.

Usage Analytics#

Use this for: High-level usage metrics, health monitoring, and trend analysis.

Key patterns: Total counts, outcome breakdowns, time series analysis.

Total verifications in the last 7 days#

Count total verifications across all keyspaces in the last 7 days.

Verifications by outcome#

Break down verifications by outcome to understand success vs failure rates.

All outcomes in a single row#

Get all verification outcomes in one row with individual columns for each outcome type.

All outcomes per key#

Get outcome breakdown for each API key in a single row per key.

Daily verification trend#

Track daily verification patterns over the last 30 days.

Hourly breakdown for today#

Analyze hourly verification patterns for today with outcome breakdown.

Usage by User#

Use this for: Understanding user behavior, identifying power users, tracking user activity over time.

Key patterns: User ranking, activity trends, specific user analysis.

All users ranked by usage#

Rank all users by their total verification usage over the last 30 days.

Usage for a specific user#

Analyze usage patterns for a specific user over the last 30 days.

Top 10 users by API usage#

Identify your most active users by verification count.

Daily usage per user#

Track daily verification patterns for each user over 30 days.

Keyspace Analytics#

Use this for: Comparing keyspace performance, usage across different keyspaces, keyspace-specific analysis.

Key patterns: Keyspace comparison, success rates, per-keyspace breakdowns.

Usage per keyspace#

Compare usage across all keyspaces to identify most active endpoints.

Usage for a specific keyspace#

Analyze detailed usage patterns for a specific keyspace over 30 days.

Compare multiple keyspaces#

Calculate success rates for multiple keyspaces to compare performance.

Key Analytics#

Use this for: Individual API key analysis, identifying problematic keys, key-specific usage patterns.

Key patterns: Key ranking, error analysis, specific key monitoring.

Usage per key#

Identify your most frequently used API keys over the last 30 days.

Usage for a specific key#

Analyze detailed usage patterns for a specific API key.

Keys with most errors#

Find API keys that are generating the most errors.

Tag-Based Analytics#

Use this for: Custom metadata filtering, endpoint analysis, user segmentation using tags.

Key patterns: Tag filtering, endpoint breakdowns, custom attribute analysis.

Tags allow you to add custom metadata to verification requests for filtering and aggregation.

Filter by single tag#

Count verifications for requests with a specific tag.

Filter by multiple tags (OR)#

Count verifications matching any of multiple tags.

Filter by multiple tags (AND)#

Count verifications matching all specified tags.

Group by tag#

Aggregate verifications by individual tags to see usage patterns.

Breakdown by endpoint (using path tag)#

Analyze request volume by API endpoint over the last 24 hours.

Note

This query uses the raw table for detailed tag analysis. For longer time ranges, consider using aggregated tables and pre-filtered tags.

Billing & Usage-Based Pricing#

Use this for: Usage-based billing implementation, credit tracking, user tier calculation.

Key patterns: Credit aggregation, billing cycles, tier determination, cost analysis.

Monthly credits per user#

Calculate monthly credit consumption per user for billing.

Current billing period credits#

Calculate credit usage for a specific billing period.

Credit-based tier calculation#

Determine user tiers based on monthly credit consumption.

Daily credit usage and cost#

Track daily credit consumption and calculate estimated costs.

Advanced queries#

Use this for: Moving averages, trend smoothing, and advanced insights.

Key patterns: Trend smoothing and window functions.

Moving average (7-day)#

Calculate 7-day moving average to smooth out daily fluctuations.

Using Aggregated Tables#

For better performance on large time ranges, use pre-aggregated tables:

Hourly aggregates#

Query hourly verification counts for the last 7 days.

Daily aggregates#

Query daily verification counts for the last 30 days.

Monthly aggregates#

Query monthly verification counts for the last year.

Filling Gaps in Time Series (WITH FILL)#

When querying time series data, you may have periods with no activity that result in missing time points. ClickHouse's WITH FILL clause ensures all time periods are included in results, filling gaps with zeros.

Note

WITH FILL is particularly useful for creating charts and visualizations where you need consistent time intervals, even when there's no data for some periods.

Warning

WITH FILL only works when grouping by the time column alone. To include outcome breakdowns or other dimensions, use sumIf() to pivot them into columns (see the last example below).

Note

Type matching: The time column type varies by table:

  • Hourly/Minute tables: DateTime - use toStartOfHour(now() - INTERVAL N HOUR)
  • Daily/Monthly tables: Date - use toDate(now() - INTERVAL N DAY) or toDate(toStartOfMonth(...))

WITH FILL expressions must match the column type exactly.

Hourly data with gaps filled#

Get hourly verification counts for the last 7 days, including hours with zero activity.

Daily data with gaps filled#

Get daily verification counts for the last 30 days, ensuring all days are present.

Monthly data with gaps filled#

Get monthly verification counts for the last 12 months with all months included.

Filling gaps with aggregations#

For more complex queries that aggregate by outcome, use a subquery or pivot approach instead of WITH FILL with multiple GROUP BY columns.

Note

WITH FILL only works when grouping by time alone. For outcome breakdowns, use sumIf() to pivot outcomes into separate columns as shown above.

Tips for Efficient Queries#

  1. Always filter by time - Use indexes by including time filters
  2. Use aggregated tables - Hourly/daily/monthly tables for longer ranges
  3. Add LIMIT clauses - Prevent returning too much data
  4. Filter before grouping - Use WHERE instead of HAVING when possible