Sportsbook: SDK

The sportsbook runs in an iframe inside your site. The SBRenderer library mounts the iframe, hands over the player session and tells your site when the player wants to log in or deposit, or when the session expires.

Overview#

Browser
Your server
TALOS
Sportsbook
  1. 1.logged-in player opens Sports
  2. 2.POST /v1/game/launch { game: "sportsbook" }
  3. 3.launch_url with ?jwt=
  4. 4.jwt
  5. 5.SBRenderer.initialize({ token: jwt })
  6. 6.bets → wallet callback
  1. On the server, launch with game: "sportsbook" and extract the jwt parameter from the launch_url.
  2. In the browser, load the library and call initialize with the jwt and your brand.
  3. Bets reach your wallet through the callbacks, like any game.

1. Launch on the server#

TypeScript
import { talos } from './talos' // see Authentication

export async function sportsbookToken(playerId: string, lang: string): Promise<string> {
  const res = await talos('POST', '/v1/game/launch', { player_id: playerId, game: 'sportsbook', lang })
  if (!res.success) throw new Error(`${res.error.code}: ${res.message}`)
  return new URL(res.data.launch_url).searchParams.get('jwt')!
}

The jwt is valid for 10 minutes and is single-use: generate a new one every time you mount the sportsbook and when the session expires. For visitors (not logged in) do not launch — mount the sportsbook with token: null.

2. Library in the browser#

The library is served by the sportsbook itself:

HTML
<div id="sportsbook" style="height: 100vh"></div>
<script src="https://<sportsbook>/sb-renderer.min.js"></script>
<script>
  const sportsbook = new SBRenderer()
  sportsbook.initialize({
    target: document.getElementById('sportsbook'),
    brand_id: 'my-brand',             // GET /v1/merchant → brand
    token: jwtFromYourServer,         // null = visitor
    lang: 'en',
    onLogin: () => openLogin(),
    onRegister: () => openSignUp(),
    onRecharge: () => openDeposit(),
    onTokenExpired: async () => (await fetch('/api/sportsbook/token', { method: 'POST' }).then((r) => r.json())).jwt,
    onBalanceChange: ({ amount, currency }) => updateHeaderBalance(amount, currency)
  })
</script>

The iframe fills 100% of the target: give it a height. The sportsbook URL comes from the script origin; to serve the script from elsewhere, pass url.

Script integrity

The SRI hash of the published version is at https://<sportsbook>/sb-renderer.integrity.json. Use it in the integrity attribute (with crossorigin="anonymous") if your security policy requires it.

Options#

OptionTypeDescription
targetHTMLElementElement where the iframe is mounted. Required.
brand_idstringYour brand (brand from GET /v1/merchant). Required.
tokenstring | nullThe launch jwt. null or empty = visitor.
urlstringSportsbook address. Default: the origin the script was loaded from.
langstringpt, es or en (regional tags such as en-US are accepted).
themeNamestringForces a color theme (list below). Without it, your brand theme applies.
layout"sidebar" | "classic" | "tile"Forces a layout. Without it, your brand layout applies.
oddsFormat"decimal" | "fractional" | "american"Odds format.
pathstringInitial route (deep link), e.g. "/soccer". Default: the page ?sb-path=.
syncPathbooleanKeeps the internal route in your page ?sb-path= (F5 and shared links open in the same place). Default: true.
debugbooleanLogs the sportsbook messages to the console. Default: false.

Events#

CallbackWhen
onAppInitialized()The sportsbook finished loading.
onLogin()The player clicked "Log in": open your login.
onRegister()The player clicked "Sign up".
onRecharge()The player wants to deposit (e.g. not enough balance in the betslip).
onRouteChange(path)The internal route changed.
onTokenExpired()The session expired. Return a new jwt (do another launch on your server) — it may be a Promise — and the sportsbook reconnects by itself. null = continue as a visitor.
onSessionRefresh()Alternative to onTokenExpired: it only notifies; you call updateOptions({ token }).
onBetslipChanged({ count })The number of selections in the betslip changed.
onBetPlaced({ betIds, stake })Bet placed. stake in the minor currency unit (cents).
onBalanceChange({ amount, currency })Balance after bets and settlements, in the minor currency unit (cents; CLP in pesos).

Different units

SDK events use the minor unit (cents), like the sportsbook front end. The wallet callback and the API use the major unit (2.5 = US$ 2.50).

Errors inside your callbacks are caught and logged; they do not bring the sportsbook down.

Methods#

JavaScript
sportsbook.updateOptions({ token: newJwt })      // login/logout without reloading
sportsbook.updateOptions({ lang: 'es' })        // live language switch
sportsbook.updateOptions({ themeName: 'gold-navy', layout: 'classic' })
sportsbook.navigate('/soccer')                   // navigates inside the sportsbook
sportsbook.refreshBalance()                      // after a deposit/withdrawal on your site
sportsbook.kill()                                // removes the iframe

updateOptions accepts everything except target, brand_id and url. Calling initialize again replaces the iframe.

Login, visitor and renewal#

  • Visitor: mount with token: null. The player browses and builds the betslip; the betslip and "My bets" show the "Log in" button, which calls onLogin.
  • After login: launch on the server and call updateOptions({ token }), without reloading the iframe.
  • Logout: updateOptions({ token: null }).
  • Expired session: implement onTokenExpired returning a new token. Several simultaneous expirations become a single call. If your callback fails, the player continues as a visitor.

Themes and layouts#

By default, theme and layout come from your brand configuration. themeName and layout override them only on that page.

LayoutDescription
sidebarSide navigation of sports + betslip on the right (default).
classicDenser table list.
tileCards and a sports bar at the top.

Themes: mint-carbon, azure-carbon, gold-navy, emerald-carbon, flame-carbon, lilac-plum, brasil-navy, lilac-light, canary-plum, red-navy, coral-light, aqua-carbon, navy-light, amber-carbon.

Without the library#

The launch_url also opens directly in an <iframe src>. You lose the events (login, deposit, balance, expired session) and automatic renewal; use it only for tests.