SofaScore API endpoint
Returns SofaScore's winning odds list for a sport: about twenty upcoming events whose favourite SofaScore highlights, each as the usual event summary plus `winning_odds` (fractional), the `expected` and `actual` percentages SofaScore reports for it (returned as supplied) and the full-time market with opening and current prices (`change` is 1 above the opening price, -1 below it, 0 unchanged). The `sport` enum accepts `all` and the SofaScore sport keys; it defaults to `all`. A sport with no qualifying events at the moment (for example baseball, cricket and esports when probed) returns 404.
/sofascore/odds-winningQuery parameters:
sport: optional enum. Allowed values: all, american-football, aussie-rules, badminton, bandy, baseball, basketball, beach-volley, cricket, darts, esports, floorball, football, futsal, handball, ice-hockey, mma, minifootball, padel, rugby, snooker, table-tennis, tennis, volleyball, waterpolo. Defaults to all.Notable response behavior:
sport key, winning_odds (the highlighted favourite's fractional odds), the expected and actual percentages SofaScore reports for it (returned as supplied, not interpreted) and the full-time market with each choice's opening initial_value and current value. change is 1 when the price is above its opening value, -1 when below it and 0 when unchanged.404 (baseball, american-football, volleyball, handball, cricket and esports did when checked). An unsupported sport returns 400.| Field | Filled in, of 20 checked | Values in the sample |
|---|---|---|
| id | 20 | |
| slug | 20 | |
| start_timestamp | 20 | 2026-10-13 to 2026-10-14 |
| start_time | 20 | 2026-10-13 to 2026-10-14 |
| status | 20 | |
| tournament | 20 | |
| home_team | 20 | |
| away_team | 20 | |
| sport | 20 | football (10), tennis (6), basketball (2) and 1 more |
| winning_odds | 20 | “3/4” and 17 other values |
| expected | 20 | 31 to 97, median 49 |
| actual | 20 | 1 to 60, median 13 |
| market | 20 |
| Parameter | Type | Required | Default | Description | Example |
|---|---|---|---|---|---|
| sport | string | No | all | Sport key, or all for every sport. Defaults to all Allowed values: all, american-football, aussie-rules, badminton, bandy, baseball, basketball, beach-volley, cricket, darts, esports, floorball, football, futsal, handball, ice-hockey, mma, minifootball, padel, rugby, snooker, table-tennis, tennis, volleyball, waterpolo. | football |
| x-api-key (header) | string | Yes | API key required |
curl -X GET "https://api.crawlora.net/api/v1/sofascore/odds-winning?sport=all" \ -H "x-api-key: $CRAWLORA_API_KEY"
{
"code": 200,
"msg": "OK",
"data": {
"sport": "all",
"source_url": "https://api.sofascore.com/api/v1/odds/1/winning/all",
"fetched_at": "2026-07-08T00:00:00Z",
"count": 3,
"events": [
{
"id": 17226333,
"slug": "atlanta-dream-new-york-liberty",
"start_timestamp": 1791415800,
"start_time": "2026-10-07T23:30:00Z",
"status": {
"code": 0,
"description": "Not started",
"type": "notstarted"
},
"tournament": {
"id": 11419,
"name": "WNBA, Playoffs",
"slug": "wnba-playoffs",
"category": "USA",
"unique_tournament_id": 486,
"unique_tournament_name": "WNBA"
},
"home_team": {
"id": 35545,
"name": "Atlanta Dream",
"short_name": "Dream",
"slug": "atlanta-dream"
},
"away_team": {
"id": 3446,
"name": "New York Liberty",
"short_name": "Liberty",
"slug": "new-york-liberty"
},
"sport": "basketball",
"winning_odds": "24/25",
"expected": 51,
"actual": 1,
"market": {
"name": "Full time",
"group": "Home/Away",
"period": "Match",
"is_live": false,
"choices": [
{
"name": "1",
"value": "79/100",
"initial_value": "31/50",
"change": 1
},
{
"name": "2",
"value": "24/25",
"initial_value": "6/5",
"change": -1
}
]
}
}
]
}
}Request schema
No body schema
Response schema
#/definitions/sofascore.oddsWinningResponseDoc
| Field | Type | Required | Enum | Bounds | Example | Description |
|---|---|---|---|---|---|---|
| code | integer | No | 200 | |||
| data | sofascore.OddsWinningResponse | No | ||||
| data.count | integer | No | ||||
| data.events | array | No | ||||
| data.events[].actual | number | No | 1 | |||
| data.events[].away_score | object | No | Away side's score, when available. | |||
| data.events[].away_score.current | integer | No | Current score, which is the final score once the match is over. | |||
| data.events[].away_score.period1 | integer | No | Score in the first period. | |||
| data.events[].away_score.period2 | integer | No | Score in the second period. | |||
| data.events[].away_team | object | No | Away side. | |||
| data.events[].away_team.country | string | No | Spain | Country the team belongs to. | ||
| data.events[].away_team.id | integer | No | 2817 | SofaScore team id. Use it with the team endpoints. | ||
| data.events[].away_team.name | string | No | FC Barcelona | Full team name. | ||
| data.events[].away_team.national | boolean | No | True for a national team. | |||
| data.events[].away_team.short_name | string | No | Barcelona | Shortened team name. | ||
| data.events[].away_team.slug | string | No | barcelona | URL slug of the team on SofaScore. | ||
| data.events[].expected | number | No | 51 | |||
| data.events[].home_score | object | No | Home side's score, when available. | |||
| data.events[].home_score.current | integer | No | Current score, which is the final score once the match is over. | |||
| data.events[].home_score.period1 | integer | No | Score in the first period. | |||
| data.events[].home_score.period2 | integer | No | Score in the second period. | |||
| data.events[].home_team | object | No | Home side. | |||
| data.events[].home_team.country | string | No | Spain | Country the team belongs to. | ||
| data.events[].home_team.id | integer | No | 2817 | SofaScore team id. Use it with the team endpoints. | ||
| data.events[].home_team.name | string | No | FC Barcelona | Full team name. | ||
| data.events[].home_team.national | boolean | No | True for a national team. | |||
| data.events[].home_team.short_name | string | No | Barcelona | Shortened team name. | ||
| data.events[].home_team.slug | string | No | barcelona | URL slug of the team on SofaScore. | ||
| data.events[].id | integer | No | 14025013 | SofaScore event id. Use it with the event endpoints. | ||
| data.events[].market | sofascore.MoverOddsMarket | No | ||||
| data.events[].market.choices | array | No | ||||
| data.events[].market.choices[].change | integer | No | 1 | Change is 1 when the fractional price is above its opening value, -1 when below it and 0 when unchanged. | ||
| data.events[].market.choices[].initial_value | string | No | 31/50 | |||
| data.events[].market.choices[].name | string | No | 1 | |||
| data.events[].market.choices[].value | string | No | 29/100 | |||
| data.events[].market.group | string | No | 1X2 | |||
| data.events[].market.is_live | boolean | No | ||||
| data.events[].market.name | string | No | Full time | |||
| data.events[].market.period | string | No | Full-time | |||
| data.events[].market.suspended | boolean | No | ||||
| data.events[].slug | string | No | URL slug of the match on SofaScore. | |||
| data.events[].sport | string | No | basketball | |||
| data.events[].start_time | string | No | 2025-08-15T19:00:00Z | Start time in UTC (RFC 3339). | ||
| data.events[].start_timestamp | integer | No | Start time as a Unix timestamp in seconds. | |||
| data.events[].status | object | No | Current status of the match. | |||
| data.events[].status.code | integer | No | SofaScore's numeric status code, for example 0 for not started and 100 for ended. | |||
| data.events[].status.description | string | No | Ended | Status as displayed, for example "Ended". | ||
| data.events[].status.type | string | No | finished | Status group, for example `notstarted`, `inprogress` or `finished`. | ||
| data.events[].tournament | object | No | Tournament and parent competition the match belongs to. | |||
| data.events[].tournament.category | string | No | England | Category the tournament sits under, usually a country or region. | ||
| data.events[].tournament.id | integer | No | SofaScore id of the tournament the match is filed under. The seasons, standings and round endpoints take `unique_tournament_id` instead. | |||
| data.events[].tournament.name | string | No | Premier League | Tournament name. | ||
| data.events[].tournament.slug | string | No | premier-league | URL slug of the tournament on SofaScore. | ||
| data.events[].tournament.unique_tournament_id | integer | No | 17 | Id of the parent competition. This is the tournament id the tournament-seasons, standings and round-events endpoints take. | ||
| data.events[].tournament.unique_tournament_name | string | No | Premier League | Name of the parent competition. | ||
| data.events[].winner_code | integer | No | Result code: 1 when the home side won, 2 when the away side won, 3 for a draw. Omitted until the match is decided. | |||
| data.events[].winning_odds | string | No | 24/25 | |||
| data.fetched_at | string | No | ||||
| data.source_url | string | No | ||||
| data.sport | string | No | all | |||
| 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/odds-winning?sport=all" \
-H "x-api-key: $CRAWLORA_API_KEY"