Results and evidence
Report, correct and revert match results, read result history, handle forfeits, collect and review evidence, purge evidence media, and read standings.
A match result is written once and then corrected or reverted as needed. Every write is kept as a revision. Every write recomputes later bracket matches, standings, stage completion and tournament placements in the same transaction.
Report a result
PUT /matches/:matchId/result (results:mutate, Idempotency-Key required) records the outcome of
a match that is ready, playing or already completed.
| Field | Meaning |
|---|---|
expectedRevision | The match's current revision. A stale value is refused with 409 RESULT_STALE. |
submissionKey | Your identifier for this submission. Resending the same key returns the original outcome and changes nothing, even if the match has moved on since. |
entries | One entry per occupant: entrantKey, plus score (score and sets scoring) or rank (rank scoring). |
curl -X PUT "$TOURNAMENT_API_URL/matches/$MATCH_ID/result" \
-H "Authorization: Bearer $TANITAR_API_KEY" \
-H "Idempotency-Key: $(uuidgen)" \
-H "Content-Type: application/json" \
-d '{"expectedRevision":3,"submissionKey":"final-report-1","entries":[{"entrantKey":"ent_a","score":2},{"entrantKey":"ent_b","score":1}]}'The answer carries the updated match, the new result revision, the operation performed
(apply for the first result, correct for any later one) and the cascade: its cascadeId, the
affectedMatchIds, and whether standings were recomputed.
Rules the result must satisfy:
- The entries must name exactly the match's occupants and fit its scoring mode
(
RESULT_ENTRANTS_INVALID,RESULT_ENTRIES_INVALID,RESULT_ENTRIES_INCOMPLETE). - A match that feeds another match cannot end in a draw (
RESULT_DRAW_NOT_PROPAGABLE). - When the match requires evidence, an approved piece of evidence must exist first
(
RESULT_EVIDENCE_REQUIRED). - A
pendingordormantmatch has no result yet (RESULT_MATCH_NOT_READY).
The first result publishes tournament.match.result-applied; a correction publishes
tournament.match.result-corrected. Both are followed by tournament.standings.updated.
Correct a result
To correct a completed match, call PUT /matches/:matchId/result again with the match's current
revision, a new submissionKey and the right entries. The previous revision is superseded, and
everything downstream is recomputed: a later match whose slot changes has its own result
invalidated and its occupants replaced, and a stage or tournament that was complete can reopen.
Revert a result
POST /matches/:matchId/result/revert clears the active result of a completed match and returns it
to ready for replay.
| Field | Meaning |
|---|---|
expectedRevision | The match's current revision. |
submissionKey | Resending the same key replays the original revert. |
reason | Optional, up to 500 characters. |
Dependent slots empty out, their results are invalidated, and standings and placements recompute.
A match with no active result is refused with RESULT_NOT_APPLIED. The revert publishes
tournament.match.result-reverted.
Result history
GET /matches/:matchId/result-revisions (results:read) returns every revision of the match in
order, without pagination. Each revision records its operation (apply, correct, revert, or
invalidate when an upstream correction voided it), its origin (participant for a result you
reported, system for one Tanitar applied), the outcome, the cascadeId, who applied it and
when, and which revision superseded it.
Forfeits
When a tournament sets lifecyclePolicy.matchForfeitTimeoutMinutes, each match starts a forfeit
deadline when it becomes ready. At the deadline, if the match is still ready:
| Situation at the deadline | Outcome |
|---|---|
| Every occupant marked ready | Nothing happens; the forfeit is cancelled. |
| One of two occupants marked ready | That occupant wins. Tanitar applies the result with origin system, without requiring evidence. |
| Anything else | The forfeit expires unresolved; you report the result yourself. |
Each resolution publishes tournament.match.forfeit-resolved with its resolution (applied or
expired_unresolved) and, when applied, the winnerEnrollmentId. Reporting a result before the
deadline cancels the forfeit. See
match readiness.
Evidence
Evidence is a screenshot, a recording or another file an entrant submits to back a result. It is
required before a result is accepted when the match has evidenceRequired (set through the
tournament's resultPolicy). Submitting evidence acts for an entrant and needs
participants:mutate; reviewing and purging it needs results:mutate; reading it needs
results:read.
Upload a file
Files go straight to storage through a short-lived upload link; they never pass through the API.
-
Create an upload intent with
POST /matches/:matchId/evidence/uploads:Field Meaning submittedByEntrantKeyThe entrant submitting. It must occupy the match. contentTypeThe file's media type; types your deployment does not accept are refused with EVIDENCE_CONTENT_TYPE_INVALID.contentLengthSize in bytes; above the limit is refused with EVIDENCE_UPLOAD_TOO_LARGE.checksumSha256Hex SHA-256 of the file. originalFilenameThe file's name. setNumberOptional: the game or set this evidence covers. The answer gives the
uploadId, theuploadUrl, therequiredHeadersto send with it, themaximumSizeand the link'sexpiresAt. -
PUTthe file touploadUrlwith exactly therequiredHeaders, beforeexpiresAt. -
Complete it with
POST /matches/:matchId/evidence/uploads/:uploadId/complete. Tanitar verifies the stored object against the declared size and checksum and creates the evidence inpending. A mismatch is refused withEVIDENCE_STORAGE_VERIFICATION_FAILED, an expired upload withEVIDENCE_UPLOAD_EXPIRED. Completing twice returns the same evidence.
An upload that is never completed is cleaned up automatically after it expires. To discard one
straight away, call DELETE /matches/:matchId/evidence/uploads/:uploadId (results:mutate).
To replace the file of a pending piece of evidence, run the same two steps on
POST /matches/:matchId/evidence/:evidenceId/uploads and
POST /matches/:matchId/evidence/:evidenceId/uploads/:uploadId/complete. Only the original submitter
can replace it.
Read, edit and withdraw
| Route | Scope | What it does |
|---|---|---|
GET /matches/:matchId/evidence | results:read | Lists the match's evidence, optionally filtered by state (pending, approved, rejected, withdrawn); withdrawn evidence is left out unless you ask for it. No pagination. |
GET /matches/:matchId/evidence/:evidenceId | results:read | Reads one. |
GET /matches/:matchId/evidence/:evidenceId/media-url | results:read | Returns a short-lived download url for the current file, with its contentType, contentLength, checksumSha256 and expiresAt. Withdrawn evidence has none. |
PATCH /matches/:matchId/evidence/:evidenceId | participants:mutate | Changes the setNumber of pending evidence. |
DELETE /matches/:matchId/evidence/:evidenceId | participants:mutate | Withdraws pending evidence. |
POST /matches/:matchId/evidence with a mediaReference link records evidence hosted elsewhere
instead of uploaded. It is accepted only where your deployment enables external links and only for
allowed hosts; prefer uploads.
Review
POST /matches/:matchId/evidence/:evidenceId/review (results:mutate) takes a decision of
approved or rejected. Only pending evidence can be reviewed. The review publishes
tournament.match.evidence-reviewed; an approved piece unblocks a result on a match that requires
evidence.
Purge media
Evidence keeps each file it has ever held. To delete a replaced file or a file from rejected or
withdrawn evidence permanently, call
DELETE /matches/:matchId/evidence/:evidenceId/media/:mediaId (results:mutate). The current file
of pending or approved evidence cannot be purged (409 EVIDENCE_MEDIA_CURRENT).
If storage cannot delete the file, the media is marked purge-failed, the call answers 503
EVIDENCE_STORAGE_UNAVAILABLE, and tournament.match.evidence-media-purge-failed is published.
Retry with POST /matches/:matchId/evidence/:evidenceId/media/:mediaId/retry-purge. Purging a file
that is already purged succeeds and changes nothing. A completed purge publishes
tournament.match.evidence-media-purged.
Standings
GET /tournaments/:slug/standings (results:read) returns the computed standings, optionally for
one stageId, without pagination. Each row belongs to a stage and group and carries the entrant's
played, wins, losses, draws, points, gamesWon, gamesLost, scored, conceded,
pointDifference, its rank (or rankFrom/rankTo for a shared rank), the tiebreakApplied, and
the computedFromCascadeId of the result write that produced it.
Standings are recomputed with every result, correction and revert; you never trigger them. Listen
for tournament.standings.updated rather than polling. The ranking follows the tournament's
resultPolicy (rankBy and tiebreakers) or the stage's standingPolicy.
See the event catalog for the full payload of every event on this page.