錯誤碼
失敗的回應一律是:
json
{ "ok": false, "error": { "code": "INSUFFICIENT_BALANCE", "message": "insufficient available balance" } }- 以
code判斷,不要以message判斷:message是給開發者看的說明(多為英文),之後可能調整。 - HTTP 狀態碼有意義:
400參數錯誤、401簽章驗證失敗、403權限(IP、租戶、玩家)、404找不到、409衝突、413本文過大、429限流、5xx伺服器錯誤。 5xx的本文可能不是 JSON(例如在 Cloudflare 層就失敗時),請一律視為暫時錯誤。
重試原則
| 狀況 | 處理 |
|---|---|
429、5xx、逾時、連線錯誤 | 退避後重試(例如 1、2、4、8 秒,加上隨機延遲)。每次重試都產生新的 nonce 與時間戳 |
| 轉入、轉出的狀態不明 | 以相同的 txnId 與內容重試,直到得到 2xx 或 4xx,見錢包:逾時與重試 |
其他 4xx | 不要原樣重試:依錯誤碼修正請求 |
401(nonce already used) | 這個請求沒有被處理;以新的 nonce 重新送出 |
下表由 OpenAPI 規格產生,列出實作可能回傳的全部錯誤碼。
共通錯誤(任何端點都可能回傳)
| 錯誤碼 | HTTP | 意義 | 處理方式 | 可重試 |
|---|---|---|---|---|
UNAUTHORIZED | 401 | 簽章驗證失敗。invalid credentials:金鑰 ID 格式錯誤、金鑰不存在或已停用(輪替中的舊金鑰超過 24 小時也算)、nonce 格式錯誤,或簽章不符。timestamp outside the ±300 s window:X-Timestamp 格式錯誤或與伺服器時間差超過 300 秒。nonce already used:同一個 nonce 在 10 分鐘內重複使用(這次請求沒有被處理)。message:invalid credentials、timestamp outside the ±300 s window、nonce already used | 用〈簽章除錯器〉比對簽章字串;確認路徑從 /api/tenant/v1 開始並含查詢字串、以實際送出的本文位元組計算雜湊;伺服器校時(NTP);每個請求(含重試)都產生新的 nonce 與時間戳。 | 修正後再送 |
IP_NOT_ALLOWED | 403 | 你設定了 IP 白名單,而這個請求的來源 IP 不在名單內。message:source IP is not in the allowlist | 在 Console「上線與串接 → IP 白名單與 Webhook」加入伺服器的對外 IP(IPv4/IPv6 或 CIDR)。 | 修正後再送 |
TENANT_SUSPENDED | 403 | 租戶已停用、停權或已關閉,所有 API 都暫停服務。message:tenant is suspended | 登入 Console 查看帳戶狀態,或聯絡支援。 | 修正後再送 |
RATE_LIMITED | 429 | 超過每秒請求上限(付費方案 100 次/秒、沙箱 20 次/秒、免費方案 5 次/秒,可短暫突發到 2 倍)。message:too many requests | 退避後重試(例如 200 ms、400 ms、800 ms…,加隨機延遲),並換新的 nonce 與時間戳;平時以批次與游標減少呼叫次數。 | 可以(換新的 nonce 與時間戳) |
PAYLOAD_TOO_LARGE | 413 | 請求本文超過 64 KB。message:request body too large | 縮小本文;本 API 的正常請求都遠小於這個上限。 | 修正後再送 |
INVALID_JSON | 400 | 本文不是合法的 JSON,或不是 JSON 物件。message:request body is not valid JSON、request body must be an object | 送出 Content-Type: application/json 與 JSON 物件({…})。 | 修正後再送 |
NOT_FOUND | 404 | unknown endpoint:方法與路徑不存在(例如用 GET 呼叫 POST 端點,或局 ID 不是 26 字元大寫 ULID)。table not found:啟用或停用的桌號不存在。message:unknown endpoint、table not found | 對照〈API 參考〉的方法與路徑;桌號以 GET /tables 為準。 | 修正後再送 |
INTERNAL_ERROR | 500 | 伺服器暫時錯誤。任何 5xx(包含本文不是 JSON 的情況)都視為這一類。message:internal error, please retry | 退避後重試。轉帳請以相同的 txnId 重試,或先以 GET /wallet/transfer 查詢;持續發生請查看狀態頁或聯絡支援。 | 可以(換新的 nonce 與時間戳) |
端點相關錯誤
| 錯誤碼 | HTTP | 意義 | 處理方式 | 可重試 |
|---|---|---|---|---|
INVALID_PARAMETER | 400 | 缺少必要欄位,或欄位格式、值不正確;message 會指出是哪個欄位。message:<field> is required、<field> must be a string、unsupported lang、lobbyUrl must be an http(s) URL、status must be active, locked or no_bet、password must be 6–64 characters、limitProfileId must be a positive integer or null、limitProfileId not found、limitProfileId currency is <CUR>, player currency is <CUR>、txnId must be 1–64 characters of A-Z a-z 0-9 _ . : -、txnId is required、from must be an ISO time、date must be a valid YYYY-MM-DD、from and to must be YYYY-MM-DD | 依〈API 參考〉修正欄位後重送。 | 修正後再送 |
INVALID_USERNAME | 400 | 玩家帳號不符合規則(1–32 個字元,英數字與 _ . @ -),或查詢時沒有帶 username。message:username must be 1–32 characters of A-Z a-z 0-9 _ . @ -、invalid username | 在你的系統把玩家帳號對應成符合規則的字串(例如以你的會員 ID 產生)。 | 修正後再送 |
INVALID_CURRENCY | 400 | 建立新玩家時指定的幣別代碼不合法(需要 3–5 個英文字母)。message:invalid currency | 使用正確的幣別代碼,或不帶 currency 以使用租戶預設幣別。 | 修正後再送 |
CURRENCY_NOT_ENABLED | 400 | 建立新玩家時指定的幣別,租戶還沒開啟(多幣別:Console「限紅方案 → 幣別」)。已存在的玩家不受影響。message:currency <CUR> is not enabled for this operator (enabled: <CUR>, <CUR>) | 在 Console 開啟這個幣別並設定該幣別的限紅方案後再建立玩家,或不帶 currency 以使用主要幣別。 | 修正後再送 |
INVALID_AMOUNT | 400 | 金額不是大於 0、最多 4 位小數的十進位字串。message:amount must be a positive decimal string with at most 4 decimals、invalid amount | 以字串傳送金額(例如 "100.5"),不要用浮點數或科學記號。 | 修正後再送 |
INVALID_CURSOR | 400 | cursor 格式錯誤。message:cursor must come from a previous response | 原樣帶回上一頁的 nextCursor;遺失時改用 from 從某個時間重新同步,並以 (slipId, rev) 去重。 | 修正後再送 |
CURRENCY_MISMATCH | 400 | 轉帳的 currency 與玩家的幣別不同。玩家的幣別在建立時決定,之後不能變更。message:player currency is <CUR> | 以玩家的幣別轉帳(GET /player 可查);不同幣別請使用不同的玩家帳號。 | 修正後再送 |
PLAYER_NOT_FOUND | 404 | 這個帳號的玩家不存在。message:player not found | 玩家會在第一次 launch 或第一次轉入時自動建立;請先完成其中一個步驟。 | 修正後再送 |
PLAYER_LOCKED | 403 | 玩家已被鎖定,不能啟動遊戲。message:player is locked | 需要時以 POST /player/update 把 status 改回 active。 | 修正後再送 |
PLAYER_LIMIT | 403 | 玩家帳號數已達方案上限(免費展示方案預設 50、沙箱 500)。message:demo plan allows at most <N> players | 沿用既有的測試玩家,或升級付費方案。 | 修正後再送 |
TXN_CONFLICT | 409 | 這個 txnId 已經用在另一筆金額或方向不同的轉帳,或最近兩個月內已用在另一位玩家。message:txnId was already used with different content、txnId was already used for another player | 這是你的系統的單號錯誤:每筆新的轉帳都要用新的 txnId(整個租戶內唯一);重試時則必須和第一次內容完全相同。 | 修正後再送 |
INSUFFICIENT_BALANCE | 409 | 轉出金額大於可用餘額(未結算注單的本金不可轉出)。message:insufficient available balance | 以 GET /wallet/balance 取得可用餘額後再轉出。 | 修正後再送 |
TXN_NOT_FOUND | 404 | 查不到這個 txnId 的轉帳:查詢時有帶 username 表示這筆轉帳沒有執行(或仍在處理中);沒帶時只查租戶流水(當月與前 3 個月)。message:transfer not found | 以相同的 txnId 與內容重送轉帳,直到得到明確的成功或 4xx 結果。不要當成失敗而改用新的單號。 | 修正後再送 |
ROUND_NOT_FOUND | 404 | 這一局不存在,或尚未結算。message:round not found | 局在結算後才查得到;注單上的 roundId 一定查得到。 | 修正後再送 |
QUOTA_EXCEEDED | 409 | 已啟用的桌數達到免費方案配額(預設 2 桌)。message:超過方案配額(<N> 桌) | 先停用其他桌,或在 Console「方案與帳單 → 方案」升級付費方案。 | 修正後再送 |
ACCOUNT_LOCKED | 409 | 帳戶已停權或關閉,不能啟用桌檯。message:account is suspended | 聯絡支援。 | 修正後再送 |