Schemas

Every shape in the contract. Frames and views link here from the guide.

#User

idstring
namestring
emailstring

#ApiKeyMeta

idstring
kind"bearer" | "signature"
namestring
publicKeystring | null The registered key for signature keys, else null.
scopes"bots.read" | "bots.write" | "keys.read" | "keys.write" | "account.read" | "account.write"[]
createdAtstring
lastUsedAtstring | null
revokedAtstring | null

#Bot

idstring
ownerIdstring
namestring
mode"live" live: the game runs on a real 60 Hz clock; a pad that has not arrived when its frame is polled is neutral.
urlstring Where stomped connects the match WebSocket (and the /ping deploy check). In production it must be https — upgraded to wss for match sockets — and resolve to a public address (private/loopback ranges rejected), checked at registration and again at every connect. Registered URLs are never exposed publicly.
status"active" | "paused" active bots are seated by matchmaking whenever idle; paused bots sit out. stomped pauses a bot itself after a week-long streak of missed games (see Matchmaking & rating).
createdAtstring

#MatchSummary

idstring
mode"live" live: the game runs on a real 60 Hz clock; a pad that has not arrived when its frame is polled is neutral.
status"running" | "completed" | "aborted" aborted = the mode's wall clock expired, neither bot connected, or the engine failed: no placements, no rating changes.
stage31 | 32 | 28 | 8 | 2 | 3 | null Null until the game starts.
playersMatchPlayer[]
summaryGameSummary | null The result, once the match ends.
replayBytesinteger | null Size of the .slp at GET /matches/{id}/replay.slp; null while running, and once the arena's retention period has deleted the replay.
startedAtstring
endedAtstring | null

#MatchPlayer

port0 | 1 0 or 1 — the Slippi player index.
botIdstring
botNamestring
character0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | null Null until the game starts.
costumeinteger (0–5) | null
placementinteger | null 1 = won, 2 = lost; a draw is 1 for both. Null while running.
scoreinteger | null Stocks left at the end (a forfeit scores 0 against 4). Null while running.
ratingDeltanumber | null Rating after minus before, once the match completes.

#Match

idstring
mode"live" live: the game runs on a real 60 Hz clock; a pad that has not arrived when its frame is polled is neutral.
status"running" | "completed" | "aborted" aborted = the mode's wall clock expired, neither bot connected, or the engine failed: no placements, no rating changes.
stage31 | 32 | 28 | 8 | 2 | 3 | null Null until the game starts.
playersMatchPlayer[]
summaryGameSummary | null The result, once the match ends.
replayBytesinteger | null Size of the .slp at GET /matches/{id}/replay.slp; null while running, and once the arena's retention period has deleted the replay.
startedAtstring
endedAtstring | null
seedstring | null The engine's random seed. Null while the match runs — public once it ends.

#GameSummary

The result of a finished game, or where an aborted one stood.

stage31 | 32 | 28 | 8 | 2 | 3 A legal stage's slp id (Stage in @slippi/slippi-js).
players[object, object] By port.
framesinteger Frames played, from frame 0 to the last.
endReason"stocks" | "time" | "forfeit" | "engine" stocks: last stock standing. time: the timer ran out — more stocks wins, then lower percent; equal is a draw. forfeit: no pad of a bot's landed for 300 consecutive polls, or it never connected. engine: the engine broke; the match is aborted and unrated.
winner0 | 1 | null Null = draw (or no result on engine).

#LiveMatch

idstring
mode"live" live: the game runs on a real 60 Hz clock; a pad that has not arrived when its frame is polled is neutral.
stage31 | 32 | 28 | 8 | 2 | 3 | null Null while the bots pick.
frameinteger The latest frame the engine reported.
playersobject[]
port0 | 1 0 or 1 — the Slippi player index.
botIdstring
botNamestring
character0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | null
costumeinteger (0–5) | null
stocksinteger
percentnumber
xnumber
ynumber
startedAtstring

#LeaderboardRow

rankinteger
botIdstring
namestring
ownerstring The owner's public handle.
ratingnumber Conservative openskill estimate mu − 3σ, rounded to 1dp. New bots start ~0.
gamesPlayedinteger
winsinteger
lossesinteger
drawsinteger Ties on time and double forfeits.

#PickRequest

The one JSON text frame of a match, server → bot: pick a character.

id0 Always 0 — echo it in the answer.
kind"pick"
matchIdstring
mode"live" live: the game runs on a real 60 Hz clock; a pad that has not arrived when its frame is polled is neutral.
port0 | 1 Your port, 0 or 1 — the Slippi player index in the event stream.
opponentobject
botIdstring
namestring
deadlineMsinteger How long you have to answer, in milliseconds. Late = random character.
inputDelayFramesinteger The mode's lead: having seen frame F, send the pad for F + 1 + inputDelayFrames.

#PickResponse

The answer, bot → server, as a JSON text frame. Invalid or late: a random character, costume 0.

id0
actionobject
character0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 A playable character's slp external id (Character in @slippi/slippi-js): 0 Captain Falcon … 25 Ganondorf.
costumeinteger (0–5) Costume index, 0 = default.

#Pad

One controller state. On the wire it is 8 bytes after the i32 frame.

buttonsinteger (0–65535)
stickXinteger (0–255)
stickYinteger (0–255)
cstickXinteger (0–255)
cstickYinteger (0–255)
linteger (0–255)
rinteger (0–255)