Websocket
Real-time orderbook, trade, and market updates via WebSocket.
Connection
wss://api.turbinefi.com/api/v1/streamNo authentication is required. The WebSocket endpoint is public.
Connection Lifecycle
- The server sends a ping every 54 seconds.
- Clients must respond with a pong within 60 seconds or the connection is closed.
- On subscribe, you receive a confirmation message followed by the current orderbook snapshot.
Example
const ws = new WebSocket("wss://api.turbinefi.com/api/v1/stream");
ws.onopen = () => {
console.log("Connected");
};
ws.onmessage = (event) => {
const msg = JSON.parse(event.data);
console.log(msg.type, msg.data);
};Subscribe
Subscribe to real-time updates for a market. You can optionally filter by outcome.
Request
{
"type": "subscribe",
"marketId": "0x1234...abcd"
}With outcome filter:
{
"type": "subscribe",
"marketId": "0x1234...abcd",
"data": {
"outcome": 0
}
}| Field | Type | Description |
|---|---|---|
| type | string | "subscribe" |
| marketId | bytes32 | Market to subscribe to |
| data.outcome | uint8 | Optional. 0 = YES only, 1 = NO only. Omit for all outcomes |
Response
You receive a subscription confirmation followed by the initial orderbook snapshot:
{
"type": "subscribe",
"marketId": "0x1234...abcd",
"data": {
"status": "subscribed"
}
}Unsubscribe
Stop receiving updates for a market.
Request
{
"type": "unsubscribe",
"marketId": "0x1234...abcd"
}Response
{
"type": "unsubscribe",
"marketId": "0x1234...abcd",
"data": {
"status": "unsubscribed"
}
}Event Types
All server messages follow this format:
{
"type": "<event_type>",
"marketId": "0x...",
"data": { ... }
}orderbook
Full orderbook snapshot sent on subscribe and after each trade or order change.
| Field | Type | Description |
|---|---|---|
| bids | array | Buy orders, sorted by price descending |
| asks | array | Sell orders, sorted by price ascending |
| bids[].price | uint64 | Bid price (6 decimals). 450000 = $0.45 |
| bids[].size | uint64 | Total size at this price (6 decimals). 20000000 = 20 shares |
| asks[].price | uint64 | Ask price (6 decimals). 550000 = $0.55 |
| asks[].size | uint64 | Total size at this price (6 decimals) |
| lastUpdate | uint64 | Unix timestamp of last update |
trade
Sent when a trade is executed.
| Field | Type | Description |
|---|---|---|
| price | uint64 | Trade price (6 decimals). 550000 = $0.55 |
| size | uint64 | Trade size (6 decimals). 10000000 = 10 shares |
| outcome | uint8 | 0 = YES, 1 = NO |
| timestamp | uint64 | Unix timestamp |
| tradeHash | string | Unique trade identifier |
| maker | address | Limit order placer |
| taker | address | Market order placer |
| side | uint8 | Taker's side: 0 = BUY, 1 = SELL |
trade_error
Sent when an on-chain trade settlement fails.
| Field | Type | Description |
|---|---|---|
| buyer | address | Buyer's wallet address |
| seller | address | Seller's wallet address |
| price | uint64 | Trade price (6 decimals) |
| size | uint64 | Trade size (6 decimals) |
| txHash | string | Failed transaction hash |
| error | string | Error description |
order_cancelled
Sent when an order is cancelled, either by the user or by the system (e.g., during market rebalancing).
| Field | Type | Description |
|---|---|---|
| orderHash | string | Cancelled order hash |
| marketId | string | Market identifier |
| side | string | "buy" or "sell" |
| trader | address | Order owner |
| reason | string | Cancellation reason (e.g., "user_cancelled", "market_rebalancing") |
quick_market
Broadcast to all connected clients when a quick market is created or resolved.
| Field | Type | Description |
|---|---|---|
| data.type | string | "new_market" or "resolved" |
| data.asset | string | Asset symbol (e.g., "BTC") |
| data.marketId | string | Market identifier |
| data.quickMarket | object | Quick market details |
Quick market events are sent to all connected clients regardless of subscriptions.
Full Example
const ws = new WebSocket("wss://api.turbinefi.com/api/v1/stream");
ws.onopen = () => {
// Subscribe to a market (YES outcome only)
ws.send(JSON.stringify({
type: "subscribe",
marketId: "0x1234...abcd",
data: { outcome: 0 }
}));
};
ws.onmessage = (event) => {
const msg = JSON.parse(event.data);
switch (msg.type) {
case "subscribe":
console.log("Subscribed:", msg.data.status);
break;
case "orderbook":
console.log("Bids:", msg.data.bids);
console.log("Asks:", msg.data.asks);
break;
case "trade":
console.log(`Trade: ${msg.data.size} shares at $${msg.data.price / 1000000}`);
break;
case "trade_error":
console.error("Settlement failed:", msg.data.error);
break;
case "order_cancelled":
console.log("Order cancelled:", msg.data.orderHash, msg.data.reason);
break;
case "quick_market":
console.log("Quick market:", msg.data.type, msg.data.asset);
break;
}
};
ws.onclose = () => {
console.log("Disconnected");
};import websocket
import json
def on_message(ws, message):
msg = json.loads(message)
print(f"{msg['type']}: {msg.get('data')}")
def on_open(ws):
ws.send(json.dumps({
"type": "subscribe",
"marketId": "0x1234...abcd"
}))
ws = websocket.WebSocketApp(
"wss://api.turbinefi.com/api/v1/stream",
on_message=on_message,
on_open=on_open
)
ws.run_forever()