Time windows
How analytics windows resolve, how growth is compared, and what coverage tells you.
2 min read
Every analytics endpoint answers for a window of days. You choose it with time_range, or with explicit dates.
Choosing a window#
| Parameter | Values |
|---|---|
time_range | 7d, 14d, 30d, 90d, 180d, 365d, all, a quarter like 2026-Q3, or Q3 for that quarter this year. |
start_date + end_date | YYYY-MM-DD, both inclusive. Send both. They override time_range. |
Windows are UTC calendar days and include today. 30d on 2026-10-14 means 2026-09-15 through 2026-10-14.
The previous period is the same number of days immediately before the window. For quarter tokens it is the previous quarter.
The window object#
Windowed responses echo what they resolved, so you never have to recompute it:
{
"time_range": "30d",
"kind": "rolling",
"start": "2026-09-15",
"end": "2026-10-14",
"days": 30,
"previous_start": "2026-08-16",
"previous_end": "2026-09-14"
}Coverage#
Not every platform has data for every day. coverage says how much of the window is backed by data:
{
"start": "2026-08-16",
"embedded_boundary": "2026-09-15",
"history_used": true,
"current_window_coverage_days": 30,
"previous_window_coverage_days": 11,
"growth_basis": "like_for_like",
"warnings": ["Previous window has data for 11 of 30 days; growth is not shown."]
}| Field | |
|---|---|
embedded_boundary | Today minus 29 days. Recent days come from each platform’s live series; older days come from stored history. |
history_used | true when the window reached into stored history. |
current_window_coverage_days, previous_window_coverage_days | How many days of each window have data. |
growth_basis | How growth was compared (below). |
warnings | Plain-language reasons when something was left out. Show them to users. |
Growth#
Growth compares the window with the previous period. It is null when the previous window has data for fewer than half of its days, because comparing against a mostly empty baseline produces numbers like +3,441% that mean nothing. The reason is in coverage.warnings.
Show null growth as a dash, never as 0
Never coerce null growth to 0. Zero claims “no change”; null means “not comparable”. The Listener apps show a dash (—) in that case, and your users will expect the same.
Like-for-like growth on long windows#
For windows longer than 30 days (90d, quarters, custom ranges), growth is compared like for like: only platforms whose data covers at least half of the previous window take part, and both windows are summed over exactly those platforms. coverage.growth_basis is "like_for_like" and coverage.growth_platforms lists the platforms compared. If no platform qualifies, growth is null.
Endpoints with fixed windows#
The dashboard KPIs (GET /v1/analytics/dashboard) and per-show platform stats (GET /v1/shows/{show_id}/platforms) accept 7d, 30d or 90d. On 90d, impressions, downloads and engagement rate cover all 90 days from history, but likes, comments, posts, top content and follower changes stay on the last 30 days, because there is no long-range source for them. metric_windows (and each tile’s window) says which window every metric used. Those 30-day metrics, and EMV, have no growth on 90d.
Custom ranges#
Custom ranges are the most precise way to align with a reporting period:
curl -G https://api.listener.com/v1/analytics/reach \
-H "Authorization: Bearer $LISTENER_API_KEY" \
-d start_date=2026-07-01 \
-d end_date=2026-09-30That is equivalent to time_range=2026-Q3, and its previous period is 2026-Q2.