注单同步
已结算的注单以 GET /bets 依写入顺序增量读取。你只要保存上一页返回的 nextCursor,下一次原样带回,就能不漏、不重地同步到你的系统。
- 一位玩家在一局的所有下注是一张注单(
slipId)。 - 注单在该局结算后才会出现(通常在开牌后几秒内)。
- 结果修正或作废时,同一张注单会以较大的
rev再出现一次,成为新的一笔记录。
同步循环
cursor = 读取上次保存的游标(第一次为空)
重复:
page = GET /bets?limit=1000&cursor=<cursor> 第一次可改带 from=<ISO 时间>
在同一个数据库交易中:
以 (slipId, rev) 为唯一键写入 page.items(已存在就略过)
保存 cursor = page.nextCursor
若 page.hasMore 为 false:已追上,等待 5–30 秒// Node.js:以〈认证与签名〉的 call() 送出签名请求
async function syncBets(db, auth) {
let cursor = await db.loadCursor(); // 第一次为 null
for (;;) {
const query = cursor ? `cursor=${encodeURIComponent(cursor)}` : 'from=2026-09-01T00:00:00Z';
const page = await call('GET', `/api/tenant/v1/bets?limit=1000&${query}`, undefined, auth);
await db.transaction(async (tx) => {
for (const bet of page.items) await tx.upsertBet(bet); // 唯一键 (slipId, rev)
await tx.saveCursor(page.nextCursor);
});
cursor = page.nextCursor;
if (!page.hasMore) await new Promise((r) => setTimeout(r, 10_000)); // 已追上:稍后再轮询
}
}- 先写入注单、再保存游标(同一个交易最好):中途失败时,下次会从旧游标重读,以
(slipId, rev)去重即可。 hasMore为true时立即读下一页;为false表示已追上,稍后再用同一个nextCursor轮询。limit为 1–1000,默认 500。- 游标格式是
yyyymm.序号,请当成不透明字符串保存;格式错误回400 INVALID_CURSOR。 - 有
cursor时会忽略from。第一次同步不带cursor时,从当月(UTC)第一笔开始,或从from指定的时间(以分钟对齐)开始。 - 从很久以前补数据时,每次调用最多往后推进 3 个月;游标还没追到目前的 UTC 月份时
hasMore一律是true,照着nextCursor一直读即可。 recSeq只在同一个 UTC 月份内递增,跨月重新起算,不要拿它当唯一键。
版次(rev)、重算与作废
status | 意义 | rev |
|---|---|---|
settled | 首次结算 | 通常为 1 |
recalculated | 数据源修正结果后重新结算 | 较大 |
void | 作废(倒牌、荷官失误、设备故障…),本金全额退回(牛牛连同预扣) | 较大 |
- 同一个
slipId以最大的rev为准;旧版本保留下来可以追溯。 - 重算与作废的记录依发生的时间写入,一定出现在你目前的游标之后,游标同步不会漏掉任何版本(包含跨月的情况)。
delta是这个版本对玩家余额的实际入账差额:首次结算为payout;重算为新旧派彩的差(可以是负数,也就是收回已派彩的金额);作废为本金(牛牛再加预扣)减去先前的派彩。玩家钱包已经由本平台自动调整,你不需要另外转账。- 重算可能让玩家余额变成负数(已派出的彩金被收回、玩家已把钱转出时)。
- 结果修正与作废有护栏:在结算后 30 分钟内送达、且新结果完整并通过补牌规则验证时才会自动重算或冲回;超出护栏时维持原结果、不动金额,该局列为争议局(
GET /rounds/{roundId}的status为disputed)。 - 在你的报表中,用新版本取代旧版本即可;需要差额时以
delta或前后两版的winLoss相减。
注单内容
{
"recSeq": 1024,
"slipId": "01K5Y0B8Z6R2M4N7P9Q3S5T8VW.7H3KQ2XA",
"rev": 1,
"status": "settled",
"username": "alice",
"currency": "TWD",
"tableId": "S01",
"game": "baccarat",
"variant": "nocomm",
"roundId": "01K5Y0B8Z6R2M4N7P9Q3S5T8VW",
"shoe": "260924-03",
"round": 12,
"bets": [
{ "zone": "B", "amount": "10000", "return": "15000" },
{ "zone": "S6", "amount": "1000", "return": "13000" }
],
"stake": "11000",
"validStake": "6000",
"rolling": "0",
"payout": "28000",
"winLoss": "17000",
"delta": "28000",
"result": { "code": "1", "cardInfo": "122334424000" },
"placedAt": "2026-09-24T03:00:41.120Z",
"settledAt": "2026-09-24T03:01:20.480Z"
}这张注单是免佣百家乐:押庄 10,000、超级六 1,000,庄 6 点胜。
| 字段 | 说明 |
|---|---|
bets[] | 各投注区的本金 amount 与退回 return(本金+净赢;和局退回本金;输为 0)。投注区见桌台与局结果 |
stake | 本金合计(11,000) |
payout | 派彩合计,含本金(15,000 + 13,000 = 28,000) |
winLoss | 玩家输赢 = payout − stake(17,000,正数表示玩家赢);牛牛还要减去预扣,见牛牛的注单 |
validStake | 有效投注:庄胜时为「庄净赢减去闲注的绝对值」加上和、对子、超级六的本金(这里是 5,000 − 0 再加 1,000 = 6,000);闲胜对称;和局只计和、对子(与超级六)。龙虎见桌台与局结果 |
rolling | 洗码量:输掉的注本金合计(超级六不计);这张注单没有输的注,所以是 0 |
result | 局的结果码与牌面字符串,格式见桌台与局结果 |
placedAt、settledAt | 第一笔下注时间、这个版本的结算时间 |
德州扑克的注单
德州扑克(game: "holdem")每一手、每位参与的玩家一张注单:roundId 是这一手的 ID、round 是这张桌的第几手、shoe 为空字符串。另外多 rake、onsite 与 hand 三个字段:
{
"recSeq": 2048,
"slipId": "01K62H3P9R8Q7M6N5B4V3C2X1Z.3",
"rev": 1,
"status": "settled",
"username": "alice",
"currency": "TWD",
"tableId": "H01",
"game": "holdem",
"variant": "casino",
"roundId": "01K62H3P9R8Q7M6N5B4V3C2X1Z",
"shoe": "",
"round": 318,
"bets": [
{ "zone": "ANTE", "amount": "100", "return": "200" },
{ "zone": "CALL", "amount": "200", "return": "400" },
{ "zone": "AAB", "amount": "50", "return": "0" }
],
"stake": "350",
"validStake": "350",
"rolling": "350",
"payout": "600",
"winLoss": "250",
"delta": "600",
"result": { "code": "player_wins", "cardInfo": "AS KD 7H 7C 2S|AH 7D|QS 3C" },
"rake": "0",
"onsite": false,
"hand": { "handId": "01K62H3P9R8Q7M6N5B4V3C2X1Z", "no": 318, "outcome": "player_wins", "cards": "AS KD 7H 7C 2S|AH 7D|QS 3C" },
"placedAt": "2026-09-27T08:12:03.410Z",
"settledAt": "2026-09-27T08:13:10.020Z"
}这张注单是玩家对荷官桌:底注 100、跟注 200、AA 边注 50;玩家两对赢荷官一对 Q,底注 1 赔 1、跟注 1 赔 1,AA 边注没中。
| 字段 | 说明 |
|---|---|
variant | casino 玩家对荷官(Casino Hold'em)、nlhe 玩家对玩家(无限注) |
bets[] | 玩家对荷官:ANTE 底注、CALL 跟注(弃牌时没有)、AAB AA 边注;玩家对玩家:一笔 POT(这手投入底池的合计,return 为没被跟注退回的部分)。规则见桌台与局结果 |
validStake、rolling | 玩家对荷官:没有退回的注的本金(和局、荷官不合格而退回的跟注不计);玩家对玩家:这手投入的金额。作废为 0 |
rake | 这手归这位玩家的抽水(玩家对玩家桌;玩家对荷官桌为 0) |
onsite | true 表示现场座位:开桌商户摄影棚里的现场客人,由荷官在平板登记、不走钱包(username 为「现场 #座位」),只出现在开桌商户的注单 |
result.code | 这位玩家这手的结果:玩家对荷官 player_wins、dealer_wins、tie、dealer_not_qualified、fold;玩家对玩家 win、split、lose、fold;作废 void |
result.cardInfo | 公牌|这位玩家的两张底牌|荷官的两张,空白分隔的牌面代码(例如 AS KD 7H 7C 2S|AH 7D|QS 3C);荷官的部分只有玩家对荷官桌才有 |
hand | 这一手的结果摘要(handId、no、outcome、cards),和上面的字段相同,方便直接取用 |
- 作废:玩家对荷官桌全额退回;玩家对玩家桌退回这手所有投入(含盲注);
status为void。 - 玩家对玩家桌的买入与兑回是钱包转账,不是注单;每手的输赢以
POT注单记录。 - 别的商户提供给你的德州桌(跨商户),你的玩家的注单照常出现在你的
GET /bets。
牛牛的注单
牛牛(game: "niuniu"、variant: "standard")和百家乐一样,一位玩家在一局的所有下注是一张注单。每局用一副新牌、没有「靴」:shoe 是场次(默认每 60 局换一场),round 是本场次第几局。
翻倍可能输超过本金(默认最多输本金的 3 倍),所以押翻倍时,平台除了本金,还会从玩家余额预扣「本金 × 2」,开牌后把没用到的部分连同派彩一起退回。因此牛牛的注单多了预扣相关的字段:
{
"recSeq": 3072,
"slipId": "01K65N7Q2W4E6R8T0Y1V3J5K7P.7H3KQ2XA",
"rev": 1,
"status": "settled",
"username": "alice",
"currency": "TWD",
"tableId": "N01",
"game": "niuniu",
"variant": "standard",
"roundId": "01K65N7Q2W4E6R8T0Y1V3J5K7P",
"shoe": "260928-01",
"round": 7,
"bets": [
{ "zone": "P1E", "amount": "1000", "return": "1950" },
{ "zone": "P2D", "amount": "500", "return": "500", "hold": "1000", "mult": 2 },
{ "zone": "P3E", "amount": "500", "return": "975" },
{ "zone": "P3D", "amount": "1000", "return": "5850", "hold": "2000", "mult": 3 }
],
"stake": "3000",
"hold": "3000",
"validStake": "5500",
"rolling": "1000",
"payout": "9275",
"winLoss": "3275",
"delta": "9275",
"result": {
"code": "5893A",
"cardInfo": "7H|KS QD 10C 3S 5H|4C 6D JS 9C KH|2D 8S QC AH 2C|7D 3H KD 5C 5D",
"hands": { "B": 8, "P1": 9, "P2": 3, "P3": 10 },
"winners": { "P1": "P", "P2": "B", "P3": "P" }
},
"placedAt": "2026-09-28T06:30:12.300Z",
"settledAt": "2026-09-28T06:30:51.640Z"
}这张注单押了闲一平倍 1,000、闲二翻倍 500(预扣 1,000)、闲三平倍 500、闲三翻倍 1,000(预扣 2,000);开出庄牛8、闲一牛9、闲二牛3、闲三牛牛,所以闲一、闲三赢,闲二输。
| 字段 | 说明 |
|---|---|
bets[] | 投注区 P1E~P3D(见桌台与局结果)。翻倍格多 hold(这一格的预扣)与 mult(实际套用的倍数:闲赢看闲家的牌型、闲输看庄家的牌型;退款为 0)。return 含退回的预扣:闲三翻倍 1,000 + 2,000 + 1,000 × 3 × 0.95 = 5,850;闲二翻倍输给庄牛8(×2)输 1,000,退回 500 + 1,000 − 1,000 = 500 |
stake | 本金合计,不含预扣(3,000) |
hold | 预扣合计(1,000 + 2,000 = 3,000);没有押翻倍时为 "0"。只有牛牛的注单有这个字段 |
payout | 退回合计,含退回的预扣(1,950 + 500 + 975 + 5,850 = 9,275) |
winLoss | payout − stake − hold(9,275 − 3,000 − 3,000 = 3,275)。牛牛不能用 payout − stake 推算输赢,对账请一律用 winLoss |
validStake | 平倍=本金;翻倍=本金 × 实际倍数(1,000 + 500 × 2 + 500 + 1,000 × 3 = 5,500);退款的格子不算 |
rolling | 输掉的金额(只有闲二翻倍输了 500 × 2 = 1,000) |
delta | 首次结算为 payout(9,275);下注时已扣本金+预扣 6,000,所以玩家这局净赢 3,275 |
result.code | 5 字符结果码(格式),5893A=庄牛8,闲一牛9 赢、闲二牛3 输、闲三牛牛 赢 |
result.cardInfo | 头牌|庄|闲一|闲二|闲三,每家 5 张(格式) |
result.hands、result.winners | 各家的牌型代码(0 无牛、1–9 牛几、10 牛牛…)与每一家闲对庄的输赢(P 闲赢、B 庄赢),不必自己解结果码 |
- 下注时玩家钱包扣的是本金+预扣;开牌前
GET /wallet/balance的余额已经扣掉预扣,结算时连同派彩一起退回。 - 作废(
status: void):本金与预扣全额退回(payout为本金+预扣、winLoss为0,翻倍格的mult为0),result没有hands、winners。 - 结果不完整(数据源只提供各家输赢):平倍照常结算;翻倍要有赢家的牌型才能结算,没有就退回本金与预扣(
mult为0)。 - 每日汇总的
payout以「本金+输赢」计入,不含退回的预扣。
每日汇总
GET /api/tenant/v1/bets/summary?date=2026-09-24依你的租户时区计算某一天每位玩家的注单数、本金、有效投注、洗码量、派彩、输赢与抽水(rake,德州玩家对玩家桌),只计每张注单当天的最新版本,作废注单的本金不计入 stake。最多返回 1,000 位玩家。德州扑克的现场座位(注单 onsite: true)不是你的会员,不列入汇总。牛牛的注单在汇总的 payout 以「本金+输赢」计入,不含退回的预扣(注单本身的 payout 含预扣)。适合每天和你自己汇总的数字核对。date 必须是存在的日期(例如 2026-02-30 回 400 INVALID_PARAMETER)。
安全网与建议
- 以
/bets为准:Webhook 只是加速通知,可能延迟或重送;正确性一律以游标同步为准。 - (选用)定期重扫:想多一层保险时,可以每天以
from=<前一天 00:00 UTC>另外扫一次前一天的记录,以(slipId, rev)去重写入;游标同步本身不会漏数据。 - 保留期:API 可查询的注单保留期为付费方案约 400 天、免费展示方案 7 天(以整月为单位清除,当月与上个月一律保留)。请把注单存进你自己的数据库。
错误码
| 错误码 | HTTP | 原因 |
|---|---|---|
INVALID_CURSOR | 400 | cursor 不是上一页返回的格式 |
INVALID_PARAMETER | 400 | from 不是合法的时间、date 不是存在的 YYYY-MM-DD 日期 |
其他共通错误见错误码。