Backpack Exchange API (1.0)

Download OpenAPI specification:Download

Introduction

Welcome to the Backpack Exchange API. This API is for programmatic trade execution. All of the endpoints require requests to be signed with an ED25519 keypair for authentication.

The API is hosted at https://api.backpack.exchange/ and the WS API is hosted at wss://ws.backpack.exchange/.

Authentication

Signing requests

Signed requests are required for any API calls that mutate state. Additionally, some read only requests can be performed by signing or via session authentication.

Signed requests require the following additional headers:

  • X-Timestamp - Unix time in milliseconds that the request was sent.
  • X-Window - Time window in milliseconds that the request is valid for, default is 5000 and maximum is 60000.
  • X-API-Key - Base64 encoded verifying key of the ED25519 keypair.
  • X-Signature - Base64 encoded signature generated according to the instructions below.

To generate a signature perform the following:

  1. The key/values of the request body or query parameters should be ordered alphabetically and then turned into query string format.

  2. Append the header values for the timestamp and receive window to the above generated string in the format &timestamp=<timestamp>&window=<window>. If no X-Window header is passed the default value of 5000 still needs to be added to the signing string.

Each request also has an instruction type, valid instructions are:

balanceQuery
depositAddressQuery
depositQueryAll
fillHistoryQueryAll
orderCancel
orderCancelAll
orderExecute
orderHistoryQueryAll
orderQuery
orderQueryAll
withdraw
withdrawalQueryAll

The correct instruction type should be prefixed to the signing string. The instruction types for each request are documented alongside the request.

For example, an API request to cancel an order with the following body:

{
    "orderId": 28
    "symbol": "BTC_USDT",
}

Would require the following to be signed:

instruction=orderCancel&orderId=28&symbol=BTC_USDT&timestamp=1614550000000&window=5000

If the API endpoint requires query parameters instead of a request body, the same procedure should be used on the query parameters. If the API endpoint does not have a request body or query parameters, only the timestamp and receive window need to be signed.

This message should be signed using the private key of the ED25519 keypair that corresponds to the public key in the X-API-Key header. The signature should then be base64 encoded and submitted in the X-Signature header.




Changelog

2024-05-03

  • Add single market order update stream account.orderUpdate.<symbol>.

2024-05-02

  • Add optional from/to timestamp to get withdrawals endpoint.

2024-05-01

  • Add optional from/to timestamp to get deposits endpoint.

2024-03-14

  • Add optional orderId filter to order history endpoint.
  • Add optional from/to timestamp to order fills endpoint.

2024-02-28

  • Return the withdrawal in request withdrawal response.

2024-02-24

  • An additional field t was added to the private order update stream. It is the trade_id of the fill that generated the order update.
  • Added a maximum value for the X-Window header of 60000.

2024-01-16

Breaking

  • A new websocket API is available at wss://ws.backpack.exchange. Please see the documentation. The previous API remains on the same endpoint and will be deprecated after a migration period. The new API changes the following:
    • Subscription endpoint is now wss://ws.backpack.exchange instead of wss://ws.backpack.exchange/stream.
    • Can subscribe and unsubscribe to/from multiple streams by passing more than one in the params field.
    • Signature should now be sent in a separate signature field.
    • Signature instruction changed from accountQuery to subscribe.
    • Event and engine timestamps are now in microseconds instead of milliseconds.
    • Add engine timestamp to bookTicker, depth, and order streams.
    • Add quote asset volume to ticker stream.
    • Add sequential trade id to trade stream.
    • Rename the event type in the depth stream from depthEvent to depth.
    • Change the format of streams from <symbol>@<type> to <type>.<symbol> or kline.<interval>.<symbol> for K-lines.
    • Flatten the K-Line in the K-line stream so its not nested.

2024-01-11

Breaking

  • Replaced identifier field on deposits with transaction_hash and provider_id. This aims to provide clearer representation of the field, particularly for fiat deposits.
  • Removed duplicate pending values from the WithdrawalStatus and DepositStatus spec enum.




Markets

Public market data.

Get assets.

Retrieves all the assets that are supported by the exchange.

Responses

Response samples

Content type
application/json; charset=utf-8
[
  • {
    }
]

Get markets.

Retrieves all the markets that are supported by the exchange.

Responses

Response samples

Content type
application/json; charset=utf-8
[
  • {
    }
]

Get ticker.

Retrieves summarised statistics for the last 24 hours for the given market symbol.

query Parameters
symbol
required
string

