Rollback
Reverse a previously registered bet
155 calls your wallet (signed with X-Marbles-Signature) to reverse a previously registered /bet — for example when a round is cancelled or errors out before settlement. You must refund the stake to the player's balance.
When This Fires
/rollback only fires before /win has been sent for a given bet. Once /win is delivered (regardless of amount, including the amount: 0 loss form), the round is terminal — no /rollback will follow.
Triggers for /rollback:
- The round was cancelled before settlement
- The player's bet timed out during chip placement
/betwas received and acknowledged, but a downstream error required us to reverse the debit before the round settled
Not for Reversing Settlements
To reverse a granted-but-unused freebet, use POST /game/free-bets/rewards/cancel — not /rollback. See Freebets & Rewards.
Endpoint
POST /rollbackRequest
POST /rollback HTTP/1.1
Host: your.game.api
X-Marbles-Signature: <signature>
Content-Type: application/json
{
"requestId": "8df0475e-5069-483a-8205-f6089997abc9",
"transactionId": "9ea48131-3a0f-4067-94d0-3212e7e25abb",
"referenceTransactionId": "ea0240f5-483d-434b-a8d4-04dabf61cde3",
"clientSessionId": "0k3cz83bb3h2vn53ocnc7pxw9",
"clientPlayerId": "02mnrpyv2qd9jbwhoniyimxsy",
"roundId": "17cc81fd-df13-4ca4-857d-de0f766dc372",
"gameId": "f1c0b104-f29d-44a9-ae93-e8afcbe3feb9",
"roundClosed": true,
"timestamp": "2025-06-15T14:30:00.000Z"
}Request Fields
| Field | Type | Description |
|---|---|---|
requestId | string | Unique request identifier (UUID) |
transactionId | string | Unique transaction identifier for this rollback |
referenceTransactionId | string | The original bet transaction ID being rolled back |
clientSessionId | string | The player's session identifier |
clientPlayerId | string | The player's unique identifier |
roundId | string | The game round identifier |
gameId | string | The game identifier |
isFree | boolean | true if the original bet was a freebet |
rewardUuid | string | The clientRewardId from the original freebet grant (only present when isFree is true) |
roundClosed | boolean | Whether this transaction closes the round (see below) |
timestamp | string | ISO 8601 UTC timestamp of when the request was created |
Round Lifecycle
The roundClosed field indicates whether this is the final transaction for a round:
roundClosed: true- This is the final transaction. The round is cancelled and no more transactions will occur.roundClosed: false- More transactions may follow (rare for rollbacks, but possible in multi-bet scenarios).
Use roundClosed to finalize round records in your system. When true, you can safely mark the round as cancelled/voided for reporting purposes.
The Rollback-to-Zero Rule
Restore the stake — nothing more, nothing less
A /rollback refunds the stake so the balance returns to exactly what it was before the bet — restore the stake, never re-debit, never double-refund.
The net effect of /bet followed by /rollback must be zero: the player ends with the same balance they had before the bet was placed. Refund the original stake (the amount from the referenced /bet) and stop there. Do not deduct anything, and do not refund a stake that was already refunded — see Idempotency below.
Freebet Rollbacks
When the original bet was a freebet, the request includes isFree: true:
{
"requestId": "...",
"transactionId": "...",
"referenceTransactionId": "...",
"isFree": true,
"rewardUuid": "promo-winter-2025-001",
"roundClosed": true
}isFreeistrueto indicate the original bet was a freebetrewardUuidcontains yourclientRewardIdfor tracking which promotion this freebet belongs to- Pass
isFreeandrewardUuidthrough unchanged so the rollback maps to the correct grant - No balance refund needed (the original freebet had
amount: 0) — mark the freebet as cancelled in your records
Rolling back an already-settled freebet is treated as a duplicate and silently deduped — return SUCCESS, balance unchanged. See Freebets & Rewards for the full reward flow.
Response Contract
Always respond HTTP 200; put the outcome in status. We read the status field, not the HTTP code, to decide what happens to the rollback.
The full status set lives in Error codes — that is the canonical home for the enum across all callbacks. For /rollback the relevant outcomes are:
status | When you return it | What 155 does |
|---|---|---|
SUCCESS | Stake refunded (or already rolled back) | Rollback recorded |
UNKNOWN_ERROR | Unexpected operator-side failure | 155 retries |
Never return a non-200 HTTP status or a bare error body — always respond 200 with one of the status values above. A non-200 is read as a transport failure and may trigger retries before the body is parsed.
Idempotency
Networks retry, so 155 may resend a callback it isn't certain landed. Dedupe by transactionId so a replay never refunds the stake twice. A replayed /rollback is treated as the original rollback: return plain SUCCESS with the balance unchanged — the stake was already restored once, and there is nothing more to refund.
This matches /win, which uses the same success-dedupe rule, and is asymmetric with /bet: a replayed /bet returns DUPLICATE_TRANSACTION_ERROR, whereas a replayed /rollback (like /win) returns SUCCESS.
Worked Examples
Success — first /rollback
The stake is refunded and the player's balance returns to exactly what it was before the bet.
HTTP/1.1 200 OK
X-Marbles-Signature: <signature>
Content-Type: application/json
{
"status": "SUCCESS",
"requestId": "8df0475e-5069-483a-8205-f6089997abc9",
"clientPlayerId": "02mnrpyv2qd9jbwhoniyimxsy",
"currency": "USD",
"balance": 1000000
}Replayed /rollback — same transactionId
155 resent the callback. You return the original rollback result: still SUCCESS, balance unchanged (the stake was already refunded once — do not refund again).
HTTP/1.1 200 OK
X-Marbles-Signature: <signature>
Content-Type: application/json
{
"status": "SUCCESS",
"requestId": "8df0475e-5069-483a-8205-f6089997abc9",
"clientPlayerId": "02mnrpyv2qd9jbwhoniyimxsy",
"currency": "USD",
"balance": 1000000
}Response Fields
| Field | Type | Description |
|---|---|---|
status | string | "SUCCESS" |
requestId | string | Echo back the request ID |
clientPlayerId | string | Echo back the player ID |
currency | string | ISO 4217 currency code |
balance | int64 | Balance after rollback — equals the pre-bet balance (5-digit precision) |
Error Response
HTTP/1.1 200 OK
X-Marbles-Signature: <signature>
Content-Type: application/json
{
"status": "UNKNOWN_ERROR",
"requestId": "8df0475e-5069-483a-8205-f6089997abc9",
"clientPlayerId": "02mnrpyv2qd9jbwhoniyimxsy"
}See the Response Contract above for what 155 does with each status, and Error codes for the canonical enum.