---
title: "Cancel a tournament"
method: POST
path: "/tournaments/{identifier}/cancel"
tags: ["Tournament: Lifecycle"]
---

# Cancel a tournament

`POST /tournaments/{identifier}/cancel`

Cancels a tournament. IRREVERSIBLE - there is no un-cancel, and a COMPLETED or already CANCELLED tournament answers 400. Cancelling delists the tournament, emits a `tournament.cancelled` webhook, system-cancels every non-terminal generated match with no forfeit penalty, and notifies the captains of every approved participant. It does NOT change the approval status, so the response reports lifecycle status and approval status as independent fields. Requires an API key holding the tournaments lifecycle capability whose owner is a tournament ADMIN - a tournamentStaff MODERATOR is NOT sufficient and receives 403.

## Path parameters

- `identifier` string, required — Tournament slug.

## Request body

- TournamentCancelRequestBody — Tournament cancellation payload.
  - `reason` string — Optional human-readable cancellation reason. It is echoed to participants in the cancellation notification and in the `tournament.cancelled` webhook payload, so treat it as PUBLIC.

## Response `200`

The tournament was cancelled.

- TournamentCancelResponse — Result of cancelling a tournament.
  - `success` true, required
  - `status` 'CANCELLED', required — The lifecycle status this call set.
  - `approvalStatus` 'NOT_SUBMITTED' | 'AWAITING_APPROVAL' | 'APPROVED' | 'REJECTED', required — The tournament's approval status as of this request's authorization snapshot. Cancelling does NOT touch it, so it is reported as an INDEPENDENT field: `CANCELLED` alongside `NOT_SUBMITTED` is a real, reachable pair, and any status projection you build must handle it rather than deriving one field from the other.
  - `timestamp` string, required

## Other responses

- `400` — Bad request (invalid body, cursor, limit, or date).
- `401` — Missing or invalid API key.
- `403` — API key lacks the required permission.
- `404` — Resource not found.
- `429` — Rate limited.
- `500` — Internal server error.

---

[API](https://skmtc.net/teambattles/apis/teambattles-api.md) · [All operations](https://skmtc.net/teambattles/apis/teambattles-api/llms.txt) · [OpenAPI document](https://skmtc-service-staging.skmtc.workers.dev/v1/apis/teambattles/teambattles-api/revisions/2ffe8fb53b7d/schema)
