Messages
The user feed sends each update as a bare JSON object (no tuple envelope). All updates share one envelope; the action is determined by which ofunmatched / matched are populated and by origin.
Common envelope
messageID is the stream entry id added by the streaming-api before send. Persist the latest one you have processed — it is your replay cursor. See Replaying missed messages below.
How to identify the action
unmatched.filled === 0 && unmatched.offered > 0-> order placedunmatched.offered === 0-> order cancelledmatched != null && unmatched == null-> matched as takermatched != null && unmatched != null-> matched as maker (partial fill ifunmatched.remaining > 0)
orderType: "postArb" also carry isPostArb: true inside matched / unmatched (on placed, filled, and cancelled updates); the field is omitted otherwise.
Side and market semantics by bet type
The meaning ofside (and which extra fields appear) inside matched / unmatched depends on type:
market is only present on moneyline1x2 updates: it names the 3-way outcome the market is about (home team, away team, or the draw), and side says whether the bet is yes or no on that outcome. All fields are from your perspective — as maker you see your posted side; as taker you see the side you took.
Action: order placed
A new offer was put on the book.unmatched.filled is 0, unmatched.offered > 0, and matched is null.
Action: order cancelled
The user (or the system on their behalf) cancelled an offer. The distinguishing field isunmatched.offered === 0.
Action: order matched (taker)
The user took someone else’s offer.unmatched is null, matched carries the fill, and origin is "wager".
Action: order matched (maker, partial fill)
Someone hit the user’s posted offer. Bothmatched and unmatched are populated; unmatched.remaining shows what is still on the book. Because unmatched is set, origin is "offer".
Action: order matched (moneyline1x2)
Fills on 3-way soccer markets carry themarket + side pair described above instead of a participant-hex side. Here the user took “yes” on the home team at +120 (a bet that Arsenal wins):
side: "yes" at +120, the maker sees side: "no" at -120 on the same market.
Replaying missed messages
The v2 user feed supports gap recovery after a dropped connection. Every message carries amessageID (a monotonically increasing stream entry id, e.g. "1751552702114-0"). If your connection drops, you can fetch exactly the messages you missed.
Endpoint
Authorization header, Auth header, or token query parameter. Only messages belonging to the authenticated user are returned.
Response: success
Your afterID was still present in the retained history, so the returned list is a complete gap-fill — nothing between afterID and beforeID was lost:
Response: cache_expired
Your afterID has aged out of the retained history, so the server cannot prove the replay is complete:
availableMessages is whatever is still retained, oldest first. Messages older than the retention window are not recoverable through replay — reconnect promptly rather than relying on long look-back.