Partner API

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.

What Your Token Reaches

Two things are agreed separately and checked on every request.

ScopeWhat it decides
Tournaments Which tournaments answer at all — by game, organizer, event series and date window. A tournament outside it returns 403, the same scope that decides what you see signed in on the site
Endpoints Which of the endpoints below your agreement covers. One not covered returns 403
Fields Which fields an endpoint returns for you. A field outside your agreement is absent from the rows — the request still succeeds, and meta is never trimmed

Every example below shows the full set of fields. Yours may be narrower; nothing else about the shape changes.

Errors

{
  "error": "game_id is not in your allowed games list.",
  "status": 403
}
CodeMeaning
401 Missing or invalid token
403 The tournament is outside your partner access scope — the same scope that decides which tournaments you see on the site
403 The endpoint, or a field inside it, is not part of your API access
404 Requested tournament does not exist
422 Validation error — check required parameters
429 Rate limit exceeded

Field Glossary

Canonical fields returned across viewership endpoints.

FieldDescription
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 Broadcast day number, 1-based, as the site's Days table lists them: rest days are not counted, and a broadcast that runs past midnight UTC stays one day. null for data outside a labelled broadcast day
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 Slot timestamp (UTC), the start of the slot. Slot width is meta.granularity: 1 minute for RAW, 1 or 5 minutes for VERIFIED
start_timestamp Min start datetime across official channels (UTC)
end_timestamp Max end datetime across official channels (UTC)
tournament_id, channel_id, stream_entity_id Stable join keys. Names can change; ids do not. stream_entity_id is set when channel_id is 0; it is an unsigned 64-bit integer, so read it with a parser that does not turn large numbers into doubles
is_official true for an official broadcast channel; the boolean form of category
channel_url The channel's page on its platform, e.g. https://www.twitch.tv/ow_esports. null for in-game broadcasts with no public page
broadcast_date The UTC date the broadcast day starts on. A broadcast that runs past midnight UTC keeps the date it started on (channel-day only)
airtime Total broadcast hours, to four decimals
airtime_minutes Total broadcast minutes, a whole number. The same value as airtime, without the unit conversion
hours_watched Total hours watched (viewers × time)
average_viewers Average concurrent viewers. On channel-minute, the average within the slot: hours watched in the slot are average_viewers × slot width
peak_viewers Maximum concurrent viewers
peak_viewers_at Start (UTC) of the 5-minute slot in which peak_viewers was reached
data_updated_at UTC. The later of the last moderation edit and the last recalculation of the tournament's numbers. Responses are cached for up to an hour, so overlap incremental syncs by an hour
concurrent_viewers Concurrent viewers in the slot. RAW slots are 1 minute wide; VERIFIED slots are 1 or 5 minutes wide, see meta.granularity
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)
GET /tournaments

List Tournaments

Paginated list of tournaments with aggregated viewership stats. Results are limited to tournaments in your partner access scope.

Query Parameters

ParameterTypeRequiredDescription
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,
      "views": 36199618,
      "prize_pool": 3000000,
      "is_offline": 1,
      "organizer_names": "Ubisoft",
      "venue_names": "Montreal",
      "matches_count": 42,
      "match_days": 12,
      "peak_viewers_at": "2025-02-23 23:40:00",
      "data_updated_at": "2025-02-24 11:30:00"
    }
  ],
  "meta": {
    "page": 1,
    "per_page": 50,
    "total": 1,
    "sort_by": "ends_at",
    "sort_order": "DESC"
  }
}
GET /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

ParameterTypeRequiredDescription
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": [
    {
      "tournament_id": 1234,
      "channel_id": 5678,
      "stream_entity_id": 0,
      "channel_name": "Rainbow6",
      "channel_slug": "rainbow6",
      "platform": "Twitch",
      "platform_slug": "twitch.tv",
      "channel_url": "https://www.twitch.tv/rainbow6",
      "category": "Official",
      "is_official": true,
      "language": "English",
      "other_languages": [],
      "hours_watched": 920000.0,
      "peak_viewers": 180000,
      "peak_viewers_at": "2025-02-23 23:40:00",
      "avg_viewers": 95000.0,
      "airtime": 54.0,
      "airtime_minutes": 3240,
      "views": 4200000,
      "data_updated_at": "2025-02-24 11:30:00"
    }
  ],
  "meta": {
    "tournament_id": 1234,
    "official_only": false,
    "sort_by": "hours_watched",
    "sort_order": "DESC",
    "count": 18
  }
}
GET /tournament-matches

Tournament Matches

