Integration Process
Moonshot is the game provider. Your backend is the operator and owns player wallets. The same signed HTTP contract applies to every partner and every game. Use the API overview for the complete endpoint list, call directions and links to each request/response contract.
A complete game session
Read the normal flow from top to bottom. The backend verifies signed responses before trusting them; the browser never receives the shared HMAC secret.
1. Configure the partner
Use the onboarding handoff to collect exact base URLs, credentials, allowed game origins and enabled game/currency settings. Follow the integration quickstart from callback implementation to sandbox launch and wallet settlement.
Receive a stable operatorSlug, a provider-issued operatorId (UUID), a callback
base URL registration, and a separate shared HMAC secret for each environment.
Enable the agreed games, currencies, and limits. Keep the secret on your backend.
2. Keep identity namespaces separate
| Field | Owner and meaning |
|---|---|
operatorSlug | Agreed partner routing key, bound to the signing secret. |
operatorId | Operator UUID issued by Moonshot, also returned in the signed launch response. It is not your database's provider ID. |
playerId | Your player UUID, sent at launch and echoed in callbacks. |
sessionId | Your session reference, sent at launch and echoed unchanged in bet, win, and cancel callbacks. Nonempty string, at most 256 characters. |
betId | Moonshot's bet UUID, shared by the bet and its settlements. |
transactionId | Moonshot's UUID for one wallet operation; the callback idempotency key. |
Authenticate the agreed operatorSlug with its registered secret and resolve your
local integration from that verified identity. operatorId is informational for
the operator backend; no additional database ID mapping or pinning is required.
Do not use it to choose a wallet or bypass session ownership checks. Internal IDs
remain local to each system. Never use a provider's internal player-session
credential as sessionId.
3. Launch a game
Call POST /launch from your backend, using the
canonical request signature. Verify the response signature
and echoed slug/idempotency key before embedding data.url in an iframe.
A reload creates a fresh launch request and session. A launch timeout is an unknown
outcome: do not invent a successful session or replay gameplay against it.
4. Implement wallet callbacks
Expose these paths beneath your registered callback base URL:
Verify signatures on raw request bytes before handling the callback. Atomically
record the transaction and mutate the wallet, keyed by (authenticated operatorSlug, transactionId).
A repeated identical operation returns its stored response without another debit or
credit. Reject reuse of an ID with changed request content. Win and cancel must refer
to an accepted original bet, with the same player, currency, game, and session.
Settlements can arrive after a session expires; resolve them from the original bet.
Follow the money
This regular-wallet example starts at 10 asset units and stakes 0.01.
The branches below are alternative outcomes for one accepted bet.
A win is the gross credit amount, including any returned stake. A zero payout settles the bet without adding money. A final settlement must not also receive an independent refund.
Handle a repeated callback
Authenticate first. Keep the idempotency decision and money mutation inside the same database transaction and wallet lock, including across backend instances.
Look up transactions by (authenticated operatorSlug, transactionId). "Same request"
means the same endpoint and exact payload. Replay and conflict branches never
mutate the wallet. For a new operation, validate the bet and atomically store either
its wallet/state changes and result, or its business rejection without a wallet
change. A later identical retry returns that stored outcome.
| On an identical wallet callback retry | Keep or regenerate? |
|---|---|
Endpoint, transactionId and exact body bytes | Keep unchanged. |
x-request-id, timestamp and request signature | Regenerate for each HTTP attempt. |
Response data and operatorTransactionId | Replay the original stored result. |
Response signature and echoed x-request-id | Regenerate for the current attempt. |
Launch is different: its current key correlates requests and does not guarantee session replay. Follow the launch retry rules.
5. Test before enabling traffic
Prove launch → bet → win and launch → bet → cancel using different IDs in both systems. Check insufficient funds, wrong operator/player/session, malformed signatures, sequential and concurrent duplicate callbacks, changed-payload retries, and retries after a response is lost. An HTTP conflict must include a signed, actionable error message. Verify that rejected callbacks do not change balances. Use independent test credentials and wallets; repeat the agreed checks for production. The sandbox test matrix lists expected results, recovery checks and go-live evidence. See Troubleshooting for common failures.
Freeplays use the separate freebet contract and must be enabled and tested explicitly. Contact [email protected] for onboarding.