braket.gg
EN

Tournament formats and lifecycle

This chapter covers the two tournament formats, how groups and qualifiers and the small final work, the two team sizes (1v1 and NvM team battles), the ready-up window that takes a match live, and the lifecycle states a tournament and a match move through. Every field named here is a real column on the tournaments, matches, groups, teams, or team_members tables.

The two formats

A tournament's format is one of two values:

World Cup: groups_playoffs

Registrants are split into groups of groupSize (default 4). Within each group a full round-robin is generated: every player faces every other player once. Each match is a scheduled window [opensAt, closesAt], roundDurationHours long (default 48).

Group standings rank players by points, with tiebreakers, using the pure standings math in src/core/. The public standings row exposes played, wins, losses, scoreDiff, and points.

The top qualifiersPerGroup players from each group (default 2) advance to the playoff bracket. Qualifier seeding is computed so that group winners are spread across the bracket rather than meeting early.

Playoffs: single-elimination with a small final

The playoff bracket is single-elimination. Matches carry a stage of playoff, and the last two are final and small_final. The small final is the third-place match: the two losing semifinalists meet so the bracket resolves a clean 1st, 2nd, and 3rd. Bracket wiring is explicit on each match: feedsMatchId / feedsSlot say where the winner goes, and for semifinals loserFeedsMatchId / loserFeedsSlot route the loser into the small final. bracketSlot labels positions like R1M3, SF1, SMALL_FINAL, and FINAL; roundLabel gives the human label ("Quarterfinal 1", "Final").

The top three earn a Steam-visible tournament trophy (trophy_grants, one row per rank 1/2/3, per user so every roster member of a winning team is covered).

Match stages

matches.stage is one of:

Stage Meaning
group A round-robin group match (World Cup only)
playoff A knockout bracket match
small_final The third-place match
final The championship match

1v1 and NvM team battles

A tournament sets a min and max players per side with teamMinPlayers and teamMaxPlayers (both default 1):

The captain-as-side model

Team battles reuse all of the 1v1 bracket math with no changes. The trick is that the captain's user id doubles as the side id everywhere a match references a "player":

For game-verified results, team matches use the same braket.result.v3 protocol as 1v1: the game names any one player on the winning side as winner, and Braket maps that SteamID64 to a side via the registered rosters. Those rosters plus per-side limits are handed to the game via the live-match discovery endpoint (p1Roster, p2Roster, teamMinPlayers, teamMaxPlayers). See The game-client result protocol (dual attestation).

Ready-up windows: how a match goes live

A match does not go live on a timer; it goes live when both sides ready up while the window is open, FaceIt-style. This is the readiness model in src/services/tournamentService.ts.

The readiness fields on a match are p1ReadyAt, p2ReadyAt, and startedAt; sessionNonce is null until the match goes live.

Tournament lifecycle states

tournaments.status moves through:

Status Meaning
draft Being configured; not visible in the public API
registration_open Players may register (up to maxPlayers)
registration_closed Registration ended; group stage not yet generated
group_stage Round-robin groups are being played (World Cup only)
playoffs The single-elimination bracket is being played
completed Podium resolved; completedAt stamped, anchored to a ladder season
cancelled Called off

Draft tournaments are hidden from the public REST API; every other status is visible.

Match lifecycle states

matches.status moves through:

Status Meaning
scheduled Window assigned; not yet live
live Both sides readied; the game is being played; sessionNonce minted
awaiting_result A result was reported/submitted but not yet confirmed by the other side
confirmed Result agreed and final
disputed Conflicting reports/submissions; awaits admin resolution
forfeited Resolved by forfeit (admin)

confirmed and forfeited are the two resolved states; propagation to the next bracket match happens on resolution. How a match reaches confirmed or disputed (report, confirm, dispute, auto-confirm grace, game-client dual attestation, AI video) is the subject of Result verification: the resultSource model.

Ladder and seasons

Completed tournaments with at least 5 participants feed a season ladder: one placement row per participant per completed tournament, with points = 10 * (N - placement + 1) where N is the field size. completedAt anchors the tournament to its ladder season. Community-run "fan bracket" tournaments (isCommunity) are ladder-ineligible by default (ladderEligible), and the studio can flip either. The ladder is exposed at GET /api/v1/ladder (see Public REST API reference).