跳转到主要内容

端点

wss://mmapi.55-tech.com/ws/subscribe

连接流程

1. 连接

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

2. 订阅

在连接后 30秒 内发送订阅消息:
{
  "type": "subscribe",
  "api_key": "your-uuid-api-key",
  "channels": ["orders", "bets", "accounts", "scores", "emergency"]
}

3. 确认

成功后,服务器响应:
{
  "type": "subscribed",
  "subscription_id": 1,
  "channels": ["orders", "bets", "accounts", "scores", "emergency"]
}

4. 接收广播

数据更新以广播消息形式到达,包含当前和先前状态:
{
  "type": "broadcast",
  "channel": "orders",
  "event": "UPDATE",
  "payload": {
    "orderId": 123,
    "orderStatus": "FILLED",
    "matchedStake": 100.0,
    "matchedAt": "2026-02-15T10:30:05Z"
  },
  "old": {
    "orderStatus": "PLACED",
    "matchedStake": 0
  }
}
old 字段包含先前状态,便于检测变更。

5. 保持活跃

发送心跳保持连接:
{"type": "ping"}
服务器响应:
{"type": "pong"}
服务器也会每 60秒 发送心跳:
{"type": "heartbeat"}

6. 取消订阅

停止接收更新并清理订阅:
{"type": "unsubscribe"}

频道

客户端过滤频道

这些频道仅传递属于您客户端的数据:
频道事件描述
ordersINSERT, UPDATE交易所订单下达、状态变更、成交
betsINSERT, UPDATE对冲投注下达、确认、结算
accountsUPDATE账户余额和状态变更

全局频道

所有订阅者都会收到:
频道事件描述
scoresUPDATE实时比分更新(进球、盘、节)
emergencyUPDATE紧急模式激活/停用

消息示例

订单成交

当交易所订单被匹配时:
{
  "type": "broadcast",
  "channel": "orders",
  "event": "UPDATE",
  "payload": {
    "orderId": 123,
    "fixtureId": "id1000000861624412",
    "outcomeId": 161,
    "exchange": "polymarket",
    "exchangeOrderId": "0x1a2b3c...",
    "orderStatus": "FILLED",
    "matchedStatus": "FULLY_MATCHED",
    "orderCents": 0.45,
    "orderStake": 100.0,
    "matchedStake": 100.0,
    "matchedAt": "2026-02-15T10:30:05Z"
  },
  "old": {
    "orderStatus": "PLACED",
    "matchedStatus": "NOT_MATCHED",
    "matchedStake": 0
  }
}

对冲投注下达

订单成交后,系统自动下对冲注:
{
  "type": "broadcast",
  "channel": "bets",
  "event": "INSERT",
  "payload": {
    "betId": 456,
    "orderId": 123,
    "client": "your-client",
    "bookmaker": "vertex",
    "placedPrice": 1.808,
    "placedStake": 100.0,
    "betStatus": "matched",
    "sentData": {
      "requestId": "a1b2c3d4",
      "eventId": 98765,
      "price": 1.808,
      "amount": 100.0,
      "side": "1"
    },
    "receivedData": {
      "betId": "789",
      "status": "U"
    },
    "placedAt": "2026-02-15T10:30:08Z"
  }
}

实时比分更新

{
  "type": "broadcast",
  "channel": "scores",
  "event": "UPDATE",
  "payload": {
    "fixtureId": "id1000000861624412",
    "live": true,
    "statusId": 1,
    "currentPeriod": "下半场",
    "currentMinute": 67,
    "scores": {
      "home": 2,
      "away": 1,
      "period1Home": 1,
      "period1Away": 0
    }
  }
}

紧急状态

{
  "type": "broadcast",
  "channel": "emergency",
  "event": "UPDATE",
  "payload": {
    "emergency": true,
    "reason": "手动触发",
    "triggeredAt": "2026-02-15T10:30:00Z"
  }
}

连接限制

设置
每API密钥最大连接数5
认证超时30秒
服务器心跳间隔60秒
客户端心跳间隔30秒(推荐)

错误消息

错误描述
api_key required订阅消息中缺少 api_key 字段
Invalid api_key formatAPI密钥必须是有效的UUID
Invalid API keyAPI密钥未找到或客户端未激活
Connection limit exceeded此API密钥已有5个活跃连接

示例:Python 客户端

import asyncio
import json
import websockets

async def connect():
    uri = "wss://mmapi.55-tech.com/ws/subscribe"
    async with websockets.connect(uri) as ws:
        # 订阅
        await ws.send(json.dumps({
            "type": "subscribe",
            "api_key": "YOUR_API_KEY",
            "channels": ["orders", "bets", "scores"]
        }))

        # 等待确认
        sub_resp = json.loads(await ws.recv())
        print(f"已订阅 (id={sub_resp.get('subscription_id')})")

        # 保活任务
        async def keep_alive():
            while True:
                await asyncio.sleep(30)
                await ws.send(json.dumps({"type": "ping"}))

        asyncio.create_task(keep_alive())

        # 监听更新
        async for message in ws:
            data = json.loads(message)
            if data["type"] == "broadcast":
                channel = data["channel"]
                event = data["event"]
                print(f"[{channel}:{event}] {data['payload']}")
                if "old" in data:
                    print(f"  变更自: {data['old']}")

asyncio.run(connect())

示例:JavaScript 客户端

const WebSocket = require('ws');

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

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

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

  if (msg.type === 'subscribed') {
    console.log(`已订阅 (id=${msg.subscription_id})`);
  }

  if (msg.type === 'broadcast') {
    console.log(`[${msg.channel}:${msg.event}]`, msg.payload);
    if (msg.old) {
      console.log('  变更自:', msg.old);
    }
  }
});

// 保持活跃
setInterval(() => {
  if (ws.readyState === WebSocket.OPEN) {
    ws.send(JSON.stringify({ type: 'ping' }));
  }
}, 30000);