The free key reads yesterday again: our one-month trial of today on the free key has finished. Read the changelog

Changelog

Every change, dated. v1 only ever gains fields.

The promise

Within v1 we only ever add fields. Adding one is routine and needs nothing from you. Removing or renaming one is a changelog event with a deprecation window, announced before it happens and never on the day.

Ids we issue are stable. What you store today still resolves later.

Entries

30 October 2026 · Measured xG back to 2014/15 in six top divisions

From the nightly rebuild of 30 October, the Premier League, LaLiga, the Bundesliga, Serie A, Ligue 1 and the Russian Premier League carry measured expected goals (home_xg, away_xg) for every season from 2014/15, not only from 2022. 18,179 matches gain measured xG they did not have; matches that already held it keep their figures. A match whose result could not be confirmed against ours is left without, rather than given figures that may belong to another match.

Nothing has been removed or renamed in any response.

30 October 2026 · Duplicate matches removed from the archive

From the nightly rebuild of 30 October, a match the archive held twice, a day or two apart with the same clubs and score, is held once. The 1999 Premier League showed every Sheffield Wednesday game twice, 418 matches in a 380-match season; it now holds 380, on their correct dates. Other seasons with the same fault, such as English League One and League Two of 1998, are corrected the same way.

Also corrected: in Ligue 1 from 1993 to 1997, and Ligue 2 in 1998, the matches of Cannes were filed under a second Bastia. They now belong to Cannes, so both clubs' records and the tables for those seasons are right.

Nothing has been removed or renamed in any response.

29 October 2026 · Every match says why it has no statistics

From the nightly rebuild of 30 October, every played match carries statistics_status and, where team statistics are not held, statistics_reason in plain words: still being gathered (played in the last three days), none published for that match, none published by that competition for that season, not gathered yet, or not played (awarded or a walkover). A match with statistics reads held. A gap is never left for you to guess at.

Also corrected on 29 October: 114 matches carried a half-time score but no final score. The half-time score was cleared rather than left standing on its own, and a half-time score above the final score can no longer stand.

Nothing has been removed or renamed in any response.

29 October 2026 · Our own club and player rankings

New on the Live & Archive plan: our own rankings of club football, worked out every night over the last twelve months. /v1/rankings/clubs ranks about 8,000 clubs and /v1/rankings/players about 16,000 players, best first, each with a score out of 100, by country, competition, club or, for players, role. /v1/teams/{id}/ranking and /v1/players/{id}/ranking give one club's or one player's place and how it moved week by week. National-team matches are left out. The existing /v1/rankings, by rating from results alone, is unchanged. The top 50 clubs and players, by country and by role, are free to read on the new Rankings page, and every ranked club and player has a page of its own there, with its rank week by week and the clubs or players around it.

Nothing has been removed or renamed in any response.

29 October 2026 · Closing prices for 14 more countries

11,087 more matches now carry a closing price for the home win, the draw and the away win, in the top divisions of Argentina, Austria, Brazil, China, Denmark, Finland, Japan, Mexico, Norway, Romania, Russia, Sweden, Switzerland and the USA, from 2012 on. They are in the same kickoff price fields as every other priced match, so the odds endpoints, /v1/backtest and /v1/upsets now read them too. Some of those matches also gained their referee.

Nothing has been removed or renamed in any response.

29 October 2026 · Live scores from our own collection

In /v1/live, the score of most matches in play, about seven in ten, now comes from our own collection. Tested over a full evening of matches, it showed each goal at the same moment as before at the median, nine in ten within a minute, and the same score 96.5% of the time. For those matches the minute now comes from our own collection too, and a match that kicks off is listed as in play, with match.started, as soon as we see it start. The other matches carry on as before. Since 28 October, 209 matches that had finished have left the feed as soon as the result was in, rather than staying listed as in play.

Nothing has been removed or renamed in any response.

28 October 2026 · Upsets, with the reasons

