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, the whole squad in fútbol, 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, PICKLEBALL or FUTBOL
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 standings table shows — fútbol adds the goal columns
sportSettingsFútbol only: modality, extra time, forfeit award — see below. null otherwise
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.

sportSettings

A fútbol (soccer) tournament carries a sportSettings block with the rules the organizer chose. For PADEL, TENNIS and PICKLEBALL the field is null.

FieldNotes
modalityF5, F7, F9, F11 or FUTSAL — squad size and pitch
extraTimeWhether a tied knockout game goes to extra time before a shootout
matchMinutesRegulation playing time, in minutes
h2hRequiresCompleteSubsetSkip the head-to-head mini-league unless every tied pair has met
forfeitScoreGoals awarded to the non-offending side on a forfeit
fairPlayWeights{ yellow, secondYellow, directRed, yellowThenRed }, nullable

Fútbol tournaments are always type: TOURNAMENT, always registered by teams (a captain enters the squad), and never part of a circuit — circuit and circuitCategory stay null.

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 and for fútbol squads
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.

A fútbol round is always round-robin or single elimination, never qualifiers, and always one set: numberOfSets is 1, proSets and playAllSets are false, and pointsPerSet is null.

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.

In fútbol those same counters are goals: pointsFor is goals for, pointsAgainst goals against, and pointsDifference the goal difference. The set-shaped stats — setsPointsFor, setsPointsAgainst and setsPointsDifference — are never written for fútbol and stay 0.

tournament.standingColumns picks which of those statistics the table shows. A fútbol tournament adds GOALS_FOR, GOALS_AGAINST and GOAL_DIFFERENCE — three columns that read the pointsFor / pointsAgainst / pointsDifference fields above — in place of the SETS_* / POINTS_* columns, which it cannot use. The match counters are untouched: a new fútbol tournament is seeded with GAMES_PLAYED, GAMES_WON, GAMES_TIED, GAMES_LOST and those three goal columns. Racket sports keep their sets and points columns and never get the goal ones.

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.

Fútbol adds one criterion to that order: H2HL, the head-to-head mini-league. The teams still level are re-ranked on a sub-table built only from the games they played against each other — points first, then goal difference, then goals for inside that sub-table. It is skipped while those teams have not all met, unless the organizer turned sportSettings.h2hRequiresCompleteSubset off.

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, awayTeamDetailsThe slot's label while its team is unknown — see below
score{ home, away, sets[] } when populated — see below
isRetirementWhether the match ended in a retirement

Slot labels

In a bracket, a game often exists before its participants are known. Then homeTeam is null and homeTeamDetails holds the slot's label, which says where the team will come from:

{
  "label": "Winner of Game 3",
  "labelEs": "Ganador del juego 3",
  "teamNumber": null,
  "poolNumber": null,
  "poolRank": null,
  "sourceGameNumber": 3,
  "sourceResult": "WINNER"
}

label is the stored key, mostly in English; labelEs is the same label as the SETTO dashboard words it in Spanish («Ganador del juego 3», «1ro Grupo A»). For another language, build it from sourceGameNumber / sourceResult (or poolNumber / poolRank) 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.

Fútbol scores

A fútbol result reuses that shape with a different reading. score.home and score.away are regulation goals — the score at full time — and sets holds exactly one element repeating them, with isTieBreak: false. That single synthetic set is deliberate: an integration that sums sets[] keeps working, it just sums goals instead of per-set points.

{
  "idx": "7d2c9a41-0b63-4f18-9e57-3a4c8d015f6b",
  "home": 2,
  "away": 2,
  "sets": [
    { "idx": "…", "number": 1, "home": 2, "away": 2, "isTieBreak": false }
  ],
  "extraTime": { "home": 1, "away": 0 },
  "penalties": null,
  "decisionMethod": "EXTRA_TIME"
}

Three fields only fútbol fills; a racket score returns null for all three:

FieldNotes
extraTime{ home, away } — goals scored during extra time, or null
penalties{ home, away } — kicks converted in the shootout, or null
decisionMethodREGULATION, EXTRA_TIME, SHOOTOUT or WALKOVER (forfeit)

Extra time does not accumulate, kicks are not goals

extraTime counts only what was scored in the extra period, so add it to score.home / score.away for the total: the example above is 2-2 at full time and a 3-2 win after extra time. A shootout is not scoring at all — penalties never reaches the standings, so winning 4-3 on kicks leaves both teams' pointsFor untouched.

A fútbol group game may simply end level: the result stands as a draw and winner is null. A knockout game cannot — a tie goes to extra time (when the organizer enabled it) and then to a shootout, and SETTO derives winner from whichever decider settled it. Read winner and decisionMethod rather than comparing score.home and score.away, which stay at the full-time goals.

Team

FieldNotes
nameÁlvarez / Peña for a pair, the player's name in singles, the squad in fútbol
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