
Watch time, retention, and impressions sound like three numbers a single API call should return together. AIOZ Stream's Analytics API splits them across three different endpoints instead, and one of those eight documented metrics, retention, isn't available from the simplest one at all. That's not an oversight. It's a real constraint worth understanding before wiring up dashboard widgets that assume every metric works the same way.
TL;DR:
AIOZ Stream's Analytics API is built around three distinct endpoints, and picking the wrong one for a given dashboard widget is the easiest mistake to make before actually reading through all three. POST /api/analytics/metrics/data/:metric/:aggregation returns a single number, a metric reduced by an aggregation like count, total, average, or sum. POST /api/analytics/metrics/bucket/:metric/:breakdown returns that same kind of metric, but split across a dimension, by media ID, country, device type, browser, and so on, useful for a leaderboard or a geographic breakdown. POST /api/analytics/metrics/timeseries/:metric/:interval returns a value per hour or per day across a date range, the shape an actual trend chart needs. All three take a required from/to UNIX timestamp range and an optional filter_by object (media_ids, media_type, continents, countries, device_types, os, browsers, tags), so filtering works consistently across all three even though the output shape doesn't.
The documented metrics, with their exact definitions: play, "the number of times your content has been played." start, "the number of times playback was started." end, "the number of times playback has ended with the content watched until the end." impression, "the number of times your content has been loaded and was ready for playback." watch_time, "the cumulative time in seconds that the user has spent watching your content." view, "the number of times your content has been watched in playback." retention, "the total amount of time a user has continuously engaged with your content." play_rate, "the ratio that calculates the number of plays your content receives divided by its impressions."
Worth being direct about something the documentation doesn't clarify: play, start, and view read as near-synonyms. All three describe a viewer engaging with playback, and nothing in the docs states what operationally distinguishes a "play" from a "start" from a "view." A reasonable guess is that play fires on the initial user action (clicking the play button), start fires when the player actually begins rendering frames (which can lag behind the click on a slow connection), and view counts something closer to a qualifying watch session, but that's inference, not documented fact. Building a dashboard that reports all three side by side without checking whether they actually diverge in real traffic risks displaying three numbers that are effectively the same metric measured three times, confusing rather than clarifying for whoever reads the dashboard. The practical fix: pull all three for a real video with meaningful traffic before deciding which ones earn a spot on the dashboard, rather than assuming distinct value from the names alone.
The aggregated-metrics endpoint's documented :metric list is play, start, end, impression, watch_time, view, six values, verified directly against the docs. retention and play_rate are absent from that list; they only appear as valid values on the breakdown and timeseries endpoints. That's not an inconsistency to work around, it lines up with what retention actually means as a concept. A retention curve, the standard way the video industry visualizes this metric, is a graph plotting the percentage of viewers still watching at each point in a video's timeline, not a single number. A steep early drop typically signals a mismatch between what a thumbnail promised and what the video delivers, while a sudden cliff partway through usually marks a specific moment, an awkward transition or a slow section, where attention breaks. None of that is visible in one aggregate figure. Collapsing retention into a single sum or average the way watch_time can be summed would throw away the one thing that makes it useful, so AIOZ's decision to only expose it through bucket or timeseries, where it can actually be plotted as a curve, is a defensible design choice once you see what the metric is for, even though the docs themselves never explain the reasoning.
A real analytics dashboard usually needs four kinds of widgets, and each one maps to exactly one of the three endpoints once the retention constraint above is accounted for. A single summary number, total plays this month, average watch time per session, pulls from the aggregated endpoint, one request per number. A trend line, plays or impressions per day over the last 30 days, pulls from the timeseries endpoint with interval=day. A retention curve for one video pulls from the timeseries endpoint too, filtered to a single media_id, since that's the only way to get retention as a curve rather than a flat total. A leaderboard, top 10 videos by watch time, or a geographic breakdown, watch time by country, pulls from the bucket endpoint with the relevant breakdown value, media-id or country.
A worked example, pulling a week of watch time as a daily trend line:
POST /api/analytics/metrics/timeseries/watch_time/day
{
"from": 1788652800,
"to": 1789257600,
"filter_by": {
"media_ids": ["abc123"]
}
}The response returns one data entry per day in range, each with a metric_value and an emitted_at timestamp, exactly the shape a charting library expects without further reshaping. Swap watch_time for retention on the same request and the same shape becomes a retention curve instead of a watch-time trend, the endpoint and interval logic doesn't change, only the metric name does.
A dashboard with four or five widgets, each refreshing on a schedule, adds up in request volume faster than a single integration test suggests, especially once real users start loading it concurrently. AIOZ Stream's documented limits cap reads at 500 requests per minute, comfortable for a single dashboard session but worth checking against actual expected concurrent usage before assuming it'll never be an issue, the rate limits article covers the exact headers and handling pattern for exactly this kind of read-heavy integration.
Which endpoint should I use to get a single summary number, like total plays this month?
The aggregated-metrics endpoint, POST /api/analytics/metrics/data/:metric/:aggregation, returns one reduced value per request.
Why can't I get retention from the aggregated-metrics endpoint?
Retention and play_rate are only documented on the breakdown and timeseries endpoints. Retention specifically only makes sense as a curve over time or a video's timeline, not a single aggregate figure, which is likely why it's excluded from the single-number endpoint.
What's the actual difference between play, start, and view?
The documentation defines all three but doesn't state what operationally distinguishes them in practice. Pull all three for a real, high-traffic video and compare before assuming a dashboard needs to display all of them separately.
How do I build a per-video retention curve?
Use the timeseries endpoint with metric=retention, filtered to a single media_id via filter_by, and a day or hour interval depending on the video's length.
Can I filter analytics by country or device type?
Yes. All three endpoints accept the same filter_by object, including continents, countries, device_types, os, and browsers, alongside media_ids, media_type, and tags.
Will a busy analytics dashboard hit AIOZ Stream's rate limits?
Reads are capped at 500 requests per minute. A handful of widgets refreshing periodically stays well under that, but concurrent dashboard sessions or aggressive polling intervals are worth checking against that ceiling directly rather than assuming it never applies.

Choose OBS encoder settings for AIOZ Stream: the documented 1080p30 values, the missing 720p figure, NVENC vs x264, keyframes, 60 fps and a test procedure.

Set up OBS Studio for AIOZ Stream: build a scene, connect with a Custom RTMP service and stream key, enter the documented output settings, and confirm the stream is live.

Seven steps to go live on AIOZ Stream with OBS or PRISM: stream key, session form, RTMP credentials, bandwidth math, and the first two minutes after you start.

How live streaming on AIOZ Stream works: stream keys, sessions and saved media, OBS and PRISM setup over RTMP, restreaming, statistics, archiving, and what the docs leave out.

What separates a real web3 streaming platform from marketing language, and how AIOZ Stream's DePIN network, on-chain payments and W2E rewards measure up.

WCAG's five real video accessibility rules, why auto-captions usually fail them, what AIOZ Stream actually supports, and how the 2026 ADA deadline changes affect compliance.