Full match schedule for a tournament with aggregated viewership stats. All parallel matches (Stream A / Stream B) are returned as separate rows. Useful for attributing viewership to specific matches.

Query Parameters

ParameterTypeRequiredDescription
tournament_id int ✓ Tournament ID
date Y-m-d Filter to matches played on a specific day. Omit to get all matches for the tournament

Response

{
  "data": [
    {
      "match_id": 101,
      "match_name": "Falcons VS EP",
      "stage_name": "Group Stage",
      "day": 3,
      "event_name": "Group Stage, Day 3",
      "phase": "Group Stage",
      "starts_at": "2025-11-15 14:00:00",
      "ends_at": "2025-11-15 15:28:00",
      "team_a": "Falcons",
      "team_b": "EP",
      "hours_watched": 12500.0,
      "peak_viewers": 45000,
      "avg_viewers": 38200.0,
      "air_time_minutes": 88
    },
    {
      "match_id": 102,
      "match_name": "Wildcard VS LOS",
      "stage_name": "Group Stage",
      "day": 3,
      "event_name": "Group Stage, Day 3",
      "phase": "Group Stage",
      "starts_at": "2025-11-15 14:00:00",
      "ends_at": "2025-11-15 15:15:00",
      "team_a": "Wildcard",
      "team_b": "LOS",
      "hours_watched": 3200.0,
      "peak_viewers": 9800,
      "avg_viewers": 7500.0,
      "air_time_minutes": 75
    }
  ],
  "meta": {
    "tournament_id": 1234,
    "date": null,
    "count": 2,
    "days": [
      { "day": 1, "date": "2025-11-13", "event_name": "Group Stage, Day 1", "phase": "Group Stage" },
      { "day": 2, "date": "2025-11-14", "event_name": "Group Stage, Day 2", "phase": "Group Stage" },
      { "day": 3, "date": "2025-11-15", "event_name": "Group Stage, Day 3", "phase": "Group Stage" }
    ],
    "stages": ["Group Stage"]
  }
}

Grouping a Tournament the Way the Site Does

The tournament page filters matches by day and by stage. Both option lists travel in meta, and every match names which one it belongs to — so a client can rebuild those groupings without a second call.

FieldDescription
day The broadcast day the match was played in, 1-based. Rest days are not counted and a broadcast past midnight UTC stays one day, so it matches /broadcast-day and /channel-day
event_name The day label the site's day filter lists, e.g. "Week 1, Day 3"
phase The stage filter's value — the part of event_name before the comma, e.g. "Week 1". For a league this is the week number
stage_name The stage recorded against the match itself. Usually equal to phase, but it comes from the match schedule rather than from the broadcast day
meta.days Every broadcast day of the tournament, ascending — the day filter's option list. Returned only when date is omitted: asking for one day and being handed every other one is 5 KB nobody reads
meta.stages Distinct phases in broadcast order — the stage filter's option list

A match played on a date with no broadcast carries null for all three — there are no viewership numbers for it either.

GET /tournaments-teams

Tournaments Teams

Viewership attributed to each team — the same breakdown the team chart shows on the tournament page. Sorted by hours watched, descending.

Query Parameters

ParameterTypeRequiredDescription
tournament_id int ✓ Tournament ID

Response

{
  "data": [
    {
      "name": "Six Invitational 2025",
      "team": [
        {
          "team_name": "RSG SG",
          "team_id": 101,
          "hours_watched": 228100,
          "pcu": 85200,
          "acu": 42100,
          "airtime": 6.5,
          "views": 36199618
        },
        {
          "team_name": "BURN x FLASH",
          "team_id": 108,
          "hours_watched": 205800,
          "pcu": 76300,
          "acu": 33400,
          "airtime": 5.5,
          "views": 28104433
        }
      ]
    }
  ],
  "meta": {
    "tournament_id": 1234,
    "players_only": false,
    "count": 2
  }
}
FieldDescription
pcu Peak concurrent viewers — peak_viewers elsewhere in this API
acu Average concurrent viewers — avg_viewers elsewhere in this API
airtime Broadcast hours attributed to the team

Hours watched and both viewer counts are whole numbers, and airtime is hours to four decimals, so it stays whole minutes. A players-only tournament is broken down by player instead; the rows keep the team_id / team_name keys and meta.players_only is true. An unknown tournament_id returns 404.

GET /tournaments-language

Tournaments Language

Viewership split by broadcast language — the same breakdown the language chart shows on the tournament page, so the shares match. Sorted by hours watched, descending.

Query Parameters

ParameterTypeRequiredDescription
tournament_id int ✓ Tournament ID

