Skip to main content

Endpoint

wss://v2.55-tech.com/ws

Connection flow

1. Connect

Open a WebSocket connection. No authentication is needed at connection time.

2. Login

Send a login message within 30 seconds of connecting:
{
  "type": "login",
  "apiKey": "YOUR_API_KEY",
  "channels": []
}
An empty channels array subscribes to all available channels. To subscribe to specific channels:
{
  "type": "login",
  "apiKey": "YOUR_API_KEY",
  "channels": ["orders", "bets", "settlements"]
}
You can optionally enable reliable delivery with message acknowledgments:
{
  "type": "login",
  "apiKey": "YOUR_API_KEY",
  "channels": ["orders", "bets"],
  "reliableDelivery": true
}

3. Login confirmation

On success, the server responds with:
{
  "type": "login_ok",
  "clientName": "your-client",
  "channels": ["orders", "bets", "settlements"],
  "subscriptionId": 1,
  "access": {
    "clientFiltered": ["orders", "bets", "settlements", "accounts", "balance", "betslip"],
    "global": ["fixtures", "currencies", "status", "emergency"]
  },
  "reliableDelivery": false,
  "features": {
    "messageOrdering": true,
    "acknowledgments": false,
    "batchAck": false
  }
}

4. Receive updates

Data messages follow this format:
{
  "type": "data",
  "channel": "orders",
  "event": "INSERT",
  "payload": { ... },
  "ts": 1771183909789,
  "seq": 1
}
FieldDescription
typeAlways "data" for data messages
channelWhich channel this message belongs to
eventEvent type: INSERT, UPDATE, DELETE, SETTLED, STATUS
payloadThe full updated object (see payload schemas)
tsServer timestamp (milliseconds since epoch)
seqPer-subscription monotonically increasing sequence number
requireAckPresent and true only when reliable delivery is enabled
Full per-channel payload schemas are in Payload schemas below.

5. Keep alive

The server sends a ping every 30 seconds:
{"type": "ping"}
Respond with pong within 120 seconds or the connection is closed:
{"type": "pong"}
You can also send pings from the client — the server responds with pong.

Channels

Client-filtered channels

These channels only deliver data belonging to your clientName:
ChannelEventsDescription
ordersINSERT, UPDATE, DELETEOrder placement, fills, status changes
betsINSERT, UPDATE, DELETEBet placement, confirmation, and removal
settlementsSETTLEDSettlement status updates (same payload as bets)
accountsINSERT, UPDATE, DELETEAccount creation, updates, and deletion
balanceUPDATEBalance change notifications
betslipUPDATEReal-time odds updates for active betslip subscriptions (60s window after each GET /betslip call)

Global channels

All subscribers receive these:
ChannelEventsDescription
fixturesUPDATEFixture metadata and score changes
currenciesUPDATECurrency exchange rate updates
statusSTATUSSystem status changes
emergencySTATUSEmergency mode activation/deactivation

Reliable delivery & acknowledgments

By default, messages are fire-and-forget — fast, but a message dropped during a disconnect is gone. Enable reliable delivery at login to get at-least-once delivery with acknowledgments and replay:
{ "type": "login", "apiKey": "YOUR_API_KEY", "channels": ["orders", "bets"], "reliableDelivery": true }
When enabled, each data message carries requireAck: true, and you must acknowledge it so the server can release it from its buffer:
{ "type": "ack", "seq": 42 }
Or acknowledge a range in one message (recommended for throughput):
{ "type": "ack_batch", "upToSeq": 50 }
How it works:
  • The server buffers up to 100 unacknowledged messages per subscription and re-sends any not acked within 30 seconds.
  • seq is per-subscription and strictly increasing, so a gap in seq means you missed a message.
  • To recover missed messages after a reconnect, request a replay from the last seq you processed:
{ "type": "replay", "fromSeq": 40 }
If you fall further behind than the 100-message buffer, the oldest unacked messages are dropped. Ack promptly (or use ack_batch) and treat any seq gap that a replay can’t fill as a signal to reconcile via the REST endpoints (GET /orders, GET /bets).

Changing subscriptions

Change channels without reconnecting:
{ "type": "update_channels", "channels": ["orders", "bets", "settlements"] }
The server replies with channels_updated.

Betslip subscriptions

The betslip channel pushes real-time odds for selections you’re watching. There are two ways to subscribe:
  1. Via REST — calling GET /betslip registers a 60-second sliding window; each call resets the timer and immediately broadcasts a snapshot over the WebSocket.
  2. Via WebSocket — send a subscribe_betslip message with an explicit ttl (10–3600s) and bookmaker list for finer control, and unsubscribe_betslip to cancel early.
