OHKO's game server exposes a REST API under /api and a WebSocket at /ws, on the same origin
as the web app (for example https://ohko.duckdns.org/api/stats). The web app itself uses
exactly these endpoints.
The complete, machine-readable spec with every request and response schema is generated from
the server's validation schemas and served at /api/docs (interactive) and
/api/docs/json (raw OpenAPI 3).
JSON in, JSON out. Every input is validated; unknown or malformed fields are rejected with
VALIDATION_FAILED.
Amounts are strings of integer base units (lamports for SOL, millionths for USDC and
$OHKO), so no precision is ever lost.
Auth is a cookie. POST /api/session/guest creates a guest session; Sign-In With Solana
(/api/auth/siws/challenge, then /api/auth/siws/verify) creates a 12-hour wallet session in
an httpOnly cookie. Endpoints that act for a player need one of them.
Request IDs. Every response carries an x-request-id header (a well-formed one you send is
reused). Include it when you report a problem.
Rate limits. 120 requests per minute per IP, plus 240 per minute per signed-in wallet
across IPs. Joining staked queues is limited further. Over the limit you get HTTP 429 with
RATE_LIMITED.
Connect to wss://<host>/ws. The connection authenticates from the session cookie; a socket
opened before the cookie existed can bind with an auth message carrying the token from
GET /api/session. Every message is a JSON object with a type. Send a ping at least every
25 seconds to stay counted as online.
Your queue state: table, players searching, rating band, estimated wait
queue:matched
You were paired; the battle id
battle:state
Full battle snapshot for joining and resyncing
battle:update
New protocol lines; from is the first line's index, a gap means resync
battle:request
Your next decision
battle:choice
Your choice (or undo) was accepted
battle:timer
Both clocks
battle:presence
Who is connected, and a disconnect countdown
battle:end
Winner, reason and turns
battle:chat
A chat line or emote
battle:rematch
Rematch offer state
stake:state
A staked match's state
tournament:state
A tournament's registrations and bracket
tournament:ready
Your next bracket match and its show-up deadline
challenge:accepted
Someone accepted your challenge link
error
An error code and message, with the battle it concerns
Battle protocol lines are the simulator's own protocol. Requests are the simulator's request
JSON; choices use its choice syntax (move 1, switch 3, move 2 terastallize, team 123456)
and are validated by the server before they reach the simulator.