Subscribe to changes in a particular order book. You will receive updates when orders are filled, cancelled, or posted. Note that for performance reasons, updates are delayed by at most 100ms.
There are two channels for order book data. Each publish is broadcast to both:
| Channel | Subscribe when you want to… |
|---|
order_book:market_{marketHash} | Track a specific market |
order_book:event_{sportXeventId} | Track all markets for a given event |
The channel no longer includes a baseToken parameter. The payload’s marketHash field can be used to identify the token if needed.
By market
CHANNEL NAME FORMAT
order_book:market_{marketHash}
| Name | Type | Description |
|---|
| marketHash | string | The market to subscribe to |
// To subscribe
const marketHash = "0x04b9af76dfb92e71500975db77b1de0bb32a0b2413f1b3facbb25278987519a7";
const sub = client.newSubscription(`order_book:market_${marketHash}`, { positioned: true, recoverable: true });
sub.on("publication", (ctx) => {
const data = ctx.data;
// message handler logic
});
sub.subscribe();
By event
CHANNEL NAME FORMAT
order_book:event_{sportXeventId}
| Name | Type | Description |
|---|
| sportXeventId | string | The event to subscribe to. Receives updates for all markets under this event. |
// To subscribe
const eventId = "L13772588";
const sub = client.newSubscription(`order_book:event_${eventId}`, { positioned: true, recoverable: true });
sub.on("publication", (ctx) => {
const data = ctx.data;
// message handler logic
});
sub.subscribe();
Message payload
Both channels share the same payload format. The message is an array of order objects with the fields below — the same fields as in the orders section, with additional status and updateTime fields.
| Name | Type | Description |
|---|
| orderHash | string | A unique identifier for this order |
| status | string | "ACTIVE" if still valid, "INACTIVE" if cancelled, "FILLED" if completely filled |
| fillAmount | string | How much this order has been filled in Ethereum units. See unit conversion. |
| pendingFillAmount | string | Amount pending fill in Ethereum units. See unit conversion. |
| maker | string | The market maker for this order |
| totalBetSize | string | Total size of this order in Ethereum units. See unit conversion. |
| percentageOdds | string | The odds the maker receives in the sportx protocol format. To convert to implied odds divide by 10^20. To get taker implied odds: takerOdds = 1 - percentageOdds / 10^20. See unit conversion. |
| expiry | number | Deprecated. Always 2209006800. |
| apiExpiry | number | The time in unix seconds after which this order is no longer valid |
| salt | string | A random number to differentiate identical orders |
| isMakerBettingOutcomeOne | boolean | true if the maker is betting outcome one |
| signature | string | Signature of the maker on this order |
| updateTime | string | Server-side clock time for the last modification of this order |
| sportXeventId | string | The event related to this order |
Messages are sent in batches as an array. If you receive two updates for the same orderHash, order them by updateTime after converting to a BigInt.
[
{
"orderHash": "0x7bd76648f589f3e272d48294d8881fe68aae7704f7b2ef0a50bf612be44271",
"status": "INACTIVE",
"fillAmount": "2000000000",
"pendingFillAmount": "1000000000",
"maker": "0x9883D5e7dC023A441A81Ef95af406C69926a0AB6",
"totalBetSize": "500000000",
"percentageOdds": "750000000000000000000",
"expiry": 1747500000000,
"apiExpiry": 1747500000000,
"salt": "12345678901234567890",
"isMakerBettingOutcomeOne": false,
"signature": "0xbf099ab02255d5e2a9e063dc43a7afe96e65f5e8fc2ed3d2ba60b0a3fcadb3441bf32271293e85b7a795c9d86a2384035a0da3285113e746547e236bc58885e01",
"updateTime": 1747490000000,
"sportXeventId": "L13772588"
}
]