A maximum of 20 active betslip subscriptions per client (REST + WS combined) is enforced. Message shapes and the subscribed_betslip confirmation are documented in Betslip subscription messages below.

Example: Python client

import asyncio
import json
import websockets

async def connect():
    uri = "wss://v2.55-tech.com/ws"
    async with websockets.connect(uri) as ws:
        # Login
        await ws.send(json.dumps({
            "type": "login",
            "apiKey": "YOUR_API_KEY",
            "channels": ["orders", "bets", "settlements"]
        }))

        # Wait for login confirmation
        login_resp = json.loads(await ws.recv())
        print(f"Logged in as {login_resp.get('clientName')}")

        # Listen for updates (respond to pings automatically)
        async for message in ws:
            data = json.loads(message)
            if data["type"] == "ping":
                await ws.send(json.dumps({"type": "pong"}))
            elif data["type"] == "data":
                print(f"[{data['channel']}:{data['event']}] {data['payload']}")

asyncio.run(connect())

Example: JavaScript client

const WebSocket = require('ws');

const ws = new WebSocket('wss://v2.55-tech.com/ws');

ws.on('open', () => {
  ws.send(JSON.stringify({
    type: 'login',
    apiKey: 'YOUR_API_KEY',
    channels: ['orders', 'bets', 'settlements']
  }));
});

ws.on('message', (raw) => {
  const msg = JSON.parse(raw);

  if (msg.type === 'login_ok') {
    console.log(`Logged in as ${msg.clientName}`);
  }

  if (msg.type === 'ping') {
    ws.send(JSON.stringify({ type: 'pong' }));
  }

  if (msg.type === 'data') {
    console.log(`[${msg.channel}:${msg.event}]`, msg.payload);
  }
});

Message types

Client → Server

TypeExamplePurpose
login{"type": "login", "apiKey": "...", "channels": []}Authenticate and subscribe. Optional reliableDelivery: true.
update_channels{"type": "update_channels", "channels": ["orders"]}Change channel subscriptions after login.
pong{"type": "pong"}Reply to a server ping.
ping{"type": "ping"}Liveness check; server replies with pong.
ack{"type": "ack", "seq": 42}Acknowledge one message (reliable delivery).
ack_batch{"type": "ack_batch", "upToSeq": 50}Acknowledge all messages up to and including upToSeq.
replay{"type": "replay", "fromSeq": 40}Request re-send of buffered messages from fromSeq.
subscribe_betslipsee belowOpen a betslip price subscription with a custom TTL.
unsubscribe_betslipsee belowCancel a betslip subscription early.

Server → Client

TypePurpose
login_okLogin succeeded; echoes channels, access scopes, and enabled features.
channels_updatedConfirms an update_channels change.
dataA channel event (see payload schemas).
pingServer keep-alive; reply with pong.
subscribed_betslipConfirms a subscribe_betslip, with effective expiresAt.
errorA problem with a client message; includes a ref to the offending request.

Betslip subscription messages

The betslip channel must be in your subscriptions (add it via login or update_channels) before subscribing.

subscribe_betslip

{
  "type": "subscribe_betslip",
  "fixtureId": "id1000004461512432",
  "outcomeId": 103,
  "playerId": 0,
  "bookmakers": ["pinnacle", "sharpbet"],
  "ttl": 300
}
  • bookmakers must be a non-empty list.
  • ttl is optional (seconds), clamped to 10–3600s; defaults to 60s if omitted.
  • Re-subscribing to the same selection refreshes the TTL and updates the bookmaker set (idempotent).
Server confirms:
{
  "type": "subscribed_betslip",
  "fixtureId": "id1000004461512432",
  "outcomeId": 103,
  "playerId": 0,
  "bookmakers": ["pinnacle", "sharpbet"],
  "expiresAt": "2026-02-07T17:34:37+00:00"
}
Bookmakers you have no account for are dropped from the subscription and returned in a skipped array. A maximum of 20 active betslip subscriptions per client (REST + WS combined) is enforced.

unsubscribe_betslip

{
  "type": "unsubscribe_betslip",
  "fixtureId": "id1000004461512432",
  "outcomeId": 103,
  "playerId": 0
}

Payload schemas

Data messages wrap channel payloads in the envelope {type, channel, event, payload, ts, seq}. The orders, bets, and settlements channels deliver the full database row (row_to_json); balance, emergency, and betslip use custom shapes.

Orders