Response

{
  "data": [
    {
      "name": "M7 World Championship",
      "viewership_language": [
        {
          "tournament_id": 1234,
          "language": "English",
          "hours_watched": 228100,
          "peak_viewers": 85200,
          "peak_viewers_at": "2025-11-23 13:15:00",
          "avg_viewers": 42100,
          "airtime": 6.5,
          "airtime_minutes": 390,
          "views": 36199618,
          "data_updated_at": "2025-11-24 06:00:00"
        },
        {
          "tournament_id": 1234,
          "language": "Indonesian",
          "hours_watched": 205800,
          "peak_viewers": 76300,
          "peak_viewers_at": "2025-11-23 12:50:00",
          "avg_viewers": 33400,
          "airtime": 5.5,
          "airtime_minutes": 330,
          "views": 28104433,
          "data_updated_at": "2025-11-24 06:00:00"
        }
      ]
    }
  ],
  "meta": {
    "tournament_id": 1234,
    "count": 2
  }
}

Hours watched and average viewers are whole numbers, and airtime is hours to four decimals, so it stays whole minutes. Peak viewers are the language's own peak — summed across its channels slot by slot — so they cannot be rebuilt by adding up the channels' peaks from /tournament-channels. data is a one-element list so the tournament name travels with its breakdown. A language the dictionary does not know is reported as "Others". An unknown tournament_id returns 404. China platforms are excluded, as everywhere else.

GET /channel-minute

Channel Minute

Concurrent viewers per minute for a given day. Pass channel_id or stream_entity_id for a single channel, channel_ids[]/stream_entity_ids[] for a subset, or omit all to get every channel.

RAW — 1-min granularity from raw scans, ≤5 min delay, last 30 days only VERIFIED — 1-min (last 30 days) or 5-min granularity with match context, available 24–120 h after stream end

Query Parameters

ParameterTypeRequiredDescription
tournament_id int ✓ Tournament ID
status string ✓ RAW or VERIFIED
date Y-m-d ✓* Date to query. Required unless match_id is provided (date is derived from the match automatically)
match_id int Filter to a single match window. Shorthand for match_ids[]=X. When provided, date can be omitted
match_ids[] int[] Filter to one or more matches — e.g. match_ids[]=101&match_ids[]=102. Minutes within any of the match windows are returned. date can be omitted. Works with both RAW and VERIFIED
channel_id int Single channel ID (when channel_id != 0 in /tournament-channels). Mutually exclusive with channel_ids[]
stream_entity_id int Single stream entity ID, unsigned 64-bit (when channel_id == 0 in /tournament-channels). Mutually exclusive with stream_entity_ids[]
channel_ids[] int[] Filter multiple channels by ID — e.g. channel_ids[]=1&channel_ids[]=2. Only applied when channel_id/stream_entity_id are omitted
stream_entity_ids[] int[] Filter multiple stream entities by ID, unsigned 64-bit. Only applied when channel_id/stream_entity_id are omitted. Can be combined with channel_ids[]
page int Page number (default: 1)
per_page int Rows per page (default: 10000, max: 50000)
granularity int VERIFIED only: 5 for 5-minute slots, the ones the dashboard is built from. 1 (default) returns 1-minute slots where available, for the last 30 days only

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,
      "average_viewers": 11873
    }
  ],
  "status": "RAW",
  "meta": {
    "tournament_id": 1234,
    "tournament_name": "SLC Major 2026",
    "channel_id": 5678,
    "date": "2026-05-15",
    "day": 6,
    "scope": "channel",
    "granularity": 1
  }
}

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,
      "average_viewers": 11873
    }
  ],
  "status": "VERIFIED",
  "meta": {
    "tournament_id": 1234,
    "tournament_name": "Six Invitational 2025",
    "channel_id": 5678,
    "date": "2025-02-10",
    "day": 1,
    "scope": "channel",
    "granularity": 1
  }
}

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 minute, 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,
      "average_viewers": 11873
    }
  ],
  "status": "RAW",
  "meta": {
    "tournament_id": 1234,
    "tournament_name": "SLC Major 2026",
    "channel_id": null,
    "date": "2026-05-15",
    "day": 6,
    "scope": "all_channels",
    "granularity": 1,
    "page": 1,
    "per_page": 10000,
    "count": 10000,
    "total": 40519,
    "pages": 5,
    "has_more": true
  }
}

Pagination — check this before charting a full day

Without channel_id you get one row per channel per slot, so a busy day exceeds the default per_page=10000 — the first page can end hours before the broadcast did. Watch meta.has_more / meta.total: a whole day of every channel on a big tournament is around 80 000 rows, more than one page even at the maximum per_page=50000, so page through with page until meta.has_more is false. Pages are cut by row count, not by slot, so the last slot of a truncated page is partial — don’t plot it. Requests with per_page above 15 000 bypass the response cache, so a full-day pull is always fresh.

Response — status=VERIFIED, without channel_id

One row per channel per slot of meta.granularity minutes, 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,
      "average_viewers": 11873
    }
  ],
  "status": "VERIFIED",
  "meta": {
    "tournament_id": 1234,
    "tournament_name": "SLC Major 2026",
    "channel_id": null,
    "date": "2026-05-15",
    "day": 6,
    "scope": "all_channels",
    "granularity": 5,
    "page": 1,
    "per_page": 10000,
    "count": 10000,
    "total": 11556,
    "pages": 2,
    "has_more": true
  }
}
GET /channel-day

Channel Day

Aggregated stats for a calendar date or a broadcast day, one row per broadcast day. With channel_id — that channel only. Without — one row per channel, ordered by hours watched within each broadcast day.

RAW — near real-time, ≤5 min delay VERIFIED — post-processed, available 24–120 h after stream end

Query Parameters

ParameterTypeRequiredDescription
tournament_id int ✓ Tournament ID
date Y-m-d ✓* Calendar date (UTC). Rows are split by broadcast day, so a date holding the tail of the previous evening returns it as its own row. Required unless day is given
day int ✓* Broadcast day number, as in meta.days of /tournament-matches. Returns the whole broadcast day, also when it runs past midnight UTC. Use instead of date
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, unsigned 64-bit (channel_id == 0 in /tournament-channels). Mutually exclusive with channel_id

Response — status=RAW

{
  "data": [
    {
      "tournament_id": 1234,
      "channel_id": 5678,
      "stream_entity_id": 0,
      "channel_name": "Rainbow6",
      "platform": "Twitch",
      "category": "Official",
      "is_official": true,
      "language": "English",
      "tournament": "SLC Major 2026",
      "day": 6,
      "broadcast_date": "2026-05-15",
      "start_timestamp": "2026-05-15 12:00:00",
      "end_timestamp": "2026-05-15 20:30:00",
      "airtime": 8.5,
      "airtime_minutes": 510,
      "hours_watched": 104933,
      "average_viewers": 12345,
      "peak_viewers": 12345,
      "views": 4321,
      "peak_viewers_at": "2026-05-15 18:40:00",
      "data_updated_at": "2026-05-16 06:00:00"
    }
  ],
  "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": [
    {
      "tournament_id": 1234,
      "channel_id": 5678,
      "stream_entity_id": 0,
      "channel_name": "Rainbow6",
      "platform": "Twitch",
      "category": "Official",
      "is_official": true,
      "language": "English",
      "tournament": "SLC Major 2026",
      "day": 6,
      "broadcast_date": "2026-05-15",
      "phase": "Playoffs",
      "start_timestamp": "2026-05-15 12:00:00",
      "end_timestamp": "2026-05-15 20:30:00",
      "airtime": 8.5,
      "airtime_minutes": 510,
      "hours_watched": 104933,
      "average_viewers": 12345,
      "peak_viewers": 12345,
      "views": 4321,
      "peak_viewers_at": "2026-05-15 18:40:00",
      "data_updated_at": "2026-05-16 06:00:00"
    }
  ],
  "status": "VERIFIED",
  "meta": {
    "tournament_id": 1234,
    "tournament_name": "SLC Major 2026",
    "channel_id": null,
    "date": "2026-05-15",
    "day": 6,
    "scope": "all_channels"
  }
}

Reconciliation. Rows are cut from the same 5-minute slots as /tournament-channels, so summed over every date of the tournament a channel's hours_watched and airtime_minutes equal its /tournament-channels totals, up to the rounding of each row to whole hours. peak_viewers is a maximum: take the largest day, never the sum. A language's peak cannot be rebuilt from these rows either — use /tournaments-language.

GET /broadcast-day

Broadcast Day

Totals across all channels that broadcast the tournament for a calendar date or a broadcast day, one row per broadcast day. Concurrent viewers are summed per 5-minute slot before aggregation. Use official_only=true to limit it to official channels.

RAW — ≤30 min delay VERIFIED — post-processed, available 24–120 h after stream end

Query Parameters

