Brackets for esports
Run the tournament. Let everything else read the bracket.
Single and double elimination, round robin and Swiss. Enter results yourself, or hand teams a link and let them report their own. Either way the bracket advances itself, your site embeds it live, and your bot drives all of it through the same API the website uses.
Four formats, one bracket engine
Matches are stored as a graph with routing pointers, so a result moves the winner and the loser the same way no matter which format generated them. Byes resolve on generation instead of becoming a special case forever.
Single elimination
One loss and you are out. Optional third place match.
Byes are placed by seed, never drawn as empty matches.
Double elimination
A losers bracket, a grand final, and the reset match if you want it.
Losers drop to the exact slot the graph routes them to.
Round robin
Everyone plays everyone, optionally split into snake-seeded groups.
Standings computed with head to head as the tiebreak.
Swiss
Pair by record each round, avoiding rematches where possible.
Median-Buchholz tiebreak, rounds default to ceil(log2(n)).
Everything the event actually needs
Live embeds
One iframe, no script tag, no key. Rendered on the server and updated over SSE while the event runs.
Magic links for teams
Each entrant gets a link that logs them in as themselves. No accounts, no passwords, nothing to reset at 2am.
Optional self-reporting
Hand out entrant links and both sides report. Agreement advances the bracket automatically, disagreement flags a dispute instead of a coin flip.
Organiser always wins
Score every match yourself if you prefer, and override any submission or dispute, with optimistic locking so two admins cannot quietly overwrite each other.
Searchable and public
Public tournaments are browsable and searchable by name, game, format and status. Unlisted stays link-only, private stays yours.
Audit trail
Every advancement records who did it, with which credential, and when. Months later that question still has an answer.
Webhooks that can be trusted
HMAC-SHA256 signed, timestamped against replay, and refused at registration if the URL points inside the network.
Seeding you control
Standard fold, random with a reproducible seed, or exactly as entered.
Standings included
Round robin and Swiss return computed standings with the bracket, so nobody maintains a spreadsheet.
An API, not an export button
There is no private admin API. The dashboard, the public page and the embed all call the endpoints below, which means the documented surface is the whole surface. Bearer keys, idempotent writes, optimistic locking on results, signed webhooks and a live SSE feed.
- Bearer keys scoped to their owner, and unable to mint more keys
- Idempotency-Key on every POST, so a retry cannot advance a bracket twice
- expectedVersion on results, so concurrent organisers get a 409 not a corrupt bracket
- Server-Sent Events for live updates, no polling loop to write
- 404 instead of 403 on brackets you may not see, so ids cannot be enumerated
# Create, fill, start. Three calls.
curl -X POST https://gauntletbrackets.com/api/v1/tournaments \
-H "Authorization: Bearer gt_live_..." \
-H "Content-Type: application/json" \
-d '{"name":"Spring Invitational","format":"double_elim"}'
curl -X POST https://gauntletbrackets.com/api/v1/tournaments/$ID/participants \
-H "Authorization: Bearer gt_live_..." \
-H "Content-Type: application/json" \
-d '{"names":["Vortex","Halcyon","Nine Lives","Kestrel"]}'
curl -X POST https://gauntletbrackets.com/api/v1/tournaments/$ID/start \
-H "Authorization: Bearer gt_live_..." \
-H "Idempotency-Key: start-$ID"
# Then follow along without polling.
curl -N https://gauntletbrackets.com/api/v1/tournaments/$ID/streamStart in about a minute
Sign in with Discord, paste your entrant list, hit start. Share the link, drop the embed in your site, and score the matches from the dashboard, or hand out entrant links and let the teams do it.
Sign in with Discord