跳转到主要内容

端点

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

连接流程

1. 连接

打开WebSocket连接。连接时无需身份验证。

2. 登录

在连接后 30秒 内发送登录消息:
{
  "type": "login",
  "apiKey": "YOUR_API_KEY",
  "channels": []
}
空的 channels 数组订阅所有可用频道。要订阅特定频道:
{
  "type": "login",
  "apiKey": "YOUR_API_KEY",
  "channels": ["orders", "bets", "settlements"]
}
可选启用可靠传递和消息确认:
{
  "type": "login",
  "apiKey": "YOUR_API_KEY",
  "channels": ["orders", "bets"],
  "reliableDelivery": true
}

3. 登录确认

成功后,服务器响应:
{
  "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. 接收更新

数据消息格式如下:
{
  "type": "data",
  "channel": "orders",
  "event": "INSERT",
  "payload": { ... },
  "ts": 1771183909789,
  "seq": 1
}
字段描述
type数据消息始终为 "data"
channel此消息所属频道
event事件类型:INSERTUPDATEDELETESETTLEDSTATUS
payload完整的更新对象(见下方各频道负载格式)
ts服务器时间戳(自纪元以来的毫秒数)
seq每订阅的单调递增序列号
requireAck仅在启用可靠传递时存在且为 true

5. 保持活跃

服务器每 30秒 发送一次 ping:
{"type": "ping"}
120秒 内回复 pong,否则连接将被关闭:
{"type": "pong"}
您也可以从客户端发送 ping — 服务器会回复 pong。

频道

客户端过滤频道

这些频道仅传递属于您 clientName 的数据:
频道事件描述
ordersINSERT, UPDATE, DELETE订单下达、成交、状态变更
betsINSERT, UPDATE, DELETE投注下达、确认和移除
settlementsSETTLED结算状态更新(负载与 bets 相同)
accountsINSERT, UPDATE, DELETE账户创建、更新和删除
balanceUPDATE余额变动通知
betslipUPDATE活跃投注单订阅的实时赔率更新(每次 GET /betslip 调用后 60 秒窗口)

全局频道

所有订阅者都会收到:
频道事件描述
fixturesUPDATE赛事元数据和比分变更
currenciesUPDATE货币汇率更新
statusSTATUS系统状态变更
emergencySTATUS紧急模式激活/停用

负载格式

订单负载

orders 表的完整数据行:
{
  "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 表的完整数据行:
{
  "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"
}

余额负载

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

紧急负载

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

投注单负载

当投注单订阅处于活跃状态时推送实时赔率更新。调用 GET /betslip 注册一个 60 秒的滑动窗口 — 在此窗口内,价格变化以与投注单 REST 响应相同的格式进行广播。每次轮询重置计时器。 这适用于赛事和期货投注单订阅。对于期货,负载包含 futureIdparticipantId 而非 fixtureId 赛事投注单示例:
{
  "fixtureId": "id1000004461512432",
  "outcomeId": 103,
  "playerId": 0,
  "client": "demo",
  "userRef": null,
  "odds": {
    "pinnacle": {
      "odds_12345": {
        "price": 1.98,
        "limit": 500.0,
        "limitMin": 1.0,
        "limitCurrency": "USD",
        "limitUsd": 500.0,
        "limitMinUsd": 1.0,
        "active": true,
        "account": "pinnacle_main"
      }
    }
  }
}
期货投注单示例(即将推出):
{
  "futureId": "fut_123456",
  "outcomeId": 0,
  "playerId": 0,
  "participantId": 5,
  "client": "demo",
  "userRef": null,
  "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"
      }
    }
  }
}
期货投注单 WebSocket 广播尚未启用。订阅基础设施已就绪,将在即将发布的版本中激活。

连接限制

设置
每API密钥最大连接数5
认证超时30秒
服务器 ping 间隔30秒
Pong 超时(断开连接)120秒
消息缓冲区(可靠传递)100条消息
每客户端输出队列2000条消息

示例:Python 客户端

import asyncio
import json
import websockets

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

        # 等待登录确认
        login_resp = json.loads(await ws.recv())
        print(f"已登录为 {login_resp.get('clientName')}")

        # 监听更新(自动回复 ping)
        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())

示例:JavaScript 客户端

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(`已登录为 ${msg.clientName}`);
  }

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

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