Current score only — lowest-latency REST read (FREE)
This is a POINT-IN-TIME SNAPSHOT: the single current state, overwritten on every score commit. It carries no history and no accumulated statistics. For the SEQUENCE of states — who served each game, hold/break, every score state in forward order — use /history/matches/{matchId}?sequence=clean, which works on a LIVE match, not only a completed one. For in-play statistics use /matches/{matchId}/statistics (ULTRA); they are deliberately not on this object, because they can be further behind the match than the score and must carry their own as_of. ARCHIVED FINALS (since 2026-09-20). The live-score rows behind this read are retired by a 90-day retention sweep, and a match recovered from an official day list may never have had one. When there is no live row at all, a SETTLED match — outcome non-null on the match object: completed, retired, walkover, default, abandoned, unresolved — is answered from its archived final: the same read GET /matches?status=completed already embeds, through the same serializer, so the listing and this endpoint can never disagree about whether a score exists. A live tape always outranks the archive — the fallback is reached only when no publishable live row exists, so a live match reads exactly what it did before. An archived final carries age_seconds: null, observed_age_seconds: null, sources_count: null and accepted_at: null — no clock is claimed for a state nobody watched — and timestamp is null where the archived row has none (a reconstructed final). The Score object carries no data-source label; whether that final was observed or reconstructed is what GET /history/matches/{matchId} reports once, in meta.point_source. 404 is kept for: an upcoming match with no row (nothing to serve yet), a cancelled match that was never played (nothing settled), and a settled match with nothing recorded anywhere — the fallback serves a final that exists, it never invents one. WITHDRAWN STATES (since 2026-09-23). When the legality gate behind this read refuses a state a stream has already published, the verdict object on the score says so: kind, superseded_sequence, reason and safe_to_resume. It is null on an ordinary read. The push feed, the WebSocket and webhooks carry the same judgement as a score_withdrawn frame naming the same sequence, so a stream consumer learns a state was taken back without polling. GET /history/incidents is the published register of data-quality incidents. THE RECOVERY PATH (since 2026-09-25). A consumer that missed the frame cannot get the live verdict back, because it is recomputed over the newest state and returns null as soon as the next state is accepted. Every withdrawal is now recorded durably when the judgement is made: pass ?sequence=N here to have verdict answer for the sequence you hold, and read GET /matches/{matchId}/withdrawals for the whole record on a match, including the frame exactly as the feed sent it. Before 2026-09-20 every settled match older than the retention window answered 404 here (13,437 completed matches from the previous 180 days, 157,170 all time, measured at the change) while the completed listing served its score.
Request
- Base URL: https://api.livetennisapi.com/api/public/v1
- URL: https://api.livetennisapi.com/api/public/v1/matches/{matchId}/score
- Auth: one of:
- HTTP bearer
- API key in header X-API-Key
Path parameters
The match id. Every match route shares ONE id space, so the same value works everywhere matchId appears.
Get it from any match list, where it is the id field of each match object: GET /matches?status=live (in progress), GET /matches?status=upcoming or GET /fixtures (scheduled), GET /matches?status=completed or GET /history/matches (finished).
Ids are stable for the life of a match, so one captured before it starts still resolves after it finishes.
Query parameters
The sequence YOU HOLD for this match, from the push feed, the WebSocket or an earlier read. verdict is recomputed on every read over the newest state, so on its own it says nothing about a sequence that was withdrawn before the next state landed. With ?sequence=N, and only when the read carries no verdict of its own, verdict answers for N from the durable withdrawal record: kind: withdrawn with the recorded reason when we discarded that state, null when we never did. Only a discarded record is re-asserted this way; a deferred state may since have been corroborated and a withheld read described that moment's scan, so neither is. A verdict the read produces itself always wins, because it describes the state being served. Every other field still describes the served state. A non-integer is 400 bad_sequence, never accepted and ignored.
Response
Current score (ULTRA adds win_probability_p1 + danger). On a settled match with no live row, the archived final (since 2026-09-20) — age_seconds, observed_age_seconds, sources_count and accepted_at null.
Example response
{
"win_probability_meta": {
"model_version": "markov-population-2026-08-23"
}
}Changes
No recorded changes to this operation across all 1 revision of this API.