Bullish · AsyncAPI Specification

Multi-Order Book

Version 1.0.0

This allows simultaneous subscriptions to multiple L1 and L2 order books of different markets. The order books of different markets to be subscribed are controlled by the parameters in the subscription message listed below. ``` /trading-api/v1/market-data/orderbook ```

View Spec View on GitHub Digital AssetsCryptocurrencyExchangeTradingDerivativesCustodyMarket DataFinancial ServicesInstitutionalFIXAsyncAPIWebhooksEvents

Channels

data

Servers

wss
prod-public
Production / Public
wss
prod-registered
Production / Registered
wss
prod-direct
Production / Direct Connect
wss
simnext-public
SimNext / Public
wss
simnext-registered
SimNext / Registered
wss
simnext-direct
SimNext / Direct Connect

AsyncAPI Specification

Raw ↑
asyncapi: 3.0.0
info:
  title: Multi-Order Book
  version: 1.0.0
  description: |
    This allows simultaneous subscriptions to multiple L1 and L2 order books of different markets.

    The order books of different markets to be subscribed are controlled by the parameters in the subscription message listed below.

    ```
    /trading-api/v1/market-data/orderbook
    ```
servers:
  prod-public:
    host: api.exchange.bullish.com
    protocol: wss
    description: Production / Public
  prod-registered:
    host: registered.api.exchange.bullish.com
    protocol: wss
    description: Production / Registered
  prod-direct:
    host: prod.access.bullish.com
    protocol: wss
    description: Production / Direct Connect
  simnext-public:
    host: api.simnext.bullish-test.com
    protocol: wss
    description: SimNext / Public
  simnext-registered:
    host: registered.api.simnext.bullish-test.com
    protocol: wss
    description: SimNext / Registered
  simnext-direct:
    host: simnext.access.bullish.com
    protocol: wss
    description: SimNext / Direct Connect

