Developer docs

Build your first match.

The REST + Server-Sent Events reference for what ships today. Everything below is live against the API — no SDK required. The examples use api.matchkit.dev; running locally, the service is on localhost:8080.

Features still in flight are collected under Coming soon rather than documented as if they exist.

Interactive reference

Try every endpoint in the browser.

The full product API is published as live, “try it out” API docs — auto-generated from the service itself, always in sync with what's deployed. Authorize with your API key or JWT and fire real requests. The raw OpenAPI spec is there too, so you can generate a typed client for any language.

Quickstart

Create an account, mint an API key, and put your first player in a queue. MatchKit is a plain REST + Server-Sent Events API — it works from any engine, language, or backend today, no SDK required.

# 1 · Create your developer account → returns a JWT + refresh token
curl -X POST https://api.matchkit.dev/auth/register \
  -H 'Content-Type: application/json' \
  -d '{"username":"studio-one","email":"dev@studio.gg",
       "password":"hunter2","role":"DEV"}'

# 2 · Mint an API key for your game servers (Bearer = the JWT above)
curl -X POST https://api.matchkit.dev/developer/api-keys \
  -H "Authorization: Bearer $JWT" \
  -d '{"name":"prod","env":"live"}'
# → { "key": "mk_live_…" }   ← shown once, store it now

# 3 · Create a player and queue them up
curl -X POST https://api.matchkit.dev/player -H "X-API-KEY: mk_live_…" \
  -H 'Content-Type: application/json' \
  -d '{"username":"Ninja","region":"eu-west",
       "matchmakingMode":"MMR","ratingMode":"TS"}'

Authentication

Two ways in. Your dashboard and account calls use a JWT from /auth/login (access token 24h, refresh token 7 days). Your game servers use an X-API-KEY header — test keys (mk_test_) in development, live keys (mk_live_) in production. Most product endpoints accept either. New accounts verify their email before first login.

# Log in → { token, refreshToken, email, role, id }
curl -X POST https://api.matchkit.dev/auth/login \
  -H 'Content-Type: application/json' \
  -d '{"email":"dev@studio.gg","password":"hunter2"}'

# Refresh the 24h access token — refresh token goes in the header, not the body
curl -X POST https://api.matchkit.dev/auth/refresh-token \
  -H 'X-REFRESH-TOKEN: <refreshToken>'

# Server-to-server: send the API key instead of a JWT
curl https://api.matchkit.dev/player -H 'X-API-KEY: mk_live_…'

Responses & errors

Almost every endpoint wraps its payload in a consistent envelope — unwrap .data on the client. On failure, status is "ERROR" and error carries { code, detail, validationErrors[] }. (A few /queue/* endpoints return a bare string like "Joined queue" instead — handle both.)

{
  "status": "SUCCESS",
  "message": "Player fetched successfully",
  "data": { "id": 101, "username": "Ninja", "stats": { … } },
  "timestamp": "2026-07-06T10:15:30.123",
  "error": null
}

Accounts & API keys

Manage your account over /auth/me (read and update username, email, password). API keys are mk_live_ / mk_test_ prefixed, hashed at rest, and the full secret is revealed exactly once on creation. During beta the free tier allows 1,000 write calls (POST/PUT) per day; reads, account, and key management don't count.

GET    /auth/me                    your account (from the JWT)
PATCH  /auth/me                    update username / email / password
DELETE /auth/me                    self-service account deletion
GET    /developer/api-keys         list keys (masked, never plaintext)
POST   /developer/api-keys         create → returns the secret once
DELETE /developer/api-keys/{id}    revoke

Players API

A player belongs to your account and carries a multi-algorithm stats block — wins/losses, MMR (matchmakingScore), TrueSkill μ/σ (skillMean/uncertainty), plus K/D/A counters. Full CRUD over REST, with a gRPC surface for server-to-server integrations.

POST   /player               create a player
PUT    /player               update
GET    /player               list all your players
GET    /player/{id}          one player, with stats
GET    /player/{id}/history  per-match K/D/A + win/loss records
DELETE /player/{id}          delete (blocked if in a live team)

Queues & matchmaking

Join, leave, inspect, tune, and drop queues over REST — Redis-backed with single-writer match resolution. MatchmakingMode ∈ {ELO, MMR, LP} decides how teams are formed; RatingMode ∈ {TS, MMR} decides how ratings update after a match (Glicko-2 is on the way — see Coming soon).

POST   /queue/join    {playerId, gameMode, teamSize}   → "Joined queue"
POST   /queue/leave?playerId=
GET    /queue/all                       every live queue + entries
GET    /queue/player?playerId=          which queue a player sits in
POST   /queue/config?queueID=           tune relaxation params live
DELETE /queue?queueID=                  drop a queue

Matches

When a full match forms it is persisted and pushed to clients in realtime. End a match with the winning team and per-player stats to trigger rating updates; read live match rosters or search history by time range, team, game mode, or rating mode.

POST /match/end   {matchId, winningTeamId,
                   playerStats:[{playerId,kills,deaths,assists}]}
GET  /match/getActiveMatchDetails?matchId=      live teamA / teamB rosters
GET  /match/search?gameMode=&ratingMode=&hasEnded=    searchable history

Realtime events (SSE)

Match found, updated, and completed events stream over Server-Sent Events — no polling. Subscribe a single player to their own queue→match lifecycle, or subscribe an operations view to all matchmaking activity. Because EventSource can't set headers, browsers connect through a same-origin proxy that injects the token; servers pass the API key.

const es = new EventSource("https://api.matchkit.dev/sse/client/101");
es.onmessage = (e) => console.log("match event:", JSON.parse(e.data));

// /sse/client/{playerId}  — one player's queue → match lifecycle
// /sse/admin/{clientId}   — the full firehose of matchmaking activity

Health & monitoring

A public, unauthenticated GET /health for liveness checks. Operators also get Prometheus metrics and detailed health via the actuator endpoints, intended for the internal metrics network rather than the public internet.

GET /health                 public liveness → { status: "UP" }
GET /actuator/health        detailed health (ops network)
GET /actuator/prometheus    scrape target for metrics
Coming soon

On the roadmap

Planned and in-progress surface, listed here so the docs stay honest. Track status on the roadmap.

  • PlannedClient SDKs

    Native packages for Unity, Godot, and Unreal plus language libraries that wrap auth, queueing, and the event stream. Until they land, the REST + SSE API above works from any stack.

  • PlannedBilling & plans API

    /plans and /billing/* for subscriptions and quotas. MatchKit is free during beta — only the free-tier 1,000-writes/day cap is enforced, no paid quotas yet.

  • PlannedWebhooks

    Push match.found / match.completed / player.timeout to your endpoint with retries and a delivery log, as an alternative to holding an SSE connection. Use SSE until then.

  • PlannedUsage metrics & request logs

    Aggregated usage and a queryable request-log stream to back the dashboard Overview. Today those panels run on representative sampled data.

  • PlannedPagination on list endpoints

    Cursor + total controls on /player, /match/search, and /auth/devs so large datasets stay fast.

  • PlannedGlicko-2 ratings & parties

    Glicko-2 (GK2) alongside MMR and TrueSkill, plus party/group matchmaking, multi-region queues, leaderboards, and tournament brackets.

Ready to build?

Grab a free API key and hit the sandbox — 1,000 API calls/day, no card required. Only write calls (POST/PUT) count toward it; reads, account, and API-key management don't.

Get your API key