Responses

Response samples

Content type
application/json; charset=utf-8
{
  • "symbol": "string",
  • "firstPrice": "string",
  • "lastPrice": "string",
  • "priceChange": "string",
  • "priceChangePercent": "string",
  • "high": "string",
  • "low": "string",
  • "volume": "string",
  • "quoteVolume": "string",
  • "trades": "string"
}

Get tickers.

Retrieves summarised statistics for the last 24 hours for all market symbols.

Responses

Response samples

Content type
application/json; charset=utf-8
[
  • {
    }
]

Get depth.

Retrieves the order book depth for a given market symbol.

query Parameters
symbol
required
string

Responses

Response samples

Content type
application/json; charset=utf-8
{
  • "asks": [
    ],
  • "bids": [
    ],
  • "lastUpdateId": "1684026955123"
}

Get K-lines.

Get K-Lines for the given market symbol, optionally providing a startTime and endTime. If no startTime is provided, the interval duration will be used. If no endTime is provided, the current time will be used.

query Parameters
symbol
required
string
interval
required
string (KlineInterval)
Enum: "1m" "3m" "5m" "15m" "30m" "1h" "2h" "4h" "6h" "8h" "12h" "1d" "3d" "1w" "1month"
startTime
integer <int64>

UTC timestamp in seconds.

endTime
integer <int64>

UTC timestamp in seconds.

Responses

Response samples

Content type
application/json; charset=utf-8
[
  • {
    }
]

System

Exchange system status.

Status.

Get the system status, and the status message, if any.

Responses

Response samples

Content type
application/json; charset=utf-8
{
  • "status": "Ok",
  • "message": "string"
}

Ping.

Responds with pong.

Responses

Get system time.

Retrieves the current system time.

Responses

Trades

Public trade data.

Get recent trades.

Retrieve the most recent trades for a symbol. This is public data and is not specific to any account.

The maximum available recent trades is 1000. If you need more than 1000 trades use the historical trades endpoint.

query Parameters
symbol
required
string

Market symbol to query fills for.

limit
integer <uint16>

Limit the number of fills returned. Default 100, maximum 1000.

Responses

Response samples

Content type
application/json; charset=utf-8
[
  • {
    }
]

Get historical trades.

Retrieves all historical trades for the given symbol. This is public trade data and is not specific to any account.

query Parameters
symbol
required
string
limit
integer <int64>

Limit the number of trades returned. Default 100, maximum 1000.

offset
integer <int64>

Offset. Default 0.

Responses

Response samples

Content type
application/json; charset=utf-8
[
  • {
    }
]

Capital

Capital management.

Get balances.

Retrieves account balances and the state of the balances (locked or available).

Locked assets are those that are currently in an open order.

Instruction: balanceQuery

header Parameters
X-API-KEY
string

API key

X-SIGNATURE
string

Signature of the request

X-TIMESTAMP
integer <int64>

Timestamp of the request in milliseconds

X-WINDOW
integer <uint64>

Time the request is valid for in milliseconds (default 5000, maximum 60000)

Responses

Response samples

Content type
application/json; charset=utf-8
{
  • "property1": {
    },
  • "property2": {
    }
}

Get deposits.

Retrieves deposit history.

Instruction: depositQueryAll

query Parameters
from
integer <int64>

Filter to minimum time (milliseconds).

to
integer <int64>

Filter to maximum time (milliseconds).

limit
integer <int64>

Maximum number to return. Default 100, maximum 1000.

offset
integer <int64>

Offset. Default 0.

header Parameters
X-API-KEY
string

API key

X-SIGNATURE
string

Signature of the request

X-TIMESTAMP
integer <int64>

Timestamp of the request in milliseconds

X-WINDOW
integer <uint64>

Time the request is valid for in milliseconds (default 5000, maximum 60000)

Responses

Response samples

Content type
application/json; charset=utf-8
[
  • {
    }
]

Get deposit address.

Retrieves the user specific deposit address if the user were to deposit on the specified blockchain.

Instruction: depositAddressQuery

query Parameters
blockchain
required
string (Blockchain)
Enum: "Solana" "Ethereum" "Polygon" "Bitcoin"

Blockchain symbol to get a deposit address for.

header Parameters
X-API-KEY
string

API key

X-SIGNATURE
string

Signature of the request

X-TIMESTAMP
integer <int64>

Timestamp of the request in milliseconds

X-WINDOW
integer <uint64>

Time the request is valid for in milliseconds (default 5000, maximum 60000)

