Documentation Index
Fetch the complete documentation index at: https://docs.55-tech.com/llms.txt
Use this file to discover all available pages before exploring further.
wss://mmapi.55-tech.com/ws/subscribe
连接流程
1. 连接
打开WebSocket连接。连接时无需身份验证。
2. 订阅
在连接后 30秒 内发送订阅消息:
{
"type": "subscribe",
"apiKey": "your-uuid-api-key",
"channels": ["orders", "bets", "accounts", "scores", "emergency"]
}
3. 确认
成功后,服务器响应:
{
"type": "subscribed",
"subscriptionId": 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. 保持活跃
发送心跳保持连接:
服务器响应:
服务器也会每 60秒 发送心跳:
6. 取消订阅
停止接收更新并清理订阅:
客户端过滤频道
这些频道仅传递属于您客户端的数据:
| 频道 | 事件 | 描述 |
|---|
orders | INSERT, UPDATE | 交易所订单下达、状态变更、成交 |
bets | INSERT, UPDATE | 对冲投注下达、确认、结算 |
accounts | UPDATE | 账户余额和状态变更 |
全局频道
所有订阅者都会收到:
| 频道 | 事件 | 描述 |
|---|
scores | UPDATE | 实时比分更新(进球、盘、节) |
emergency | UPDATE | 紧急模式激活/停用 |
消息示例
订单成交
当交易所订单被匹配时:
{
"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": "placed",
"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秒(推荐) |
错误消息
| 错误 | 描述 |
|---|
apiKey required | 订阅消息中缺少 apiKey 字段 |
Invalid apiKey format | API密钥必须是有效的UUID |
Invalid API key | API密钥未找到或客户端未激活 |
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",
"apiKey": "YOUR_API_KEY",
"channels": ["orders", "bets", "scores"]
}))
# 等待确认
sub_resp = json.loads(await ws.recv())
print(f"已订阅 (id={sub_resp.get('subscriptionId')})")
# 保活任务
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',
apiKey: 'YOUR_API_KEY',
channels: ['orders', 'bets', 'scores']
}));
});
ws.on('message', (raw) => {
const msg = JSON.parse(raw);
if (msg.type === 'subscribed') {
console.log(`已订阅 (id=${msg.subscriptionId})`);
}
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);