DRAFT v0.3 / Protocol

Connection and subscription.

The proposed protocol uses a long-lived secure WebSocket. Clients authenticate once, create a scoped subscription, establish state from a snapshot, and process ordered deltas.

TRANSPORT

Connection

The production hostname is not yet active. The intended connection target is shown only to make the draft concrete.

wss://stream.oddsloom.com/v1
Encoding

UTF-8 JSON text frames for the initial beta.

Direction

Control messages are bidirectional; state and deltas flow server to client.

Compression

WebSocket compression policy remains under evaluation.

Environment

Sandbox and production credentials will be isolated.

CLIENT → SERVER

Authentication

The proposed handshake sends a scoped API key in the first application frame. This avoids putting credentials in URLs and keeps authentication explicit.

{
  "type": "session.authenticate",
  "request_id": "req_01J5Y7JVB6",
  "data": { "api_key": "ol_test_••••••••" }
}

Until the service exists, key format, scopes, rotation, and authentication timeouts remain design decisions rather than guarantees.

SERVER → CLIENT

Session ready

A successful handshake returns session capabilities before subscriptions are accepted.

{
  "type": "session.ready",
  "schema_version": "0.3",
  "message_id": "msg_01J5Y7K2DX",
  "sequence": 0,
  "emitted_at": "2026-08-07T05:19:59.981Z",
  "data": {
    "session_id": "ses_01J5Y7K1Y7",
    "environment": "sandbox",
    "heartbeat_interval_ms": 15000,
    "resume_supported": true
  }
}
session_idstringIdentifier for this connection lifetime.
environmentenumsandbox or production.
heartbeat_interval_msintegerExpected maximum interval between liveness messages.
resume_supportedbooleanWhether this session class supports replay from a committed position.
CLIENT → SERVER

Create a subscription

Filters describe the state the consumer wants maintained. The server validates the combination and returns the effective scope; it does not silently broaden a request.

{
  "type": "subscription.create",
  "request_id": "req_01J5Y7KZXN",
  "data": {
    "sports": ["basketball"],
    "leagues": ["nba"],
    "books": ["book_a", "book_b"],
    "market_types": ["moneyline", "spread", "total"],
    "event_phase": ["pregame", "live"]
  }
}
sportsstring[]Canonical sport keys.
leaguesstring[]?Optional league restriction.
booksstring[]Canonical book IDs to include.
market_typesstring[]?Optional canonical market families.
event_phaseenum[]?pregame, live, or both.
SERVER → CLIENT

Subscription ready

The accepted message establishes the stream position immediately before the initial snapshot.

{
  "type": "subscription.ready",
  "schema_version": "0.3",
  "message_id": "msg_01J5Y7M0A2",
  "sequence": 18490,
  "emitted_at": "2026-08-07T05:20:00.041Z",
  "data": {
    "subscription_id": "sub_01J5Y7KZXN",
    "effective_filters": {
      "sports": ["basketball"],
      "leagues": ["nba"],
      "books": ["book_a", "book_b"]
    }
  }
}

Lifecycle

OPENAUTHSESSION READYSUBSCRIBESUBSCRIPTION READYSNAPSHOTLIVE DELTAS

Subscription modification and multiple concurrent subscriptions are still open design questions. The first beta may intentionally support one subscription per connection to keep sequence ownership unambiguous.

CONTINUEExplore the entity model