Skip to main content

WebSocket API

Real-time data streaming for Hypercall options trading.

Interactive Reference

Check out the Interactive WebSocket API Reference for a better browsing experience with live examples and schema details.

Machine-Readable Spec

Download the AsyncAPI specification for programmatic use.

Connection

Connect to wss://HOST/ws with optional query parameters:

ParameterRequiredDescription
walletFor auth channelsYour wallet address (hex string)
API Not Yet Public

The Hypercall API is not yet publicly available. The examples below use placeholder URLs. Check back after testnet launch for live endpoints.

Endpoints:

  • Production: wss://api.hypercall.io/ws
  • Local: ws://localhost:3000/ws

Connection Liveness

The server enforces a WebSocket heartbeat:

  • Sends a Ping control frame every 20 seconds
  • Expects a matching Pong within 60 seconds
  • Closes the connection with close code 1008 and reason pong timeout if the client stops answering

Browser WebSocket implementations handle ping/pong automatically. Many Rust websocket libraries, including tungstenite and tokio-tungstenite, also handle control-frame ping/pong for you. Check your client's library documentation before adding manual Pong handling. Custom or raw socket implementations must reply to Ping frames with Pong.

Subscribing to Channels

Send a JSON message to subscribe:

{"type": "Subscribe", "channel": "orderbook"}

To unsubscribe:

{"type": "Unsubscribe", "channel": "orderbook"}

You'll receive a confirmation:

{"type": "Subscribed", "channel": "orderbook"}

Available Channels

ChannelAuth RequiredDescription
orderbookNoL2 orderbook updates for all symbols
tradesNoPublic trade feed
market_updatesNoMarket listing changes (created/deleted/expired)
order_updatesYesYour order status changes
fillsYesYour trade fills
portfolioYesYour position and balance updates
liquidationYesYour liquidation state changes
competitionYesYour competition PnL summary, rank, and final stats

Message Types

Orderbook Update

L2 orderbook snapshot/update for a symbol.

{
"type": "OrderbookUpdate",
"symbol": "BTC-20260131-100000-C",
"bids": [["95000.5", "10.5"], ["94999.0", "25.0"]],
"asks": [["95001.0", "8.0"], ["95002.5", "15.0"]],
"timestamp": 1737331200000
}
FieldTypeDescription
symbolstringOption symbol
bidsarrayBid levels as [price, size] tuples, size is in human-readable contracts
asksarrayAsk levels as [price, size] tuples, size is in human-readable contracts
timestampintegerUnix timestamp (milliseconds)

Trade

Public trade event.

{
"type": "Trade",
"symbol": "BTC-20260131-100000-C",
"price": "0.0523",
"size": "5.0",
"side": "buy",
"timestamp": 1737331200000
}
FieldTypeDescription
symbolstringOption symbol
pricestringTrade price in USD
sizestringTrade size in contracts
sidestringAggressor side (buy or sell)
timestampintegerUnix timestamp (milliseconds)

Fill (Authenticated)

Your trade fill notification.

{
"type": "Fill",
"order_id": 12345,
"fill_id": 67890,
"symbol": "BTC-20260131-100000-C",
"side": "buy",
"price": "0.0523",
"size": "5.0",
"timestamp": 1737331200000,
"wallet_address": "0x1234...abcd",
"fee": "0.0005",
"trade_id": 99999,
"is_taker": true
}
FieldTypeDescription
order_idintegerYour order ID
fill_idintegerFill ID
symbolstringOption symbol
sidestringTrade side (buy or sell)
pricestringFill price in USD
sizestringFill size in contracts
timestampintegerUnix timestamp (milliseconds)
wallet_addressstringYour wallet address
feestringTrading fee charged
trade_idintegerUnique trade ID
is_takerbooleanWhether you were the taker
builder_code_addressstring?Builder code wallet (if any)
builder_code_feestring?Builder code fee (if any)

Portfolio Update (Authenticated)

Portfolio stream update for positions, balances, margin, and Greeks.

Greeks update example:

{
"type": "PortfolioUpdate",
"timestamp": 1737331200000,
"per_leg": [
{
"symbol": "BTC-20260131-100000-C",
"quantity": "2.0",
"delta": 0.91,
"gamma": 0.003,
"theta": -0.12,
"vega": 0.44,
"iv": 0.63
}
],
"aggregate": {
"delta": 0.91,
"gamma": 0.003,
"theta": -0.12,
"vega": 0.44,
"iv": 0.63
}
}

For empty portfolios, Greeks updates use:

  • per_leg: []
  • aggregate: null

Competition PnL Summary (Authenticated)

Competition stream update for header/footer PnL display.

{
"type": "CompetitionPnlSummary",
"wallet_address": "0x1234...abcd",
"lifetime_realized_pnl": "1250.50",
"active_competition": {
"competition_id": 7,
"competition_name": "Spring Sprint",
"competition_state": "active",
"rank": 12,
"pnl": "420.25",
"volume": "25000",
"efficiency": "0.01681",
"medal": null
},
"timestamp": 1737331200000
}

When there is no active competition, active_competition is null.

Order Update (Authenticated)

Order status change notification.

{
"type": "OrderUpdate",
"order_id": 12345,
"client_order_id": "my-order-1",
"status": "filled",
"filled_size": "10.0",
"remaining_size": "0",
"avg_fill_price": "0.0523"
}

Market Update

Market listing changes.

Market Created:

{
"type": "MarketUpdate",
"action": "Created",
"symbol": "BTC-20260131-100000-C",
"strike": "100000",
"is_call": true,
"underlying": "BTC",
"expiry": 1738281600,
"timestamp": 1737331200000
}

Market Expired:

{
"type": "MarketUpdate",
"action": "Expired",
"symbol": "BTC-20260131-100000-C",
"strike": "100000",
"is_call": true,
"underlying": "BTC",
"expiry": 1738281600,
"timestamp": 1738281600000
}

Position Expired (Authenticated)

Notification when your position settles at expiry.

{
"type": "PositionExpired",
"wallet_address": "0x1234...abcd",
"symbol": "BTC-20260131-100000-C",
"position_size": "10.0",
"settlement_price": "105000",
"settlement_value": "500.0",
"timestamp": 1738281600000
}

Liquidation State Change (Authenticated)

Your account liquidation state change.

{
"type": "LiquidationStateChange",
"wallet_address": "0x1234...abcd",
"previous_state": "Normal",
"new_state": "Warning",
"equity": "10000.0",
"mm_required": "9500.0",
"shortfall": "0",
"auction_id": null,
"timestamp": 1737331200000
}
StateDescription
NormalAccount is healthy
WarningApproaching margin call
LiquidatingLiquidation auction active

Error

Server error message.

{
"type": "Error",
"message": "Invalid channel: foobar"
}

Authentication

Authenticated channels require the wallet query parameter in the connection URL:

wss://api.hypercall.io/ws?wallet=0x1234567890abcdef...

Messages on authenticated channels are filtered to only show data for your wallet. No signature is required for WebSocket connections.

Example: Python Client

import asyncio
import websockets
import json

async def main():
uri = "wss://api.hypercall.io/ws?wallet=0xYourWallet"

async with websockets.connect(uri) as ws:
# Subscribe to orderbook
await ws.send(json.dumps({
"type": "Subscribe",
"channel": "orderbook"
}))

# Subscribe to your fills
await ws.send(json.dumps({
"type": "Subscribe",
"channel": "fills"
}))

# Listen for messages
async for message in ws:
data = json.loads(message)
print(f"Received: {data['type']}")

asyncio.run(main())

Example: TypeScript Client

const ws = new WebSocket(
"wss://api.hypercall.io/ws?wallet=0xYourWallet"
);

ws.onopen = () => {
// Subscribe to channels
ws.send(JSON.stringify({ type: "Subscribe", channel: "orderbook" }));
ws.send(JSON.stringify({ type: "Subscribe", channel: "fills" }));
};

ws.onmessage = (event) => {
const msg = JSON.parse(event.data);
console.log(`Received: ${msg.type}`);

if (msg.type === "OrderbookUpdate") {
console.log(`${msg.symbol}: ${msg.bids.length} bids, ${msg.asks.length} asks`);
}
};