All timestamps are UTC.
If a change affects data shape or behavior, it will be marked as Breaking.
2026-10-28
✨ Added
previousFixtureIdon every fixture response — REST (GET /fixtures,/fixtures/today,/fixtures/live,/fixtures/odds, …) and thefixturesWebSocket channel. The inverse ofreissuedFixtureId(added 2026-10-09): where that field points forward from a cancelled fixture to its replacement, this one points back from the replacement to the fixture it replaced.previousFutureIdon every future response — same semantics, onGET /futures,GET /futures/oddsand thefuturesWebSocket channel.
null most of the time, a plain id string, one hop
only — a fixture postponed twice gives A → B → C, where B carries both
previousFixtureId: A and reissuedFixtureId: C. One predecessor at most, cleared again if
a postponement is reverted. Existing reissue pairs are backfilled, so the back-pointer is
also present on replacements created before this date.
⚠️ Breaking
- Fixture and future response shapes gained a top-level key.
previousFixtureIdsits next tofixtureIdandreissuedFixtureId;previousFutureIdnext tofutureIdandreissuedFutureId. Clients that reject unknown fields when deserializing need to add them; everyone else is unaffected.
2026-10-09
✨ Added
reissuedFixtureIdon every fixture response — REST (GET /fixtures,/fixtures/today,/fixtures/live,/fixtures/odds, …) and thefixturesWebSocket channel. When a cancelled fixture is re-listed under a new id — a postponed match moved to a later date, a board re-keyed by the provider — the cancelled fixture points at its replacement.reissuedFutureIdon every future response — same semantics, onGET /futures,GET /futures/oddsand thefuturesWebSocket channel.
null most of the time — it is only populated on a
cancelled entity (status.statusId 3) that already has a replacement in the feed.
Many cancellations are permanent and stay null; others are re-listed later, so the value
can appear after you first saw the entity cancelled. It is a plain id string, one hop only:
if the replacement is cancelled too, read its own reissuedFixtureId.
⚠️ Breaking
- Fixture and future response shapes gained a top-level key.
reissuedFixtureIdsits next tofixtureId,reissuedFutureIdnext tofutureId. Clients that reject unknown fields when deserializing need to add them; everyone else is unaffected.
2026-10-05
This entry is a data change only — no endpoint, field or type changes. It all surfaces throughGET /markets (and GET /fixtures/markets): refetch the
catalogue once on or after this date and you are current. Odds payloads are
untouched, they just start carrying the new outcomeIds.
✨ Added
- 64 new esports
marketTypevalues and 568 newmarketType×periodcombinations — objectives, first-objective and multikill markets across Counter-Strike, League of Legends, Dota, Valorant and Rainbow Six. Map-level markets arrive under a newsportId83 (ESport Mobile Legends). - 195 new
periodkeys, all sub-period grids —p1r1…p5r36(round within map) andp1g2…p5g6(tennis). The vocabulary goes from 19 values to 213 and stays append-only.
All 64 new marketType values
All 64 new marketType values
Totals / spreads / team totals on esports objectives —
totals-kills, totals-towers, totals-turrets, totals-dragons, totals-barons, totals-roshans, totals-inhibitors, totals-barracks, totals-rounds, totals-headshots, spreads-kills, spreads-towers, spreads-turrets, spreads-dragons, spreads-roshans, spreads-inhibitors, spreads-barracks, spreads-rounds, teamtotals-kills-team1/-team2, teamtotals-towers-team1/-team2, teamtotals-turrets-team1/-team2, teamtotals-dragons-team1/-team2, teamtotals-barons-team1/-team2, teamtotals-roshans-team1/-team2, teamtotals-inhibitors-team1/-team2, teamtotals-barracks-team1/-team2, teamtotals-rounds-team1/-team2First objective — firstblood, firsttower, firstbaron, firstroshan, firstinhibitor, firstbarracksMultikills — triplekill, quadrakill, pentakillOther — 1x2-kills, drawnobet-kills, oddeven-kills, oddeven-rounds, racetokills, winningmargin-rounds, playertotals-kills, playertotals-headshots, toqualifyRename targets that did not exist before — spreads-bookings, players-commitpenalty, players-goalieshutouts, players-goalsagainst, players-nextgoalscorer, players-powerplaypoints, players-secondgoalscorer, players-shorthandedgoals, players-shorthandedgoalscorer, players-thirdgoalscorer. These are new only because the market moved to them — see the rename table below.🔁 Changed
- 24
marketTypevalues are renamed for cross-sport consistency, affecting 222 markets in Ice Hockey, Soccer and Cricket. The singular prefixesplayer-,spread-andtotal-become the pluralplayers-,spreads-andtotals-already used everywhere else. periodchanges on 74 markets. 28 move fromfulltimetoresultacross 26 sports that have no scoring phase after regulation, so the two values were names for one number — see Periods per sport. The other 46 had a blankperiodand are now populated.marketIds are unchanged throughout.- No market has an empty
periodany more. If you special-cased the blank, drop that branch.
All 74 period changes
All 74 period changes
fulltime → result — the 1x2 market in 26 sports: MMA 203, Boxing 213, Beach Volley 303, Squash 343, Basketball 3x3 353, Curling 393, Padel 403, Soccer Specials 443, Beach Handball 473, Athletics 483, Badminton 493, Bowls 503, Cross-Country 513, ESport Call of Duty 563, ESport Overwatch 573, ESport Rainbow Six 583, ESport Rocket League 593, ESport StarCraft 603, ESport Valorant 613, ESport Arena of Valor 623, ESport King of Glory 633, Judo 643, ESport Honor of Kings 653, Speedway 663, Golf 673, Cycling 683.Boxing also moves two Total Rounds lines (216, 218) — its last fulltime markets, in a sport whose other Total Rounds lines were already on result.Blank → populated, 46 markets:Full marketType rename table
Full marketType rename table
13 of these renames merge into a
marketType that already existed —
players-anytimegoalscorer, players-assists, players-blocks,
players-firstgoalscorer, players-goals, players-lastgoalscorer,
players-points, players-saves, players-shots, players-shotsongoal,
spreads-corners, totals-fours and totals-sixes were already in the
registry alongside their singular twin. If you group by marketType, those
groups get larger rather than disappearing — the duplicate spelling for
the same concept is gone.The moneyline → toqualify row is the one rename that is not cosmetic: a single Soccer market
typed moneyline becomes toqualify, which is what it always meant. It is also the only market
whose marketName changes in this release — Winner (incl. overtime) becomes To Qualify.2026-09-28
✨ Added
GET /{lang}/fixtures/odds/parlay— price an accumulator from a list ofoddsIds, across fixtures and sports. See Parlays & SGP.GET /{lang}/fixtures/odds/sgp— price a correlated same-game parlay, quoted by the bookmaker.pricecarries the correlation,singlesPricethe naive product.missingOddsIdson both new endpoints — names the requested legs that could not be found, so an empty section is never ambiguous.X-API-Keyheader authentication on every endpoint, alongside theapiKeyquery parameter. Send one or the other. See Authentication.
2026-05-25
✨ Added
- WebSocket
receiveType: "zstd"— dictless compression. Opt-in zstd egress with no dictionary handling: every data frame is a standalone dictless zstd frame (dictId 0), decoded in one line (zstd.decompress(frame)→ JSON). ~5–6× smaller than JSON onodds— the simplest way to cut bandwidth. See Compression. - WebSocket
receiveType: "zstd-dict"— trained dictionaries. Maximum ratio (~7–9× onodds) using per-channel dictionaries the server pushes asdictcontrol frames at connect.
🔁 Changed
receiveType: "zstd"now means dictless. During the zstd beta,"zstd"previously delivered trained dictionaries; that behavior moved to the new"zstd-dict". If you were decoding dictionary frames under"zstd", switch to"zstd-dict".- Dictionary version cache removed. The
dictslogin field is gone; the server now re-sends the (~32 KB) dictionaries on everyzstd-dictconnection, so clients no longer persist or version dictionaries across reconnects. Adictsfield, if still sent, is ignored.
2026-04-09
✨ Added
- Fixture view:
venuesection — new nested object on all fixture responses withvenueId,venueName, andvenueLocation. Translated per language. - Fixture view:
clocksection — new nested object on all fixture responses withcurrentPeriod,currentTime,remainingTime,remainingTimeInPeriod, andstopped. All keys present withnullvalues until clock data is populated for a fixture. - Fixture view:
participant1ShortName/participant2ShortName— new fields in theparticipantssection of fixture responses, sourced from translated participant data. - Fixture view:
seasonRound— new field in theseasonsection of fixture responses. - Futures view:
marketId— themarketsection in future responses now includes themarketIdfrom the futures table. Name fields (marketName,marketType,playerMarket,participantMarket) remainnullfor now. - Participants endpoint:
participantShortName— theGET /{lang}/participantsresponse now includesparticipantShortNamefor each participant. - New REST endpoint:
GET /{lang}/venues?venueIds=...— returns venue data with translatedvenueNameandvenueLocation. - New WebSocket channel:
clocks— delivers live clock updates per fixture (same routing asscores: filtered byfixtureId, sport, tournament). Supports resume/replay.
⚠️ Breaking
- Fixture response shape changed — all fixture endpoints (REST and WebSocket) now include three new top-level keys:
venue(object),clock(object), and updatedparticipants/seasonsections. Clients parsing fixture responses strictly should update their models.seasonnow includesseasonRound: integer | nullparticipantsnow includesparticipant1ShortName: string | nullandparticipant2ShortName: string | nullvenue: { venueId, venueName, venueLocation }added afterseasonclock: { currentPeriod, currentTime, remainingTime, remainingTimeInPeriod, stopped }added afterscores
- Future response shape changed —
market.marketIdis now populated (integer or null) instead of alwaysnull.
2025-12-12
✨ Added
- WebSocket resume & replay support using
entryIdcursors - New WebSocket channels:
injurieslineupsstats
- AsyncAPI 3.0 reference for WebSocket gateway
🔧 Improved
- Reduced WebSocket latency for
oddsandscores - Better filtering for
sportIds,tournamentIds, andbookmakers
🐛 Fixed
- Fixed an issue where some
oddsupdates were delivered without bookmaker gating - Fixed incorrect
liveflag on some fixtures during transitions
2025-11-28
⚠️ Breaking
odds.payload.oddskeys are now always bookmaker-scoped- Old clients expecting a flat structure must update
✨ Added
- Support for
receiveType: "binary"(MessagePack) - Added
entryIdto all update messages
2025-11-10
✨ Added
- Initial WebSocket gateway
- Channels:
fixturesscoresoddsbookmakers