Viewership API
Access tournament viewership data programmatically — concurrent viewers, daily stats, channel breakdowns.
Overview
Base URL
https://app.escharts.com/api/viewership
All endpoints return JSON. Dates use Y-m-d format. Timestamps are UTC.
Authentication
Pass your API token as a Bearer token in every request:
Authorization: Bearer <your_token>
Rate Limiting
120 requests per minute per token. Exceeding the limit returns 429 Too Many Requests.
Errors
{
"error": "game_id is not in your allowed games list.",
"status": 403
}
| Code | Meaning |
|---|---|
| 401 | Missing or invalid token |
| 403 | Requested data is outside your partner access scope |
| 422 | Validation error — check required parameters |
| 429 | Rate limit exceeded |
Field Glossary
Canonical fields returned across viewership endpoints.
| Field | Description |
|---|---|
| channel_name | Display name of the channel |
| platform | Streaming platform (Twitch, YouTube, etc.) |
| category | "Official" or "Co-stream" |
| language | Human-readable language name (e.g. "English") |
| tournament | Tournament display name |
| day | Tournament day number (1-based, from tournament start date) |
| phase | Stage / phase name (VERIFIED only) |
| label | Match label, e.g. "Faze Clan vs Falcons" (channel-minute VERIFIED only) |
| team_a, team_b | Names of the two teams playing the match (channel-minute VERIFIED only) |
| timestamp | 5-minute slot timestamp (UTC) for channel-minute |
| start_timestamp | Min start datetime across official channels (UTC) |
| end_timestamp | Max end datetime across official channels (UTC) |
| airtime | Total broadcast hours |
| hours_watched | Total hours watched (viewers × time) |
| average_viewers | Average concurrent viewers |
| peak_viewers | Maximum concurrent viewers |
| concurrent_viewers | Live viewers in a single 5-minute slot |
| views | Total view count |
| unique_viewers | Estimated unique viewers (broadcast-tournament only) |
| media_value_eur | Estimated ad-equivalent media value in EUR (broadcast-tournament only) |
/tournaments
List Tournaments
Paginated list of tournaments with aggregated viewership stats. Results are limited to tournaments in your partner access scope.
Query Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
| game_id | int | Filter by game ID | |
| organizer_id | int | Filter by organizer ID | |
| event_id | int | Filter by event series ID | |
| date_from | Y-m-d | Tournaments that ended on or after this date | |
| date_to | Y-m-d | Tournaments that started on or before this date | |
| search | string | Partial match on tournament name (max 100 chars) | |
| sort_by | string | name · hours_watched · peak_viewers · avg_viewers · air_time · starts_at · ends_at · prize_pool · matches_count · match_days | |
| sort_order | string | ASC or DESC (default DESC) | |
| page | int | Page number (default 1) | |
| per_page | int | Results per page, max 200 (default 50) |
Response
{
"data": [
{
"tournament_id": 1234,
"name": "Six Invitational 2025",
"slug": "six-invitational-2025",
"game_name": "Rainbow Six Siege",
"game_id": 11,
"event_name": "Six Invitational",
"event_id": 42,
"starts_at": "2025-02-10 00:00:00",
"ends_at": "2025-02-23 00:00:00",
"hours_watched": 2540000.0,
"peak_viewers": 312000,
"avg_viewers": 85000.0,
"air_time_minutes": 5400,
"prize_pool": 3000000,
"is_offline": 1,
"organizer_names": "Ubisoft",
"venue_names": "Montreal",
"matches_count": 42,
"match_days": 12
}
],
"meta": {
"page": 1,
"per_page": 50,
"total": 1,
"sort_by": "ends_at",
"sort_order": "DESC"
}
}
/tournament-channels
Tournament Channels
Full channel breakdown for a tournament — one row per channel with aggregated stats for the entire event. Use the returned channel_id values with the channel-level endpoints.
Query Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
| tournament_id | int | ✓ | Tournament ID |
| official_only | bool | Return only official/main broadcast channels (default false) | |
| sort_by | string | hours_watched · peak_viewers · avg_viewers · air_time · channel_name (default hours_watched) | |
| sort_order | string | ASC or DESC (default DESC) |
Response
{
"data": [
{
"channel_id": 5678,
"stream_entity_id": 0,
"channel_name": "Rainbow6",
"channel_slug": "rainbow6",
"platform": "Twitch",
"platform_slug": "twitch.tv",
"category": "Official",
"language": "English",
"other_languages": [],
"hours_watched": 920000.0,
"peak_viewers": 180000,
"avg_viewers": 95000.0,
"airtime": 54.0,
"views": 4200000
}
],
"meta": {
"tournament_id": 1234,
"official_only": false,
"sort_by": "hours_watched",
"sort_order": "DESC",
"count": 18
}
}
/channel-minute
Channel Minute
Concurrent viewers in 5-minute intervals for a given day. Omit channel_id to get totals summed across all channels.
Query Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
| tournament_id | int | ✓ | Tournament ID |
| date | Y-m-d | ✓ | Date to query |
| status | string | ✓ | RAW or VERIFIED |
| channel_id | int | Channel ID from /tournament-channels (when channel_id != 0). Omit for cross-channel totals | |
| stream_entity_id | int | Stream entity ID from /tournament-channels (when channel_id == 0). Mutually exclusive with channel_id |
Response — status=RAW, with channel_id
{
"data": [
{
"channel_name": "Rainbow6",
"platform": "Twitch",
"category": "Official",
"language": "English",
"tournament": "SLC Major 2026",
"timestamp": "2026-05-15 15:33:00",
"concurrent_viewers": 12345
}
],
"status": "RAW",
"meta": {
"tournament_id": 1234,
"tournament_name": "SLC Major 2026",
"channel_id": 5678,
"date": "2026-05-15",
"day": 6,
"scope": "channel"
}
}
Response — status=VERIFIED, with channel_id
{
"data": [
{
"channel_name": "Rainbow6",
"platform": "Twitch",
"category": "Official",
"language": "English",
"tournament": "SLC Major 2026",
"day": 6,
"phase": "Playoffs",
"label": "Faze Clan vs Falcons",
"team_a": "Faze Clan",
"team_b": "Falcons",
"timestamp": "2026-05-15 15:33:00",
"concurrent_viewers": 12345
}
],
"status": "VERIFIED",
"meta": {
"tournament_id": 1234,
"tournament_name": "Six Invitational 2025",
"channel_id": 5678,
"date": "2025-02-10",
"day": 1,
"scope": "channel"
}
}
day, phase, label, team_a, team_b are only present in VERIFIED responses. Values are null for slots outside any match window.
Response — status=RAW, without channel_id
One row per channel per 5-minute slot, ordered by timestamp ASC, concurrent_viewers DESC.
{
"data": [
{
"channel_name": "Rainbow6",
"platform": "Twitch",
"category": "Official",
"language": "English",
"tournament": "SLC Major 2026",
"timestamp": "2026-05-15 15:33:00",
"concurrent_viewers": 12345
}
],
"status": "RAW",
"meta": {
"tournament_id": 1234,
"tournament_name": "SLC Major 2026",
"channel_id": null,
"date": "2026-05-15",
"day": 6,
"scope": "all_channels"
}
}
Response — status=VERIFIED, without channel_id
One row per channel per 5-minute slot, with match context attached.
{
"data": [
{
"channel_name": "Rainbow6",
"platform": "Twitch",
"category": "Official",
"language": "English",
"tournament": "SLC Major 2026",
"day": 6,
"phase": "Playoffs",
"label": "Faze Clan vs Falcons",
"team_a": "Faze Clan",
"team_b": "Falcons",
"timestamp": "2026-05-15 15:33:00",
"concurrent_viewers": 12345
}
],
"status": "VERIFIED",
"meta": {
"tournament_id": 1234,
"tournament_name": "SLC Major 2026",
"channel_id": null,
"date": "2026-05-15",
"day": 6,
"scope": "all_channels"
}
}
/channel-day
Channel Day
Aggregated daily stats. With channel_id — one summary row for that channel. Without — one row per channel ordered by hours watched.
Query Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
| tournament_id | int | ✓ | Tournament ID |
| date | Y-m-d | ✓ | Date to query |
| status | string | ✓ | RAW or VERIFIED |
| channel_id | int | Channel ID (channel_id != 0 in /tournament-channels). Omit for one row per channel | |
| stream_entity_id | int | Stream entity ID (channel_id == 0 in /tournament-channels). Mutually exclusive with channel_id |
Response — status=RAW
{
"data": [
{
"channel_name": "Rainbow6",
"platform": "Twitch",
"category": "Official",
"language": "English",
"tournament": "SLC Major 2026",
"day": 6,
"start_timestamp": "2026-05-15 12:00:00",
"end_timestamp": "2026-05-15 20:30:00",
"airtime": 8.5,
"hours_watched": 104932.5,
"average_viewers": 12345,
"peak_viewers": 12345,
"views": 4321
}
],
"status": "RAW",
"meta": {
"tournament_id": 1234,
"tournament_name": "SLC Major 2026",
"channel_id": null,
"date": "2026-05-15",
"day": 6,
"scope": "all_channels"
}
}
Response — status=VERIFIED (adds phase)
{
"data": [
{
"channel_name": "Rainbow6",
"platform": "Twitch",
"category": "Official",
"language": "English",
"tournament": "SLC Major 2026",
"day": 6,
"phase": "Playoffs",
"start_timestamp": "2026-05-15 12:00:00",
"end_timestamp": "2026-05-15 20:30:00",
"airtime": 8.5,
"hours_watched": 104932.5,
"average_viewers": 12345,
"peak_viewers": 12345,
"views": 4321
}
],
"status": "VERIFIED",
"meta": {
"tournament_id": 1234,
"tournament_name": "SLC Major 2026",
"channel_id": null,
"date": "2026-05-15",
"day": 6,
"scope": "all_channels"
}
}
/broadcast-day
Broadcast Day
Daily totals across all official channels. Concurrent viewers are summed per 5-minute slot before aggregation.
Query Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
| tournament_id | int | ✓ | Tournament ID |
| date | Y-m-d | ✓ | Date to query |
| status | string | ✓ | RAW or VERIFIED |
Response
{
"data": [
{
"tournament": "SLC Major 2026",
"day": 6,
"start_timestamp": "2026-05-15 12:00:00",
"end_timestamp": "2026-05-15 20:30:00",
"airtime": 8.5,
"hours_watched": 104932.5,
"average_viewers": 12345,
"peak_viewers": 12345,
"views": 4321
}
],
"status": "RAW",
"meta": {
"tournament_id": 1234,
"tournament_name": "SLC Major 2026",
"date": "2026-05-15",
"day": 6
}
}
Response — status=VERIFIED (adds phase)
{
"data": [
{
"tournament": "SLC Major 2026",
"day": 6,
"phase": "Playoffs",
"start_timestamp": "2026-05-15 12:00:00",
"end_timestamp": "2026-05-15 20:30:00",
"airtime": 8.5,
"hours_watched": 104932.5,
"average_viewers": 12345,
"peak_viewers": 12345,
"views": 4321
}
],
"status": "VERIFIED",
"meta": {
"tournament_id": 1234,
"tournament_name": "SLC Major 2026",
"date": "2026-05-15",
"day": 6
}
}
/broadcast-tournament
Broadcast Tournament
Single-row tournament-level totals across all official channels. Same shape for RAW and VERIFIED — RAW has shorter cache.
Query Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
| tournament_id | int | ✓ | Tournament ID |
| status | string | ✓ | RAW or VERIFIED |
Response
start_timestamp / end_timestamp are min/max across all official channels.
{
"data": {
"tournament": "SLC Major 2026",
"start_timestamp": "2026-05-08 10:05:00",
"end_timestamp": "2026-05-17 18:45:00",
"airtime": 120.75,
"hours_watched": 1490659.75,
"average_viewers": 12345,
"peak_viewers": 12345,
"views": 36199618,
"unique_viewers": 543210,
"media_value_eur": 1454581
},
"status": "VERIFIED",
"meta": {
"tournament_id": 1234
}
}
unique_viewers may be null if post-verification has not yet completed. media_value_eur is estimated using CPM rates by language and game area.
Typical Workflow
-
1
/tournamentsDiscover available tournaments and their IDs. Filter by game, date range, or event series.
-
2
/tournament-channelsGet all channels for a tournament. Each entry has a channel_id for the next steps.
-
3
/channel-minute or /channel-dayFetch channel-level viewership. Pass channel_id for one channel, or omit it for aggregated totals.
-
4
/broadcast-day or /broadcast-tournamentGet official broadcast totals — peak concurrent and hours watched across main streams.