Bitget APIBitget API
UTAClassic
Legacy Doc
  • Overview
  • API Documentation
  • WebSocket
  • Agent Hub
  • SDK
  • Changelog
Copied to clipboard
Websocket
Public
Private
Reality
SBE
    SBE IntroductionSBE BBO Integration GuideSBE Level 50 Integration GuideSBE Public Trade Integration Guide
SBE

SBE BBO Integration Guide

Overview

FieldDescription
Topicbooks1
TemplateId1002
FormatSBE binary frame (opcode = 2), little-endian
DepthProvides real-time Level 1 best bid/ask prices and corresponding order sizes
UnitsTimestamps in microseconds (µs), but only accurate to milliseconds. Append 000 to a millisecond timestamp to get the microsecond format. E.g., millisecond timestamp 1726233600001 corresponds to µs timestamp 1726233600001000
Update FrequencyReal-time

Connection

  • WebSocket URL: wss://ws.bitget.com/v3/ws/public/sbe
  • Heartbeat: Send text frame "ping" every 30 seconds, server responds with "pong"
  • Message Protocol: JSON text frames during subscription phase; SBE binary frames during market data push phase, distinguished by WebSocket opCode (opCode=1 for text, opCode=2 for binary)

Subscription Flow

1. Send Subscription Request

Code
{ "op": "subscribe", "args": [ { "instType": "usdt-futures", "topic": "books1", "symbol": "BTCUSDT" } ] }

Parameter Description:

ParameterTypeDescription
instTypestringProduct type: spot
usdt-futures
usdc-futures
coin-futures
topicstringFixed value: books1
symbolstringSymbol name, e.g. BTCUSDT, ETHUSDT

2. Subscription Confirmation

Code
{ "event": "subscribe", "arg": { "instType": "usdt-futures", "topic": "books1", "symbol": "BTCUSDT" } }

3. Receiving Data

After subscription confirmation, SBE binary frames are pushed in real-time as BBO updates arrive.

The books1 channel uses auto-culling: under high system load, stale events may be discarded instead of queued and delivered with delay. For example, if a new BBO event is generated at time T2 while a prior event at T1 (T1 < T2) is still pending delivery, the T1 event is dropped and only the T2 event is sent. This behavior is applied independently per symbol.

4. Unsubscribe

Code
{ "op": "unsubscribe", "args": [ { "instType": "usdt-futures", "topic": "books1", "symbol": "BTCUSDT" } ] }

SBE Message Structure

Best bid/ask price and corresponding size for a specified trading pair.

Price/Size Calculation Formula

Code
actual_value = mantissa × 10^exponent

Example: mantissa = 123456, exponent = -4, represents 12.3456 (actual_value = mantissa × 10 ^ exponent)

Common Message Header (8 bytes)

All SBE messages must include a fixed 8-byte header for parsing and identifying subsequent data.

FieldTypeLength (Byte)Description
blockLengthuint162Root block length
templateIduint162Channel unique identifier, fixed value = 1002
schemaIduint162Schema ID
versionuint162Schema version

Message Field Definitions

#FieldTypeDescription
-messageHeaderCompositeFixed header
1tsuint64Matching engine timestamp
µs timestamp, but only accurate to milliseconds. Append 000 to a millisecond timestamp to get the microsecond format. E.g., millisecond timestamp 1726233600001 → µs 1726233600001000
2bid1Priceint64Best bid price
3bid1Sizeint64Best bid size
4ask1Priceint64Best ask price
5ask1Sizeint64Best ask size
6priceExponentint8Price exponent
7sizeExponentint8Size exponent
8sequint64Depth sequence number, used for message ordering and packet loss detection
9stsuint64Stream service push timestamp in microseconds
10categoryuint8Product line: spot / usdt-futures / coin-futures / usdc-futures
100paddinguint8Padding bytes
200symbolvarString[8]Symbol name, UTF-8 format

Binary Layout Overview

Code
┌─────────────┬──────────────┬──────────┐ │ Header (8B) │ Root (56B) │ Symbol │ └─────────────┴──────────────┴──────────┘

Total message size: 8 + 56 + 1 + len(symbol) = approximately 72 bytes


Decoding Example

Raw Binary (hex)

Code
38 00 EA 03 01 00 02 00 <- header: blockLength=56, templateId=1002, schemaId=1, version=2 01 80 C6 A7 86 3E 06 00 <- ts (uint64 LE) 4E 3C 64 00 00 00 00 00 <- bid1Price = 6569038 98 3A 00 00 00 00 00 00 <- bid1Size = 15000 52 3C 64 00 00 00 00 00 <- ask1Price = 6569042 20 4E 00 00 00 00 00 00 <- ask1Size = 20000 FE <- priceExponent = -2 FC <- sizeExponent = -4 01 00 00 00 00 00 00 00 <- seq (uint64 LE) = 1 00 00 00 00 00 00 <- padding6 07 42 54 43 55 53 44 54 <- symbol: length=7, "BTCUSDT"

