Skip to content

Player sessions

Your server tells the platform who the player is. There is no sportsbook login for your players: the call below is the login, authenticated by your API key. The platform finds the player by your id (or creates them), opens a session and returns a single-use launch token for the iframe.

Endpoint, server to server
POST /api/v1/integration/sessions
Launch token
single use, 120 s
Session
12 h absolute, idle timeout
POST /api/v1/integration/sessions
Content-Type: application/json
X-Tenant-ID: demo-embed
X-API-Key: <your integration API key>
{"externalPlayerId": "player-42", "displayName": "Maria", "path": "/live", "locale": "pt-BR"}
Field Type
externalPlayerId string required Your stable player id, at most 128 characters. The same id is always the same player; it is the playerId of every wallet call.
displayName string optional Shown in the sportsbook, at most 64 characters. Updated when it changes. Default Player.
currency string optional Must equal the tenant currency when sent.
cpf string BR tenants The player’s CPF, digits or formatted (529.982.247-25). See Brazil.
path string optional Deep link put in launchUrl: /, /live, /live/{sportId}, /sport/{sportId}, /competition/{id}, /event/{eventId}, /my-bets.
locale string optional en or pt-BR, put in launchUrl. Default: the tenant locale.

Unknown fields are refused (400 validation), so typos do not pass silently.

200 OK:

{
"launchToken": "lt_NIpjVSCtwQlG0iLUbF9T7WeY84YSVs3pVQeLxbbH1O0",
"launchExpiresAt": "2026-10-16T03:01:22.081091Z",
"launchUrl": "https://sportsbook.example.com/?tenant=demo-embed&launch=lt_NIpjVSCtwQlG0iLUbF9T7WeY84YSVs3pVQeLxbbH1O0&path=%2Flive&locale=pt-BR",
"token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9…",
"player": {
"id": "pl_bd387263c326f44e90808bde",
"tenantId": "demo-embed",
"externalId": "player-42",
"status": "active",
"displayName": "Maria",
"currency": "USD",
"kycStatus": "verified",
"createdAt": "2026-10-16T02:43:38.465403Z"
}
}
Field
launchToken Give this to the page: pass it to the embed SDK (launchToken option or setLaunchToken()). Single use, expires at launchExpiresAt.
launchUrl The same token as a ready-made iframe URL, for integrations without the SDK.
token The session token itself. Keep it on your server (or ignore it): never put it in a URL or a page. It stays in the response for backward compatibility.
player The platform’s player record (abridged above). kycStatus is verified because identity checks are delegated to you, which is recorded as evidence.

The origin of launchUrl is the platform’s configured sportsbook URL (SPORTSBOOK_URL); when unset, the origin your request was sent to.

Status code When
401 unauthorized Missing or wrong X-API-Key, or the tenant has no key. Every failure is audited with the caller’s IP.
400 validation Bad field; details.field names it (externalPlayerId, displayName, currency, cpf, path, locale), or an unknown field.
403 account_blocked The player is blocked or closed on the platform.
403 prohibited_bettor, self_excluded BR: the CPF is on the prohibited-bettor list or in the national self-exclusion system.
404 not_found Unknown tenant (X-Tenant-ID).
503 unavailable The tenant is suspended, or a compliance provider is down. Retry later.

A launch token is how the session reaches the iframe without ever being put in a URL. The sportsbook exchanges it once, at start-up or when it receives set_launch_token:

POST /api/v1/integration/launch
Content-Type: application/json
X-Tenant-ID: demo-embed
{"launchToken": "lt_NIpjVSCtwQlG0iLUbF9T7WeY84YSVs3pVQeLxbbH1O0"}
{ "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9…", "player": { "id": "pl_bd387263c326f44e90808bde", "…": "…" } }

You never call this endpoint yourself; the iframe does. It keeps the session token in memory and in sessionStorage for that iframe, and removes launch from its own address before anything else loads.

Rule
Single use The exchange marks the token used in the same database statement: a second exchange (a replayed or shared URL, the browser history) gets 401 with details.reason: "launch_token_used", and the replay is audited.
Expiry 120 seconds after it was issued (launchExpiresAt): 401, launch_token_expired. Create the session right before you render the sportsbook.
Tenant A token only works for its own tenant: elsewhere it is launch_token_invalid, like an unknown token.
Session The session must still be alive: a logged-out or expired session gives 401 (unauthorized or session_expired).
Storage Only a SHA-256 hash of the token is stored. Used and expired tokens are deleted after a day.

When the exchange fails at start-up, the sportsbook stays anonymous and sends your page an error event (code = the reason) followed by session_expired, so the SDK’s onSessionExpired can fetch a fresh token.

  • A session lasts at most 12 hours and ends after the jurisdiction’s idle timeout (60 minutes for .com tenants, 30 minutes for Brazil). Every authenticated call from the iframe (balance, bets, My Bets) counts as activity; browsing odds does not.
  • Each call to integration/sessions opens a new session; earlier sessions of the player keep working until they expire. When the player logs out of your site, call logout() on the SDK to end the sportsbook session too.
  • To refresh, call integration/sessions again and send the new launch token to the iframe. With the SDK, return it from onSessionExpired:
BookmakerSportsbook.mount('#sportsbook', {
url: 'https://sportsbook.example.com',
tenant: 'your-tenant',
launchToken,
// called when the sportsbook session ends (idle, expiry, refused token)
onSessionExpired: async () => {
const res = await fetch('/my-site/sportsbook-launch', { method: 'POST' }); // your endpoint
return res.ok ? (await res.json()).launchToken : null; // null: stay logged out
},
});

The same mechanism logs a player in without reloading the iframe: after your login dialog, call sb.setLaunchToken(newLaunchToken).

Brazilian tenants must send cpf for every session. The platform validates it and checks it against the operator’s prohibited-bettor list and the national self-exclusion system before the session opens. If the player already exists with another CPF, the call is refused (400 validation, field cpf). For other tenants cpf is optional and, when sent, checked the same way.