WebSocket Guide
Real-time market data via WebSocket.
Connection
Served by the gateway at /v1/ws — same host as the REST API (e.g.
wss://api.parti.com/v1/ws in production). No auth needed for public
market-data channels.
Subscribing to Channels
After connecting, send JSON messages to subscribe. The message field is
type (not action):
{"type": "subscribe", "channel": "book:abc123def456..."}
Available channels (served by the gateway relay today):
| Channel | Events | Description |
|---|---|---|
book:{market_id} |
book_update | Order book changes with prices |
trades:{market_id} |
trade | Individual fills on a market |
Other channel kinds (
user:,markets,price:,sports:) are reserved for the per-market MarketEngine DO feed and are not served by the current gateway relay — subscribing returnsunknown_channel_kind.
Heartbeat: send {"type":"ping"} → server replies {"type":"pong"}.
Unsubscribe:
{"type": "unsubscribe", "channel": "book:abc123def456..."}
Server acknowledgement:
{"type": "subscribed", "channel": "book:abc123def456..."}
Event Types
Trade
Emitted on every fill. Sent to trades:{market_id} and user:{maker} / user:{taker} channels.
{
"type": "trade",
"market_id": "abc123...",
"trade": {
"maker_order_id": 10,
"taker_order_id": 42,
"maker": "0x4b2a9e7c...",
"taker": "0x7a3f1c0d...",
"quantity": 100,
"price": 6200,
"settlement_type": "mint",
"maker_side": "sell",
"taker_side": "buy",
"outcome": "yes",
"timestamp": 1700000000,
"taker_fee": 12,
"maker_rebate": 3
}
}
BookUpdate
Emitted after every order submission, cancellation, or fill. Contains the full order book snapshot plus live prices.
{
"type": "book_update",
"market_id": "abc123...",
"snapshot": {
"market_id": "abc123...",
"yes_bids": [{"price": 6200, "size": 500, "order_count": 3}],
"yes_asks": [{"price": 6300, "size": 200, "order_count": 1}],
"no_bids": [{"price": 3700, "size": 200, "order_count": 1}],
"no_asks": [{"price": 3800, "size": 500, "order_count": 3}],
"yes_price": 6250,
"no_price": 3750,
"best_yes_bid": 6200,
"best_yes_ask": 6300,
"best_no_bid": 3700,
"best_no_ask": 3800,
"spread": 100,
"total_volume": 150000,
"timestamp": 1700000000,
"sequence": 42
}
}
Use sequence to detect gaps. If you see a jump, re-fetch via GET /v1/markets/{id}/book.
MarketUpdate
Emitted when a market's status changes (resolved, halted).
{
"type": "market_update",
"market_id": "abc123...",
"market": {
"market_id": "abc123...",
"status": "resolved",
"resolved_outcome": "yes",
"yes_price": 10000,
"no_price": 0
}
}
Backpressure
The server buffers up to 4096 messages per client. If your client falls behind:
{"type": "error", "code": "lagged", "message": "Dropped 50 messages due to slow consumption"}
When you receive a lagged error, re-fetch current state via REST for all subscribed markets.
Keepalive
Send a WebSocket ping frame every 30 seconds to keep the connection alive. The server responds with pong.
Example (JavaScript)
const ws = new WebSocket('wss://oracle-api.parti.com/v1/ws');
ws.onopen = () => {
// Subscribe to order book updates for a market
ws.send(JSON.stringify({
type: 'subscribe',
channel: `book:${marketId}`
}));
// Subscribe to trades
ws.send(JSON.stringify({
type: 'subscribe',
channel: `trades:${marketId}`
}));
};
ws.onmessage = (event) => {
const data = JSON.parse(event.data);
if (data.type === 'book_update') {
// Update order book display
updateOrderBook(data.snapshot);
// Update price display
updatePrice(data.snapshot.yes_price, data.snapshot.no_price);
}
if (data.type === 'trade') {
// Add to trade history
addTrade(data.trade);
}
};