Skip to content

rollback — Debit Cancellation ​

Cancels a previously sent debit and returns its amount to the player. The platform retries rollbacks until it receives OK. Because the original debit may never have reached the operator, you must handle that case as well.

http
POST {wallet_base_url}/rollback

When It Is Called ​

reasonWhenDoes the operator have the original debit?
cancel_betThe player cancels a bet before betting closesYes (a debit that received OK)
round_voidThe round is voided (game progression error, platform server recovery, etc.). One per unsettled debit in that roundUsually yes. May be missing if the debit's outcome was uncertain
timeoutThe debit outcome is uncertain (3-second timeout, non-HTTP-200, connection failure, UNKNOWN_ERROR). Sent immediately after the debit failsUnknown — it may never have arrived, may have been processed late, or may still be in progress
systemCleanup of debits whose result has been unknown for more than 30 seconds because a platform server stopped mid-debit, and cleanup of buy-ins interrupted mid-seating during server recoveryUnknown
  • A rollback cancels only debits. It never cancels credits.
  • The tx_id of the rollback for a given debit is fixed and unique. The same debit is never cancelled twice under different reasons.
  • New reason values may be added. If you receive an unknown value, do not reject it.

Request ​

Headers are the same as the common headers.

FieldTypeRequiredDescription
tx_idstring●ID of the rollback transaction itself. Idempotency key
ref_tx_idstring●The tx_id of the debit to cancel
external_idstring●Operator-side player ID
player_idstring●Platform player ID (pl_…), for reference
currencystring●Currency code
amountinteger●Amount of the original debit (1 or more). There are no partial rollbacks
reasonstring●A value from the table above
game_codestring●Game code. May be an empty string on platform recovery paths
table_idstring●Table ID (tbl_…)
round_idstring●Round ID (rnd_…) or table session ID (tss_…) of the original debit
operator_session_idstring | null●The value sent at game launch. May be null on platform recovery paths (system, round_void)
created_atstring●Time the platform created the rollback transaction (UTC, milliseconds). Does not change on retries
json
{
  "amount": 5000,
  "created_at": "2026-10-19T02:10:03.131Z",
  "currency": "PHP",
  "external_id": "u-102938",
  "game_code": "live_baccarat",
  "operator_session_id": "s-88af21",
  "player_id": "pl_0199e8b4f2a37c1d8e5b6a4f3c2d1e0b",
  "reason": "timeout",
  "ref_tx_id": "tx_0199f2a1c3d47e8b9a6f1e2d3c4b5a69",
  "round_id": "rnd_0199f2a0b1c27d3e8f4a5b6c7d8e9f01",
  "table_id": "tbl_0199a1b2c3d47e5f8a9b0c1d2e3f4a5b",
  "tx_id": "tx_3b7e1c9a5d2f4e8b6a0c2d4f6e8a0b1c"
}
json
{
  "amount": 5000,
  "created_at": "2026-10-19T02:10:09.870Z",
  "currency": "PHP",
  "external_id": "u-102938",
  "game_code": "live_baccarat",
  "operator_session_id": "s-88af21",
  "player_id": "pl_0199e8b4f2a37c1d8e5b6a4f3c2d1e0b",
  "reason": "cancel_bet",
  "ref_tx_id": "tx_0199f2a1c3d47e8b9a6f1e2d3c4b5a70",
  "round_id": "rnd_0199f2a0b1c27d3e8f4a5b6c7d8e9f01",
  "table_id": "tbl_0199a1b2c3d47e5f8a9b0c1d2e3f4a5b",
  "tx_id": "tx_9d1f3a5c7e9b0d2f4a6c8e0b2d4f6a8c"
}

Response ​

FieldTypeRequiredDescription
statusstring●Must be OK for the transaction to finish
balanceinteger●Balance after processing
operator_tx_idstringOperator-side transaction ID
json
{ "status": "OK", "balance": 1250000, "operator_tx_id": "w-99814" }

Handling by Case ​

Handling depends on the state of the debit referenced by ref_tx_id. Return OK in every case.

Original debit state (operator record)HandlingResponse
Succeeded (deducted)Refund the original debit amount and mark the debit as "rolled back"OK + balance after the refund
No record (never arrived, or not yet processed)Do not refund; record ref_tx_id in the rollback markersOK + current balance
A debit that was rejected (INSUFFICIENT_FUNDS, etc.)Do not refund; record it in the rollback markersOK + current balance
Already rolled backDo nothingOK + current balance
Repeated request with the same rollback tx_idDo not process againThe original response as is
  • For the refund amount, use the original debit amount recorded by the operator. The request's amount is the same value, but if it differs from the original record, the original record takes precedence.
  • Refund even if the player is blocked, logged out, or has an expired session.

When the original debit does not exist yet ​

timeout and system rollbacks may be processed before the original debit. For example, while the operator takes more than 3 seconds to process a debit, the platform has already treated it as a failure and sent a rollback.

Platform                                 Operator
  debit tx_10 (5,000) ─────────────────▶  processing delayed …
  ── 3 seconds elapsed, bet rejected ──
  rollback tx_11 (ref=tx_10) ─────────▶  no record of tx_10 → OK without refund, mark tx_10 as rolled back
                                          (delayed debit tx_10 continues processing)
                                          tx_10 is in rollback markers → TX_ALREADY_ROLLED_BACK, no deduction

Conversely, if the debit commits first and the rollback arrives afterwards, it becomes the "succeeded → refund" case. Either way, the final balance must be the same as if the debit had never happened.

To guarantee this:

  1. Process debits and rollbacks inside the same player-row lock.
  2. A debit checks the rollback markers after acquiring the lock. If it checks before the lock, and a rollback commits in between, the debit misses the rollback marker and deducts the amount anyway.
  3. Do not delete rollback markers (keep them for at least a few days). Late debits usually arrive within a few seconds, but they can be delayed further by operator-side outages.

Rollbacks cannot be rejected

If you return anything other than OK for a rollback (including TX_ALREADY_ROLLED_BACK and PLAYER_NOT_FOUND), the transaction does not finish and is retried at 1 s → 2 s → 5 s → 15 s → 1 min → 5 min, then every 5 minutes indefinitely. Return OK even if you cannot find the original debit or have already rolled it back.

Processing Order ​

  1. Verify the signature → on failure, INVALID_SIGNATURE (it will be retried, so fix the cause right away)
  2. Validate fields (tx_id, ref_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 rollback tx_id exists → return the stored response as is
  4. Lock the player row
  5. Look up (and lock) the debit for ref_tx_id → see Handling by Case above
  6. Record the rollback marker, record the rollback tx_id with its response, and return OK

Docs v1.0.0 · Operator API v1