channels:
  data:
    address: /trading-api/v1/market-data/orderbook
    messages:
      subscribe:
        title: Subscription
        summary: Let you subscribe to a given topic
        payload:
          type: object
          required:
            - id
            - method
            - params
          properties:
            method:
              type: string
              description: '"subscribe"'
              example: subscribe
            id:
              $ref: "#/components/schemas/MarketDataOrderbookJsonRpcRequestId"
            jsonrpc:
              $ref: "#/components/schemas/MarketDataOrderbookJsonRpcVersion"
            type:
              $ref: "#/components/schemas/MarketDataOrderbookJsonRpcCommandType"
            params:
              $ref: "#/components/schemas/MarketDataOrderbookTopicSubscriptionParams"
      subscribe-ack:
        title: Acknowledgment
        summary: Confirm the topic being subscribed
        payload:
          type: object
          properties:
            id:
              $ref: "#/components/schemas/MarketDataOrderbookJsonRpcRequestId"
            jsonrpc:
              $ref: "#/components/schemas/MarketDataOrderbookJsonRpcVersion"
            result:
              type: object
              properties:
                responseCodeName:
                  type: string
                  description: '"OK"'
                  example: OK
                responseCode:
                  type: string
                  description: "200"
                  example: "200"
                message:
                  type: string
                  description: "Confirmation of what has been subscribed. The trailing numeric field identifies the order book topic: 1 for `l1Orderbook` and 2 for `l2Orderbook`."
                  example: Successfully subscribed ( BTCUSD 1)
      subscribe-msg-0:
        title: Snapshot/Update for L1
        summary: Latest update for L1
        payload:
          type: object
          properties:
            type:
              type: string
              description: '"update"'
              example: update
            dataType:
              type: string
              description: '"V1TALevel1"'
              example: V1TALevel1
            data:
              type: object
              properties:
                sequenceNumber:
                  type: string
                  description: incrementing, unique, unsigned integer that identifies a state of the L1 order book
                  example: "8"
                symbol:
                  type: string
                  description: Market symbol
                  example: BTCUSD
                timestamp:
                  type: string
                  description: Denotes the epoch millisecond time the datum was updated by the exchange
                  example: "1719642590000"
                bid:
                  type: array
                  description: Nested array containing price and quantity of highest bid
                  items:
                    type: string
                  example:
                    - "5199.5000"
                    - "61.95995262"
                ask:
                  type: array
                  items:
                    type: string
                  description: Nested array containing price and quantity of lowest ask
                  example:
                    - "5199.6000"
                    - "96.59626782"
      subscribe-msg-1:
        title: Snapshot/Update for L2
        summary: Latest update for L2
        payload:
          type: object
          properties:
            type:
              type: string
              description: '"snapshot"'
              example: snapshot
            dataType:
              type: string
              description: '"V1TALevel2"'
              example: V1TALevel2
            data:
              type: object
              properties:
                symbol:
                  type: string
                  description: Market symbol
                  example: BTCUSD
                bids:
                  type: array
                  description: Array of size 200 where even indices denote price, odd indices denote absolute quantities
                  items:
                    type: string
                  example:
                    - "5199.5000"
                    - "61.95995262"
                    - "5199.4000"
                    - "20.92470365"
                asks:
                  type: array
                  items:
                    type: string
                  description: Array of size 200 where even indices denote price, odd indices denote absolute quantities
                  example:
                    - "5199.6000"
                    - "96.59626782"
                    - "5199.7000"
                    - "0.92465082"
                sequenceNumberRange:
                  type: array
                  items:
                    type: integer
                  description: |
                    Array of size 2 where first element denotes lower bound, second element denotes upper bound of sequence numbers
                    . Lower and upper bound are equal for initial snapshot; this may differ for subsequent snapshots
                  example:
                    - 1370055970
                    - 1370055970
                datetime:
                  type: string
                  description: Denotes the time the update was created by the engine, ISO 8601 with millisecond as string
                  example: "2024-06-29T06:29:50.500Z"
                timestamp:
                  type: string
                  description: Denotes the epoch millisecond time the datum was created by the exchange
                  example: "1719642590000"
                publishedAtTimestamp:
                  type: string
                  description: Denotes the epoch millisecond time the datum was updated by the exchange
                  example: "1719642590000"
      subscribe-nack:
        title: Rejection
        summary: Explain why the topic could not be subscribed
        payload:
          $ref: "#/components/schemas/MarketDataOrderbookRejectionPayload"
      keepalive-ping:
        title: Keepalive Ping
        payload:
          type: object
          required:
            - id
            - method
            - params
          properties:
            method:
              type: string
              description: '"keepalivePing"'
              example: keepalivePing
            params:
              type: object
            id:
              $ref: "#/components/schemas/MarketDataOrderbookJsonRpcRequestId"
            jsonrpc:
              $ref: "#/components/schemas/MarketDataOrderbookJsonRpcVersion"
            type:
              $ref: "#/components/schemas/MarketDataOrderbookJsonRpcCommandType"
      keepalive-pong:
        title: Keepalive Pong
        payload:
          type: object
          properties:
            id:
              $ref: "#/components/schemas/MarketDataOrderbookJsonRpcRequestId"
            jsonrpc:
              $ref: "#/components/schemas/MarketDataOrderbookJsonRpcVersion"
            result:
              type: object
              properties:
                responseCodeName:
                  type: string
                  description: '"OK"'
                  example: OK
                responseCode:
                  type: integer
                  description: "200"
                  example: 200
                message:
                  type: string
                  description: '"Keep alive pong"'
                  example: Keep alive pong
      unsubscribe:
        title: Unsubscription
        summary: Let you unsubscribe to a given index
        payload:
          type: object
          required:
            - id
            - method
            - params
          properties:
            method:
              type: string
              description: '"unsubscribe"'
              example: unsubscribe
            id:
              $ref: "#/components/schemas/MarketDataOrderbookJsonRpcRequestId"
            jsonrpc:
              $ref: "#/components/schemas/MarketDataOrderbookJsonRpcVersion"
            type:
              $ref: "#/components/schemas/MarketDataOrderbookJsonRpcCommandType"
            params:
              $ref: "#/components/schemas/MarketDataOrderbookTopicSubscriptionParams"
      unsubscribe-ack:
        title: Acknowledgment
        summary: Confirm the topic being unsubscribed
        payload:
          type: object
          properties:
            id:
              $ref: "#/components/schemas/MarketDataOrderbookJsonRpcRequestId"
            jsonrpc:
              $ref: "#/components/schemas/MarketDataOrderbookJsonRpcVersion"
            result:
              type: object
              properties:
                responseCodeName:
                  type: string
                  description: '"OK"'
                  example: OK
                responseCode:
                  type: string
                  description: "200"
                  example: "200"
                message:
                  type: string
                  description: "Confirmation of what has been unsubscribed. The trailing numeric field identifies the order book topic: 1 for `l1Orderbook` and 2 for `l2Orderbook`."
                  example: Successfully unsubscribed ( BTCUSD 1)
      unsubscribe-nack:
        title: Rejection
        summary: Explain why the topic could not be unsubscribed
        payload:
          $ref: "#/components/schemas/MarketDataOrderbookRejectionPayload"
