FAQ

Upside handles the player shell, authentication context, WIN balance display, game discovery, bet spending, payout crediting, match history, and standard win/loss modals. Your game handles the iframe UI, backend game logic, storage, and settlement calls.

The integration surface in this repo is the iframe postMessage bridge and the signed /upside/game-actions backend API. The iframe can use plain browser APIs; the backend can use your own small HMAC helper.

Only in your backend or worker secret store. Never expose UPSIDE_API_KEY, UPSIDE_SECRET_KEY, or UPSIDE_PASSPHRASE to the iframe frontend.

HMAC authenticates the game worker. B3-JWT authenticates the player. The JWT is included in the signature payload so a signed request cannot be reused for a different player token.

WIN amounts are strings in atomic units with 18 decimals. For example, 1000000000000000000 is 1 WIN.

No. The iframe does not have your HMAC secret and should never receive one. The iframe calls your backend, and your backend calls Upside.

Call placeBet after validating the player request and before revealing or resolving the final outcome. This ensures the player's bet is locked before the game result is known.

Call processPayout after backend game logic has produced a final result. Send payoutAmount: "0" for losses. Call it once per placed bet.

Upside rejects duplicate payout processing for the same session. Treat duplicate responses as a reconciliation case and fetch history rather than attempting a second payout.

A player can play different game types, but you should avoid multiple simultaneous sessions for the same player and gameType. Disable duplicate clicks and keep server-side session state.

The service calculates max bet from the current game pool balance. Call getMaxBet before showing high-value options and still handle max-bet errors server-side.

Base64 encode your local game URL and open https://upside.win/test/games/{BASE64_URL}. For example, http://localhost:3000 becomes aHR0cDovL2xvY2FsaG9zdDozMDAw.

Trust https://upside.win and, if needed, https://www.upside.win. If you are assigned a staging origin, add only that explicit origin for staging builds.

Common causes are clock drift, a body string mismatch, using /upside/game-actions/ instead of /upside/game-actions, not including B3-JWT in the prehash, or signing a different JWT from the one sent in the header.

No. The browser can animate the result, but final outcome generation and payout calculation should run on your backend. Store enough metadata to audit the outcome.

After backend settlement succeeds, the iframe posts showWinModal or showLossModal to the Upside parent shell. Then it should post refetchBalance and refreshMatchHistory.

You can pass an optional htmlContent string for win/loss/custom modals. Keep it trusted and sanitized; do not pass raw user-generated HTML.

Log sessionId, gameId, gameType, trigger, bet amount, payout amount, result, response status, and request latency. Do not log JWTs, secret keys, passphrases, signatures, or Authorization headers.

Persist local session state. Use getActive to find active Upside sessions and either resume gameplay or reconcile and settle from the backend.

Work with the B3 team to approve the game record, production iframe URL, game type, HMAC credentials, and any launch-specific pool or limits.

Still Blocked?

Testing

Debug localhost loading, bridge messages, signatures, and settlement.

Learn More
Contact B3 Team

Share your game details and integration status.

Ask a question... ⌘I