New on the Live & Archive plan: /v1/upsets, the results nobody expected, each with the reasons in plain words: the chance the winner had before kickoff, the rating gap between the two sides and the gap in the table. Judged on the score after 90 minutes. With an exchange price at kickoff, an upset is a win by a side with a 30% chance or less, or a draw against a favourite with 70% or more; with no price, it is judged by our team ratings before kickoff. upset_size runs from 0 to 100, how far under the 30% line it fell.

The latest seven days by default, newest first. Give date, or date_from and date_to (up to 92 days), narrow it by competition, country or club, set min_size, and sort=size puts the biggest first. A match whose score is still in question is left out until it is settled.

28 October 2026 · Archive corrections, and finished matches leave the live feed

A full check of the archive corrected these, and every nightly rebuild now applies the same checks:

  • 478 matches where the extra-time goals had been counted twice in the final score;
  • 3,805 matches held twice, a day apart or under a second spelling of a club, now held once;
  • 69 matches filed in two competitions, now in the right one only;
  • 48 rows with the same club on both sides, removed;
  • 43 matches shown 0-0 before any score was known, 7 settled matches with no score, and 19 penalty shootouts with no shootout score, now filled;
  • 66,965 more matches with a half-time score, from goalless matches and from goal times.

In /v1/live, a match that has finished now leaves the feed with its final score and sends match.finished as soon as the result is in, where before it could stay listed as in play long after the final whistle.

Nothing has been removed or renamed in any response.

22 October 2026 · Step 4 this season, and the early rounds of the FA Cup

The eight Step 4 divisions now carry on into 2026/27, every match so far and each new one the morning after: Non League Div One - Northern East, Northern West and Northern Midlands, Southern South and Southern Central, and Isthmian North, Isthmian South Central and Isthmian South East. They are the same competitions, with the same ids, as their earlier seasons. That is 1,072 matches so far this season, and they come whole: the score and half-time score, the referee, the crowd and the ground, every goal with its scorer and every sending-off, both line-ups with shirt numbers, and every substitution, so minutes played add up for them as for any other match. Every competition we hold is listed on Leagues we cover.

The FA Cup and the FA Trophy now hold more of their early qualifying ties: 262 more this season, in the same competitions as the rounds already there. Most of the early ties carry the result alone.

Across all competitions, more matches now carry team statistics, line-ups, half-time scores and xG where they had none. Each side's statistics in /v1/matches/{id}/statistics may now also hold shots_off_target, shots_blocked, shots_inside_box, passes_accurate_pct, big_chances, crosses, tackles, interceptions, clearances, duels_won, free_kicks, throw_ins, goal_kicks, hit_woodwork, xg_on_target and expected_assists where they are known. Nothing has been removed or renamed.

21 October 2026 · Substitutions, and minutes played

/v1/matches/{id}/lineups now carries substitutions, every change in match order with its minute, player_off and player_on, and appearances, every player who took part with minute_on, minute_off and minutes_played. This reaches competitions that publish no player figures, the National League among them, so who took part and for how long can now be told for them too. Held for every National League match from 2023/24 and filled for other competitions from 2025/26 on.

20 October 2026 · Every part of the score, and prices settled on 90 minutes

Every played match now carries the score of each part on its own: regular_time_home_goals and regular_time_away_goals with regular_time_result, extra_time_home_goals and extra_time_away_goals, and shootout_home_goals and shootout_away_goals, filled for the past as well. home_goals, away_goals and full_time_result are unchanged: the final score, after extra time where played.

The odds endpoints, /v1/backtest and a club's market figures now settle on regular_time_result, as the exchange does, and no longer settle awarded matches or walkovers. Results on matches that went to extra time may change in those answers. Shootout kicks are no longer listed as goals in a match's events. Scores and results sets out every field and status.

20 October 2026 · Keys: two headers, never the address

A key is sent as X-API-Key or as Authorization: Bearer; both are read the same way. A key in the address (?key= or ?api_key=) is now refused with 400 key_in_address, since addresses end up in logs and browser history. If you were passing the key in the address, move it into either header.

