Skip to main content

POST /transactions/win

Moonshot sends a settlement for an accepted bet. The callback has its own new transactionId and the original betId, player, game, currency and session.

Every callback uses canonical signed headers and responses. sessionId echoes the partner reference from /launch; operatorId is the Moonshot-issued operator UUID. operatorSlug identifies the configured signing relationship. Never substitute your local provider ID for operatorId.

The JSON request body is unwrapped; successful responses use { "data": ... }. Amounts and balances are decimal strings in asset units, not atomic integers.

Request​

{
"operatorId": "8e563380-2a27-41b1-8be5-2cdd7d1ec271",
"operatorSlug": "your-partner-slug",
"sessionId": "partner-session-123",
"transactionId": "b37fb156-c781-4b87-b36b-ea45e6c9a982",
"playerId": "fd63c560-f443-49b5-a721-c40c0e06b7be",
"betId": "f72dc49d-9d88-4193-8a66-8e27b136f0ea",
"isFree": false,
"amount": "0.02",
"currency": "SOL",
"gameSlug": "rusty-ring"
}

amount is the gross payout to credit, including the returned stake where the game rules include it. It is not the net profit. A 0.01 debit followed by a 0.02 win changes a starting balance of 10 to 10.01.

Accept amount: "0" to close an accepted losing or capped round without credit. Freeplay losses can explicitly arrive this way, with payoutCoefficient: "0". Do not require a positive amount or assume every losing round omits the callback. Support the game's agreed settlement rules and reject amounts exceeding the original bet's payout cap. A settlement can include payoutCoefficient as a decimal string. Freeplays also include freeplayGrantId and freeplayEnrollmentId. Resolve eligibility from the original bet. Session expiry must not prevent settlement of an accepted stake.

Response​

{
"data": {
"balance": "10.01",
"operatorTransactionId": "7051365e-093e-4d83-aebe-74e006c9b08a",
"statusCode": 1000
}
}

1000 means accepted. For business rejection, return HTTP 200 with a non-success statusCode, unchanged balance, transaction ID and errorMessage; 5100 denotes insufficient/invalid balance, 5000 denotes server error. An identical duplicate returns the original stored response (including 1000 for an accepted operation), not a new debit/credit or a 3000 rejection. HTTP 200 with 5000 is a business response, not a transport 5xx; it does not trigger the HTTP client's server-error retry. If a temporary error needs an HTTP retry, return a signed HTTP 5xx before committing; if committed, replay the stored result on the next attempt.

For an authenticated protocol/state conflict, return a signed HTTP 409, for example:

{
"error": {
"code": "CONFLICT",
"message": "Original accepted bet does not match the callback",
"retryable": false
}
}

Do not include tokens, secrets or internal diagnostics. Failed transport/server attempts may be retried using the same transaction ID and payload. A timeout does not prove the transaction failed: replay the stored result after commit.