Skip to content

Analytics API

The webapp’s /analytics, /analytics/audience, /analytics/usage, and /streams/:id/analytics pages are all built on the same GraphQL surface you can query directly. This page maps each view to the operations that drive it so you can replicate or extend them in your own dashboards.

The /streams/:id/analytics and /streams/:id/health views read the analytics root: analytics.health for health rollups and analytics.usage.streaming for viewer, delivery, and quality-tier summaries over a time range.

query StreamAnalytics($streamId: ID!, $timeRange: TimeRangeInput) {
analytics {
health {
streamHealthSummary(streamId: $streamId, timeRange: $timeRange) {
avgBitrate
avgFps
avgBufferHealth
totalRebufferCount
hasActiveIssues
currentQualityTier
}
}
usage {
streaming {
streamAnalyticsSummary(streamId: $streamId, timeRange: $timeRange) {
rangeAvgViewers
rangePeakConcurrentViewers
rangeUniqueViewers
rangeViewerHours
rangeEgressGb
rangePacketLossRate
rangeQuality {
tier1080pMinutes
tier720pMinutes
tier480pMinutes
tierSdMinutes
}
}
}
}
}
}

For real-time updates, subscribe instead of polling. liveStreamEvents carries lifecycle changes with a metrics snapshot; liveViewerMetrics emits per-viewer connect and disconnect records with bandwidth and packet counters.

subscription LiveStream($streamId: ID) {
liveStreamEvents(streamId: $streamId) {
type
status
timestamp
qualityTier
primaryBitrate
primaryFps
totalViewers
}
}
subscription LiveViewers($streamId: ID!) {
liveViewerMetrics(streamId: $streamId) {
timestamp
action
protocol
bandwidthOutBps
packetsLost
clientCountry
}
}

/analytics/audience aggregates viewer counts, geographic distribution, and per-stream rankings across the whole tenant.

query Audience($timeRange: TimeRangeInput!, $topN: Int = 10) {
analytics {
usage {
streaming {
streamAnalyticsSummariesConnection(timeRange: $timeRange, page: { first: 10 }) {
edges {
node {
streamId
rangeUniqueViewers
rangeViewerHours
rangeViewerSharePercent
}
}
}
tenantAnalyticsDailyConnection(timeRange: $timeRange, page: { first: 31 }) {
edges {
node {
day
totalStreams
totalViews
uniqueViewers
egressBytes
}
}
}
geographicDistribution(timeRange: $timeRange, topN: $topN) {
totalViewers
uniqueCountries
topCountries {
countryCode
viewerCount
percentage
}
}
}
}
}
}

Omitting streamId on geographicDistribution aggregates across all of the tenant’s streams.

/analytics/usage and /account/billing share the usage surface. Use usageAggregates for the rolled-up summary or usageRecordsConnection for paginated raw records.

query Usage($timeRange: TimeRangeInput!) {
usageAggregates(timeRange: $timeRange, granularity: "daily") {
usageType
periodStart
periodEnd
usageValue
}
tenantUsage(timeRange: $timeRange) {
billingPeriod
usage {
resourceType
amount
}
totalCost
currency
}
}
query DetailedUsage($timeRange: TimeRangeInput, $page: ConnectionInput) {
usageRecordsConnection(timeRange: $timeRange, page: $page) {
edges {
node {
usageType
usageValue
unit
clusterId
periodStart
periodEnd
}
}
pageInfo {
hasNextPage
endCursor
}
}
}

/network and /infrastructure/federation show public platform topology and orchestrator vantage points across the federation. Authenticated users also see subscribed or owned clusters with cluster-level KPIs, plus tenant-scoped routing and federation overlays for their own streams.

query NetworkStatus {
networkStatus {
clusters {
clusterId
region
status
currentStreams
currentViewers
egressMbps
egressCapacityMbps
}
peerConnections {
sourceCluster
targetCluster
connected
}
}
orchestratorVantages {
orchAddr
gatewayRegion
countryCode
latestLatencyMs
score
lastSeen
}
}

For dashboards that want the raw event stream (every viewer connect/disconnect, every track change, every storage event), subscribe to the firehose. Be deliberate — this is high-volume.

subscription Firehose {
liveFirehose {
type
channel
timestamp
streamEvent {
streamId
type
status
}
connectionEvent {
streamId
sessionId
connector
}
storageEvent {
streamId
action
}
}
}

channel is STREAMS, ANALYTICS, or SYSTEM; exactly one of the typed members (streamEvent, viewerMetrics, connectionEvent, trackListUpdate, storageEvent, processingEvent, routingEvent, systemHealthEvent, and others) is populated per event.

Agents call analytics through diagnostic tools rather than direct GraphQL — see agents/mcp for get_stream_health_summary, get_anomaly_report, diagnose_buffer_health, diagnose_packet_loss, diagnose_rebuffering, and diagnose_routing. Each wraps one or more of the queries above with summarization tuned for agent consumption.