URL Statistics
Get click statistics for URLs.
Retrieve aggregated click analytics with flexible grouping, filtering,
and time-range options. Results are computed in a single database round-trip
using $facet aggregation.
Authentication: Optional for scope=anon (public stats on a single URL);
required for scope=all (all URLs owned by the user).
API Key Scope: stats:read, urls:read, or admin:all
Rate Limits:
- Authenticated: 60/min, 5,000/day
- Anonymous: 20/min, 1,000/day
Scopes:
scope=anon+short_code=<alias>— public stats for one URL (if stats are not private)scope=all— aggregate stats across all URLs owned by the authenticated user
Grouping Dimensions: time, browser, os, country, city,
referrer, short_code
Metrics: clicks, unique_clicks
Filtering: Filter by browser, os, country, city, referrer,
or short_code using query params or a JSON filters object.
Authorizations
API key authentication. Pass your key as: Bearer spoo_<your_key>
Query Parameters
Statistics scope: all (authenticated only) or anon (public access).
all— aggregate stats across all URLs owned by the authenticated user. Requires authentication.anon— public stats for a single URL. Requiresshort_codeparameter. No authentication needed (unless stats are private).
all, anon URL alias to query stats for. Required when scope=anon. When scope=all, this is optional and filters stats to a specific URL.
"mylink"
Start of time range. Accepts ISO 8601 datetime string (e.g., 2025-01-01T00:00:00Z) or Unix timestamp in seconds (e.g., 1735689600). If omitted, defaults to the URL creation date.
"2025-01-01T00:00:00Z"
End of time range. Accepts ISO 8601 datetime string (e.g., 2025-12-31T23:59:59Z) or Unix timestamp in seconds (e.g., 1767225599). If omitted, defaults to now.
"2025-12-31T23:59:59Z"
Comma-separated grouping dimensions for the statistics breakdown. Defaults to time if omitted.
Available dimensions:
time— group by time buckets (day/week/month, auto-selected based on range)browser— group by browser name (e.g., Chrome, Firefox, Safari)os— group by operating system (e.g., Windows, macOS, Linux)country— group by countrycity— group by cityreferrer— group by referrer URLshort_code— group by URL alias (only withscope=all)
Multiple dimensions can be combined: time,browser returns time series broken down by browser.
"time,browser"
Comma-separated metrics to include. Defaults to clicks,unique_clicks if omitted.
Available metrics:
clicks— total click countunique_clicks— unique visitor count (deduplicated by IP + User-Agent)
"clicks,unique_clicks"
IANA timezone name for time-based grouping and output formatting (e.g., UTC, America/New_York, Asia/Kolkata). Defaults to UTC.
"UTC"
"America/New_York"
Method 1: JSON Filters Object
JSON string containing dimension filters. Format: {"dimension": ["value1", "value2"]}
Available filter dimensions:
browser— Filter by browser name (e.g., Chrome, Firefox, Safari, Edge)os— Filter by operating system (e.g., Windows, macOS, Linux, iOS, Android)country— Filter by country name (e.g., United States, Canada, Germany)city— Filter by city name (e.g., New York, London, Mumbai)referrer— Filter by referrer URL (e.g., https://google.com, https://twitter.com)short_code— Filter by URL alias (e.g., mylink, promo2024) — not allowed withscope=anon
Value format: Array of strings for each dimension.
Important: Filter values are case-sensitive. Use exact capitalization as stored in the database.
Examples:
{"browser": ["Chrome", "Firefox"]}— Chrome OR Firefox clicks{"country": ["United States", "Canada"], "browser": ["Chrome"]}— US/CA clicks from Chrome{"short_code": ["link1", "link2"]}— Stats for specific URLs (scope=allonly)
Alternative: You can also pass filters as individual query parameters (see browser, os, country, city, referrer parameters below).
"{\"browser\":[\"Chrome\",\"Firefox\"]}"
Method 2: Individual Filter Parameter
Comma-separated browser names. Alternative to using the filters JSON parameter.
Important: Values are case-sensitive. Common values include: Chrome, Firefox, Safari, Edge, Opera, Samsung Internet.
Note: Both filters JSON and individual parameters can be combined.
"Chrome,Firefox"
Method 2: Individual Filter Parameter
Comma-separated operating system names. Alternative to using the filters JSON parameter.
Important: Values are case-sensitive. Common values include: Windows, macOS, Linux, iOS, Android, Chrome OS.
Note: Both filters JSON and individual parameters can be combined.
"Windows,macOS"
Method 2: Individual Filter Parameter
Comma-separated country names. Alternative to using the filters JSON parameter.
Important: Values are case-sensitive. Use full country names as stored in the database (e.g., United States, Canada, United Kingdom, India, Germany, France, Japan).
Note: Both filters JSON and individual parameters can be combined.
"United States,Germany"
Method 2: Individual Filter Parameter
Comma-separated city names. Alternative to using the filters JSON parameter.
Important: Values are case-sensitive. Use exact capitalization as stored in the database.
Note: Both filters JSON and individual parameters can be combined.
"San Francisco,Berlin"
Method 2: Individual Filter Parameter
Comma-separated referrer URLs. Alternative to using the filters JSON parameter.
Important: Values are case-sensitive. Include the full URL including protocol.
Note: Both filters JSON and individual parameters can be combined.
"https://google.com,https://twitter.com"
Response
Successful Response
Response body for GET /api/v1/stats.
metrics uses dynamic keys ({metric}by{dimension}), each mapping to a
list of data-point dicts. Optional fields (short_code,
time_bucket_info, computed_metrics) are absent when not applicable.
Time range metadata inside StatsResponse.
Summary statistics block inside StatsResponse.
Keyed by '{metric}by{dimension}' (e.g. 'clicks_by_browser', 'unique_clicks_by_time'). Each value is a list of data-point objects whose keys are the dimension name, the metric name, and '{metric}_percentage'.
Time bucketing metadata — only present when 'time' is in group_by.
Optional computed metrics added by format_stats_response_with_metadata.