The key you are given at sign-up, and any key you make or rotate in your account, is now already in the Try it box on every endpoint page, kept in your browser only.

20 October 2026 · The free key reads yesterday again: the trial has finished

On 23 September we opened today and the fixtures ahead to the free key, as a trial for one month. That trial has now finished, and the free key goes back to reading yesterday, as one whole UTC day, across every league, at 50 calls a day.

What moves to Live: today’s card and today’s results (/v1/fixtures/today, /v1/results/today), the fixtures ahead (/v1/fixtures/upcoming) and, as before, the in-play feed. Everything before yesterday stays on Archive.

What it means for your code: no field has been removed or renamed. /v1/results/yesterday is the free key’s main call. On a free key, /v1/matches and /v1/results/latest answer with yesterday’s matches only. A date from today on is refused with 403 outside_plan_window, which states the window and names Live, and the three endpoints above answer 403 plan_required, naming Live. Every free response still carries meta.free_key, now with from and until both set to yesterday’s date.

Paid keys are not affected. Existing free keys keep working and need nothing from you.

7 October 2026 · National teams from 1872, daylight and public holidays

The archive now holds every men’s full international from 1872 up to where its own national-team matches begin in July 2012: 36,035 matches, with scorers on about 10,000 and the winner of every penalty shoot-out. A national team keeps one id across its whole history, so /v1/teams/{id}/matches runs from its first international to its last. A side that played under a former name keeps that name on the match and its successor’s id. Kickoff times before 2012 are not known, so those matches carry the date only. Seasons from 1872 are accepted wherever a season is asked for.

Three fields are new on every match. daylight_minutes is the length of that day at that ground and sun_elevation_deg is how high the sun stood at kickoff, in degrees: below 0 the sun had set, below -6 it was dark. Both are worked out from the location and the kickoff time, wherever the match has both. public_holiday names the public holiday the match fell on in its competition’s country, for 26 countries, and is null on any other day. It covers the nationwide holidays that recur by rule, not regional ones or one-off days.

The weather at kickoff: kickoff_temperature_c (degrees at 2 m), kickoff_rain_mm (rain in that hour) and kickoff_wind_ms (wind at 10 m, metres a second), for the hour nearest kickoff at the ground’s location, on matches from 2001 with a location. They describe the area around the ground, about 50 km across, not the pitch itself, and are null where a match has no location yet or the hour is not yet in.

attendance is the crowd at the match, where one was reported: from July 2012, for the competitions that publish one, filled from the latest seasons back. It is null where no crowd was given, and for matches played behind closed doors, never a 0 standing in for unknown.

Player seasons now count 0 goals and 0 assists for a player who played and did not score, where they were empty before, and carry rates per 90 minutes (goals_per_90, assists_per_90, shots_per_90, key_passes_per_90, tackles_per_90, interceptions_per_90) with duels_won_pct and shot_accuracy_pct.

What it means for your code: nothing. No field was removed or renamed.

7 October 2026 · Players, absences, and where each match was played

/v1/players/{id} returns every season of one player, one row a competition, season and club, with a career total. /v1/leagues/{id}/seasons/{season}/players ranks a whole competition-season by goals, assists, minutes, rating and nine more, with min_minutes to leave out players who barely featured.

/v1/matches/{id}/absences lists the players out or doubtful before a match, injured or suspended, from 2021 in every competition that publishes them.

Two fields are new on every match. location_precision says what latitude and longitude point at: ground for the stadium itself, city where the ground could not be placed and the city is used instead, and null where there is no location. Far more matches now carry a location than before. half_time_source says where the half-time score came from: feed as reported, or events where it was worked out from the goals, only when the goals add up to the final score. Checked against matches carrying both, the two agreed 99.67% of the time.

What it means for your code: nothing. No field was removed or renamed.

23 September 2026 · The free key now reads the recent days

The free key now reads yesterday, today and the fixtures ahead, across every league, at 50 calls a day. Until today it read the whole archive on a delay, at 500 calls a day. Today now comes through with no delay at all, as matches settle, which the old key never had.

