Every message has one job.
These v1 shapes mirror the executable delivery service and machine-readable OpenAPI and AsyncAPI contracts.
Catalog
session.authenticatedFirst-frame authentication succeeded.CONTROLsubscription.acceptedThe snapshot position and effective scope were accepted at sequence 0.CONTROLstate.snapshotComplete canonical REST state with a short-lived stream position.STATEstate.upsertFully replace a canonical reference entity.DELTAstate.removeRemove a reference entity in dependency-safe order.DELTAodds.upsertCreate or fully replace one quote.DELTAodds.removeExplicitly remove one quote.DELTAsource.statusReport streaming or degraded source state.CONTROLcoverage.manifestAnnounce release-gate changes before removals.CONTROLstate.snapshot
The REST endpoint returns a complete graph-safe snapshot. It contains canonical markets only, the effective scope, exact release gates, source status, and the short-lived position the WebSocket subscription must declare.
{
"schema_version": "1",
"type": "state.snapshot",
"sequence": 1,
"snapshot_position": 1,
"message_id": "550e8400-e29b-41d4-a716-446655440010",
"emitted_at": "2026-08-12T15:20:00.120Z",
"effective_scope": { ... },
"coverage_manifest": [ ... ],
"sources": [ ... ],
"snapshot": {
"sports": [ ... ], "leagues": [ ... ],
"participants": [ ... ], "events": [ ... ],
"markets": [ ... ], "outcomes": [ ... ], "quotes": [ ... ]
}
}schema_versionstringAlways 1 on this route.snapshot_positionintegerMust still be current when creating the matching stream subscription.message_idUUIDUnique message identifier.emitted_atRFC 3339OddsLoom publication time.snapshotobjectComplete canonical graph for the effective scope.state.upsert
Additions and corrections replace a complete canonical entity. Upserts arrive in dependency order: sport, league, participant, event, market, outcome, then quote.
{
"schema_version": "1", "type": "state.upsert", "sequence": 1,
"message_id": "550e8400-e29b-41d4-a716-446655440011",
"emitted_at": "2026-08-12T15:20:00.400Z",
"entity_type": "event",
"entity": { ... }
}odds.upsert
Create or replace one quote. A suspension is an upsert with availability: suspended; a correction is a replacement at a higher sequence.
{
"schema_version": "1", "type": "odds.upsert", "sequence": 3,
"message_id": "550e8400-e29b-41d4-a716-446655440012",
"emitted_at": "2026-08-12T15:20:00.438Z",
"quote": {
"id": "quote_01...", "eventId": "evt_01...",
"marketId": "mkt_01...", "outcomeId": "out_01...",
"bookId": "draftkings", "jurisdiction": "US-IL",
"availability": "open", "line": 5.5,
"price": { "american": -105, "decimal": 1.9524 },
"source": { "eventId": "src_evt_01...", "marketId": "src_mkt_01...", "selectionId": "src_sel_01..." },
"observedAt": "2026-08-12T15:20:00.432Z"
}
}Explicit removals
odds.remove removes a quote. state.remove uses entity_type and entity_id. Removals arrive quote-first so references never dangle.
{
"schema_version": "1", "type": "odds.remove", "sequence": 3,
"message_id": "550e8400-e29b-41d4-a716-446655440013",
"emitted_at": "2026-08-12T15:20:01.014Z",
"quote_id": "quote_01..."
}source.status
When a released source becomes stale or fails, OddsLoom reports it as degraded and removes its last-known quotes rather than presenting them as current.
{
"schema_version": "1", "type": "source.status", "sequence": 4,
"message_id": "550e8400-e29b-41d4-a716-446655440014",
"emitted_at": "2026-08-12T15:20:15.000Z",
"sources": [{
"book_id": "draftkings", "jurisdiction": "US-IL",
"phase": "live", "status": "degraded",
"last_success_at": "2026-08-12T15:19:59.000Z"
}]
}Publication and observation time
The envelope’s emitted_at is when OddsLoom published the state. A quote’s observedAt is when OddsLoom observed the provider state; source-provided clocks may be absent and are not invented.