draw on the match:
Group stage
draw: "group". Teams are drawn into groups and play a round robin of ties.Main draw
draw: "main". The knockout for the title, from the first bracket round to the final.Placement
draw: "placement". Every other knockout tie, played for a position.format: "teams", and it is also a filter:
format: "pairs", so a single equality check tells you which of the two models applies.
The tie
This is the part to model carefully, and it works the same way in all three phases. One meeting between two teams comes back as three matches, and each one carries atie object saying which meeting it belongs to:
So the three rubbers of a tie are the matches that share a
tie.id, and tie.score and tie.winner describe the tie rather than the match, so all three carry the same values and one of them is enough to know how the meeting went.
Do not confuse them with the match’s own winner, which says who won that rubber: it is team_1 or team_2, the same two sides as in tie, so a rubber with winner: "team_2" was won by the team in tie.team_2.
The tie key is only present when the tournament is format: "teams"; on any other tournament it is absent from the payload, not null.
The rubber that is not played
When a team takes the first two rubbers, the third no longer decides anything and is not played. The match still exists, with both pairs listed, and carries the statusnot_played: no score, no winner and no court.
The three phases
Group stage
The tournament opens with a round robin. Teams are split into groups, and each team meets every other team in its group once. There is no bracket here, so a result is only worth what it does to the table. In the API this isdraw: "group", with round: 0 and round_name: "Group stage", and it is requested explicitly because listings return the main draw by default:
tie.id and read score and winner off it.
Main draw
Once the groups are done the tournament becomes a knockout, and the ties that lead to the title aredraw: "main", the same value a regular tournament uses for its main draw. round means what it always means: 4 quarterfinals, 2 semifinals, 1 final.
That last column is the story of the evening, not a field:
tie.score reports the tie as it stands, so all three rubbers now read 2–1 with tie.winner on Argentina’s side.
Argentina lost the opening rubber and still took the title. A team can win a tie while losing a match, and a player can be a champion having lost their rubber.
That is why winners on the tournament resource holds six players per category instead of two: the three pairs of the winning team, listed as consecutive pairs and linked one by one through connections.pair.
Placement
A team knocked out of the title bracket does not go home: it keeps playing for a position. Those ties aredraw: "placement", and they cover everything that is not the path to the title, from the third place match to the brackets that rank the rest of the field.
round values, so round alone does not identify a stage: a round: 2 tie is a semifinal of the title bracket when draw is main, and a semifinal of a placement bracket when draw is placement. round_name reads Placement for all of them.
If your app only follows the title race, skipping this draw is enough. If it shows the full standings of the event, this is where every position below the podium is decided.
Working with the API
draw takes one phase at a time, or all for everything in a single list:
?draw=all&sort_by=round, the draws come back in the order the tournament plays them, group stage, then main draw, then placement, and the default order_by=desc walks each one chronologically; order_by=asc reverses the whole list, final first. Within a team tournament the three rubbers of a tie always come back together and in tie.rubber order, whatever you sort by, unless a page boundary splits them, so still group by tie.id when you paginate.
The tournament matches endpoint also filters on the parts of a tie:
tie[id] is the one to reach for from a single match: take the tie.id you already have and the request gives you back the rest of the meeting. tie[team_1] and tie[team_2] match one side of the tie, so a team’s full campaign is the union of both. Values are matched case-insensitively.
To keep a local copy in sync, remember that each draw has its own webhook family: an existing match.* subscription keeps delivering the main draw only, and match.group.* and match.placement.* carry the rest. Polling works the same on every draw with updated_after, as described in Data Synchronization.
Integration recap
Everything you already do with a tournament keeps working. What a team tournament adds is one level of grouping between the draw and the match:The fields and their values
The tie in your model
Give the tie a row of its own, keyed bytie.id, holding group, team_1, team_2, score and winner. Each match then points at it and keeps its rubber. Kept as a blob on the match instead, every table, bracket and standings query has to regroup the rubbers in memory first, and a table built from matches rather than from ties reads a 2–1 as a draw.
Checking it works
Tournament258, the 2024 edition, is complete in the API and makes a good fixture to assert against:
- The tournament is
format: "teams", and every match carries atie. - Grouping by
tie.idyields groups of exactly three matches, all carrying the sametie.scoreandtie.winner. ?draw=main&round=1&category=menreturns the three rubbers of the final, withtie.scoreat 2–1 andtie.winneron Argentina’s side.winners.menholds six players, three pairs.- A tie settled 2–0 leaves its third rubber with
status: "not_played"and no winner, so the parser has to accept a match with both pairs and no result.
What not to do
- Do not add endpoints or a second code path. Same routes, same authentication, same pagination, same
updated_atpolling. A team tournament is the tournament and match resources you already read. - Do not compute ratings or statistics from rubbers. A pairing put together for a team lasts one week, so the API leaves team events out of the Elo and out of player and pair statistics, title bracket included. Recomputing them locally reintroduces exactly what was excluded on purpose.
- Do not create pairs from a team line-up. Those pairings do not appear in pair listings or in a player’s partner list, and they never become a player’s current partner. You can still request one by id with
/api/pairs/{player_1}-{player_2}. - Do not require
tie. It is absent on every pairs tournament, which is most of the calendar. - Do not expect three results per tie. A tie settled 2–0 has one rubber with no winner.
Frequently asked questions
Which competitions are team tournaments?
Which competitions are team tournaments?
Any event where the entrants are teams rather than pairs, from national team championships such as the FIP World Cup to franchise competitions. They share the same skeleton: a group stage, then a knockout for the title and a set of ties played for position.
How do I tell a team tournament from a regular one?
How do I tell a team tournament from a regular one?
format: "teams" on the tournament, and a tie object on its matches. Both are stable: a tournament does not change format, and the tie key never appears on a pairs tournament.Why are there three matches where I expected one?
Why are there three matches where I expected one?
Because a tie is three rubbers. Group them by
tie.id and order them with tie.rubber.Can a team win a tie and lose more sets than its opponent?
Can a team win a tie and lose more sets than its opponent?
Yes. The tie is decided on rubbers won and nothing below that counts, so a 2–1 in straight sets and a 2–1 from a set down are the same result.
Why are the seeds null?
Why are the seeds null?
Team tournaments carry no seeding, so both sides of every match come back
null.Do team matches have live scores and stats?
Do team matches have live scores and stats?
They follow the coverage of the tournament, exactly like any other match. Where the event has detailed coverage, rubbers carry
stats and live connections and stream point by point over the WebSocket channel. A rubber that was never played has nothing to stream.Next steps
Tournament matches endpoint
Filters for
draw, round, category and the parts of a tie.Match statuses
What
not_played means, and which statuses are permanent.Webhooks
The event families that deliver each draw.
Data synchronization
How to keep a local copy in sync across every draw.