operations:
  subscribe:
    action: send
    channel:
      $ref: "#/channels/data"
    description: |
      ## Subscribe
      Multiple subscriptions could be opened within the same websocket.

      The order book of different markets to be subscribed are controlled by the parameters in the subscription message listed below.

      See [connect to multi-order book WebSocket](https://github.com/bullish-exchange/api-examples/blob/master/websocket/multi_orderbook_web_socket.py) for a sample Python script.
    messages:
      - $ref: "#/channels/data/messages/subscribe"
  subscribe-ack:
    action: receive
    channel:
      $ref: "#/channels/data"
    description: |
      After subscribing, the server sends :
      - an acknowledgement

      Then (L1 / L2 depending on your topic):
      - an initial snapshot
      - followed by incremental updates
    messages:
      - $ref: "#/channels/data/messages/subscribe-ack"
      - $ref: "#/channels/data/messages/subscribe-msg-0"
      - $ref: "#/channels/data/messages/subscribe-msg-1"
  subscribe-nack:
    action: receive
    channel:
      $ref: "#/channels/data"
    description: In case of *invalid* subscription message, an error rejection would be sent.
    messages:
      - $ref: "#/channels/data/messages/subscribe-nack"
  keepalive-ping:
    action: send
    channel:
      $ref: "#/channels/data"
    description: |
      ## Keepalive
      In case nothing is subscribed to, keep the websocket connection alive.
    messages:
      - $ref: "#/channels/data/messages/keepalive-ping"
  keepalive-pong:
    action: receive
    channel:
      $ref: "#/channels/data"
    description: |
      Acknowledgement returned by the server in response to a keepalive-ping.
    messages:
      - $ref: "#/channels/data/messages/keepalive-pong"
  unsubscribe:
    action: send
    channel:
      $ref: "#/channels/data"
    description: |
      ## Unsubscribe
      Let you unsubscribe a specific topic while keeping your websocket opened.
    messages:
      - $ref: "#/channels/data/messages/unsubscribe"
  unsubscribe-ack:
    action: receive
    channel:
      $ref: "#/channels/data"
    description: After unsubscribing, the server sends an acknowledgement.
    messages:
      - $ref: "#/channels/data/messages/unsubscribe-ack"
  unsubscribe-nack:
    action: receive
    channel:
      $ref: "#/channels/data"
    description: In case of *invalid* unsubscription message, an error rejection would be sent.
    messages:
      - $ref: "#/channels/data/messages/unsubscribe-nack"
components:
  schemas:
    MarketDataOrderbookJsonRpcRequestId:
      type: string
      description: ID returned by server in the acknowledgement
      example: "1611082473000"
    MarketDataOrderbookJsonRpcVersion:
      description: Version of the Json RPC protocol
      example: "2.0"
    MarketDataOrderbookJsonRpcCommandType:
      description: '"command"'
      example: command
    MarketDataOrderbookRejectionPayload:
      type: object
      properties:
        id:
          $ref: "#/components/schemas/MarketDataOrderbookJsonRpcRequestId"
        jsonrpc:
          $ref: "#/components/schemas/MarketDataOrderbookJsonRpcVersion"
        error:
          type: object
          properties:
            code:
              type: string
              description: a high-level code for the error
              example: "-32602"
            errorCode:
              type: string
              description: a precise typed error code
              example: "29013"
            errorCodeName:
              type: string
              description: An explanation of which value was invalid
              example: "'abcde' is not a valid topic"
    MarketDataOrderbookTopicSubscriptionParams:
      type: object
      required:
        - topic
        - symbol
      properties:
        topic:
          type: string
          description: |
            - l1Orderbook (l1 order book)
            - l2Orderbook (l2 order book)
          example: l1Orderbook
        symbol:
          type: string
          description: Market symbol, such as BTCUSD or ETHUSDC
          example: BTCUSD