Skip to content

debit — Withdrawal ​

Deducts an amount from the player's balance when the player bets or takes a seat. The platform does not retry debits. If the outcome is uncertain, it treats the debit as a failure and immediately sends a rollback.

http
POST {wallet_base_url}/debit

When It Is Called ​

reasonWhenround_idGames
betBetrnd_…Baccarat, Blackjack, Speed Hold'em
anteAnternd_…Speed Hold'em
doubleDouble downrnd_…Blackjack
splitSplitrnd_…Blackjack
buy_inTaking a seat at a table (buy-in)tss_…Buy-in-flow games (Texas Hold'em, Pot-Limit Omaha, Live Hold'em, Matgo, Go-Stop, Seotda, Tong-its, Red Dog)
top_upAdding chips while seatedtss_…Buy-in-flow games
  • In bet-flow games, a single round may receive multiple debits. Debits in the same round use the same round_id.
  • Buy-in-flow games do not debit per hand. Debits arrive only when taking a seat or adding chips.
  • New reason values may be added. If you receive an unknown value, do not reject it; process it as a regular withdrawal.

Request ​

Headers are the same as the common headers.

FieldTypeRequiredDescription
tx_idstring●Platform transaction ID (tx_ + 32 hex digits). Idempotency key
external_idstring●Operator-side player ID
player_idstring●Platform player ID (pl_…), for reference
currencystring●Currency code
amountinteger●Amount to deduct, integer in the minor unit, 1 or more
reasonstring●A value from the table above
game_codestring●Game code
table_idstring●Table ID (tbl_…)
round_idstring●Round ID (rnd_…) or table session ID (tss_…)
operator_session_idstring | null●The value sent at game launch. null if none was sent
created_atstring●Time the platform created the transaction (UTC, milliseconds)
json
{
  "amount": 5000,
  "created_at": "2026-10-19T02:10:00.123Z",
  "currency": "PHP",
  "external_id": "u-102938",
  "game_code": "live_baccarat",
  "operator_session_id": "s-88af21",
  "player_id": "pl_0199e8b4f2a37c1d8e5b6a4f3c2d1e0b",
  "reason": "bet",
  "round_id": "rnd_0199f2a0b1c27d3e8f4a5b6c7d8e9f01",
  "table_id": "tbl_0199a1b2c3d47e5f8a9b0c1d2e3f4a5b",
  "tx_id": "tx_0199f2a1c3d47e8b9a6f1e2d3c4b5a69"
}
json
{
  "amount": 100000,
  "created_at": "2026-10-19T02:12:41.507Z",
  "currency": "PHP",
  "external_id": "u-102938",
  "game_code": "holdem_nlh",
  "operator_session_id": "s-88af21",
  "player_id": "pl_0199e8b4f2a37c1d8e5b6a4f3c2d1e0b",
  "reason": "buy_in",
  "round_id": "tss_0199f29e7c6b4a5d8e3f2a1b0c9d8e7f",
  "table_id": "tbl_0199a1b5d0e47f2a9b8c7d6e5f4a3b2c",
  "tx_id": "tx_5a3c9e1f0b7d4e2a8c6f1b3d5e7a9c0e"
}

The actual body is single-line JSON with no whitespace. The examples above are split across lines for readability.

Response ​

FieldTypeRequiredDescription
statusstring●Result code
balanceinteger● when OKBalance after the deduction
operator_tx_idstringOperator-side transaction ID
json
{ "status": "OK", "balance": 1245000, "operator_tx_id": "w-99812" }
json
{ "status": "INSUFFICIENT_FUNDS", "balance": 3000 }
json
{ "status": "PLAYER_BLOCKED" }
json
{ "status": "TX_ALREADY_ROLLED_BACK" }
json
{ "status": "UNKNOWN_ERROR" }

Platform Behavior by status ​

statusWhen the operator uses itPlatform handling
OKWhen the amount was deducted (for a repeated request with the same tx_id, the original result)Bet or seat confirmed; the response balance is shown on screen
INSUFFICIENT_FUNDSWhen the balance is less than amountDefinitive rejection. The player is told the balance is insufficient
LIMIT_EXCEEDEDWhen the operator's responsible gambling limit (bet limit, loss limit, etc.) is exceededDefinitive rejection. The player is told a limit was exceeded
PLAYER_BLOCKEDWhen the player is blocked or self-excludedDefinitive rejection
PLAYER_NOT_FOUNDWhen the player does not existDefinitive rejection
CURRENCY_MISMATCHWhen the request currency differs from the player's currencyDefinitive rejection
TX_ALREADY_ROLLED_BACKWhen a rollback for this tx_id was received firstDefinitive rejection
INVALID_REQUESTMissing fields or malformed values, or the same tx_id with different contentsDefinitive rejection
INVALID_SIGNATURESignature verification failedDefinitive rejection
UNKNOWN_ERRORAn error where it is uncertain whether the deduction happenedTreated as failure + immediate rollback (timeout)
(3-second timeout, non-HTTP-200, connection failure, invalid JSON, empty status)—Treated as failure + immediate rollback (timeout)
  • On a definitive rejection, the platform does not send a rollback. Use a rejection status only when you are certain the balance was not touched.
  • Status values not in the table above are treated as definitive rejections. If it is uncertain whether the debit was processed, always respond with UNKNOWN_ERROR or HTTP 5xx.
  • A rejected bet or seat is shown as an error on the player's screen. Insufficient funds and limit exceeded are shown with that exact reason; other reasons may, depending on the game, be grouped under a wallet error (WALLET_UNAVAILABLE).
  • You may include or omit balance in a rejection response. The platform does not use the balance from rejection responses.

Processing Order ​

This is the recommended order. Perform the balance deduction and the transaction record within a single DB transaction.

  1. Verify the signature → on failure, INVALID_SIGNATURE
  2. Validate fields (tx_id and external_id present, amount is an integer of 1 or more) → on failure, INVALID_REQUEST
  3. If a record for the same tx_id exists → return the stored response as is (both successes and rejections)
  4. Lock the player row → if missing, PLAYER_NOT_FOUND
  5. If this tx_id is in the rollback markers (a record that the rollback arrived first) → TX_ALREADY_ROLLED_BACK
  6. Check the currency → CURRENCY_MISMATCH
  7. Blocked or self-excluded → PLAYER_BLOCKED; responsible gambling limit → LIMIT_EXCEEDED
  8. Check the balance → INSUFFICIENT_FUNDS
  9. Deduct and return OK + the post-deduction balance + operator_tx_id

Record rejection results by tx_id as well, and return the same rejection if the same tx_id arrives again.

Notes ​

Respond within 3 seconds ​

If the platform does not receive a debit response within 3 seconds, it rejects the bet or seat and immediately sends a rollback for the same amount (reason: "timeout", ref_tx_id = this debit). If the debit was eventually processed on the operator side, it must be reversed by that rollback; if the debit is still being processed, it may overlap with the rollback. Process both requests inside a per-player lock, and perform the rollback marker check (step 5) after acquiring the lock. For details on each case, see rollback.

The same debit is not sent twice, but be prepared anyway ​

The platform never resends a debit once sent. Even so, proxies or load balancers in front of the operator sometimes resend requests, so be sure to implement the idempotent handling in step 3.

Leaving right after sitting down ​

In buy-in-flow games, if the player leaves the seat before the debit result arrives, the platform returns the successful buy-in amount as a separate credit (reason: "cash_out", a different tx_id). This is not a cancellation (rollback) of the debit, so simply apply it as is.

Docs v1.0.0 · Operator API v1