Hybrid Integration

This guide covers how to use the client SDK and server SDK together for games that have their own backend but still need the client SDK for authentication, UI, and the points widget.


When to Use Hybrid Integration

Use this approach when your game:

  • Has a backend server that validates gameplay or runs game logic

  • Needs server-authoritative point saving (prevents client-side cheating)

  • Still wants the client SDK's built-in login, widget, and rewards UI

If your game is client-only with no backend, use the client SDK alone. If your game is fully server-rendered with no client SDK needs, use the server SDK alone.


Architecture

Player's Browser                Your Game Server              Play.fun API
┌─────────────────┐          ┌───────────────────┐        ┌───────────────┐
│  Client SDK     │          │  Server SDK       │        │               │
│                 │          │                   │        │               │
│  1. Login &     │          │                   │        │               │
│     get session ├─────────►│  3. Validate      │        │               │
│     token       │ send     │     session token ├───────►│  Verify token │
│                 │ token    │                   │        │               │
│  2. Submit game │          │  4. Run game      │        │               │
│     state +     │          │     logic &       │        │               │
│     session     │          │     validate      │        │               │
│     token to    │          │                   │        │               │
│     server      │          │  5. Save points   ├───────►│  Store points │
│                 │          │     via server SDK│        │               │
│                 │◄─────────┤                   │        │               │
│  6. Sync widget │ respond  │  6. Return result │        │               │
│     via refresh │          │     to client     │        │               │
│     PointsAnd   │          │                   │        │               │
│     Multiplier  │          │                   │        │               │
└─────────────────┘          └───────────────────┘        └───────────────┘

Step-by-Step Guide

1. Client SDK Setup

Set up the client SDK in your game as usual. The SDK handles login and provides the session token automatically after authentication.

2. Read the Session Token and Player ID

After the player logs in (either manually or when endGame() triggers auto-login), read the session token and player ID from the SDK:

Property
Type
Description

sdk.sessionToken

string | undefined

Play.fun session token (player_xxx format). Scoped to this game, expires after 30 minutes.

sdk.playerId

string | undefined

Player's Privy ID (did:privy:xxx). Use this to identify the player on your backend.

3. Validate the Token on Your Server

On your backend, use the server SDK to validate the session token. This confirms the player is genuinely authenticated through Play.fun.

4. Run Game Logic and Save Points

After validation, run your game logic and save points using the ogpId returned from validation:

5. Sync the Widget on the Client

After your server saves points, the client SDK needs to sync its UI with the server's actual data. Call refreshPointsAndMultiplier() to fetch the latest points from the Play.fun API and update the widget display:

This is critical because the widget has no way of knowing when your server saves points — without this call, the displayed points will be stale until the next page refresh.

Note: In hybrid integrations, do not call endGame() on the client. That method is for client-only integrations and will open a gameplay-blocking modal. Instead, your server handles point saving via the server SDK, and the client just syncs the display with refreshPointsAndMultiplier().


Complete Example

Client-Side (JavaScript)

Server-Side (Node.js / Express)


Security Notes

  • Session tokens are scoped per-game — a token issued for Game A cannot be used for Game B

  • Tokens expire after 30 minutes — if expired, the client SDK will automatically refresh on the next authenticated request

  • Tokens never expose the Privy auth token — the player_xxx token is a play.fun-issued session token, not the player's underlying Privy credentials

  • Always validate server-side — never trust client-sent player IDs or scores without validating the session token first

Last updated