---
title: "Start a match"
method: PATCH
path: "/v1/matches/{id}/start"
tags: ["Matches"]
---

# Start a match

`PATCH /v1/matches/{id}/start`

## Request

- Base URL: `https://api.hify.club`
- URL: `https://api.hify.club/v1/matches/{id}/start`
- Auth: API key in header `X-User-Token`

Transitions the match from pending to in_progress. Refused if another match on the same game is already live, since both would emit onto that game's score channel.

## Response `200`

Match started

- Match
  - `id` integer
  - `game_id` integer
  - `sequence_number` integer, nullable
  - `round_number` integer, nullable
  - `stage` 'league' | 'quarterfinal' | 'semifinal' | 'knockout' | 'final' | 'third_place': Where the match sits in the tournament
  - `status` 'pending' | 'in_progress' | 'completed'
  - `winner_side` 'side_a' | 'side_b' | 'draw', nullable
  - `first_serve_side` 'side_a' | 'side_b', nullable: Side that served first; set via start_scoring
  - `completion_reason` 'normal' | 'injury' | 'walkover' | 'other', nullable: How the match ended, set from the match_completed event: normal for a match played to its conclusion, injury/walkover/other for an early end. Null until the match completes.
  - `category_label` string, nullable: Display category, e.g. "Open Mixed Doubles"
  - `scoring_config_snapshot` object: The compiled rules the match is scored under, resolved from its scoring format (or its tournament's). Empty when neither names one.
  - `scored_by` object, nullable: The scorer who last claimed the match, read from the newest match_claim regardless of its status. Null when the match was never claimed.
    - `user_id` string, uuid
    - `name` string, nullable: Scorer display name, e.g. "Prajapati D.". Null until the scorer has a first/last name on record.
  - `started_at` string, date-time, nullable: scored_at of the first non-voided score entry; null until the match has been scored.
  - `ended_at` string, date-time, nullable: scored_at of the last non-voided score entry; null until the match has been scored.
  - `duration_seconds` integer, nullable: ended_at minus started_at; null until a second entry exists.
  - `created_at` string, date-time
  - `updated_at` string, date-time
  - `match_participants` MatchParticipant[]
    - `id` integer
    - `match_id` integer
    - `side` 'side_a' | 'side_b'
    - `participant_type` 'User' | 'AnonymousTournamentParticipant'
    - `participant_id` string, uuid
    - `position` string, nullable
  - `team_names` object: Each side's team name; null for a side without a team.
    - `side_a` string, nullable
    - `side_b` string, nullable
  - `match_sets` MatchSet[]
    - `id` integer
    - `match_id` integer
    - `sequence_number` integer
    - `winner_side` 'side_a' | 'side_b', nullable
    - `score` object, nullable
  - `cameras` object[]: Enabled cameras of the arena where the match is played. Included in the show response.
    - `id` integer
    - `in_arena_id` string
  - `arena` object: The arena where the match is played, including the device hostname.
    - `id` integer
    - `name` string
    - `in_facility_id` integer
    - `var_hostname` string, nullable: cloudflare_tunnel_hostname of the arena's device, if any.

## Other responses

- `401`: Unauthorized
- `404`: Match not found
- `422`: Invalid state transition, or another match is already live on this match's game

---

[API](https://skmtc.dev/hify/apis/hify-apis.md) - [All operations](https://skmtc.dev/hify/apis/hify-apis/llms.txt) - [OpenAPI document](https://skmtc.dev/hify/apis/hify-apis/revisions/b5920403538d?raw)
