API Reference
Upcoming Matches
Build tennis schedules and match previews with upcoming fixtures, player and tournament details, pre-match odds and predictions where available. Find men’s and women’s singles and doubles matches, with filters for date, tournament, player, surface and competition level.
Go deeper into every matchup. Use the players’ IDs from an upcoming match to explore Head-to-Head Stats & Analysis: previous meetings, surface records, detailed serve and return statistics, and performance against other opponents. Explore Results & Historical Data for past results and individual match analysis, with statistics, point-by-point data and historical odds where available.
As the match progresses, follow its available links to live scores, detailed statistics, point-by-point data and completed results.
Scheduled matches, factual match/H2H data and available pre-match odds are available on all plans. Model win probabilities require ULTRA or MEGA. Written prediction analysis requires MEGA. Request allowances vary by plan. On FREE / PRO, modelPrediction is returned as a plan_restricted object.
Every upcoming row links onward, so you never match records by names, tournament and date: links.live → Live Match by matchId (score, server, timeline, the live eventId and links to full statistics and point-by-point); once played, the same liveMatchId gives completed-match statistics and point-by-point. liveMatchId on upcoming rows equals matchId on live rows.
predictionSummary is the bookmaker-implied view (legacy key kept for compatibility). SportsAPI365 model win probabilities are exposed separately as modelPrediction when available. Do not mix the two.
All Upcoming Matches
Available on all plans, including full-market odds, preMatchOdds and predictionSummary (these two are opt-in: add include=preMatchOdds,predictionSummary). Only the SportsAPI365 modelPrediction (win probabilities) requires ULTRA or MEGA; on FREE / PRO it is a plan_restricted object. On ULTRA / MEGA it shows available: false for matches the model has not scored (doubles, and matches without a scheduled start time).
/tennis/v2/upcoming/matchesQuery Parameter
| Parameter | Required | Type | Description |
|---|---|---|---|
date | No | string | Lower bound, not a single day: returns upcoming matches that start after this date/time (plus matches with no time set yet). Default: now. YYYY-MM-DD or an ISO-8601 date-time; an invalid date returns 400. For one day use dateOnly. Example: date=2026-09-15. |
dateOnly | No | string | One UTC day, YYYY-MM-DD: matches scheduled that day (matches with no time set are left out). Not with date, autoPost or dateFrom/dateTo (400). Example: dateOnly=2026-10-27. |
dateFrom | No | string | With dateTo: an inclusive range of UTC days, YYYY-MM-DD (equal days allowed; a reversed range is a 400). Matches with no time set are left out. Example: dateFrom=2026-10-26&dateTo=2026-10-28. |
dateTo | No | string | Last UTC day of the range (inclusive); requires dateFrom. |
group | No | string | singles or doubles. Omitted: both. |
tournamentId | No | string | Tournament edition id(s), comma-separated (from tournament.id on rows, or /upcoming/filters?include=options). With tournament (name), both must match. Example: tournamentId=21360. |
playerId | No | string | One player id: matches where that player is on either side, including a doubles pair that contains the player. On /upcoming/matches (both tours) the id is looked up in both tours, so prefer the per-tour route. Example: playerId=84377. |
opponentId | No | string | With playerId only: the match between these two (either order). Example: playerId=84377&opponentId=31446. |
surfaceId | No | string | Surface (court) id(s), comma-separated, e.g. 1 Hard, 2 Clay, 3 I.hard; see /upcoming/filters?include=options. Example: surfaceId=1,3. |
country | No | string | Tournament country code(s), comma-separated — where the tournament is played, not player nationality. Example: country=SUI,AUT. |
rank | No | string | Tournament level: an id or a name exactly as /upcoming/filters lists them (case-insensitive), several comma-separated. ATP 250 and 500 are not separate levels: both are 2 (Main tour). An unknown level is a 400 that lists the valid ones. Example: rank=Main tour or rank=2,3. |
playerRank | No | string | Current ranking of either player. A number N = either player ranked 1 to N; a band min-max = either player ranked in that band. Unranked players never match. Example: playerRank=50 or playerRank=51-100. |
sortBy | No | string | h2h orders by head-to-head interest; startTime orders by scheduled time, earliest first, unscheduled last. Omitted: tournament level, then time (as before). Example: sortBy=startTime. |
autoPost | No | boolean | Default false. true returns only matches scheduled to start within the next 5 hours (and ignores date). Not with dateOnly/dateFrom. |
tournament | No | string | Filter by tournament name. Example: Monte-Carlo Rolex Masters - Monte-Carlo |
includeAll | No | boolean | Include Challenger/ITF and full history where supported. Example: includeAll=true |
include | No | string | Additive only. Comma-separated: preMatchOdds, predictionSummary, all (both of those), plus two opt-in extras that all does not add: fixtureDetails (round and level names, tournament.courtId, tournament.countryDetails, startTime, doubles members) and metadata (odds totalUnit, the bookmaker behind preMatchOdds / predictionSummary, h2hSummary.scope, startTimeSource, and available: false with a reason when a summary has no data). Default already includes matchId and h2hSummary. Example: include=all,fixtureDetails,metadata. |
page | No | integer | Page number, starting at 1. pageNo is accepted as an alias on every route. Example: page=1 |
limit | No | integer | Results per page. pageSize is accepted as an alias on every route. Default varies by endpoint. Example: limit=10 |
Response Properties
Shared objects in this response (defined once in Reusable response schemas): Player · Tournament · Plan-restricted field.
| Field | Type | Description |
|---|---|---|
total | integer | Total matches matching the filter. |
matches | array | Page of upcoming matches. |
page / pageNo / pageSize / limit / hasNextPage / totalPages | mixed | Pagination (advanced family uses page + limit; pageNo/pageSize are also returned). |
matches[].id / matchId | integer | Match ID for this upcoming row. Use with GET /tennis/v2/matches/{matchId} and /prediction, /odds, /stats, /live. |
matches[].liveMatchId | string | This match's key in the live service and Socket.IO: "player1Id-player2Id-tournamentId-roundId". Equals matchId on live rows and event-update. |
matches[].links.match / links.live | string | Ready-to-call paths: the match detail route, and the live route that returns the live score, statistics, timeline and live eventId once the match is in the live feed ({} before). |
matches[].tournament | object | id, name, date, rankId, country, court. |
matches[].date | string | Expected start, ISO-8601 UTC: the live service's time when it has the match (it gives each match its own time), otherwise the OnCourt schedule's (which often gives every match on a court the session start). The same time is used for sorting, the date filters, and match detail. null when not scheduled. A match that follows another can still move during the day. |
matches[].player1 / player2 | object | id, name, odd, oddBookmaker, countryAcr, seed, image. player1 is first-listed, not predicted winner. |
matches[].player1.odd / player2.odd | number | string | null | The schedule's match-winner price for that player. It is Marathonbet's price, while the row's odds object is Pinnacle's (odds.bookmaker), so the two prices differ. |
matches[].player1.oddBookmaker / player2.oddBookmaker | string | Bookmaker of odd: always Marathonbet. Present only when odd is set. |
matches[].odds | object | Pinnacle's pre-match markets when present (odds.bookmaker): k1, k2 match winner; total with ktb (over) / ktm (under) — Pinnacle's total is in sets (e.g. 2.5), not games. With include=metadata, odds.totalUnit says so. All plans; preMatchOdds repeats the match-winner prices. |
matches[].h2h | string | Career H2H as player1Wins-player2Wins string, e.g. 4-1. |
matches[].h2hSummary | object | Additive factual H2H: matchCount, player1Wins, player2Wins (always present on upcoming lists). Tour-level meetings by default; includeAll=true counts all levels. With include=metadata, scope says which: main_tour or all_levels. 0-0 means they have not met in that scope. |
matches[].preMatchOdds | object | Additive. Only when include=preMatchOdds (or include=all): player1, player2 (match-winner odds) and updatedAt, which is always null because the odds source has no update time (freshness unknown). The prices are Pinnacle's when Pinnacle has them, otherwise the schedule's Marathonbet prices; with include=metadata, bookmaker names which, and a row with no prices gets {available: false, reason: "not_available"}. |
matches[].round / startTime | object / string | include=fixtureDetails: round {id, name} (roundId is kept) and startTime, the same UTC instant as date (null when not scheduled). |
matches[].tournament.rank / courtId / court.id / countryDetails | object / integer | include=fixtureDetails: level {id, name} (rankId is kept), surface id (also court.id beside court.name), and the tournament country {name, acronym} (country keeps the code). |
matches[].player1.members / player2.members | array | include=fixtureDetails, doubles only: the two players [{id, name}]; id is null when the name does not identify one player. |
matches[].startTimeSource / startTimeUpdatedAt | string / null | include=metadata: where date comes from — live (the live service's expected time) or schedule (the OnCourt schedule) — and when that source last changed it (null: not recorded). |
matches[].predictionSummary | object | Additive when include=predictionSummary|all. Bookmaker-implied view (source=oddsImplied): predictedWinnerId, bookmakerOdds, player1ImpliedProbability, player2ImpliedProbability, normalized. |
matches[].modelPrediction | object | Always present. ULTRA/MEGA: SportsAPI365 model view (available, source, predictedWinnerId, player1WinProbability, player2WinProbability). FREE/PRO: plan_restricted stub with message "Upgrade Plan to see this" (field kept visible; not null). Separate from predictionSummary. |
matches[].links | object | Ready-made URLs for this match's detail routes. |
matches[].tournament.id | number | Tournament season ID. |
matches[].tournament.name | string | Tournament name. |
matches[].tournament.date | string | Tournament start date (ISO-8601 UTC). |
matches[].tournament.rankId | number | Tournament level ID (TourRank, see GET /tennis/v2/ranking): 0 ITF $10K, 1 Challenger/ITF > $10K, 2 Main tour, 3 Masters, 4 Grand Slam, 5 Davis/Fed Cup, 7 Tour finals, … |
matches[].tournament.country | string | Country of the tournament: three-letter code, or { name, acronym }. |
matches[].tournament.court | object | Court surface of the tournament: { id, name } (some routes return only { name }), e.g. { "name": "Hard" }. |
matches[].tournament.court.name | string | Court surface name, e.g. Hard, Clay, Grass, I.hard. |
matches[].court | string | Court surface of the match as a name, e.g. "Hard". |
matches[].roundId | number | Numeric round ID (see GET /tennis/v2/round): e.g. 4 = First, 5 = Second, 9 = 1/4, 10 = 1/2, 12 = Final; 0–3 are qualifying rounds. |
matches[].rank | number | Tournament level ID of the match (TourRank). |
matches[].type | string | Dataset: atp or wta. |
matches[].odds.id_b_o | number | Archive bookmaker ID: 1 = Marathonbet, 2 = Pinnacle. Archive IDs are their own namespace (live-service bookmaker IDs differ). |
matches[].odds.bookmaker | string | Bookmaker name. |
matches[].odds.id1_o | number | Player whose price is k1. The archive may list the pair in the other order than the match row: map prices by id1_o / id2_o, not by position. |
matches[].odds.id2_o | number | Player whose price is k2. |
matches[].odds.total | number | Games-total line that ktb (over) and ktm (under) refer to, or null. |
matches[].odds.k1 | number | Match-winner odds for player 1 (decimal). |
matches[].odds.k2 | number | Match-winner odds for player 2 (decimal). |
matches[].odds.ktb | number | Over odds for the games-total line in total, or null. |
matches[].odds.ktm | number | Under odds for the games-total line in total, or null. |
matches[].player1.name | string | Player 1 name. |
matches[].player1.countryAcr | string | Player 1 country code. |
matches[].player1.seed | string | Tournament seed as a string, or null when unseeded. |
matches[].player1.image | string | Player photo path on this API (append to the base URL). |
matches[].player1.image_p_name | string | Player photo path keyed by player name (alternative to image). |
matches[].player1.id | number | Player 1 ID. |
matches[].player2.id | number | Player 2 ID. |
matches[].player2.name | string | Player 2 name. |
matches[].player2.countryAcr | string | Player 2 country code. |
matches[].player2.seed | string | Tournament seed as a string, or null when unseeded. |
matches[].player2.image | string | Player photo path on this API (append to the base URL). |
matches[].player2.image_p_name | string | Player photo path keyed by player name (alternative to image). |
matches[].h2hSummary.matchCount | number | Career meetings between the two players. |
matches[].h2hSummary.player1Wins | number | Career head-to-head wins of player 1. |
matches[].h2hSummary.player2Wins | number | Career head-to-head wins of player 2. |
matches[].preMatchOdds.player1 | number | Match-winner odds for player 1 (decimal). |
matches[].preMatchOdds.player2 | number | Match-winner odds for player 2 (decimal). |
matches[].predictionSummary.available | boolean | true when both headline odds exist and a favourite can be derived. |
matches[].predictionSummary.source | string | Always "oddsImplied": derived from bookmaker odds. |
matches[].predictionSummary.predictedWinnerId | number | Player ID of the predicted winner. |
matches[].predictionSummary.bookmakerOdds | object | Headline bookmaker odds used for the implied probabilities: player1, player2. |
matches[].predictionSummary.bookmakerOdds.player1 | number | Bookmaker match-winner odds for player 1. |
matches[].predictionSummary.bookmakerOdds.player2 | number | Bookmaker match-winner odds for player 2. |
matches[].predictionSummary.player1ImpliedProbability | number | Implied win probability for player 1 in percent (normalised). |
matches[].predictionSummary.player2ImpliedProbability | number | Implied win probability for player 2 in percent (normalised). |
matches[].predictionSummary.normalized | boolean | true when the implied probabilities were normalised to sum to 100 (bookmaker margin removed). |
matches[].modelPrediction.available | boolean | true when model probabilities are present; false when not yet available or plan-restricted. |
matches[].modelPrediction.source | string | Always "sportsapi365" (proprietary model). |
matches[].modelPrediction.predictedWinnerId | number | Player ID of the predicted winner. |
matches[].modelPrediction.player1WinProbability | number | Model win probability for player 1 in percent; null when not available. |
matches[].modelPrediction.player2WinProbability | number | Model win probability for player 2 in percent; null when not available. |
Upcoming Matches by Tour
Available on all plans, including full-market odds, preMatchOdds and predictionSummary (these two are opt-in: add include=preMatchOdds,predictionSummary). Only the SportsAPI365 modelPrediction (win probabilities) requires ULTRA or MEGA; on FREE / PRO it is a plan_restricted object. On ULTRA / MEGA it shows available: false for matches the model has not scored (doubles, and matches without a scheduled start time).
/tennis/v2/upcoming/matches/{atp|wta}atp. Use wta for the women's dataset.Returns all upcoming scheduled matches by tour type. player1.odd / player2.odd are Marathonbet’s match-winner prices (oddBookmaker: Marathonbet); the odds object is Pinnacle’s.Path Parameter
| Parameter | Required | Type | Description |
|---|---|---|---|
atp|wta | Yes | string | Dataset to query. atp = men's tennis across all supported levels, including Grand Slams, ATP Tour, Challengers and ITF. wta = women's tennis across all supported levels, including Grand Slams, WTA Tour and ITF. There is no separate itf value. |
Query Parameter
| Parameter | Required | Type | Description |
|---|---|---|---|
date | No | string | Lower bound, not a single day: returns upcoming matches that start after this date/time (plus matches with no time set yet). Default: now. YYYY-MM-DD or an ISO-8601 date-time; an invalid date returns 400. For one day use dateOnly. Example: date=2026-09-15. |
dateOnly | No | string | One UTC day, YYYY-MM-DD: matches scheduled that day (matches with no time set are left out). Not with date, autoPost or dateFrom/dateTo (400). Example: dateOnly=2026-10-27. |
dateFrom | No | string | With dateTo: an inclusive range of UTC days, YYYY-MM-DD (equal days allowed; a reversed range is a 400). Matches with no time set are left out. Example: dateFrom=2026-10-26&dateTo=2026-10-28. |
dateTo | No | string | Last UTC day of the range (inclusive); requires dateFrom. |
group | No | string | singles or doubles. Omitted: both. |
tournamentId | No | string | Tournament edition id(s), comma-separated (from tournament.id on rows, or /upcoming/filters?include=options). With tournament (name), both must match. Example: tournamentId=21360. |
playerId | No | string | One player id: matches where that player is on either side, including a doubles pair that contains the player. On /upcoming/matches (both tours) the id is looked up in both tours, so prefer the per-tour route. Example: playerId=84377. |
opponentId | No | string | With playerId only: the match between these two (either order). Example: playerId=84377&opponentId=31446. |
surfaceId | No | string | Surface (court) id(s), comma-separated, e.g. 1 Hard, 2 Clay, 3 I.hard; see /upcoming/filters?include=options. Example: surfaceId=1,3. |
country | No | string | Tournament country code(s), comma-separated — where the tournament is played, not player nationality. Example: country=SUI,AUT. |
rank | No | string | Tournament level: an id or a name exactly as /upcoming/filters lists them (case-insensitive), several comma-separated. ATP 250 and 500 are not separate levels: both are 2 (Main tour). An unknown level is a 400 that lists the valid ones. Example: rank=Main tour or rank=2,3. |
playerRank | No | string | Current ranking of either player. A number N = either player ranked 1 to N; a band min-max = either player ranked in that band. Unranked players never match. Example: playerRank=50 or playerRank=51-100. |
sortBy | No | string | h2h orders by head-to-head interest; startTime orders by scheduled time, earliest first, unscheduled last. Omitted: tournament level, then time (as before). Example: sortBy=startTime. |
autoPost | No | boolean | Default false. true returns only matches scheduled to start within the next 5 hours (and ignores date). Not with dateOnly/dateFrom. |
tournament | No | string | Filter by tournament name. Example: Monte-Carlo Rolex Masters - Monte-Carlo |
includeAll | No | boolean | Include Challenger/ITF and full history where supported. Example: includeAll=true |
include | No | string | Additive only. Comma-separated: preMatchOdds, predictionSummary, all (both of those), plus two opt-in extras that all does not add: fixtureDetails (round and level names, tournament.courtId, tournament.countryDetails, startTime, doubles members) and metadata (odds totalUnit, the bookmaker behind preMatchOdds / predictionSummary, h2hSummary.scope, startTimeSource, and available: false with a reason when a summary has no data). Default already includes matchId and h2hSummary. Example: include=all,fixtureDetails,metadata. |
page | No | integer | Page number, starting at 1. pageNo is accepted as an alias on every route. Example: page=1 |
limit | No | integer | Results per page. pageSize is accepted as an alias on every route. Default varies by endpoint. Example: limit=10 |
Response Properties
Shared objects in this response (defined once in Reusable response schemas): Player · Tournament · Plan-restricted field.
| Field | Type | Description |
|---|---|---|
total | integer | Total matches matching the filter. |
matches | array | Page of upcoming matches. |
page / pageNo / pageSize / limit / hasNextPage / totalPages | mixed | Pagination (advanced family uses page + limit; pageNo/pageSize are also returned). |
matches[].id / matchId | integer | Match ID for this upcoming row. Use with GET /tennis/v2/matches/{matchId} and /prediction, /odds, /stats, /live. |
matches[].liveMatchId | string | This match's key in the live service and Socket.IO: "player1Id-player2Id-tournamentId-roundId". Equals matchId on live rows and event-update. |
matches[].links.match / links.live | string | Ready-to-call paths: the match detail route, and the live route that returns the live score, statistics, timeline and live eventId once the match is in the live feed ({} before). |
matches[].tournament | object | id, name, date, rankId, country, court. |
matches[].date | string | Expected start, ISO-8601 UTC: the live service's time when it has the match (it gives each match its own time), otherwise the OnCourt schedule's (which often gives every match on a court the session start). The same time is used for sorting, the date filters, and match detail. null when not scheduled. A match that follows another can still move during the day. |
matches[].player1 / player2 | object | id, name, odd, oddBookmaker, countryAcr, seed, image. player1 is first-listed, not predicted winner. |
matches[].player1.odd / player2.odd | number | string | null | The schedule's match-winner price for that player. It is Marathonbet's price, while the row's odds object is Pinnacle's (odds.bookmaker), so the two prices differ. |
matches[].player1.oddBookmaker / player2.oddBookmaker | string | Bookmaker of odd: always Marathonbet. Present only when odd is set. |
matches[].odds | object | Pinnacle's pre-match markets when present (odds.bookmaker): k1, k2 match winner; total with ktb (over) / ktm (under) — Pinnacle's total is in sets (e.g. 2.5), not games. With include=metadata, odds.totalUnit says so. All plans; preMatchOdds repeats the match-winner prices. |
matches[].h2h | string | Career H2H as player1Wins-player2Wins string, e.g. 4-1. |
matches[].h2hSummary | object | Additive factual H2H: matchCount, player1Wins, player2Wins (always present on upcoming lists). Tour-level meetings by default; includeAll=true counts all levels. With include=metadata, scope says which: main_tour or all_levels. 0-0 means they have not met in that scope. |
matches[].preMatchOdds | object | Additive. Only when include=preMatchOdds (or include=all): player1, player2 (match-winner odds) and updatedAt, which is always null because the odds source has no update time (freshness unknown). The prices are Pinnacle's when Pinnacle has them, otherwise the schedule's Marathonbet prices; with include=metadata, bookmaker names which, and a row with no prices gets {available: false, reason: "not_available"}. |
matches[].round / startTime | object / string | include=fixtureDetails: round {id, name} (roundId is kept) and startTime, the same UTC instant as date (null when not scheduled). |
matches[].tournament.rank / courtId / court.id / countryDetails | object / integer | include=fixtureDetails: level {id, name} (rankId is kept), surface id (also court.id beside court.name), and the tournament country {name, acronym} (country keeps the code). |
matches[].player1.members / player2.members | array | include=fixtureDetails, doubles only: the two players [{id, name}]; id is null when the name does not identify one player. |
matches[].startTimeSource / startTimeUpdatedAt | string / null | include=metadata: where date comes from — live (the live service's expected time) or schedule (the OnCourt schedule) — and when that source last changed it (null: not recorded). |
matches[].predictionSummary | object | Additive when include=predictionSummary|all. Bookmaker-implied view (source=oddsImplied): predictedWinnerId, bookmakerOdds, player1ImpliedProbability, player2ImpliedProbability, normalized. |
matches[].modelPrediction | object | Always present. ULTRA/MEGA: SportsAPI365 model view (available, source, predictedWinnerId, player1WinProbability, player2WinProbability). FREE/PRO: plan_restricted stub with message "Upgrade Plan to see this" (field kept visible; not null). Separate from predictionSummary. |
matches[].links | object | Ready-made URLs for this match's detail routes. |
matches[].tournament.id | number | Tournament season ID. |
matches[].tournament.name | string | Tournament name. |
matches[].tournament.date | string | Tournament start date (ISO-8601 UTC). |
matches[].tournament.rankId | number | Tournament level ID (TourRank, see GET /tennis/v2/ranking): 0 ITF $10K, 1 Challenger/ITF > $10K, 2 Main tour, 3 Masters, 4 Grand Slam, 5 Davis/Fed Cup, 7 Tour finals, … |
matches[].tournament.country | string | Country of the tournament: three-letter code, or { name, acronym }. |
matches[].tournament.court | object | Court surface of the tournament: { id, name } (some routes return only { name }), e.g. { "name": "Hard" }. |
matches[].tournament.court.name | string | Court surface name, e.g. Hard, Clay, Grass, I.hard. |
matches[].court | string | Court surface of the match as a name, e.g. "Hard". |
matches[].roundId | number | Numeric round ID (see GET /tennis/v2/round): e.g. 4 = First, 5 = Second, 9 = 1/4, 10 = 1/2, 12 = Final; 0–3 are qualifying rounds. |
matches[].rank | number | Tournament level ID of the match (TourRank). |
matches[].type | string | Dataset: atp or wta. |
matches[].odds.id_b_o | number | Archive bookmaker ID: 1 = Marathonbet, 2 = Pinnacle. Archive IDs are their own namespace (live-service bookmaker IDs differ). |
matches[].odds.bookmaker | string | Bookmaker name. |
matches[].odds.id1_o | number | Player whose price is k1. The archive may list the pair in the other order than the match row: map prices by id1_o / id2_o, not by position. |
matches[].odds.id2_o | number | Player whose price is k2. |
matches[].odds.total | number | Games-total line that ktb (over) and ktm (under) refer to, or null. |
matches[].odds.k1 | number | Match-winner odds for player 1 (decimal). |
matches[].odds.k2 | number | Match-winner odds for player 2 (decimal). |
matches[].odds.ktb | number | Over odds for the games-total line in total, or null. |
matches[].odds.ktm | number | Under odds for the games-total line in total, or null. |
matches[].player1.name | string | Player 1 name. |
matches[].player1.countryAcr | string | Player 1 country code. |
matches[].player1.seed | string | Tournament seed as a string, or null when unseeded. |
matches[].player1.image | string | Player photo path on this API (append to the base URL). |
matches[].player1.image_p_name | string | Player photo path keyed by player name (alternative to image). |
matches[].player1.id | number | Player 1 ID. |
matches[].player2.id | number | Player 2 ID. |
matches[].player2.name | string | Player 2 name. |
matches[].player2.countryAcr | string | Player 2 country code. |
matches[].player2.seed | string | Tournament seed as a string, or null when unseeded. |
matches[].player2.image | string | Player photo path on this API (append to the base URL). |
matches[].player2.image_p_name | string | Player photo path keyed by player name (alternative to image). |
matches[].h2hSummary.matchCount | number | Career meetings between the two players. |
matches[].h2hSummary.player1Wins | number | Career head-to-head wins of player 1. |
matches[].h2hSummary.player2Wins | number | Career head-to-head wins of player 2. |
matches[].preMatchOdds.player1 | number | Match-winner odds for player 1 (decimal). |
matches[].preMatchOdds.player2 | number | Match-winner odds for player 2 (decimal). |
matches[].predictionSummary.available | boolean | true when both headline odds exist and a favourite can be derived. |
matches[].predictionSummary.source | string | Always "oddsImplied": derived from bookmaker odds. |
matches[].predictionSummary.predictedWinnerId | number | Player ID of the predicted winner. |
matches[].predictionSummary.bookmakerOdds | object | Headline bookmaker odds used for the implied probabilities: player1, player2. |
matches[].predictionSummary.bookmakerOdds.player1 | number | Bookmaker match-winner odds for player 1. |
matches[].predictionSummary.bookmakerOdds.player2 | number | Bookmaker match-winner odds for player 2. |
matches[].predictionSummary.player1ImpliedProbability | number | Implied win probability for player 1 in percent (normalised). |
matches[].predictionSummary.player2ImpliedProbability | number | Implied win probability for player 2 in percent (normalised). |
matches[].predictionSummary.normalized | boolean | true when the implied probabilities were normalised to sum to 100 (bookmaker margin removed). |
matches[].modelPrediction.available | boolean | true when model probabilities are present; false when not yet available or plan-restricted. |
matches[].modelPrediction.source | string | Always "sportsapi365" (proprietary model). |
matches[].modelPrediction.predictedWinnerId | number | Player ID of the predicted winner. |
matches[].modelPrediction.player1WinProbability | number | Model win probability for player 1 in percent; null when not available. |
matches[].modelPrediction.player2WinProbability | number | Model win probability for player 2 in percent; null when not available. |
Match by matchId (detail aliases)
Take matchId from upcoming, fixtures or results rows. The response's links are ready-to-call paths for this match: each one is a documented endpoint below (or, for point-by-point, the live PBP route).
Upcoming → live in one call: every upcoming row has links.live (/tennis/v2/matches/{matchId}/live). It returns the live score, statistics, timeline and the live eventId for the live odds routes and Socket.IO. liveMatchId on the same row equals matchId on live rows, so live data can also be matched without a call.
Live → final result: once the match is completed it moves to results with a new matchId. /tennis/v2/matches/{liveMatchId}?type=atp|wta finds the same match at every stage (schedule, then completed), so keep liveMatchId to follow a fixture to its result.
/tennis/v2/matches/{matchId}Path Parameter
| Parameter | Required | Type | Description |
|---|---|---|---|
matchId | Yes | string | From upcoming matchId / fixtures matchId / results matchId, or a liveMatchId (player1Id-player2Id-tournamentId-roundId), which stays the same from the schedule to the completed match. |
Query Parameter
| Parameter | Required | Type | Description |
|---|---|---|---|
type | No | string | atp or wta. Optional; speeds up the lookup and avoids ambiguity: the same number can be a men's and a women's match. |
source | No | string | today (upcoming schedule) or game (completed matches). Optional: upcoming and completed matches are numbered separately, so links from schedule rows pass source=today and links from draws and results for completed matches pass source=game. Without it, an upcoming number that has left the schedule can match a different, archived match. |
Response Properties
Shared objects in this response (defined once in Reusable response schemas): Player.
| Field | Type | Description |
|---|---|---|
matchId | integer | Resolved match ID from the upcoming schedule or completed results. |
source | string | today = still on the upcoming schedule; game = completed archive. |
type | string | atp or wta. |
date / startTimeSource | string | Upcoming match: expected start, the same time as on the upcoming list (live = the live service's time, schedule = the OnCourt schedule's). Completed match: the recorded date, without startTimeSource. |
player1 / player2 | object | id and name. |
liveMatchId | string | This match's key in the live service and Socket.IO: "player1Id-player2Id-tournamentId-roundId" (matchId on live rows and event-update). Absent for a bye. |
links | object | Ready-to-call paths: prediction (upcoming matches only, MEGA), odds, stats, live, detailedStats (Detailed Live Match Statistics, the full statistics by set) and pointByPoint (Point-by-Point By Players, the recommended point-by-point route) — the last two by player names and match day, absent without a date. Completed matches are linked by their composite key (player1Id-player2Id-tournamentId-roundId), which survives archive reloads. Empty ({}) for a bye, which has no opponent. |
result | string | Score string, e.g. "6-3 6-4"; empty string until the match is played. |
roundId | number | Numeric round ID (see GET /tennis/v2/round): e.g. 4 = First, 5 = Second, 9 = 1/4, 10 = 1/2, 12 = Final; 0–3 are qualifying rounds. |
tournamentId | number | Numeric tournament season ID (one edition of an event). |
player1.id | number | Player 1 ID. |
player1.name | string | Player 1 name. |
player2.id | number | Player 2 ID. |
player2.name | string | Player 2 name. |
links.odds | string | URL of the archived pre-match odds for this match (both bookmakers); present when oddsAvailable is true. |
links.stats | string | URL of the completed-match statistics route (all plans). |
links.live | string | URL of the match's live route: live score, statistics, timeline and the live eventId ({} until the match is in the live feed). |
links.pointByPoint | string | URL of the live Point-by-Point By Players route for these players on the match day; absent when the match has no date. |
Match Prediction by matchId
MEGA required. FREE, PRO and ULTRA receive HTTP 403 with error: "plan_restricted".
Only for upcoming matches: a completed matchId returns 400. The example (matchId 550970, Medvedev v Atmane, Almaty quarterfinal on 2026-10-23) stops working once that match is played. For a current matchId, call Upcoming Matches and take matchId. Same response as Match Prediction & Analysis Paragraph.
/tennis/v2/matches/{matchId}/predictionPath Parameter
| Parameter | Required | Type | Description |
|---|---|---|---|
matchId | Yes | string | From matchId on upcoming, fixtures or results rows, or a liveMatchId (player1Id-player2Id-tournamentId-roundId), which stays the same from the schedule to the completed match. |
Query Parameter
| Parameter | Required | Type | Description |
|---|---|---|---|
type | No | string | atp or wta. Optional; speeds up the lookup and avoids ambiguity. |
source | No | string | today (upcoming schedule) or game (completed matches). Optional: upcoming and completed matches are numbered separately, so links from schedule rows pass source=today and links from draws and results for completed matches pass source=game. Without it, an upcoming number that has left the schedule can match a different, archived match. |
includeAll | No | boolean | Optional. true counts lower-level meetings (Challengers, ITF, qualifying) in the H2H and history the paragraph describes; the default uses main-tour matches only. Example: includeAll=true. |
onlyImp | No | boolean | Optional. true returns only the high-signal prediction bullets. Example: onlyImp=true. |
Response Properties
| Field | Type | Description |
|---|---|---|
paragraph | string | Match Prediction & Analysis Paragraph as an HTML list (<ul><li>…</li></ul>). Render as HTML or strip the tags. |
Match Odds by matchId
k1 is the price of the player in id1_o, k2 of the player in id2_o. That order can differ from the match row: completed matches list the winner as player1. Example, match 64511042: the match row has player1 Thiago Seyboth Wild (36858), player2 Francisco Comesana (61971); the Marathonbet row has id1_o 61971 with k1 2.08 and id2_o 36858 with k21.65, so Seyboth Wild's price is 1.65 and Comesana's 2.08.
prices = { [Number(o.id1_o)]: o.k1, [Number(o.id2_o)]: o.k2 }
player1Price = prices[match.player1.id]Handicap (f1/kf1, f2/kf2) and correct-score fields follow the same id1_o/id2_o sides.
/tennis/v2/matches/{matchId}/oddsThis endpoint provides stored pre-match odds from Pinnacle and Marathonbet. For pre-match prices from up to 10 bookmakers, use Pre-Match Odds in the Live Scores, Stats & Odds section: GET /tennis/v2/extend/api/odds/pre-match/{eventId}
Although listed in the Live section, this endpoint provides pre-match prices before play begins. It uses the live service’s eventId, not the upcoming matchId. Bookmaker and market availability varies by match.
Path Parameter
| Parameter | Required | Type | Description |
|---|---|---|---|
matchId | Yes | string | From matchId on upcoming, fixtures or results rows, or a liveMatchId (player1Id-player2Id-tournamentId-roundId), which stays the same from the schedule to the completed match. |
Query Parameter
| Parameter | Required | Type | Description |
|---|---|---|---|
type | No | string | atp or wta. Optional; speeds up the lookup and avoids ambiguity. |
source | No | string | today (upcoming schedule) or game (completed matches). Optional: upcoming and completed matches are numbered separately, so links from schedule rows pass source=today and links from draws and results for completed matches pass source=game. Without it, an upcoming number that has left the schedule can match a different, archived match. |
Response Properties
| Field | Type | Description |
|---|---|---|
odds[].id_b_o | string | Bookmaker ID as a numeric string: "1" = Marathonbet, "2" = Pinnacle. |
odds[].id1_o / id2_o | string | Player 1 / player 2 IDs for this odds row (numeric strings). |
odds[].id_t_o | string | Tournament season ID (numeric string). |
odds[].id_r_o | integer | Round ID. |
odds[].k1 / k2 | number | Match-winner (moneyline) odds: k1 is the price of the player in id1_o, k2 of the player in id2_o. This order can differ from the match row (completed matches list the winner as player1), so map prices by ID, never by position: { [id1_o]: k1, [id2_o]: k2 }. Compare IDs as numbers (id1_o/id2_o are numeric strings). Handicap (f1/kf1, f2/kf2) and correct-score fields follow the same id1_o/id2_o sides. |
odds[].bookmaker | string | Bookmaker name for id_b_o: Marathonbet or Pinnacle. |
odds[].total | number | null | Total line that ktb/ktm refer to, in totalUnit: games on Marathonbet (e.g. 22.5), sets on Pinnacle (2.5). null when the market is not offered. |
odds[].totalUnit | string | Unit of total: games (Marathonbet) or sets (Pinnacle). Present only when total is set. Compare totals only when the units match. |
odds[].ktb / ktm | number | null | Over (ktb) and under (ktm) odds for that total line; null when not offered. |
odds[].f1 / f2 | number | null | Handicap for player 1 / player 2, in handicapUnit: games on Marathonbet (e.g. -6), sets on Pinnacle (-1.5). null when not offered. |
odds[].handicapUnit | string | Unit of f1/f2: games (Marathonbet) or sets (Pinnacle). Present only when f1 is set. |
odds[].kf1 / kf2 | number | null | Odds for the corresponding handicap; null when not offered. |
odds[].k20 / k21 / k12 / k02 | number | null | Correct set score 2–0, 2–1, 1–2, 0–2 odds (best of three). null in a best-of-five match, where these scores cannot happen, and for bookmakers that do not offer correct-score markets (Pinnacle). |
odds[].k30 / k31 / k32 / k23 / k13 / k03 | number | null | Correct set score 3–0 … 0–3 odds (best of five). null in a best-of-three match, where these scores cannot happen, and for bookmakers that do not offer correct-score markets (Pinnacle). |
odds | array | Odds object documented in the rows below. |
odds[] | object | One item of `odds`; its fields are listed below. |
Pre-Match Odds (All Markets)
Keys such as k1, ktb, and f1 are not renamed (existing clients depend on them). Meanings are listed in the response properties below. total is the over/under line — in games for Marathonbet and in sets for Pinnacle (totalUnit says which); ktb = over, ktm = under.
/tennis/v2/upcoming/matchodds/{atp|wta}atp. Use wta for the women's dataset.Returns bookmaker odds for one upcoming matchup (moneyline, game totals, handicaps, set scores when offered). Each row names its bookmaker; totalUnit and handicapUnit give the unit of total and f1/f2: games for Marathonbet, sets for Pinnacle.This endpoint provides stored pre-match odds from Pinnacle and Marathonbet. For pre-match prices from up to 10 bookmakers, use Pre-Match Odds in the Live Scores, Stats & Odds section: GET /tennis/v2/extend/api/odds/pre-match/{eventId}
Although listed in the Live section, this endpoint provides pre-match prices before play begins. It uses the live service’s eventId, not the upcoming matchId. Bookmaker and market availability varies by match.
Path Parameter
| Parameter | Required | Type | Description |
|---|---|---|---|
atp|wta | Yes | string | Dataset to query. atp = men's tennis across all supported levels, including Grand Slams, ATP Tour, Challengers and ITF. wta = women's tennis across all supported levels, including Grand Slams, WTA Tour and ITF. There is no separate itf value. |
Query Parameter
| Parameter | Required | Type | Description |
|---|---|---|---|
player1Id | Yes | string | First player: numeric ID or display name. Example player1Id=40434 or player1Id=Jannik Sinner |
player2Id | No | string | Second player: numeric ID or display name. Example player2Id=68074 or player2Id=Carlos Alcaraz |
tournamentId | Yes | integer | Filter by tournament id. Example: tournamentId=21331 |
roundId | Yes | integer | Filter by round ID. Example: roundId=9 |
Response Properties
| Field | Type | Description |
|---|---|---|
odds | array | One object per bookmaker row (typically Marathonbet then Pinnacle). |
odds[].id_b_o | string | Bookmaker ID as a numeric string: "1" = Marathonbet, "2" = Pinnacle. |
odds[].id1_o / id2_o | string | Player 1 / player 2 IDs for this odds row (numeric strings). |
odds[].id_t_o | string | Tournament season ID (numeric string). |
odds[].id_r_o | integer | Round ID. |
odds[].k1 / k2 | number | Match-winner (moneyline) odds: k1 is the price of the player in id1_o, k2 of the player in id2_o. This order can differ from the match row (completed matches list the winner as player1), so map prices by ID, never by position: { [id1_o]: k1, [id2_o]: k2 }. Compare IDs as numbers (id1_o/id2_o are numeric strings). Handicap (f1/kf1, f2/kf2) and correct-score fields follow the same id1_o/id2_o sides. |
odds[].bookmaker | string | Bookmaker name for id_b_o: Marathonbet or Pinnacle. |
odds[].total | number | null | Total line that ktb/ktm refer to, in totalUnit: games on Marathonbet (e.g. 22.5), sets on Pinnacle (2.5). null when the market is not offered. |
odds[].totalUnit | string | Unit of total: games (Marathonbet) or sets (Pinnacle). Present only when total is set. Compare totals only when the units match. |
odds[].ktb / ktm | number | null | Over (ktb) and under (ktm) odds for that total line; null when not offered. |
odds[].f1 / f2 | number | null | Handicap for player 1 / player 2, in handicapUnit: games on Marathonbet (e.g. -6), sets on Pinnacle (-1.5). null when not offered. |
odds[].handicapUnit | string | Unit of f1/f2: games (Marathonbet) or sets (Pinnacle). Present only when f1 is set. |
odds[].kf1 / kf2 | number | null | Odds for the corresponding handicap; null when not offered. |
odds[].k20 / k21 / k12 / k02 | number | null | Correct set score 2–0, 2–1, 1–2, 0–2 odds (best of three). null in a best-of-five match, where these scores cannot happen, and for bookmakers that do not offer correct-score markets (Pinnacle). |
odds[].k30 / k31 / k32 / k23 / k13 / k03 | number | null | Correct set score 3–0 … 0–3 odds (best of five). null in a best-of-three match, where these scores cannot happen, and for bookmakers that do not offer correct-score markets (Pinnacle). |
Top Matches Today
Available on all plans, including full-market odds, preMatchOdds and predictionSummary (these two are opt-in: add include=preMatchOdds,predictionSummary). Only the SportsAPI365 modelPrediction (win probabilities) requires ULTRA or MEGA; on FREE / PRO it is a plan_restricted object. On ULTRA / MEGA it shows available: false for matches the model has not scored (doubles, and matches without a scheduled start time).
/tennis/v2/upcoming/top-tennis-matches-today/{atp|wta}atp. Use wta for the women's dataset.Returns today’s most significant singles matches (those with a prior H2H). modelPrediction (win probabilities) is ULTRA / MEGA; every other field is on all plansPath Parameter
| Parameter | Required | Type | Description |
|---|---|---|---|
atp|wta | Yes | string | Dataset to query. atp = men's tennis across all supported levels, including Grand Slams, ATP Tour, Challengers and ITF. wta = women's tennis across all supported levels, including Grand Slams, WTA Tour and ITF. There is no separate itf value. |
Response Properties
Shared objects in this response (defined once in Reusable response schemas): Player · Tournament · Plan-restricted field.
| Field | Type | Description |
|---|---|---|
[] | object | One item of the response; its fields are listed below. |
[].id | number | Numeric ID of this item (see the parent object: match, player, tournament, live event, …). |
[].matchId | number | Match ID (same value as id on core match rows). |
[].liveMatchId | string | Key of this match in the live service and Socket.IO: "player1Id-player2Id-tournamentId-roundId". Equals matchKey (and the deprecated matchId) on live rows and event-update. |
[].links | object | Ready-made URLs for this match's detail routes. |
[].links.match | string | URL of the match detail route (/tennis/v2/matches/{matchId}); source=game marks a completed match. |
[].links.live | string | URL of the match's live route: live score, statistics, timeline and the live eventId ({} until the match is in the live feed). |
[].tournament | object | Tournament object (id, name, date, level, surface, country, …). |
[].tournament.id | number | Tournament season ID. |
[].tournament.name | string | Tournament name. |
[].tournament.date | string | Tournament start date (ISO-8601 UTC). |
[].tournament.rankId | number | Tournament level ID (TourRank, see GET /tennis/v2/ranking): 0 ITF $10K, 1 Challenger/ITF > $10K, 2 Main tour, 3 Masters, 4 Grand Slam, 5 Davis/Fed Cup, 7 Tour finals, … |
[].tournament.country | string | Country of the tournament: three-letter code, or { name, acronym }. |
[].tournament.court | object | Court surface of the tournament: { id, name } (some routes return only { name }), e.g. { "name": "Hard" }. |
[].tournament.court.name | string | Court surface name, e.g. Hard, Clay, Grass, I.hard. |
[].court | string | Court surface name, e.g. "Hard". |
[].roundId | number | Numeric round ID (see GET /tennis/v2/round): e.g. 4 = First, 5 = Second, 9 = 1/4, 10 = 1/2, 12 = Final; 0–3 are qualifying rounds. |
[].rank | number | Tournament level ID (TourRank). |
[].date | string | Date/time as ISO-8601 UTC. On match rows this is the scheduled or played start; on tournaments, the start date. |
[].type | string | Dataset: atp (men) or wta (women). |
[].odds | object | Odds object documented in the rows below. |
[].odds.id_b_o | number | Archive bookmaker ID: 1 = Marathonbet, 2 = Pinnacle. Archive IDs are their own namespace (live-service bookmaker IDs differ). |
[].odds.total | number | Games-total line that ktb (over) and ktm (under) refer to, or null. |
[].odds.k1 | number | Match-winner odds for player 1 (decimal). |
[].odds.k2 | number | Match-winner odds for player 2 (decimal). |
[].odds.ktb | number | Over odds for the games-total line in total, or null. |
[].odds.ktm | number | Under odds for the games-total line in total, or null. |
[].player1 | object | Player 1 (first-listed player). On completed archive rows (results, match history, H2H) player1 is the winner; live-service responses (point-by-point, statistics) keep the live feed's order, so map sides by name or ID there. |
[].player1.name | string | Player 1 name. |
[].player1.odd | string | Pre-match match-winner odds for this player (decimal), as a string; null when not available. |
[].player1.countryAcr | string | Player 1 country code. |
[].player1.seed | string | Tournament seed as a string, or null when unseeded. |
[].player1.image | string | Player photo path on this API (append to the base URL). |
[].player1.image_p_name | string | Player photo path keyed by player name (alternative to image). |
[].player1.id | number | Player 1 ID. |
[].player2 | object | Player 2 (second-listed player). On completed archive rows player2 is the loser; live-service responses keep the live feed's order. |
[].player2.id | number | Player 2 ID. |
[].player2.name | string | Player 2 name. |
[].player2.odd | string | Pre-match match-winner odds for this player (decimal), as a string; null when not available. |
[].player2.countryAcr | string | Player 2 country code. |
[].player2.image | string | Player photo path on this API (append to the base URL). |
[].player2.image_p_name | string | Player photo path keyed by player name (alternative to image). |
[].h2h | string | Career head-to-head as "player1Wins-player2Wins", e.g. "4-1". |
[].h2hSummary | object | Factual career head-to-head: matchCount, player1Wins, player2Wins. |
[].h2hSummary.matchCount | number | Career meetings between the two players. |
[].h2hSummary.player1Wins | number | Career head-to-head wins of player 1. |
[].h2hSummary.player2Wins | number | Career head-to-head wins of player 2. |
[].modelPrediction | object | SportsAPI365 model win probabilities (ULTRA / MEGA). On FREE / PRO this field is a plan_restricted object (available: false, error, message, requiredPlan: "ULTRA", upgradeUrl). |
[].modelPrediction.available | boolean | true when model probabilities are present; false when not yet available or plan-restricted. |
[].modelPrediction.source | string | Always "sportsapi365" (proprietary model). |
[].modelPrediction.predictedWinnerId | number | Player ID of the predicted winner. |
[].modelPrediction.player1WinProbability | number | Model win probability for player 1 in percent; null when not available. |
[].modelPrediction.player2WinProbability | number | Model win probability for player 2 in percent; null when not available. |
Match Prediction & Analysis Paragraph
Returns data only while the two players have a match on the schedule (today or upcoming); afterwards the response is {}. The example (Medvedev v Atmane, Almaty quarterfinal on 2026-10-23) stops working once that match is played. For a current pair, take two players from Upcoming Matches.
The Match Prediction & Analysis Paragraph endpoint is available exclusively to MEGA plan subscribers and is not included with PRO or ULTRA plans. Restricted calls return HTTP 403 with error: plan_restricted.
/tennis/v2/upcoming/match-prediction/{atp|wta}/{player1}/{player2}atp. Use wta for the women's dataset.Returns the Match Prediction & Analysis Paragraph for this matchup: the H2H Stats Prediction Insights narrative as an HTML list (<ul><li>…</li></ul>, one insight per item) — render it as HTML or strip the tags for plain text. MEGA only. Optional onlyImp=true keeps the high-signal insights.Path Parameter
| Parameter | Required | Type | Description |
|---|---|---|---|
atp|wta | Yes | string | Dataset to query. atp = men's tennis across all supported levels, including Grand Slams, ATP Tour, Challengers and ITF. wta = women's tennis across all supported levels, including Grand Slams, WTA Tour and ITF. There is no separate itf value. |
player1 | Yes | string | First player display name. E.g: Jannik Sinner |
player2 | Yes | string | Second player display name. E.g: Carlos Alcaraz |
Query Parameter
| Parameter | Required | Type | Description |
|---|---|---|---|
includeAll | No | boolean | Include Challenger/ITF and full history where supported. Example: includeAll=true |
onlyImp | No | boolean | When true, returns only the high-signal prediction bullets. Example: onlyImp=true. |
Response Properties
| Field | Type | Description |
|---|---|---|
paragraph | string (HTML) | H2H Stats Prediction Insights narrative as an HTML list: <ul> with one <li> per insight (H2H record, career-best year, recent form, surface, pressure points, opponent quality). Render as HTML, or strip the tags for plain text. |
H2H Prediction Analysis by Player Names
This written matchup analysis is part of the Match Prediction & Analysis Paragraph, available exclusively to MEGA plan subscribers. It is not included with FREE, PRO or ULTRA plans. FREE, PRO and ULTRA receive HTTP 403 with error: "plan_restricted".
Analysis exists only for matches on the schedule (today or upcoming); for other pairs result is null. The example pair and date_only go out of date once that match is played. For a current pair and date, take two players and the date of a row from Upcoming Matches.
/tennis/v2/aggregate/head-to-head/prediction/rawQuery Parameter
| Parameter | Required | Type | Description |
|---|---|---|---|
player1 | Yes | string | First player display name. E.g: Jannik Sinner |
player2 | Yes | string | Second player display name. E.g: Carlos Alcaraz |
date_only | No | string | Target date in YYYY-MM-DD format. Example: 2026-01-01. |
Response Properties
| Field | Type | Description |
|---|---|---|
success | boolean | false when a required parameter is missing (player1 and player2 are both required). |
result | object | null | Prediction analysis for the matchup, or null when none is available for these players / date. |
result.player1 | string | First player as stored for the match (may be either of the names you sent). |
result.player2 | string | Second player as stored for the match. |
result.date | string (ISO-8601 UTC) | Scheduled start of the match the analysis is for. |
result.prediction | string | Plain-text analysis in titled sections (e.g. Second Serve & Return Patterns, Under Pressure & Performance Record, Surface Strength & Player Level, Match Opportunities & Deciding Sets, Event Insights), separated by blank lines. |
result.lastUpdatedAt | string (Unix seconds) | When the analysis was last generated. |
H2H Model Prediction (Win Probabilities) by Player Names
SportsAPI365 model win probabilities require the ULTRA or MEGA plan. FREE / PRO receive HTTP 403 (plan_restricted).
Returns a prediction only while the two players have a match on the schedule (today or upcoming); afterwards result is null. The example pair and date_only go out of date once that match is played. For a current pair and date, take two players and the date of a row from Upcoming Matches.
/tennis/v2/aggregate/head-to-head/model/predictionQuery Parameter
| Parameter | Required | Type | Description |
|---|---|---|---|
player1 | Yes | string | First player display name. E.g: Jannik Sinner |
player2 | Yes | string | Second player display name. E.g: Carlos Alcaraz |
date_only | No | string | Target date in YYYY-MM-DD format. Example: 2026-01-01. |
Response Properties
| Field | Type | Description |
|---|---|---|
success | boolean | false when a required parameter is missing (player1 and player2 are both required). |
result | object | null | null when the matchup is not found. |
result.prediction | object | null | Model prediction for the matchup, or null when none is available yet for these players / date. |
result.prediction.source | string | Always sportsapi365 (proprietary model, not bookmaker-implied). |
result.prediction.player1 / player2 | string | Players in scheduled match order (may differ from the order you sent). |
result.prediction.available | boolean | true when probabilities are present. |
result.prediction.predictedWinner | string | Name of the player the model favours. |
result.prediction.predictedWinnerId | integer | Player ID of the favoured player (same IDs as the rest of the API). |
result.prediction.player1WinProbability / player2WinProbability | number | Win probability in percent for result.prediction.player1 / player2; the two add up to 100. |
Upcoming Filters by Tour
/tennis/v2/upcoming/filters/{atp|wta}atp. Use wta for the women's dataset.Returns the tournament levels for one tour on the upcoming schedule: an array of {rankId, name}. Use rankId (or name) as rank on the upcoming lists. Add include=options for every value the list filters accept: levels, tournaments (tournamentId, with type, rankId, surfaceId, country), surfaces (surfaceId) and tournament countries (country), each with its id or code.Path Parameter
| Parameter | Required | Type | Description |
|---|---|---|---|
atp|wta | Yes | string | Dataset to query. atp = men's tennis across all supported levels, including Grand Slams, ATP Tour, Challengers and ITF. wta = women's tennis across all supported levels, including Grand Slams, WTA Tour and ITF. There is no separate itf value. |
Query Parameter
| Parameter | Required | Type | Description |
|---|---|---|---|
include | No | string | Optional. options returns an object instead of the level array: levels, tournaments, surfaces and countries, the values the upcoming list filters accept. Omitted: the level array, as before. Example: include=options. |
Response Properties
| Field | Type | Description |
|---|---|---|
[] | object | One item of the response; its fields are listed below. |
[].rankId | number | Tournament level ID (TourRank, see GET /tennis/v2/ranking): 0 ITF $10K, 1 Challenger/ITF > $10K, 2 Main tour, 3 Masters, 4 Grand Slam, 5 Davis/Fed Cup, 7 Tour finals, … |
[].name | string | Display name. |
All Upcoming Filters
/tennis/v2/upcoming/filtersQuery Parameter
| Parameter | Required | Type | Description |
|---|---|---|---|
include | No | string | Optional. options returns an object instead of the level array: levels, tournaments, surfaces and countries, the values the upcoming list filters accept. Omitted: the level array, as before. Example: include=options. |
Response Properties
| Field | Type | Description |
|---|---|---|
[] | object | One item of the response; its fields are listed below. |
[].rankId | number | Tournament level ID (TourRank, see GET /tennis/v2/ranking): 0 ITF $10K, 1 Challenger/ITF > $10K, 2 Main tour, 3 Masters, 4 Grand Slam, 5 Davis/Fed Cup, 7 Tour finals, … |
[].name | string | Display name. |