Win
Register a winning or losing bet result
155 calls your wallet (signed with X-Marbles-Signature) to register a win or loss — the settlement of a bet. For winning bets, add the win amount to the player's balance. For losing bets, the amount is 0.
Endpoint
POST /winRequest
POST /win 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",
"amount": 1000000,
"currency": "USD",
"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 win |
referenceTransactionId | string | The original bet transaction ID |
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 |
amount | int64 | Win amount (0 for losses) with 5-digit precision |
currency | string | ISO 4217 currency code |
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. No more bets, wins, or rollbacks will occur for this round.roundClosed: false- More transactions may follow for this round (e.g., multi-bet rounds).
Use roundClosed to finalize round records in your system. When true, you can safely mark the round as complete for reporting and reconciliation purposes. No /rollback will be sent for a bet after its /win callback — /win (including the amount: 0 loss form) is the terminal callback for that bet.
Win vs Loss
- Win:
amount > 0- Add this amount to the player's balance - Loss:
amount = 0- No balance change needed (bet was already deducted)
Freebet Results
When the original bet was a freebet, the request includes:
{
"requestId": "...",
"transactionId": "...",
"referenceTransactionId": "...",
"amount": 1500000,
"currency": "USD",
"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- For wins: Credit the
amountas real money to the player - For losses:
amountis0, no action needed
Freebet winnings are real money. When a freebet wins, credit the full win amount to the player's balance. See Freebets & Rewards for more details.
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 settlement.
The full status set lives in Error codes — that is the canonical home for the enum across all callbacks. For /win the relevant outcomes are:
status | When you return it | What 155 does |
|---|---|---|
SUCCESS | Win/loss settled, balance updated | Settlement recorded |
BONUS_ERROR | Free-bet/reward settlement problem | Settlement rejected |
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 retry never moves money twice. The returned status for a replay differs by callback — this is the most common point of confusion:
| Callback | Replay of the same transactionId | Returned status | Balance effect |
|---|---|---|---|
/bet | Rejected as a duplicate bet | DUPLICATE_TRANSACTION_ERROR | unchanged |
/win | Treated as the original settlement | SUCCESS | unchanged |
/rollback | Treated as the original rollback | SUCCESS | unchanged |
The asymmetry is deliberate. A replayed /bet is surfaced as DUPLICATE_TRANSACTION_ERROR — a duplicate is not a new bet, and flagging it tells 155 the stake was already debited. A replayed /win or /rollback returns plain SUCCESS: the settlement is simply re-confirmed, the money already moved once, and there is nothing to flag. In both cases the balance is unchanged — return success without crediting again; do not credit the win a second time and do not cancel the original credit.
Worked Examples
Success — first /win
The win settles and the player's balance reflects the credit.
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 /win — same transactionId
155 resent the callback. You return the original settlement result: still SUCCESS, balance unchanged (you do not credit the win 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 | New balance after win/loss (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"
}Common Mistakes
- Returning
DUPLICATE_TRANSACTION_ERRORon a/winreplay. That is the/betrule. A replayed/winreturnsSUCCESS(see Idempotency). - Re-crediting on a replay. The money already moved on the first
/win; a replay must not add the win amount again, and must not reverse the original credit. - Returning a non-200 HTTP status (or a bare error body). Always respond
200with the outcome instatus.
See the Response Contract above for what 155 does with each status, and Error codes for the canonical enum.