Skip to content

Wallet callback API reference

This is the reverse direction from the Operator API: there, you call the platform. Here, the platform calls you. Field-level semantics for the types below live in Data model & enums; this page covers the two endpoints themselves. See Implementing the wallet callback for the narrative walkthrough.

The Moose Gaming Platform never holds player funds — it's a seamless-wallet aggregator, and your wallet is the single source of truth for player balance. Every BET, WIN, and ROLLBACK is settled against your wallet in real time via two endpoints you implement:

  • POST /v1/wallet/transaction — submit a transaction
  • GET /v1/wallet/balance — query a player's current balance

Both are registered by you through your tenant's portal — see Registering your wallet callback URL.

POST /v1/wallet/transaction

Request body: TransactionRequest.

Response body:

ts
type TransactionResponse = {
  status: 'OK' | 'DECLINED' // DECLINED is only valid for BET — see
                              // Data model & enums
  balance: number             // balance after applying this transaction, minor units
}

Any non-200 response is treated as a failure. The platform may retry with the exact same transactionId — see Idempotency below.

GET /v1/wallet/balance

Query parameter: playerRef (required).

ts
// GET /v1/wallet/balance?playerRef=<ref>
// Response
{ "balance": number } // minor units

This endpoint has two callers, so implement it and keep it reliable:

  • Provider balance queries. A game studio can call POST /v1/wallet/balance on the platform to read a player's current balance on demand, without submitting a transaction. The platform forwards that request to you here, live, and returns your response verbatim. A failure or timeout on your end surfaces as an error to the provider — this is a required, provider-facing endpoint, not purely a background check.
  • Stale-round reconciliation. The platform also calls this as a best-effort sanity check while reconciling rounds that went stale (e.g. the game client disconnected mid-round). A failure, timeout, or unsupported response in that path is tolerated and never blocks the platform's own rollback — but a provider-initiated balance query has no such fallback, so don't rely on this endpoint being "optional."

Idempotency (required)

Cache the response for every transactionId you've processed, keyed per player, and replay it verbatim on a repeat — don't re-apply the balance change. The platform relies on this: after a timeout or network error it may resend the identical request, and expects the same answer back rather than a second debit/credit.

Rollback semantics

A ROLLBACK references the BET it reverses via originalTransactionId — look up that bet's amount and refund it.

The platform also has a fallback reconciler that force-closes rounds with no recent activity (client disconnected before a final roundComplete). It sends a synthetic rollback for each outstanding bet:

  • transactionId: stale-rollback: + the original bet's transactionId
  • sessionToken: the sentinel system:stale-round-reconciler

Handle it exactly like any other rollback — the same idempotency rule applies, and the deterministic transactionId means a repeated sweep just replays your cached response instead of double-refunding.

Timeouts

The platform calls you with a bounded timeout (configured per operator, 5000ms by default when your callback URL is first registered — see Environments & base URLs). No response within that window is treated as TIMED_OUT — the platform may retry (same transactionId) or resolve it later via reconciliation. Respond promptly; as long as you follow the idempotency rule above, a retry after a timeout is always safe to answer identically.

Verifying the platform's signature

The platform signs every outbound call using the same HMAC construction you use to sign your own calls to the platform, with one difference: both endpoints here sign over the full request URI — path and query string — not just the path. That's what covers GET /v1/wallet/balance's playerRef query parameter, so it can't be swapped in flight without invalidating the signature. See Signing & authentication for the full construction and the verifyPlatformSignature reference implementation.

Getting your shared secret

The same secret signs both directions — see Getting your shared secret in the signing reference.