Server-side verification

The wallet identifies the player; your backend is the relying party that trusts it. Never trust a user id or wallet address claimed by the browser — verify the player’s wallet session server-to-server with your secret key, then mint your own app session.

The flow

1. The player signs into the wallet in your frontend (Telegram / browser wallet / email) → the SDK returns a session token.
2. Your frontend sends that token to your backend.
3. Your backend calls POST /v1/sessions/verify with your sk_ key and the token. The wallet confirms it, scopes it to your app + environment, and returns the canonical identity.
4. Your backend looks up / creates its own user and issues its own JWT for your UI — trusting the verified identity, not the client.

1 · Get your secret key

In the developer portal, open your app and reveal the secret key (sk_test_… for sandbox, sk_live_… after live approval). It is shown once — store it as a backend secret (never ship it to the browser). Lost it? Rotate it from the same panel.

2 · Verify the session

Backend SDK (recommended):

TS
import { IAMGameWalletServer } from "@iamgame/wallet-sdk-server"

const wallet = new IAMGameWalletServer({
  secretKey: process.env.IAMGAME_WALLET_SECRET_KEY, // sk_live_… or sk_test_…
  baseUrl: "https://api-wallet.iamgame.com/v1",
})

// In your login handler — the browser sent you the player's wallet session token.
export async function login(req, res) {
  const { sessionToken } = req.body

  // Verify against YOUR app + environment. Throws if the token is invalid,
  // expired, or not in your app's scope/environment.
  const id = await wallet.verifySession(sessionToken)
  // id = { userId, appId, environment, walletAddress, wallets[], identities[] }

  // Look up / create YOUR own user, keyed to the canonical wallet identity.
  const user = await db.users.upsert({ walletUserId: id.userId, address: id.walletAddress })

  // Mint your OWN app JWT — never trust a user id the browser claims.
  const appJwt = signYourJwt({ sub: user.id })
  res.json({ token: appJwt })
}

Or call the endpoint directly:

bash
curl -X POST https://api-wallet.iamgame.com/v1/sessions/verify \
  -H "Authorization: Bearer $IAMGAME_WALLET_SECRET_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "sessionToken": "<player wallet session token>" }'

POST /v1/sessions/verify · auth Authorization: Bearer sk_… · body { sessionToken }. The endpoint is secret-key only — it must never be called from the browser.

Response

The canonical, verified identity for the player:

json
{
  "userId": "c8d85dc9-…",
  "appId": "5a00769e-…",
  "environment": "test",
  "authMethod": "telegram",
  "walletAddress": "J8gpeci3qKpYC34pw1Sk4XLncMawipDXGtLtVfoEq7mq",
  "wallets": [
    { "address": "J8gp…", "environment": "test", "custody": "self", "status": "active" }
  ],
  "identities": [
    {
      "id": "…",
      "type": "telegram",
      "externalId": "6931997952",
      "profile": { "username": "karpi", "firstName": "Piyush" }
    }
  ]
}

userId — the wallet’s stable user id (your join key).
walletAddress / wallets[] — the player’s managed address(es); lets you confirm an on-chain address belongs to this user.
identities[] — each login identity with its captured profile (e.g. the Telegram username), for display and cross-app attribution.

3 · Mint your own session

With the verified identity, upsert your own user and issue your own JWT (or cookie). From here your game endpoints authenticate against your token — the wallet session is only ever used at this verify step.

Errors

401 — bad / missing secret key.
403 auth/invalid_token — the session is not in your app’s scope or its environment doesn’t match your key (a test session presented with a live key is refused). Fails closed.
404 user/not_found — the session’s user no longer exists.

Scope & isolation

Verification is bound to your key’s scope and environment. Apps in the shared (default) scope resolve the same portable user across the ecosystem — the same player has one wallet address everywhere. An isolated app (e.g. a regulated entity) has app-private users and wallets: only that app’s key can verify its sessions. Choose isolation at app creation when a tenant’s users must never be resolvable from anywhere else.