A retirement (a player quits mid-match through injury or illness) can settle a tennis event market without a normal final score. So can a walkover (a player withdraws before play begins). What happens to the market depends on each venue's published resolution rules. Polymarket and Kalshi each define their own. The reliable engineering move is to read that rule from the market itself. Then detect the status change in your live-data feed, so your bot reacts in time.
This article explains the concept and why it matters for anyone building on tennis event markets. It then shows how to detect a retirement or walkover in live match-status data, which is the part we can help with directly. It is educational and observe-only, and it is not financial advice.
What retirements and walkovers mean for a tennis market
A tennis market assumes one player wins the last point. Retirements and walkovers break that assumption:
- A retirement (RET) means play has started, then one player stops. There is a "winner" by the rules of the event, but no completed final set.
- A walkover (W/O) means the match never starts because a player withdraws (illness, injury, admin). One side advances without a ball struck.
For a market, the open questions are: Does a retirement count as a win for resolution? Is a walkover a valid result, a void, or a push? Those answers are not universal. They are set per venue, and sometimes per market.
The honest rule: read the resolution text, don't assume it
Here is the part builders get wrong. We do not set resolution rules and neither should your code assume them.
Each venue publishes its own, and on Polymarket the rule text ships inside the market object itself.
When you pull a tennis market from Polymarket's public Gamma API (https://gamma-api.polymarket.com, tennis tag 864), each market carries a human-readable description and often a resolutionSource. That description is where the venue states the resolution logic, including how edge cases resolve. Read it programmatically instead of hard-coding an assumption:
# Discover live tennis markets on Polymarket (keyless, public)
import requests
r = requests.get("https://gamma-api.polymarket.com/markets",
params={"tag_id": 864, "closed": "false", "limit": 5}, timeout=10)
for m in r.json():
# The resolution logic lives in the market's own text — read it, don't assume.
print(m["question"])
print(" resolutionSource:", m.get("resolutionSource", "(stated in description)"))
The description field is prose written by the venue. Parse it, surface it to yourself, and link back to the venue's official rules. No single interpretation is fact.
Kalshi is a separate, regulated US venue with its own public API and tennis event series. There the equivalent contract lives in that market's rulebook and terms. Read Kalshi's official market rules for how retirements and walkovers settle there. When in doubt, treat the venue's published rule as the source of truth, and your job as detecting the triggering event accurately.
The current wording, verbatim. We keep a dated, side-by-side copy of the rule text from polymarket.com, Polymarket US and Kalshi (ATP/WTA vs ITF). It is in Polymarket & Kalshi tennis retirement/walkover rules (2026). A walkover is 50-50 on polymarket.com, last fair market price on Polymarket US (ITF $0.50) and fair price on Kalshi (ITF $0.50). An in-play retirement pays the advancing player on all three, except Kalshi ITF, where the withdrawing player resolves No.
Where we help: detect the status change in live data
The useful, venue-neutral thing a data feed gives you is early, structured detection that a retirement or walkover has happened.
Every match object carries a closed-vocabulary outcome (completed, retired, walkover, default, abandoned, and null until settled) next to event_status, the feed's own designator (Retired, Walk Over, Cancelled, Postponed, Interrupted), and withdrew, which names the player who stopped or conceded. The lifecycle status (upcoming / live / completed / cancelled) is a different field and does not carry these values. So your bot can see the event in the data feed instead of scraping a scoreboard.
Get a free key at livetennisapi.com/subscribe/free (no card). The free tier gives live matches and scores.
# Live matches with their current status (free tier)
curl -s "https://api.livetennisapi.com/api/public/v1/matches?status=live" \
-H "X-API-Key: YOUR_KEY"
A minimal poller that flags a non-normal ending:
import requests
BASE = "https://api.livetennisapi.com/api/public/v1"
HEADERS = {"X-API-Key": "YOUR_KEY"}
# `outcome` values that mean "this match did not end with a normal final score"
NON_NORMAL = {"retired", "walkover"}
def scan(tracked_ids):
# Re-read the matches you hold positions in. Do NOT scan ?status=live for
# this: a retired match leaves the live list the moment it ends, and a
# walkover declared before first serve was never in it. (ULTRA keys can
# subscribe signals:["status"] on the WebSocket instead of polling.)
for mid in tracked_ids:
r = requests.get(f"{BASE}/matches/{mid}", headers=HEADERS, timeout=10)
r.raise_for_status()
m = r.json()
if m.get("outcome") in NON_NORMAL:
p1 = m["players"]["p1"]["name"]; p2 = m["players"]["p2"]["name"]
print(f"[EVENT] {m['outcome'].upper()} ({m.get('event_status')}) -> "
f"match {mid}: {p1} vs {p2}, withdrew={m.get('withdrew')}")
# your logic: look up the matching market, re-read its resolution
# text, and decide what (if anything) to do per that venue's rules.
scan(TRACKED_IDS)
The pattern: detect the outcome change → find the matching market → re-read that market's own resolution text → act only on what the venue's rule says. The Polymarket tennis toolkit (MIT, observe-only) shows the discovery-and-matching side. It pulls tennis markets from Gamma, matches them to live matches, and joins them into one view you can watch.
Why detection speed matters
Between the moment a player retires and the moment a market formally resolves, the market is often still live and repricing. A bot that only learns about a retirement from the final settlement is reacting late. Reading outcome/event_status from the feed lets you recognize the situation as it happens, while still deferring the market outcome to the venue's rules. An in-play retirement is stamped within seconds of the feed stating it. A walkover declared before first serve arrives through a short pre-start status poll, because no live socket can push a match that never went live. The current cadence is in the API docs' "Status freshness" section. Detection is a data problem (ours). Resolution is a rules problem (theirs). Execution (orders, wallets, keys) is yours.
Related guides
Start from the Polymarket tennis bot pillar guide, and pair this with data-driven tennis trading signals, where retirement risk is one input among several.
Educational only. Not financial advice. Resolution rules are set and published by each venue.