KHELAU APIखेलौँ

Khelau Call Break game socket AsyncAPI 3.0.0 · protocol v1.0.0

Servers: wss://khelau-api.vercel.app/api/ws (production) · ws://localhost:8787/api/ws (local) · Machine-readable: /v1/asyncapi.json

Real-time play for Call Break on Khelau. One WebSocket carries the whole session: identify, join or create a room, then bid and play. The server is authoritative: it validates every move, keeps hidden cards server-side and sends each player only their own view.

Connection

Session lifecycle

  1. Connect and send hello (with the stored token, if any). Receive welcome.
  2. quick, create or join a room. Receive room updates.
  3. In a game, receive state after every change and send bid/play on your turn, echoing seq.

Reconnecting

Connections can drop at any time; Vercel also closes each socket after 5 minutes. Reconnect with backoff and send hello with the same token: you get your seat, hand and timers back. If the server that hosted the game went away, the game is restored from the database.

Messages

Client → Server

Server → Client

Client → Server

hello Hello Client → Server

Identify the player. Must be the first message on every connection.

Send the stored session token to return to your seat after a refresh, a dropped connection or a server restart; send null the first time. The server answers with welcome, then room (and state when at a table).

FieldTypeDescription
t"hello"
v1Protocol version.
tokenstring | nullSession token from a previous welcome, or null.
max length 128
namestringDisplay name; trimmed and cut to 16 characters.
avatarintegerAvatar number. Photos never leave the device.
min 0, max 18
clientId optionalstringAnonymous per-browser id, used for statistics only.
pattern ^[A-Za-z0-9_-]{8,40}$

Example

{
  "t": "hello",
  "v": 1,
  "token": null,
  "name": "Asha",
  "avatar": 10,
  "clientId": "k3v9x0q2m1"
}

quick Find a game Client → Server

Join the public lobby with the most players waiting, or open a new one.

FieldTypeDescription
t"quick"

Example

{
  "t": "quick"
}

create Create private room Client → Server

Open a private room; its code is in the next room message.

FieldTypeDescription
t"create"

Example

{
  "t": "create"
}

join Join room Client → Server

Join a room by code.

FieldTypeDescription
t"join"
codestringThe 5-character room code (case-insensitive).
max length 16

Example

{
  "t": "join",
  "code": "KTM42"
}

founders Join Founders lobby Client → Server

Join the invite-only Founders lobby.

The password is checked only on the server. 5 wrong tries per 10 minutes.

FieldTypeDescription
t"founders"
namestring
max length 64
passwordstring
max length 256

Example

{
  "t": "founders",
  "name": "Sabin",
  "password": "********"
}

sitOut Sit out Client → Server

Founders lobby: move from a seat to the bench (before a game).

FieldTypeDescription
t"sitOut"

Example

{
  "t": "sitOut"
}

sitIn Take a seat Client → Server

Founders lobby: move from the bench to a free seat.

FieldTypeDescription
t"sitIn"

Example

{
  "t": "sitIn"
}

start Start Client → Server

Start now; bots fill empty seats. Private rooms: host only.

FieldTypeDescription
t"start"

Example

{
  "t": "start"
}

bid Bid Client → Server

Bid for the round when it is your turn.

FieldTypeDescription
t"bid"
bidinteger
min 1, max 13
seq optionalintegerThe seq of the latest state this client saw. A move made against an older state is ignored and the current state is sent again. Optional for older clients.
min 0

Example

{
  "t": "bid",
  "bid": 3,
  "seq": 12
}

play Play card Client → Server

Play a card from your hand when it is your turn. It must be one of state.view.legal.

FieldTypeDescription
t"play"
cardCard
seq optionalintegerThe seq of the latest state this client saw. A move made against an older state is ignored and the current state is sent again. Optional for older clients.
min 0

Example

{
  "t": "play",
  "card": {
    "suit": "S",
    "rank": 14
  },
  "seq": 13
}

ready Next round Client → Server

Ready for the next round (between rounds).

FieldTypeDescription
t"ready"

Example

{
  "t": "ready"
}

again Play again Client → Server

Start a new game in the same room after game over (host only).

FieldTypeDescription
t"again"

Example

{
  "t": "again"
}

leave Leave Client → Server

Leave the room. Mid-game, a bot takes the seat and it is held for you for 2 minutes (see rejoin).

FieldTypeDescription
t"leave"

Example

{
  "t": "leave"
}

rejoin Rejoin Client → Server

Take back the seat you left, while the rejoin offer is open.

FieldTypeDescription
t"rejoin"

Example

{
  "t": "rejoin"
}

ping Ping Client → Server

