---
title: "Season script report for one WTA player (upsets vs expected)"
method: GET
path: "/v1/players/wta/{player}/prediction-performance"
tags: ["players"]
---

# Season script report for one WTA player (upsets vs expected)

`GET /v1/players/wta/{player}/prediction-performance`

## Request

- Base URL: `https://api.predixsport.com` (the document declares no server; this is the origin it was published from)
- URL: `https://api.predixsport.com/v1/players/wta/{player}/prediction-performance`
- Auth: none declared

Season script report for one player: how often our model's favorite actually lost in their matches (upsets) versus how often the model itself expected it for that exact schedule (the sum of the priced favorite-loses probabilities). `player` accepts the as-observed display name ("Jannik Sinner") or its slug ("jannik-sinner"). Each season row carries actual vs expected upsets, the difference with a 95% interval, and a tier: on_script (fewer upsets than priced, shown on the site as "Straight sets"), in_line ("On serve") or chaos ("Wild card"). Verdicts are SEASON-level by design — being hard to predict does not persist year over year, so there is no career score. `source` distinguishes the as-published daily record (recent seasons) from a strict out-of-sample backtest of the current model (earlier seasons); one source per season, never mixed. Use `/tennis/...` for the ATP tour and `/wta/...` for the WTA tour.

## Path parameters

- `player` string, required

## Query parameters

- `last` integer: How many recent matches to return

## Headers

- `authorization` string, nullable

## Response `200`

Successful Response

- TennisPlayerPerformanceResponse
  - `player` string, required
  - `tour` string, required
  - `seasons` TennisSeasonScript[], required: Newest season first; seasons with 15+ reconciled matches
    - `season` string, required
    - `source` string, required: 'backtest' = strict out-of-sample holdout of the current model; 'production' = the as-published daily record. One source per season, never mixed.
    - `matches` integer, required
    - `wins` integer, required
    - `losses` integer, required
    - `upsets` integer, required: Matches where the model's favorite lost
    - `expected_upsets` number, required: Sum of the priced favorite-loses probabilities across this player's matches — the upset count a calibrated model expects for that exact schedule
    - `extra_upsets` number, required: upsets - expected_upsets (negative = steadier than priced)
    - `ci` number, required: 95% interval half-width on extra_upsets
    - `z` number, required
    - `tier` string, required: 'on_script' (Straight sets, z <= -1.5), 'in_line' (On serve) or 'chaos' (Wild card, z >= 1.5). A SEASON-level verdict: it does not persist year over year and is never a career label.
    - `model_hit_pct` number, required: Share of this player's matches where the model's favorite won
    - `decisiveness_pct` number, required: Average favorite probability in this player's matches
  - `recent_matches` TennisMatchLine[], required: Most recent matches of the newest listed season, newest first
    - `match_id` string, nullable: Prediction file_name — join key across the API
    - `date` string, required
    - `opponent` string, required
    - `won` boolean, required
    - `favorite_prob` number, required: Pre-match probability of the model's favorite (0-1)
    - `upset` boolean, required: True when the model's favorite lost

## Other responses

- `422`: Validation Error

---

[API](https://skmtc.dev/predixsport/apis/predixsport-api.md) · [All operations](https://skmtc.dev/predixsport/apis/predixsport-api/llms.txt) · [OpenAPI document](https://skmtc.dev/predixsport/apis/predixsport-api/revisions/02014aee733d?raw)