Responses

Response samples

Content type
application/json; charset=utf-8
{
  • "address": "string"
}

Get withdrawals.

Retrieves withdrawal history.

Instruction: withdrawalQueryAll

query Parameters
from
integer <int64>

Filter to minimum time (milliseconds).

to
integer <int64>

Filter to maximum time (milliseconds).

limit
integer <int64>

Maximum number to return. Default 100, maximum 1000.

offset
integer <int64>

Offset. Default 0.

header Parameters
X-API-KEY
string

API key

X-SIGNATURE
string

Signature of the request

X-TIMESTAMP
integer <int64>

Timestamp of the request in milliseconds

X-WINDOW
integer <uint64>

Time the request is valid for in milliseconds (default 5000, maximum 60000)

Responses

Response samples

Content type
application/json; charset=utf-8
[
  • {
    }
]

Request withdrawal.

Requests a withdrawal from the exchange.

The twoFactorToken field is required if the withdrawal address is not an address that is configured in the address book to not require 2FA. These addresses can be configured here.

Instruction: withdraw

header Parameters
X-API-KEY
required
string

API key

X-TIMESTAMP
required
integer <int64>

Timestamp of the request in milliseconds

X-WINDOW
integer <uint64>

Time the request is valid for in milliseconds (default 5000, maximum 60000)

X-SIGNATURE
required
string

Signature of the request

Request Body schema: application/json; charset=utf-8
required
address
required
string

Address to withdraw to.

blockchain
required
string
Enum: "Solana" "Ethereum" "Polygon" "Bitcoin"

Blockchain to withdraw on.

clientId
string

Custom client id.

quantity
required
string <decimal>

Quantity to withdraw.

symbol
required
string

Symbol of the asset to withdraw.

twoFactorToken
string

Issued two factor token.

Responses

Request samples

Content type
application/json; charset=utf-8
{
  • "address": "string",
  • "blockchain": "Solana",
  • "clientId": "string",
  • "quantity": "string",
  • "symbol": "string",
  • "twoFactorToken": "string"
}

Response samples

Content type
application/json; charset=utf-8
{
  • "id": 0,
  • "blockchain": "Solana",
  • "clientId": "string",
  • "identifier": "string",
  • "quantity": "string",
  • "fee": "string",
  • "symbol": "string",
  • "status": "confirmed",
  • "subaccountId": 0,
  • "toAddress": "string",
  • "transactionHash": "string",
  • "createdAt": "string",
  • "isInternal": true
}

History

Historical account data.

Get order history.

Retrieves the order history for the user. This includes orders that have been filled and are no longer on the book. It may include orders that are on the book, but the /orders endpoint contains more up to date data.

Instruction: orderHistoryQueryAll

query Parameters
orderId
string

Filter to the given order.

symbol
string

Filter to the given symbol.

limit
integer <int64>

Maximum number to return. Default 100, maximum 1000.

offset
integer <int64>

Offset. Default 0.

header Parameters
X-API-KEY
string

API key

X-SIGNATURE
string

Signature of the request

X-TIMESTAMP
integer <int64>

Timestamp of the request in milliseconds

X-WINDOW
integer <uint64>

Time the request is valid for in milliseconds (default 5000, maximum 60000)

Responses

Response samples

Content type
application/json; charset=utf-8
[
  • {
    }
]

Get fill history.

Retrieves historical fills, with optional filtering for a specific order or symbol.

Instruction: fillHistoryQueryAll

query Parameters
orderId
string

Filter to the given order.

from
integer <int64>

Filter to minimum time (milliseconds).

to
integer <int64>

Filter to maximum time (milliseconds).

symbol
string

Filter to the given symbol.

limit
integer <int64>

Maximum number to return. Default 100, maximum 1000.

offset
integer <int64>

Offset. Default 0.

header Parameters
X-API-KEY
string

API key

X-SIGNATURE
string

Signature of the request

X-TIMESTAMP
integer <int64>

Timestamp of the request in milliseconds

X-WINDOW
integer <uint64>

Time the request is valid for in milliseconds (default 5000, maximum 60000)

Responses

Response samples

Content type
application/json; charset=utf-8
[
  • {
    }
]

Order

Order management.

Get open order.

Retrieves an open order from the order book. This only returns the order if it is resting on the order book (i.e. has not been completely filled, expired, or cancelled).

One of orderId or clientId must be specified. If both are specified, then orderId takes precedence.

Instruction: orderQuery

query Parameters
clientId
integer <uint32>

Client ID of the order.

orderId
string

ID of the order.

symbol
required
string

Market symbol for the order.

header Parameters
X-API-KEY
string

API key

X-SIGNATURE
string

Signature of the request

X-TIMESTAMP
integer <int64>

Timestamp of the request in milliseconds

X-WINDOW
integer <uint64>

Time the request is valid for in milliseconds (default 5000, maximum 60000)

Responses

Response samples

Content type
application/json; charset=utf-8
Example
{
  • "orderType": "Market",
  • "id": "string",
  • "clientId": 0,
  • "symbol": "string",
  • "side": "Bid",
  • "quantity": "string",
  • "executedQuantity": "string",
  • "quoteQuantity": "string",
  • "executedQuoteQuantity": "string",
  • "triggerPrice": "string",
  • "timeInForce": "GTC",
  • "selfTradePrevention": "RejectTaker",
  • "status": "Cancelled",
  • "createdAt": 0
}

Execute order.

Submits an order to the matching engine for execution.

Instruction: orderExecute

header Parameters
X-API-KEY
required
string

API key

X-SIGNATURE
required
string

Signature of the request

X-TIMESTAMP
required
integer <int64>

Timestamp of the request in milliseconds

X-WINDOW
integer <uint64>

Time the request is valid for in milliseconds (default 5000, maximum 60000)

Request Body schema: application/json; charset=utf-8
required
clientId
integer <uint32>

Custom order id.

orderType
required
string
Enum: "Market" "Limit"

Order type, market or limit.

postOnly
boolean

Whether the order is post only or not

price
string <decimal>

The order price if this is a limit order

quantity
string <decimal>

The order quantity. Market orders must specify either a quantity or quoteQuantity. All other order types must specify a quantity.

quoteQuantity
string <decimal>

The maximum amount of the quote asset to spend (Ask) or receive (Bid) for market orders. This is used for reverse market orders. The order book will execute a quantity as close as possible to the notional value of quote_quantity.

selfTradePrevention
string
Enum: "RejectTaker" "RejectMaker" "RejectBoth" "Allow"

Action to take in the event the user crosses themselves in the order book.

side
required
string
Enum: "Bid" "Ask"

The order side. It will be matched against the resting orders on the other side of the order book.

symbol
required
string

The market for the order.

timeInForce
string
Enum: "GTC" "IOC" "FOK"

How long the order is good for.

triggerPrice
string <decimal>

Trigger price if this is a conditional order.

Responses

Request samples

Content type
application/json; charset=utf-8
{
  • "clientId": 0,
  • "orderType": "Market",
  • "postOnly": true,
  • "price": "string",
  • "quantity": "string",
  • "quoteQuantity": "string",
  • "selfTradePrevention": "RejectTaker",
  • "side": "Bid",
  • "symbol": "string",
  • "timeInForce": "GTC",
  • "triggerPrice": "string"
}

Response samples

Content type
application/json; charset=utf-8
Example
{
  • "orderType": "Market",
  • "id": "string",
  • "clientId": 0,
  • "symbol": "string",
  • "side": "Bid",
  • "quantity": "string",
  • "executedQuantity": "string",
  • "quoteQuantity": "string",
  • "executedQuoteQuantity": "string",
  • "triggerPrice": "string",
  • "timeInForce": "GTC",
  • "selfTradePrevention": "RejectTaker",
  • "status": "Cancelled",
  • "createdAt": 0
}

Cancel open order.

Cancels an open order from the order book.

One of orderId or clientId must be specified. If both are specified, then orderId takes precedence.

Instruction: orderCancel

header Parameters
X-API-KEY
required
string

API key

X-SIGNATURE
required
string

Signature of the request

X-TIMESTAMP
required
integer <int64>

Timestamp of the request in milliseconds

X-WINDOW
integer <uint64>

Time the request is valid for in milliseconds (default 5000, maximum 60000)

Request Body schema: application/json; charset=utf-8
required
clientId
integer <uint32>

Client ID of the order.

orderId
string

ID of the order.

symbol
required
string

Market the order exists on.

Responses

Request samples

Content type
application/json; charset=utf-8
{
  • "clientId": 0,
  • "orderId": "string",
  • "symbol": "string"
}

Response samples

