WebSocket streams
Real-time market data and per-session event channels.
A single WebSocket endpoint streams live market data and per-session events. It's what keeps the live trading screen and the strategy results progress current in real time.
Endpoint
wss://api.0dtespx.com/__ws
Handshake
After connecting, you have 5 seconds to send an auth message — either anonymous or token-authenticated:
{"auth": "public"}
{"token": "8a4f3e21d6c94b0e9f2a1c5b7d8e4f60"}
A freshly authenticated connection has no subscriptions; you must explicitly subscribe to each channel you want. channels (array) and channel (single) are both accepted on subscribe and unsubscribe:
{"action": "subscribe", "channels": ["live_aggregate_data", "live_option_chain"]}
{"action": "unsubscribe", "channel": "live_option_chain"}
Wire format
Every server-sent message is a JSON object with a top-level channel field — dispatch on that, never on payload shape. Market-data channels nest their data under payload; event channels put id, type/data as siblings of channel:
{"channel": "live_aggregate_data", "payload": { … }}
{"channel": "live_option_chain", "payload": [{"strike": 5950, "call": {"bid": 4.2, "ask": 4.4, "delta": 0.523}, "put": {"bid": 3.1, "ask": 3.3, "delta": 0.477}}, … ]}
{"channel": "session_events", "id": 42, "session_id": "<uuid>", "account_id": "<uuid>", "type": "order_update", "payload": { … }}
{"channel": "end_of_data"}
Channels
| Channel | Cadence | Access |
|---|---|---|
live_aggregate_data |
1-second | Public + authenticated |
live_option_chain |
1-second | Token-authenticated only |
session_events |
Event-driven | Token-authenticated, per session |
backtest_events |
Event-driven | Token-authenticated, per strategy (source hash) |
assistant_draft_events |
Event-driven | Token-authenticated, per draft (owner only) |
end_of_data |
Terminal | — |
live_aggregate_data— the 1-second aggregate market feed: SPX, VIX, the expected move, and the two chain-wide premium totals (summed OTM bids and total extrinsic value) — the same series the historical endpoint serves for past sessions.live_option_chain— the latest SPX option-chain snapshot. Each strike'scallandputcarrybid,ask, anddelta— the same fields the REST snapshot endpointGET /market-data/option-chain-snapshots/{timestamp}returns. (Second-order Greeks, IV, and theoretical price are no longer provided.)session_events— discrete state changes for a live session:order_update(status transitions),financials_update(cash, buying power, realized P&L),ended, andsettlement_failed. Subscribe per session with{"action":"subscribe","channel":"session_events","session_id":"<uuid>"}; each envelope carries top-levelsession_idandaccount_idso clients route to per-session state. Per-tick continuous values (P&L, delta) aren't pushed here — compute them fromlive_option_chain.backtest_events— strategy results progress for one strategy's backtest. Subscribe per strategy with itssource_hash:{"action":"subscribe","channel":"backtest_events","source_hash":"<hex>"}(authorized against a saved strategy of yours with that source, or your live builder preview). Each frame carries the full fee-overlaid results snapshot underdata.snapshot(the same shapeGET /strategies/preview/{source_hash}/resultsreturns), folded for you — render straight from it, no per-tick refetch.data.typeis one ofstarted,day_completed,completed,stopped,failed. The HTTP results endpoint stays the source of truth for the initial load and reconnect. A dropped socket never stops a run; reconnect and re-subscribe.assistant_draft_events— the AI assistant chat stream for one of your drafts. Subscribe with the draft id:{"action":"subscribe","channel":"assistant_draft_events","draft_id":"<uuid>"}(authorized against your ownership of the draft).data.typeis one ofdelta(assistant text chunk),thinking(a chunk of the model's streamed reasoning while it works — display-only, not part of the final message),tool_status,ask_user,message(the finalized assistant message),preview({source_hash, description, risks}— the live preview moved to a new hash and the strategy description + risk scenarios were updated with it; re-key yourbacktest_eventssubscription to it),turn_complete,error. A reconnect may supplylast_event_by_draft(draft id → highest seen id) to replay the gap.
Event ordering and recovery
Event-channel envelopes carry a monotonically increasing id. backtest_events deliberately has no replay — but it needs none: each frame carries the full current snapshot, so a missed frame self-heals on the next one, and the HTTP results endpoint backs the initial load and reconnect. For live-session state after a disconnect, refetch positions, orders, and transactions over REST to be safe.
Connection limits
- Anonymous (
{"auth":"public"}) connections stream for at most 5 minutes, after which the server sends{"channel":"end_of_data"}and closes. They may subscribe tolive_aggregate_databut notlive_option_chain. - Token-authenticated accounts have no concurrency limit and no time cap.
Quick test
( echo '{"auth":"public"}'; cat ) | websocat 'wss://api.0dtespx.com/__ws'
Subscribe messages sent before auth completes are ignored, and unknown channel names are silently dropped.