> For the complete documentation index, see [llms.txt](https://docs.sportradar.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.sportradar.com/nextgen-igaming/ignite/sportsbook-frontend-api-integration.md).

# Sportsbook Frontend API Integration

## 1. About

This document will summarize the APIs needed to implement the UI for the NextGen Sportsbook and describe some specific use cases.

Backend (PAM-PAM) implementation is documented within iGNITE 4 B2B Operators, PAMs & iGaming Platforms and this document serves for operators that want to build their own UI from start to finish.\
​\
Services that are necessary to implement your own UI are:\
\- **Distribution HTTP API** needed to display all sports, categories, tournaments, and ultimately events that can be added to the betslip\
\- **Distribution ASYNC API** real-time updates of distribution data.\
\- **Betslip HTTP API** for calculating winnings, placing bets, and previewing placed bets will be described.\
\- **Betslip ASYNC API** for receiving information regarding betslip placement status.

<figure><img src="https://3839004948-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FDkauK0C2WfKWZ6elg1ZV%2Fuploads%2FpARplUbE7M4biwHIVdcm%2F1.png?alt=media&amp;token=ce2fb1f0-5d3f-43ff-ad99-f53aeedae023" alt=""><figcaption></figcaption></figure>

## 2. Distribution HTTP API

📌&#x20;[Offer Distribution HTTP OpenAPI Specification](https://aio-offer-distribution.staging.de-2.nsoft.cloud/docs/swagger-ui/index.html#/Offer%20ID%20exchange%20routes/offer-id-exchange) \[Credentials available on demand]\
​\\

Chapters below describe necessary sections from the OpenAPI documentation for the purpose of creating the UI for the Sportsbook application. The sections will be described according to an arbitrary position, taking into account the default NSoft Web application.

### 2.1. Offer statistics

The API that we believe should be accessed first is "Offer statistics". These endpoints are used to retrieve all types of statistics, as well as metadata of entities such as sports, categories, tournaments, and tournament rounds. In addition to this data, the number of events for each of the previously mentioned entities will also be available here. All mentioned data will be fetched for a specific date range that’s provided in query parameters.

### 2.2. Paged offer

Paged offer endpoints are used to fetch events for a specific period. Besides events, this response also includes metadata such as sports, categories, tournaments, and tournament rounds. It should be noted that the provided metadata only pertains to the events fetched in this response.

\
It is also important to note that through query parameters, it is possible to define which metadata are already known to the client application, and these will be omitted in the response, which can affect the size of the response and ultimately the response speed.

\
Pagination works on the principle of a cursor, where the API user defines how many events they want to fetch, and on the first load, they fetch the /offer/cursors route, which, in addition to event data, also returns a cursorId, which must be sent in all subsequent requests using the route /offer/cursors/$cursorId. Based on the cursor&#x20;id value, the service will calculate which events have been delivered up to that point and deliver new x events on the next request. Each response from /offer/cursors/$cursorId returns a new cursor id that must be sent on the next request.

\
❗ The number of delivered events can be greater than the requested number because the API always returns all events of one tournament.

### 2.3. Offer ID exchange

The previously described API (Paged offer) uses so-called "Synthetic ID" for all id values in its response, and this ID can be used in all distribution requests.\
However, if any of the IDs (event id, tournament id, market id, outcome id) are needed to fetch data from the API for the betslip, the core id must be sent, which is not available in the paged offer response.

\
This is where the Offer ID exchange API comes in, which returns the Core or UOF id for a given synthetic id (check the OpenAPI documentation to see which query parameter is used to defi ne this type). The Core ID is needed if you want to work with the betslip API, while the eg UOF id can be used for some SportRadar widgets, such as Live Match Tracker, Bet Assist, or BetRadar Statistics.

### 2.4. Offer

This endpoint can be considered a combination of the Offer statistics and Paged offer endpoints, where all metadata and events can be fetched in one response. This might be a simpler version of the data to use; however, it does not support cursor pagination, so this response can be quite large, which can result in slower requests and, consequently, slower application load times.

\
It should also be noted that this section includes the route /offer/events/$listOfEventIds, which can be used if data for only one event is needed (for example, an Event View display) or x events if data is needed for only specifi c events for a smaller section of the Offer.

### 2.5. Favorites

This section of the endpoint is identical to the paged offer endpoint, except that it supports an additional query parameter for events, tournaments, sports and categories, based on which the API delivers all active events that belong to that meta entity. The reason is that on the client UI application, there may be a need to mark the entire tournament as a favorite. Storing of favorite events and tournaments will be described in another section

### 2.6. Recommended offer

Endpoint is used to fetch events that utilize an AI recommendation system in to generate recommended events based on the provided punter id. The response and structure of the endpoint are identical to that of the paged offer.

## 3. Distribution async API (websockets)

{% file src="/files/Dk7LUwJ2daUAViCAPzuf" %}

For all metadata as well as events, there is real-time update support. This includes changes in the status of each entity, changes in names, positions, etc., as well as the deletion or addition of a new entity. Besides entity updates, this Async API also delivers changes to the event markets and outcomes, including odds value.

## 4. Betslip proxy service

**Betslip Proxy Service** uses a WebSocket connection to perform real-time calculations that are presented to the player on the betslip prior to bet placement.

The service is responsible for handling the majority of the calculation logic associated with selections added to the betslip, including:

* Potential winnings
* Total odds
* Betting limits
* Applicable bonuses
* Taxes

By performing these calculations through a persistent WebSocket connection, the service provides the player with up-to-date betslip information before the bet is submitted.

<https://aio-client-proxy.de-2.nsoft.cloud/docs/asyncapi/betslip-calculation> \[Credentials available on demand]

{% file src="/files/DUAf7mIICfk2QX4ia33Q" %}

## 5. Betslip HTTP API

Betslips are placed using POST /tenants/{tenantUuid}/betslips. All required headers and Once a ticket is placed, its status can be retrieved by GET /tenants/${tenantUuid}/betslips/requestUuids/${requestUuid}.&#x20;

Besides HTTP bet check, information about bet placement can be received in real time using [Betslip ASYNC API](#id-6.-betslip-async-api-websockets).&#x20;

For the client application to receive real-time updates on the status of a placed bet, it needs to subscribe to the notification system for bets. This is done using the socket.io library, and detailed documentation can be found at the Betslip Async API (Websockets) chapter.&#x20;

All other methods are documented via the provided Open Api spec.

{% file src="/files/BADb7JN56W4EczF7HAFU" %}

## 6. Betslip async API (Websockets)

For the client application to receive real-time updates on the status of a placed bet, it needs to subscribe to the notification system for bets. This is done using the socket.io library.&#x20;

Betslip API will respond with a socket message about betslip placement status. Since Betslip contains can contain multiple bets, each Bet will have its own placement status which can be:

\- PLACED&#x20;

\- REJECTED

Connection example

```javascript
const socketConnection = io(${baseDistUrl}, {
    path: "/client/distribution/sio",
        query: {
        playerId: "01ARZ3NDEKTSV4RRFFQ69G5FAV"
    },
    transports: ["websocket"],
    auth: {
        token: "$tokenValue",
    }
});
```

### 6.1. Message types

#### 6.1.1. placementResult

Result of placement action

Payload example

{% code expandable="true" %}

```javascript
{
  "reqUuid": "550e8400-e29b-41d4-a716-446655440000",
  "betslipId": "1",
  "bets": [
    {
      "betId": "1",
      "status": "PLACED",
      "winnings": [
        {
          "type": "MIN",
          "win": 5,
          "total": 5
        },
        {
          "type": "MAX",
          "win": 5,
          "total": 5
        }
      ],
      "payin": {
        "stake": 1,
        "totalStake": 1
      },
      "datetimes": [
        {
          "phase": "PREPARED",
          "value": "2024-06-05T07:50:29.000Z"
        },
        {
          "phase": "PLACED",
          "value": "2024-06-05T08:36:23.301Z"
        }
      ]
    }
  ]
}
```

{% endcode %}

## 7. Cashout

Flow:

* Connect to cashout websocket with player's token (acquired from punter-exchange-token)
* send GET request to `/bet-profiles`. The response contains a list of bets available for cashout
* send POST request to `/bet-profiles/status` with payload containing betProfile IDs (*BetProfileStatus*). This subscribes the selected bets for cashout calculation updates.
* Once subscribed, the client will receive `calculationResult` messages containing information about whether cashout is currently available for each bet and, if available, the exact cashout amount (*CalculationResult*).
* The cashout amount and status need to be updated as soon as new `calculationResult` message for specific bet is received
* Submitting cashout request is done by sending POST request to `/bet-profiles/{{betProfileId}}` with requested amount (*BetProfileRequest*)

\
*BetProfileStatus*

```json
[
  {
    "betProfile": {
      "id": "01K76P2R2G74AWYXXM7ZN8BGFN"
    }
  },
  {
    "betProfile": {
      "id": "01K6MG7SPS7FDDH2TWD9WTR89Y"
    }
  }
]
```

*CalculationResult*

```json
{
  "allowed": true,
  "betProfile": {
    "id": "01K76P2R2G74AWYXXM7ZN8BGFN",
    "bet": {
      "id": "01K76P2QVMBZ8K86G62988DS3Y",
      "winnings": {
        "bonuses": [],
        "total": 1.9
      }
    }
  },
  "reasons": []
}
```

*BetProfileRequest*

{% code expandable="true" %}

```json
{
  "bet": {
    "winnings": {
      "win": "3.28",
      "bonuses": [],
      "total": 3.28
    }
  },
  "punterSettings": {
    "oddsChange": "HIGHER"
  }
}
```

{% endcode %}

## 8. Custom bet

**Custom Bet API** provides endpoints for retrieving selections available for combining on the same event and calculating the combined odds for a set of selected outcomes.

It exposes two main operations:

* **Selections** – Retrieves the event markets and outcomes available for combining in a Custom Bet.
* **Calculation** – Calculates the resulting odds and probability based on the selected event market outcomes.

{% file src="/files/fWhrq6xspUt1SYuvHGW4" %}

## 9. Login

Login flow consists of two consecutive API calls: **Login** and **Punter Token Exchange**.

First, the client calls the `/login` endpoint to authenticate the player. The response provides an **access token**, which is then used to call `/punter-token-exchange` with the required payload.

&#x20;`punter-token-exchange` response contains two important properties:

* **`accessToken`** — the token that must be used for subsequent Betslip API actions.
* **`expiresIn`** — the token validity period, expressed as the token's expiration interval.

To keep the session active, the client should use `expiresIn` to determine when the current token is about to expire and call `/punter-token-exchange` **a few seconds before expiration** to obtain a new access token. This token renewal process can be repeated throughout the session without requiring the player to log in again.

To decode JWT token you can use <https://www.jwt.io/>.

{% file src="/files/kODyN4KyH0JnwblTFLmM" %}

## 10. Bets list

**Bet List API** provides a single entry point for retrieving a player's betting history and bet-related data. It allows clients to retrieve bets for a specific player and apply a wide range of filters, including placement, settlement and payout time ranges, bet type, status, resolution status and other bet attributes.

The API supports pagination and sorting to efficiently retrieve and present large sets of bets. In addition to the core bet information, each returned bet can include its selections, event and market details, odds, stake and payout information, resolution statuses, origin information, cashout details, bonuses...

The API is exposed through a single `GET` endpoint described in OAS below.

{% file src="/files/JTNlttFY4AI1v8iZmbtT" %}

## 11. Expression language SDK

System allows setting dynamic expressions in entity (market, outcome...) names so frontend application can receive names in following format:

* &#x20;{{E.C1.NAME}} to win a set
* {{M.S.SET\_NUMBER}}. set {{M.S.GAME\_NUMBER}}. game - Winner

These expressions should be parsed and placeholders replaced with proper special values .

To install the Expression Language package, configure your `.npmrc` file to use the Sportradar's GitHub Package Registry and include your Personal Access Token (PAT) for authentication.

> Note: GitHub requires authentication for all packages, regardless of whether they are public or private. Ensure that your PAT includes the appropriate scopes (such as `read:packages`) for accessing packages.

Use the following one-liner to update your `.npmrc` file and install display-name SDK:

```
echo "//npm.pkg.github.com/:_authToken=${NPM_GITHUB_TOKEN}"$'\n'"@nsftx:registry=" >> .npmrc

npm install @nsftx/sports-client-aio-display-name-sdk
```

> Note: Please make sure the environment variable `NPM_GITHUB_TOKEN` is defined and contains a valid PAT.

Example:

```javascript
import { Supplemental } from '@nsftx/sports-client-aio-display-name-sdk';

const supplemental = new Supplemental();

// Mock data
const supplementalId = 1; // Supplemental name you're willing to use. If going without supplementals, specify `null`.
const market = {
  ...eventMarket, // the `eventMarket` node in full
  name: 'Xth set - Winner',
  eventMarketName: '{{M.S.SET_NUMBER}}. set - Winner', // expression formula
}
const event = offer.event; // Entire event node from distribution

const output = supplemental.getMarketSupplementalName(
  supplementalId, 
  market, 
  event,
);

console.log('expression language output', output);
```

## 12. Service base URLs

| Service                   | Staging                                                                                                                                | Production                                                                                                              |
| ------------------------- | -------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------- |
| Login                     | <p><code><https://svn-sxg-womb-bigi.staging.de-2.nsoft.cloud/tenants></code><br><mark style="color:$info;">providerId: 4340</mark></p> | <p><code><https://sxg-womb-bigi.de-2.nsoft.cloud/tenants></code><br><mark style="color:$info;">providerId: 3</mark></p> |
| Distribution HTTP         | `https://aio-offer-distribution.staging.de-2.nsoft.cloud/tenants`                                                                      | `https://aio-offer-distribution.de-2.nsoft.cloud/tenants`                                                               |
| Distribution WSS          | `wss://aio-offer-distribution.staging.de-2.nsoft.cloud`                                                                                | `wss://aio-offer-distribution.de-2.nsoft.cloud`                                                                         |
| Betslip HTTP              | `https://aio-betslip-rest.staging.de-2.nsoft.cloud/api/v1/tenants`                                                                     | `https://aio-betslip-rest.de-2.nsoft.cloud/api/v1/tenants`                                                              |
| Betslip WSS               | `wss://aio-betslip-distribution.staging.de-2.nsoft.cloud`                                                                              | `wss://aio-betslip-distribution.de-2.nsoft.cloud`                                                                       |
| Betslip Proxy Service WSS | `wss://aio-client-proxy.staging.de-2.nsoft.cloud`                                                                                      | `wss://aio-client-proxy.de-2.nsoft.cloud/`                                                                              |
| Bet List HTTP             | `https://aio-bet-list-rest.staging.de-2.nsoft.cloud`                                                                                   | `https://aio-bet-list-rest.de-2.nsoft.cloud`                                                                            |
| Cashout HTTP              | `https://aio-cashout.staging.de-2.nsoft.cloud/tenants`                                                                                 | `https://aio-cashout.de-2.nsoft.cloud/tenants`                                                                          |
| Cashout WSS               | `wss://aio-cashout-distribution.staging.de-2.nsoft.cloud`                                                                              | `wss://aio-cashout-distribution.de-2.nsoft.cloud`                                                                       |
| Custom Bet HTTP           | `https://aio-custom-bet-rest.staging.de-2.nsoft.cloud/api/v1/tenants`                                                                  | `https://aio-custom-bet-rest.de-2.nsoft.cloud/api/v1/tenants`                                                           |

## 13. How we’ve done it

Building your own UI means you are opinionated about how your frontend will look like. And while any API allows you to be as creative as you like, we are providing insight in how API’s provided correlate to one of our own fronted designs.

\
Please find working solution available at following [link](https://staging.sports-aio-web.7platform.net/sports?tenantId=0c17fe55-315e-4ee0-b4f6-1364c8557dd1\&currency=eur\&language=en\&externalId=dctest\&feToken=c\&platform=aio\&standalone=true).

\
Images below depict correlation of distribution HTTP APIs with our own UI:

<figure><img src="https://3839004948-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FDkauK0C2WfKWZ6elg1ZV%2Fuploads%2F4CJN5E9vnA0SsLxJ7C5Y%2F2.png?alt=media&amp;token=ebfe5150-d079-4b23-9904-dcbe081e4f9e" alt=""><figcaption></figcaption></figure>

<figure><img src="https://3839004948-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FDkauK0C2WfKWZ6elg1ZV%2Fuploads%2FyVXK84dp005WbKcHefex%2F3.png?alt=media&amp;token=bdd3c8bf-e397-403b-a56e-648895189fc2" alt=""><figcaption></figcaption></figure>

<figure><img src="https://3839004948-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FDkauK0C2WfKWZ6elg1ZV%2Fuploads%2FVFwlZ2lOZmDoN5Yp1ZbB%2F4.png?alt=media&amp;token=56ba3680-ce62-44ef-b6fd-6c874471040d" alt=""><figcaption></figcaption></figure>

<figure><img src="https://3839004948-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FDkauK0C2WfKWZ6elg1ZV%2Fuploads%2FcwefCTnBFcDCO225I76t%2F5.png?alt=media&amp;token=5928a59e-d6cf-4178-a880-456ccf887c4f" alt=""><figcaption></figcaption></figure>


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://docs.sportradar.com/nextgen-igaming/ignite/sportsbook-frontend-api-integration.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
