Skip to main content

Contract WebSocket Guide

The BigONE Contract WebSocket API differs significantly from the Spot API. It uses a URL-based subscription model for public data and a Header-based authentication model for private streams.

Prerequisites

  • Public URL Base: wss://api.big.one/ws/contract/v2
  • Private URL: wss://api.big.one/ws/contract/v2/stream
  • Authentication: Handled via the HTTP Authorization header during the handshake.

Lesson 1: Public Market Data (URL Based)

Unlike the Spot API, where you send a JSON message to subscribe, the Contract API subscribes you based on the URL path you connect to.

The Logic

To watch a specific channel, you open a new connection to that specific URL. If you want to watch multiple markets, you open multiple connections.

Available Channels:

  • Order Book: .../depth@{symbol}
  • Trades: .../trades@{symbol}
  • Candlesticks: .../candlesticks/{period}@{symbol}

Code Example: Watch BTCUSD Order Book

import asyncio
import websockets
import json

# Note: The symbol is part of the URL
URL = "wss://api.big.one/ws/contract/v2/depth@BTCUSD"

async def watch_depth():
async with websockets.connect(URL) as ws:
print("Connected to BTCUSD Order Book")
while True:
msg = await ws.recv()
data = json.loads(msg)

# The first message is a full snapshot
# Subsequent messages are incremental updates
print(f"Update received. Best Bid: {data['bestPrices']['bid']}")

if __name__ == "__main__":
asyncio.run(watch_depth())

Lesson 2: Private Data Streams (Header Authentication)

To receive updates for your Positions, Orders, and Balances, you connect to a single unified "Stream" channel.

The Logic

  1. Generate a standard JWT.
  2. Pass the JWT in the Authorization header during the WebSocket handshake.
  3. The server validates the header. If invalid, the connection is closed with a 401 error.

Private Stream URL: wss://api.big.one/ws/contract/v2/stream

Code Example: Private Updates

import asyncio
import websockets
import json
import time
import jwt

API_KEY = "YOUR_KEY"
SECRET_KEY = "YOUR_SECRET"

def generate_token():
payload = {
"sub": API_KEY,
"nonce": int(time.time() * 1000000),
"iat": int(time.time()),
"exp": int(time.time()) + 60
}
return jwt.encode(payload, SECRET_KEY, algorithm="HS256")

async def watch_private():
token = generate_token()
headers = {"Authorization": f"Bearer {token}"}

url = "wss://api.big.one/ws/contract/v2/stream"

async with websockets.connect(url, extra_headers=headers) as ws:
print("Connected to Private Stream")
while True:
msg = await ws.recv()
data = json.loads(msg)

# The response is a container object
if "positions" in data:
for pos in data['positions']:
print(f"Position Update: {pos['symbol']} size: {pos['size']}")

if "orders" in data:
for order in data['orders']:
print(f"Order {order['id']} is {order['status']}")

if __name__ == "__main__":
asyncio.run(watch_private())

Complete Example: Multi-Stream Bot

For a real trading bot, you usually need to combine both.

import asyncio
import websockets
import json

async def main():
# Run both public and private listeners concurrently
await asyncio.gather(
watch_depth(), # From Lesson 1
watch_private() # From Lesson 2
)

if __name__ == "__main__":
asyncio.run(main())

Conclusion

The Contract WebSocket API is designed for performance with its URL-based routing.

Key Takeaways:

  • URL Subscription: Each public market/channel needs its own connection.
  • Header Auth: Private streams authenticate during the handshake, not via a message.
  • Snapshots: Expect a full snapshot as the first message on every channel.

Next Steps: