Skip to main content
Connect to wss://partner-api.bravadotrade.com/orderbook-feed/ws to receive a live order book for one or more outcome tokens. On connect you get a book snapshot, then incremental updates as the book changes, plus last-trade price and best bid/ask events. The feed is public, no API key or signature is required. Bravado multiplexes upstream: every client watching the same asset shares one upstream connection.
You need an outcome token ID (assetId) to subscribe. Discover active ones from the Live Trades feed, every trade frame carries the assetId that just traded.

Connect

Pass the asset in the query string. Two modes share the same endpoint.

Single asset

JavaScript

Multiple assets

Pass a comma-separated list, and add or remove assets live with in-band JSON frames over the same socket. One connection can hold up to 120 assets.
JavaScript
There is no per-asset envelope: a multi-asset client routes updates by asset_id. Where that field lives depends on the frame. On book, last_trade_price and tick_size_change it is at the top level. On price_change — the great majority of traffic — the top level carries event_type, market, price_changes and timestamp, and the asset_id sits inside each entry of price_changes[]; one frame can therefore carry entries for more than one asset.
A connection with no assetId or assetIds is closed immediately with code 1008. Always subscribe to at least one asset in the query string.

Frames

Order-book frames are forwarded from the venue verbatim and are identified by an event_type field. Incremental events arrive as JSON objects. The initial book snapshot arrives either as a JSON array containing one book object, or as a bare object, and you must handle both. The array form is what we see in practice; the bare object can reach you as the replay of a cached book. Normalise with Array.isArray(msg) ? msg : [msg], as the samples above do. There is a third shape, and it is the one that breaks parsers: an asset with no book can answer with [[]] — an array containing one empty array, no object at all. It is neither a book nor a bare object, and it does not produce a no_book frame: it is a message from the venue, so it cancels the timer described below. After normalising, skip anything that is not an object:

book

A full snapshot of the order book, sent on subscribe and re-sent to late joiners.

price_change

Incremental level updates. Apply each entry in price_changes to your local book by asset_id and side.
A size of "0" means the level was removed. best_bid and best_ask give you the top of book without recomputing it.

last_trade_price

A lightweight update for a running price display: carries an asset_id at the top level and the price of the latest fill. There is no best_bid_ask frame. The top of book is delivered as the best_bid and best_ask fields inside each price_changes[] entry of a price_change frame — see above.

tick_size_change

Emitted when the venue changes a market’s minimum price increment. Carries an asset_id at the top level. Rare, but a client that switches on event_type should not treat it as unknown.

no_book

Emitted by Bravado when no message at all arrives from the venue for a subscribed asset within 8 seconds of opening the upstream connection, so your UI can render an empty state instead of hanging:
This is the one frame Bravado originates rather than forwarding from the venue.
It measures silence, not the absence of a book. The timer is cancelled by the first upstream message of any kind — including an empty frame that carries no book, and including a frame Bravado then discards. An asset that receives chatter but never a book therefore produces no no_book, and a client waiting for one waits forever. Do not use it as “this market has no book”; use it as “nothing came back”. The timer is re-armed only when the upstream connection is re-opened.

Limits

  • 120 assets per connection. Additional sub requests past the cap are ignored.
  • Upstreams are shared and ref-counted, so subscribing to a popular asset does not open a new upstream connection.

Health