WebSocket
Connecting
Open a WebSocket to /v1/ws/market or /v1/ws/user. The first message you send picks the channel.
- Subscribe within 10 seconds of connecting, or the connection is closed.
- Send the text frame
PINGto keep the connection open. The server answersPONG. The server does not send pings of its own. - A connection that sends nothing for 60 seconds is closed, so ping more often than that.
- Inbound messages are limited to 64 KiB.
- Like the book endpoints, the connection is refused with 503 while order books are loading. Retry shortly.
Market Channel
The market channel is public. Subscribe with the token IDs you want to follow:
{ "type": "market", "assetsIds": ["<tokenId>", "<tokenId>"] }Add or remove tokens on the same connection:
{ "operation": "subscribe", "assetsIds": ["<tokenId>"] }
{ "operation": "unsubscribe", "assetsIds": ["<tokenId>"] }- A connection can follow up to 500 tokens.
- The key is
assetsIds, in camelCase. - Unknown token IDs are ignored without an error.
Market Events
Every message has an eventType and a timestamp in Unix milliseconds as a string.
book is sent once per token right after you subscribe. It is a full snapshot, merged with the other outcome the same way as GET /book. Bids are in ascending price order and asks in descending order, so the best price is last.
{
"eventType": "book",
"market": "0x<conditionId>",
"assetId": "<tokenId>",
"timestamp": "1760000000000",
"hash": "<sha1 hex>",
"bids": [ { "price": "0.47", "size": "50" }, { "price": "0.48", "size": "120" } ],
"asks": [ { "price": "0.53", "size": "30" }, { "price": "0.52", "size": "80" } ]
}price_change is sent about every 100 milliseconds while a followed book changes. Each entry gives the new size at a price level. A size of "0" means the level was removed.
{
"eventType": "price_change",
"market": "0x<conditionId>",
"priceChanges": [
{
"assetId": "<tokenId>",
"price": "0.48",
"size": "0",
"side": "BUY",
"hash": "<sha1 hex>",
"bestBid": "0.47",
"bestAsk": "0.52"
}
],
"timestamp": "1760000000100"
}last_trade_price is sent as soon as a trade is matched, before it settles on-chain, for both tokens of the market. transactionHash is empty in this event.
{
"eventType": "last_trade_price",
"market": "0x<conditionId>",
"assetId": "<tokenId>",
"price": "0.48",
"side": "BUY",
"size": "40",
"feeRateBps": "0",
"timestamp": "1760000000200",
"transactionHash": ""
}User Channel
The user channel streams events for orders placed with one API key. Authenticate with the key credentials in the subscribe message:
{
"type": "user",
"auth": { "apiKey": "<apiKey>", "secret": "<secret>", "passphrase": "<passphrase>" },
"markets": ["0x<conditionId>"]
}- Send
secretandpassphraseexactly as issued. No request signature is used here. - An empty
marketsarray follows every market. Sending the message again replaces the market list. - One connection follows one API key. The number of user connections per key is limited, so keep one connection per key.
- Only orders placed with this key produce events. Orders placed with the wallet's other keys do not.
User Events
order events carry the same fields as the REST order object, plus type:
PLACEMENTwhen the order enters the book, with statusLIVE.CANCELLATIONwhen the order is canceled or expires, with statusCANCELEDorEXPIRED.
{ "eventType": "order", "type": "PLACEMENT", "timestamp": "1760000000000", "id": "0x...", "status": "LIVE", ... }trade events carry the REST trade fields from your side, with type set to TRADE and a bare status:
MATCHEDwhen the trade is matched.CONFIRMEDwhen settlement is confirmed, withtransactionHash.FAILEDwhen settlement fails.
{ "eventType": "trade", "type": "TRADE", "status": "MATCHED", "timestamp": "1760000000200", "id": "<trade ID>", ... }CANCELLATION event. Use GET /data/order/{id} to confirm the final status.Errors and Closing
- Errors use the REST envelope, for example
{"payload":null,"error":{"code":4001,"message":"malformed message: ..."}}. After an invalid message the connection stays open. - Failed authentication replies with code
4002andinvalid API key or signature, then closes the connection. - If the key is revoked, the connection receives an error within about 10 seconds and is closed.
- After any disconnect, reconnect, subscribe again, and reload your open orders and recent trades over REST before you trust the stream.
- A client that reads too slowly to keep up is disconnected.
- Server-initiated closes use close code
1008with a reason string.