ParameterTypeRequiredDescription
tournament_id int ✓ Tournament ID
date Y-m-d ✓* Calendar date (UTC). Rows are split by broadcast day, so a date holding the tail of the previous evening returns it as its own row. Required unless day is given
day int ✓* Broadcast day number, as in meta.days of /tournament-matches. Returns the whole broadcast day, also when it runs past midnight UTC. Use instead of date
status string ✓ RAW or VERIFIED
official_only bool true to aggregate only official/main channels (default false)

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": 104933,
      "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,
    "official_only": false
  }
}

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": 104933,
      "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,
    "official_only": false
  }
}

day counts only days with a broadcast — rest days are skipped, so it matches the tournament’s Days table on the site.

GET /broadcast-tournament

Broadcast Tournament

Single-row tournament-level totals across all channels that broadcast the tournament. Same shape for RAW and VERIFIED — RAW has shorter cache.

RAW — ≤30 min cache VERIFIED — post-processed totals

Query Parameters

ParameterTypeRequiredDescription
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": 1490660,
    "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. 1

    /tournaments

    Discover available tournaments and their IDs. Filter by game, date range, or event series.

  2. 2

    /tournament-channels

    Get all channels for a tournament. Each entry has a channel_id for the next steps.

  3. 3

    /channel-minute or /channel-day

    Fetch channel-level viewership. Pass channel_id for one channel, or omit it for aggregated totals.

  4. 4

    /broadcast-day or /broadcast-tournament

    Get broadcast totals — peak concurrent and hours watched across all channels, or official ones with official_only=true. Pass day to get a whole broadcast day.

Changelog

Every user-visible change to the Viewership API, newest first. Endpoints stay backward compatible unless an entry says otherwise.

    • Added data_updated_at on /tournaments, /tournament-channels, /tournaments-language and /channel-day: when the tournament's data last changed, by moderation or by a recalculation. Re-sync tournaments whose value is newer than your last sync.
    • Added airtime_minutes on /tournament-channels, /tournaments-language and /channel-day. airtime stays in hours.
    • Added views on /tournaments.
    • Added channel_url on /tournament-channels: the channel's page on its platform, the link the site's channels table uses. null for in-game broadcasts with no public page.
    • Added peak_viewers_at on /tournaments, /tournament-channels, /tournaments-language and /channel-day.
    • Added /tournament-channels, /tournaments-language and /channel-day rows carry tournament_id; /tournament-channels and /channel-day also carry is_official, and /channel-day carries channel_id, stream_entity_id and broadcast_date.
    • Added New day parameter on /broadcast-day and /channel-day: pass a broadcast day number, as listed in meta.days of /tournament-matches, instead of date to get the whole broadcast day, including the part after midnight UTC.
    • Added /channel-minute: granularity parameter (VERIFIED only; 5 returns the 5-minute slots the dashboard is built from) and meta.granularity, the slot width actually returned.
    • Added /channel-minute: average_viewers, the average audience within the slot, next to concurrent_viewers.
    • Changed day is the broadcast day as the site's Days table lists it: a broadcast that runs past midnight UTC stays one day, so day numbers after such a broadcast are lower than before. Applies to /broadcast-day, /channel-day, /channel-minute and /tournament-matches.
    • Changed Breaking: /channel-minute accepts per_page up to 50000 (was 100000). A whole day of every channel can take two pages — page through until meta.has_more is false.
    • Changed /channel-minute: 1-minute data has one row per channel for every minute of the broadcast in every scope, not only with channel_id or channel_ids[]; concurrent_viewers is a number rather than a string.
    • Fixed /channel-minute VERIFIED: 1-minute data no longer ends five minutes before the broadcast does.
    • Fixed /tournament-matches: hours_watched and air_time_minutes were doubled for matches with two teams; they now match the matches table on the site.
    • Added /tournament-matches: each match now carries day, event_name and phase, and meta.stages lists the tournament page's stage filter options. meta.days lists its day filter options, and is returned only when date is omitted.
    • Added New endpoint /tournaments-teams — viewership attributed to each team, matching the team chart on the tournament page.
    • Added New endpoint /tournaments-language — viewership by broadcast language, matching the language chart on the tournament page.
    • Fixed day now counts broadcast days only — rest days are skipped, matching the Days table on the site.
    • Changed /broadcast-day and /broadcast-tournament aggregate all channels that broadcast the tournament, not only official ones.
    • Added official_only parameter on both endpoints (default false) restores the previous official-only totals.
    • Added New endpoint /tournament-matches — full match schedule with per-match viewership.
    • Added Initial release: /tournaments, /tournament-channels, /channel-minute, /channel-day, /broadcast-day, /broadcast-tournament.