---
title: "Implementing the Flash Bet Adapter Endpoints"
canonical_url: "https://apidocs.sportradar.com/resources/widgets/docs/tutorials/examples/adapter-flash-bet-endpoint-example"
markdown_url: "https://apidocs.sportradar.com/resources/widgets/docs/tutorials/examples/adapter-flash-bet-endpoint-example.md"
last_updated: "2026-06-18T10:54:24Z"
---

# Implementing the Flash Bet Adapter Endpoints

## Intended Audience

- Developers implementing a custom adapter for Virtual Stadium
- Integrators managing real-time adapter communication between widgets and backend systems

## Goals

By completing this tutorial, you will:

- Understand the multi-step real-time flow of Flash Bet using modern adapter endpoints
- Implement the mandatory `matchEventSuggestedSelection` endpoint to receive live match events and suggest potential bets
- Implement either the `market` or `eventMarkets` endpoint to return localized markets/odds data
- Manage real-time odds updates, deactivations, and suspension states (e.g., during "bet stops") using active callbacks

## Prerequisites

Before implementing the Flash Bet-related endpoints, ensure you have:

- An active Sportradar Entity ID (`srEntityId`) managed and configured in your channel through the Moderation UI
- Access to the [Adapter Types documentation](https://apidocs.sportradar.com/resources/widgets/docs/adapter/Types.md) for detailed references

> **Info**
>
> Flash Bet uses a two-step real-time flow:
>
> 1. **`matchEventSuggestedSelection`**: Triggered when a match event occurs in the chat. The widget calls this to ask your adapter what specific market or outcome should be suggested to the user for this incident. This endpoint returns a selection definition (specifying the match `event`, `market` ID, optional `specifiers`, and optional recommended `outcome`).
> 2. **`market`** or **`eventMarkets`**: The widget takes the selection signature returned by `matchEventSuggestedSelection` and passes it directly as the request argument (`args.selection`) to resolve and subscribe to the actual market details (display names, active outcomes, outcomes' status, decimal odds, etc.) from `market` or `eventMarkets`.

***

## Overview

To fully support the Flash Bet UX, your custom adapter object implements:

1. **`matchEventSuggestedSelection`** (required) — Translates incoming match incidents (like goals, bookings, or tennis points) into potential market or outcome selections.
2. **Either `market` or `eventMarkets`** (required, mutually exclusive) — Supplies the active selections, outcome naming, and current odds to the Flash Bet UI, and provides the mechanism to push real-time status updates (like suspending or deactivating a selection to trigger a temporary suspension).

***

## Tutorial Steps

### Step 1: Register Your Adapter

Start by registering your adapter object using the global `SIR` function. Ensure only one adapter is registered per page load.

```javascript
const adapter = {
    endpoints: {
        // Endpoints will go here
    }
};

SIR('registerAdapter', adapter);
```

***

### Step 2: Implement matchEventSuggestedSelection

Add the `matchEventSuggestedSelection` endpoint to suggestion list. This endpoint receives the incident's metadata via `args` and returns structured market selections.

```javascript
const adapter = {
    endpoints: {
        matchEventSuggestedSelection: (args, callback) => {
            // args example:
            // {
            //   matchEvent: { type: "GAME_WON", metadata: { set_number: 1 } },
            //   event: { event: "sr:match:12345", type: "uf" },
            //   widget: "flashBet",
            //   channelId: "ATP_02.11.25_player1_vs_player2"
            // }

            const { matchEvent, event } = args;
            
            // Custom sport/event routing logic
            // Assuming event.sport or channel metadata is known. Here is illustrative branching:
            if (matchEvent.type === "GAME_WON" && matchEvent.metadata?.set_number === 1) {
                // Suggest Next Game Winner - Set 1 (Market ID 202, for example)
                callback(undefined, {
                    selections: [
                        { event: event.event, market: "202", specifiers: "setnr=1", type: "uf" }
                    ]
                });
            } else if (matchEvent.type === "GOAL") {
                // Suggest Next Team To Score (Market ID 18, for example)
                callback(undefined, {
                    selections: [
                        { event: event.event, market: "18", type: "uf" }
                    ]
                });
            } else {
                // No specific suggestion, return empty or fallback
                callback(undefined, { selections: [] });
            }

            return () => {
                // Cleanup logic if subscribing to an external suggestions stream
            };
        }
    }
};
```

***

### Step 3: Implement Market-fetch (Choose One)

The selections returned in Step 2 are resolved and rendered using either the `market` endpoint or the `eventMarkets` endpoint. **Do not implement both.** Choose based on your API capability and layout:

- **Option A (`market` + `availableMarketsForEvent`)**: Implement this if your API serves market data and odds based on specific market/selection IDs (and specifiers), allowing subscription to individual markets.
- **Option B (`eventMarkets`)**: Implement this if your API only serves market data and odds on an event level, returning all markets for the entire event ID in a single payload.

#### Option A: Implement `market`

Choose this option if your system's API allows fetching and subscribing to updates by specific market/selection IDs.

```javascript
const marketCallbaks = {};

const adapter = {
    endpoints: {
        market: (args, callback) => {
            // args example:
            // {
            //   selection: { event: "sr:match:12345", market: "202", specifiers: "setnr=1", type: "uf" },
            //   language: "en",
            //   oddsType: "eu"
            // }
            const { event, market, specifiers } = args.selection;
            const key = `${event}:${market}:${specifiers || ''}`;

            // Save callback to push real-time updates / suspensions later
            marketCallbaks[key] = callback;

            // Fetch odds from backend
            fetchMarketOdds(event, market, specifiers, (error, data) => {
                if (error) {
                    return callback(error);
                }

                // Transform custom odds to MarketResponse format
                callback(undefined, {
                    market: {
                        id: market,
                        name: "Next Game Winner - Set 1",
                        status: "active",
                        outcomes: [
                            { id: "1", name: "Player A", status: "active", odds: { type: "eu", value: String(data.oddsA) } },
                            { id: "2", name: "Player B", status: "active", odds: { type: "eu", value: String(data.oddsB) } }
                        ]
                    },
                    event: event,
                });
            });

            // Return unsubscribe cleanup function
            return () => {
                delete marketCallbaks[key];
            };
        }
    }
};
```

#### Option B: Implement `eventMarkets`

Choose this option to supply and update markets for the entire match fixture collectively.

```javascript
const eventMarketsCallbacks = {};

const adapter = {
    endpoints: {
        eventMarkets: (args, callback) => {
            // args example:
            // {
            //   selection: { event: "sr:match:12345", type: "uf" },
            //   language: "en",
            //   oddsType: "eu"
            // }
            const { event } = args.selection;
            eventMarketsCallbacks[event] = callback;

            fetchActiveMarketsForEvent(event, (error, marketsData) => {
                if (error) {
                    return callback(error);
                }

                callback(undefined, {
                    event: event,
                    markets: marketsData.map(m => ({
                        id: m.id,
                        name: m.name,
                        specifiers: m.specifiers,
                        status: m.status, // "active" | "suspended" etc.
                        outcomes: m.outcomes.map(o => ({
                            id: o.id,
                            name: o.name,
                            odds: { type: "eu", value: String(o.oddsDecimal) },
                            status: o.isActive ? "active" : "deactivated"
                        }))
                    }))
                });
            });

            return () => {
                delete eventMarketsCallbacks[event];
            };
        }
    }
};
```

***

### Step 4: Handle Real-Time Suspensions & Bet Stops

If a match incident occurs that pauses play (like a goal revision or court medical timeout) right before outcomes resolve, you should suspend the active Flash Bet to prevent users from placing invalid bets.

By default, the suspension is held in the UI for **65 seconds** (configurable in your Moderation UI settings). To trigger this state, execute your active endpoint callback with an updated market status.

#### Example: Push Suspension Update (Using Market Callback)

```javascript
// Retreive active callback saved during step 3 Option A
const key = "sr:match:12345:202:setnr=1";
const activeCallback = marketCallbaks[key];

if (activeCallback) {
    // Notify widget that the market is suspended
    activeCallback(undefined, {
        market: {
            id: "202",
            name: "Next Game Winner - Set 1",
            status: "suspended", // Tells Flash Bet to enter a Bet Stop state
            outcomes: [
                { id: "1", name: "Player A", status: "suspended", odds: { type: "eu", value: "1.85" } },
                { id: "2", name: "Player B", status: "suspended", odds: { type: "eu", value: "2.10" } }
            ]
        },
        event: "sr:match:12345"
    });
}
```

#### Example: Push Deactivation Update (Counts down but disables clicking)

If you wish to keep the flash bet Timer active but temporarily lock outcomes from being clicked, update outcome status parameters to `"deactivated"` or set the market status to `"deactivated"`.

```javascript
if (activeCallback) {
    activeCallback(undefined, {
        market: {
            id: "202",
            name: "Next Game Winner - Set 1",
            status: "deactivated", // Countdown stays active, outcomes disabled
            outcomes: [
                { id: "1", name: "Player A", status: "deactivated", odds: { type: "eu", value: "1.85" } },
                { id: "2", name: "Player B", status: "deactivated", odds: { type: "eu", value: "2.10" } }
            ]
        },
        event: "sr:match:12345"
    });
}
```

***

## Response Formatting Specifications

For reference, inspect the type definitions inside your [Adapter API reference](https://apidocs.sportradar.com/resources/widgets/docs/adapter/Types.md):

### MatchEventSuggestedSelectionResponse

| Property     | Type          | Description                                            |
| ------------ | ------------- | ------------------------------------------------------ |
| `selections` | `Selection[]` | Array of suggested outcome or market selection objects |

```json
{
  "selections": [
    {
      "event": "sr:match:12345",
      "market": "202",
      "specifiers": "setnr=1",
      "type": "uf"
    }
  ]
}
```

***

## Next Steps

- Check the [Adapter API Types documentation](https://apidocs.sportradar.com/resources/widgets/docs/adapter/Types.md) for robust schema definitions
- Review the frontend configuration options in the [Flash Bet Widget Guide](https://apidocs.sportradar.com/resources/virtual-stadium/docs/web/widgets/virtualStadium/features/flashBet.md) to customize display duration timers
