Skip to main content

Documentation Index

Fetch the complete documentation index at: https://teambattles.gg/docs/llms.txt

Use this file to discover all available pages before exploring further.

Interactive Endpoints

Try out the API directly from the docs:

User Matches

Retrieve matches where you’re on the roster

Team Matches

Retrieve matches for a specific team

Organization Matches

Retrieve matches for all teams in an organization

Twitch Global Badges

Access global Twitch badge data

Twitch Channel Badges

Access channel-specific Twitch badge data
The OpenAPI specification at /api-reference/openapi.json covers 13 paths: three match listing endpoints (user / team / org), two Twitch badge endpoints, and eight league endpoints. Game-developer score and lifecycle endpoints, overlay endpoints, and OAuth-proxy routes are intentionally excluded from the public spec.

API Key Permissions

API keys carry a 5-category permission object. Every category appears in the create/edit dialog at /settings/developer. The leagues category is v.optional() in src/convex/schema/validators.ts:735 - older keys may lack it on disk, and the dialog auto-fills it from defaultLeagues (src/routes/(app)/settings/developer/(components)/api-key-edit-dialog.svelte:134-137) so all five categories remain editable.
CategoryScopesValues
Matchesuser_matches, team_matches, org_matchesnone / read / read-write
Connectionsdiscord, twitch, github, battlenetnone / enabled
Gamescores, lifecyclenone / write (scores), none / read / read-write (lifecycle)
Webhooksmanagenone / enabled
Leaguesleague_public, league_adminnone / read

Presets

The create-key dialog ships with two one-click permission presets (src/routes/(app)/settings/developer/(components)/api-key-edit-dialog.svelte:98-130). A preset is only selectable when every connection in its requiredConnections list is linked on the user’s account.
PresetScopes setRequired connections
battles-replaymatches.user_matches: read, connections.twitch: enabledTwitch
league-managermatches.team_matches: read, leagues.league_public: read, leagues.league_admin: readnone

Captain Score Endpoints

These endpoints allow team captains to submit and manage scores.
MethodEndpointDescriptionPermission
POST/matches/{matchId}/scoresSubmit a map scorematches.team_matches: read-write
PATCH/matches/{matchId}/scoresConfirm opponent’s scorematches.team_matches: read-write
GET/matches/{matchId}/scoresGet all map scoresmatches.team_matches: read

Game Developer Endpoints

These endpoints are for approved game developers.

Score Submission

MethodEndpointDescriptionPermission
POST/game/matches/{matchId}/scoresSubmit verified scoregame.scores: write

Match Lifecycle

MethodEndpointDescriptionPermission
POST/game/matchesList matches (JSON body with gameId)game.lifecycle: read
GET/game/matches/{matchId}Get match detailsgame.lifecycle: read
GET/game/matches/{matchId}/rostersGet match rostersgame.lifecycle: read
GET/game/matches/{matchId}/statusGet match statusgame.lifecycle: read
PATCH/game/matches/{matchId}/statusUpdate match statusgame.lifecycle: read-write

Player Stats

MethodEndpointDescriptionPermission
POST/game/matches/{matchId}/player-statsSubmit player stats for a mapgame.scores: write

Common Response Codes

StatusDescription
200Success
201Created
400Bad request - invalid parameters
401Unauthorized - missing or invalid API key
403Forbidden - insufficient permissions
404Resource not found
409Conflict - duplicate or invalid state
429Rate limited
500Internal server error

Error Format

All errors follow a consistent format:
{
	"error": "ERROR_CODE",
	"message": "Human-readable description"
}

Common Error Codes

The error field uses a stable machine-readable identifier. The most common pagination-related codes are:
Error codeHTTPWhen it occurs
INVALID_NUM_ITEMS400Returned by the match listing endpoints when numItems is outside 1-100. See src/routes/api/v1/user/matches/+server.ts.
INVALID_LIMIT400Returned by the league listing endpoints and /game/matches when limit is outside the supported range (1-50 for /leagues, 1-100 elsewhere).
Both codes map to HTTP 400 with the canonical Convex error identifiers error_invalid_num_items and error_invalid_limit (src/convex/_helpers/errors.ts:21-22). Clients should treat the error field, not the message, as the stable contract.

Pagination

The v1 API is mid-migration and currently exposes two pagination envelope shapes. Check each endpoint’s reference page for its exact response shape.

Native envelope (match listing endpoints)

The three match listing endpoints use Convex’s native pagination envelope: Request fields: numItems (page size, default 25) and cursor (opaque string from the previous response, or omit/null for the first page). Response shape: { page, isDone, continueCursor }. Iterate page for results, check isDone to know when you’ve reached the end, and pass continueCursor as cursor in the next request.
POST /api/v1/user/matches
Content-Type: application/json

{
  "numItems": 25,
  "cursor": "g2wAAAACYQJhAmo="
}

Legacy envelope (all other v1 endpoints)

Most remaining v1 paginated endpoints still wrap results in a legacy envelope: { matches, pagination: { cursor, hasMore }, timestamp }. Pass cursor (and typically limit) in the request body to get the next page. This shape will be migrated to the native envelope in a follow-up release.
POST /api/v1/game/matches
Content-Type: application/json

{
  "gameId": "call_of_duty_black_ops_7",
  "cursor": "25",
  "limit": 25
}