Data model
The SETTO domain tree — organization, tournament, division, round, pool, draw and game — plus the id conventions and the enum values you will switch on.
Everything the External API returns hangs off one tree: an organization owns tournaments; a tournament has divisions (categories) and teams; a division has rounds; a round holds pools (groups, with standings) for round-robin play and draws (brackets) for knockout play; both ultimately contain games, and a finished game has a score with sets. Learn this shape once and the six endpoints stop looking like six unrelated things.
The tree
In prose:
- An Organization owns tournaments. Your token is bound to exactly one.
- A Tournament is one competition. It carries the format (
type), the sport, the lifecyclestatus, dates, and apublicUrl. - A Division is what organizers and players call a categoría: a bracket of
skill level and gender inside the tournament (
Cuarta Fuerza Varonil). It owns the rounds and the price. - A Round is one phase — group play or a knockout stage.
- A Pool is a group inside a round-robin round; it holds the teams in that group and their standings.
- A Draw is a bracket. It contains draw rounds (
Quarterfinals,Semifinals, …) inorder, and each draw round contains its games. - A Game is one match. Finished games carry a score, which carries its sets.
- A Team is a registered entry: a pair in doubles, a single player in singles, and in team leagues a squad linked to a league team.
Identifiers
Every resource exposes a UUID v4 as idx. That is the id you pass in a path
(/v1/external/tournaments/{idx}) and the id you store on your side. The numeric
primary keys SETTO uses internally are never exposed.
Tournaments carry two extra identifiers:
| Field | Example | Use |
|---|---|---|
slug | torneo-apertura-2026 | Human-readable, unique, stable |
publicUrl | https://www.setto.io/t/torneo-apertura-2026 | Canonical public page, ready to link |
Endpoints take idx, not slug. Keep the idx from the list call; use the
slug for display and the publicUrl for links.
Tournament
| Field | Notes |
|---|---|
type | Competition format — see below |
sport | PADEL, TENNIS or PICKLEBALL |
status | Lifecycle — see below |
startDate, endDate | ISO 8601 UTC timestamps |
timezone | IANA zone the schedule was authored in (America/Monterrey), nullable |
isPublic | Whether the public page is reachable — false does not hide it from the API |
isFormatComplete | Whether the organizer finished configuring the format |
matchDays | Number of jornadas, for league-shaped tournaments |
standingColumns | Which statistics the organizer shows in the standings table |
publicUrl | https://www.setto.io/t/{slug} |
organization | { idx, name, slug } — always present |
type
The four formats you will meet most often:
| Value | Shape |
|---|---|
TOURNAMENT | A one-off event: group stage and/or a bracket |
LEAGUE | A season of jornadas between pairs |
TEAM_LEAGUE | A season between squads; a round may have division: null |
INDIVIDUAL_LEAGUE | A season between individual players |
Specialised formats (Americano, express/lucky-loser and pickleball individual
leagues) carry their own type values. Treat type as an open string: switch on
the values you care about and fall through for the rest, rather than asserting
the set is closed.
status
The lifecycle runs in one direction:
DRAFT → UPCOMING → IN_PROGRESS → COMPLETED → ARCHIVEDAll five are returned. DRAFT and ARCHIVED tournaments are visible to your
token even though the public site hides them — filter with the status query
parameter, or drop them client-side, before you render anything public.
Division (categoría)
| Field | Notes |
|---|---|
name | Cuarta Fuerza Varonil |
number | Display order; lists are sorted by it ascending |
color | Hex colour the organizer picked, used across SETTO's UI |
isDoubles | true for pairs, false for singles |
isVisible | false means the organizer hid this category on the public site |
price | Entry price for this category, nullable |
minParticipants, maxParticipants, maxRegistrations | Capacity, all nullable |
tournament | { idx } back-reference |
Hidden is returned, not filtered
A hidden division comes back with isVisible: false rather than being
dropped. The API's job is to tell you the truth; deciding what to show is
yours. The same applies to rounds.
Round
| Field | Notes |
|---|---|
name | Pool Play, Playoffs or Qualifiers |
type | ROUND_ROBIN_ROUND, SINGLE_ELIMINATION_ROUND or QUALIFIERS_ROUND |
number | Order within the division |
isVisible | Same semantics as a division's |
isSetup | Whether the organizer has generated the round's games |
numberOfSets, proSets, playAllSets, pointsPerSet | Scoring rules |
drawSize, numQualifiers, placements | Bracket sizing |
division | { idx, name } — nullable: a TEAM_LEAGUE round can span the whole tournament |
A round-robin round fills pools; a single-elimination round fills draws. Many
rounds fill both games (the flat list) and the nested bracket structure — the
same game can therefore appear twice in one payload, once under games and once
under draws[].rounds[].games[]. De-duplicate on game.idx.
Pool, standing and team stats
A pool is a group: { idx, name, number }, plus teams and standings when
you populate them. A standing carries rank, awardedPoints, its team
reference, and a teamStats object with points, wins, losses, ties,
forfeits, pointsFor / pointsAgainst, setsPointsFor / setsPointsAgainst
and the two computed differences.
About rank
rank is the stored rank as SETTO last computed it. The public site
applies head-to-head and other configured tiebreaks on top when it renders a
standings table, so a table you build from rank alone can differ from the
one on setto.io. If exact parity matters, order by the tournament's own
tiebreak rules (populate=rankedTiebreakRules on the tournament) rather than
by rank.
Draw and draw round
A draw is one bracket: { idx, placement }. placement distinguishes the
main draw from consolation/third-place brackets. Its draw rounds carry a
label (Quarterfinals, Semifinals, Final) and an order; sort by order
to lay the bracket out left to right.
Game
| Field | Notes |
|---|---|
number, displayNumber | Match numbering; displayNumber is what organizers show |
status | UPCOMING, FINISHED, CANCELLED, FORFEIT or BYE |
time | Scheduled kickoff, ISO 8601 UTC, nullable |
courtNumber, court | Court number and, when populated, the court object |
matchDay | Jornada number, for leagues |
homeTeam, awayTeam, winner | { idx, name } references, each nullable |
homeTeamDetails, awayTeamDetails | Placeholder slot description — see below |
score | { home, away, sets[] } when populated |
isRetirement | Whether the match ended in a retirement |
Placeholder slots
In a bracket, a game often exists before its participants are known. Then
homeTeam is null and homeTeamDetails describes where the team will come
from:
{
"label": "Winner of Game 3",
"teamNumber": null,
"poolNumber": null,
"poolRank": null,
"sourceGameNumber": 3,
"sourceResult": "WINNER"
}label is a stored English string. If your site is not in English, render
sourceGameNumber and sourceResult yourself rather than printing label.
Score and sets
{
"idx": "1b9d7c36-4e58-40af-92c1-6d3f8a05b7e2",
"home": 2,
"away": 1,
"sets": [
{ "idx": "…", "number": 1, "home": 6, "away": 4, "isTieBreak": false },
{ "idx": "…", "number": 2, "home": 3, "away": 6, "isTieBreak": false },
{ "idx": "…", "number": 3, "home": 7, "away": 5, "isTieBreak": false }
]
}score.home / score.away are sets won, not points. Per-set points live in
sets[], ordered by number.
Team
| Field | Notes |
|---|---|
name | Álvarez / Peña for a pair, the player's name in singles |
seed, seedNumber | Seeding; nullable, and sorted nulls-last in list responses |
division | { idx, name }, nullable |
players | [{ idx, firstName, lastName, avatar }] when populated — no contact data, ever |
captainProfileIdx | The captain's player-profile idx, when populated |
leagueTeam | { idx, name, color, logo, position, pointsAdjustment } for team leagues |
isWildCard, qualifierStatus, drawAssignment | Qualifier/wildcard bookkeeping |
picture, club, ranking, description | Optional presentation fields |
In a TEAM_LEAGUE, a team belongs to a league team — the squad
(Alemania, Brasil) that accumulates points across the season.
Dates and time zones
Every timestamp is ISO 8601 in UTC with a Z suffix
(2026-09-18T17:00:00.000Z). The tournament's timezone field tells you which
IANA zone the organizer authored the schedule in; convert into it before showing
a kickoff time, or a Monterrey 19:00 match will read as 01:00 the next day.