注單同步
已結算的注單以 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 日期 |
其他共通錯誤見錯誤碼。