Per-match tape — point-by-point score + per-point model probabilities (BASIC)

The tape is the point-by-point score sequence we hold for this match — every recorded score row including the model fields win_probability_p1 and danger at that point — plus match metadata and the model profiles produced during the match. The model fields here are part of the paid History product by design, distinct from the ULTRA-gated LIVE model fields. One match per request. Requires BASIC on the live API, or the Historical Data API Starter plan and up.

The tape is NOT guaranteed to cover the whole match — check meta.coverage and meta.point_source before backtesting. Rows expanded after the fact from a finished-match point-by-point record carry a null timestamp and null model fields; nothing is ever synthesised.

WORKS ON A LIVE MATCH, not only a completed one. The tape is assembled from whatever has been committed so far, so it is how you read the point-by-point history of a match in progress — including games played before you started watching, where we were already watching them. The LIST endpoint is completed-only; get live ids from /matches?status=live. /matches/{matchId}/score is one state; this is the sequence of states.

get/history/matches/{matchId}

Request

  • Base URL: https://api.livetennisapi.com/api/public/v1
  • URL: https://api.livetennisapi.com/api/public/v1/history/matches/{matchId}
  • Auth: one of:
    • HTTP bearer
    • API key in header X-API-Key

Path parameters

matchIdinteger required

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

sequence'raw' | 'clean'

raw (default) is every row we committed, in commit order — deliberately non-monotonic, since independent sources race and a higher-trust one may correct a lower-trust one backwards. clean returns one row per distinct score state, keeping the last assertion of each, ordered by MATCH PROGRESS (the same ranking our arbiter uses), not by wall clock — so array order is the authoritative point order, and timestamp values may locally disagree with it by a few seconds where a stale re-assertion carried a later clock. Within a game, deuce states legitimately cycle (40-40 ↔ AD) and rank equally, so consecutive clean rows are not guaranteed point-monotonic there; point_winner is only set where the transition is a single attributable point. winner (since 2026-09-22) rides every row of EITHER sequence with the same verdict: on the raw sequence it is judged against the previous raw row, so a re-send reads null there and collapses away here. An unknown value is a 400 bad_sequence.

points'default' | 'complete'

default serves observed rows first — what our own pipeline committed, a SAMPLED record of the match. complete is the explicit opt-out of that precedence for consumers who want every point: where a whole-match reconstruction exists it is served WHOLE, in its own point order, with point_winner (and winner, the same verdict) on every row and null timestamps/model fields per the reconstruction contract. Where none exists, the response is exactly the default read plus meta.points (whose available_complete tells the cases apart) — no error. Cannot combine with sequence=clean (400 bad_combination — the state-key collapse would delete the repeated deuce states a complete point sequence contains). An unknown value is a 400 bad_points; where not yet enabled, complete answers 400 points_read_disabled rather than silently serving the default. coverage and meta.points are orthogonal axes: coverage says how the rows were OBTAINED, points says how COMPLETE the sequence is — completeness is only ever claimed per match, as measured.

Response

The full tape (match + tape + profiles + coverage meta)

profilesobject[]

Model profiles, oldest first (Analysis profile shape)

Example response

{
  "match": {
    "score": {
      "win_probability_meta": {
        "model_version": "markov-population-2026-08-23"
      }
    }
  },
  "tape": [
    {
      "tiebreak_final": [
        2,
        7
      ]
    }
  ]
}

Changes

No recorded changes to this operation across all 1 revision of this API.