Complete API reference for the Bet Concierge widget with detailed parameter descriptions.
| Property | Type | Required | Default | Description |
|---|---|---|---|---|
entityId | string | Yes | - | Sportradar entity identifier in sr:match:{id} format (e.g., "sr:match:50955863"). See Getting Identifiers. |
jwt getJwt | string function getJwt | Yes | - | User's JWT Token or a callback promise function that returns user's JWT Token for authentication. Either jwt or getJwt must be provided. |
numberOfSuggestedQuestions | number | No | 3 | Number of suggested questions (conversation starters) to display for each category. Range: 0-5. Set to 0 to hide suggestions entirely. |
isInline | boolean | No | false | When true, enables inline mode without close button. |
disableHeader | boolean | No | false | When true, hides widget header. |
disableHomeLink | boolean | No | false | When true, hides home navigation link in header. |
disableCoverage | boolean | No | false | When true, hides match coverage information. Coverage displays information about the data availability for the selected match and bet concierge capabilities in answering questions about that match. |
disableChatHistory | boolean | No | false | When true, disables chat history stored in local storage. Chat history is stored for each entityId separately with expiration time set to 1 day. |
termsPage | string | No | "hidden" | Controls terms page display. Options:
Terms and conditions page is meant to be displayed on the widget load. When user clicks on agree or decline buttons, AcceptTerms & DeclineTerms click actions are handled in the onAction function. Client is expected to handle these actions and show/hide 'termsPage' in the widget accordingly. |
enableTermsLink | boolean | No | false | When true, displays terms and conditions link |
enableCustomBet | boolean | No | false | Set this prop to true when implementing Custom Bet feature. This will enable calculateCbXml adapter call. |
enableInsights | boolean | No | true | When true, the widget will display insights on the start screen to users, providing them with valuable information and enhancing their engagement. |
enableMarketQuestions | boolean | No | false | When true, the widget will display AI-generated market based questions on the start screen to users, enhancing their engagement and interaction with the available betting options. |
globeIconStyle | "light" | "dark" | No | "light" | Visual style for the globe icon: "light" for light backgrounds, "dark" for dark backgrounds. |
onAction | function callback | No | Optional callback invoked when the widget needs your app to react (for example: close or hide the widget, handle terms, handle errors, or add a selection to the bet slip). See The onAction callback. |
Pass onAction function when you need to handle user events on bet concierge. The widget calls it with one argument: an object { type, data }.
type — Which category of event occurred. Use this in a switch (or equivalent) as the first branch.data — Payload for that event. The shape depends on type.Each time the widget invokes your callback, it passes an object with the following fields:
| Property | Type | Description |
|---|---|---|
type | 'Close' | 'Click' | 'Error' | 'AddSelectionsToBetSlip' | 'CustomBetAddToBetSlip' | High-level event category. See Action types. |
data | object | Payload for that category; interpret it together with type. |
type | When it fires | data shape |
|---|---|---|
'Close' | User closes the widget or declines terms (see data.source). | CloseBetConcierge or DeclineTerms |
'Click' | User clicks on one of the links or buttons in the widget. | ReadMoreTerms or AcceptTerms |
'Error' | Authentication or another recoverable widget error. | WidgetError |
'AddSelectionsToBetSlip' | User selects a suggested outcome (bet suggestion flow). | AddSelectionsToBetSlip |
'CustomBetAddToBetSlip' | User clicks Add to bet slip on a custom bet combo. | CustomBetAddToBetSlip |
Emitted when the user closes the widget from the header (X) button. Your integration should hide or unmount the widget (or navigate away), according to how you embedded it.
| Property | Type | Description |
|---|---|---|
source | 'CloseSolution' | Literal discriminator for this payload. |
{
source: "CloseSolution",
}Emitted when the user taps Decline on the terms screen. Treat it like a close action for your shell (hide the widget) and, if you track consent, record that terms were not accepted.
| Property | Type | Description |
|---|---|---|
source | 'DeclineTerms' | Literal discriminator for this payload. |
entityId | string | Sportradar match URN. |
{
source: "DeclineTerms",
entityId: "sr:match:123456",
}Emitted when the user opens Read more on the 'Terms and conditions' screen. Set the enableTermsLink prop to true if this link should appear.
| Property | Type | Description |
|---|---|---|
source | 'ReadMoreTerms' | Literal discriminator for this payload. |
entityId | string | Sportradar match URN. |
Example payload:
{
source: "ReadMoreTerms",
entityId: "sr:match:123456",
}Emitted when the user taps Agree on the 'Terms and conditions' screen. Persist consent in your app if required, then stop showing the terms screen by updating widget props (for example set termsPage to 'hidden').
| Property | Type | Description |
|---|---|---|
source | 'AcceptTerms' | Literal discriminator for this payload. |
entityId | string | Sportradar match URN. |
Example payload:
{
source: "AcceptTerms",
entityId: "sr:match:123456",
}Emitted when the widget reports an error (for example JWT failure). You can use error / details for logging.
| Property | Type | Description |
|---|---|---|
error | string | Summary message. |
details | string | Additional detail. |
Example payload:
{
error: "401 Error when requesting https://sportradar.com/status",
details: "Client token exception - Invalid token",
}Emitted when the user selects an outcome from AI-suggested markets (full integration with bet suggestion). Use the IDs to add the selection to your bet slip (or remove selection from bet slip - if selection is already in the bet slip).
| Property | Type | Description |
|---|---|---|
selections | SelectionOutcome[] | Outcome selection object |
Example payload:
{
selections: [
{
type: "uf",
event: "sr:match:123456",
market: "1",
outcome: "3",
odds: {
type: "eu",
value: "2.50",
},
},
];
}Emitted when 'Bet Combo' is enabled and the user adds a combo to the bet slip by clicking on 'Add to Betslip' button on the bet combo. Map selectedOutcomes into your bet slip.
| Property | Type | Description |
|---|---|---|
entityId | string | Sportradar match URN. |
displayedOdds | string | Combined odds for the combo. |
selectedOutcomes | array | Selections in the combo. |
selectedOutcomes.marketId | string | Sportradar market ID. |
selectedOutcomes.marketSpecifier | string (optional) | Market specifier, when applicable. |
selectedOutcomes.marketName | string | Market display name. |
selectedOutcomes.outcomeId | string | Sportradar outcome ID. |
selectedOutcomes.outcomeName | string | Outcome display name. |
Example payload:
{
entityId: "sr:match:61623782",
displayedOdds: "2.95",
selectedOutcomes: [
{
marketId: "1",
outcomeId: "1",
marketName: "1x2",
marketSpecifier: undefined,
outcomeName: "Ceuta",
},
{
marketId: "18",
outcomeId: "12",
marketName: "Total Goals",
marketSpecifier: "total=0.5",
outcomeName: "Over 0.5",
},
],
}onAction: function (action) {
const { type, data } = action;
switch (type) {
case "Close": {
if (data.source === "CloseSolution") {
// Hide or destroy the widget container (header close).
} else if (data.source === "DeclineTerms") {
// User declined terms; hide widget and optionally record non-consent.
}
break;
}
case "Click": {
if (data.source === "ReadMoreTerms") {
// Open your full terms URL.
} else if (data.source === "AcceptTerms") {
// Persist acceptance and set termsPage so the terms screen stays hidden.
}
break;
}
case "Error": {
// Surface data.error / data.details to the user or your logger.
break;
}
case "AddSelectionsToBetSlip": {
// Add data.selections to the bet slip.
break;
}
case "CustomBetAddToBetSlip": {
// Map data.selectedOutcomes to your bet slip (requires enableCustomBet).
break;
}
default:
// Optional: ignore or log unexpected types for forward compatibility.
break;
}
},Defines the structure of a callback promise function that retrieves a JWT token for user authentication. This function gets called when the Bet Concierge widget is initialized and when token refresh is needed.
// Example implementation of getJwt function:
function getJwt() {
return fetch("https://example.com/api/get-jwt/user123")
.then((response) => response.json())
.then((data) => data.token); // Must resolve to the JWT string - assuming backend returns { "token": "..." }
}This guide provides step-by-step instructions for integrating the Sportradar Bet Concierge widget into your website. It includes details about the required components, such as an adapter developed by Sportradar's engineering team, and options for custom theming. Following these instructions will help ensure a seamless integration and an improved user experience.
Before starting, ensure you have:
See Getting Identifiers for information on obtaining match IDs and authentication tokens.
The Bet Concierge widget can be integrated into your website using JavaScript. There are three levels of integration, each offering different features and requiring varying levels of development effort:
This is the simplest option and requires minimal development effort. It includes an interactive AI chat widget that can answer all stats-related queries.
Properties do not always transfer from the above table directly into integration code. Properties must be transformed differently for each integration method:
SIR() callcardVariant: "compact"In javascript integration, the properties go into an object which is passed as the 4th argument of the call ti SIR() function. Please see Global SIR API
data-sr- prefixcardVariant → data-sr-card-variantfilters.sport.hidden → Complex objects must be passed as JSON stringsIn HTML integration, the properties go into the parent HTML object as object properties, prefixed with data-sr- as explained above.
This method supports only simple (base) properties and does not support properties that require functions.
In all examples replace sportradar in the widgetloader URL path with your clientId.
Example if your clientId is client1:
https://widgets.sir.sportradar.com/sportradar/widgetloaderhttps://widgets.sir.sportradar.com/client1/widgetloaderAdd the widgetloader script to your HTML page:
<script>
(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/sportradar/widgetloader","SIR", {
language: 'en'
});
// Bet Concierge Widget
SIR('addWidget', '.sr-bc-widget', 'betConcierge', {
entityId: {ENTITY_ID},
jwt: "{JWT}"
});
</script>Replace sportradar in the widgetloader URL path with your clientId, ENTITY_ID with Sportradar entity identifier in sr:match:{id} format (e.g., "sr:match:50955863"), and JWT with your JSON Web Token.
JWT can be provided as string or a callback promise function that returns string with signed JSON Web Token.
async function getJwt() {
const response = await fetch("/api/get-token");
const data = await response.json();
return data.jwt;
}
SIR("addWidget", ".sr-bc-widget", "betConcierge", {
entityId: { ENTITY_ID },
getJwt: getJwt,
});Add a container element where the widget will be displayed:
<div class="bc-wrapper">
<div class="sr-bc-widget"></div>
</div>That's it! The Bet Concierge widget is now live on your page.
Now that you have integration working, check Theming customization for custom styling.