Matches
How matches are created, played, and resolved in Tournament Suite.
A match is a head-to-head competition between two sides — either two individual participants or two teams. Matches are generated automatically when a tournament starts and its bracket is built.
Match lifecycle
Each match runs through a match room that coordinates both sides from arrival to result:
waiting → ready check → (map veto) → server provisioning → server ready → in progress → reporting → completed
└── disputed
| Stage | Description |
|---|---|
waiting | Room is open; participants can join but the ready check hasn't started |
ready check | Both sides must confirm they're ready to play |
server provisioning | A game server is being prepared after both sides ready up |
server ready | Connection details are available and participants can join the server |
in progress | The match is actively being played |
reporting | The game is over and a result is awaited |
disputed | A participant has challenged the reported result; queued for organizer review |
completed | Result is confirmed; the winner advances in the bracket |
A match can also end in a forfeit or no-show instead of a normal result, and a room can be cancelled before it completes. Disputes are tracked separately until an organizer resolves them, at which point the match reaches its final result.
Joining the match room and readying up
Once a match is scheduled, participants join its room and confirm they're ready:
POST /api/v1/matches/:matchId/room/join
Authorization: Bearer ACCESS_TOKEN
Content-Type: application/json
{
"role": "player"
}
POST /api/v1/matches/:matchId/room/ready
Authorization: Bearer ACCESS_TOKEN
Content-Type: application/json
{
"readyStatus": "ready"
}
Once every participant is ready, the room automatically moves through server provisioning and into in progress — there's no separate "start" call to make.
Map veto
For disciplines that use map bans/picks, a veto session runs as part of match setup before the server is provisioned. The session walks through ban/pick turns based on the match format (best-of-1/3/5) and produces the map list the server is provisioned with.
POST /api/v1/matches/:matchId/veto/:sessionId/action
Authorization: Bearer ACCESS_TOKEN
Content-Type: application/json
{
"actionType": "ban",
"map": "de_inferno"
}
Veto sessions are created, started, and finalized automatically as part of the match setup flow; organizers can also finalize or cancel a session manually if needed.
Reporting a result
After the game, a participant submits the outcome:
POST /api/v1/matches/:matchId/room/report
Authorization: Bearer USER_ACCESS_TOKEN
Content-Type: application/json
{
"winnerId": "participant-uuid",
"team1Score": 13,
"team2Score": 7,
"evidenceUrls": ["https://cdn.example.com/screenshot.png"]
}
Confirming a result
The opposing participant confirms the reported result:
POST /api/v1/matches/:matchId/room/confirm
Authorization: Bearer OPPONENT_ACCESS_TOKEN
Once both sides confirm — or the organizer approves the result — the match moves to completed and the winner advances in the bracket.
Disputing a result
If a participant disagrees with the reported result, they can open a dispute:
POST /api/v1/matches/:matchId/room/dispute
Authorization: Bearer USER_ACCESS_TOKEN
Content-Type: application/json
{
"reason": "The reported score is incorrect. We won 13-9, not 7-13.",
"evidenceUrls": ["https://cdn.example.com/screenshot.png"]
}
Disputed matches are queued for organizer review. The organizer investigates and sets the final result, resolving the dispute.
Retrieving match details
The licensed public Data API exposes read-only match data for approved integrations, authenticated with a project-scoped API key:
GET /api/v1/data/matches/:id
X-API-Key: YOUR_API_KEY
Response includes both participants, the current score, status, and scheduled time. To get all matches for a tournament:
GET /api/v1/data/tournaments/:id/matches
X-API-Key: YOUR_API_KEY
You can also fetch a match's normalized event feed:
GET /api/v1/data/matches/:id/events
X-API-Key: YOUR_API_KEY
These endpoints require the read:matches key scope.
Real-time match updates
You can subscribe to live match and tournament events two ways:
Webhooks — register a webhook (see Webhooks) to receive:
match.created— a new match was scheduledmatch.started— match has begunmatch.completed— result confirmed, winner setmatch.disputed— result is under reviewmatch.rescheduled— the match's scheduled time changedmatch.forfeited— the match ended in a forfeit
Realtime stream — for lower-latency updates, connect to the /data-stream Socket.IO namespace with your API key (requires the stream:match_events scope) and subscribe to a specific match or tournament:
socket.emit("subscribe", { matchId: "match-uuid" });
socket.on("data:event", (event) => {
// event.matchId, event.tournamentId, event type and payload
});Was this helpful?