Decoded JSON

Code
{ "header": { "block_length": 56, "template_id": 1002, "schema_id": 1, "version": 2 }, "ts": 1700000000000001, "bid1_price": "65690.38", "bid1_size": "1.5000", "ask1_price": "65690.42", "ask1_size": "2.0000", "price_exponent": -2, "size_exponent": -4, "seq": 1, "sts": 1700000000001001, "category": 1, "symbol": "BTCUSDT" }

Python Integration Example

Code
"""Bitget books1 (BBO) SBE WebSocket subscription example""" import asyncio import json import struct from decimal import Decimal import websockets WS_URL = "wss://ws.bitget.com/v3/ws/public/sbe" INST_TYPE = "usdt-futures" SYMBOL = "BTCUSDT" TOPIC = "books1" def decode_bbo(data: bytes) -> dict: """Decode BestBidAsk (templateId=1002) SBE frame""" block_length, template_id, schema_id, version = struct.unpack_from('<HHHH', data, 0) assert template_id == 1002, f"unexpected templateId: {template_id}" offset = 8 base = offset ts, = struct.unpack_from('<Q', data, offset); offset += 8 bid1_price, = struct.unpack_from('<q', data, offset); offset += 8 bid1_size, = struct.unpack_from('<q', data, offset); offset += 8 ask1_price, = struct.unpack_from('<q', data, offset); offset += 8 ask1_size, = struct.unpack_from('<q', data, offset); offset += 8 price_exp, = struct.unpack_from('<b', data, offset); offset += 1 size_exp, = struct.unpack_from('<b', data, offset); offset += 1 seq, = struct.unpack_from('<Q', data, offset); offset += 8 sts, = struct.unpack_from('<Q', data, offset); offset += 8 category, = struct.unpack_from('<B', data, offset); offset += 1 # Skip padding, based on blockLength offset = base + block_length # symbol (varString8) sym_len, = struct.unpack_from('<B', data, offset); offset += 1 symbol = data[offset:offset + sym_len].decode('utf-8') to_dec = lambda m, e: Decimal(m) * Decimal(10) ** e return { "ts": ts, "bid1_price": str(to_dec(bid1_price, price_exp)), "bid1_size": str(to_dec(bid1_size, size_exp)), "ask1_price": str(to_dec(ask1_price, price_exp)), "ask1_size": str(to_dec(ask1_size, size_exp)), "price_exponent": price_exp, "size_exponent": size_exp, "seq": seq, "sts": sts, "category": category, "symbol": symbol, } async def main(): async with websockets.connect(WS_URL) as ws: # Subscribe await ws.send(json.dumps({ "op": "subscribe", "args": [{"instType": INST_TYPE, "topic": TOPIC, "symbol": SYMBOL}] })) print(f"[SUB] {INST_TYPE} {TOPIC} {SYMBOL}") # Heartbeat async def ping_loop(): while True: await asyncio.sleep(20) await ws.send("ping") print("[PING] sent") asyncio.create_task(ping_loop()) async for message in ws: if isinstance(message, bytes): try: msg = decode_bbo(message) ts_ms = msg['ts'] // 1000 spread = Decimal(msg['ask1_price']) - Decimal(msg['bid1_price']) print(f"\n[BBO] {msg['symbol']} ts={ts_ms}ms seq={msg['seq']} sts={msg['sts']} category={msg['category']}") print(f" bid: price={msg['bid1_price']} size={msg['bid1_size']}") print(f" ask: price={msg['ask1_price']} size={msg['ask1_size']}") print(f" spread: {spread}") except Exception as e: print(f"[ERROR] {e} raw={message.hex()}") else: if message == "pong": print("[PONG] received") else: print(f"[TEXT] {message}") if __name__ == "__main__": asyncio.run(main())
SBE IntroductionSBE Level 50 Integration Guide
On this page
  • Overview
  • Connection
  • Subscription Flow
    • 1. Send Subscription Request
    • 2. Subscription Confirmation
    • 3. Receiving Data
    • 4. Unsubscribe
  • SBE Message Structure
    • Price/Size Calculation Formula
    • Common Message Header (8 bytes)
    • Message Field Definitions
    • Binary Layout Overview
  • Decoding Example
    • Raw Binary (hex)
    • Decoded JSON
  • Python Integration Example
JSON
JSON
JSON
Javascript
Javascript
Javascript