WebSocket API

Overview

How to connect to the WebSocket API, the message format, the topics you can subscribe to, and the rules that keep a connection open.

The WebSocket API streams live market data and the events of your own orders over one connection. You connect once, subscribe to the topics you need, and the server pushes each topic's messages as they happen.

Connect

NetworkURL
BNB Mainnetwss://ws.predict.fun/ws
BNB TestnetNot available yet

Connections are served only on the /ws path, over TLS.

Send your API key when you connect, in one of two ways:

  • The x-api-key header, which is preferred.
  • The apiKey query parameter, for clients that can't set headers, such as browsers: wss://ws.predict.fun/ws?apiKey=YOUR_API_KEY.

The key is checked once, at the handshake. A handshake that fails gets an HTTP status instead of a connection, such as 401 for an invalid key or 503 while the service is unavailable.

Messages

Every message is a JSON text frame. Field names and values are case-sensitive, and timestamps are milliseconds since the Unix epoch.

You send requests, with a method, a requestId of your choice and the request's params:

{ "method": "subscribe", "requestId": 1, "params": ["predictOrderbook/123"] }

The server answers each request with a response (type: "R") that carries the same requestId:

{ "type": "R", "requestId": 1, "success": true }

Everything else the server sends is a topic message (type: "M"), with the topic it belongs to and its data:

{ "type": "M", "topic": "predictOrderbook/123", "data": { "marketId": 123, "asks": [[0.62, 1500]], "bids": [[0.61, 2000]] } }

The requests are Subscribe, Unsubscribe and Set language. Each subscribe or unsubscribe names one topic.

Errors

A request that fails gets a response with success: false and an error:

{
  "type": "R",
  "requestId": 1,
  "success": false,
  "error": { "code": "invalid_topic", "message": "unknown topic: predictOrderbok" }
}
error.codeCause
invalid_jsonThe frame isn't a valid request, for example its requestId or params is missing. The response's requestId is -1.
invalid_topicThe topic is missing or unknown, or one of its parameters is invalid.
invalid_paramsA Set language request has no language code.
invalid_credentialsThe JWT in a wallet events topic is invalid, revoked or expired.
internal_server_errorSomething failed on our side. Try again.

Topics

TopicWhat it sendsLatest value on subscribe
predictOrderbook/{marketId}The market's whole order book, each time it changes.Yes
predictTopOfBook/{marketId}The market's best bid and best ask, each time either changes.Yes
predictTradingStatus/{marketId}Changes to the market's tradingStatus.Yes
predictMarketStatus/{marketId}Changes to the market's status, such as resolution.Yes
predictMarketChanged/{marketId}A notice that the market's details changed.No
predictCategoryChanged/{categoryId}A notice that the category's details changed.No
predictWalletEvents/{jwt}The events of your wallet's orders. The topic holds a JWT from the REST API.No

For the topics marked Yes, the latest value arrives right after the subscribe response, followed by live updates. It's best effort: when there's nothing to send yet, only updates arrive.

Keep the connection open

  • Heartbeats. Every 15 seconds the server sends a heartbeat message. Echo its data back before the next one, or the server closes the connection.
  • Reconnect notices. Before a server shuts down, it sends a reconnect notice on the system topic, then closes the connection after graceMs.
  • Message size. A frame from the client can be at most 8 KiB. A larger one closes the connection.
  • Keeping up. Read messages as fast as they arrive. The server disconnects a client that falls too far behind.
Close codeWhy the server closed the connection
1000A heartbeat went unanswered, or a message from the client was over 8 KiB once decompressed.
1001The server is shutting down, after a reconnect notice. The reason is server draining.
1009A frame from the client was over 8 KiB.
NoneThe client fell behind, or the server dropped its connections after a gap in delivery. The server sends no close frame, so browsers report 1006.

Reconnect after every close you didn't start. Subscriptions don't carry over to a new connection, and messages sent while you were disconnected aren't replayed. After you reconnect, subscribe again and refetch what you track from the REST API. Stay connected shows how.

How-tos

The client example is a complete TypeScript client with heartbeats, reconnection and typed messages.

The AsyncAPI document behind these pages is at /asyncapi/websocket.json. You can use it to generate a client.

On this page