SofaScore API endpoint
Returns the knockout tree(s) of a cup or playoff competition season: every round with its ties, each tie's participants (team or player, seed, winner flag, the earlier tie it advanced from), result and score strings (a shoot-out is appended, such as `1 (4)`), match ids and start time, plus the final and third-place tie. Tennis competitions return two trees (main draw and qualifying). League seasons have no tree and answer 404, as does a season id that does not belong to the competition. Get `id` from search or tournaments-with-feature and `season` from tournament-seasons; pass the returned `event_ids` to the event endpoints.
/sofascore/tournament-cuptreeQuery parameters:
id: required. Numeric SofaScore unique-tournament (competition) id of a cup or playoff competition, e.g. 7 for the UEFA Champions League, 19 for the FA Cup, 16 for the FIFA World Cup, 132 for the NBA, 234 for the NHL. Find competitions with sofascore/tournaments-with-feature (feature=cuptree) or sofascore/search-typed.season: required. Numeric SofaScore season id from sofascore/tournament-seasons, e.g. 76953 for the 2025/26 Champions League.Notable response behavior:
trees holds one tree for most competitions. Tennis competitions return two: the main draw and, when it exists, the qualifying draw (named ... Qualifying).description (for example Quarterfinal), order and round_type, the upstream round code: the number of ties for the standard knockout rounds (8 round of 16, 4 quarterfinals, 2 semifinals, 1 final), and other codes such as 0 (playoff round), 101 to 105 (named rounds) and 201, 202 (qualification rounds). current_round is the order of the round in play.matches is the scheduled length of the tie (1 single match, 2 two-legged tie, 7 best-of-seven series, 0 bye), so a series that ended 4:2 still shows 7. result is the tie result as SofaScore publishes it (4:5 aggregate or series score, or a text such as Retired), and home_score and away_score are the scores of the participants with order 1 and 2. They are strings because a shoot-out is appended (1 (4)). finished, in_progress and each participant's winner show the state; both winner flags are false until a tie is decided.matches 0 and no result. A participant's source_block_id is the block_id of the earlier tie it advanced from, so the tree can be rebuilt; first-round participants have none. seed carries the draw seed or entry label (WC for a wild card) when published. In individual sports participants[].team is the player; a not-yet-decided slot appears as a placeholder name such as WSF1.event_ids are the match ids of the tie; fetch each with sofascore/event. series_start_time is the first match's start (UTC). Some blocks carry a venue (for example World Cup knockout ties).final_match repeats the final tie from the last round and is omitted when the tree has no final yet; third_place_match is present when the competition plays one (the FIFA World Cup).Example response (shortened):
{
"code": 200,
"msg": "OK",
"data": {
"tournament_id": 7,
"season_id": 76953,
"count": 1,
"source_url": "https://api.sofascore.com/api/v1/unique-tournament/7/season/76953/cuptrees",
"fetched_at": "2026-10-07T14:00:00Z",
"trees": [
{
"id": 10850333,
"name": "UEFA Champions League 25/26, Knockout stage",
"tournament_name": "UEFA Champions League, Knockout stage",
"current_round": 5,
"rounds": [
{
"id": 228056,
"order": 5,
"description": "Final",
"round_type": 1,
"blocks": [
{
"id": 2947007,
"block_id": 2536394,
"order": 1,
"finished": true,
"in_progress": false,
"matches": 1,
"result": "1:1",
"home_score": "1 (4)",
"away_score": "1 (3)",
"participants": [
{ "team": { "id": 1644, "name": "Paris Saint-Germain", "short_name": "PSG", "slug": "paris-saint-germain" }, "order": 1, "winner": true, "source_block_id": 2536390 },
{ "team": { "id": 42, "name": "Arsenal", "short_name": "Arsenal", "slug": "arsenal" }, "order": 2, "winner": false, "source_block_id": 2536392 }
],
"event_ids": [15632636],
"series_start_timestamp": 1780156800,
"series_start_time": "2026-05-30T16:00:00Z"
}
]
}
]
}
]
}
}
| Field | Filled in, of 1 checked | Values in the sample |
|---|---|---|
| id | 1 | |
| name | 1 | “UEFA Champions League 25/26, Knockout stage” |
| tournament_name | 1 | “UEFA Champions League, Knockout stage” |
| current_round | 1 | 5 |
| rounds | 1 | median 5 entries |
| final_match | 1 |
| Parameter | Type | Required | Default | Description | Example |
|---|---|---|---|---|---|
| id | string | Yes | Numeric SofaScore unique-tournament (competition) id of a cup or playoff competition | 7 | |
| season | string | Yes | Numeric SofaScore season id | 76953 | |
| x-api-key (header) | string | Yes | API key required |
curl -X GET "https://api.crawlora.net/api/v1/sofascore/tournament-cuptree?id=7&season=76953" \ -H "x-api-key: $CRAWLORA_API_KEY"
{
"code": 200,
"msg": "OK",
"data": {
"tournament_id": 7,
"season_id": 76953,
"count": 1,
"source_url": "https://api.sofascore.com/api/v1/unique-tournament/7/season/76953/cuptrees",
"fetched_at": "2026-10-07T14:00:00Z",
"trees": [
{
"id": 10850333,
"name": "UEFA Champions League 25/26, Knockout stage",
"tournament_name": "UEFA Champions League, Knockout stage",
"current_round": 5,
"rounds": [
{
"id": 228056,
"order": 5,
"description": "Final",
"round_type": 1,
"blocks": [
{
"id": 2947007,
"block_id": 2536394,
"order": 1,
"finished": true,
"in_progress": false,
"matches": 1,
"result": "1:1",
"home_score": "1 (4)",
"away_score": "1 (3)",
"participants": [
{
"team": {
"id": 1644,
"name": "Paris Saint-Germain",
"short_name": "PSG",
"slug": "paris-saint-germain"
},
"order": 1,
"winner": true,
"source_block_id": 2536390
},
{
"team": {
"id": 42,
"name": "Arsenal",
"short_name": "Arsenal",
"slug": "arsenal"
},
"order": 2,
"winner": false,
"source_block_id": 2536392
}
],
"event_ids": [
15632636
],
"series_start_timestamp": 1780156800,
"series_start_time": "2026-05-30T16:00:00Z"
}
]
}
]
}
]
}
}Request schema
No body schema
Response schema
#/definitions/sofascore.tournamentCupTreeResponseDoc
| Field | Type | Required | Enum | Bounds | Example | Description |
|---|---|---|---|---|---|---|
| code | integer | No | 200 | |||
| data | sofascore.TournamentCupTreeResponse | No | ||||
| data.count | integer | No | ||||
| data.fetched_at | string | No | ||||
| data.season_id | integer | No | ||||
| data.source_url | string | No | ||||
| data.tournament_id | integer | No | ||||
| data.trees | array | No | ||||
| data.trees[].current_round | integer | No | 5 | |||
| data.trees[].final_match | object | No | FinalMatch is the final tie, repeated from the last round. It is omitted when the tree has no final yet (a qualifying tree). | |||
| data.trees[].final_match.away_score | string | No | 1 (3) | |||
| data.trees[].final_match.block_id | integer | No | 2536336 | BlockID is the identifier later blocks cite as source_block_id. | ||
| data.trees[].final_match.event_ids | array | No | EventIDs are the match ids of the tie; fetch each with the event endpoint. | |||
| data.trees[].final_match.finished | boolean | No | ||||
| data.trees[].final_match.home_score | string | No | 1 (4) | HomeScore and AwayScore are the scores of the participants with order 1 and 2. They are strings because a shoot-out is appended ("1 (4)"). | ||
| data.trees[].final_match.id | integer | No | 2946978 | |||
| data.trees[].final_match.in_progress | boolean | No | InProgress is true while a match of the tie is being played. | |||
| data.trees[].final_match.matches | integer | No | 2 | Matches is the scheduled length of the tie: 1 for a single match, 2 for a two-legged tie, 7 for a best-of-seven series (whether or not all seven were needed), 0 for a bye. | ||
| data.trees[].final_match.order | integer | No | 2 | |||
| data.trees[].final_match.participants | array | No | ||||
| data.trees[].final_match.participants[].order | integer | No | 1 | Order is the side's position in the block; the block's home_score belongs to order 1 and away_score to order 2. | ||
| data.trees[].final_match.participants[].seed | string | No | WC | Seed is the draw seed or entry label ("1", "WC" for a wild card), when published. | ||
| data.trees[].final_match.participants[].source_block_id | integer | No | SourceBlockID is the block_id of the earlier block this side advanced from. | |||
| data.trees[].final_match.participants[].team | sofascore.TeamRef | No | TeamRef record, 6 fields: country, id, name, national, short_name, slug. Described under SofaScore venue API. | |||
| data.trees[].final_match.participants[].winner | boolean | No | ||||
| data.trees[].final_match.result | string | No | 4:5 | Result is the tie result as published ("4:5", or a text such as "Retired"). | ||
| data.trees[].final_match.series_start_time | string | No | 2026-02-17T20:00:00Z | |||
| data.trees[].final_match.series_start_timestamp | integer | No | ||||
| data.trees[].final_match.venue | sofascore.Venue | No | ||||
| data.trees[].final_match.venue.capacity | integer | No | 61276 | Venue capacity. | ||
| data.trees[].final_match.venue.city | string | No | Liverpool | City the venue is in. | ||
| data.trees[].final_match.venue.country | string | No | England | Country the venue is in. | ||
| data.trees[].final_match.venue.name | string | No | Anfield | Venue name. | ||
| data.trees[].id | integer | No | 10850333 | |||
| data.trees[].name | string | No | UEFA Champions League 25/26, Knockout stage | |||
| data.trees[].rounds | array | No | ||||
| data.trees[].rounds[].blocks | array | No | ||||
| data.trees[].rounds[].blocks[].away_score | string | No | 1 (3) | |||
| data.trees[].rounds[].blocks[].block_id | integer | No | 2536336 | BlockID is the identifier later blocks cite as source_block_id. | ||
| data.trees[].rounds[].blocks[].event_ids | array | No | EventIDs are the match ids of the tie; fetch each with the event endpoint. | |||
| data.trees[].rounds[].blocks[].finished | boolean | No | ||||
| data.trees[].rounds[].blocks[].home_score | string | No | 1 (4) | HomeScore and AwayScore are the scores of the participants with order 1 and 2. They are strings because a shoot-out is appended ("1 (4)"). | ||
| data.trees[].rounds[].blocks[].id | integer | No | 2946978 | |||
| data.trees[].rounds[].blocks[].in_progress | boolean | No | InProgress is true while a match of the tie is being played. | |||
| data.trees[].rounds[].blocks[].matches | integer | No | 2 | Matches is the scheduled length of the tie: 1 for a single match, 2 for a two-legged tie, 7 for a best-of-seven series (whether or not all seven were needed), 0 for a bye. | ||
| data.trees[].rounds[].blocks[].order | integer | No | 2 | |||
| data.trees[].rounds[].blocks[].participants | array | No | ||||
| data.trees[].rounds[].blocks[].participants[].order | integer | No | 1 | Order is the side's position in the block; the block's home_score belongs to order 1 and away_score to order 2. | ||
| data.trees[].rounds[].blocks[].participants[].seed | string | No | WC | Seed is the draw seed or entry label ("1", "WC" for a wild card), when published. | ||
| data.trees[].rounds[].blocks[].participants[].source_block_id | integer | No | SourceBlockID is the block_id of the earlier block this side advanced from. | |||
| data.trees[].rounds[].blocks[].participants[].team | sofascore.TeamRef | No | TeamRef record, 6 fields: country, id, name, national, short_name, slug. Described under SofaScore venue API. | |||
| data.trees[].rounds[].blocks[].participants[].winner | boolean | No | ||||
| data.trees[].rounds[].blocks[].result | string | No | 4:5 | Result is the tie result as published ("4:5", or a text such as "Retired"). | ||
| data.trees[].rounds[].blocks[].series_start_time | string | No | 2026-02-17T20:00:00Z | |||
| data.trees[].rounds[].blocks[].series_start_timestamp | integer | No | ||||
| data.trees[].rounds[].blocks[].venue | sofascore.Venue | No | ||||
| data.trees[].rounds[].blocks[].venue.capacity | integer | No | 61276 | Venue capacity. | ||
| data.trees[].rounds[].blocks[].venue.city | string | No | Liverpool | City the venue is in. | ||
| data.trees[].rounds[].blocks[].venue.country | string | No | England | Country the venue is in. | ||
| data.trees[].rounds[].blocks[].venue.name | string | No | Anfield | Venue name. | ||
| data.trees[].rounds[].description | string | No | Quarterfinal | |||
| data.trees[].rounds[].id | integer | No | ||||
| data.trees[].rounds[].order | integer | No | 1 | |||
| data.trees[].rounds[].round_type | integer | No | 4 | RoundType is the upstream round code: the number of ties for the standard knockout rounds (8 round of 16, 4 quarterfinals, 2 semifinals, 1 final) and other codes (0, 101 to 105, 201 to 202) for named rounds. | ||
| data.trees[].third_place_match | object | No | ThirdPlaceMatch is the third-place tie, when the competition plays one. | |||
| data.trees[].third_place_match.away_score | string | No | 1 (3) | |||
| data.trees[].third_place_match.block_id | integer | No | 2536336 | BlockID is the identifier later blocks cite as source_block_id. | ||
| data.trees[].third_place_match.event_ids | array | No | EventIDs are the match ids of the tie; fetch each with the event endpoint. | |||
| data.trees[].third_place_match.finished | boolean | No | ||||
| data.trees[].third_place_match.home_score | string | No | 1 (4) | HomeScore and AwayScore are the scores of the participants with order 1 and 2. They are strings because a shoot-out is appended ("1 (4)"). | ||
| data.trees[].third_place_match.id | integer | No | 2946978 | |||
| data.trees[].third_place_match.in_progress | boolean | No | InProgress is true while a match of the tie is being played. | |||
| data.trees[].third_place_match.matches | integer | No | 2 | Matches is the scheduled length of the tie: 1 for a single match, 2 for a two-legged tie, 7 for a best-of-seven series (whether or not all seven were needed), 0 for a bye. | ||
| data.trees[].third_place_match.order | integer | No | 2 | |||
| data.trees[].third_place_match.participants | array | No | ||||
| data.trees[].third_place_match.participants[].order | integer | No | 1 | Order is the side's position in the block; the block's home_score belongs to order 1 and away_score to order 2. | ||
| data.trees[].third_place_match.participants[].seed | string | No | WC | Seed is the draw seed or entry label ("1", "WC" for a wild card), when published. | ||
| data.trees[].third_place_match.participants[].source_block_id | integer | No | SourceBlockID is the block_id of the earlier block this side advanced from. | |||
| data.trees[].third_place_match.participants[].team | sofascore.TeamRef | No | TeamRef record, 6 fields: country, id, name, national, short_name, slug. Described under SofaScore venue API. | |||
| data.trees[].third_place_match.participants[].winner | boolean | No | ||||
| data.trees[].third_place_match.result | string | No | 4:5 | Result is the tie result as published ("4:5", or a text such as "Retired"). | ||
| data.trees[].third_place_match.series_start_time | string | No | 2026-02-17T20:00:00Z | |||
| data.trees[].third_place_match.series_start_timestamp | integer | No | ||||
| data.trees[].third_place_match.venue | sofascore.Venue | No | ||||
| data.trees[].third_place_match.venue.capacity | integer | No | 61276 | Venue capacity. | ||
| data.trees[].third_place_match.venue.city | string | No | Liverpool | City the venue is in. | ||
| data.trees[].third_place_match.venue.country | string | No | England | Country the venue is in. | ||
| data.trees[].third_place_match.venue.name | string | No | Anfield | Venue name. | ||
| data.trees[].tournament_name | string | No | UEFA Champions League, Knockout stage | |||
| msg | string | No | OK |
| Status | Description | Schema |
|---|---|---|
| 400 | Bad Request | #/definitions/app.Response |
| 404 | Not Found | #/definitions/app.Response |
| 429 | Too Many Requests | #/definitions/app.Response |
| 503 | Service Unavailable | #/definitions/app.Response |
Use environment variables for secrets and keep Crawlora API keys server-side.
curl -X GET "https://api.crawlora.net/api/v1/sofascore/tournament-cuptree?id=7&season=76953" \
-H "x-api-key: $CRAWLORA_API_KEY"