Content type
application/json; charset=utf-8
Example
{
  • "orderType": "Market",
  • "id": "string",
  • "clientId": 0,
  • "symbol": "string",
  • "side": "Bid",
  • "quantity": "string",
  • "executedQuantity": "string",
  • "quoteQuantity": "string",
  • "executedQuoteQuantity": "string",
  • "triggerPrice": "string",
  • "timeInForce": "GTC",
  • "selfTradePrevention": "RejectTaker",
  • "status": "Cancelled",
  • "createdAt": 0
}

Get open orders.

Retrieves all open orders. If a symbol is provided, only open orders for that market will be returned, otherwise all open orders are returned.

Instruction: orderQueryAll

query Parameters
symbol
string

The symbol of the market for the orders.

header Parameters
X-API-KEY
string

API key

X-SIGNATURE
string

Signature of the request

X-TIMESTAMP
integer <int64>

Timestamp of the request in milliseconds

X-WINDOW
integer <uint64>

Time the request is valid for in milliseconds (default 5000, maximum 60000)

Responses

Response samples

Content type
application/json; charset=utf-8
[
  • {
    }
]

Cancel open orders.

Cancels all open orders on the specified market.

Instruction: orderCancelAll

Request Body schema: application/json; charset=utf-8
required
symbol
required
string

Market to cancel orders for.

Responses

Request samples

Content type
application/json; charset=utf-8
{
  • "symbol": "string"
}

Response samples

Content type
application/json; charset=utf-8
[
  • {
    }
]

Streams

Usage

Subscribing

To use the websocket API, connect to wss://ws.backpack.exchange.

To subscribe to a stream with the name stream send a text frame over the websocket connection with the following JSON payload:

{
  "method": "SUBSCRIBE",
  "params": ["stream"]
}

Similarly, to unsubscribe from a stream with the name stream:

{
  "method": "UNSUBSCRIBE",
  "params": ["stream"]
}

You can subscribe or unsubscribe from multiple streams if you include more than one in the params field.

All data from streams is wrapped in a JSON object of the following form:

{
  "stream": "<stream>",
  "data": "<payload>"
}

The following command can be used to test subscribing to a stream:

(sleep 1; \
echo '{"method":"SUBSCRIBE","params":["depth.SOL_USDC"]}';\
cat) |\
wscat -c wss://ws.backpack.exchange

The payloads for each stream time are outlined below.

Timing

Timestamps are in microseconds (except for the K-line start and end times). The event timestamp is the time the event was emitted from the websocket server, and the engine timestamp is the time the event was generated by the matching engine.

If a message aggregates more than one event (for example, a depth message), the engine timestamp will be the timestamp of the last matching engine event.

Keeping the connection alive

To keep the connection alive, a Ping frame will be sent from the server every 60s, and a Pong is expected to be received from the client. If a Pong is not received within 120s, a Close frame will be sent and the connection will be closed.

If the server is shutting down, a Close frame will be sent and then a grace period of 30s will be given before the connection is closed. The client should reconnect after receiving the Close frame. The client will be reconnected to a server that is not shutting down.

Private

Subscribing to a private stream requires a valid signature generated from an ED25519 keypair. For stream subscriptions, the signature should be of the form:

instruction=subscribe&timestamp=1614550000000&window=5000

Where the timestamp and window are in milliseconds.

Private streams are prefixed with account. and require signature data to be submitted in the subscribe parameters. The verifying key and signature should be base64 encoded.

{
  "method": "SUBSCRIBE",
  "params": ["stream"],
  "signature": ["<verifying key>", "<signature>", "<timestamp>", "<window>"]
}

Order update stream

On any mutation to an order the order will be pushed to the order update stream. The event type of the order update will be one of the following:

  • orderAccepted
  • orderCancelled
  • orderExpired
  • orderFill

Stream name format for all markets: account.orderUpdate Stream name format for single market: account.orderUpdate.<symbol>

{
  "e": "orderAccepted",   // Event type
  "E": 1694687692980000,  // Event time in microseconds
  "s": "SOL_USD",         // Symbol
  "c": "123",             // Client order ID
  "S": "Bid",             // Side
  "o": "LIMIT",           // Order type
  "f": "GTC",             // Time in force
  "q": "32123",           // Quantity
  "Q": "32123",           // Quantity in quote
  "p": "20",              // Price
  "P": "21",              // Trigger price
  "X": "Filled",          // Order state
  "i": "1111343026172067" // Order ID
  "t": "123",             // Trade id
  "l": "1.23",            // Fill quantity
  "z": "321",             // Executed quantity
  "Z": "123",             // Executed quantity in quote
  "L": "20",              // Fill price
  "m": true,              // Whether the order was maker
  "n": "23",              // Fee
  "N": "1.23",            // Fee symbol
  "V": "RejectTaker",     // Self trade prevention
  "T": 1694687692989999   // Engine timestamp in microseconds
}

