TL;DR
We’ve shipped a major-version upgrade to the AnySport football data API. In short: we now serve more data, and our real-time push covers far more of it.
- Data scale: odds markets are now standardized into a
market_codedictionary (63 pre-match, 499 live), and we’ve added a batch of new endpoints — seasons, coaches, injuries, match details, live match situation, match events, and a relative upcoming-fixtures window. - Real-time push: the old WebSocket could only deliver live scores. After this upgrade, you can subscribe over WebSocket to scores, match situation, pre-match odds, and live odds.
This release also changes the base URL, the authentication method, and the ID scheme, so existing v1 users need to update their code per the migration guide below — it is not a drop-in, painless swap. We’ve written down every gotcha in this post.
📌 The docs moved too. The new docs are at docs.anysport.io; the old v1 docs are archived at docsv1.anysport.io. Every endpoint, field, and code below refers to the new version.
1. What’s New at a Glance
Here’s the full picture in one table (🔴 = a breaking change for v1 users that requires code changes):
| Aspect | v1 (old) | New | |
|---|---|---|---|
| REST base URL | https://api.anysport.io/v1 | https://data.anysport.io/v1/soccer | 🔴 |
| Authentication | X-API-Key header or ?api_key= query param | apikey header only (lowercase, no X-); query params not supported | 🔴 |
| Entity IDs | plain integers (match_id: 1234567, league_id: 148) | semantic prefixed strings (as_ / asl_ / ast_ …) | 🔴 |
| Odds data model | human-readable market_name ("1X2"), no full catalog | standardized market_code dictionary (match_winner) | 🔴 |
| Pre-match markets | a handful of common markets | 63 market_codes, fully cataloged | ⬆️ |
| Live (in-play) markets | some common markets, no unified code dictionary | 499 market_codes, full dictionary | ⬆️ |
| WebSocket data | a single livescore_update stream | four streams: scores / situation / pre-match odds / live odds | ⬆️🔴 |
| WebSocket protocol | filter via league_id/match_id in the URL | subscribe protocol: send a subscription code + heartbeat | 🔴 |
| Response envelope | success / data / meta | success / data / meta / traceId | ⬆️ |
| New endpoints | — | seasons, coaches, injuries, match details, live situation, match events, upcoming-fixtures window | ⬆️ |
Two themes run through this release: breadth of data and real-time reach over WebSocket. Let’s take them one at a time.
2. Upgrade #1: Bigger, Cleaner Data Coverage
2.1 Odds: a Standardized market_code Dictionary
In v1, each odds market was represented by a human-readable market_name string with no authoritative catalog — you had to guess and string-match your way through it:
// v1: GET https://api.anysport.io/v1/odds?match_id=1234567
{
"data": [{
"match_id": 1234567,
"bookmakers": [{
"bookmaker_name": "bet365",
"markets": [
{ "market_name": "1X2", "odds": [ {"value":"Home","odd":1.38}, ... ] },
{ "market_name": "Over/Under", "odds": [ {"value":"Over","odd":2.0,"handicap":"2.5"}, ... ] }
]
}]
}]
}The new version fully standardizes markets into a market_code enum dictionary and publishes the complete catalog — enumerable, easy to cross-reference, and easy to build a mapping table against:
- Pre-match odds
GET /odds/prematch: 63market_codes — frommatch_winner,asian_handicap, andgoals_over_undertodouble_chance,ht_ft_double,odd_even, and more. Essentially everything a typical pre-match analysis page needs. - Live odds
GET /odds/live: a full dictionary of 499market_codes — European (3-way) handicap, Asian handicap (including 1st/2nd half), over/under, full-match and half corners, next goal, remaining-time lines, and so on. A single in-play match typically has dozens of active markets updating at once.
For v1 users, this means your old logic that string-matched on market_name needs to switch to routing on market_code (see the migration in Section 4).
⚠️
market_codeis an open enum and will keep growing. We’ll continue adding new markets, so your client should degrade gracefully on unknownmarket_codes rather than throw — skip or pass them through untouched. That way your parsing layer won’t break when we ship new markets.
A few long-standing odds gotchas still apply:
⚠️ Pre-match and live are two independent streams with different label systems. For the same home/draw/away outcome, pre-match uses
Home/Draw/Awaywhile live uses1/X/2— if you want one parser for both streams, you must map between them. Thehandicapvalue also lives in different places (embedded in the option name for pre-match, in the standalonemarkets[].handicapfield for live), and after full time a live match’smarketsmay shrink to an empty array[].
2.2 A Batch of New Endpoints
Beyond odds, this release fills in a lot of data endpoints:
- Seasons
- Coaches
- Injuries
- Match details
- Live match situation
- Upcoming-fixtures window
Together with the existing fixtures, scores, lineups, standings, top scorers, and head-to-head endpoints, that rounds out a complete football data pipeline.
3. Upgrade #2: WebSocket Expands to Four Subscribable Streams
This is the part we’re most excited about — and the biggest change.
The old WebSocket had a single stream. You connected to wss://api.anysport.io/v1/ws/live?api_key=KEY&league_id=148 and the server pushed a continuous feed of livescore_update messages. It could power a scoreboard, but it couldn’t deliver odds, had no dedicated technical-stats stream, and could only be filtered via league_id/match_id in the URL:
// v1: the only push type
{ "type": "livescore_update", "data": [ { "match_id": 1234567, "score": "2-1", "minute": 67, ... } ] }The new version splits it apart and expands it dramatically. Over a single long-lived connection, you can subscribe to any combination of the 4 data products below, each with its own subscription code and push type, independently of the others:
| Data product | Subscribe code | Sub confirmed | Unsubscribe code | Push type |
|---|---|---|---|---|
| Scores | 20200 | 20201 | 21200 | score_update |
| Situation (event feed + technical stats) | 20000 | 20001 | 21000 | situation_update |
| Live odds | 20100 | 20101 | 21100 | odds_live_update |
| Pre-match odds | 20300 | 20301 | 21300 | odds_prematch_update |
The two most tangible changes: odds can be pushed over WebSocket for the first time (both pre-match and live), and the match situation becomes its own richest stream (complete events — goals, cards, substitutions — plus stats_json technical stats and ball_xy ball coordinates). A live betting page that used to stitch together three separate mechanisms — “WebSocket for scores + polling for odds + polling for events” — is now handled by one connection and one match_id.
3.1 Establishing a Connection
The new handshake URL (note the domain is data., not the old api.):
wss://data.anysport.io/v1/ws/live?api_key=YOUR_API_KEYA successful handshake returns a connected message. At this point no data is pushed yet — pushes start only after you send a subscription message:
{ "type": "connected", "message": "WebSocket connected. Send subscribe message to receive data.", "timestamp": "2026-07-13T08:00:00.000Z" }3.2 Subscribe to Scores (20200)
Filters (match_id/league_id/country_id) go inside the subscription message’s data, not the URL. A match_id of null means subscribe to everything allowed by your plan/filters:
{ "code": 20200, "trace": "score-sub-001", "data": { "match_id": null } }Push (score_update; the score semantics match the REST /livescore endpoint exactly):
{
"type": "score_update",
"data": {
"type": "score", "match_id": "as_3b37c382...", "home_team": "Argentina", "away_team": "Switzerland",
"phase": "2H", "minute": 67, "home_score": 2, "away_score": 1, "ht_score": "1-0", "reg_score": "2-1"
},
"timestamp": "2026-07-13T15:47:01.250Z"
}3.3 Subscribe to Live Situation (20000)
{ "code": 20000, "trace": "situation-sub-001", "data": { "match_id": "as_3b37c382..." } }Push (situation_update; includes the event feed, technical stats, and ball coordinates):
{
"type": "situation_update",
"data": {
"type": "situation", "match_id": "as_3b37c382...", "status": "live", "minute": 67,
"ball_xy": "0.52,0.48", "events_json": {}, "stats_json": {}
},
"timestamp": "2026-07-13T15:47:01.250Z"
}3.4 Subscribe to Live Odds (20100) / Pre-match Odds (20300)
{ "code": 20100, "trace": "live-odds-sub-001", "data": { "match_id": "as_3b37c382..." } }Push (odds_live_update):
{
"type": "odds_live_update",
"data": {
"type": "odds", "match_id": "as_3b37c382...", "phase": "live", "main_market": "1X2",
"home_odd": "2.10", "draw_odd": "3.40", "away_odd": "3.20", "markets_json": {}
},
"timestamp": "2026-07-13T15:47:01.250Z"
}For pre-match odds, just switch the code to 20300; the push type is odds_prematch_update and the data structure is identical to live odds, differing only in that data.phase is prematch.
⚠️ Subscription state does not persist across connections. After a reconnect you must re-send your subscription messages. Send a heartbeat every 30 seconds (
code: 20010) or the server will drop you on timeout. The4xxxxseries (e.g. subscription failure40301) are recoverable client-side errors that do not close the connection — fix the message format, fields, or plan permission and retry.
4. Migration Checklist for v1 Users (Important)
This release has breaking changes, so existing integrations need the steps below. It comes down to three things: URL, authentication, and IDs.
4.1 Authentication & URL (required)
- # v1
- GET https://api.anysport.io/v1/odds?match_id=1234567
- X-API-Key: YOUR_API_KEY # or ?api_key=YOUR_API_KEY
+ # New
+ GET https://data.anysport.io/v1/soccer/odds/prematch?match_id=as_3b37c382...
+ apikey: YOUR_API_KEY # this header only; passing the key as a query param always returns 401- Base URL:
api.anysport.io/v1→data.anysport.io/v1/soccer(note the added/soccersegment). - Auth header:
X-API-Key(or?api_key=) →apikey, the lowercase header, only. Still usingX-API-Key, or putting the key in the URL, returns401 UNAUTHORIZED.
4.2 IDs Change from Integers to Prefixed Strings (required)
v1 match_id/league_id/team_id were plain integers; the new version makes them all semantic prefixed strings:
| Prefix | Entity | Example |
|---|---|---|
as_ | Match (unified across all endpoints) | as_3b37c382f39a4235aa93705f053b2da4 |
asl_ | League | asl_62db9cfc3ebf4b87a44570b16668b23e |
ast_ | Team | ast_9137ee449e3b40a68149ca319373adaf |
asx_ asp_ asc_ | Country / Player / Coach | — |
Any database column that stores an ID, and every place you build a URL, needs to move from integer to string. The good news: the same match_id runs through fixtures, scores, situation, odds, and WebSocket, identical everywhere — no ID mapping table required.
4.3 Parse Odds by market_code
Replace logic that string-matched on market_name ("1X2", "Over/Under") with routing on market_code (match_winner, goals_over_under), and degrade gracefully on unknown codes. See the pre-match and live market directories in the new docs for the full catalog.
4.4 Switch WebSocket to the Subscribe Protocol
- Change the URL to
wss://data.anysport.io/v1/ws/live. - Move filters from URL params to a subscription message (
code+data). - Subscribe to whichever codes you need, and add the 30-second heartbeat plus reconnect-and-resubscribe logic.
5. Which Plan Do These Features Require?
| Plan | Price (USDT/month) | Odds | WebSocket |
|---|---|---|---|
| Free trial (7 days) | 0 | ❌ | ❌ |
| Basic | 99 | ❌ | ❌ |
| Pro | 199 | ✅ Pre-match odds | ❌ |
| Premium | 399 | ✅ Pre-match + live | ✅ (all four data streams) |
6. Summary
This upgrade pushes two of AnySport’s core capabilities forward:
- Data breadth: odds standardized into a
market_codedictionary — 63 pre-match plus 499 live — along with a batch of new endpoints (seasons, coaches, injuries, situation, events, and more). - Full real-time coverage: WebSocket goes from a single live-scores stream to four independently subscribable streams — scores, situation, pre-match odds, and live odds — with odds on WebSocket for the first time, all over one connection and one
match_id.
👉 Sign up now at anysport.io and start a free 7-day trial — get the scores stream running first, then upgrade to odds and WebSocket as you need them.