---
title: "Create a match or an americano tournament"
method: POST
path: "/api/v1/matches"
tags: ["matches"]
---

# Create a match or an americano tournament

`POST /api/v1/matches`

## Request

- Base URL: `https://kicksma.sh`
- URL: `https://kicksma.sh/api/v1/matches`
- Auth: one of:
  - none
  - HTTP bearer

Returns the public match plus the organizer's personal token, personal link and private manage link. Give those to the person you act for; never publish them.

## Request body

- CreateMatch
  - `type` 'match' | 'tournament': A match is exactly four players. A tournament is an americano with 4 to 64 players in fours.
  - `startsAt` string, required: ISO 8601 date-time. With an offset or Z it is absolute; without one it is read in tz. Example: 2026-09-11T19:00
  - `tz` string, required: IANA time zone the players live in, for example Asia/Singapore or Asia/Bangkok.
  - `durationMinutes` 60 | 90 | 120: How long the court is booked: 60, 90 or 120 minutes. Omit for 90 (a match) or 120 (a tournament). The match page, the cards and the calendar invitation show it.
  - `venue` string: Club or court name. Enables the venue board and the booking link.
  - `venueMapUrl` string, uri
  - `court` string: Court within the venue, e.g. "3".
  - `capacity` integer: Tournaments only, a multiple of 4. Matches are always 4.
  - `format` 'americano' | 'mexicano' | 'king': Tournaments only. americano: partners rotate, everyone plays everyone. mexicano: courts by standings after round 1. king: winners move up a court, losers down.
  - `fixedPairs` boolean: Tournaments only: two partners play every round together, in any format. Pairs sign up together (join_match with partner); a player alone is listed as needing a partner. Americano then rotates the opponents: every pair meets every other pair, and the table ranks pairs.
  - `pointsPerMatch` integer: Tournaments only: fixed points per match (16, 21, 24, 32). Omit for free scoring; mexicano defaults to 24.
  - `gamesTo` integer: Tournaments only: first to N games (4, 6, 8) instead of points; the table then ranks by matches won.
  - `whenFull` 'waitlist' | 'closed'
  - `levelMin` number, nullable: Level range 0 to 7 (Playtomic-style). Omit both for any level.
  - `levelMax` number, nullable
  - `verifiedLevelsOnly` boolean: With a range: only levels confirmed by an organizer, a coach or a club walk in; declared levels inside the range ask to join.
  - `category` 'men' | 'women' | 'mixed', nullable: Who the match is for: men, women or mixed. Omit for anyone. Information for the players who find it; nobody is checked when they join.
  - `ageMin` 35 | 45 | 55, nullable: An age tag: 35, 45 or 55 means 35+, 45+ or 55+. Omit for any age. Information only; nobody is checked when they join.
  - `title` string
  - `note` string
  - `bookingUrl` string, uri: The club's booking page or confirmation link, shown to players.
  - `cost` string: What each player pays, as free text: 400 THB, €8, split 4 ways.
  - `listOnVenueBoard` boolean: Show the match on the public venue board (/v/{venue-slug}). Off by default.
  - `organizer` object, required
    - `name` string, required: First name is enough.
    - `token` string: Personal token of an existing Kicksmash player, returned by earlier calls, so the same person organizes again.
    - `email` string, email: Optional. Gets the organizer link and calendar invite by email.
    - `level` number
  - `organizerPlays` boolean: Seat the organizer in the match (default). False when they only organize.

## Response `201`

Created

- CreateMatchResult
  - `match` Match: Exactly what the public match page shows. First names and levels only; never emails, phones, tokens or manage links.
    - `code` string, required
    - `url` string, required
    - `type` 'match' | 'tournament', required
    - `format` 'americano' | 'mexicano' | 'king' | 'null', nullable: Tournaments only.
    - `fixedPairs` boolean, nullable: Tournaments only: two partners play every round together instead of rotating.
    - `pairs` object[], nullable: A fixed-pairs tournament's list as pairs, in order: two first names each, or one name that needs a partner. Null otherwise.
      - `names` string[]
      - `partnerNeeded` boolean
    - `title` string, nullable
    - `status` 'open' | 'full' | 'cancelled' | 'past', required
    - `startsAt` string, date-time, required
    - `endsAt` string, date-time: startsAt plus durationMinutes.
    - `durationMinutes` 60 | 90 | 120: How long the organiser booked the court, in minutes. The calendar invitation ends here too.
    - `tz` string, required
    - `venue` object, nullable
      - `name` string
      - `slug` string, nullable
      - `mapUrl` string, nullable
      - `court` string, nullable
      - `boardUrl` string, nullable
    - `capacity` integer, required
    - `players` object[], required
      - `name` string
      - `level` number, nullable
      - `organizer` boolean
      - `status` 'joined' | 'confirmed' | 'invited'
    - `spotsLeft` integer, required
    - `waitlist` integer
    - `whenFull` 'waitlist' | 'closed'
    - `level` object, nullable
      - `min` number, nullable
      - `max` number, nullable
      - `preset` string, nullable: bronze, silver, gold, platinum or custom
      - `verifiedOnly` boolean: Only levels confirmed by an organizer, a coach or the club walk in; declared levels inside the range ask to join.
    - `category` 'men' | 'women' | 'mixed' | 'null', nullable: Who the match is for; null for anyone. Information only: nobody is checked when they join.
    - `ageMin` 35 | 45 | 55 | null, nullable: An age tag, read as 35+, 45+ or 55+; null for any age. Information only.
    - `group` object, nullable
      - `code` string
      - `name` string
      - `url` string
    - `listed` boolean
    - `bookingUrl` string, nullable
    - `courtBooked` object, nullable: A player booked the court in the club's own app and said so. Null while not booked and on a cancelled match. Kicksmash never books or takes a payment.
      - `at` string, date-time
      - `by` string, nullable: The booker's first name; null when the booker no longer holds a seat or their account is gone.
    - `cost` string, nullable: What each player pays, free text.
    - `note` string, nullable
    - `result` object, nullable
      - `sets` object[]
        - `a` integer
        - `b` integer
      - `teamA` string[]
      - `teamB` string[]
      - `winner` 'a' | 'b' | 'draw': Sets can be empty when only the winner was recorded.
      - `confirmed` boolean
    - `createdAt` string, date-time
  - `organizer` object
    - `name` string
    - `personalToken` string
    - `personalUrl` string
    - `manageUrl` string
  - `shareUrl` string
  - `next` string

## Other responses

- `422`: Invalid request; the message names the field
- `429`: Rate limited; the hint says how to get more room

---

[API](https://skmtc.dev/kicksma/apis/kicksmash-api.md) · [All operations](https://skmtc.dev/kicksma/apis/kicksmash-api/llms.txt) · [OpenAPI document](https://skmtc.dev/kicksma/apis/kicksmash-api/revisions/8ae952aa0f19?raw)
