Padel API#
Padel is played in pairs, and the pair is the unit that competes. Two good players who have been together three months are not the same team as the same two freshly paired, so everything here — the rating, the record, the head-to-head — belongs to the pair, not to the individual. The players are there too, with their world ranking, because a pair is made of two of them.
Base URL: https://sports.bzzoiro.com/padel/api/v2/
What this covers, and what it does not#
The feed carries tournaments, draws, and matches with a set-by-set score.
It does not carry match statistics, betting odds or point-by-point — none
of those exist upstream for padel, at any source we know of. There is no
/odds/ route and no /predictions/ route here, because publishing an empty
endpoint would promise data that does not exist.
History starts in March 2026. That is not where our collection begins; it is where the sport's coverage begins upstream. Nothing earlier is available to anyone.
Draws are published on the day of play. A tournament's matches typically appear a few hours before they start, so the schedule is thin more than a day out — that is the tour's publishing rhythm, not a gap on our side.
Access#
Requires the Sports Addon ($5/month) — it unlocks the tennis, padel, CS2, darts, hockey, basketball and horse racing APIs plus their MCP servers. Get it at /addons/. You also need a free account token from /register/.
Authorization: Token YOUR_API_KEY
List endpoints paginate with limit (default 50, max 200) and offset, and
return {count, next, previous, results}.
Endpoints#
| Endpoint | Description |
|---|---|
GET /padel/api/v2/tournaments/ |
List tournaments, most recent first |
GET /padel/api/v2/tournaments/{id}/ |
Tournament detail with match count |
GET /padel/api/v2/matches/ |
List matches |
GET /padel/api/v2/matches/live/ |
Matches in play right now |
GET /padel/api/v2/matches/{id}/ |
Match detail |
GET /padel/api/v2/pairs/ |
List/search pairs by Elo |
GET /padel/api/v2/pairs/{id}/ |
Pair detail with record |
GET /padel/api/v2/players/ |
List/search players |
GET /padel/api/v2/players/{id}/ |
Player detail |
There is also an MCP server at /padel/mcp/ with seven tools:
list_tournaments, list_pairs, search_pairs, search_players,
list_matches, get_match and get_pair.
Tournaments#
Query parameters
| Param | Type | Description |
|---|---|---|
category |
string | Circuit, e.g. Cupra FIP Tour |
gender |
string | M or F |
limit / offset |
int | Pagination |
start_date and end_date are derived from the tournament's matches — the
tournament itself carries no dates upstream — and are null until at least
one match is known. The list is ordered by end_date, newest first, because
the circuit reuses tournament names every season and an alphabetical list
mixes editions.
curl -H "Authorization: Token YOUR_API_KEY" \
"https://sports.bzzoiro.com/padel/api/v2/tournaments/?gender=F&limit=1"
{"count": 256, "results": [
{"id": 188, "name": "FIP Platinum Lyon Women - Qualification",
"category": "Cupra FIP Tour", "gender": "F",
"start_date": "2026-09-22", "end_date": "2026-09-22"}
]}
Matches#
Query parameters
| Param | Type | Description |
|---|---|---|
status |
string | See the status table below |
tournament_id |
int | Filter by tournament |
pair_id |
int | Matches involving this pair, either side |
limit / offset |
int | Pagination |
Status values#
| Value | Meaning |
|---|---|
scheduled |
Not started |
live |
In play |
finished |
Played to a result |
walkover |
One pair did not play |
retired |
Abandoned mid-match |
cancelled / postponed |
As published upstream |
unresolved |
Ours, not theirs. The scheduled time passed and no result was ever published |
unresolved deserves a note, because it will be a meaningful share of any
full archive you pull. The tour publishes a draw with provisional ids and
republishes the whole thing every time the order of play changes, without
resolving the old entries — the same Round of 32 can leave six rows behind,
none with a score. Calling those scheduled forever would be wrong, and
inventing a result would be worse. unresolved says exactly what is known:
that we never learned how it ended. Filter them out when counting meetings
or building a record — they are not matches that were played.
curl -H "Authorization: Token YOUR_API_KEY" \
"https://sports.bzzoiro.com/padel/api/v2/matches/?status=finished&limit=1"
{"count": 5264, "results": [
{"id": 4168,
"tournament": {"id": 89, "name": "FIP Bronze QNB CUP Izmir Women - Main Draw",
"category": "Cupra FIP Tour", "gender": "F"},
"home_pair": {"id": 1574, "name": "M. Portillo Perez / N. Sluzhiteleva",
"country_code": "", "elo_rating": 1549.7,
"players": [
{"id": 1086, "name": "Maria Portillo Perez",
"country_code": "ES", "country_name": "Spain", "ranking": 84},
{"id": 358, "name": "Nika Sluzhiteleva",
"country_code": "RU", "country_name": "Russia", "ranking": 166}]},
"away_pair": {"id": 215, "name": "R. Lopez Lopez / C. Rose", "elo_rating": 1533.1,
"players": []},
"match_date": "2026-09-19T09:00:00Z", "status": "finished",
"round_name": "Round of 16",
"home_sets": 2, "away_sets": 0,
"sets_detail": [{"set": 1, "home": 6, "away": 3},
{"set": 2, "home": 6, "away": 4}],
"home_games": 12, "away_games": 7,
"winner_pair_id": 1574}
]}
sets_detail is the per-set game score in order. winner_pair_id matches
home_pair.id or away_pair.id, and is null until the match is decided.
Pairs#
Query parameters
| Param | Type | Description |
|---|---|---|
search |
string | Pair name search |
player_id |
int | Every pair this player has been part of |
limit / offset |
int | Pagination |
Ordered by elo_rating, highest first.
{"id": 46, "name": "J. Collantes Guijo / A. Martinez Lopez",
"country_code": "", "elo_rating": 1695.3, "elo_peak": 1695.3,
"players": [
{"id": 90, "name": "Javier Collantes Guijo", "country_code": "ES",
"country_name": "Spain", "ranking": 283},
{"id": 91, "name": "Asier Martinez Lopez", "country_code": "ES",
"country_name": "Spain", "ranking": 220}],
"matches_played": 12, "matches_won": 11, "win_rate": 0.917}
About the Elo#
The rating is recomputed from the whole archive on every run, never incrementally: matches arrive out of order — the calendar first, the back catalogue after — and an incremental rating that receives an old match after a new one stays wrong forever.
There is no home advantage in it. In a draw, "home" is which side of the bracket a pair came out of, not where they are playing. Adding an advantage there would be inventing one.
A pair at exactly 1500 with matches played is not a bug: 1500 is the starting rating, and winning one and losing one against evenly matched opponents returns you to it.
country_code on a pair is filled only when both players share a nationality.
A mixed pair has no flag, which is the truth — it is left empty rather than
guessing one of the two.
Players#
Query parameters
| Param | Type | Description |
|---|---|---|
search |
string | Name search |
limit / offset |
int | Pagination |
curl -H "Authorization: Token YOUR_API_KEY" \
"https://sports.bzzoiro.com/padel/api/v2/players/?search=coello"
{"count": 2, "results": [
{"id": 1250, "name": "Arturo Coello", "country_code": "ES",
"country_name": "Spain", "ranking": 1},
{"id": 1107, "name": "Rodrigo Coello Manso", "country_code": "ES",
"country_name": "Spain", "ranking": 104}
]}
ranking is the individual world ranking as last seen. It arrives inside the
team payload rather than from a rankings endpoint, so there is no ranking
history to query and it is null for players who have not appeared with one.
Photos#
Player photos are served through the image proxy:
https://sports.bzzoiro.com/img/padel/player/{id}/
Use the id from this API. Add ?bg=transparent to strip the white border.