Live event feed (WebSocket)
Every game has a live feed of attack and King-of-the-Hill events — the same stream that drives the animation on /games/{id}/attack. Participants can tap it from a script, bot, or custom overlay.
There are two ways to consume it:
The plain WebSocket is the easy one — no negotiate handshake, no SignalR protocol, no auth token. This page documents it. (The SignalR hub is unchanged and still powers the in-app animation; the two carry identical events.)
Connecting
- Use
wss://over HTTPS,ws://over plain HTTP (e.g.ws://localhost:8080/hub/attack/ws?game=19). - No authentication. The feed is public — anyone can watch any visible game. (Draft/
Hiddengames are monitor-only, same as the rest of the public surface.) - The server pushes frames; the client sends nothing. Anything you send is ignored.
- Bad/missing
game, or a game you can't see, closes the connection (HTTP400/404on the upgrade).
The connection stays open for the whole game; reconnect if it drops (a slow client may be disconnected — see Backpressure below).
Frames
Each frame is one JSON object with a kind field telling you what it is:
hello — sent once, on connect
ping — keepalive, ~every 25s when idle
Ignore it (or use it as a liveness check). It exists so reverse proxies don't idle-drop the socket.
attack — a flag submission (A&D capture or jeopardy solve)
koth — a King-of-the-Hill control change
Fired when a hill's holder changes (a takeover, or a hill going uncontrolled).
Freeze & visibility. Events are subject to the same gate as the scoreboard: nothing is emitted for Hidden games, and during an ICPC-style freeze window the feed goes quiet for non-monitors — the same rule that hides late-game state on the frozen board.
Examples
websocat (shell)
Browser / Node
Python (pip install websockets)
Notes
- Backpressure. Each connection has a bounded outbound queue; if your client can't keep up, the oldest events are dropped (never the broadcaster — one slow client can't stall the feed for others). Keep your handler fast, or buffer on your side.
- Ordering. Events are delivered in broadcast order per connection. There is no replay/backfill — you only get events that occur while you're connected. For historical data use the REST scoreboard / timeline (
/api/Game/{id}/Ad/Scoreboard,/api/Game/{id}/Ad/Timeline). - It's a mirror. The plain-WS feed and the SignalR hub publish the same events at the same time; pick whichever client is easier for your tooling.
See also: Attack & Defense for the attack/submit/targets REST API, and Scoring for how these events turn into points.