SETTO API

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 lifecycle status, dates, and a publicUrl.
  • 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, …) in order, 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:

FieldExampleUse
slugtorneo-apertura-2026Human-readable, unique, stable
publicUrlhttps://www.setto.io/t/torneo-apertura-2026Canonical 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

FieldNotes
typeCompetition format — see below
sportPADEL, TENNIS or PICKLEBALL
statusLifecycle — see below
startDate, endDateISO 8601 UTC timestamps
timezoneIANA zone the schedule was authored in (America/Monterrey), nullable
isPublicWhether the public page is reachable — false does not hide it from the API
isFormatCompleteWhether the organizer finished configuring the format
matchDaysNumber of jornadas, for league-shaped tournaments
standingColumnsWhich statistics the organizer shows in the standings table
publicUrlhttps://www.setto.io/t/{slug}
organization{ idx, name, slug } — always present

type

The four formats you will meet most often:

ValueShape
TOURNAMENTA one-off event: group stage and/or a bracket
LEAGUEA season of jornadas between pairs
TEAM_LEAGUEA season between squads; a round may have division: null
INDIVIDUAL_LEAGUEA 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 → ARCHIVED

All 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)

FieldNotes
nameCuarta Fuerza Varonil
numberDisplay order; lists are sorted by it ascending
colorHex colour the organizer picked, used across SETTO's UI
isDoublestrue for pairs, false for singles
isVisiblefalse means the organizer hid this category on the public site
priceEntry price for this category, nullable
minParticipants, maxParticipants, maxRegistrationsCapacity, 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

FieldNotes
namePool Play, Playoffs or Qualifiers
typeROUND_ROBIN_ROUND, SINGLE_ELIMINATION_ROUND or QUALIFIERS_ROUND
numberOrder within the division
isVisibleSame semantics as a division's
isSetupWhether the organizer has generated the round's games
numberOfSets, proSets, playAllSets, pointsPerSetScoring rules
drawSize, numQualifiers, placementsBracket 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

FieldNotes
number, displayNumberMatch numbering; displayNumber is what organizers show
statusUPCOMING, FINISHED, CANCELLED, FORFEIT or BYE
timeScheduled kickoff, ISO 8601 UTC, nullable
courtNumber, courtCourt number and, when populated, the court object
matchDayJornada number, for leagues
homeTeam, awayTeam, winner{ idx, name } references, each nullable
homeTeamDetails, awayTeamDetailsPlaceholder slot description — see below
score{ home, away, sets[] } when populated
isRetirementWhether 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

FieldNotes
nameÁlvarez / Peña for a pair, the player's name in singles
seed, seedNumberSeeding; nullable, and sorted nulls-last in list responses
division{ idx, name }, nullable
players[{ idx, firstName, lastName, avatar }] when populated — no contact data, ever
captainProfileIdxThe captain's player-profile idx, when populated
leagueTeam{ idx, name, color, logo, position, pointsAdjustment } for team leagues
isWildCard, qualifierStatus, drawAssignmentQualifier/wildcard bookkeeping
picture, club, ranking, descriptionOptional 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.

On this page