Skip to main content
POST
/
matches
/
create
curl -X POST https://teambattles.gg/api/v1/matches/create \
  -H "Authorization: Bearer tb_your_api_key" \
  -H "Content-Type: application/json" \
  -d '{"teamId": "jh7abc123", "gameId": "bo6", "gameModeId": "hardpoint", "matchType": "XP_ONLY", "mapSelectionType": "COMPETITIVE", "mapPreferenceMode": "VETO", "teamSize": 4, "bestOf": 5, "activeRoster": ["jd7user123", "jd7user456"]}'
{
  "success": true,
  "matchId": "<string>",
  "timestamp": "<string>"
}

Permission Required

This endpoint requires matches.user_matches:read-write on your API key. A free (api_free) key receives 403 error_api_feature_required; this requires an api_pro+ plan.

Access / Membership Rules

The match is created as the API key owner, derived from the key itself - it is never accepted as a body field. The owner must captain the creator team (teamId), and every user in activeRoster must be a member of that team. League and challenge rules are enforced exactly as in the web app: when isChallenge is true a challengedTeamId is required, and a leagueId opts the match into a league with its own eligibility rules. A personal key can only create matches for teams its owner actually captains - the route binding is a no-op and this authorization is enforced inside Convex. A non-personal key receives 403 API_KEY_PERMISSION_DENIED. This route accepts an optional Idempotency-Key header so retries are safe.

Request Body

FieldTypeRequiredDescription
teamIdstringYesCreator team ID. The owner must captain it.
gameIdstringYesGame ID for the match.
gameModeIdstringYesGame mode ID (client-side definition).
matchTypestringYesMatch type: XP_ONLY or WAGER.
mapSelectionTypestringYesMap selection type: COMPETITIVE or FLEX.
mapPreferenceModestringYesMap preference mode: PREFERRED, VETO, or MANUAL.
teamSizenumberYesPlayers per team.
bestOfnumberYesSeries length (best of N).
activeRosterarrayYesActive roster user IDs (must be creator-team members).
platformstringNoPlatform: PC, XBOX, PLAYSTATION, CONSOLE_ONLY, CROSSPLAY (defaults to CROSSPLAY).
inputDevicestringNoInput device: ALL, CONTROLLER, KB_M (defaults to ALL).
regionstringNoRegion (defaults to NONE).
scheduledAtnumberNoScheduled start (epoch ms).
wagerAmountnumberNoWager amount (WAGER matches only).
selectedMapsarrayNoSelected map IDs.
selectedObjectivesarrayNoSelected objective IDs.
gameSpecificOptionsobjectNoGame-specific options.
lockedRulesobjectNoLocked rule flags.
notesstringNoOptional match notes.
publishStatusstringNoPublish status: DRAFT, PUBLISHED, ARCHIVED (defaults to DRAFT).
benchRosterarrayNoOptional bench roster (objects with id and priority).
isChallengebooleanNoCreate as a direct challenge to another team.
challengedTeamIdstringNoChallenged team ID (required when isChallenge is true).
leagueIdstringNoLeague ID for a league match.

What’s Returned

Returns success: true, the new matchId, and a timestamp. Mintlify renders the full schema from the spec below.
curl -X POST https://teambattles.gg/api/v1/matches/create \
  -H "Authorization: Bearer tb_your_api_key" \
  -H "Content-Type: application/json" \
  -d '{"teamId": "jh7abc123", "gameId": "bo6", "gameModeId": "hardpoint", "matchType": "XP_ONLY", "mapSelectionType": "COMPETITIVE", "mapPreferenceMode": "VETO", "teamSize": 4, "bestOf": 5, "activeRoster": ["jd7user123", "jd7user456"]}'

Authorizations

Authorization
string
header
required

Send your API key as: Authorization: Bearer tb_

Body

application/json

Creates a new match as the API key owner.

teamId
string
required

Creator team ID. The owner must captain it.

Minimum string length: 1
gameId
string
required

Game ID for the match.

Minimum string length: 1
gameModeId
string
required

Game mode ID (client-side definition).

Minimum string length: 1
matchType
enum<string>
required

Match type.

Available options:
XP_ONLY,
WAGER
mapSelectionType
enum<string>
required

Map selection type.

Available options:
COMPETITIVE,
FLEX
mapPreferenceMode
enum<string>
required

Map preference mode.

Available options:
PREFERRED,
VETO,
MANUAL
teamSize
integer
required

Players per team.

Required range: -9007199254740991 <= x <= 9007199254740991
bestOf
integer
required

Series length (best of N).

Required range: -9007199254740991 <= x <= 9007199254740991
activeRoster
string[]
required

Active roster user IDs (must be creator-team members).

Minimum array length: 1
Minimum string length: 1
platform
enum<string>

Platform (defaults to CROSSPLAY).

Available options:
PC,
XBOX,
PLAYSTATION,
CONSOLE_ONLY,
CROSSPLAY
inputDevice
enum<string>

Input device (defaults to ALL).

Available options:
ALL,
CONTROLLER,
KB_M
region
enum<string>

Region (defaults to NONE).

Available options:
NONE,
NA_EAST,
NA_WEST,
EU,
ASIA,
OCEANIA,
SOUTH_AMERICA,
MIDDLE_EAST,
AFRICA
scheduledAt
number

Scheduled start (epoch ms).

wagerAmount
number

Wager amount (WAGER matches only).

selectedMaps
string[]

Selected map IDs.

selectedObjectives
string[]

Selected objective IDs.

gameSpecificOptions
object

Game-specific options.

lockedRules
object

Locked rule flags.

notes
string

Optional match notes.

publishStatus
enum<string>

Publish status (defaults to DRAFT).

Available options:
DRAFT,
PUBLISHED,
ARCHIVED
benchRoster
object[]

Optional bench roster.

isChallenge
boolean

Create as a direct challenge to another team.

challengedTeamId
string

Challenged team ID (required when isChallenge is true).

Minimum string length: 1
leagueId
string

League ID for a league match.

Minimum string length: 1

Response

The match was created.

success
boolean
required
matchId
string
required
timestamp
string
required