Some fields are conditional on the order settings or event type:

  • c - Only present if the order has a client order ID.
  • q - Only present if the order has a quantity set.
  • Q - Only present if the order is reverse market order.
  • p - Only present if the order is a limit order.
  • P - Only present if the order is a trigger order.
  • t - Only present if the event is a orderFill event.
  • l - Only present if the event is a orderFill event.
  • L - Only present if the event is a orderFill event.
  • m - Only present if the event is a orderFill event.
  • n - Only present if the event is a orderFill event.
  • N - Only present if the event is a orderFill event.

Public

K-Line stream

Stream name format: kline.<interval>.<symbol>

{
  "e": "kline",           // Event type
  "E": 1694687692980000,  // Event time in microseconds
  "s": "SOL_USD",         // Symbol
  "t": 123400000,         // K-Line start time in seconds
  "T": 123460000,         // K-Line close time in seconds
  "o": "18.75",           // Open price
  "c": "19.25",           // Close price
  "h": "19.80",           // High price
  "l": "18.50",           // Low price
  "v": "32123",           // Base asset volume
  "n": 93828,             // Number of trades
  "X": false              // Is this k-line closed?
}

Ticker stream

The ticker stream pushes 24hr rolling statistics for a single symbol.

Stream name format: ticker.<symbol>

{
  "e": "ticker",          // Event type
  "E": 1694687692980000,  // Event time in microseconds
  "s": "SOL_USD",         // Symbol
  "o": "18.75",           // First price
  "c": "19.24",           // Last price
  "h": "19.80",           // High price
  "l": "18.50",           // Low price
  "v": "32123",           // Base asset volume
  "V": "928190",          // Quote asset volume
  "n": 93828              // Number of trades
}

Trade stream

Contains public trade data for a single symbol. The trade ID is a sequential number specific to the symbol.

Stream name format: trade.<symbol>

{
  "e": "trade",                   // Event type
  "E": 1694688638091000,          // Event time in microseconds
  "s": "SOL_USDC",                // Symbol
  "p": "18.68",                   // Price
  "q": "0.122",                   // Quantity
  "b": "111063114377265150",      // Buyer order ID
  "a": "111063114585735170",      // Seller order ID
  "t": 12345,                     // Trade ID
  "T": 1694688638089000,          // Engine timestamp in microseconds
  "m": true                       // Is the buyer the maker?
}

Depth stream

Contains incremental depth updates. Each depth update has the absolute value of the depths at the given levels, and only changes when the depth has changed.

To obtain an initial snapshot of the depth, the client should query the REST API.

The depth stream will push updates as quickly as possible, but under load it may aggregate more than one update into a single event. In this case the U and u fields will not be the same. The U field is the first update ID in the event, and the u field is the final update ID in the event.

There is an alternative depth stream that aggregates updates into a single message over a 200ms period instead of pushing updates in realtime. This is useful for reducing network traffic.

Updates are sequential, so U will always be u + 1 from the previous message. If this is not the case, the client should assume that the depth has been invalidated and requery the REST API.

Stream name format: depth.<symbol> (realtime) Stream name format: depth.200ms.<symbol> (aggregated)

{
  "e": "depth",           // Event type
  "E": 1694687965941000,  // Event time in microseconds
  "s": "SOL_USDC",        // Symbol
  "a": [                  // Asks
    [
      "18.70",
      "0.000"
    ]
  ],
  "b": [                  // Bids
    [
      "18.67",
      "0.832"
    ],
    [
      "18.68",
      "0.000"
    ]
  ],
  "U": 94978271,          // First update ID in event
  "u": 94978271,          // Final update ID in event
  "T": 1694687965940999   // Engine timestamp in microseconds
}

Book Ticker stream

Stream name format: bookTicker.<symbol>

{
  "e": "bookTicker",          // Event type
  "E": 1694687965941000,      // Event time in microseconds
  "s": "SOL_USDC",            // Symbol
  "a": "18.70",               // Inside ask price
  "A": "1.000",               // Inside ask quantity
  "b": "18.67",               // Inside bid price
  "B": "2.000",               // Inside bid quantity
  "u": "111063070525358080",  // Update ID of event
  "T": 1694687965940999       // Engine timestamp in microseconds
}