# Badminton API manual

World badminton as JSON: results and full draws since 1899, players, head to head, world rankings, venues, opening and closing odds, our own rating and analyses, and live scores. 45 endpoints and an MCP server, one key. Built 2026-10-12 from the list the API runs on.

- Base address: https://api.badmintonapi.com/v1
- MCP server: https://api.badmintonapi.com/mcp
- Documentation: https://badmintonapi.com/documentation
- Status: https://badmintonapi.com/status
- Operator: DeveloperData.net, Empire Tower, 41st Floor, Unit 4106-7, South Sathorn Road, Yannawa, Sathorn, Bangkok 10120, Thailand. support@developerdata.net

## Before anything else

- Every call sends a key in a header: `Authorization: Bearer <key>` or `X-API-Key: <key>`. A key in the address is refused.
- Every answer is `{"data": ..., "meta": {...}}` or `{"error": {"code", "message", "docs"}}`. Times are UTC; days are YYYY-MM-DD.
- Ids say what they are: `pl_` player, `tr_` tournament edition, `mt_` draw match, `ev_` result or fixture, `vn_` venue. Countries are IOC codes. Find ids with `/v1/search`.
- A field your plan does not include is `null`, never missing, and `meta.note` names the plan that has it.
- Data is factual: results, draws, prices and ratings. Our rating and win chance are our own model, not official BWF figures.
- Team events (Thomas, Uber and Sudirman Cups) are held tie by tie at /v1/tournaments/{id}/ties; para-badminton matches carry their sport class. Not included: draws the record does not hold, and prices before June 2012.

## Plans

| Plan | Price | Calls a minute | Calls a day | Endpoints |
|---|---|---|---|---|
| Free key | Free | 10 | 50 | 9 |
| Archive | $19 a month | 60 | 5,000 | 38 |
| Odds | $49 a month | 120 | 20,000 | 43 |
| Live | $149 a month | 300 | 100,000 | 45 |

Each plan has every endpoint of the plans before it. Prices in US dollars; card charges appear as DEVELOPERDATA.NET.

## Coverage

- Seasons with draws: 118, from 1899 to 2026.
- Draw matches: 129,194 across 1,141 tournament editions.
- Years with no draws held: 1915, 1916, 1917, 1918, 1919, 1942, 1943, 1944, 1945, 1946.
- Layers from: draws 1899, game scores 1899, odds 2012, live 2026.
- Prices start 2012-06-13. The 1,407 feed results before that (from 2009-03-03) have none; /v1/predict with a date gives our rating's fair price for them, a model and not a market price.
- Before the full lists, the top of each world ranking list is held week by week from 2012-08-28 (1,360 weekly top lists, about 20 places deep): /v1/rankings with an earlier date answers from them, with meta.full false.
- Full weekly ranking lists are kept from 2026-09-21; the world number one is held for every week from 2009-10-01 (/v1/rankings/number-ones).

## Rate limits

Limits count per key; the day resets at 00:00 UTC. Every answer carries `X-RateLimit-Limit`, `X-RateLimit-Remaining`, `X-RateLimit-Reset` (Unix time) and `X-Quota-Remaining`. A 429 carries `Retry-After` in seconds: `rate_limited` means too many this minute, `quota_exceeded` means today's calls are used and `error.resets_at` says when they return. A refused call is not counted. `/v1/usage` is never counted.

## Errors

| Status | Code | Meaning |
|---|---|---|
| 400 | `bad_request` | A value was the wrong shape; the message names it. |
| 401 | `unauthorized` | No key, an inactive key, or a key in the address. |
| 403 | `upgrade_required` | The endpoint comes with a higher plan; error.plan names it. |
| 404 | `not_found` | No such endpoint, or nothing with that id. |
| 422 | `unknown_parameter` | A parameter the endpoint does not take; error.allowed lists those it does. |
| 429 | `rate_limited` | Too many calls this minute; wait Retry-After. |
| 429 | `quota_exceeded` | Today's calls are used; they return at error.resets_at. |
| 500 | `server_error` | Our fault; it is logged. |

## Pages of results

Lists come 50 at a time, up to 200 with `per_page`. Use `page` (meta has `total`, `total_pages`, `next_page`, `prev_page`) or pass `meta.next_cursor` back as `cursor` until it is null.

## Endpoints

### Search and countries

One search across every name, and every nation that plays.

#### Search: `GET /v1/search`

Find players, pairs, tournaments, series, countries, venues and cities by name, in one call. Accents and capitals do not matter; "Name / Name" finds both players of a pair; a year picks that edition.

- Plan: Free key. MCP tool: `search`
- Example: `https://api.badmintonapi.com/v1/search?q=axelsen`

| Parameter | In | Type | Required | Default | Allowed | What it does |
|---|---|---|---|---|---|---|
| `q` | query | text | yes |  |  | what to look for: "axelsen", "lee chong wei", "all england 2023", "istora" |
| `kind` | query | text | no |  | player, tournament, series, country, venue, city | only this kind: player, tournament, series, country, venue or city |
| `limit` | query | whole number | no | 10 |  | most results (for each player of a pair) |

Returns: `kind` (player, tournament, series, country, venue or city); `id` (The id: pl_, tr_, mt_, ev_ or vn_, never changing); `name` (The name as held); `country` (IOC country code, like DEN, or null); `score` (How well the name matched, 30 to 100).

#### Countries: `GET /v1/countries`

Every country with players held: players, active players, and titles by discipline.

- Plan: Free key. MCP tool: `list_countries`
- Example: `https://api.badmintonapi.com/v1/countries`

Returns: `code` (The IOC country code, like DEN); `name` (The name as held); `players` (How many players are held for the country); `active_players` (Players with a match in the last two years); `first_year` (The first year a player from the country appears); `titles` (Finals won); `titles_by_discipline` (Titles in MS, WS, MD, WD and XD).

#### Country profile: `GET /v1/countries/{code}`

One country by its IOC code: titles by discipline, its most successful players, recent titles and the editions it hosted.

- Plan: Archive. MCP tool: `country_profile`
- Example: `https://api.badmintonapi.com/v1/countries/DEN`

| Parameter | In | Type | Required | Default | Allowed | What it does |
|---|---|---|---|---|---|---|
| `code` | path | IOC code | yes |  |  | The country, like DEN. |

Returns: `code` (The IOC country code, like DEN); `name` (The name as held); `players` (How many players are held for the country); `active_players` (Players with a match in the last two years); `titles` (Finals won); `titles_by_discipline` (Titles in MS, WS, MD, WD and XD); `top_players` (The most successful players); `recent_titles` (The latest titles, with players); `hosted` (Editions staged, or hosted by a country).

### Results and calendar

Yesterday, today, the fixtures ahead and the season's calendar.

#### Yesterday's results: `GET /v1/results/yesterday`

Every match finished yesterday (UTC), with scores and closing prices.

- Plan: Free key. MCP tool: `yesterdays_results`
- Example: `https://api.badmintonapi.com/v1/results/yesterday`

