Skip to content

Snapshot vs events

The SDK gives you two complementary ways to read the world: a synchronous snapshot of the current state, and streaming events as it changes. Use both — they’re cheap and they’re always consistent with each other.

const { sportEvents, stale } = client.snapshot()
// sportEvents: ReadonlyMap<SportEventId, SportEvent>
// stale: true when the connection is currently down

The snapshot is a live view of the SDK’s internal store. It’s not a copy — it reflects everything received so far, every time you read it.

Use it when:

  • You’re rendering a dashboard and need to draw the current state of all events.
  • You just started up and want to see what’s already known before subscribing.
  • A user navigated to a screen mid-session and you need to populate it.
function renderEventList() {
const { sportEvents } = client.snapshot()
return [...sportEvents.values()]
.filter(ev => ev.sport === 'basketball')
.map(ev => `${ev.name}${ev.markets.size} markets`)
}

Lookup by id is O(1) via client.getSportEvent(id) or snapshot().sportEvents.get(id).

Events — what changed since you last looked

Section titled “Events — what changed since you last looked”

Subscribe to events to react to changes:

EventWhen
sportEvent:addedA sport event is observed for the first time (per bookmaker).
sportEvent:updatedThe event’s metadata, market list, or any odds value changed.
sportEvent:removedA sport event is no longer reported by its source.
odds:changedA specific selection’s quote (or order book) changed. Fires alongside sportEvent:updated.
client.on('odds:changed', ({ bookmaker, selectionId, quote }) => {
console.log(`${bookmaker} ${selectionId}${quote.price}`)
})

See the Events reference for full payload shapes.

sportEvent:updated fires on every change to a sport event, including odds updates — the gateway’s store creates a new immutable instance each time, so consumers tracking by reference need the new one. This means:

  • If you only want to know when an event is added or removed, subscribe to sportEvent:added/sportEvent:removed.
  • If you want to know when anything about an event changes (so you can re-render it as a whole), subscribe to sportEvent:updated.
  • If you want per-selection price updates only, subscribe to odds:changed — it carries just the new quote plus its identifiers, so you don’t have to diff the whole event.

You’ll often subscribe to both sportEvent:updated (for re-rendering) and odds:changed (for line-move detection or alerting).

When you call connect(), the gateway sends the SDK its current state in one or more frames. The SDK populates the store before resolving connect(). This means:

  1. Right after await client.connect(), client.snapshot() is already populated.
  2. The sportEvent:added events that fire during the initial sync also fire — you’ll see one per existing event. If you only want to handle new events, attach the listener after await connect() if that fits, or filter using a “ready” flag.
// Pattern: ignore initial-sync events
let ready = false
client.on('sportEvent:added', ({ sportEvent }) => {
if (!ready) return // skip during initial sync
notifyNewMatch(sportEvent)
})
await client.connect()
ready = true

For UI: read the snapshot on first paint, subscribe to sportEvent:updated to invalidate cached views by id. The snapshot is fresh enough to drive any list view, and event-driven updates keep your UI in sync without polling.