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.
Recovery & reliability
Recovery, history, deduplication, and the snapshot-plus-subscribe seed pattern live on the Recovery & reliability reference. In short: passrecoverable: 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:connectingandsubscribingare non-terminal states. They fire on the initial connect or subscribe and also on automatic retry paths.disconnectedandunsubscribedare terminal states for automatic retry.
Client lifecycle
The client connection moves through these states:disconnected -> connecting -> connected: initial connectconnected -> connecting -> connected: retryable disconnect, then successful reconnectconnecting/connected -> disconnected: terminal disconnect
connecting: fired on the initialconnect()and on retryable reconnects. The event includes acodeandreason.connected: fired when the transport is established and the client is ready.disconnected: fired only when the client reaches terminaldisconnectedstate. 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.
client.connect() explicitly.
Subscription lifecycle
Each client-side subscription moves through its own state machine:unsubscribed -> subscribing -> subscribed: initial subscribesubscribed -> subscribing -> subscribed: retryable interruption, reconnect, or resubscribesubscribing/subscribed -> unsubscribed: terminal subscription stop
subscribing: fired on the initialsubscribe()and on retryable resubscribe paths.subscribed: fired when the subscription becomes active.unsubscribed: fired only when the subscription reaches terminalunsubscribedstate. 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.
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 toorderbook_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:
Monitor your active orders
Subscribe toaccount: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
ThegetToken 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:
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 subscriptionerror 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 code2500 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 gapwasRecovering: true, recovered: false: replay could not fill the gap, so re-seed from REST
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 the3500-3999 range.
Common terminal examples include:
3500invalid token3501bad request3503force disconnect3507permission denied
Slow consumer
The server buffers about 1 MB per connection. If yourpublication 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.
Related
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.