Returns: `id` (The id: pl_, tr_, mt_, ev_ or vn_, never changing); `tournament` (The tournament: id, name and year); `discipline` (MS, WS, MD, WD or XD); `team_event` (True for a tie in a team event); `start` (The first day or start time); `status` (scheduled, live, finished; or finished, in_progress, upcoming); `side1` (The first side: players and seed); `side2` (The second side: players and seed); `sets` (Games won by each side); `games` (Game scores, like [[21,17],[19,21],[21,15]]; side 1 first unless stated); `winner` (The winning side: 1 or 2, or its players); `match` (The mt_ id of the draw match); `odds` (Prices: bookmakers counted, opening, closing and best prices, the market's chance and margin. Odds plan); `duration_min` (How long a finished match lasted, in minutes, from its start to its final point; null until it has finished, and for older matches whose record keeps no end time).

Held back below their plan: `odds` (Odds).

#### Results on a day: `GET /v1/results`

Matches finished on a day. The free key covers yesterday and today; Archive covers every day held.

- Plan: Free key. MCP tool: `results_on_date`
- Example: `https://api.badmintonapi.com/v1/results?date=2026-10-11`

| Parameter | In | Type | Required | Default | Allowed | What it does |
|---|---|---|---|---|---|---|
| `date` | query | date | yes |  |  | the UTC day, YYYY-MM-DD |
| `discipline` | query | text | no |  | MS, WS, MD, WD, XD | MS, WS, MD, WD or XD |
| `page` | query | whole number | no | 1 |  | Which page. |
| `per_page` | query | whole number | no | 50 |  | Results a page, up to 200. |
| `cursor` | query | text | no |  |  | meta.next_cursor from the page before. |

Returns: `id` (The id: pl_, tr_, mt_, ev_ or vn_, never changing); `tournament` (The tournament: id, name and year); `discipline` (MS, WS, MD, WD or XD); `team_event` (True for a tie in a team event); `start` (The first day or start time); `status` (scheduled, live, finished; or finished, in_progress, upcoming); `side1` (The first side: players and seed); `side2` (The second side: players and seed); `sets` (Games won by each side); `games` (Game scores, like [[21,17],[19,21],[21,15]]; side 1 first unless stated); `winner` (The winning side: 1 or 2, or its players); `match` (The mt_ id of the draw match); `odds` (Prices: bookmakers counted, opening, closing and best prices, the market's chance and margin. Odds plan); `duration_min` (How long a finished match lasted, in minutes, from its start to its final point; null until it has finished, and for older matches whose record keeps no end time).

Held back below their plan: `odds` (Odds).

#### Fixtures: `GET /v1/fixtures`

Matches scheduled next and those under way, soonest first.

- Plan: Free key. MCP tool: `upcoming_matches`
- Example: `https://api.badmintonapi.com/v1/fixtures`

| Parameter | In | Type | Required | Default | Allowed | What it does |
|---|---|---|---|---|---|---|
| `discipline` | query | text | no |  | MS, WS, MD, WD, XD | MS, WS, MD, WD or XD |
| `page` | query | whole number | no | 1 |  | Which page. |
| `per_page` | query | whole number | no | 50 |  | Results a page, up to 200. |
| `cursor` | query | text | no |  |  | meta.next_cursor from the page before. |

Returns: `id` (The id: pl_, tr_, mt_, ev_ or vn_, never changing); `tournament` (The tournament: id, name and year); `discipline` (MS, WS, MD, WD or XD); `team_event` (True for a tie in a team event); `start` (The first day or start time); `status` (scheduled, live, finished; or finished, in_progress, upcoming); `side1` (The first side: players and seed); `side2` (The second side: players and seed); `sets` (Games won by each side); `games` (Game scores, like [[21,17],[19,21],[21,15]]; side 1 first unless stated); `winner` (The winning side: 1 or 2, or its players); `match` (The mt_ id of the draw match); `odds` (Prices: bookmakers counted, opening, closing and best prices, the market's chance and margin. Odds plan); `duration_min` (How long a finished match lasted, in minutes, from its start to its final point; null until it has finished, and for older matches whose record keeps no end time).

Held back below their plan: `odds` (Odds).

#### One result or fixture: `GET /v1/events/{id}`

One match from the results and fixtures lists, by its ev_ id.

- Plan: Free key
- Example: `https://api.badmintonapi.com/v1/events/ev_trk0gykq`

| Parameter | In | Type | Required | Default | Allowed | What it does |
|---|---|---|---|---|---|---|
| `id` | path | ev_ id | yes |  |  | Which one, by its id. |

Returns: `id` (The id: pl_, tr_, mt_, ev_ or vn_, never changing); `tournament` (The tournament: id, name and year); `discipline` (MS, WS, MD, WD or XD); `team_event` (True for a tie in a team event); `start` (The first day or start time); `status` (scheduled, live, finished; or finished, in_progress, upcoming); `side1` (The first side: players and seed); `side2` (The second side: players and seed); `sets` (Games won by each side); `games` (Game scores, like [[21,17],[19,21],[21,15]]; side 1 first unless stated); `winner` (The winning side: 1 or 2, or its players); `match` (The mt_ id of the draw match); `odds` (Prices: bookmakers counted, opening, closing and best prices, the market's chance and margin. Odds plan); `duration_min` (How long a finished match lasted, in minutes, from its start to its final point; null until it has finished, and for older matches whose record keeps no end time).

Held back below their plan: `odds` (Odds).

#### Season calendar: `GET /v1/calendar`

A year's tournaments in date order, with dates, city, venue, prize money and whether each is finished, in progress or upcoming.

- Plan: Free key. MCP tool: `season_calendar`
- Example: `https://api.badmintonapi.com/v1/calendar`

| Parameter | In | Type | Required | Default | Allowed | What it does |
|---|---|---|---|---|---|---|
| `year` | query | year | no |  |  | the season; this year when left out |
| `series` | query | text | no |  |  | a series from /v1/series |
| `level` | query | text | no |  | senior, junior, para |  |

Returns: `id` (The id: pl_, tr_, mt_, ev_ or vn_, never changing); `name` (The name as held); `series` (The series, like all-england); `level` (senior or junior); `start` (The first day or start time); `end` (The last day, YYYY-MM-DD, where known); `city` (The host city); `country` (IOC country code, like DEN, or null); `venue` (The arena: id and name); `prize_money` (Prize money as a whole number, as the record gives it); `elevation_m` (Height above sea level in metres (the venue's own, else its host city's); null when not known. Shuttles fly faster in thinner air); `status` (finished, in_progress, upcoming, or unknown when no dates are held).

### Tournaments and draws

Every edition and every draw, first round to final, back to the first All England in 1899.

#### Series: `GET /v1/series`

The tournament series held, with their first and latest years.

- Plan: Free key
- Example: `https://api.badmintonapi.com/v1/series`

Returns: `series` (The series, like all-england); `name` (The series' name); `level` (senior or junior); `first_year` (The first year held); `last_year` (The latest year held); `editions` (How many tournament editions).

#### Roll of honour: `GET /v1/series/{slug}/champions`

The roll of honour of a series: champions and runners-up in every event, year by year, with the players who won it most in meta.

- Plan: Archive. MCP tool: `roll_of_honour`
- Example: `https://api.badmintonapi.com/v1/series/all-england/champions`

| Parameter | In | Type | Required | Default | Allowed | What it does |
|---|---|---|---|---|---|---|
| `slug` | path | series | yes |  |  | The series, like all-england; the list is at /v1/series. |
| `discipline` | query | text | no |  | MS, WS, MD, WD, XD | MS, WS, MD, WD or XD |

Returns: `year` (The year); `tournament` (The edition: id and name); `champions` (The winners in each discipline, with ids. Para badminton has one per sport class, keyed like "MS WH1"); `runners_up` (The beaten finalists, keyed as champions are).

#### Tournaments: `GET /v1/tournaments`

Tournament editions, newest first, with the disciplines and match counts of each.

- Plan: Archive. MCP tool: `find_tournaments`
- Example: `https://api.badmintonapi.com/v1/tournaments`

| Parameter | In | Type | Required | Default | Allowed | What it does |
|---|---|---|---|---|---|---|
| `series` | query | text | no |  |  | a series from /v1/series, like all-england |
| `year` | query | year | no |  |  |  |
| `level` | query | text | no |  | senior, junior, para |  |
| `page` | query | whole number | no | 1 |  | Which page. |
| `per_page` | query | whole number | no | 50 |  | Results a page, up to 200. |
| `cursor` | query | text | no |  |  | meta.next_cursor from the page before. |

Returns: `id` (The id: pl_, tr_, mt_, ev_ or vn_, never changing); `series` (The series, like all-england); `name` (The name as held); `year` (The year); `level` (senior or junior); `disciplines` (The disciplines held); `matches` (Matches played, or the matches themselves).

#### One tournament: `GET /v1/tournaments/{id}`

One tournament edition, with its rounds by discipline and its podium: gold, silver and both bronzes in each event.

- Plan: Archive
- Example: `https://api.badmintonapi.com/v1/tournaments/tr_0574err6`

| Parameter | In | Type | Required | Default | Allowed | What it does |
|---|---|---|---|---|---|---|
| `id` | path | tr_ id | yes |  |  | Which one, by its id. |

Returns: `id` (The id: pl_, tr_, mt_, ev_ or vn_, never changing); `series` (The series, like all-england); `name` (The name as held); `year` (The year); `level` (senior or junior); `disciplines` (The disciplines held); `matches` (Matches played, or the matches themselves); `rounds` (Matches in each round, by discipline); `podium` (Each event's medallists: gold, silver and both bronzes (the losing semi-finalists), each a list of players with id, name and country; empty when the edition has no medal table).

#### Tournament draw: `GET /v1/tournaments/{id}/draw`

A whole draw, first round to final, with seeds, scores and closing prices where held.

- Plan: Archive. MCP tool: `tournament_draw`
- Example: `https://api.badmintonapi.com/v1/tournaments/tr_0574err6/draw?discipline=MS`

| Parameter | In | Type | Required | Default | Allowed | What it does |
|---|---|---|---|---|---|---|
| `id` | path | tr_ id | yes |  |  | Which one, by its id. |
| `discipline` | query | text | yes |  | MS, WS, MD, WD, XD | MS, WS, MD, WD or XD |
| `sport_class` | query | text | no |  |  | para badminton only: one sport class, like WH1 or SL3, or a pair, like WH1-WH2 |

Returns: `id` (The id: pl_, tr_, mt_, ev_ or vn_, never changing); `tournament` (The tournament: id, name and year); `discipline` (MS, WS, MD, WD or XD); `round` (The round, as the draw names it, or its code); `round_code` (R128, R64, R32, R16, QF, SF, 3P or F); `sport_class` (Para badminton only: the sport class played, WH1, WH2, SL3, SL4, SU5 or SH6, or a pair such as WH1-WH2 for doubles; null otherwise); `side1` (The first side: players and seed); `side2` (The second side: players and seed); `games` (Game scores, like [[21,17],[19,21],[21,15]]; side 1 first unless stated); `winner` (The winning side: 1 or 2, or its players); `outcome` (played, retired or walkover); `event` (The ev_ id of the same match in the results feed, when linked); `odds` (Prices: bookmakers counted, opening, closing and best prices, the market's chance and margin. Odds plan).

Held back below their plan: `odds` (Odds).

#### Ties: `GET /v1/tournaments/{id}/ties`

A team event (Thomas, Uber, Sudirman Cup): every tie with its nations, score, date and venue, and the matches inside it.

- Plan: Archive. MCP tool: `team_ties`
- Example: `https://api.badmintonapi.com/v1/tournaments/tr_0574err6/ties`

| Parameter | In | Type | Required | Default | Allowed | What it does |
|---|---|---|---|---|---|---|
| `id` | path | tr_ id | yes |  |  | Which one, by its id. |
| `stage` | query | text | no |  |  | one stage only, as named: Group A, Quarter-finals, Final |

Returns: `stage` (The stage, as named: Group A, Quarter-finals, Final); `round_code` (QF, SF or F in the knockout stage; null in a group); `number` (The tie's place on its page, in the order written); `team1` (The first nation: code and name); `team2` (The second nation: code and name); `score` (Matches won by each nation, [3, 1]); `winner` (The nation that won the tie: 1 or 2); `date` (The day of the tie (YYYY-MM-DD), when known); `venue` (Where the tie was played, as written (the hall, and the court when given)); `matches` (The matches of the tie in order, each as /v1/matches gives it).

#### Draw matches: `GET /v1/matches`

Draw matches by player, tournament, series, year, discipline and round.

- Plan: Archive. MCP tool: `find_matches`
- Example: `https://api.badmintonapi.com/v1/matches`

| Parameter | In | Type | Required | Default | Allowed | What it does |
|---|---|---|---|---|---|---|
| `player` | query | pl_ id | no |  |  |  |
| `tournament` | query | tr_ id | no |  |  |  |
| `series` | query | text | no |  |  |  |
| `year` | query | year | no |  |  |  |
| `discipline` | query | text | no |  | MS, WS, MD, WD, XD | MS, WS, MD, WD or XD |
| `round` | query | text | no |  | R128, R64, R32, R16, QF, SF, 3P, F | R128, R64, R32, R16, QF, SF, 3P or F |
| `with_odds` | query | true or false | no |  |  | true for matches with closing prices only |
| `page` | query | whole number | no | 1 |  | Which page. |
| `per_page` | query | whole number | no | 50 |  | Results a page, up to 200. |
| `cursor` | query | text | no |  |  | meta.next_cursor from the page before. |

Returns: `id` (The id: pl_, tr_, mt_, ev_ or vn_, never changing); `tournament` (The tournament: id, name and year); `discipline` (MS, WS, MD, WD or XD); `round` (The round, as the draw names it, or its code); `round_code` (R128, R64, R32, R16, QF, SF, 3P or F); `sport_class` (Para badminton only: the sport class played, WH1, WH2, SL3, SL4, SU5 or SH6, or a pair such as WH1-WH2 for doubles; null otherwise); `side1` (The first side: players and seed); `side2` (The second side: players and seed); `games` (Game scores, like [[21,17],[19,21],[21,15]]; side 1 first unless stated); `winner` (The winning side: 1 or 2, or its players); `outcome` (played, retired or walkover); `event` (The ev_ id of the same match in the results feed, when linked); `odds` (Prices: bookmakers counted, opening, closing and best prices, the market's chance and margin. Odds plan).

Held back below their plan: `odds` (Odds).

#### One draw match: `GET /v1/matches/{id}`

One draw match.

- Plan: Archive
- Example: `https://api.badmintonapi.com/v1/matches/mt_3bt85wzp`

| Parameter | In | Type | Required | Default | Allowed | What it does |
|---|---|---|---|---|---|---|
| `id` | path | mt_ id | yes |  |  | Which one, by its id. |

Returns: `id` (The id: pl_, tr_, mt_, ev_ or vn_, never changing); `tournament` (The tournament: id, name and year); `discipline` (MS, WS, MD, WD or XD); `round` (The round, as the draw names it, or its code); `round_code` (R128, R64, R32, R16, QF, SF, 3P or F); `sport_class` (Para badminton only: the sport class played, WH1, WH2, SL3, SL4, SU5 or SH6, or a pair such as WH1-WH2 for doubles; null otherwise); `side1` (The first side: players and seed); `side2` (The second side: players and seed); `games` (Game scores, like [[21,17],[19,21],[21,15]]; side 1 first unless stated); `winner` (The winning side: 1 or 2, or its players); `outcome` (played, retired or walkover); `event` (The ev_ id of the same match in the results feed, when linked); `odds` (Prices: bookmakers counted, opening, closing and best prices, the market's chance and margin. Odds plan).

Held back below their plan: `odds` (Odds).

### Players

Careers, partners, rivals, titles, form, game statistics and ranking history.

#### Players: `GET /v1/players`

Players by name, country (IOC code) and gender, most matches first.

- Plan: Archive. MCP tool: `find_player`
- Example: `https://api.badmintonapi.com/v1/players`

| Parameter | In | Type | Required | Default | Allowed | What it does |
|---|---|---|---|---|---|---|
| `q` | query | text | no |  |  | part of a name |
| `country` | query | text | no |  |  | IOC code, like DEN |
| `gender` | query | text | no |  | M, W |  |
| `page` | query | whole number | no | 1 |  | Which page. |
| `per_page` | query | whole number | no | 50 |  | Results a page, up to 200. |
| `cursor` | query | text | no |  |  | meta.next_cursor from the page before. |

Returns: `id` (The id: pl_, tr_, mt_, ev_ or vn_, never changing); `name` (The name as held); `slug` (The name in a web address); `country` (IOC country code, like DEN, or null); `gender` (M or W, from the events played); `first_year` (The first year held); `last_year` (The latest year held); `matches` (Draw matches played); `wins` (Matches won).

#### Player profile: `GET /v1/players/{id}`

One player, with matches and wins by discipline, their best world ranking, and their birth date, playing hand and height where known.

- Plan: Archive
- Example: `https://api.badmintonapi.com/v1/players/pl_9k1rzjad`

| Parameter | In | Type | Required | Default | Allowed | What it does |
|---|---|---|---|---|---|---|
| `id` | path | pl_ id | yes |  |  | Which one, by its id. |

Returns: `id` (The id: pl_, tr_, mt_, ev_ or vn_, never changing); `name` (The name as held); `slug` (The name in a web address); `country` (IOC country code, like DEN, or null); `gender` (M or W, from the events played); `first_year` (The first year held); `last_year` (The latest year held); `matches` (Draw matches played); `wins` (Matches won); `by_discipline` (The same figures split by MS, WS, MD, WD and XD); `career_high` (The player's best world ranking: rank, discipline, date (YYYY-MM-DD, or YYYY-MM when only the month is known) and doubles partner, with the best in each other event in other_events; null when none is known); `number_one` (Time at world number one since 1 October 2009, by discipline: weeks in all, reigns, first and last day (last is null while it goes on) and current; null for a player who never was); `born` (The player's birth date, YYYY-MM-DD; null when not known); `hand` (The hand the player plays with: left or right; null when not known); `height_cm` (The player's height in centimetres; null when not known); `coach` (The player's coach or coaches as their own page names them, comma separated; null when not known).

#### Player matches: `GET /v1/players/{id}/matches`

A player's draw matches, newest first.

- Plan: Archive. MCP tool: `player_matches`
- Example: `https://api.badmintonapi.com/v1/players/pl_9k1rzjad/matches`

| Parameter | In | Type | Required | Default | Allowed | What it does |
|---|---|---|---|---|---|---|
| `id` | path | pl_ id | yes |  |  | Which one, by its id. |
| `year` | query | year | no |  |  |  |
| `discipline` | query | text | no |  | MS, WS, MD, WD, XD | MS, WS, MD, WD or XD |
| `page` | query | whole number | no | 1 |  | Which page. |
| `per_page` | query | whole number | no | 50 |  | Results a page, up to 200. |
| `cursor` | query | text | no |  |  | meta.next_cursor from the page before. |

Returns: `id` (The id: pl_, tr_, mt_, ev_ or vn_, never changing); `tournament` (The tournament: id, name and year); `discipline` (MS, WS, MD, WD or XD); `round` (The round, as the draw names it, or its code); `round_code` (R128, R64, R32, R16, QF, SF, 3P or F); `sport_class` (Para badminton only: the sport class played, WH1, WH2, SL3, SL4, SU5 or SH6, or a pair such as WH1-WH2 for doubles; null otherwise); `side1` (The first side: players and seed); `side2` (The second side: players and seed); `games` (Game scores, like [[21,17],[19,21],[21,15]]; side 1 first unless stated); `winner` (The winning side: 1 or 2, or its players); `outcome` (played, retired or walkover); `event` (The ev_ id of the same match in the results feed, when linked); `odds` (Prices: bookmakers counted, opening, closing and best prices, the market's chance and margin. Odds plan).

Held back below their plan: `odds` (Odds).

#### Doubles partners: `GET /v1/players/{id}/partners`

A player's doubles partners, most matches together first, with wins and titles as a pair.

- Plan: Archive. MCP tool: `player_partners`
- Example: `https://api.badmintonapi.com/v1/players/pl_9k1rzjad/partners`

| Parameter | In | Type | Required | Default | Allowed | What it does |
|---|---|---|---|---|---|---|
| `id` | path | pl_ id | yes |  |  | Which one, by its id. |
| `discipline` | query | text | no |  | MS, WS, MD, WD, XD | MS, WS, MD, WD or XD |

Returns: `partner` (The doubles partner, or null in singles); `discipline` (MS, WS, MD, WD or XD); `matches` (Matches played together); `wins` (Matches won together); `titles` (Titles won together); `first_year` (The first year held); `last_year` (The latest year held).

#### Rivals: `GET /v1/players/{id}/opponents`

The players met most often, with wins and losses against each and the last meeting.

- Plan: Archive. MCP tool: `player_opponents`
- Example: `https://api.badmintonapi.com/v1/players/pl_9k1rzjad/opponents`

| Parameter | In | Type | Required | Default | Allowed | What it does |
|---|---|---|---|---|---|---|
| `id` | path | pl_ id | yes |  |  | Which one, by its id. |
| `discipline` | query | text | no |  | MS, WS, MD, WD, XD | MS, WS, MD, WD or XD |
| `limit` | query | whole number | no | 20 |  |  |

Returns: `opponent` (The player met); `meetings` (Times they met); `wins` (Meetings this player won); `losses` (Meetings this player lost); `last` (The most recent meeting, with score).

#### Titles and finals: `GET /v1/players/{id}/titles`

Every final a player reached, won or lost, newest first, with partner, opponents and score; totals by discipline in meta.

- Plan: Archive. MCP tool: `player_titles`
- Example: `https://api.badmintonapi.com/v1/players/pl_9k1rzjad/titles`

| Parameter | In | Type | Required | Default | Allowed | What it does |
|---|---|---|---|---|---|---|
| `id` | path | pl_ id | yes |  |  | Which one, by its id. |
| `discipline` | query | text | no |  | MS, WS, MD, WD, XD | MS, WS, MD, WD or XD |

Returns: `result` (W or L, or won or runner_up); `tournament` (The tournament: id, name and year); `level` (senior or junior); `discipline` (MS, WS, MD, WD or XD); `sport_class` (Para badminton only: the sport class played, WH1, WH2, SL3, SL4, SU5 or SH6, or a pair such as WH1-WH2 for doubles; null otherwise); `partner` (The doubles partner, or null in singles); `opponents` (The other side's players); `games` (Game scores from this player's side); `match` (The mt_ id of the draw match).

#### Form: `GET /v1/players/{id}/form`

A player's latest results, newest first, with the record over them and the winning or losing run they are on.

- Plan: Archive. MCP tool: `player_form`
- Example: `https://api.badmintonapi.com/v1/players/pl_9k1rzjad/form`

| Parameter | In | Type | Required | Default | Allowed | What it does |
|---|---|---|---|---|---|---|
| `id` | path | pl_ id | yes |  |  | Which one, by its id. |
| `discipline` | query | text | no |  | MS, WS, MD, WD, XD | MS, WS, MD, WD or XD |
| `last` | query | whole number | no | 10 |  | how many matches |

Returns: `result` (W or L, or won or runner_up); `tournament` (The tournament: id, name and year); `date` (The day, YYYY-MM-DD); `discipline` (MS, WS, MD, WD or XD); `round` (The round, as the draw names it, or its code); `opponents` (The other side's players); `games` (Game scores from this player's side); `outcome` (played, retired or walkover); `match` (The mt_ id of the draw match).

#### Game statistics: `GET /v1/players/{id}/stats`

Game statistics from every score held: games and points won, deciding games, extended games (20-all and beyond), comebacks after losing the first game, retirements.

- Plan: Archive. MCP tool: `player_stats`
- Example: `https://api.badmintonapi.com/v1/players/pl_9k1rzjad/stats`

| Parameter | In | Type | Required | Default | Allowed | What it does |
|---|---|---|---|---|---|---|
| `id` | path | pl_ id | yes |  |  | Which one, by its id. |
| `discipline` | query | text | no |  | MS, WS, MD, WD, XD | MS, WS, MD, WD or XD |
| `from` | query | year | no |  |  |  |
| `to` | query | year | no |  |  |  |

Returns: `player` (The player: id, name and country); `filters` (The filters applied); `matches` (Matches played, or the matches themselves); `wins` (Matches won); `win_rate` (Share of matches won); `game_win_rate` (Share of games won); `point_share` (Share of all points won); `deciding_games` (Three-game matches: played, won, rate); `extended_games` (Games where the loser reached 20 (21-point scoring, 2006 on): played, won, rate); `after_losing_first_game` (Matches after losing the first game: played, won, rate); `after_winning_first_game` (Matches after winning the first game: played, won, rate); `retirements` (Matches won or lost by retirement); `walkovers` (Matches given or conceded without play); `by_discipline` (The same figures split by MS, WS, MD, WD and XD).

#### Schedule load: `GET /v1/players/{id}/schedule`

How hard a player's calendar has been: each event played, newest first, with dates, matches, how far they went and the rest days before it; in meta, days since the last event, events and matches in the last 30 to 90 days and back-to-back weeks, as they stood on any day.

- Plan: Archive. MCP tool: `player_schedule`
- Example: `https://api.badmintonapi.com/v1/players/pl_9k1rzjad/schedule`

| Parameter | In | Type | Required | Default | Allowed | What it does |
|---|---|---|---|---|---|---|
| `id` | path | pl_ id | yes |  |  | Which one, by its id. |
| `discipline` | query | text | no |  | MS, WS, MD, WD, XD | MS, WS, MD, WD or XD |
| `date` | query | date | no |  |  | the day to measure from, YYYY-MM-DD (default today); later events are left out |
| `last` | query | whole number | no | 20 |  | how many events |

Returns: `tournament` (The tournament: id, name and year); `level` (senior or junior); `start` (The first day or start time); `end` (The last day, YYYY-MM-DD, where known); `disciplines` (The disciplines held); `matches` (Matches played, or the matches themselves); `wins` (Matches won); `furthest` (The furthest round reached: F, SF, QF, R16, R32, R64 or R128); `title`; `rest_days` (Free days between the end of the player's previous event and the start of this one; null for their first); `back_to_back` (True when this event started within a week of the previous one ending: no free week between); `week_run` (How many events in a row, ending with this one, were played back to back).

#### Ranking history: `GET /v1/players/{id}/rankings`

A player's world ranking over time, list by list, newest first: every list from September 2026, and the weekly top lists back to 2013 for weeks they were in them.

- Plan: Archive. MCP tool: `player_ranking_history`
- Example: `https://api.badmintonapi.com/v1/players/pl_9k1rzjad/rankings`

| Parameter | In | Type | Required | Default | Allowed | What it does |
|---|---|---|---|---|---|---|
| `id` | path | pl_ id | yes |  |  | Which one, by its id. |
| `discipline` | query | text | no |  | MS, WS, MD, WD, XD | MS, WS, MD, WD or XD |

Returns: `date` (The day, YYYY-MM-DD); `discipline` (MS, WS, MD, WD or XD); `rank` (Position in the list); `points` (Ranking points).

#### Head to head: `GET /v1/h2h`

Every meeting of two players, singles or doubles, with the wins of each.

- Plan: Archive. MCP tool: `head_to_head`
- Example: `https://api.badmintonapi.com/v1/h2h?player1=pl_9k1rzjad&player2=pl_hmfabfyf`

| Parameter | In | Type | Required | Default | Allowed | What it does |
|---|---|---|---|---|---|---|
| `player1` | query | pl_ id | yes |  |  |  |
| `player2` | query | pl_ id | yes |  |  |  |

Returns: `player1` (The first player and their wins); `player2` (The second player and their wins); `meetings` (Times they met); `matches` (Matches played, or the matches themselves).

### Rankings and ratings

The world ranking as published, and our own rating and win chance.

#### World rankings: `GET /v1/rankings`

The world ranking for a discipline, the latest or as it stood on a date: every ranked player from September 2026, and for earlier dates back to 2013 the week's top list (about 20 to 25 places; meta.full says which).

- Plan: Archive. MCP tool: `world_rankings`
- Example: `https://api.badmintonapi.com/v1/rankings?discipline=MS`

| Parameter | In | Type | Required | Default | Allowed | What it does |
|---|---|---|---|---|---|---|
| `discipline` | query | text | yes |  | MS, WS, MD, WD, XD | MS, WS, MD, WD or XD |
| `date` | query | date | no |  |  | the ranking in force on this day |
| `page` | query | whole number | no | 1 |  | Which page. |
| `per_page` | query | whole number | no | 50 |  | Results a page, up to 200. |
| `cursor` | query | text | no |  |  | meta.next_cursor from the page before. |

Returns: `rank` (Position in the list); `name` (The entry: a player, or both players of a doubles pair); `players` (The entry's players: id (null when not yet matched to a player), name and country); `points` (Ranking points).

#### World number ones: `GET /v1/rankings/number-ones`

Every world number one since the computer ranking began on 1 October 2009: each reign with its dates and weeks, by discipline, on a date, or for one player.

- Plan: Archive. MCP tool: `world_number_ones`
- Example: `https://api.badmintonapi.com/v1/rankings/number-ones`

| Parameter | In | Type | Required | Default | Allowed | What it does |
|---|---|---|---|---|---|---|
| `discipline` | query | text | no |  | MS, WS, MD, WD, XD | MS, WS, MD, WD or XD |
| `date` | query | date | no |  |  | only the reign in force on this day |
| `player` | query | pl_ id | no |  |  | only this player's reigns |

Returns: `discipline` (MS, WS, MD, WD or XD); `start` (The first ranking day of the reign, YYYY-MM-DD); `end` (The last ranking day of the reign, YYYY-MM-DD; null while it goes on); `weeks` (Weeks in this reign, as the reign is counted); `current` (True for the reign still going); `players` (The number one: one player in singles, both partners in doubles, each with id (null when not in the draws), name and country).

#### Our rating: `GET /v1/ratings`

Our own rating (Elo-style, from every senior result) as a table for a discipline on any date, or one player's rating history. Not an official BWF figure.

- Plan: Archive. MCP tool: `player_ratings`
- Example: `https://api.badmintonapi.com/v1/ratings`

| Parameter | In | Type | Required | Default | Allowed | What it does |
|---|---|---|---|---|---|---|
| `discipline` | query | text | no |  | MS, WS, MD, WD, XD | MS, WS, MD, WD or XD |
| `date` | query | date | no |  |  | the ratings as they stood that day; today when left out |
| `player` | query | pl_ id | no |  |  | one player's history instead of a table |
| `active` | query | true or false | no |  |  | only players rated in the year before the date (default true) |
| `page` | query | whole number | no | 1 |  | Which page. |
| `per_page` | query | whole number | no | 50 |  | Results a page, up to 200. |
| `cursor` | query | text | no |  |  | meta.next_cursor from the page before. |

Returns: `rank` (Position in the list); `player` (The player: id, name and country); `rating` (Our rating, starting at 1500); `matches` (Matches played, or the matches themselves); `last_rated` (The last day of the edition in which the rating last changed (for an edition still under way, the day it is due to end)).

#### Win chance: `GET /v1/predict`

The chance each side wins from our rating, with a fair price and their head-to-head. Singles or doubles, on any date.

- Plan: Odds. MCP tool: `win_chance`
- Example: `https://api.badmintonapi.com/v1/predict?player1=pl_9k1rzjad&player2=pl_hmfabfyf`

| Parameter | In | Type | Required | Default | Allowed | What it does |
|---|---|---|---|---|---|---|
| `player1` | query | pl_ id | yes |  |  |  |
| `player2` | query | pl_ id | yes |  |  |  |
| `partner1` | query | pl_ id | no |  |  | doubles: player1's partner |
| `partner2` | query | pl_ id | no |  |  | doubles: player2's partner |
| `discipline` | query | text | no |  | MS, WS, MD, WD, XD | MS, WS, MD, WD or XD |
| `date` | query | date | no |  |  | the ratings as they stood that day |
| `host` | query | text | no |  |  | the host country's IOC code, like DEN: a side whose players are all from it is moved by the home figure in meta.model.home_edge (rating points; null when testing found none, and it can be below 0) |
| `games` | query | text | no |  |  | in play at one game all: the first two games from side 1, like 21-15,18-21; adds the chance of the deciding game |

Returns: `discipline` (MS, WS, MD, WD or XD); `date` (The day, YYYY-MM-DD); `host` (The host given: code, and home_side (1 or 2, the side whose players are all from it; null when neither or both)); `side1` (Side 1: players, rating, continent (the one its players share, else null), chance and fair price); `side2` (Side 2: players, rating, continent, chance and fair price); `head_to_head` (Meetings between the two sides and the wins of each); `age_gap_years` (Singles: how many years older side 2 is than side 1 on the date (below 0 when side 1 is older), when both birth dates are known; the chance includes the age term (meta.model.age). Null in doubles or when a date is missing); `decider` (With games at one game all: each side's chance of the deciding game (side1, side2), fair_price for each, which side won the second game and by how many points; null without games).

### Venues and cities

The arena and city of every edition held.

#### Venues: `GET /v1/venues`

Arenas that have staged tournaments held, most editions first, by country, city or name, with their height above sea level.

- Plan: Archive. MCP tool: `find_venues`
- Example: `https://api.badmintonapi.com/v1/venues`

| Parameter | In | Type | Required | Default | Allowed | What it does |
|---|---|---|---|---|---|---|
| `country` | query | text | no |  |  | IOC code, like INA |
| `city` | query | text | no |  |  |  |
| `q` | query | text | no |  |  | part of the venue name |
| `page` | query | whole number | no | 1 |  | Which page. |
| `per_page` | query | whole number | no | 50 |  | Results a page, up to 200. |
| `cursor` | query | text | no |  |  | meta.next_cursor from the page before. |

Returns: `id` (The id: pl_, tr_, mt_, ev_ or vn_, never changing); `name` (The name as held); `city` (The host city); `country` (IOC country code, like DEN, or null); `editions` (Editions staged there); `first_year` (The first year held); `last_year` (The latest year held); `elevation_m` (Height above sea level in metres (the venue's own, else its host city's); null when not known. Shuttles fly faster in thinner air); `elevation_from` (Where elevation_m comes from: venue (its own height) or city (the host city's); null when not known).

#### Venue profile: `GET /v1/venues/{id}`

One venue and every edition it staged, newest first.

- Plan: Archive
- Example: `https://api.badmintonapi.com/v1/venues/vn_957y5h4h`

| Parameter | In | Type | Required | Default | Allowed | What it does |
|---|---|---|---|---|---|---|
| `id` | path | vn_ id | yes |  |  | Which one, by its id. |

Returns: `id` (The id: pl_, tr_, mt_, ev_ or vn_, never changing); `name` (The name as held); `city` (The host city); `country` (IOC country code, like DEN, or null); `editions` (Editions staged there); `first_year` (The first year held); `last_year` (The latest year held); `elevation_m` (Height above sea level in metres (the venue's own, else its host city's); null when not known. Shuttles fly faster in thinner air); `elevation_from` (Where elevation_m comes from: venue (its own height) or city (the host city's); null when not known); `hosted` (Editions staged, or hosted by a country).

#### Host cities: `GET /v1/locations`

Host cities, most editions first, with their venues and the years they staged tournaments.

- Plan: Archive. MCP tool: `host_cities`
- Example: `https://api.badmintonapi.com/v1/locations`

| Parameter | In | Type | Required | Default | Allowed | What it does |
|---|---|---|---|---|---|---|
| `country` | query | text | no |  |  | IOC code, like ENG |
| `q` | query | text | no |  |  | part of the city name |
| `page` | query | whole number | no | 1 |  | Which page. |
| `per_page` | query | whole number | no | 50 |  | Results a page, up to 200. |
| `cursor` | query | text | no |  |  | meta.next_cursor from the page before. |

Returns: `city` (The host city); `country` (IOC country code, like DEN, or null); `country_name` (The country's name); `editions` (Editions staged in the city); `venues` (How many venues in the city); `first_year` (The first year held); `last_year` (The latest year held).

### Odds and analysis

Opening and closing prices, backtests, upsets, seeds, deciding games and records.

#### Biggest upsets: `GET /v1/analysis/upsets`

The biggest upsets: winners at the longest closing prices, or with the lowest chance by our rating.

- Plan: Odds. MCP tool: `biggest_upsets`
- Example: `https://api.badmintonapi.com/v1/analysis/upsets`

| Parameter | In | Type | Required | Default | Allowed | What it does |
|---|---|---|---|---|---|---|
| `by` | query | text | no | price | price, rating |  |
| `discipline` | query | text | no |  | MS, WS, MD, WD, XD | MS, WS, MD, WD or XD |
| `from` | query | year | no |  |  |  |
| `to` | query | year | no |  |  |  |
| `limit` | query | whole number | no | 25 |  |  |

Returns: `match` (The mt_ id of the draw match); `tournament` (The tournament: id, name and year); `discipline` (MS, WS, MD, WD or XD); `round` (The round, as the draw names it, or its code); `winner` (The winning side: 1 or 2, or its players); `loser` (The losing side's players); `games` (Game scores from the winner's side); `winner_price` (The winner's average closing price); `winner_chance` (The winner's chance by our rating before the match).

#### How seeds perform: `GET /v1/analysis/seeds`

How seeds perform: for each seed, how often they reach the semi-final and final and win the title, and seeded against unseeded round by round.

- Plan: Archive. MCP tool: `seed_performance`
- Example: `https://api.badmintonapi.com/v1/analysis/seeds`

| Parameter | In | Type | Required | Default | Allowed | What it does |
|---|---|---|---|---|---|---|
| `discipline` | query | text | no |  | MS, WS, MD, WD, XD | MS, WS, MD, WD or XD |
| `from` | query | year | no |  |  |  |
| `to` | query | year | no |  |  |  |

Returns: `by_seed` (For each seed: draws, win rate, and how often it reached the semi-final, the final and the title); `by_round` (Seeded against unseeded, round by round: matches and the seed's win rate).

#### Deciding games: `GET /v1/analysis/deciders`

How often matches go to a third game, how often the first-game loser wins, points per game and extended games, by decade or year.

- Plan: Archive. MCP tool: `deciding_games`
- Example: `https://api.badmintonapi.com/v1/analysis/deciders`

| Parameter | In | Type | Required | Default | Allowed | What it does |
|---|---|---|---|---|---|---|
| `by` | query | text | no | decade | decade, year |  |
| `discipline` | query | text | no |  | MS, WS, MD, WD, XD | MS, WS, MD, WD or XD |
| `from` | query | year | no |  |  |  |
| `to` | query | year | no |  |  |  |

Returns: `decade` (The decade, like 1990); `matches` (Matches played, or the matches themselves); `three_games` (Share of matches that went to a third game); `won_after_losing_first_game` (Share of matches won by the side that lost the first game); `points_per_game` (Average points played in a game); `extended_games` (Games where the loser reached 20 (21-point scoring, 2006 on): played, won, rate).

#### Records: `GET /v1/analysis/records`

Records: most titles, most finals, longest winning runs, widest winning margins and most points in a match.

- Plan: Archive. MCP tool: `records`
- Example: `https://api.badmintonapi.com/v1/analysis/records?type=most_titles`

| Parameter | In | Type | Required | Default | Allowed | What it does |
|---|---|---|---|---|---|---|
| `type` | query | text | yes |  | most_titles, most_finals, longest_win_streak, widest_margin, most_points |  |
| `discipline` | query | text | no |  | MS, WS, MD, WD, XD | MS, WS, MD, WD or XD |
| `from` | query | year | no |  |  |  |
| `to` | query | year | no |  |  |  |
| `limit` | query | whole number | no | 25 |  |  |

Returns: `player` (The player: id, name and country); `count` (The record: titles, finals, wins in a row, a margin or points); `first_year` (The first year held); `last_year` (The latest year held); `match` (The mt_ id of the draw match).

#### Market accuracy: `GET /v1/analysis/market`

How accurate the closing market is: favourites' expected and actual win rate by price band, by round and by seeding, the return at the closing price, and each bookmaker's average margin.

- Plan: Odds. MCP tool: `market_accuracy`
- Example: `https://api.badmintonapi.com/v1/analysis/market`

| Parameter | In | Type | Required | Default | Allowed | What it does |
|---|---|---|---|---|---|---|
| `discipline` | query | text | no |  | MS, WS, MD, WD, XD | MS, WS, MD, WD or XD |
| `from` | query | year | no |  |  |  |
| `to` | query | year | no |  |  |  |

Returns: `favourite_by_price` (For each price band: matches, the market's chance, how often favourites won, the return at the close); `favourite_by_round` (The closing favourite by round (R64 to F): matches, the market's expected win rate and the actual one); `favourite_by_seeding` (The closing favourite by seeding, favourite first (seeded_v_unseeded and so on): matches, expected and actual win rate); `bookmakers` (Each bookmaker: its prices, or its average margin).

#### Match odds: `GET /v1/odds/{id}`

Opening and closing prices, bookmaker by bookmaker, for a draw match (mt_) or a results match (ev_): the match winner, and the handicap and total lines in games and points.

- Plan: Odds. MCP tool: `match_odds`
- Example: `https://api.badmintonapi.com/v1/odds/mt_3bt85wzp`

| Parameter | In | Type | Required | Default | Allowed | What it does |
|---|---|---|---|---|---|---|
| `id` | path | mt_ or ev_ id | yes |  |  | Which one, by its id. |

Returns: `match` (The mt_ id of the draw match); `event` (The ev_ id of the same match in the results feed, when linked); `summary` (The market across bookmakers); `bookmakers` (Each bookmaker: its prices, or its average margin); `lines` (Handicap and total lines: kind (handicap or total), unit (games or points), the line (a handicap's is side 1's), each bookmaker's opening and closing prices, and the average close. Handicap prices are side 1 then side 2; total prices are over then under).

#### Backtest a strategy: `GET /v1/backtest`

Run a simple strategy over every settled match with closing prices: strike rate, return and how far it is from chance.

- Plan: Odds. MCP tool: `backtest_strategy`
- Example: `https://api.badmintonapi.com/v1/backtest?strategy=favourite`

| Parameter | In | Type | Required | Default | Allowed | What it does |
|---|---|---|---|---|---|---|
| `strategy` | query | text | yes |  | favourite, outsider, seeded, unseeded, steam, drift | favourite, outsider, seeded, unseeded, steam (the side the market moved to) or drift |
| `discipline` | query | text | no |  | MS, WS, MD, WD, XD | MS, WS, MD, WD or XD |
| `round` | query | text | no |  | R128, R64, R32, R16, QF, SF, 3P, F | R128, R64, R32, R16, QF, SF, 3P or F |
| `from` | query | year | no |  |  |  |
| `to` | query | year | no |  |  |  |
| `min_price` | query | number | no |  |  | lowest average closing price backed |
| `max_price` | query | number | no |  |  | highest average closing price backed |

Returns: `strategy` (The strategy tested); `filters` (The filters applied); `bets` (Bets the strategy placed); `won` (Bets or matches won); `strike_rate` (Share of bets won); `market_chance` (The average chance the closing market gave the side backed); `roi_average` (Return a bet at the average closing price); `roi_best` (Return a bet at the best closing price); `z` (How far the return is from chance, in standard errors; under 2 is noise); `by_year` (The same figures year by year).

### Live

Scores while the shuttle is in the air.

#### Live scores: `GET /v1/live`

Matches under way now, with the score so far.

- Plan: Live. MCP tool: `live_scores`
- Example: `https://api.badmintonapi.com/v1/live`

Returns: `id` (The id: pl_, tr_, mt_, ev_ or vn_, never changing); `tournament` (The tournament: id, name and year); `discipline` (MS, WS, MD, WD or XD); `team_event` (True for a tie in a team event); `start` (The first day or start time); `status` (scheduled, live, finished; or finished, in_progress, upcoming); `side1` (The first side: players and seed); `side2` (The second side: players and seed); `sets` (Games won by each side); `games` (Game scores, like [[21,17],[19,21],[21,15]]; side 1 first unless stated); `winner` (The winning side: 1 or 2, or its players); `match` (The mt_ id of the draw match); `odds` (Prices: bookmakers counted, opening, closing and best prices, the market's chance and margin. Odds plan); `duration_min` (How long a finished match lasted, in minutes, from its start to its final point; null until it has finished, and for older matches whose record keeps no end time).

#### Live stream: `GET /v1/live/stream`

Live scores pushed to you as Server-Sent Events: every match in play on connect, then each match the moment its score, status or prices change, and a heartbeat every 15 seconds. A connection lasts about 5 minutes and counts as one call; reconnect when it ends (EventSource does by itself). Two streams at a time per key.

- Plan: Live
- Example: `https://api.badmintonapi.com/v1/live/stream`
- Answers `text/event-stream` (Server-Sent Events), not JSON: each event has a name and JSON data. The key goes in a header, so read it with fetch or a client that sets headers (the browser's EventSource cannot).

| Parameter | In | Type | Required | Default | Allowed | What it does |
|---|---|---|---|---|---|---|
| `discipline` | query | text | no |  | MS, WS, MD, WD, XD | MS, WS, MD, WD or XD |

Returns: `hello` (Event, on connect: plan, discipline (the filter, or null), closes_at (when the server will end this connection) and check_seconds); `snapshot` (Event, on connect: data, every match in play as /v1/live gives them, and meta with count and at); `match` (Event: one match, as /v1/live gives it, whenever its score, status or prices change; a match that finishes is sent once more with status finished and its final score); `seen` (Event, every 15 seconds when nothing has changed: live (matches in play) and at. It also keeps the connection open through proxies); `bye` (Event, before the server ends the connection: reconnect. EventSource reconnects by itself; a new connection is a new call and starts with a fresh snapshot).

#### Point by point: `GET /v1/events/{id}/points`

Point by point: every rally of a match, game by game, with the score after it, who won it and who served it, and each side's points won on and against serve and longest run. A match in play needs the Live plan. Rallies are being read for every finished match held, newest first.

- Plan: Archive. MCP tool: `match_points`
- Example: `https://api.badmintonapi.com/v1/events/ev_trk0gykq/points`

| Parameter | In | Type | Required | Default | Allowed | What it does |
|---|---|---|---|---|---|---|
| `id` | path | ev_ id | yes |  |  | Which one, by its id. |

Returns: `event` (The match, as /v1/events/{id} gives it); `complete` (True once the match has finished and its rallies were read after it: they are final); `read` (When the rallies were last read, UTC); `games` (Each game: game, score, rallies, and points, every rally in order with n, score after it (side 1 first), won (1 or 2) and server (1 or 2, null when not given)); `totals` (For side1 and side2: points_won, served, won_on_serve, won_receiving and longest_run (the most rallies won in a row, across games)).

### Your key

What your key can do, and what it has used.

#### Your usage: `GET /v1/usage`

Your key: plan, calls today and this month, limits and when they reset. Free to call.

- Plan: Free key
- Example: `https://api.badmintonapi.com/v1/usage`

Returns: `key` (Your key's prefix); `plan` (Your plan); `calls` (Calls today and this month); `limits` (Calls a minute and a day on your plan); `remaining` (Calls left this minute and today); `resets` (When the minute and the day reset); `data` (What your plan covers: every year, or yesterday and today).

## Our rating, and how the win chance is made

An Elo-style rating per player and discipline (MS, WS, MD, WD, XD), our own model and never an official BWF figure. Served by `/v1/ratings` and turned into a chance by `/v1/predict`.

- Everyone starts at 1500. Every senior draw result is replayed in order (tournaments by start date, then round by round), and the whole history is rebuilt every night.
- Before a match: `E_A = 1 / (1 + 10^((R_B - R_A) / 400))`. After it: `R_A + K * (S_A - E_A)`, with S = 1 for a win and 0 for a loss. With the same K on both sides, what one gains the other loses.
- K is 32 for a player's first 20 rated matches in a discipline and 20 after. `matches` on every rating says how many are behind it.
- Doubles: a pair is the average of its two players' ratings, and both move by the same amount. Each discipline is rated apart.
- Counted: winner and loser, opponent strength, order, retirements as the result stands. Not counted: the score, walkovers, tournament level, junior events, time away.
- The published chance uses a scale fitted each night to every rated match since 2000 (now 320, in `meta.model.chance_scale`): `P_A = 1 / (1 + 10^((R_B - R_A) / 320))`. `fair_price` is 1 / chance.
- `date` gives ratings as they stood that day, from earlier results only, so backtests do not see the future. Tables list active players (rated in the 365 days before the date); `active=false` lists everyone.
- Since 2010, across 91,343 matches scored before they were played, the rating's favourite won 71.2%, Brier score 0.1854 (0.25 is a coin toss). On the 10,675 with a closing price: market favourite 75.3% (Brier 0.166), ours 74% (Brier 0.1757).
- Continents: players mostly meet others from their own region, so a rating earned in a smaller pool runs high against the strongest. The chance adds a fitted offset per continent, in rating points with Europe at 0 (Africa -280, Asia +40, North America -50, Oceania -90, South America -110), tested first on matches it was not fitted on. `meta.model.continent_offset` gives them; a side whose players come from two continents takes none.
- Limits: margins are not counted, ratings do not fade with time away, eras and men against women are not comparable.

## MCP

POST JSON-RPC 2.0 to https://api.badmintonapi.com/mcp with `Authorization: Bearer <key>`. `initialize` and `tools/list` need no key. Every tool is read-only and answers the same `{"data", "meta"}` JSON as its endpoint.

```json
{ "mcpServers": { "badminton": { "type": "http", "url": "https://api.badmintonapi.com/mcp", "headers": { "Authorization": "Bearer <your key>" } } } }
```

## Changelog

### 2026-10-10: The 2020 ranking freeze, and how old a list is

- /v1/rankings for a date before our full lists now says how old the list given is (meta.list_age_days: a list stays in force until the next is published). For a date from 16 March 2020 to 10 January 2021 it also carries meta.frozen: the world ranking was frozen then and no new list was published, so the list given is the one that stood through the freeze.

### 2026-10-10: Age in singles chances

- /v1/predict and the win_chance MCP tool now weigh age in singles. Our rating trails a rising player: since 2010 the side younger by 5 years or more won 5.8 points in 100 more often than its rating said. A shift for the side younger by 5 to 9 years and by 10 or more, fitted on 2010 to 2019, lowered the Brier score on 11,261 singles from 2020 on that it never saw, from 0.1826 to 0.1810. It applies when both players' birth dates are known; age_gap_years gives the gap and meta.model.age the shifts.

### 2026-10-09: Win chances between top players

- Between two highly rated sides our chance ran a little too sure: where the market prices a match, our favourites won 1 to 3 in 100 less often than we said. /v1/predict and the win_chance MCP tool now use a scale of their own when the lower-rated side is rated 1512.9 or more. Tested first on 18,751 such matches from 2022 on that it was not fitted on, it lowered the Brier score there from 0.1945 to 0.1939, and on the 3,704 priced among them from 0.193 to 0.192. meta.model.top_level gives the bar and the scale.

### 2026-10-09: Deciding-game chance

- /v1/predict and the win_chance MCP tool take games, the first two games at one game all (21-15,18-21), and add decider: each side's chance of the third game. It starts from the match chance and adds the second game's margin: a second game won by 6 or more carries into the third, and one won by 2 runs slightly the other way. Tested first on 10,597 deciders from 2020 on that it was not fitted on, it scored better there than the match chance alone (Brier 0.2258 against 0.2263). meta.model.decider gives the fit.

### 2026-10-09: Group stages read in full

- Group-stage matches at the Olympics and other events with groups now carry both partners in doubles and every game score: 301 more group matches have their games, and 178 more doubles group matches have both players on each side. They reach /v1/matches, /v1/tournaments/{id}/draw, player records and our rating, and 150 more results matches are now tied to their draw match.

### 2026-10-09: Win chances across continents

- /v1/predict and the win_chance MCP tool now add a fitted offset per continent. A rating earned mostly against players from the same region ran high against the strongest: at neutral venues Asian players beat their ratings by about 12 points in 100 and African players fell about 32 short. Tested first on matches from 2020 on that it was not fitted on, the offset lowered the Brier score there from 0.172 to 0.161. Each side now gives its continent, and meta.model.continent_offset the offsets.

### 2026-10-09: Draw matches held once

- Some draws printed their last rounds twice (once in sections, once in a finals bracket), and those matches were held twice. Each is now held once, with the fuller names, so counts in /v1/players/{id}/stats, /v1/h2h, /v1/analysis/records and our rating no longer count them double. Results matches are also tied to their draw match by the edition's dates, which linked 134 more.

### 2026-10-09: Faster live scores

- /v1/live, /v1/live/stream and the webhooks: matches in play are now read four times a minute, so a point is here in about 15 seconds. meta.poll_seconds is 15.

### 2026-10-09: Live stream

- /v1/live/stream on the Live plan: live scores pushed as Server-Sent Events. Every match in play on connect, then each match the moment its score, status or prices change, a heartbeat every 15 seconds, and a fresh connection every 5 minutes (one call each). Two streams at a time per key; filter with discipline. The Python client has live_stream(), a generator of events that reconnects by itself.

### 2026-10-09: Better calibrated win chances

- /v1/predict and the win_chance MCP tool now use two fitted scales: one for matches where every player has 10 or more rated matches in the event, and one, fitted on its own, when anyone on court has fewer. Both are fitted to every match since 2010, and meta.model gives both (chance_scale and chance_scale_newcomer).

### 2026-10-09: Match duration

- /v1/results, /v1/results/yesterday, /v1/events/{id}, /v1/live and the webhooks now give duration_min: how long a finished match lasted, in minutes, from its start to its final point.

### 2026-10-09: Python client

- /sdk/badmintonapi.py: one file, standard library only, with a method for every endpoint (written from the API as it stands, so a new endpoint is in it at once), iterate() for every page of a list, and the per-minute limit waited out by itself.

### 2026-10-09: Point by point

- /v1/events/{id}/points and the match_points MCP tool: every rally of a match, game by game, with the score after it, who won it and who served it, and each side's points won on and against serve and longest run. Rallies are read while a match is in play (Live plan) and again once it has finished (Archive plan).
- /v1/live is now read twice a minute while a match is in play: meta.poll_seconds is 30.

### 2026-10-09: Webhooks

- On the Live plan, add up to 10 endpoints in your account (Webhooks) and get a signed POST the moment a match starts (match.started), finishes (match.finished) or has its result corrected (result.corrected). The body is the same match as /v1/events/{id}; each delivery is signed in X-BDA-Signature and tried 8 times over about 3 days.

### 2026-10-09: Venue altitude

- /v1/venues, /v1/venues/{id} and /v1/calendar now give elevation_m: the height above sea level of the venue, or of its host city where the venue has none, with elevation_from saying which.

### 2026-10-09: Market accuracy by round and seeding

- /v1/analysis/market now also gives favourite_by_round and favourite_by_seeding: how often the closing favourite won against how often the market expected, round by round and by whether each side was seeded.

### 2026-10-09: Schedule load

- /v1/players/{id}/schedule and the player_schedule MCP tool: every event a player played with its dates, matches, furthest round and the rest days before it, and in meta the days since their last event, events and matches in the last 30, 60 and 90 days and back-to-back weeks, as they stood on any day you name.

### 2026-10-09: Playing hand, height and coach for more players

- /v1/players/{id} now fills hand and height_cm from the player's own page where the open knowledge base has none, and adds coach.

### 2026-10-09: World ranking history back to 2013

- /v1/rankings with a date before September 2026 now answers with that week's top list (about 20 to 25 places), back to 2013 (women's singles from 2012); meta.full is false for these and meta.depth says how deep.
- /v1/players/{id}/rankings now includes every week the player was in those top lists.
- The rankings pages open any of those weeks from their list picker.

### 2026-10-09: World number ones, and OpenAPI

- /v1/rankings/number-ones and the world_number_ones MCP tool: every world number one in each discipline since the computer ranking began on 1 October 2009, reign by reign, with dates and weeks; on a date, or for one player.
- The whole API as OpenAPI 3.1 at https://badmintonapi.com/openapi.json, built from the same list the API runs on.
- /v1/players/{id} now gives number_one: weeks at world number one in each discipline, with reigns and dates.

### 2026-10-05: Handicaps and totals

- /v1/odds/{id} and the match_odds MCP tool now carry lines: every handicap and total line priced before play, in games or points, with each bookmaker's opening and closing price and the average close.
- /v1/players/{id} also gives born, hand and height_cm where known.
- /v1/players/{id} now gives career_high: the player's best world ranking with its event, date and doubles partner, for over 2,300 players.
- /v1/tournaments/{id} now gives podium: gold, silver and both bronzes in each event, for editions with a medal table.
- Draw matches: finals for 480 more editions whose medal tables are all that is published (gold beat silver, no score), and full draws for the junior championships whose event pages were not read before.

### 2026-10-04: Accounts, keys and plans

- Sign in with Google at /login: a free key is made at once, with no card.
- Your account at /account: today's calls, keys (up to five, each with a name, rotated with a day's overlap or revoked), the plans and billing, and every endpoint's calls and errors over 30 days.
- Paid plans in US dollars a month: Archive $19, Odds $49 and Live $149, changed or cancelled at any time. Support and refunds at /support and /refunds.
- An agent skill at /skill.md and /.well-known/agent-skills/index.json teaches AI agents the API and the MCP tools.

### 2026-10-03: Status, as uptime

- /status and /status.json now show whether the website, the REST API and the MCP server are answering, their uptime over the last day, week, month and quarter, and every incident with its updates.
- Each part in /status.json is matched by its key: site, api or mcp. The freshness of results, prices and rankings is no longer on the status page.

### 2026-10-01: Twice the tournaments

- 124,000 draw matches in 92 series, up from 67,000 in 30: the rest of the World Tour, the Grand Prix circuit before it, and the Oceania, African, European, Pan American and Pacific championships and Games.
- Team events: the Thomas, Uber and Sudirman Cups, every tie since 1949 with the matches inside it, in /v1/tournaments/{id}/ties and each player's record.
- Juniors: the Asian, European and African junior championships beside the world title.
- Para badminton: the Paralympic Games and the para world championships, each match with its sport_class (WH1 to SH6). /v1/tournaments/{id}/draw takes sport_class, /v1/series/{slug}/champions keys para finals by class ("MS WH1"), /v1/players/{id}/titles gives each final's class, and level=para lists the editions.
- Group stages: 2,500 round-robin matches from the Olympic and Paralympic Games, the season finals and the European Games, each with its group as the round.
- This season's results for every tournament we carry prices for, and the Super Series years of six more opens.

### 2026-09-30: Our own names throughout

- /v1/rankings: each entry names its players as we hold them, with their player ids and, in doubles, both partners.
- /v1/results, /v1/fixtures and /v1/live: tournaments under our own names, and players under ours wherever the match is in a draw.
- /status.json: each run is named by one of our own job keys.
- /v1/venues and /v1/venues/{id}: meta.source is no longer sent.

### 2026-09-30: MCP server

- 33 tools at https://api.badmintonapi.com/mcp, one for every endpoint worth asking about, with the same key, plans and limits as the API.

### 2026-09-30: Our rating, win chance and five analyses

- /v1/ratings: an Elo-style rating for every player on any date, with each player's history.
- /v1/predict: the chance each side wins, with a fair price and their head-to-head.
- /v1/analysis/upsets, seeds, deciders, records and market.
- /v1/series/{slug}/champions: the roll of honour of every series.

### 2026-09-30: Players in depth

- /v1/players/{id}/partners, opponents, titles, form, stats and rankings.

### 2026-09-30: Search, countries, the calendar and places

- /v1/search: players, pairs, tournaments, series, countries, venues and cities in one call, on every plan.
- /v1/countries and /v1/countries/{code}.
- /v1/calendar: a season in date order with venue, dates and prize money.
- /v1/venues, /v1/venues/{id} and /v1/locations.

### 2026-09-29: The API opens

- 19 endpoints: results, fixtures, tournaments, draws since 1899, players, head to head, world rankings, odds, backtests and live scores.

## About

Badminton API is operated by DeveloperData.net, Bangkok, Thailand. Terms: https://badmintonapi.com/terms. Privacy: https://badmintonapi.com/privacy. Support: support@developerdata.net.
