Fixtures and results
Upcoming matches, recent scores, a day's games, matchdays and tournament rounds, all from one endpoint.
Fixtures and results both come from /matches. You choose what you get with filters: a team, a competition, a date range, a status. This guide walks through the questions people ask most.
Every example sends your key in the X-Api-Key header. Keep that key on your server.
A team's next match
Ask for scheduled matches, soonest first, one per page:
curl "https://api.soccer-data.co/v1/matches?team_id=team_f0ibhxdw7hs5&status=scheduled&sort=utc_date&per_page=1" \
-H "X-Api-Key: YOUR_API_KEY"
{
"data": [
{
"id": "match_yoeml0e6ae37",
"competition_id": "competition_705uv6jm8myn",
"season_id": "season_hr1ie7yrsdmt",
"matchday": 6,
"status": "scheduled",
"utc_date": "2026-10-10T11:30:00.000Z",
"home_team": { "id": "team_f0ibhxdw7hs5", "name": "Arsenal" },
"away_team": { "id": "team_w63vzmngfyz9", "name": "Leeds United" },
"score": { "home": null, "away": null, "winner": null },
"odds_available": true,
"live_odds_available": false
}
],
"meta": { "page": 1, "per_page": 1, "total": 9, "total_pages": 9 }
}
Change per_page=1 to per_page=5 for the next five. meta.total tells you how many scheduled matches the team has in the data.
A team's latest results
Ask for finished matches and leave sort out. The default order already puts the most recent kickoff first.
curl "https://api.soccer-data.co/v1/matches?team_id=team_f0ibhxdw7hs5&status=finished&per_page=1" \
-H "X-Api-Key: YOUR_API_KEY"
{
"data": [
{
"id": "match_nbqbxh7kv0q8",
"status": "finished",
"utc_date": "2026-09-19T14:00:00.000Z",
"home_team": { "id": "team_v70dqyg1h8b0", "name": "Brighton & Hove Albion" },
"away_team": { "id": "team_f0ibhxdw7hs5", "name": "Arsenal" },
"score": {
"home": 3,
"away": 0,
"regulation": { "home": 3, "away": 0 },
"went_to_extra_time": false,
"went_to_penalties": false,
"winner": "home"
},
"xg_available": true,
"shotmap_available": true
}
],
"meta": { "page": 1, "per_page": 1, "total": 561, "total_pages": 561 }
}
For the venue, referee and half-time score of a single match, call /matches/{match_id}.
One day's matches, in your time zone
Set date_from and date_to to the same day. Add utc_offset when "the day" should mean your local day rather than the UTC one:
curl "https://api.soccer-data.co/v1/matches?competition_id=competition_705uv6jm8myn&date_from=2026-10-10&date_to=2026-10-10&utc_offset=%2B10:00&sort=utc_date" \
-H "X-Api-Key: YOUR_API_KEY"
The offset changes which matches fall inside the day. In UTC, 10 October 2026 has six Premier League matches. At +10:00, the local day runs from 14:00 UTC on 9 October to 14:00 UTC on 10 October, so only Arsenal v Leeds United (11:30 UTC) is included.
Warning In a URL, a bare
+is read as a space, and the request fails with400 BAD_REQUEST. Write+as%2B, as above, or build the query withURLSearchParamsor your HTTP library's params option. Negative offsets like-05:00need no encoding.
Kickoff times in the response stay in UTC either way. Convert them for display in your app.
A league matchday
curl "https://api.soccer-data.co/v1/matches?competition_id=competition_705uv6jm8myn&season_id=season_hr1ie7yrsdmt&matchday=6" \
-H "X-Api-Key: YOUR_API_KEY"
This returns the ten matches of Premier League matchday 6.
Tournament groups and knockouts
For a group in a tournament, pass group along with the competition and season. This returns the six Group A matches of the 2022 World Cup:
curl "https://api.soccer-data.co/v1/matches?competition_id=competition_7vpwx91c7j7h&season_id=season_st2tyewgtq2j&group=A&sort=utc_date" \
-H "X-Api-Key: YOUR_API_KEY"
Use stage to split a season into parts:
stage=playoff: knockout rounds and play-offs only (16 matches for the 2022 World Cup).stage=regular: league and group matches only.
/competitions/{competition_id}/seasons/{season_id}/groups lists the group labels a season has.
How far ahead fixtures go
Later rounds of a season aren't always in the data yet. To see how far it reaches, ask for the season's scheduled matches without a sort:
curl "https://api.soccer-data.co/v1/matches?competition_id=competition_705uv6jm8myn&season_id=season_hr1ie7yrsdmt&status=scheduled&per_page=1" \
-H "X-Api-Key: YOUR_API_KEY"
The first row is the furthest fixture we have, and meta.total is how many scheduled matches are loaded. Coverage gives the same picture for every season.
Getting every page
Lists come 20 to a page by default. To read everything, ask for per_page=100 and keep increasing page until it reaches meta.total_pages. Pagination has ready-made loops. Each page is one request, so filter as tightly as you can first.
Filters at a glance
| Parameter | What it does |
|---|---|
team_id |
Matches the team plays in, at home or away. |
competition_id, season_id |
One competition, one season. The season must belong to the competition. |
status |
scheduled, live, finished, postponed or cancelled. |
date_from, date_to |
Kickoff date range, YYYY-MM-DD, both ends included. There's no date parameter. |
utc_offset |
The time zone the dates are read in, such as -05:00. Defaults to UTC. |
sort |
-utc_date (latest first, the default) or utc_date (soonest first). |
matchday |
A league round. |
stage |
regular, playoff or all. |
group |
A tournament group, such as A. Needs competition_id. |
page, per_page |
Paging. 20 per page by default, 100 at most. |
The /matches reference has the full details.
Reading the score
score.homeandscore.awayare the goals scored in normal time. They'renullbefore kickoff.score.winnerishome,awayordrawonce the match is over, and takes extra time and penalties into account.score.regulationrepeats the normal-time score;went_to_extra_timeandwent_to_penaltiessay how far the match went.score.after_extra_timeandscore.penalty_shootoutonly appear when a match got that far.
Good to know
utc_dateis always UTC.- Matches that kick off at the same moment always come back in the same order, so paging through them is stable.
- Every request counts against your limits, including each page. Cache what doesn't need to be fresh, such as finished results.
Common mistakes
- Leaving out
sort=utc_datewhen you want the next match. You get the match furthest in the future instead. - A bare
+inutc_offset. Encode it as%2B. - Sending
date. It returns400 UNKNOWN_PARAMETER. The message suggests the closest valid parameter and lists the ones the endpoint takes,date_fromanddate_toamong them. - Sending
groupwithoutcompetition_id, orper_pageabove 100. Both return400. - Assuming the whole season is loaded. Check how far fixtures go before you promise them to users.
Related endpoints
# Fixtures and results
Upcoming matches, recent scores, a day's games, matchdays and tournament rounds, all from one endpoint.
Fixtures and results both come from [`/matches`](/docs/reference/matches/list). You choose what you get with filters: a team, a competition, a date range, a status. This guide walks through the questions people ask most.
Every example sends your key in the `X-Api-Key` header. Keep that key on your server.
## A team's next match
Ask for scheduled matches, soonest first, one per page:
```bash
curl "https://api.soccer-data.co/v1/matches?team_id=team_f0ibhxdw7hs5&status=scheduled&sort=utc_date&per_page=1" \
-H "X-Api-Key: YOUR_API_KEY"
```
```json
{
"data": [
{
"id": "match_yoeml0e6ae37",
"competition_id": "competition_705uv6jm8myn",
"season_id": "season_hr1ie7yrsdmt",
"matchday": 6,
"status": "scheduled",
"utc_date": "2026-10-10T11:30:00.000Z",
"home_team": { "id": "team_f0ibhxdw7hs5", "name": "Arsenal" },
"away_team": { "id": "team_w63vzmngfyz9", "name": "Leeds United" },
"score": { "home": null, "away": null, "winner": null },
"odds_available": true,
"live_odds_available": false
}
],
"meta": { "page": 1, "per_page": 1, "total": 9, "total_pages": 9 }
}
```
Change `per_page=1` to `per_page=5` for the next five. `meta.total` tells you how many scheduled matches the team has in the data.
## A team's latest results
Ask for finished matches and leave `sort` out. The default order already puts the most recent kickoff first.
```bash
curl "https://api.soccer-data.co/v1/matches?team_id=team_f0ibhxdw7hs5&status=finished&per_page=1" \
-H "X-Api-Key: YOUR_API_KEY"
```
```json
{
"data": [
{
"id": "match_nbqbxh7kv0q8",
"status": "finished",
"utc_date": "2026-09-19T14:00:00.000Z",
"home_team": { "id": "team_v70dqyg1h8b0", "name": "Brighton & Hove Albion" },
"away_team": { "id": "team_f0ibhxdw7hs5", "name": "Arsenal" },
"score": {
"home": 3,
"away": 0,
"regulation": { "home": 3, "away": 0 },
"went_to_extra_time": false,
"went_to_penalties": false,
"winner": "home"
},
"xg_available": true,
"shotmap_available": true
}
],
"meta": { "page": 1, "per_page": 1, "total": 561, "total_pages": 561 }
}
```
For the venue, referee and half-time score of a single match, call [`/matches/{match_id}`](/docs/reference/matches/show).
## One day's matches, in your time zone
Set `date_from` and `date_to` to the same day. Add `utc_offset` when "the day" should mean your local day rather than the UTC one:
```bash
curl "https://api.soccer-data.co/v1/matches?competition_id=competition_705uv6jm8myn&date_from=2026-10-10&date_to=2026-10-10&utc_offset=%2B10:00&sort=utc_date" \
-H "X-Api-Key: YOUR_API_KEY"
```
The offset changes which matches fall inside the day. In UTC, 10 October 2026 has six Premier League matches. At `+10:00`, the local day runs from 14:00 UTC on 9 October to 14:00 UTC on 10 October, so only Arsenal v Leeds United (11:30 UTC) is included.
> **Warning:** In a URL, a bare `+` is read as a space, and the request fails with `400 BAD_REQUEST`. Write `+` as `%2B`, as above, or build the query with `URLSearchParams` or your HTTP library's params option. Negative offsets like `-05:00` need no encoding.
Kickoff times in the response stay in UTC either way. Convert them for display in your app.
## A league matchday
```bash
curl "https://api.soccer-data.co/v1/matches?competition_id=competition_705uv6jm8myn&season_id=season_hr1ie7yrsdmt&matchday=6" \
-H "X-Api-Key: YOUR_API_KEY"
```
This returns the ten matches of Premier League matchday 6.
## Tournament groups and knockouts
For a group in a tournament, pass `group` along with the competition and season. This returns the six Group A matches of the 2022 World Cup:
```bash
curl "https://api.soccer-data.co/v1/matches?competition_id=competition_7vpwx91c7j7h&season_id=season_st2tyewgtq2j&group=A&sort=utc_date" \
-H "X-Api-Key: YOUR_API_KEY"
```
Use `stage` to split a season into parts:
- `stage=playoff`: knockout rounds and play-offs only (16 matches for the 2022 World Cup).
- `stage=regular`: league and group matches only.
[`/competitions/{competition_id}/seasons/{season_id}/groups`](/docs/reference/competitions/groups) lists the group labels a season has.
## How far ahead fixtures go
Later rounds of a season aren't always in the data yet. To see how far it reaches, ask for the season's scheduled matches without a `sort`:
```bash
curl "https://api.soccer-data.co/v1/matches?competition_id=competition_705uv6jm8myn&season_id=season_hr1ie7yrsdmt&status=scheduled&per_page=1" \
-H "X-Api-Key: YOUR_API_KEY"
```
The first row is the furthest fixture we have, and `meta.total` is how many scheduled matches are loaded. [Coverage](/docs/concepts/coverage) gives the same picture for every season.
## Getting every page
Lists come 20 to a page by default. To read everything, ask for `per_page=100` and keep increasing `page` until it reaches `meta.total_pages`. [Pagination](/docs/concepts/pagination) has ready-made loops. Each page is one request, so filter as tightly as you can first.
## Filters at a glance
| Parameter | What it does |
|---|---|
| `team_id` | Matches the team plays in, at home or away. |
| `competition_id`, `season_id` | One competition, one season. The season must belong to the competition. |
| `status` | `scheduled`, `live`, `finished`, `postponed` or `cancelled`. |
| `date_from`, `date_to` | Kickoff date range, `YYYY-MM-DD`, both ends included. There's no `date` parameter. |
| `utc_offset` | The time zone the dates are read in, such as `-05:00`. Defaults to UTC. |
| `sort` | `-utc_date` (latest first, the default) or `utc_date` (soonest first). |
| `matchday` | A league round. |
| `stage` | `regular`, `playoff` or `all`. |
| `group` | A tournament group, such as `A`. Needs `competition_id`. |
| `page`, `per_page` | Paging. 20 per page by default, 100 at most. |
The [`/matches` reference](/docs/reference/matches/list) has the full details.
## Reading the score
- `score.home` and `score.away` are the goals scored in normal time. They're `null` before kickoff.
- `score.winner` is `home`, `away` or `draw` once the match is over, and takes extra time and penalties into account.
- `score.regulation` repeats the normal-time score; `went_to_extra_time` and `went_to_penalties` say how far the match went.
- `score.after_extra_time` and `score.penalty_shootout` only appear when a match got that far.
## Good to know
- `utc_date` is always UTC.
- Matches that kick off at the same moment always come back in the same order, so paging through them is stable.
- Every request counts against your limits, including each page. Cache what doesn't need to be fresh, such as finished results.
## Common mistakes
- **Leaving out `sort=utc_date` when you want the next match.** You get the match furthest in the future instead.
- **A bare `+` in `utc_offset`.** Encode it as `%2B`.
- **Sending `date`.** It returns `400 UNKNOWN_PARAMETER`. The message suggests the closest valid parameter and lists the ones the endpoint takes, `date_from` and `date_to` among them.
- **Sending `group` without `competition_id`, or `per_page` above 100.** Both return `400`.
- **Assuming the whole season is loaded.** Check how far fixtures go before you promise them to users.
## Related endpoints
- [List matches](/docs/reference/matches/list)
- [Get a match](/docs/reference/matches/show)
- [List groups in a season](/docs/reference/competitions/groups)
- [Coverage by competition](/docs/reference/coverage/league)