Time semantics
There are three timestamps in play, and they answer three different questions. Use the right one — they are not interchangeable.
receivedAt — local clock, on every event payload
Section titled “receivedAt — local clock, on every event payload”Every SDK event payload carries receivedAt: number (ms since epoch, from Date.now()). It records the moment the SDK received the message, on your machine’s clock.
client.on('odds:changed', ({ quote, receivedAt }) => { const sdkLatencyMs = Date.now() - receivedAt // very small unless you queued the callback})Use it for:
- End-to-end latency analysis (gateway → SDK).
- Stale-data detection (“alert if no
odds:changedfor selection X in the last 10 seconds”). - Ordering events from the same connection, since they’re monotonic per-client.
Don’t use it to compare against another machine’s clock — it’s local.
quote.timestamp — observation time
Section titled “quote.timestamp — observation time”Every Quote has a timestamp: number. It’s set by whichever party constructed the Quote — usually the gateway, occasionally the SDK during hydration.
It approximates how fresh the quote is — but it is not the bookmaker’s authoritative emit time. The gateway doesn’t get that from upstream; it stamps the Quote when it processes the update.
Use it for:
- Rough freshness checks (“this quote is more than 30s old, treat as stale”).
- Cross-bookmaker comparisons when you need a single notion of “around when”.
Don’t use it for:
- Sub-second arbitrage windows — the gateway’s clock and the bookmaker’s clock are not synchronised.
- Latency budgets —
receivedAt - quote.timestampincludes whatever staleness was already in the gateway’s view.
orderBook.timestamp
Section titled “orderBook.timestamp”Same semantics as quote.timestamp, but for the full order book snapshot. Set when the gateway constructs the OrderBook.
sportEvent.startDate
Section titled “sportEvent.startDate”The scheduled match start time, as a Luxon DateTime. Optional — some bookmakers don’t provide it. Use it for “this match starts in N minutes” displays. Not related to update freshness.
| You want to know… | Use… |
|---|---|
| When the SDK saw this update | receivedAt |
| Roughly how fresh this price is | quote.timestamp |
| When the match starts | sportEvent.startDate |
| End-to-end SDK latency | Date.now() - receivedAt |
| Whether the connection is down | client.snapshot().stale |