Skip to content
Kontest

Developers

Run tournaments from your code or your AI agent: brackets, round robin, Swiss and groups, for any game or sport. Free, rate-limited.

MCP server

Add Kontest to Claude, ChatGPT, Cursor or any MCP client and ask it to “set up a round robin for my 12 colleagues” or “report 3–1 for Ada in the semi-final”. The server is at https://kontest.games/mcp (Streamable HTTP). Your client signs you in with Kontest the first time.

Claude Code:

claude mcp add --transport http kontest https://kontest.games/mcp

Any client that takes a JSON config:

{
  "mcpServers": {
    "kontest": { "type": "http", "url": "https://kontest.games/mcp" }
  }
}

A client that can’t sign in can send an API key instead, as Authorization: Bearer kt_live_….

Tools: whoami, list_tournaments, get_tournament, update_tournament, add_entrants, remove_entrant, seed_tournament, start_tournament, report_result, clear_result, cancel_tournament, and list_webhooks, create_webhook, update_webhook, delete_webhook, test_webhook, list_webhook_deliveries.

REST API

JSON over HTTPS at https://kontest.games/api/v1, described in full by OpenAPI 3.1. Reading public tournaments needs no key.

# Read a tournament
curl https://kontest.games/api/v1/tournaments/office-fifa-cup-x7k2

Every tournament also reads as Markdown at https://kontest.games/t/<slug>.md. Errors are { "error": { "code", "message" } }.

Webhooks

Have Kontest tell your server when your tournaments change: a match is ready or finished, somebody joins, the tournament completes. Add one below, or POST /api/v1/webhooks. Each covers every tournament you organise.

Events:

  • tournament.started The draw is fixed and the first matches can be played.
  • tournament.completed The last result counts: final places and the champion.
  • tournament.cancelled The organiser called it off.
  • tournament.reset Back to sign-up from running, results gone.
  • entrant.added Somebody joined, or the organiser added a name.
  • entrant.removed An entrant was taken out before the start.
  • entrant.checked_in An entrant checked in, or out (checkedIn says which).
  • match.ready Both sides of a match are known: it can be played.
  • match.reported A player reported a result; it waits for the other side.
  • match.disputed The other side said otherwise; the organiser decides.
  • match.completed A result counts: confirmed, the organiser’s, or left alone 24 hours.
  • match.cleared The organiser cleared a result.

Each is a POST with a JSON body:

{
  "type": "match.completed",
  "timestamp": "2026-10-12T18:04:05.000Z",
  "data": {
    "tournament": { "id": "trn_…", "slug": "office-fifa-cup-x7k2", "name": "Office FIFA Cup",
                    "game": "FIFA 26", "state": "running", "url": "https://kontest.games/t/office-fifa-cup-x7k2" },
    "match": { "id": "W1-1", "round": 1, "a": { "id": "ten_…", "name": "Ada" },
               "b": { "id": "ten_…", "name": "Bo" }, "state": "done", "winner": "a",
               "scoreA": 3, "scoreB": 1, "forfeit": false }
  }
}

They follow Standard Webhooks: check the webhook-signature header with your endpoint’s secret, using any of its libraries:

import { Webhook } from 'standardwebhooks'

const wh = new Webhook(process.env.KONTEST_WEBHOOK_SECRET) // whsec_…
const event = wh.verify(rawBody, request.headers) // throws if not from Kontest

Answer with any 2xx within 10 seconds. Anything else is tried again after 5 seconds, 5 minutes, 30 minutes, then 2, 5, 10 and 10 hours. The webhook-id header stays the same on every try, so ignore one you’ve already had. An endpoint that does nothing but fail for 5 days is turned off. Order isn’t guaranteed: go by the timestamp, or read the tournament.

Signing in

API keys are for your own scripts and servers: made below, shown once, revocable. They act as you.

OAuth 2.1 is for apps and agents acting for other people: the authorization code flow with PKCE (S256), dynamic client registration, and refresh tokens that rotate. Discovery: /.well-known/oauth-authorization-server and /.well-known/oauth-protected-resource. Scopes: tournaments:write and webhooks:write.

Organising needs a kept account, not a guest one. Limits are per account; a 429 says when to try again.

Your keys and apps

Your keys

Sign in to make API keys, add webhooks and see the apps you’ve connected.

Sign in