WebSocket feed
Real-time book, trades and your own order events from the matching engine.
Connect to the engine's /ws endpoint. On this environment that is:
wss://api-prediction.daejin.xyz/clob-engine/wsAuthenticate the handshake, never the URL — query strings land in access logs:
- Node clients: send
X-API-Key: tp_…(orAuthorization: Bearer tp_…) as a header on the upgrade request. - Browsers signed in to the app: the session cookie travels automatically.
- Anonymous connections are accepted with public channels only, at two per address.
The first message is always hello:
{ "type": "hello", "epoch": 1758196800000, "seq": 41822,
"subject": { "kind": "key", "address": "0x…" },
"limits": { "maxSubs": 50, "maxConns": 5 }, "mode": "required" }Channels
Subscribe to what you want; you receive nothing else.
{ "type": "subscribe", "channels": ["book:evm:56:1042", "trades:evm:56:1042", "orders"] }| Channel | Who | Messages |
|---|---|---|
book:<market> | anyone | book — aggregated depth after every change |
trades:<market> | anyone | trade — price, size, side, outcome, settlement type. No wallets, no order ids. |
orders | a wallet's key or session | order (accepted, partial, filled, cancelled, expired, rejected, restored, closed), fill (your side), settlement (on-chain status with your order ids) |
Requesting a channel your credential may not see answers { "type": "error", "code": "unauthorized" }. At most 50 channels per connection and 10 inbound messages per second.
Sequence numbers and reconnecting
Every delivered message carries seq (monotonic per engine process) and ts. Keep the
last seq you saw and the epoch from hello. On reconnect:
{ "type": "subscribe", "channels": ["book:evm:56:1042"], "since": 41822, "epoch": 1758196800000 }The engine replays what you missed on those channels, in order, before live delivery.
If the gap is older than its buffer or epoch changed (the engine restarted, so the book
may differ), it answers { "type": "resync_required" }: fetch /markets/{market}/book
and /users/{user}/orders again, then continue from the live stream.
Reconnect with exponential backoff — 1s, 2s, 4s … capped at 30s, with jitter. The server pings every 25 seconds; answer pongs (every WebSocket library does) or it will drop you.
Message shapes
{ "type": "book", "seq": 1, "ts": 0, "market": "evm:56:1042",
"bids": [{ "price": 640, "size": "10000000" }], "asks": [{ "price": 660, "size": "5000000" }] }
{ "type": "trade", "seq": 2, "ts": 0, "market": "evm:56:1042",
"price": 660, "size": "4000000", "settlement": "TRADE", "side": "buy", "outcome": "YES" }
{ "type": "order", "seq": 3, "ts": 0, "event": "partial",
"order": { "id": "o104", "market": "evm:56:1042", "status": "partial", "action": "sell",
"outcome": "YES", "price": 660, "size": "10000000", "remaining": "6000000",
"type": "GTC", "createdAt": 0 } }
{ "type": "fill", "seq": 4, "ts": 0, "market": "evm:56:1042", "orderId": "o104",
"role": "maker", "price": 660, "size": "4000000", "settlement": "TRADE" }
{ "type": "settlement", "seq": 5, "ts": 0, "id": 17, "status": "settled",
"ref": "0x…txhash", "orderIds": ["o104"] }Prices are integer ticks (1000 = $1.00); sizes are decimal strings in the collateral's base units.