LeagueSpy API v2
The most accurate football lineup predictions on the market. We track injuries, suspensions, and squad rotation patterns to forecast who starts, who sits, and who's out — before anyone else.
Quick start
curl -H "X-API-Key: YOUR_KEY" \
"https://api.leaguespy.com/v2/fixtures/updates?limit=1"
league_id or team_id to narrow results, or use updated_since to poll only for changes.Authentication
Every request requires an API key. Pass it as a header or query parameter.
# Header (recommended)
curl -H "X-API-Key: YOUR_KEY" \
"https://api.leaguespy.com/v2/fixtures/updates"
# Query parameter
curl "https://api.leaguespy.com/v2/fixtures/updates?api_key=YOUR_KEY"
Tiers
Each API key is bound to a tier. Your tier determines data freshness, update frequency, and field visibility.
| Tier | Sync | Description |
|---|---|---|
| professional | Every 3 hours | Predicted XI and bench, missing players with reasons, official lineups as soon as published. See the competitions. |
| realtime | ≤15 min | Full depth: probabilities and expected minutes, squad roles, absence impact, returning players, positional battles, season statistics. See the competitions. |
meta.tier and subscription.tier.
List fixture updates
Returns fixture lineup previews sorted by most recently updated. Includes predicted XI, bench, missing players, and confirmed lineups when available.
Query parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
| limit | integer | 20 | Results per page. Range: 1–100. |
| offset | integer | 0 | Pagination offset. Range: 0–5000. |
| team_id | string | — | Filter by team public ID (matches home or away). |
| league_id | string | — | Filter by league public ID. |
| fixture_id | string | — | Filter by fixture public ID. |
| updated_since | string | — | ISO 8601 datetime with timezone. Only return fixtures updated after this time. Maximum lookback: 48 hours.2026-06-05T08:30:00Z |
| cursor | string | — | Opaque pagination cursor for stable incremental polling. Use the next_cursor value from the previous response. Only valid together with updated_since. Cannot be combined with offset. |
| include | string | — | Optional response blocks, comma-separated. league_stats adds season statistics to player objects, broadcasts the TV and streaming broadcasters of the fixture. |
| lang | string | — | Response language for names, positions and reasons, e.g. ko. See Localization. |
Example request
curl -H "X-API-Key: YOUR_KEY" \
"https://api.leaguespy.com/v2/fixtures/updates?league_id=lg_xyz789&limit=5"
Response
{
"data": [
{
"fixture_id": "VJfWANbE",
"home_team_id": "11uGdbIt",
"home_team_name": "Levante",
"home_team_name_en": "Levante",
"home_team_logo": "https://img.leaguespy.com/teams/11uGdbIt.png",
"away_team_id": "aGpkiedc",
"away_team_name": "Athletic Club",
"away_team_name_en": "Athletic Club",
"away_team_logo": "https://img.leaguespy.com/teams/aGpkiedc.png",
"league_id": "QBIQ7xJS",
"league_name": "La Liga",
"league_name_en": "La Liga",
"league_logo": "https://img.leaguespy.com/leagues/QBIQ7xJS.png",
"country_name": "Spain",
"country_name_en": "Spain",
"season_id": "n82fEZtc",
"season_name": "2026/2027",
"starting_at": "2026-10-21T18:00:00Z",
"status": "scheduled",
"home_score": null,
"away_score": null,
"updated_at": "2026-10-21T09:16:54.882613Z",
"lineup": {
"home": {
"formation": "4-1-4-1",
"is_confirmed": false,
"is_nomination_announced": false,
"starting_xi": [
{
"name": "Ryan M.",
"name_en": "Ryan M.",
"player_id": "BFKC5XyX",
"squad_role": "regular",
"detailed_position": "Goalkeeper",
"formation_position": 1,
"start_xi_probability": 99,
"bench_probability": 0,
"expected_minutes": 90,
"expected_sub_off_probability": 0,
"expected_sub_off_minute": null
},
{
"name": "Ratkov P.",
"name_en": "Ratkov P.",
"player_id": "jzHpyPj5",
"squad_role": "backup",
"detailed_position": "Centre Forward",
"formation_position": 11,
"start_xi_probability": 10,
"bench_probability": 40,
"expected_minutes": 60.0,
"expected_sub_off_probability": 100,
"expected_sub_off_minute": 60
}
],
"bench": [
{
"name": "Axel Tape",
"name_en": "Axel Tape",
"player_id": "W10cOGaz",
"squad_role": "youth",
"detailed_position": "Right Back",
"start_xi_probability": 0,
"bench_probability": 50,
"expected_minutes": 0,
"expected_sub_in_probability": 0,
"expected_sub_in_minute": null
}
],
"missing": [
{
"name": "Primo A.",
"name_en": "Primo A.",
"player_id": "Y78HfNjW",
"squad_role": null,
"detailed_position": "Goalkeeper",
"missing_type": "injury",
"reason": "Shoulder Injury",
"missed_in_row": 10,
"days_missed": 157,
"expected_return": {
"from": "2026-11-29",
"to": "2027-02-24"
},
"absence_impact": null
},
{
"name": "Sotelo H.",
"name_en": "Sotelo H.",
"player_id": "oSwdFDDa",
"squad_role": "backup",
"detailed_position": "Central Midfield",
"missing_type": "doubtful",
"reason": "Knee Injury",
"missed_in_row": 3,
"days_missed": 31,
"expected_return": null,
"absence_impact": "low",
"play_probability": 30,
"start_xi_probability": 17
}
],
"new_arrivals": [],
"returning": [
{
"name": "Marc Santos",
"name_en": "Marc Santos",
"player_id": "F1PnN5eB",
"squad_role": "youth",
"detailed_position": "Left Back",
"games_missed": 2,
"days_out": 8,
"returning_to": "bench"
}
],
"positional_battles": [
{
"position": "Right Back",
"formation_position": 2,
"contenders": [
{
"name": "Toljan J.",
"name_en": "Toljan J.",
"player_id": "0G8ozWJE",
"squad_role": "rotation",
"probability": 50
},
{
"name": "Nacho Pérez",
"name_en": "Nacho Pérez",
"player_id": "fIaRlrWZ",
"squad_role": "regular",
"probability": 50
}
]
}
],
"lineup_changes": {
"count": 4,
"in": [
{
"name": "Toljan J.",
"name_en": "Toljan J.",
"player_id": "0G8ozWJE"
},
{
"name": "Mandi A.",
"name_en": "Mandi A.",
"player_id": "6DY8rtL6"
},
{
"name": "Olasagasti J. A.",
"name_en": "Olasagasti J. A.",
"player_id": "6dWOnhit"
},
{
"name": "Ratkov P.",
"name_en": "Ratkov P.",
"player_id": "jzHpyPj5"
}
],
"out": [
{
"name": "Nacho Pérez",
"name_en": "Nacho Pérez",
"player_id": "fIaRlrWZ"
},
{
"name": "Ifeanyi Ndukwe",
"name_en": "Ifeanyi Ndukwe",
"player_id": "c3gj48hd"
},
{
"name": "Enzo Bardeli",
"name_en": "Enzo Bardeli",
"player_id": "RrdKtGfe"
},
{
"name": "Thiago Fernández",
"name_en": "Thiago Fernández",
"player_id": "k2fmKhNO"
}
]
}
}
}
}
],
"meta": {
"total": 1,
"limit": 20,
"offset": 0,
"next_cursor": null,
"has_more": false,
"tier": "realtime",
"timezone": "UTC"
},
"rate_limit": {
"remaining": 119,
"limit": 120,
"resets_in_seconds": 60
},
"subscription": {
"plan": "LeagueSpy Realtime",
"sport": "Football",
"tier": "realtime"
}
}
{
"data": [
{
"fixture_id": "VJfWANbE",
"home_team_id": "11uGdbIt",
"home_team_name": "Levante",
"home_team_name_en": "Levante",
"home_team_logo": "https://img.leaguespy.com/teams/11uGdbIt.png",
"away_team_id": "aGpkiedc",
"away_team_name": "Athletic Club",
"away_team_name_en": "Athletic Club",
"away_team_logo": "https://img.leaguespy.com/teams/aGpkiedc.png",
"league_id": "QBIQ7xJS",
"league_name": "La Liga",
"league_name_en": "La Liga",
"league_logo": "https://img.leaguespy.com/leagues/QBIQ7xJS.png",
"country_name": "Spain",
"country_name_en": "Spain",
"season_id": "n82fEZtc",
"season_name": "2026/2027",
"starting_at": "2026-10-21T18:00:00Z",
"status": "scheduled",
"home_score": null,
"away_score": null,
"updated_at": "2026-10-21T09:16:54.882613Z",
"lineup": {
"home": {
"formation": "4-1-4-1",
"is_confirmed": false,
"is_nomination_announced": false,
"starting_xi": [
{
"name": "Ryan M.",
"name_en": "Ryan M.",
"player_id": "BFKC5XyX",
"formation_position": 1
},
{
"name": "Ratkov P.",
"name_en": "Ratkov P.",
"player_id": "jzHpyPj5",
"formation_position": 11
}
],
"bench": [
{
"name": "Axel Tape",
"name_en": "Axel Tape",
"player_id": "W10cOGaz"
}
],
"missing": [
{
"name": "Primo A.",
"name_en": "Primo A.",
"player_id": "Y78HfNjW",
"missing_type": "injury",
"reason": "Shoulder Injury"
},
{
"name": "Sotelo H.",
"name_en": "Sotelo H.",
"player_id": "oSwdFDDa",
"missing_type": "doubtful",
"reason": "Knee Injury"
}
],
"new_arrivals": [],
"lineup_changes": {
"count": 4,
"in": [
{
"name": "Toljan J.",
"name_en": "Toljan J.",
"player_id": "0G8ozWJE"
},
{
"name": "Mandi A.",
"name_en": "Mandi A.",
"player_id": "6DY8rtL6"
},
{
"name": "Olasagasti J. A.",
"name_en": "Olasagasti J. A.",
"player_id": "6dWOnhit"
},
{
"name": "Ratkov P.",
"name_en": "Ratkov P.",
"player_id": "jzHpyPj5"
}
],
"out": [
{
"name": "Nacho Pérez",
"name_en": "Nacho Pérez",
"player_id": "fIaRlrWZ"
},
{
"name": "Ifeanyi Ndukwe",
"name_en": "Ifeanyi Ndukwe",
"player_id": "c3gj48hd"
},
{
"name": "Enzo Bardeli",
"name_en": "Enzo Bardeli",
"player_id": "RrdKtGfe"
},
{
"name": "Thiago Fernández",
"name_en": "Thiago Fernández",
"player_id": "k2fmKhNO"
}
]
}
}
}
}
],
"meta": {
"total": 1,
"limit": 20,
"offset": 0,
"next_cursor": null,
"has_more": false,
"tier": "professional",
"timezone": "UTC"
},
"rate_limit": {
"remaining": 29,
"limit": 30,
"resets_in_seconds": 60
},
"subscription": {
"plan": "LeagueSpy Professional",
"sport": "Football",
"tier": "professional"
}
}
Get single fixture
Returns lineup data for a single fixture by its public ID. Response is the same shape as one item from the data array above, with rate_limit and subscription at the top level.
Path parameter
| Parameter | Type | Description |
|---|---|---|
| fixture_id | string | The fixture's public ID. |
Example
curl -H "X-API-Key: YOUR_KEY" \
"https://api.leaguespy.com/v2/fixtures/fx_a1b2c3"
Response
Returns the fixture object wrapped in a data object, with rate_limit and subscription at the top level.
{
"data": {
"fixture_id": "fx_a1b2c3",
"home_team_name": "FC Barcelona",
"away_team_name": "Real Madrid",
"lineup": { /* ... */ } // Same structure as list response
},
"rate_limit": { /* ... */ },
"subscription": { /* ... */ }
}
Health check
No authentication required. Returns a simple status object.
{ "status": "ok" }
Fixture object
One item of data in /v2/fixtures/updates, and data of /v2/fixtures/{fixture_id}.
| Field | Type | Description |
|---|---|---|
| fixture_id | string | Fixture ID (opaque string). |
| home_team_id | string | Home team ID. |
| home_team_name | string | Home team name (localized with ?lang=). |
| home_team_name_en | string | English / original name, on every request (use it for matching). |
| home_team_logo | string (URL) | Home team logo. A generic placeholder image when the team has no logo. |
| away_team_id | string | Away team ID. |
| away_team_name | string | Away team name (localized with ?lang=). |
| away_team_name_en | string | English / original name, on every request (use it for matching). |
| away_team_logo | string (URL) | Away team logo (placeholder image when none). |
| league_id | string | Competition ID. |
| league_name | string | Competition name (localized with ?lang=). |
| league_name_en | string | English / original name, on every request (use it for matching). |
| league_logo | string (URL) | Competition logo (placeholder image when none). |
| country_name | string | Country of the competition. International competitions use a region: World, Europe, Asia, South America, North & Central America… |
| country_name_en | string | English / original name, on every request (use it for matching). |
| season_id | string | Season ID. |
| season_name | string | Season label: 2026/2027 for seasons across the turn of the year, 2026 for calendar-year seasons. |
| starting_at | string | Kickoff time, UTC (YYYY-MM-DDTHH:MM:SSZ). Follows any rescheduling. |
| status | string | Match status: scheduled, live, finished, postponed, cancelled… See status values. |
| home_score | integer | null | Home team goals: the current score while the match is live, the final score once it is finished. null before kickoff, for postponed or cancelled matches and when no score is known. A goal does not change updated_at, and a match leaves /v2/fixtures/updates one hour after kickoff, so read the live and the final score from /v2/fixtures/{fixture_id}. |
| away_score | integer | null | Away team goals: the current score while the match is live, the final score once it is finished. null before kickoff, for postponed or cancelled matches and when no score is known. A goal does not change updated_at, and a match leaves /v2/fixtures/updates one hour after kickoff, so read the live and the final score from /v2/fixtures/{fixture_id}. |
| period | string | null | Part of a live match: first_half, half_time, second_half, break (before extra time, between its halves or before penalties), extra_time, penalties. null when the match is not live. |
| minute | integer | null | Match minute while the ball is in play (1 to 45, 46 to 90, 91 to 120). In added time it stays at 45, 90, 105 or 120 and extra_minute counts the added minutes (45+2 = minute 45, extra_minute 2). null at half-time, in breaks, during penalties and when the match is not live. Accurate to about 30 seconds. |
| extra_minute | integer | null | Added-time minutes on top of minute; 0 outside added time, null when minute is null. |
| updated_at | string | Last time this fixture changed: lineup data, status or kickoff time. ISO 8601 UTC, the number of fractional-second digits varies. Use it for incremental polling. |
| lineup | object | lineup.home and lineup.away team objects. |
| broadcasts | array | null | TV and streaming broadcasters by country, see broadcasts. Only with ?include=broadcasts; null otherwise. Optional, present only when it applies. |
Lineup object
Each side, lineup.home and lineup.away.
| Field | Type | Description |
|---|---|---|
| formation | string | null | Formation, e.g. 4-2-3-1. Predicted while is_confirmed is false, official afterwards. null when not known. |
| is_confirmed | boolean | true once the official starting lineup is published. From then on starting_xi, bench and formation hold the official data. |
| is_nomination_announced | boolean | true once the official matchday squad is known. Currently switches together with is_confirmed. |
| starting_xi | array | Starting eleven, predicted before confirmation and official after. [] when no lineup is available yet. |
| bench | array | Substitutes, predicted before confirmation and official after. Can be []. |
| missing | array | Players who are out or doubtful for this match. [] when none are known. |
| new_arrivals | array | Recent signings named in this matchday squad. [] when none. |
| returning | array | RT Players in this match's XI or bench who missed the team's most recent match(es). At most 4. |
| positional_battles | array | RT Positions where the starting choice is open. |
| lineup_changes | object | null | Changes in starting_xi compared with the team's previous match. See lineup changes. null when the two lineups cannot be compared. |
Data lifecycle
- A fixture appears in
/v2/fixtures/updatesonce lineup data exists for it, from up to 7 days before kickoff, and stays until 1 hour after kickoff (48 hours for postponed, interrupted, cancelled and similar fixtures). - Predicted lineups and missing players arrive first, up to 7 days before kickoff (a team that plays twice in a week has both matches), where a prediction is available for the competition. The prediction is updated with every new piece of information until the official lineup. Before confirmation
is_confirmedisfalseandstarting_xi/benchhold the prediction. - The official lineup replaces the prediction as soon as it is published, usually 40 to 60 minutes before kickoff (about 50 to 60 minutes in the top European leagues and UEFA club competitions).
is_confirmedswitches totrueand is never switched back by a later prediction. For some lower-division matches the official lineup arrives only shortly before kickoff. - Every change of lineup data,
statusorstarting_atupdatesupdated_at, so polling withupdated_sincesees all of them. /v2/fixtures/{fixture_id}returns matches from the start of your subscription onwards.
Player objects
Players in starting_xi and bench.
starting_xi[]
| Field | Type | Description |
|---|---|---|
| name | string | Player name (localized with ?lang=). |
| name_en | string | English / original name, on every request (use it for matching). |
| player_id | string | null | Player ID. null only if the player could not be identified. |
| squad_role | string | null | RT Role in the squad this season. See squad_role. |
| detailed_position | string | RT Usual position. See positions. Always English. Optional, present only when it applies. |
| detailed_position_label | string | RT Position in the requested language. Only with ?lang=. Optional, present only when it applies. |
| formation_position | integer | null | Slot in the formation grid, 1 to 11. See formation_position. |
| exact_position | string | Official tactical slot code, e.g. RCB. Only on some official lineups. Optional, present only when it applies. |
| start_xi_probability | integer | null | RT Chance (%) to start, 0 to 99: starts in the team's last 10 competitive matches. Players in an official lineup have 99. null without recent match history. |
| bench_probability | integer | null | RT Chance (%) to be named among the substitutes, 0 to 99. |
| expected_minutes | number | RT Most likely minutes played: 90, or the expected substitution minute when a substitution is more likely than not. 0 to 90. |
| expected_sub_off_probability | integer | null | RT Chance (%) to be substituted off. Goalkeepers 0. |
| expected_sub_off_minute | integer | null | RT Expected substitution minute, 1 to 89. null when the chance is below 25 %. |
| was_doubtful | boolean | true when the player was doubtful before the match but is in the lineup. Optional, present only when it applies. |
| debut | boolean | true when this can be the player's first appearance for the club (see new_arrivals). Optional, present only when it applies. |
| returning_after_missed | integer | On some official lineups: consecutive matches the player missed before this one. Optional, present only when it applies. |
| league_stats | object | Season statistics, see league_stats. Only with ?include=league_stats. |
bench[]
| Field | Type | Description |
|---|---|---|
| name | string | Player name. |
| name_en | string | English / original name, on every request (use it for matching). |
| player_id | string | null | Player ID. |
| squad_role | string | null | RT Role in the squad this season. |
| detailed_position | string | RT Usual position (always English). Optional, present only when it applies. |
| detailed_position_label | string | RT Position in the requested language. Only with ?lang=. Optional, present only when it applies. |
| start_xi_probability | integer | null | RT Chance (%) to start. In a predicted lineup never above the lowest starting_xi player at the same detailed_position. Official substitutes have 0. |
| bench_probability | integer | null | RT Chance (%) to be named among the substitutes. |
| expected_minutes | number | null | RT Most likely minutes: 0, or the expected minutes after coming on when that is more likely than not. |
| expected_sub_in_probability | integer | null | RT Chance (%) to come on. Goalkeepers 0. |
| expected_sub_in_minute | integer | null | RT Expected minute of coming on, 1 to 89. null below 25 %. |
| was_doubtful | boolean | Doubtful before the match but named in the squad. Optional, present only when it applies. |
| debut | boolean | Possible first appearance for the club. Optional, present only when it applies. |
| league_stats | object | Season statistics. Only with ?include=league_stats. |
Missing player object
Players in missing[]: out or doubtful for this match.
| Field | Type | Description |
|---|---|---|
| name | string | Player name. |
| name_en | string | English / original name, on every request (use it for matching). |
| player_id | string | null | Player ID. |
| squad_role | string | null | RT Role in the squad this season. |
| detailed_position | string | RT Usual position (always English). Optional, present only when it applies. |
| detailed_position_label | string | RT Position in the requested language. Only with ?lang=. Optional, present only when it applies. |
| missing_type | string | Category of the absence. doubtful means the player may still play. See missing_type. |
| reason | string | null | Short reason from a fixed list, e.g. Knee Injury, Red Card, Transfer to <club> (<country>). See reasons. Always English; the translation is in reason_label. null when no reason is known. |
| reason_label | string | Reason in the requested language. Only with ?lang=. Optional, present only when it applies. |
| missed_in_row | integer | RT Consecutive played team matches (friendlies included), right before this one, without the player in the matchday squad (counted since he joined the team). 0 = he was in the last squad. 10 with no earlier squad on record = 10 or more. |
| days_missed | integer | null | RT Days between the first match of the current absence and this match. null when no match has been missed yet. |
| expected_return | object | null | RT Estimated return window of an injured or suspended player: the first and last date he is expected back. For a suspension both dates are the date of the first match after the ban. Updated as new information arrives. null for other absences and when no estimate is available. |
| expected_return.from / .to | string | RT Dates, YYYY-MM-DD. from equals to when a single date is known. |
| absence_impact | string | null | RT How strongly the team should feel the absence. See absence_impact. |
| start_xi_probability | integer | RT Only for some doubtful players: chance (%) to start, 0 to 100. Optional, present only when it applies. |
| play_probability | integer | RT Only for some doubtful players: chance (%) to play any minutes, 0 to 100. Optional, present only when it applies. |
| transfer_date | string | Only for transfer_out: date the player left (YYYY-MM-DD). Optional, present only when it applies. |
| to_team_country | string | Only for transfer_out: country of the new club (localized with ?lang=). Optional, present only when it applies. |
| to_team_country_en | string | English / original name, on every request (use it for matching). Optional, present only when it applies. |
| to_team_tier | integer | null | Only for transfer_out: league level of the new club (1 = top division). Optional, present only when it applies. |
| league_stats | object | Season statistics. Only with ?include=league_stats. |
New arrival object
Players in new_arrivals[]: joined the club recently and are named in this match's XI or bench. Listed for the first 3 matches after the move.
| Field | Type | Description |
|---|---|---|
| name | string | Player name. |
| name_en | string | English / original name, on every request (use it for matching). |
| player_id | string | Player ID. |
| signed_from | string | null | Previous club with its country, Club (Country) (localized with ?lang=). null when not known. |
| signed_from_en | string | English / original name, on every request (use it for matching). Optional, present only when it applies. |
| transfer_date | string | Date the player joined (YYYY-MM-DD). |
| stage | string | Debut progress at the new club. See stage. |
| games_since_arrival | integer | Team matches played since the player joined, 0 to 2. |
| starts | integer | Starts for the club since joining, 0 to 2. |
Returning player object
RT Players in returning[]: named in this match's XI or bench after missing the team's most recent match(es). At most 4 per team, longest absences first.
| Field | Type | Description |
|---|---|---|
| name | string | RT Player name. |
| name_en | string | RT English / original name, on every request (use it for matching). |
| player_id | string | RT Player ID. |
| squad_role | string | null | RT Role in the squad this season. |
| detailed_position | string | null | RT Usual position (always English). |
| detailed_position_label | string | RT Position in the requested language. Only with ?lang=. Optional, present only when it applies. |
| games_missed | integer | RT Consecutive team matches missed before this one, 1 to 10 (10 = 10 or more). |
| days_out | integer | null | RT Days between the first missed match and this match. |
| returning_to | string | RT starting_xi or bench: where the player is listed for this match. |
Positional battle object
RT Items of positional_battles[]: positions where the player in the predicted XI is not a clear choice — a challenger is a bench player at the same position whose starts in recent matches are close to, and not above, the starter's. probability is each player's chance to start this match, so the starter's counts his place in the predicted XI and the challengers share at most the rest (e.g. 78 vs 22).
| Field | Type | Description |
|---|---|---|
| position | string | RT Contested position (always English). |
| position_label | string | RT Position in the requested language. Only with ?lang=. Optional, present only when it applies. |
| formation_position | integer | RT Slot in the formation grid, 1 to 11. |
| contenders | array | RT Candidates, 2 or more. The first one is the player currently in starting_xi. |
| contenders[].name | string | RT Player name. |
| contenders[].name_en | string | RT English / original name, on every request (use it for matching). |
| contenders[].player_id | string | RT Player ID. |
| contenders[].squad_role | string | null | RT Role in the squad this season. |
| contenders[].probability | integer | RT Chance (%) that this player starts, 0 to 99. |
Lineup changes object
lineup_changes compares starting_xi with the starting eleven of the team's previous finished match in any competition. Club friendlies are skipped; for national teams friendlies count. Before confirmation it uses the predicted XI, after confirmation the official one. null when there is no previous match with a complete lineup, when the current XI is not complete yet, and after the team plays another match, until the comparison is refreshed (at the latest on the day of the match).
| Field | Type | Description |
|---|---|---|
| count | integer | Players in starting_xi who did not start the previous match. 0 = the same eleven. |
| in | array | Players who start now but did not start the previous match. |
| out | array | Players who started the previous match but are not in starting_xi now. |
| in[].name / out[].name | string | Player name (localized with ?lang=). |
| in[].name_en / out[].name_en | string | English / original name, on every request (use it for matching). |
| in[].player_id / out[].player_id | string | Player ID. |
Season statistics (league_stats)
Optional block on starting_xi[], bench[] and missing[] players, added with ?include=league_stats. Always refers to the player's domestic league, also for cup and international matches.
| Field | Type | Description |
|---|---|---|
| league_stats.current_season | object | null | The player's record for this team in the current league season. null when there is none. Only with ?include=league_stats. |
| league_stats.previous_season | object | null | Previous league season (club with most appearances). Filled only until the team has played 4 league matches of the new season. Only with ?include=league_stats. |
| …league / league_id | string | League name (localized with ?lang=) and ID. Only with ?include=league_stats. |
| …league_en | string | English / original name, on every request (use it for matching). Only with ?include=league_stats. |
| …season | string | Season label. Only with ?include=league_stats. |
| …team / team_id | string | Team the numbers belong to (localized with ?lang=) and its ID. Only with ?include=league_stats. |
| …team_en | string | English / original name, on every request (use it for matching). Only with ?include=league_stats. |
| …appearances / starts / sub_appearances | integer | Matches played, started, and entered as a substitute. Only with ?include=league_stats. |
| …substituted_off / bench_appearances | integer | Matches substituted off; matches named on the bench. Only with ?include=league_stats. |
| …minutes / goals / assists | integer | Minutes, goals, assists. Only with ?include=league_stats. |
| …yellow_cards / second_yellow_cards / red_cards | integer | Yellow cards, second yellows, direct red cards. Only with ?include=league_stats. |
Localization
Add ?lang=ko to either fixtures endpoint, or ask us to set Korean as your key's default language. Without a language parameter (or with ?lang=en) the response is in English, unless your key has a default language. GET /v2/languages lists the available languages.
Names are translated in place: team, league, country and player names (also inside league_stats), signed_from and to_team_country. A name without a translation is returned in English. The English original is always available next to it in *_en (home_team_name_en, name_en, …), on every request, so you can match against your own data.
Fixed values are never translated: detailed_position, positional_battles[].position and reason always stay in English. With a language, their translation is added in detailed_position_label, position_label and reason_label. Codes such as status, missing_type, squad_role, absence_impact and stage, IDs, numbers, dates, formations and season labels are never translated.
We announce any change to the language or format of response values in advance, by email and in the changelog.
Broadcasts (broadcasts)
Optional block on the fixture, added with ?include=broadcasts: the broadcasters known for the match, one entry per country. England, Scotland, Wales and Northern Ireland are listed together as United Kingdom. Broadcast information usually appears about three days before kickoff; an empty array means no broadcaster is known yet. Broadcasters can be added or change without a change of updated_at, so read the block when you show the match.
| Field | Type | Description |
|---|---|---|
| country | string | Country (localized with ?lang=). Optional, present only when it applies. |
| country_en | string | English name of the country, on every request. Optional, present only when it applies. |
| channels[].channel | string | Broadcaster or channel. Korean broadcasters in Korean with ?lang=ko where they write their name in Korean. Optional, present only when it applies. |
| channels[].channel_en | string | Original name of the broadcaster, on every request. Optional, present only when it applies. |
| channels[].type | string | tv (a TV channel) or streaming (a streaming service or app). Optional, present only when it applies. |
Meta, rate limit & subscription
meta is part of every list response; rate_limit and subscription of every response.
| Field | Type | Description |
|---|---|---|
| meta.total | integer | null | Total matching fixtures. null in cursor mode. |
| meta.limit | integer | Page size used. |
| meta.offset | integer | null | Offset used. null in cursor mode. |
| meta.next_cursor | string | null | Cursor for the next page. null on the last page. |
| meta.has_more | boolean | true when more pages are available. |
| meta.tier | string | professional or realtime. |
| meta.timezone | string | Always UTC. |
| rate_limit.remaining | integer | Requests left in the current one-minute window. |
| rate_limit.limit | integer | Requests allowed per minute. |
| rate_limit.resets_in_seconds | integer | Seconds until the window resets. |
| subscription.plan | string | Plan name, e.g. LeagueSpy Realtime. |
| subscription.sport | string | Always Football. |
| subscription.tier | string | professional or realtime. |
Value lists
status
Fixtures in postponed, suspended, interrupted, cancelled, abandoned or awarded stay in /v2/fixtures/updates for 48 hours after kickoff. A status or kickoff change updates updated_at.
| Value | Meaning |
|---|---|
| scheduled | Not started yet. |
| tba | Kickoff time not fixed yet. |
| delayed | Kickoff pushed back on the day. |
| live | In play (including half-time, extra time and penalties). |
| interrupted | Stopped during play (e.g. weather) and may resume. |
| finished | Finished (also after extra time or penalties). |
| postponed | Postponed. starting_at shows the new date once it is known. |
| suspended | Stopped, to be continued on another day. |
| cancelled | Cancelled, will not be played. |
| abandoned | Stopped and will not be continued. |
| awarded | Result decided off the pitch (e.g. walkover). |
| unknown | Status not confirmed yet. |
missing_type
| Value | Meaning |
|---|---|
| injury | Injured or ill. |
| suspended | Suspended (cards, red card or disciplinary ban). |
| doubtful | Doubtful: may still play. start_xi_probability and play_probability may be given. |
| national_team | Away on national team duty. |
| out_of_selection | Fit but not in the matchday squad (coach's decision, rested, not registered). |
| transfer_out | Left the club recently (transfer or loan). Shown for the first few matches after the move. |
| other | Unavailable for another reason (e.g. lacking match fitness, personal reasons). |
absence_impact
| Value | Meaning |
|---|---|
| critical | Key player, absence just started. Major effect expected. |
| high | Clear effect expected. |
| medium | Noticeable effect. |
| low | Small effect. |
| minimal | Little or no effect (fringe or youth player). |
| null | Not known (player's role not classified). |
squad_role
| Value | Meaning |
|---|---|
| key_player | One of the team's most important players this season. |
| regular | First-choice starter. A long-injured, ill, banned or doubtful player keeps the role he had when fit. |
| rotation | Plays regularly but rotates with others. |
| backup | Squad player with limited playing time. |
| youth | Young player with limited first-team time. |
| null | Not classified (e.g. too few matches this season). |
new_arrivals[].stage
| Value | Meaning |
|---|---|
| pre_debut | First time in a matchday squad for the new club. |
| bench_debut | Named in a squad before, has not played yet. |
| played | Has played for the club, not started yet. |
| started | Has started for the club. |
returning[].returning_to
| Value | Meaning |
|---|---|
| starting_xi | Returns in the starting XI. |
| bench | Returns on the bench. |
Absence reasons (reason)
reason always comes from this list or one of the transfer templates. With ?lang=ko it is returned in Korean (right column).
| Value | Korean (?lang=ko) |
|---|---|
| Abdominal strain | 복근 부상 |
| Achilles Tendon Injury | 아킬레스건 부상 |
| Ankle Injury | 발목 부상 |
| Arm Injury | 팔 부상 |
| Back Injury | 허리 부상 |
| Broken Hand | 손 골절 |
| Broken Leg | 다리 골절 |
| Broken ankle | 발목 골절 |
| Broken calfbone | 종아리뼈 골절 |
| Broken cheekbone | 광대뼈 골절 |
| Broken collarbone | 쇄골 골절 |
| Broken hipbone | 고관절 골절 |
| Broken jawbone | 턱뼈 골절 |
| Broken nose | 코뼈 골절 |
| Broken rib | 갈비뼈 골절 |
| Broken shinbone | 정강이뼈 골절 |
| Broken tailbone | 꼬리뼈 골절 |
| Broken thighbone | 대퇴골 골절 |
| Calf Injury | 종아리 부상 |
| Chest Injury | 가슴 부상 |
| Coach's decision | 감독 판단 |
| Concussion | 뇌진탕 |
| Contusion | 타박상 |
| Convalescence | 회복 중 |
| Cruciate Ligament Injury | 십자인대 부상 |
| Dislocation | 탈구 |
| Doping | 도핑 징계 |
| Doubtful | 출전 불투명 |
| Elbow Injury | 팔꿈치 부상 |
| Excluded | 명단 제외 |
| Eye injury | 눈 부상 |
| Face Injury | 얼굴 부상 |
| Finger Injury | 손가락 부상 |
| Foot Injury | 발 부상 |
| Forearm injury | 아래팔 부상 |
| Fracture | 골절 |
| Groin Injury | 사타구니 부상 |
| Hamstring Injury | 햄스트링 부상 |
| Hand Injury | 손 부상 |
| Head Injury | 머리 부상 |
| Health problems | 건강 문제 |
| Heart Problems | 심장 이상 |
| Heel Injury | 발뒤꿈치 부상 |
| Hernia | 탈장 |
| Hip Injury | 고관절 부상 |
| Illness | 질병 |
| Inactive | 명단 제외 |
| Injury | 부상 |
| International duty | 국가대표 차출 |
| Jaw injury | 턱 부상 |
| Knee Injury | 무릎 부상 |
| Knee Ligament Injury | 무릎 인대 부상 |
| Knock | 가벼운 부상 |
| Lack of regular playing time at club | 소속팀 출전 시간 부족 |
| Lacking Match Fitness | 경기 감각 부족 |
| Leg Injury | 다리 부상 |
| Ligament Injury | 인대 부상 |
| Loan agreement | 임대 계약 조항 |
| Lower Back Injury | 허리 부상 |
| Lower-Body Injury | 하체 부상 |
| Meniscus Injury | 반월판 부상 |
| Muscle Injury | 근육 부상 |
| Muscle Tear | 근육 파열 |
| Muscle Tightness | 근육 경직 |
| Neck Injury | 목 부상 |
| Not considered | 전력 외 |
| Not in squad | 명단 제외 |
| Off the roster | 엔트리 제외 |
| Other | 기타 |
| Overload | 피로 누적 |
| Pelvis Injury | 골반 부상 |
| Personal Reasons | 개인 사정 |
| Red Card | 퇴장 징계 |
| Rest | 휴식 |
| Ribs Injury | 갈비뼈 부상 |
| Shin Injury | 정강이 부상 |
| Shoulder Injury | 어깨 부상 |
| Stomach Disorder | 위장 장애 |
| Surgery | 수술 |
| Suspended | 출장 정지 |
| Tendon Injury | 힘줄 부상 |
| Thigh Injury | 허벅지 부상 |
| Toe Injury | 발가락 부상 |
| Tooth injury | 치아 부상 |
| Transfer | 이적 |
| Transfer negotiations | 이적 협상 |
| Upper Back Injury | 등 부상 |
| Upper-Body Injury | 상체 부상 |
| Without a club | 무소속 |
| Wrist Injury | 손목 부상 |
| Yellow Cards | 경고 누적 |
Transfer templates
Transfer to <club> (<country>), Transfer/loan to <club> (<country>), Loan ended (returned to <club> (<country>))
Positions
Values of detailed_position and positional_battles[].position. Defender, Midfielder and Attacker appear when only the line is known.
| Value | Korean (?lang=ko) |
|---|---|
| Goalkeeper | 골키퍼 |
| Centre Back | 센터백 |
| Left Back | 레프트백 |
| Right Back | 라이트백 |
| Left Wing Back | 왼쪽 윙백 |
| Right Wing Back | 오른쪽 윙백 |
| Defensive Midfield | 수비형 미드필더 |
| Central Midfield | 중앙 미드필더 |
| Attacking Midfield | 공격형 미드필더 |
| Left Midfield | 왼쪽 미드필더 |
| Right Midfield | 오른쪽 미드필더 |
| Left Wing | 왼쪽 윙어 |
| Right Wing | 오른쪽 윙어 |
| Striker | 스트라이커 |
| Centre Forward | 센터포워드 |
| Second Striker | 세컨드 스트라이커 |
| Defender | 수비수 |
| Midfielder | 미드필더 |
| Attacker | 공격수 |
formation_position
1 is the goalkeeper, then each line from defence to attack, each line read from right to left from the team's own view. Example 4-3-3: 1 GK, 2–5 back four (2 right back … 5 left back), 6–8 midfield, 9–11 forwards.
formation
Read from defence to attack, goalkeeper not counted, e.g. 4-2-3-1, 4-3-3, 4-4-2, 3-4-2-1, 4-1-4-1, 3-4-3, 3-5-2, 5-4-1, 5-3-2, 3-4-1-2, 3-1-4-2, 4-3-1-2, 4-1-3-2, 4-4-1-1, 4-2-2-2, 4-5-1.
exact_position codes
GK, RB, RCB, CB, LCB, LB, RWB, LWB, RDM, DM, LDM, RCM, CM, LCM, RM, LM, RAM, AM, LAM, RW, LW, CF, ST.
Probabilities and minutes
All probabilities are whole percentages, 0 to 100 (start_xi_probability and bench_probability are capped at 99). In an official lineup starters have start_xi_probability: 99 and substitutes 0. Minute fields are 1 to 89; null means not expected (chance below 25 %).
Null, empty and absent
An empty array [] means nothing is known, not an error. null means not known. Flags (was_doubtful, debut) appear only when true. New keys may be added; clients should ignore unknown keys.
Error codes
All errors return a JSON body with error_code and detail. Rate limit errors also include retry_after.
{
"error_code": "RATE_LIMIT_EXCEEDED",
"detail": "Rate limit exceeded. Please wait before making more requests.",
"retry_after": 60
}
| HTTP | Error Code | Meaning | Retry? |
|---|---|---|---|
| 400 | INVALID_DATETIME | Bad datetime format | No — fix request |
| 400 | INVALID_ID_FORMAT | Malformed public ID | No — fix ID |
| 400 | UPDATED_SINCE_TOO_OLD | Lookback exceeds 48 hours | No — use offset pagination for full dataset |
| 400 | INVALID_CURSOR | Corrupted or tampered cursor | No — restart query without cursor |
| 400 | CURSOR_EXPIRED | Cursor older than 2 hours | No — restart query without cursor |
| 400 | INVALID_PARAMS | cursor + offset used together, or cursor without updated_since | No — fix request |
| 401 | MISSING_API_KEY | No API key provided | No — add header |
| 401 | INVALID_API_KEY | Key not recognized | No — check key |
| 403 | VERSION_ACCESS_DENIED | No v2 access on this key | No — contact us |
| 404 | ID_NOT_FOUND | Entity doesn't exist | No — verify ID |
| 405 | — | Wrong HTTP method | No — use GET |
| 429 | RATE_LIMIT_EXCEEDED | Too many requests | Yes — wait retry_after |
| 500 | INTERNAL_ERROR | Server error | Yes — retry 30s |
| 503 | SERVICE_UNAVAILABLE | Temporarily unavailable | Yes — retry 30s |
Response headers
Included on every response.
| Header | Description |
|---|---|
| X-Request-Id | Unique request identifier. Include in bug reports. |
| X-RateLimit-Limit | Max requests per minute for your tier. |
| X-RateLimit-Remaining | Requests remaining in current window. |
| X-RateLimit-Reset | Unix timestamp when the window resets. |
| Retry-After | Seconds to wait. Present on 429 responses only. |
Initial data sync
New integrations should follow this two-phase approach to build and maintain their local dataset:
# Phase 1: Full dataset download (one-time)
# Use offset pagination without updated_since
all_fixtures = []
offset = 0
sync_started_at = datetime.now(timezone.utc).isoformat()
while True:
resp = httpx.get(API_URL, headers=headers, timeout=30,
params={"limit": 100, "offset": offset})
page = resp.json()
all_fixtures.extend(page["data"])
if not page["meta"]["has_more"]:
break
offset += page["meta"]["limit"]
# Phase 2: Incremental updates (ongoing)
# Switch to updated_since + cursor
last_check = sync_started_at
while True:
params = {"limit": 100, "updated_since": last_check}
cursor = None
while True:
if cursor:
params["cursor"] = cursor
resp = httpx.get(API_URL, headers=headers, params=params, timeout=30)
data = resp.json()
for fixture in data["data"]:
upsert_fixture(fixture) # Your upsert logic
if not data["meta"]["has_more"]:
break
cursor = data["meta"]["next_cursor"]
last_check = datetime.now(timezone.utc).isoformat()
time.sleep(300) # Poll every 5 minutes
updated_since has a 48-hour lookback limit. Once you have the full dataset, switch to cursor-based incremental polling for all subsequent updates.
Cursor pagination
When polling for updates using updated_since, use cursor-based pagination instead of offset. Cursor pagination guarantees data consistency — you won't miss records or see duplicates, even when data changes between page requests.
How it works
Each response includes a next_cursor field in the meta object. Pass this value as the cursor query parameter in your next request to continue from exactly where you left off.
Example: multi-page fetch
# 1. First request — start with updated_since, no cursor
GET /v2/fixtures/updates?updated_since=2026-06-05T08:00:00Z&limit=50
# Response:
{
"data": [...50 fixtures...],
"meta": {
"next_cursor": "eyJ1Ijoi...abc.d4e5f6",
"has_more": true,
"total": null
}
}
# 2. Next page — pass the cursor from previous response
GET /v2/fixtures/updates?updated_since=2026-06-05T08:00:00Z&limit=50&cursor=eyJ1Ijoi...abc.d4e5f6
# 3. Last page — no more data
{
"data": [...12 fixtures...],
"meta": {
"next_cursor": null,
"has_more": false
}
}
• Cursors are opaque — do not parse, modify, or store them long-term.
• Cursors expire after 2 hours. If expired, restart your query without the cursor parameter.
•
cursor requires updated_since. Sending cursor alone returns 400.•
cursor and offset cannot be combined. Use offset only for full dataset browsing without updated_since.•
updated_since supports a maximum lookback of 48 hours.
Polling strategy
Use cursor-based polling with updated_since to efficiently fetch only changes since your last sync.
import httpx
import time
from datetime import datetime, timezone
API_URL = "https://api.leaguespy.com/v2/fixtures/updates"
headers = {"X-API-Key": "YOUR_KEY"}
last_check = datetime.now(timezone.utc).isoformat()
while True:
params = {"limit": 100, "updated_since": last_check}
cursor = None
while True: # Page through all results
if cursor:
params["cursor"] = cursor
resp = httpx.get(API_URL, headers=headers, params=params, timeout=30)
data = resp.json()
for fixture in data["data"]:
process_fixture(fixture)
if not data["meta"]["has_more"]:
break
cursor = data["meta"]["next_cursor"]
last_check = datetime.now(timezone.utc).isoformat()
time.sleep(300) # Poll every 5 minutes
Pagination
When meta.total exceeds your limit, increment offset to fetch remaining pages.
import httpx
API_URL = "https://api.leaguespy.com/v2/fixtures/updates"
headers = {"X-API-Key": "YOUR_KEY"}
all_fixtures = []
offset = 0
while True:
resp = httpx.get(API_URL, headers=headers, timeout=30,
params={"limit": 100, "offset": offset})
page = resp.json()
all_fixtures.extend(page["data"])
# Stop when we've fetched everything
if offset + page["meta"]["limit"] >= page["meta"]["total"]:
break
offset += page["meta"]["limit"]
Changelog
| Date | Version | Changes |
|---|---|---|
| 2026-10-27 | 2.4.0 | ?include=broadcasts: TV and streaming broadcasters of the fixture by country. Live clock on the fixture: period, minute, extra_minute. |
| 2026-10-21 | 2.3.0 | expected_return on missing[] players (Realtime): estimated return window for injured and suspended players. |
| 2026-10-19 | 2.2.0 | home_score and away_score. lineup_changes: changes in the starting XI against the team's previous match. English originals of all names in *_en on every request. detailed_position, position and reason are always English again; translations moved to *_label. |
| 2026-10-08 | 2.1.0 | New status field (postponed, cancelled, interrupted and other match states); status and kickoff changes update updated_at. Korean localization extended to positions and absence reasons. reason now always comes from a fixed list. Documentation of all response fields refreshed. |
| 2026-06-05 | 2.0.4 | Improved response consistency for fixtures with partial data. Updated API documentation. |
| 2026-01-08 | 2.0.2 | Research team expanded with analysts dedicated to squad rotation during congested schedules. |
| 2025-11-20 | 2.0.1 | Coverage expansion for lower-profile leagues. Improved data freshness for non-top-5 competitions. |
| 2025-09-10 | — | API response time reduced to <120ms (p95). Infrastructure migrated to edge-optimized deployment. |
| 2025-08-15 | — | Match-day squad detection (is_nomination_announced). Improved missing player categorization. |
| 2025-06-20 | — | Expanded filtering options: team_id, league_id and fixture_id query parameters. |
| 2025-03-01 | 2.0.0 | v2 GA release. Tier-based access, structured rate limiting, enriched entity names, updated_since polling. |
| 2024-11-15 | 2.0.0-beta | v2 beta. New response schema, confirmed lineup flow (is_confirmed), nomination tracking. |
| 2024-09-01 | 1.4.0 | Rate limiting rework. Added X-RateLimit-* response headers. Per-key tracking. |
| 2024-09-01 | — | Research team expanded across more time zones. Faster updates throughout the day. |
| 2024-08-15 | — | API infrastructure: gzip compression enabled, significantly reduced payload sizes. Health check endpoint added. |
| 2024-07-10 | 1.3.0 | Tier system introduced (Essential / Professional / Real-Time). Data freshness guarantees per tier. |
| 2024-05-01 | 1.2.0 | Start probability field added. Expected minutes for substitutes — designed for fantasy and DFS platforms. |
| 2024-05-01 | — | Prediction accuracy milestone: significant improvement in starting XI match rate across all covered leagues. |
| 2024-03-15 | 1.1.0 | Formation detection and bench predictions added to response schema. |
| 2024-03-15 | — | Missing player reason enrichment. Detailed categorization: injury type and suspension. |
| 2023-11-01 | 1.0.1 | Pagination support. Stabilized response schema. Added updated_at field. |
| 2023-11-01 | — | Third-tier league coverage: League One & Two (England), 3. Liga (Germany), National (France). |
| 2023-08-10 | — | Prediction accuracy improvements. Better handling of mid-season managerial changes and rotation patterns. |
| 2023-08-01 | 1.0.0 | v1 GA release. Public API with key authentication. 70 competitions covered. |
| 2023-02-01 | — | Second division expansion: Championship, 2. Bundesliga, Serie B, Ligue 2, Segunda División. 50 leagues total. |
| 2022-12-10 | — | API webhook support in private beta. Push-based notifications for lineup changes on selected fixtures. |
| 2022-10-20 | — | South America launch: Brasileirão Série A, Argentine Primera División, Copa Libertadores. |
| 2022-08-01 | — | Asian market entry: J1 League (Japan), K League 1 (South Korea), A-League (Australia). |
| 2022-04-15 | — | Research team expanded with dedicated lineup analysts for every covered league. |
| 2022-01-10 | — | Coverage expanded to 35 leagues. Added Eredivisie, Primeira Liga, Süper Lig, Belgian Pro League, and Scottish Premiership. |
| 2021-11-01 | — | API uptime reaches 99.95% SLA. Migrated to high-availability cloud infrastructure. |
| 2021-09-01 | — | Research team expanded with match preparation specialists. |
| 2021-06-15 | — | 5 additional leagues added. Total coverage: 25 competitions across 12 countries. |
| 2021-02-01 | — | JSON response format stabilized. API key authentication introduced. |
| 2020-10-15 | — | Research team expanded with squad specialists. Squad roles tracked for every covered team. |
| 2020-08-01 | — | Predicted bench added to lineup data. Expanded missing player reasons with detailed categories. |
| 2020-05-10 | — | Research team expanded to 40 football experts worldwide. Enhanced coverage depth for mid-table clubs. |
| 2020-02-01 | — | Improved injury and absence tracking. More detailed absence categories. |
| 2019-09-15 | — | Research team expanded. Absence impact assessed for every missing player. |
| 2019-06-01 | — | Coverage expanded to 25 leagues. Added MLS, Liga MX, Russian Premier League, and Swiss Super League. |
| 2019-01-10 | — | Research team scaled to 20 analysts. Improved coverage for lower-profile fixtures. |
| 2018-11-01 | — | API response caching introduced. Average response time dropped from 800ms to under 200ms. |
| 2018-08-15 | — | 10 additional leagues added: Eredivisie, Primeira Liga, Austrian Bundesliga, Danish Superliga, and more. |
| 2018-03-01 | — | Notable improvement in prediction accuracy across top 10 leagues after the research team grew. |
| 2017-11-01 | — | Domestic cup coverage added: FA Cup, Copa del Rey, DFB-Pokal, Coppa Italia, Coupe de France. |
| 2017-08-01 | — | Expanded to top 10 European leagues. Added Eredivisie, Primeira Liga, Russian Premier League, Turkish Süper Lig, Belgian Pro League. |
| 2017-02-15 | — | Dedicated research team formed for the top 5 leagues. |
| 2016-11-25 | — | LeagueSpy launched. Top 5 leagues: Premier League, La Liga, Serie A, Bundesliga, Ligue 1. Predicted starting XI. |