Wallet Callback (Seamless)
In Seamless Mode the player balance lives in your system. Mangoplay calls the Call back endpoint you supplied on the Request Form every time a bet is placed or settled.
This page is the contract for that endpoint. Getting the idempotency rules right is what keeps money correct on both sides.
The same contract is published as an OpenAPI specification with a schema browser and copy-ready examples for every action: Wallet Callback API reference.
Request
Mangoplay sends POST with a JSON body. Every request carries these headers:
The action field tells you what happened:
Fields
Every action carries the same envelope:
info dealId differs between bet and settle
The bet carries ..._B and its settlement carries ..._S — the same bill, two distinct
de-duplication keys. Store both.
Money fields
winLose is what you credit. winLoseWithOutTurnOver is the player's net result, for
your reporting. Both are decided by gameResult:
The last row is not a zero-value transaction. It appears on BET_RETURN, and on a
CANCEL re-send. Both ask you to reverse a transaction you already applied,
identified by dealId. The amount to reverse is the one from that original transaction,
not from this payload.
A first-attempt CANCEL_SETTLE is different: it repeats the original settlement rather
than zeroing it — see
Examples
Player bets 100 on Hilo:
{
"action": "BET",
"type": "BET",
"id": 1786615539367226,
"username": "0tonebx4",
"dealId": "HL-B20260813100522-1786615539334-QGF2BP31_B",
"betId": "HL-B20260813100522-HL-B",
"roundId": "HL-B20260813100522",
"game": "Hilo",
"providerName": "Hilo",
"gameType": "CASINO",
"betDetail": "HOLE_3_5",
"validBet": 100,
"turnOver": 100,
"winLose": -100,
"winLoseWithOutTurnOver": -100,
"gameResult": "Wait",
"betTime": 1786615539334,
"reportDate": "13-08-2026",
"ip": "127.0.0.1",
"remark": "Waiting for settlement"
}
The bet wins and pays even money — profit 100 on a stake of 100. Note the _S deal id:
{
"action": "SETTLE",
"type": "SETTLE",
"id": 1786615800702941,
"username": "0tonebx4",
"dealId": "HL-B20260813100522-1786615539334-QGF2BP31_S",
"betId": "HL-B20260813100522-HL-B",
"roundId": "HL-B20260813100522",
"game": "Hilo",
"providerName": "Hilo",
"gameType": "CASINO",
"betDetail": "HOLE_3_5",
"validBet": 100,
"turnOver": 100,
"winLose": 200,
"winLoseWithOutTurnOver": 100,
"gameResult": "WIN",
"betTime": 1786615539334,
"settleTime": 1786615800000,
"reportDate": "13-08-2026",
"ip": "127.0.0.1"
}
Reversals
Three actions target a bill you already processed. In every case the amount to reverse is the one you recorded originally — never compute it from the reversal payload.
BET_RETURN — the stake goes back to the player. Carries the bet's _B deal id,
gameResult: DRAW_RETURN, and 0 in both money fields.
CANCEL_SETTLE — a settlement is being undone, usually because a round result was
corrected. This one repeats the original settlement: the _S deal id, the original
gameResult (WIN, LOSE, …), and the original winLose / winLoseWithOutTurnOver.
The id field is not generated by us here — we echo back the transaction id you
returned when you accepted that settle, so you can locate the exact transaction.
CANCEL — the same cancellation being re-sent after a failed attempt. Carries
gameResult: CANCEL_SETTLE and 0 in both money fields, and id is a value we generate
rather than your transaction id. Match this one on dealId.
If a corrected result produces a new payout, a fresh SETTLE follows with a new id.
Response
Return code 0 (also accepted: 200, 201) for success. Always include the balance:
{ "code": 0, "balanceBefore": 1000, "balanceAfter": 900 }
warning Balance is required on every successful response
This includes responses where you reject the call as a duplicate. Without
balanceBefore / balanceAfter we cannot show the player their balance.
On failure, return a non-success code and an errorType:
{ "code": 4000, "errorType": "INSUFFICIENT_BALANCE", "message": "Insufficient balance" }
A timeout, a connection error, or a 5xx is always retried — we cannot tell from those
whether you applied the transaction.
Idempotency — the important part
De-duplicate by dealId.
dealId is unique per bet. Every retry of the same logical transaction reuses the same
dealId and the same id, so either field is a safe de-duplication key.
danger Do not de-duplicate by betId
betId identifies the round, not the bet. When a player places several bets in one
round, every one of them carries the same betId. De-duplicating on it would silently
reject all bets after the first.
When you receive a dealId you have already applied, return
errorType: "DUPLICATE_TRANSACTION" together with the balance from the original
transaction. Do not apply it a second time.
Retries and timeouts
If your system is consistently slower than these defaults we can raise the timeout for your agent — tell us your realistic p99 response time for bet and for settle separately.
info Why the timeout matters
If we time out on a call you actually processed, our records and yours disagree: you debited the player, we recorded the bet as failed. Raising the settle timeout to match your real response time is the single most effective way to prevent bills stuck on "awaiting payment".
Per-agent options
These are configured by Mangoplay on request, once the behaviour is confirmed with your team. Every one of them defaults to off, so nothing changes unless you ask.
When something goes wrong
Do not raise a ticket for a single stuck bill. Use the Reconciliation APIs instead:
-
POST /api/v1/open/seamLess/betInfo— shows the bet status, the settle status, and the last request/response we exchanged with you for that deal. -
POST /api/v1/open/seamLess/reSettle— flips a bet we marked failed to success and settles it. Idempotent, and safe to call again. Call it only after the round closed.
Both use your AgentPrefixId and Security headers and only reach your own deals.