Streaming API (Socket.IO)
Real-time feeds use Socket.IO over WebSockets, on a different host from the REST API. The REST endpoints underhttps://api.4cx.io are not WebSocket endpoints.
Server
Authentication
You authenticate the socket connection with the same REST session token returned by Log in (data.user.auth). Pass it on the handshake — either as a query parameter or as the Authorization header. No Bearer prefix — the raw token only.
Error: not authorized.
Recommended Socket.IO clients
- JavaScript: socket.io-client
- Java: socket.io-client-java
- C++: socket.io-client-cpp
Namespaces
The server uses Socket.IO namespaces to separate feeds. Connect to a namespace by appending it to the host.<username> must be the username of the account whose token you’re using (not the email, not the ObjectId). The server enforces this — if the namespace username doesn’t match the token owner, the handshake is rejected.
All event payloads are stringified JSON. You must
JSON.parse them in your handler. The server does this so the wire format is uniform across clients regardless of how their Socket.IO library serializes objects./priceUpdates events
orderUpdate
Emitted when a single side of a market changes — a new resting order, a fill, a cancel, or an edit. One emission per side that changed.
Outer payload (after JSON.parse):
Each
sideOrders entry:
gameUpdate
Emitted when a game is first published, its market opens or closes, the start time changes, or odds across the full game are republished (e.g. by a seeding job).
Payload includes: id, parentGameID, league, sport, start, ended, participants, awayMoneylines, homeMoneylines, awaySpreads, homeSpreads, over, under, mainHomeSpread, mainAwaySpread, mainTotal, and messageType (marketOpen | marketClosed) when present.
Full payloads are large; ask your integration contact for a sample if you need the exact field set for a given league.
/v2/user/<username> events
This namespace emits exactly one event: positionUpdate. Every state change on one of your orders, and every fill that involves you (as offerer or taker), arrives as a positionUpdate.
Payload shape
unmatched— state of your resting offer. Fields:orderID,odds,offered(original size),filled(cumulative amount filled into this order),remaining(offered - filled). Present whenever your resting state changed.matched— the fill that just occurred. Fields:txID(cross-reference with REST matched-play endpoints),filled(size of this specific fill),odds(always from your side — if you offered −105 you’ll see −105 here even though the counterparty saw +105). Present whenever a fill involving you just happened.
origin field is a hint emitted by the server:
origin: "offer"—unmatchedis present (your resting offer changed in some way).origin: "wager"— onlymatchedis present, nounmatched(you took someone else’s resting liquidity).
How to tell what just happened
Use the table below in your handler. All checks are on the parsedpositionUpdate payload.
Example handler
REST cross-reference
For looking up atxID (matched fills) or orderID (your resting state), see Look up single order. To list all of your current open offers in one call, use List my open orders.