Full row from the orders table:
{
  "orderId": 327,
  "requestUuid": "eb45b192-317b-42d5-9f65-af497b9fa8c1",
  "client": "demo",
  "clientName": "demo",
  "fixtureId": "id1000004461512432",
  "outcomeId": 103,
  "playerId": 0,
  "orderPrice": 1.95,
  "orderStake": 10.0,
  "filledStake": 10.0,
  "remainingStake": 0.0,
  "orderStatus": "FILLED",
  "statusReason": null,
  "userRef": "bettor1234",
  "testOrder": false,
  "acceptBetterOdds": true,
  "acceptPartialStake": true,
  "orderCurrency": "USD",
  "back": true,
  "allowedBookmakers": "*",
  "oddsInfo": null,
  "meta": {},
  "expiresAt": "2026-02-07T17:29:37+00:00",
  "filledAt": "2026-02-07T17:29:32+00:00",
  "createdAt": "2026-02-07T17:29:32+00:00",
  "updatedAt": "2026-02-07T17:29:32+00:00"
}

Bets / settlements

Full row from the bets table (the settlements channel uses the same shape):
{
  "betId": 73,
  "orderId": 327,
  "bookmaker": "pinnacle",
  "bookmakerBetId": "3332684214",
  "betStatus": "CONFIRMED",
  "settlementStatus": "UNSETTLED",
  "placedStake": 10.0,
  "placedPrice": 1.98,
  "placedCurrency": "USD",
  "account": "pinnacle_main",
  "requestUuid": "eb45b192-317b-42d5-9f65-af497b9fa8c1",
  "userRef": "bettor1234",
  "testBet": false,
  "client": "demo",
  "clientName": "demo",
  "sentData": { "stake": 10.0, "price": 1.95 },
  "receivedData": { "betId": "3332684214", "status": "accepted", "price": 1.98 },
  "settlementAmount": null,
  "settlementReason": null,
  "settledAt": null,
  "declineReason": null,
  "betRequestId": null,
  "oddsInfo": null,
  "meta": {},
  "placedAt": "2026-02-07T17:29:32+00:00",
  "createdAt": "2026-02-07T17:29:32+00:00",
  "updatedAt": "2026-02-07T17:29:32+00:00"
}
Subscribing to both bets and settlements delivers settlement updates twice — once on each channel. Use settlements alone if you want a dedicated settlement feed.

Balance

{
  "clientName": "demo",
  "bookmaker": "pinnacle",
  "username": "pinnacle_main",
  "balance": 4990.0,
  "currency": "USD",
  "ts": 1771183910123
}

Emergency

{
  "active": true,
  "reason": "Upstream provider maintenance",
  "ts": 1771183910123
}

Betslip

Pushed while a betslip subscription is active. For futures the payload carries futureId and participantId instead of fixtureId. Fixture:
{
  "clientName": "demo",
  "fixtureId": "id1000004461512432",
  "outcomeId": 103,
  "playerId": 0,
  "odds": {
    "pinnacle": {
      "id1000004461512432:pinnacle:103:0": {
        "price": 1.98,
        "limit": 500.0,
        "limitMin": 1.0,
        "limitCurrency": "USD",
        "limitUsd": 500.0,
        "limitMinUsd": 1.0,
        "active": true,
        "account": "pinnacle_main",
        "currencyInfo": { "currency": "USD", "currencyValue": 1, "updatedAt": "2026-02-07T17:29:32+00:00" }
      }
    }
  }
}
Futures (coming soon):
{
  "clientName": "demo",
  "futureId": "fut_123456",
  "outcomeId": 0,
  "playerId": 0,
  "participantId": 5,
  "odds": {
    "pinnacle": {
      "fut_123456:pinnacle:0:0:5": {
        "price": 3.50,
        "limit": 1000.0,
        "limitMin": 5.0,
        "limitCurrency": "USD",
        "limitUsd": 1000.0,
        "limitMinUsd": 5.0,
        "active": true,
        "account": "pinnacle_main",
        "currencyInfo": { "currency": "USD", "currencyValue": 1, "updatedAt": "2026-02-07T17:29:32+00:00" }
      }
    }
  }
}
Futures betslip WebSocket broadcasting is not yet enabled. The subscription infrastructure is in place and will be activated in an upcoming release.

Connection limits

SettingValue
Max connections per API key5
Auth timeout30 seconds
Server ping interval30 seconds
Pong timeout (disconnect)120 seconds
Message buffer (reliable delivery)100 messages
Output queue per client2000 messages
Max betslip subscriptions per client20

Next steps

Currency & Limits

How values are denominated and converted across currencies.

Errors

Handle error responses and decline reasons.