---
title: "Next Bet Integration"
canonical_url: "https://apidocs.sportradar.com/resources/widgets/docs/next-bet/next-bet-integration"
markdown_url: "https://apidocs.sportradar.com/resources/widgets/docs/next-bet/next-bet-integration.md"
last_updated: "2026-10-30T07:53:39Z"
---

# Next Bet Integration

Next Bet is a live, in-play micro-betting experience for tennis, delivered through the **`immersiveBetting`** widget. It brings together a
live scoreboard, betting panel, bet history, and an embedded **LMT Plus** court visualization or AV stream.

**Next Bet** supplies markets and odds for the experience. **Wallet settlement** and **stake limits** are owned by the **bookmaker** or by **MTS**, not by Next Bet. Optional **Punter Bets** in Betting History & Timeline depend on the integration model, data source, and a widgets license flag — see [Betting history](#betting-history).

***

## Integration at a glance

### 1. Embed

Load the widgetloader and mount `immersiveBetting` with an eligible `matchId` and `sportId`.

### 2. Configure the punter

Supply a bookmaker-issued `sessionToken` and the required `punter` stake UI fields. Handle login, token refresh, and logout.

### 3. Connect ticketing

Choose MTS-managed or Bookmaker-managed routing and complete the corresponding API workstream.

These workstreams can run in parallel. Typical integration takes **1–3 weeks when authentication and bookmaker APIs already exist**; new backend work and optional features add time.

***

## Before you start

**Widget embed**

- Licensed widgets **`clientId`** with `immersiveBetting` enabled
- Numeric **`matchId`** for an eligible live tennis match

**Session and stake configuration**

- A `punter` object with currency and stake settings for the betting panel (see [Punter authentication](#punter-authentication-and-stake-configuration)).
- Ability to issue, refresh, and revoke bookmaker **`sessionToken`** values for logged-in punters
- **`updateWidget`** when the token changes; **`onSignIn`** for sign-in on demand and after invalid/expired token (see [lifecycle](#session-and-widget-lifecycle))

**UOF (all models)**

- UOF account, purchased matches, prod access (not bundled with widgets license by default)
- ATP and Challenger events typically have the strongest Next Point coverage — prioritize those matches when purchasing UOF

**[MTS-managed](#mts-managed)**

- Existing or new **MTS account** and [Transaction 3.0 API](https://docs.sportradar.com/transaction30api) integration
- Bookmaker **`auth`** API — see [Bookmaker API documentation](#bookmaker-api-documentation)

**[Bookmaker-managed](#bookmaker-managed)**

- Ticketing APIs **`health`**, **`auth`**, **`place`** — see [Bookmaker API documentation](#bookmaker-api-documentation)
- **UOF consumer** on the bookmaker side for settle/cancel/rollback

**Optional**

- [Bet status delivery](#bet-status-updates-for-history-and-timeline) to include Punter Bets in history/timeline (Bookmaker-managed only)
- [Punter bet history](#disable-punter-bet-history) is **on by default** and is agreed with the bookmaker during integration; upon the bookmaker's request, Sportradar can disable this feature on the widgets license.
- Live video AV (optional): widgets license AV entitlement and top-level **`jwt`** with **`av`** in token `scope` (same model as [LMT video streaming](https://apidocs.sportradar.com/resources/widgets/docs/lmt/lmt.md#video-streaming-lco)); see [JSON Web Token (JWT)](https://apidocs.sportradar.com/resources/widgets/docs/tutorials/jwt.md)
- `sportProps.withMatches` and **`onMatchChange`** if the match switcher is enabled

**Integration**

- A point of contact for the shared integration channel

**Integration responsibilities**

### Integration responsibilities

| Workstream                                  | Owner                             | Bookmaker deliverable                                                                                                                                                                                                                         |
| ------------------------------------------- | --------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Widget embed                                | Bookmaker                         | Widgetloader, DOM container, `matchId`, licensed `clientId`                                                                                                                                                                                   |
| Punter session (`sessionToken`)             | Bookmaker                         | Issue, refresh, and revoke opaque session tokens; call `updateWidget` when the token changes                                                                                                                                                  |
| Punter stake UI (`punter`)                  | Bookmaker                         | Currency, default stake, and preset amounts in `punter` at mount or `updateWidget`; optional UI limits in the same object. See [Punter authentication](#punter-authentication-and-stake-configuration)                                        |
| UOF access (all models)                     | Bookmaker                         | UOF account, purchased matches; ATP and Challenger for strong Next Point coverage — see [UOF prerequisites](#uof-prerequisites-all-models)                                                                                                    |
| **[MTS-managed](#mts-managed)**             | Bookmaker + Sportradar (MTS)      | [Transaction 3.0 API](https://docs.sportradar.com/transaction30api) integration; bookmaker [`auth`](#auth-api-format) API                                                                                                                     |
| **[Bookmaker-managed](#bookmaker-managed)** | Bookmaker + Sportradar (Next Bet) | `health`, [`auth`](#auth-api-format), [`place`](#place-api-format); [UOF consumer](https://docs.sportradar.com/uof/introduction/overview) for wallet settlement; optional [bet status delivery](#bet-status-updates-for-history-and-timeline) |
| Odds and markets                            | Sportradar (Next Bet)             | Next Bet supplies markets and odds; the bookmaker does not feed odds into Next Bet                                                                                                                                                            |
| Bet status (panel)                          | Sportradar (Next Bet)             | Bet status updates in the betting panel over WebSocket                                                                                                                                                                                        |

Embed, session, and bookmaker API onboarding can run in parallel. Widgets licensing and Next Bet configuration are coordinated during Next Bet integration onboarding.

***

## Quick start

Replace `YOUR_CLIENT_ID` with your licensed widgets client ID and `YOUR_MATCH_ID` with a numeric eligible tennis match ID. The **bookmaker issues the session token**, not Sportradar.

The stake values below follow the team's supplied example. Configure them using the widget monetary units agreed during onboarding; this guide does not assume those units are identical to the placement API's smallest-currency-unit amounts.

```html
<div id="sr-widget"></div>
<script>
    var clientId = 'YOUR_CLIENT_ID';

    (function (a, b, c, d, e, f, g, h, i) {
        a[e] ||
            ((i = a[e] =
                function () {
                    (a[e].q = a[e].q || []).push(arguments);
                }),
            (i.l = 1 * new Date()),
            (i.o = f),
            (g = b.createElement(c)),
            (h = b.getElementsByTagName(c)[0]),
            (g.async = 1),
            (g.src = d),
            g.setAttribute('n', e),
            h.parentNode.insertBefore(g, h));
    })(window, document, 'script', 'https://widgets.sir.sportradar.com/' + clientId + '/widgetloader', 'SIR', { language: 'en' });

    var punterConfig = {
        currency: 'EUR',
        defaultBetSize: 500,
        betSizes: [100, 500, 1000, 5000],
        /** Optional UI limits starts */
        maxBet: 10000,
        minBet: 100,
        maxWin: 50000,
        maxOdds: 50,
        /** Optional UI limits ends */
    };

    SIR('addWidget', '#sr-widget', 'immersiveBetting', {
        matchId: YOUR_MATCH_ID,
        sportId: 5,
        sessionToken: 'YOUR_BOOKMAKER_SESSION_TOKEN',
        punter: punterConfig,
        onSignIn: function () {
            // Open bookmaker login; then call setPunterSession(token, config).
        },
        onClose: function () {
            // Handle host-page navigation or visibility.
        },
    });

    function setPunterSession(token, config) {
        SIR('updateWidget', '#sr-widget', {
            sessionToken: token,
            punter: config,
        });
    }

    // Refresh token when stake configuration has not changed:
    // SIR('updateWidget', '#sr-widget', { sessionToken: 'NEW_TOKEN' });

    // Logout:
    // SIR('updateWidget', '#sr-widget', { sessionToken: undefined, punter: undefined });

    // Teardown:
    // SIR('removeWidget', '#sr-widget');
</script>
```

For a logged-out mount, omit `sessionToken` and supply token plus required `punter` values after successful login.

***

## Widget configuration

To enable betting, pass `sessionToken` and `punter` at mount or after login via `updateWidget`. To **log out**, call `updateWidget` with **`sessionToken` and `punter` removed** (for example, set both to `undefined`).

### Logged-in mount

```javascript
SIR('addWidget', '#sr-widget', 'immersiveBetting', {
    matchId: 12345678,
    sportId: 5,
    sessionToken: 'YOUR_SESSION_TOKEN',
    punter: {
        currency: 'EUR',
        defaultBetSize: 500,
        betSizes: [100, 500, 1000, 5000],
        /** Optional UI limits starts */
        maxBet: 10000,
        minBet: 100,
        maxWin: 50000,
        maxOdds: 50,
        /** Optional UI limits ends */
    },
});
```

### Logged-out mount

```javascript
SIR('addWidget', '#sr-widget', 'immersiveBetting', {
    matchId: 12345678,
    sportId: 5,
});
```

| Parameter      | Required                 | Description                                                                                                             |
| -------------- | ------------------------ | ----------------------------------------------------------------------------------------------------------------------- |
| Widget name    | Yes                      | `immersiveBetting`                                                                                                      |
| `matchId`      | Yes                      | Match id. Obtain via Sports API, Coverage Feed, UOF, or Mapping Feed.                                                   |
| `sportId`      | Yes                      | `5` for tennis                                                                                                          |
| `sessionToken` | When punter is logged in | Opaque bookmaker session token — see [Punter authentication](#punter-authentication-and-stake-configuration)            |
| `punter`       | When punter is logged in | Currency and stake settings for the panel — see [Punter authentication](#punter-authentication-and-stake-configuration) |

### Update and remove

```javascript
SIR('updateWidget', '#sr-widget', { matchId: 87654321 });

// Log out (clear session and stake configuration):
SIR('updateWidget', '#sr-widget', { sessionToken: undefined, punter: undefined });

SIR('removeWidget', '#sr-widget');
```

> **Note**
>
> Next Bet embeds LMT Plus internally. Do not mount a separate `match.lmtPlus` for the same match. Only one `immersiveBetting` instance per match per page is recommended.

***

## Sports and markets

> **Info**
>
> **Tennis is the only supported sport currently.** Soccer and Basketball are **to be developed** and are not available for integration today. No release dates are specified. Tennis market IDs, options, and rally rules must not be reused for those future sports.

| Sport      | Status          | Scope                                        |
| ---------- | --------------- | -------------------------------------------- |
| Tennis     | Supported       | Live Next Point betting; `sportId: 5`        |
| Soccer     | To be developed | Markets and configuration not yet documented |
| Basketball | To be developed | Markets and configuration not yet documented |

### Tennis experience

| Area                | Description                                                                  |
| ------------------- | ---------------------------------------------------------------------------- |
| Scoreboard          | Player names, sets/games/points, serve indicator                             |
| Betting panel       | Market, stake control, bet confirmation, users' betting statistics           |
| Court visualization | Embedded `match.lmtPlus` (rear court view, momentum/tabs disabled)           |
| AV visualization    | Alternative to the court visualization; embedded `match.lmtPlus`             |
| Bet history         | Per-set timeline of bets placed by authorized punters over the last 24 hours |
| Bet outcome (panel) | Win/loss/cancel bet status notifications in the betting panel                |
| Match overlays      | Set break, tiebreak, match ended, unauthorized state                         |

Court surface theme (hard, clay, grass) is resolved automatically from tournament data.

### Tennis markets and lifecycle

| Item                  | Value                                                                                             |
| --------------------- | ------------------------------------------------------------------------------------------------- |
| Primary market        | **Next Point** (point winner)                                                                     |
| Market id             | `218`                                                                                             |
| Odds and market state | Next Bet supplies markets and odds for the experience                                             |
| Betting window        | See [Betting window](#betting-window)                                                             |
| Bet status (panel)    | Bet status updates in the betting panel                                                           |
| UOF market setting    | For Next Point, **Exclude the next point from the offer** must be **off** in the UOF market offer |

When a UOF market is open and outcomes are streamed, the widget may enable acceptance **between rallies** (see [Betting window](#betting-window)). When
the market is suspended or disabled, placement is blocked regardless of punter session state. See [Odds source and UOF prerequisites](#odds-source-and-uof-prerequisites).

### Betting window

Placement requires **all** of the following:

- the UOF market is open and outcomes are available;
- the punter is authorized (`sessionToken` supplied and required `punter` fields present: `currency`, `defaultBetSize`, `betSizes`);
- the widget is **not** in the active-rally suspend state (betting is blocked while a rally is in progress).

> **Warning**
>
> Verify the [UOF market setting](#tennis-markets-and-lifecycle) for Next Point before go-live.

### Tennis optional configuration

Additional behaviour can be passed under `sportProps` (tennis only today):

```javascript
SIR('addWidget', '#sr-widget', 'immersiveBetting', {
    matchId: 12345678,
    sportId: 5,
    jwt: 'YOUR_AV_STREAM_JWT',
    sportProps: {
        withPlayerInfo: true,
        withMatches: true,
        withBetSizeOptions: false,
        stakeControlView: 'standard',
    },
});
```

| Prop / parameter     | Default    | Description                                                                                                                                                                                                                                        |
| -------------------- | ---------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `jwt`                | —          | Top-level JWT for live AV in the embedded LMT Plus court view. Include **`av`** in `scope`; sign server-side (RS256) on the bookmaker backend — see [JSON Web Token (JWT)](https://apidocs.sportradar.com/resources/widgets/docs/tutorials/jwt.md) |
| `withPlayerInfo`     | `false`    | Player labels on court; highlight the player linked to the active bet                                                                                                                                                                              |
| `withMatches`        | `false`    | Live match switcher when the current match ends; fires `onMatchChange`                                                                                                                                                                             |
| `withBetSizeOptions` | `false`    | Show preset stake chips from `punter.betSizes` when `true`                                                                                                                                                                                         |
| `stakeControlView`   | `standard` | Stake control layout: `standard` or `compact`                                                                                                                                                                                                      |

***

## Odds source and UOF prerequisites

Next Bet supplies markets and odds for the experience. The bookmaker does not feed odds into Next Bet.

For **[Bookmaker-managed](#bookmaker-managed)** settlement, the bookmaker still needs a [UOF](https://docs.sportradar.com/uof/introduction/overview) consumer on their side. Market definitions, availability, and settlement signals follow the UOF model.

Placement gates are defined in [Betting window](#betting-window).

Sportradar configures Next Bet connectivity and per-bookmaker identifiers (`customerId`, API/WSS URLs) in the widgets license during Next Bet integration onboarding.

### UOF prerequisites (all models)

Regardless of MTS or Bookmaker-managed routing, the bookmaker should:

- Create a **[UOF](https://docs.sportradar.com/uof/introduction/overview)** account and obtain **production** access through Sportradar onboarding
  (UOF is **not** automatically included in the widgets license).
- Purchase or subscribe to the **matches** they intend to offer in Next Bet.
- Prioritize **ATP** and **Challenger** events, which typically have the strongest Next Point coverage.
- Align production identifiers and connectivity with the Next Bet integration channel before go-live.

***

## Punter authentication and stake configuration

The **`sessionToken` is issued by the bookmaker** (opaque string). There is no separate Sportradar token-issuance API in the public integration path. The
same value is passed to the widget and included when the punter places a bet. **Next Bet Backend** calls the bookmaker [`auth`](#auth-api-format) API
**immediately before placement** (not when the token is first supplied to the widget).

Stake configuration is passed in a top-level **`punter`** object at mount or on `updateWidget`. The widget does not load these values from Next Bet.

A few fields are **required** so the betting panel can open. **Optional** limits apply in the panel only when you pass them — if you leave one out, the punter will not see that limit in the UI.

| Field            | Required | Description                                                                                     |
| ---------------- | -------- | ----------------------------------------------------------------------------------------------- |
| `currency`       | Yes      | Currency shown in the UI                                                                        |
| `defaultBetSize` | Yes      | Default stake when the panel opens                                                              |
| `betSizes`       | Yes      | Array of preset stake amounts (used with `sportProps.withBetSizeOptions`)                       |
| `maxBet`         | No       | Highest stake the punter can enter in the panel. Not passed — no maximum stake shown in the UI. |
| `minBet`         | No       | Lowest stake in the panel. Not passed — no minimum stake shown in the UI.                       |
| `maxWin`         | No       | Cap on potential winnings in the panel. Not passed — no win cap in the UI.                      |
| `maxOdds`        | No       | Highest odds the punter can pick in the panel. Not passed — no odds ceiling in the UI.          |

Minimum `punter` (required fields only):

```javascript
punter: {
    currency: 'EUR',
    defaultBetSize: 500,
    betSizes: [100, 500, 1000, 5000],
}
```

Two integration approaches are available:

- **Pre-authenticated session** — pass `sessionToken` and `punter` when mounting the widget.
- **Sign-in on demand** — mount without a token; use the `onSignIn` callback and `updateWidget` after login.

> **Warning**
>
> Optional limits in `punter` only affect what the punter sees in the panel. They do **not** replace sportsbook or MTS rules — balance, stakes, and risk are still enforced on the **bookmaker** side (or by **MTS** where that model applies).

**Pre-authenticated**

### Option A: Pre-authenticated Session

The bookmaker passes `sessionToken` and `punter` at mount. The widget enables bet placement when the UOF market is open, the widget is not suspended for an active rally, `sessionToken` is present, and required `punter` fields are supplied.

Use when the Next Bet page is behind login or the bookmaker already has a session token before the widget loads.

```javascript
SIR('addWidget', '#sr-widget', 'immersiveBetting', {
    matchId: 12345678,
    sportId: 5,
    sessionToken: 'YOUR_SESSION_TOKEN',
    punter: {
        currency: 'EUR',
        defaultBetSize: 500,
        betSizes: [100, 500, 1000, 5000],
        /** Optional UI limits starts */
        maxBet: 10000,
        minBet: 100,
        maxWin: 50000,
        maxOdds: 50,
        /** Optional UI limits ends */
    },
});
```

On token refresh or logout, update the widget:

```javascript
SIR('updateWidget', '#sr-widget', { sessionToken: 'NEW_SESSION_TOKEN' });
// To log out:
SIR('updateWidget', '#sr-widget', { sessionToken: undefined, punter: undefined });
```

**Sign-in on demand**

### Option B: Sign-in on Demand

The widget mounts without `sessionToken`. Match and market data still load; the betting panel shows an unauthorized state. The bookmaker handles login
through the `onSignIn` callback and passes the token once available.

Use when the bookmaker wants to show the live experience before login or authentication completes asynchronously after the page loads.

```javascript
SIR('addWidget', '#sr-widget', 'immersiveBetting', {
    matchId: 12345678,
    sportId: 5,
    onSignIn: function () {
        // Open bookmaker login; after success, call updateWidget with sessionToken and required punter fields
    },
});
```

```javascript
// After successful login
SIR('updateWidget', '#sr-widget', {
    sessionToken: 'YOUR_SESSION_TOKEN',
    punter: {
        currency: 'EUR',
        defaultBetSize: 500,
        betSizes: [100, 500, 1000, 5000],
        /** Optional UI limits starts */
        maxBet: 10000,
        minBet: 100,
        maxWin: 50000,
        maxOdds: 50,
        /** Optional UI limits ends */
    },
});
```

### Bet placement

The full bet acceptance flow runs inside the widget:

1. Select the stake amount.
2. Select an outcome from the market.
3. Confirm the selected market outcome.
4. The widget sends the ticket to Next Bet (including `sessionToken`). Next Bet Backend calls bookmaker [`auth`](#auth-api-format), then routes placement per the chosen
   model ([MTS-managed](#mts-managed) or [Bookmaker-managed](#bookmaker-managed)).
5. Bet status updates are received over WebSocket and shown in the betting panel.

### Session and widget lifecycle

| Event                        | Bookmaker action                                                                  | Widget behaviour                                                                                                                                                  |
| ---------------------------- | --------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Login / first token          | `updateWidget` with `sessionToken` and `punter` (or pass at mount)                | Authorized betting panel when token and required `punter` fields are present; opens bet WebSocket when the match is in play                                       |
| Token refresh                | `updateWidget` with new `sessionToken` (and `punter` if stake config changed)     | Applies new token and `punter` values; bet WebSocket reconnects as needed                                                                                         |
| Logout                       | `updateWidget` with `sessionToken` and `punter` removed (for example `undefined`) | Unauthorized panel; bet socket torn down                                                                                                                          |
| Invalid / expired token      | Provide a new token via `updateWidget` after sign-in                              | Rejected **placement** due to invalid session → widget invokes **`onSignIn`** (if provided); inline expired-session message                                       |
| No token                     | Omit `sessionToken` or leave user logged out                                      | Markets and match UI still load; unauthorized panel; optional sign-in button calls **`onSignIn`**                                                                 |
| Match switch (`withMatches`) | Update page state in **`onMatchChange`**; widget updates `matchId` internally     | Bet WebSocket resubscribes to the new event                                                                                                                       |
| Rejected placement           | None required                                                                     | Inline error in the bet panel (insufficient funds, high odds, invalid session, bookmaker unavailable, generic rejection); errors auto-clear after a short timeout |
| Teardown                     | `removeWidget` when leaving the page                                              | Widget unmounts                                                                                                                                                   |

Connection loss and WebSocket retry behaviour are not part of the public integration contract in this release.

### Wallet, limits, and acceptance rules

Responsibility is split across **UOF**, **Next Bet**, and the **bookmaker**:

| Concern                   | Owner                       | In the widget                                                                                                                                                                                                                                                                                                                                            |
| ------------------------- | --------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **Odds and market state** | UOF                         | Markets, odds, and whether a market is open or suspended come from **UOF** and are shown in the betting panel.                                                                                                                                                                                                                                           |
| **Wallet**                | Bookmaker or MTS            | Funds and payouts stay with the bookmaker sportsbook or MTS. Bookmaker [`auth`](#auth-api-format) does not return balance; errors such as insufficient funds come from [`place`](#place-api-format) (Bookmaker-managed) or from MTS (MTS-managed).                                                                                                       |
| **Stake UI (`punter`)**   | Bookmaker                   | Currency and stake amounts you supply in `punter`; not loaded from Next Bet. Optional limits only change what the punter sees in the panel. See [Punter authentication](#punter-authentication-and-stake-configuration).                                                                                                                                 |
| **Placement**             | Next Bet + bookmaker or MTS | When the UOF market is open, the widget submits to Next Bet. **MTS-managed:** MTS handles risk and placement per [MTS-managed](#mts-managed). **Bookmaker-managed:** Next Bet calls bookmaker [`place`](#place-api-format) ([Bookmaker-managed](#bookmaker-managed)). The widget also blocks bets during an active rally, on top of market availability. |
| **Wallet settlement**     | Bookmaker or MTS            | **MTS-managed:** MTS owns bet lifecycle. **Bookmaker-managed:** the bookmaker settles, cancels, and rolls back bets locally using a [bookmaker UOF consumer](#bookmaker-managed).                                                                                                                                                                        |
| **Bet status (panel)**    | Next Bet Backend            | Bet status updates over WebSocket in the betting panel. These updates are not wallet settlement — payouts stay with the bookmaker or MTS.                                                                                                                                                                                                                |

### Page callbacks

| Callback        | When fired                                                                                                                 |
| --------------- | -------------------------------------------------------------------------------------------------------------------------- |
| `onSignIn`      | User taps sign-in in the unauthorized panel, **or** placement is rejected because the `sessionToken` is invalid or expired |
| `onClose`       | User closed the widget (header close action)                                                                               |
| `onMatchChange` | User switched to another live match (`sportProps.withMatches: true`); receives the new numeric `matchId`                   |

```javascript
SIR('addWidget', '#sr-widget', 'immersiveBetting', {
    matchId: 12345678,
    sportId: 5,
    sessionToken: 'YOUR_SESSION_TOKEN',
    punter: {
        currency: 'EUR',
        defaultBetSize: 500,
        betSizes: [100, 500, 1000, 5000],
        /** Optional UI limits starts */
        maxBet: 10000,
        minBet: 100,
        maxWin: 50000,
        maxOdds: 50,
        /** Optional UI limits ends */
    },
    onClose: () => {
        /* navigate away or hide container */
    },
    onMatchChange: (matchId) => {
        /* update page URL/state */
    },
});
```

### Choosing an Authentication Approach

|                              | Pre-authenticated session                                            | Sign-in on demand                                                       |
| ---------------------------- | -------------------------------------------------------------------- | ----------------------------------------------------------------------- |
| `sessionToken` at mount      | Required                                                             | Not passed at mount                                                     |
| Betting before login         | No                                                                   | No — markets visible, placement disabled                                |
| Bookmaker's main deliverable | Issue `sessionToken` and `punter` (required fields) before page load | `onSignIn` handler + `updateWidget` with token and `punter` after login |
| Token refresh                | `updateWidget` with new token                                        | Same                                                                    |
| Typical effort               | \~3–5 days                                                           | \~5–7 days                                                              |

***

## Bookmaker integration

When a punter places a bet, **Next Bet** accepts the ticket from the widget, calls bookmaker [`auth`](#auth-api-format), then either submits through **MTS** or calls bookmaker [`place`](#place-api-format), depending on the integration model. Two models are supported; choose one during **Next Bet integration onboarding**:

| Model                                       | When to use                                                                    | Who owns risk and bet lifecycle                                                                                      |
| ------------------------------------------- | ------------------------------------------------------------------------------ | -------------------------------------------------------------------------------------------------------------------- |
| **[MTS-managed](#mts-managed)**             | Sportradar **MTS** (Managed Trading Services) handles trading and bet workflow | MTS via [Transaction 3.0 API](https://docs.sportradar.com/transaction30api)                                          |
| **[Bookmaker-managed](#bookmaker-managed)** | No MTS; bookmaker runs its own sportsbook stack                                | Bookmaker (wallet settlement via [UOF](https://docs.sportradar.com/uof/introduction/overview) on the bookmaker side) |

```mermaid
flowchart TD
    start([Start onboarding]) --> useMts{Use MTS?}
    useMts -->|Yes| mtsPath[MTS-managed]
    useMts -->|No| bmPath[Bookmaker-managed]
    mtsPath --> includeMts[Punter Bets from MTS data]
    bmPath --> historyBm{Provide bet status for history?}
    historyBm -->|Yes| includeBm[Include Punter Bets in history and timeline]
    historyBm -->|No| excludeBm[Exclude Punter Bets; other timeline data remains]
```

On **MTS-managed**, Next Bet always ingests bet data from **MTS**. A widgets **license flag** (on by default) only controls whether **Punter Bets** are shown in the history UI; panel bet status is unchanged. On **Bookmaker-managed**, [bet status delivery](#bet-status-updates-for-history-and-timeline) is needed to **show** Punter Bets when the history flag is on: without it, match timeline content remains but **Punter Bets** are excluded.

### Bookmaker API documentation

The bookmaker always provides API documentation (and production base URLs) covering each required endpoint and **all possible errors per endpoint**. Sportradar configures the connector against that documentation. Required endpoints depend on the integration model:

| Endpoint | [MTS-managed](#mts-managed) | [Bookmaker-managed](#bookmaker-managed) |
| -------- | --------------------------- | --------------------------------------- |
| `health` | —                           | Yes                                     |
| `auth`   | Yes                         | Yes                                     |
| `place`  | —                           | Yes                                     |

### Auth API format

The bookmaker defines HTTP paths, headers, and envelope; Next Bet maps them to the connector. Required semantic fields:

**Request**

| Field          | Type   | Description                                               |
| -------------- | ------ | --------------------------------------------------------- |
| `sessionToken` | string | Opaque punter session token (same value as on the widget) |

**Response (success)**

| Field      | Type   | Description                                            |
| ---------- | ------ | ------------------------------------------------------ |
| `punterId` | string | Stable punter identifier for placement and correlation |

No other response fields are required from the bookmaker for Next Bet. Balance, wallet, and profile data are out of scope for `auth` (see [Auth behaviour](#auth-behaviour)).

### Auth behaviour

- **When called:** immediately **before** Next Bet accepts or forwards a placement ticket (not when the widget receives `sessionToken`).
- **Request:** the punter token (same value as widget `sessionToken`).
- **Response:** punter **id** if valid, or an **error** if not.
- **Not in scope:** balance or wallet data.

### MTS-managed

#### When it applies

The bookmaker is (or becomes) an **MTS client**. Risk management, bet acceptance, and lifecycle orchestration run through Sportradar **MTS** using the
[Transaction 3.0 API](https://docs.sportradar.com/transaction30api).

#### Bookmaker deliverables

1. **MTS account** — confirm an existing MTS client relationship or create an MTS account with Sportradar.
2. **Transaction 3.0 integration** — connect the bookmaker trading stack to MTS per the official API documentation.
3. **Punter auth API** — expose an `auth` endpoint that Next Bet calls with the widget `sessionToken` **immediately before placement** and that returns a stable **punter id** (see
   [Auth API format](#auth-api-format)). Next Bet adapts the bookmaker's request/response format to the connector. Deliver the endpoint documentation as described in [Bookmaker API documentation](#bookmaker-api-documentation).

#### Flow (MTS-managed)

```mermaid
sequenceDiagram
    participant Widget
    participant SR as Sportradar_Next_Bet
    participant BookmakerAuth as Bookmaker_auth
    participant MTS as MTS_Transaction_3_0

    Widget->>SR: Place_ticket_with_sessionToken
    SR->>BookmakerAuth: auth
    BookmakerAuth-->>SR: punterId_or_error
    SR->>MTS: Ticket_via_Transaction_3_0
    MTS-->>SR: Acceptance_or_rejection
    SR->>Widget: Bet_status_over_WebSocket
```

### Bookmaker-managed

#### When it applies

The bookmaker is **not** on MTS. The bookmaker owns risk management, wallet, and the full bet lifecycle after a successful [`place`](#place-api-format). The bookmaker is responsible for wallet **settlement**, **cancellation**, and **rollback** using a **[UOF consumer](https://docs.sportradar.com/uof/introduction/overview)** on bookmaker infrastructure.

#### Required endpoints

| Endpoint | Required |
| -------- | -------- |
| `health` | Yes      |
| `auth`   | Yes      |
| `place`  | Yes      |

See [Bookmaker API documentation](#bookmaker-api-documentation) for the documentation the bookmaker must provide.

#### health

- **Request:** empty.
- **Response:** any successful response (for example HTTP `200` or `204`).

#### auth

Same behavioural contract as [Auth behaviour](#auth-behaviour); see [Auth API format](#auth-api-format).

#### place

- **When called:** after successful bookmaker [`auth`](#auth-api-format) in the same placement flow, when Next Bet must reserve funds / register the bet on the sportsbook side.
- **Request:** punter token (`sessionToken`), Next Bet–issued ticket and selection identifiers, stake, and fields per [Place API format](#place-api-format).
- **Bookmaker action:** persist the bet in the sportsbook; apply wallet rules.
- **Response:** transaction reference fields agreed in onboarding (for example transaction id and fee when applicable).

#### Place API format

Data Next Bet can send during bet placement (exact transport and envelope are agreed in onboarding):

| Field                      | Type    | Description                                                  |
| -------------------------- | ------- | ------------------------------------------------------------ |
| `ticketId`                 | string  | Next Bet–issued ticket identifier for this placement attempt |
| `punter.id`                | string  | Punter id from bookmaker `auth` in the same placement flow   |
| `punter.sessionToken`      | string  | Same opaque token as on the widget                           |
| `bet.stake.amount`         | integer | Stake in the smallest currency unit (for example, cents)     |
| `bet.stake.currency`       | string  | ISO currency code                                            |
| `bet.selection.eventId`    | string  | Event identifier for the selection                           |
| `bet.selection.marketId`   | string  | UOF market id (`218` for Next Point)                         |
| `bet.selection.outcomeId`  | string  | Selected outcome                                             |
| `bet.selection.specifiers` | string  | Market specifiers when present on the selection              |
| `bet.selection.odds`       | string  | Odds at placement time                                       |

Additional fields may be added as the contract evolves.

#### UOF consumer (bookmaker side)

The bookmaker must run a **UOF consumer** to:

- Apply **settlement** when markets result.
- **Cancel** bets when markets are voided or bets must be returned.
- **Rollback** and re-settle when UOF signals corrections.

This logic stays entirely on bookmaker infrastructure.

#### Flow (bookmaker-managed)

```mermaid
sequenceDiagram
    participant Widget
    participant SR as Sportradar_Next_Bet
    participant BookmakerAPIs as Bookmaker_APIs
    participant UOF as Bookmaker_UOF_consumer

    Widget->>SR: Place_ticket_with_sessionToken
    SR->>BookmakerAPIs: auth
    BookmakerAPIs-->>SR: punterId_or_error
    SR->>BookmakerAPIs: place
    BookmakerAPIs-->>SR: place_response
    SR->>Widget: Bet_status_over_WebSocket
    UOF-->>BookmakerAPIs: Resulting_and_market_updates
    BookmakerAPIs->>BookmakerAPIs: settle_cancel_rollback
    opt Optional_status_for_history
        BookmakerAPIs->>SR: Bet_status_for_history
        SR->>Widget: Punter_Bets_in_timeline
    end
```

***

## Betting history

By default, Next Bet shows **Betting History & Timeline** for authorized punters (match timeline plus a punter bet list). This is agreed with the bookmaker during integration. If the bookmaker does not want to share punter bet data, Sportradar disables it on the widgets license and the punter bet list is not shown.

How **Punter Bets** appear:

- **History disabled** (license flag off) — the frontend does not show the punter bet list. The match timeline does not include betting notifications. Panel bet status is unchanged. On [Bookmaker-managed](#bookmaker-managed), [bet status delivery](#bet-status-updates-for-history-and-timeline) is not required for the UI.
- **History enabled (default) + [MTS-managed](#mts-managed)** — Next Bet always ingests bet data from **MTS**; **Punter Bets** are shown in the Betting History.
- **History enabled (default) + [Bookmaker-managed](#bookmaker-managed)** — **Punter Bets** appear only if the bookmaker provides [bet status delivery](#bet-status-updates-for-history-and-timeline); otherwise see **History disabled** (license flag off).

### Disable punter bet history

Punter bet history is **on by default** and is agreed with the bookmaker during Next Bet integration. If the bookmaker does not want to share punter bet data, Sportradar disables it on the widgets license, and the punter bet list is not shown in the UI.

The **match/game timeline** in the history area can still be available; placement, live **bet status updates** in the betting panel, scoreboard, and court/AV are unchanged. On [MTS-managed](#mts-managed).

### Bet status updates for history and timeline

Applies to **[Bookmaker-managed](#bookmaker-managed)** when punter bet history is **enabled** (the license flag default). If the flag is off — see [Disable punter bet history](#disable-punter-bet-history) — this delivery is not needed for the UI. **[MTS-managed](#mts-managed)** integrations ingest **Punter Bets** from MTS regardless of the flag; the flag only controls whether they are shown on the frontend.

If the bookmaker provides current bet status (and related payout metadata), Betting History & Timeline can **include Punter Bets**. If not, those views **exclude Punter Bets** while other timeline content remains available.

**Delivery options (preferred first):**

1. **Webhooks** from bookmaker to Next Bet (batch updates preferred).
2. A **dedicated channel** (WebSocket, Kafka, or equivalent).
3. **A bookmaker API** Next Bet polls for all relevant Next Bet wagers.

**Expected data (high level):** enough to render history rows and timeline markers — bet identity, stake amount, current status, odds, and win/payout amounts when applicable (aligned with what Next Bet consumes for punter bet history).

***

## Optional features

**Live AV stream**

### AV stream (`jwt`)

Next Bet embeds **LMT Plus** for court visualization. Live video uses the same streaming JWT model as standalone LMT ([video streaming](https://apidocs.sportradar.com/resources/widgets/docs/lmt/lmt.md#video-streaming-lco)).

Pass a top-level **`jwt`** prop (not under `sportProps`) when the license includes live AV in the court view.

1. Confirm **AV entitlement** on the widgets license during Next Bet integration onboarding.
2. Share your RSA public key with Sportradar and sign JWTs **server-side** on the bookmaker backend — see [JSON Web Token (JWT)](https://apidocs.sportradar.com/resources/widgets/docs/tutorials/jwt.md).
3. Set token **`scope`** to include **`av`** (required for audio/video stream access in Live Match Tracker).
4. Pass the signed JWT from your page into `addWidget` or `updateWidget` when the punter should see the stream.

The widget does not issue or refresh JWTs; the bookmaker owns token lifetime and claims for the end user.

**Styling and theming**

### Theming

Court surface (hard, clay, grass) is applied automatically from tournament data. The widget uses internal CSS variables for colours; it does not use the
generic widgets `themingClass` pattern. For broader widget styling conventions, see [Widget Theming](https://apidocs.sportradar.com/resources/widgets/docs/tutorials/theming-widgets.md).

***

## Test and go live: tennis

Run these checks before serving punters in **production** (after Sportradar go-live sign-off).

| Step                      | Check                                                                                                                                                |
| ------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------- |
| Embed                     | Widget loads with licensed `clientId`, numeric `matchId`, `sportId: 5`                                                                               |
| Unauthorized              | Without `sessionToken`, markets visible; betting panel shows unauthorized state                                                                      |
| Sign-in                   | `onSignIn` runs from the unauthorized button; after `updateWidget` with token and required `punter`, the panel uses the supplied stake configuration |
| Invalid token             | Attempt placement with an expired/invalid token; auth rejection shows an inline error and invokes `onSignIn` when provided                           |
| Betting window            | Cannot place during an active rally; can place between rallies when UOF market is open                                                               |
| Place bet                 | Accepted bet appears in the panel; rejected bet shows a clear error (e.g. insufficient funds)                                                        |
| Panel bet status          | Win/loss/cancel bet status updates appear in the betting panel after the point is decided. Wallet settlement stays with the bookmaker or MTS.        |
| MTS path                  | Transaction 3.0 connectivity and bookmaker `auth` on production URLs                                                                                 |
| Bookmaker-managed APIs    | Next Bet can reach bookmaker `health`, `auth`, `place` on production URLs                                                                            |
| UOF (bookmaker-managed)   | Bookmaker UOF consumer processes settle/cancel/rollback locally                                                                                      |
| MTS history               | Punter Bets in the history UI come from MTS data when the license flag is on (default); ingest is independent of the flag                            |
| Bookmaker-managed history | Punter Bets appear with bookmaker status delivery; otherwise only match timeline remains                                                             |
| History disabled          | License flag off hides the punter bet list on the frontend without affecting panel status updates or MTS ingest                                      |
| Stake UI                  | Required stake settings supplied; any optional limits you pass appear in the panel                                                                   |
| UOF setting               | Next Point market offer has **Exclude the next point from the offer** switched off                                                                   |
| Match change              | With `sportProps.withMatches: true`, switching matches fires `onMatchChange`                                                                         |
| Logout / teardown         | `updateWidget` clears `sessionToken` and `punter`; `removeWidget` cleans up                                                                          |

***

## Reference

**Identifiers and match coverage**

## Identifiers and Data Sources

| Identifier     | Role                                                                                                                                                   |
| -------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `clientId`     | Widgetloader URL path; licensed widgets client                                                                                                         |
| `matchId`      | Target tennis match                                                                                                                                    |
| `sportId`      | `5` (tennis)                                                                                                                                           |
| `sessionToken` | Punter session token issued by the bookmaker; passed to the widget and validated via bookmaker [`auth`](#auth-api-format) immediately before placement |

**Nomenclature note:** widget `tournamentId` / `uniqueTournamentId` (on other widgets) map to `simpleTournamentId` / `tournamentId` in Sports API
responses. `immersiveBetting` only requires `matchId` at mount.

Match ids can be resolved from Sports API, Coverage Feed, UOF, or Mapping Feed depending on the integration scenario.

### `matchId` format

`matchId` is a **numeric** Sportradar match identifier (`PropTypes.number` in the widget). Resolve it via Sports API, Coverage Feed, UOF, or Mapping
Feed.

### Eligible matches

Next Bet targets **live tennis** with **Next Point** betting. Use a match that is in play and covered for immersive
betting; exact allowlists are confirmed during onboarding.

**Typical integration timeline**

### Typical timeline

| Step                | Description                                                                                                                         | Estimate                                            |
| ------------------- | ----------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------- |
| Kick-off            | Shared integration channel; `clientId`, session token contract; widgets license and Next Bet configuration                          | < 1 week                                            |
| Widget embed        | Widgetloader, `immersiveBetting` mount, `matchId` wiring, QA                                                                        | \~2–3 days                                          |
| Session integration | Bookmaker `sessionToken` issuance and `updateWidget` lifecycle                                                                      | Pre-auth: \~3–5 days · On-demand: \~5–7 days        |
| Integration model   | MTS account + Transaction 3.0 **or** bookmaker `health`/`auth`/`place` + UOF consumer                                               | Coordinate in kick-off; often parallel with session |
| Optional bet status | Webhooks, channel, or poll API for Punter Bets in history                                                                           | Add \~3–7 days depending on transport               |
| Optional AV stream  | AV license entitlement, [JWT](https://apidocs.sportradar.com/resources/widgets/docs/tutorials/jwt.md) (`av` scope) issuance, and QA | \~3–5 days                                          |
| Theming             | Automatic surface theme; optional page chrome around the widget                                                                     | \~1–2 days                                          |

Embed, session, and bookmaker API work can largely run in parallel. End-to-end integrations typically require **1–3 weeks** when session/auth and
bookmaker APIs already exist. Greenfield session tokens or new ticketing endpoints add time depending on the bookmaker's stack.