Why: that allowance was enough to run a product on without paying, which is not what a free key is for. A free key is for building and testing. It should show every field and every shape on real, current matches, and the recent days do that.

What moves to the paid plans: anything before yesterday is Archive. The prices on the free key’s own days, and the in-play feed, come with Archive and Live.

What it means for your code: no field has been removed or renamed. On a free key the price fields (best_odds, the kickoff and half-time prices, matched volume, overround and the Betfair ids) come back as null, each with a note in held_back naming the plan that carries it. Every free response carries meta.free_key, stating what it reaches, the allowance and when it resets. A date wholly before the window is refused with 403 outside_plan_window, which states the window, rather than answered with an empty list that reads as no football that day.

/v1/results/yesterday is new, on every plan: yesterday as a whole UTC day, never sharing a match with today’s results.

Existing keys keep working and need nothing from you. They see the new window from today.

8 September 2026 · Grounds, with capacity and surface

/v1/grounds lists every ground we hold detail for, with its city, capacity, playing surface, and how many matches in the archive were played there. /v1/matches takes surface and venue_id, so “finished matches on artificial turf” is now one request.

A match links to a ground through venue_id, matched on the ground’s own id rather than its name: names agreed barely a third of the time, ids agree all of it. Surface lives on the ground, not copied onto every match played there, so a stadium that resurfaces is corrected in one place.

8 September 2026 · Lineups and formations

/v1/matches/{id}/lineups returns the formation, the starting eleven with shirt numbers and grid positions, the substitutes and the coach for each side. Grid positions are row and column counting out from the goalkeeper, so a shape can be drawn without guessing.

home_formation and away_formation also come back on the match itself, which is the field to filter and group by.

8 September 2026 · Distance between two clubs

/v1/teams/{id}/distance/{opponent_id} gives the distance between two grounds as the crow flies, in kilometres and miles. The same measure as away_travel_km on a match, so a distance looked up here and one read off a fixture agree.

It answers before a fixture exists, which is the point: weighing a cup draw or planning a season means asking about a game that has not been arranged yet.

8 September 2026 · Travel distances corrected

A club’s ground coordinates were being read from its most recent home fixture, and fixtures added since the original archive carry no coordinates. Clubs that had played recently were quietly losing coordinates they already had, and the travel distance with them.

Fixed, and away_travel_km went from 69.2% of the archive to 81.7%: about 85,000 matches that should always have had it. If you cached travel distances, they are worth refetching.

8 September 2026 · Several matches in one call

/v1/matches takes an ids parameter: up to fifty match ids in one request, separated by a dash. Every other filter still applies, so a set can be narrowed further.

An id that is not valid is refused rather than skipped. A response that quietly drops one looks complete and is not, and that is a bug you would find in production rather than in development.

8 September 2026 · Match statistics

Shots, shots on target, possession, corners, fouls, offsides, cards, passes and expected goals, per team per match. On the match itself and on its own endpoint for when they are all you want.

Gathered while a match is in play and settled once it finishes, so a game still running may carry a partial set. Field names follow the same convention as everything else: lower case, whole words, and a percentage says _pct.

6 September 2026 · Documentation published

Full reference for every endpoint, with parameters and live sample responses pulled from the archive itself. Guides added for authentication, pagination, rate limits, errors, timezones and historical data.

6 September 2026 · Archive rebuilt

The match archive was restructured into a public schema: lowercase whole-word field names, proper types, and a coverage table recording the fill rate of every optional field per competition and season. Cancelled and postponed fixtures no longer report a 0–0 scoreline: goals are now null unless the match was played.

5 September 2026 · Accounts and free keys

Google sign-in, API key issue and rotation, and an account page showing usage against plan limits.

5 September 2026 · Pricing published

Two paid plans with the limits printed. Card payments open shortly.

Following along

This page is the record. Subscription by email and RSS is coming with the first release that changes a field.