Keep-alive; answered with pong.

FieldTypeDescription
t"ping"

Example

{
  "t": "ping"
}

Server → Client

welcome Welcome Server → Client

Reply to hello. Store token (e.g. in localStorage) and send it in every later hello.

FieldTypeDescription
t"welcome"
tokenstringSession token: it identifies your seat. Treat it as a secret.
playerIdstring

Example

{
  "t": "welcome",
  "token": "q1w2e3r4t5y6u7i8o9p0as",
  "playerId": "5f2a9c0d1e3b"
}

room Room Server → Client

The room you are in: seats, host, status and countdowns. null after leaving.

FieldTypeDescription
t"room"
roomRoomInfo | null

Example

{
  "t": "room",
  "room": {
    "code": "KTM42",
    "isPublic": false,
    "status": "lobby",
    "hostSeat": 0,
    "you": 0,
    "seats": [
      {
        "name": "Asha",
        "avatar": 10,
        "kind": "human",
        "connected": true,
        "botControlled": false
      },
      null,
      null,
      null
    ],
    "autoStartMs": null,
    "founders": false,
    "bench": null
  }
}

state Game state Server → Client

Your view of the game. It contains only your own hand; other players' cards are never sent.

FieldTypeDescription
t"state"
viewPlayerView
turnMsLeftinteger | nullMilliseconds left for the player whose turn it is.
readyarray of booleanBetween rounds: which seats pressed Next round.
nextRoundMsinteger | nullMilliseconds until the next round starts automatically.
seq optionalintegerAction counter; echo it in bid and play.
min 0

Example

{
  "t": "state",
  "view": {
    "seat": 0,
    "round": 1,
    "phase": "bidding",
    "turn": 0,
    "hand": [
      {
        "suit": "S",
        "rank": 14
      }
    ],
    "bids": [
      null,
      3,
      null,
      null
    ],
    "totals": [
      0,
      0,
      0,
      0
    ],
    "legal": []
  },
  "turnMsLeft": 29000,
  "ready": [
    false,
    false,
    false,
    false
  ],
  "nextRoundMs": null,
  "seq": 12
}

rejoin Rejoin offer Server → Client

After leaving a game in progress: your seat is held for offer.ms more milliseconds. null: nothing to rejoin.

FieldTypeDescription
t"rejoin"
offerobject | null

Example

{
  "t": "rejoin",
  "offer": {
    "code": "KTM42",
    "ms": 118000
  }
}

watch Watch Server → Client

Founders lobby: public progress for the founder sitting out (bids, tricks, totals; never cards).

FieldTypeDescription
t"watch"
watchobject | null

Example

{
  "t": "watch",
  "watch": null
}

error Error Server → Client

A request was refused (e.g. room full, not your turn, illegal card). Human-readable.

FieldTypeDescription
t"error"
messagestring

Example

{
  "t": "error",
  "message": "That room is full or already playing"
}

pong Pong Server → Client

Reply to ping, with the number of players online on this server instance.

FieldTypeDescription
t"pong"
onlineinteger
min 0

Example

{
  "t": "pong",
  "online": 3
}

Types

Card

FieldTypeDescription
suit"S" | "H" | "C" | "D"Spades (always trump), Hearts, Clubs, Diamonds.
rankinteger11 = J, 12 = Q, 13 = K, 14 = A.
min 2, max 14

Seat

FieldTypeDescription
namestring
avatarinteger
kind"human" | "bot"
connectedboolean
botControlledbooleanA human seat played by a bot for now (disconnected or left).
left optionalboolean
awayMs optionalinteger | nullMilliseconds left before a held seat is given up.

RoomInfo

FieldTypeDescription
codestring
isPublicboolean
status"lobby" | "playing" | "finished"
hostSeatinteger
min 0, max 3
youintegerYour seat (4 = the Founders bench).
min 0, max 4
seatsarray of Seat
autoStartMsinteger | nullPublic lobbies: milliseconds until bots fill the seats and the game starts.
foundersboolean
benchSeat

PlayerView

Everything one seat may know. Other hands appear only as counts.

FieldTypeDescription
seatinteger
min 0, max 3
roundinteger
min 1
dealer optionalinteger
phase"bidding" | "playing" | "trickEnd" | "roundEnd" | "gameOver"
handarray of CardYour cards only.
handCounts optionalarray of integerCards left per seat.
bidsarray of integer | null
won optionalarray of integerTricks won this round, per seat.
turninteger
trick optionalarrayCards on the table: {seat, card}.
totalsarray of integerScores in tenths (41 = +4.1).
legalarray of CardCards you may play now (empty unless it is your turn to play).