Skip to main content

Overview

SX Bet’s WebSocket API delivers real-time updates on orderbook changes, trade executions, market status, and live scores. All channels are powered by Centrifugo over a single WebSocket connection and require a short-lived token. Centrifugo provides official client SDKs for JavaScript, Python, Go, Dart, Swift, Java, and C#; the examples here use the JavaScript and Python ones. Rather than polling REST endpoints, subscribe to the channels relevant to your workflow. The recommended pattern for most use cases is: fetch current state via REST, then subscribe to stay updated — this avoids gaps between your initial snapshot and the live feed.
1

Authenticate

Pass your API key via the getToken callback. Token refresh is handled automatically.
2

Connect

Create a Centrifuge client pointed at the WebSocket URL.
3

Subscribe

Create a subscription for each channel you need and attach a publication handler.

Getting started

Install a client SDK, fetch a token, connect, and subscribe — see Initialization.

Channels

Account channels use Centrifugo’s user-limited form — a # followed by the checksummed address the channel belongs to, which must byte-match your token’s sub. See Subscribing to your own channels.

Subscribing to your own channels

Account channels use Centrifugo’s user-limited channel form: a # followed by the user the channel belongs to.
Ensure you checksum the address passed in and do not use your proxy wallet address, use your account address

Recovery & reliability

Recovery, history, deduplication, and the snapshot-plus-subscribe seed pattern live on the Recovery & reliability reference. In short: pass recoverable: true on channels whose namespace has history, then check recovered in the subscribed handler to decide whether to re-seed from REST.

Connection & Subscription Lifecycle

The client connection and each subscription have separate lifecycles. The key rule is:
  • connecting and subscribing are non-terminal states. They fire on the initial connect or subscribe and also on automatic retry paths.
  • disconnected and unsubscribed are terminal states for automatic retry.

Client lifecycle

The client connection moves through these states:
  • disconnected -> connecting -> connected: initial connect
  • connected -> connecting -> connected: retryable disconnect, then successful reconnect
  • connecting/connected -> disconnected: terminal disconnect
Use the client events to understand what happened:
  • connecting: fired on the initial connect() and on retryable reconnects. The event includes a code and reason.
  • connected: fired when the transport is established and the client is ready.
  • disconnected: fired only when the client reaches terminal disconnected state. After this, the SDK will not reconnect automatically.
  • error: fired for internal errors that do not necessarily cause a state transition, such as transport errors during initial connect or reconnect, or connection token refresh errors.
To reconnect after a terminal disconnect, call client.connect() explicitly.

Subscription lifecycle

Each client-side subscription moves through its own state machine:
  • unsubscribed -> subscribing -> subscribed: initial subscribe
  • subscribed -> subscribing -> subscribed: retryable interruption, reconnect, or resubscribe
  • subscribing/subscribed -> unsubscribed: terminal subscription stop
Use subscription events to understand what happened:
  • subscribing: fired on the initial subscribe() and on retryable resubscribe paths.
  • subscribed: fired when the subscription becomes active.
  • unsubscribed: fired only when the subscription reaches terminal unsubscribed state. After this, the SDK will not resubscribe automatically.
  • publication: fired whenever a new message arrives on the subscription while it is active.
  • error: fired for internal subscription errors that do not necessarily cause a state transition, such as temporary subscribe errors or subscription token related errors.
To start a terminally unsubscribed subscription again, call sub.subscribe() explicitly. Handle unsubscribed on every account channel. A permission refusal is terminal, and it lands there rather than on error — so a client that only watches error cannot tell a refused channel from an inactive account.

Examples

Consume a global feed

Maintain a recoverable order book

Subscribe to orderbook_v3:{marketHash} with recoverable: true. Apply only newer versions, and seed from the REST snapshot on subscribe so you never miss updates between your snapshot and the live feed:
See Book versioning for the full apply rule.

Monitor your active orders

Subscribe to account:orders_v3_#{address} to receive fills, cancellations, and new posts for your address in real time. This channel is the only place an order’s terminal reason appears:
GET /orders-v3 returns active orders only, so polling can tell you an order is gone but never why. See Tracking your orders.

Common failures

In most cases, you do not need to write custom retry logic around these errors. The SDK already handles reconnect and resubscribe automatically when the condition is retryable. The codes below are most useful for telemetry, debugging, and contacting support if an issue persists.

Auth

The getToken callback is called on initial connect and whenever the token needs to be refreshed. How you throw from it controls what the SDK does next:
If your realtime-token endpoint returns 401 or 403, throw UnauthorizedError so the connection stops retrying and moves to terminal disconnected. For transient failures like 429 or 5xx, throw a normal error so the SDK keeps retrying with backoff. See Rate limits. The server may also issue a terminal auth disconnect such as code 3500 ("invalid token"). In that case, the client stops reconnecting automatically.

Subscribe errors

Retryable subscription errors emit the subscription error event. Terminal subscription errors move the subscription to unsubscribed.
For the full list of built-in client error codes, see Centrifugo client protocol codes.

Recovery lost / insufficient state

If Centrifugo detects that recovery cannot continue from the current stream position, it may either resubscribe the affected subscription or reconnect the client, depending on where the problem is detected. This can surface as unsubscribe code 2500 or disconnect code 3010, both with reason "insufficient state". This is not terminal by itself. The next subscribed event tells you whether the replay succeeded:
  • wasRecovering: true, recovered: true: replay filled the gap
  • wasRecovering: true, recovered: false: replay could not fill the gap, so re-seed from REST
If you see insufficient state frequently, it usually indicates a stream continuity problem rather than a client bug.

Terminal disconnects

The client reconnects automatically after most disconnects. It does not reconnect for built-in terminal disconnect codes in the 3500-3999 range. Common terminal examples include:
  • 3500 invalid token
  • 3501 bad request
  • 3503 force disconnect
  • 3507 permission denied
For the full list of built-in disconnect codes, see Centrifugo client protocol codes.

Slow consumer

The server buffers about 1 MB per connection. If your publication handler is slow, that buffer fills faster than it drains and the server closes the connection. In Centrifugo this surfaces as disconnect code 3008 ("slow"), which is reconnectable but indicates your consumer cannot keep up. Keep handlers fast: receive the message and hand it off to a queue or async task immediately.

Market Making →

Using account:orders_v3 to monitor your open orders in real time.

Taking Liquidity →

How to submit fills and monitor your trade history.

Initialization →

Install, connect, and subscribe with the Centrifuge client.

Market Making Parlays →

Responding to parlay quote requests via parlay_markets:global.
Last modified on August 11, 2026