# Welcome to Odds88

Your ultimate sports data provider

This document serves as a comprehensive guide outlining the seamless integration process with Odds88. It assumes that a kick-off call has been conducted, and both parties have mutually agreed to proceed with the integration.

Upon the commencement of the integration, an Odds88 Technical Integration Specialist (TIS) will be assigned to provide dedicated support throughout the entire integration process. The TIS will assist you in all aspects of the integration, from initiation to completion. During and after the integration, the TIS will conduct tests to ensure the integration’s smooth progression and to identify any potential issues.

As integration approaches completion, risk management and limit configuration will be undertaken by an Odds88 Operational Account Manager (OAM).

Integrating with the Odds88 feed entails establishing a consistent connection to various data providers via our API. Since Odds88 functions as a feed aggregator, we receive data feeds from diverse providers and consolidate them to guarantee an efficient and seamless data flow for you.


# Integration Process

The integration process is multifaceted, with certain applications or parts of the integration dependent on the implementation of others. To manage this complexity, it is beneficial to divide the integration into stages, providing a clear overview of progress and identifying pending steps.

Recommended flow of the integration process

1. **Delta feed**
   * Establish connection with Odds88 websocket delta feed
   * Process and store messages
   * Populate database
2. **Metadata feed**
   * Establish connection
   * Process and store messages
   * Forward to Front-End
   * Reconnection should be automatically handled by integration.
3. **Bet placement**
   * Create a player database.
   * Implement Odds88 bet placement endpoints.
   * Test if it is possible to send bet placement requests
   * Compare returned values with the ones in your database
4. **Settlement feed**
   * Establish connection
   * Process message and apply settlement results.
   * Forward to Front-End
   * Reconnection should be automatically handled by integration.
5. **Translation feed**
   * Establish connection
   * Process message
   * Call corresponding endpoint to update translation
   * Save new translation to database

<figure><picture><source srcset="/files/otiMnmbXoUW9hRhzBTFk" media="(prefers-color-scheme: dark)"><img src="/files/SK0GrAec2gprsvc2BJuq" alt=""></picture><figcaption></figcaption></figure>


# Credentials

The first step for integration is creating credentials for Odds88 API, which will authorise access to the feed and API.

To grant complete access to API endpoints it is needed to whitelist IP addresses, used by you to access the link for development and integration purposes.

Once the credentials are provided you should have access to our API swagger to see the structure of the data. We will provide you with your own instance of the API that has a unique URL.


# Recommended integration flow

There is a recommended method for integrating Odds88 services.\
Not all steps need to be followed, and not all services need to be integrated.\
\
Odds88 offers multiple distinct feeds, each supported by additional or complementary REST API endpoints.\
Each feed integration should be managed as a separate service and should operate independently of other feed integrations.


# Feeds

We recommend storing a snapshot of received information in a cache or database on your side as well as storing revision for recovery. In case of recovery you will only receive snapshots for data which have changed after the specified revision which means that old finished events may not be recovered.

One message in the feed can have multiple deltas, which should be consumed in ascending order of revision number, otherwise event(s) may have incorrect status.

Feed recovery from 0 revision should happen as rarely as possible. It is a slow process which consumes a lot of resources.

Each feed should be considered as a **separate entity/integration**. They can become not accessible or drop connection independently from each-other so we don’t recommend starting full system recovery in case of some specific feed disconnected.

Feeds **are not synchronised** with each-other meaning that some information may become available from one feed and arrive with delay from another feed.

Example: event metadata can arrive through metadata feed before the event actually sent through delta feed.

The integration involves connecting to four essential feeds:

1. **Delta Feed**

* The most critical feed, providing essential information such as event fixtures, event changes, markets, and scoreboards.

{% content-ref url="/pages/m9v7kc9cRus7EPCVt3g0" %}
[Delta Feed - New Version](/integration-process/recommended-integration-flow/delta-feed-new-version)
{% endcontent-ref %}

2. **Metadata Feed**

* Supplies event-specific metadata, particularly useful for racing sports (e.g., horse racing, harness racing, greyhound racing).

{% content-ref url="/pages/HjCugoE6BZ6tHCAEI1Sg" %}
[Metadata Feed](/odds88-client-api/odds88-feeds/metadata-feed)
{% endcontent-ref %}

3. **Ticket Settlement Feed**

* Provides bet settlements on ticket level.

{% content-ref url="/pages/pCOsbPzku2QUbexzwct0" %}
[Settlement Feed](/odds88-client-api/odds88-feeds/settlement-feed)
{% endcontent-ref %}

4. **Translations Change Feed**

* Notifies you about changes in our translation data.
* Can be used in pair with our translation API endpoints to keep the data in sync.

{% content-ref url="/pages/TqkGvEKMYF8mpmNGgDt9" %}
[Translation Change Feed](/odds88-client-api/odds88-feeds/translation-change-feed)
{% endcontent-ref %}


# Delta Feed - New Version

{% content-ref url="/pages/JFJGQOsTKFaOcUqyg9Um" %}
[Delta Feed - New Version](/odds88-client-api/odds88-feeds/delta-feed-new-version)
{% endcontent-ref %}

We introduce a few changes that need to be considered in the new odds feed version which will become the main feed in the future.

## Changes:

### New & Deprecated Fields

New Fields

* **UpdateSequence -** Incremental sequence number for each delta message of an event
* **LastUpdatedTime -** Unix timestamp in seconds

Deprecated Field

* **Version -** Previously used as a recovery identifier. Now replaced by **UpdateSequence** and **LastUpdatedTime**. The old recovery logic required to reconnect using the last received versio&#x6E;**.**\
  This field is now **deprecated**.

### **New Recovery Logic** <a href="#id-2.-new-recovery-logic-using-lastupdatedtime" id="id-2.-new-recovery-logic-using-lastupdatedtime"></a>

Every delta now contains **LastUpdatedTime**, which acts as the recovery marker.

When reconnecting, its required to send the latest processed value: **revision={LastUpdatedTime}**

Odds88 will **resend all missed updates** from that timestamp to ensure catching up to the latest event state.

### **Initial Connection**

For the first-time connection, the **revision** parameter is optional.\
However, we recommend sending a **Unix timestamp for the last 1 hour** to reduce load on both sides:

* Prevents returning excessive historical data
* Ensures smoother bootstrapping process

### **UpdateSequence Behaviour & Requirements** <a href="#id-3.-updatesequence-behavior-and-client-requirements" id="id-3.-updatesequence-behavior-and-client-requirements"></a>

**UpdateSequence** increments by **1** for every delta message of **single event**.\
Expected Behaviou&#x72;**:**

* If the last received value is **12**, the next should be **13**
* Duplicate values may rarely occur and should be accepted: e.g. **12**, and next message again **12** which should be reprocessed.

**Missing Update Detection**

If there was a gap in the update sequence (e.g., 12 → 15) and the last received message **was not** a snapshot **(type=6)** it indicates that some deltas might have been missed and full **event snapshot** request from the API is required.

### **Recovery Stream Behaviour** <a href="#id-4.-recovery-stream-behavior" id="id-4.-recovery-stream-behavior"></a>

During recovery:

* The first recovery message is typically **type=6** (EventSnapshotDelta)
* Its required to **drop deltas** with an UpdateSequence **lower** than stored value

Example 1:\
Stored sequence = 10\
During recovery the first received message is: UpdateSequence = 15, type = 6\
This is acceptable - its a snapshot and **event snapshot** from API **is not required**.\
\
Example 2:\
Stored sequence = 10\
The first received message is for an event is: UpdateSequence = 15, type = 3\
This is not acceptable - not a snapshot and **it is required** to request event snapshot from API.\
\
Example 3:\
Event is missing from storage and the first received message for missing event is: UpdateSequence = 15, type = 3\
This is not acceptable - not a snapshot and **it is required** to request event snapshot from API.

{% hint style="warning" %}
If event is missing from storage but event snapshot was received during recovery then API request is not needed.
{% endhint %}

### **Heartbeat Support** <a href="#id-5.-heartbeat-support" id="id-5.-heartbeat-support"></a>

The new endpoint supports heartbeat messages so it's possible to differentiate idle periods from technical issues.

**Heartbeat Timing**

* Heartbeat every **10 seconds**
* Expected flow: Delta **or** Heartbeat message

**Connection Timeout Rules**\
If there is no delta **or** heartbeat messages received for 30 seconds then it's required to close current connection and reconnect using **LastUpdatedTime** from last processed message.\
Our system closes stale connections automatically.

### **Message Wrapper Structure** <a href="#id-6.-message-wrapper-structure" id="id-6.-message-wrapper-structure"></a>

All messages (deltas or heartbeats) are wrapped in the following structure:

```json
{
  "Payload": "Nullable<DeltaDto>",      /// Message payload. Null for ping messages.
  "PingId": "Nullable<string>",         /// Non-null only for ping messages.
  "TimestampUtc": "DateTime",           /// UTC timestamp when the message was generated by the Odds88 engine.
  "PublishTimestampUtc": "DateTime"     /// UTC timestamp when the message was published to the client.
}
```

### **Delta Structure** <a href="#id-7.-delta-structure" id="id-7.-delta-structure"></a>

The Delta message has a common structure that applies to all types:

```json
{
  "Type": "DeltaTypeEnum (long)",    /// Type of delta
  "EventId": "long",                 /// Id of changed event
  "Version": "long",                 /// Version of feed state (deprecated)
  "CorrelationId": "string",         /// Correlation id of the message to trace back.
  "CreationTime": "DateTime",        /// Captures the timestamp the dto was created.
  "SportId": "long",                 /// Id of the Sport
  "LocationId": "long",              /// Id of the Location
  "LeagueId": "long",                /// Id of the League
  "UpdateSequence": "long",          /// Event update sequence. Incremented with each sent delta.
  "LastUpdatedTime": "long"          /// Event update time.
}
```

## **Summary** <a href="#summary-of-client-responsibilities" id="summary-of-client-responsibilities"></a>

#### **On Connection** <a href="#on-connection" id="on-connection"></a>

* Send **revision=\<LastUpdatedTime>** - it is optional but recommended for first connection.

#### **While connected** <a href="#during-stream" id="during-stream"></a>

* Track **UpdateSequence** per event.
* Detect gaps and missing updates, then call snapshot API.
* Handle heartbeat logic.
* Reconnect after 30 seconds of inactivity.
* Request snapshot from API only when required.

#### **During Recovery** <a href="#during-recovery" id="during-recovery"></a>

* Drop messages with lower **UpdateSequence.**

***

### Data Elements

* Every event consists of 4 data elements. **eventInfo** - basic information about the event. **markets** - contains data about markets, selection and odds values. **scoreboard** - contains data about periods and score. **betCancellations** - contains data about the time period in which bets placed on specific markets should be cancelled.
* Every data element has a dedicated delta type that is used to send updates for this specific element. Two exceptions are **eventSnapshotDelta (type6),** which contains all data elements, and **eventStatusChangedDelta (type 1),** which is used to update **status** and **tradingStatus** that are located inside **eventInfo.**

### **Data Storage Recommendations**

* Recommended approach of storing data for events is following. **eventInfo** should be stored in a document database like MongoDB. **markets, scoreboard, betCancellation** data is stored in a cache like Redis. This allows for time critical data of **markets/odds** to be processed and forwarded to frontend as fast as it is possible.

### Establishing Connection

* After receiving credentials from TIS, the next step is to establish connection with Odds88 WebSocket delta feed. We **recommend** doing initial connection with **Unix timestamp for the last 1 hour** to reduce load on both sides as it prevents returning excessive historical data. After that you should connect with **Unix timestamp from last processed message.**

### Storing Data

* Subscribing with **revision = 0** will generate snapshots (**type 6** delta) for all events active in a Odds88 system. This type of delta contains full data about an event and includes **all 4 data elements**. If an event doesn’t exist in the your database, it should be created. If an event exists all data elements that changed should be updated.
* Upon receiving delta of **type 2** a new event should be created in your DB. If an event already exists, changed fields should be updated. Deltas of type 2 and 6 are the only two deltas that should create new events in your database.
* Next step is to process every other delta type that contains only updates for already existing events and update changed fields/properties in the database/cache for further use in your system/frontend solution. Structure of all delta types can be checked in swagger.
* Events can have from 0 to many markets.
* Markets can have from 1 to many selections.
* After message processing is implemented, you can populate your database by connecting to feed. We recommend sending a **Unix timestamp for the last 1 hour** to reduce load on both sides. In case of reconnection it should happen with **revision={LastUpdatedTime}**. Existing data should be enough to create frontend views of sports, leagues and events.
* To process messages it is required to use a multithreaded solution. Number of messages and their size can be significant during peak hours for a single threaded solution to handle the volume.
* It is recommended to use MongoDB + Redis, for quick and reliable forwarding of data to frontend.

### Market settlements

Delta Feed delivers selection-level market settlements — i.e. the outcome of each individual selection in a market. This tells your system “what happened on the field” for a market, independent of any specific player’s bet.\
There is no dedicated settlement delta type. Settlement data is carried as a regular field on each selection inside the standard delta types that include market data. When a market is settled, the selection’s `settlement` field changes from `0 (None)` to its final result.

Two delta types include selections, and therefore can carry settlement data:\
`6` - EventSnapshot\
`7` - MarketsChanged

The Delta Feed `SettlementResult` enum (used in `SelectionViewModelV2.settlement`):

| Value | Name       | Description                                      |
| ----- | ---------- | ------------------------------------------------ |
| 0     | `None`     | Not yet settled                                  |
| 1     | `Refund`   | Stake fully returned                             |
| 2     | `Lose`     | Selection lost                                   |
| 3     | `Win`      | Selection won                                    |
| 4     | `HalfLose` | Half stake lost (Asian handicap / quarter lines) |
| 5     | `HalfWin`  | Half stake won (Asian handicap / quarter lines)  |

Examples:

```json
{
  "type": 7,
  "eventId": 123456,
  "updateSequence": 42,
  "markets": [
    {
      "id": 555001,
      "tradingStatus": 2,
      "selections": [
        { "id": 777001, "name": "Team A", "status": 2, "settlement": 3 },
        { "id": 777002, "name": "Team B", "status": 2, "settlement": 2 }
      ]
    }
  ]
}
```

```json
{
  "type": 6,
  "eventId": 123456,
  "eventInfo": { "...": "..." },
  "markets": [
    {
      "id": 555001,
      "tradingStatus": 2,
      "selections": [
        { "id": 777001, "settlement": 3 },
        { "id": 777002, "settlement": 2 }
      ]
    }
  ],
  "scoreboard": { "...": "..." },
  "betCancellations": []
}
```


# Delta Feed

{% content-ref url="/pages/1d0GJsRhup2cWOSIE6bt" %}
[Delta Feed](/odds88-client-api/odds88-feeds/delta-feed)
{% endcontent-ref %}

### Data Elements

* Every event consists of 4 data elements. **eventInfo** - basic information about the event. **markets** - contains data about markets, selection and odds values. **scoreboard** - contains data about periods and score. **betCancellations** - contains data about the time period in which bets placed on specific markets should be cancelled.
* Every data element has a dedicated delta type that is used to send updates for this specific element. Two exceptions are **eventSnapshotDelta (type6),** which contains all data elements, and **eventStatusChangedDelta (type 1),** which is used to update **status** and **tradingStatus** that are located inside **eventInfo.**

### **Data Storage Recommendations**

* Recommended approach of storing data for events is following. **eventInfo** should be stored in a document database like MongoDB. **markets, scoreboard, betCancellation** data is stored in a cache like Redis. This allows for time critical data of **markets/odds** to be processed and forwarded to frontend as fast as it is possible.

### Establishing Connection

* After receiving credentials from TIS, the next step is to establish connection with Odds88 websocket delta feed. Initial connection should happen with **revision = 0** to get messages for all active events. After that you should connect with **revision = version from latest delta received.**

{% hint style="warning" %}
**Only initial connection should happen with revision = 0. Every other reconnection should happen with correct revision!**
{% endhint %}

### Storing Data

* Subscribing with **revision = 0** will generate snapshots (**type 6** delta) for all events active in a Odds88 system. This type of delta contains full data about an event and includes **all 4 data elements**. If an event doesn’t exist in the your database, it should be created. If an event exists all data elements that changed should be updated.
* Upon receiving delta of **type 2** a new event should be created in your DB. If an event already exists, changed fields should be updated. Deltas of type 2 and 6 are the only two deltas that should create new events in your database.
* Next step is to process every other delta type that contains only updates for already existing events and update changed fields/properties in the database/cache for further use in your system/frontend solution. Structure of all delta types can be checked in swagger.
* Events can have from 0 to many markets.
* Markets can have from 1 to many selections.
* After message processing is implemented, you can populate your database by connecting to feed with 0 revision. In case of reconnection it should happen with **revision = version from latest delta processed**. Existing data should be enough to create frontend views of sports, leagues and events.
* To process messages it is required to use a multithreaded solution. Number of messages and their size can be significant during peak hours for a single threaded solution to handle the volume.
* It is recommended to use MongoDB + Redis, for quick and reliable forwarding of data to frontend.

### Market settlements

Delta Feed delivers selection-level market settlements — i.e. the outcome of each individual selection in a market. This tells your system “what happened on the field” for a market, independent of any specific player’s bet.\
There is no dedicated settlement delta type. Settlement data is carried as a regular field on each selection inside the standard delta types that include market data. When a market is settled, the selection’s `settlement` field changes from `0 (None)` to its final result.

Two delta types include selections, and therefore can carry settlement data:\
`6` - EventSnapshot\
`7` - MarketsChanged

The Delta Feed `SettlementResult` enum (used in `SelectionViewModelV2.settlement`):

| Value | Name       | Description                                      |
| ----- | ---------- | ------------------------------------------------ |
| 0     | `None`     | Not yet settled                                  |
| 1     | `Refund`   | Stake fully returned                             |
| 2     | `Lose`     | Selection lost                                   |
| 3     | `Win`      | Selection won                                    |
| 4     | `HalfLose` | Half stake lost (Asian handicap / quarter lines) |
| 5     | `HalfWin`  | Half stake won (Asian handicap / quarter lines)  |

Examples:

```json
{
  "type": 7,
  "eventId": 123456,
  "updateSequence": 42,
  "markets": [
    {
      "id": 555001,
      "tradingStatus": 2,
      "selections": [
        { "id": 777001, "name": "Team A", "status": 2, "settlement": 3 },
        { "id": 777002, "name": "Team B", "status": 2, "settlement": 2 }
      ]
    }
  ]
}
```

```json
{
  "type": 6,
  "eventId": 123456,
  "eventInfo": { "...": "..." },
  "markets": [
    {
      "id": 555001,
      "tradingStatus": 2,
      "selections": [
        { "id": 777001, "settlement": 3 },
        { "id": 777002, "settlement": 2 }
      ]
    }
  ],
  "scoreboard": { "...": "..." },
  "betCancellations": []
}
```


# Metadata Feed

{% content-ref url="/pages/HjCugoE6BZ6tHCAEI1Sg" %}
[Metadata Feed](/odds88-client-api/odds88-feeds/metadata-feed)
{% endcontent-ref %}

* Establish connection to metadata feed.
* Metadata has one type of message, which contains metadata for an event. Depending on the type of sport it can have different types of metadata.
* Store received data in database or cache.
* It is highly recommended to display metadata for Thoroughbreds, Greyhounds and Harness. For these sports metadata is displayed in cards for competitors. It is your decision, what metadata and how to show.
* Reconnection should be automatically handled by integration. Automatic Reconnection should happen with `revision` **= UNIX timestamp seconds of last received message - 60 seconds**
* If a sport has metadata type listed, it **doesn’t guarantee** this type is available for all events in this sport.
* What metadata types are sent for sports can be checked in the Metadata API section.

{% content-ref url="/pages/pwg5sZEvLfdflkvSxByU" %}
[Metadata API](/odds88-client-api/odds88-api-endpoints/metadata-api)
{% endcontent-ref %}

### **Heartbeat Support** <a href="#id-5.-heartbeat-support" id="id-5.-heartbeat-support"></a>

The new endpoint supports heartbeat messages so it's possible to differentiate idle periods from technical issues.

**Heartbeat Timing**

* Heartbeat every **10 seconds**
* Expected flow: Delta **or** Heartbeat message

**Connection Timeout Rules**\
If there is no delta **or** heartbeat messages received for 30 seconds then it's required to close current connection and reconnect using **LastUpdatedTime** from last processed message.\
Our system closes stale connections automatically.

### **Message Wrapper Structure** <a href="#id-6.-message-wrapper-structure" id="id-6.-message-wrapper-structure"></a>

All messages (deltas or heartbeats) are wrapped in the following structure:

```json
{
  "Payload": "Nullable<DeltaDto>",      /// Message payload. Null for ping messages.
  "PingId": "Nullable<string>",         /// Non-null only for ping messages.
  "TimestampUtc": "DateTime",           /// UTC timestamp when the message was generated by the Odds88 engine.
  "PublishTimestampUtc": "DateTime"     /// UTC timestamp when the message was published to the client.
}
```


# Bet Placement

* Create a player database. Every player should have UUID **at least** 18 characters matching this regex `^[0-9A-Za-z#_-]*` and **not** more than 36 characters in length.
* On bet placement, it is required to specify the following parameters:
  * **`id` -** Unique identifier of bet
  * **`playerId`** - unique Id of player. Should be the same for all currencies the player uses. Generated on your side.
  * **`deviceId`** - user agent of player
  * **`ip`** - user IPv4 or IPv6 address
  * **`languageId`** - ISO 639-1 language code
  * **`segmentId`** - unique Id of a segment assigned to you where to send bets
  * **`amount`** - includes information about stake amount and currency
    * **`currency`** - code of currency
    * **`value`** - stake amount. Integer value
    * **`precision`** - precision of used currency
  * **`items`** - list of selections made, where each selection holds the following fields:
    * **`eventId`** - event player made selection from
    * **`marketId`** - ID of market from above mentioned event
    * **`selectionId`** - ID of selection from above mentioned market
    * **`racingSelection`** - Only for fixed exotics
    * **`price`** - odds of selection
* Check if it is possible to send bet placement requests
* After the player presses the button that initiates the bet placement process, stake amount is subtracted from the players’ balance or balance is locked to prevent changes and potential simultaneous access, which can lead to unneeded cancellation cases because of insufficient funds in players wallet.
* On bet placement response performs a check that compares returned values with those in your DB. In case data is different, cancel requests should be sent. **Price can be different**, if the priceChange option was sent and should be updated in DB to one in response.
* Currency data is returned from CurrencyExchange endpoints. All currencies have precision, which shows how many digits correspond to decimal positions. Placing **101000** bet in **USD** with precision **4** means stake amount 101000 / 10^4 = 10 Dollars and 10 cents

{% content-ref url="/pages/2l7cTFxJAk5U4UAqv2Er" %}
[Bets API](/odds88-client-api/odds88-api-endpoints/bets-api)
{% endcontent-ref %}

{% content-ref url="/pages/tAABok4kCnqCthSR0G3S" %}
[Currency Exchange API](/odds88-client-api/odds88-api-endpoints/currency-exchange-api)
{% endcontent-ref %}

#### **SP market**

SP (Starting Price) market is a market which has no price on time of bet placement. Such bets can be placed during the prematch phase of the event only.

{% content-ref url="/pages/WxCA3MuMh7J8iF7aZiSe" %}
[Starting Price Integration](/integration-process/recommended-integration-flow/optional-features/starting-price-integration)
{% endcontent-ref %}

#### Free bets

We also support 'free bets' in our bet placement requests. The value "FreeBetType" can have values 0 (standard bet) or 1 (free bet). This indicates whether the bet has a real value or not. All incoming bets that do not have this value specified are considered as 'real' bets.

#### **Bet placement flow**

1. After the bet placement process is initiated by the player, bet placement is requested. Stake amount is subtracted from players balance or locked until bet is placed or rejected.
2. Bet is processed by Odds88 through an internal processor which checks if markets and events are available.\ <i class="fa-arrow-right-long">:arrow-right-long:</i> If not, then the bet gets rejected and you receive a rejection reason.
3. Price and odds values get returned and are aligned with your database.\ <i class="fa-arrow-right-long">:arrow-right-long:</i> If values do not align, then a cancellation request is sent and the bet placement process is finished.

{% hint style="warning" %}
Price may be different in response, if **priceChange** is set to 1 or 2.
{% endhint %}

4. Bet is processed within acceptable delay depending on pre-match or live bet. For pre-match bet acceptable delay is up to maximum 5 seconds and for live bet acceptable delay is corresponding LTD (Live time delay) for event (maximum LTD 14 seconds) + 20 seconds.\ <i class="fa-arrow-right-long">:arrow-right-long:</i> If the bet does not get processed within the corresponding delay, then the bet gets rejected.
5. The bet is accepted by you and the bet placement process is finished. If the bet is not accepted by you, then a cancellation request is sent. If you receive a cancellation response with the code 200, then the bet placement process is finished and the respective bet is cancelled.

## Bet placement flow graph

<figure><picture><source srcset="/files/MJintmgEeCLkZnLDQApR" media="(prefers-color-scheme: dark)"><img src="/files/kK9tlaOHEGmJqqk6lV58" alt=""></picture><figcaption></figcaption></figure>


# Settlement Feed

{% content-ref url="/pages/pCOsbPzku2QUbexzwct0" %}
[Settlement Feed](/odds88-client-api/odds88-feeds/settlement-feed)
{% endcontent-ref %}

* Establish connection.
* Process message. Message schema
* Apply settlement results to the ticket in DB, update player balance accordingly.
* Every message has ticket level `settlementTime`, that shows at what time settlement happened. Normally messages are pushed to feed 0.5-2 seconds after settlement happens.
* Multiple settlement messages can be sent for one ticket. If `settlementTime` of ticket received in message is smaller than previously received in settlement message for this ticket, message should be ignored and no changes should be made. Especially important during reconnect/recovery to prevent resettlements of tickets.
* Reconnection should be automatically handled by integration. Automatic Reconnection should happen with **correct** **revision**.
* `revision` is a UNIX timestamp seconds. In case of reconnection it should have a timestamp of 1 minute before the last settlement message received. Duplicated messages expected and should be ignored. Maximum recovery period is 3 days.
* There are endpoints that can be used to get the latest result/status of specific tickets. We recommend implementing these endpoints in your backend/backoffice to get results manually if needed.
* Settlement of tickets, without interaction with Odds88 endpoints should be possible from your backoffice in case it is not possible to do it any other way.

### **Heartbeat Support** <a href="#id-5.-heartbeat-support" id="id-5.-heartbeat-support"></a>

The new endpoint supports heartbeat messages so it's possible to differentiate idle periods from technical issues.

**Heartbeat Timing**

* Heartbeat every **10 seconds**
* Expected flow: Delta **or** Heartbeat message

**Connection Timeout Rules**\
If there is no delta **or** heartbeat messages received for 30 seconds then it's required to close current connection and reconnect using **LastUpdatedTime** from last processed message.\
Our system closes stale connections automatically.

### **Message Wrapper Structure** <a href="#id-6.-message-wrapper-structure" id="id-6.-message-wrapper-structure"></a>

All messages (deltas or heartbeats) are wrapped in the following structure:

```json
{
  "Payload": "Nullable<DeltaDto>",      /// Message payload. Null for ping messages.
  "PingId": "Nullable<string>",         /// Non-null only for ping messages.
  "TimestampUtc": "DateTime",           /// UTC timestamp when the message was generated by the Odds88 engine.
  "PublishTimestampUtc": "DateTime"     /// UTC timestamp when the message was published to the client.
}
```


# Translation Feed

{% content-ref url="/pages/TqkGvEKMYF8mpmNGgDt9" %}
[Translation Change Feed](/odds88-client-api/odds88-feeds/translation-change-feed)
{% endcontent-ref %}

* It is recommended to use translations provided from Odds88. All translations are received via corresponding endpoints.
* Translation changes feed is used to get information about what properties have translation updated. Depending on the type of message received from the feed one of the translation endpoints has to be called with id specified in the message.
* Sports, Locations, Leagues rarely receive translation updates. Every event, market and selection inside the event are translated after being created.
* Messages have following types and actions that have to be done upon receiving it:

0 - sport translation changed. Fetch and update translations for sport

1 - location translation changed. Fetch and update translations for location

2 - league translation changed. Fetch and update translations for league

3 - competitor translation changed. Fetch and update translations for competitor

4 - market translation changed. This type of translation can be ignored as every event has individual translations for selections and markets

5 - selection translation changed. This type of translation can be ignored as every event has individual translations for selections and markets

6 - event translation changed. Fetch translation for the event [**/api/translations/all/event/{eventId}**](/odds88-client-api/odds88-api-endpoints/translations-api#get-api-translations-all-event-eventid) and markets [**/api/translations/all/{eventId}/markets**](/odds88-client-api/odds88-api-endpoints/translations-api#get-api-translations-all-eventid-markets) from this event. Update translations for event, markets and selection names

* In case there is no translation for a certain language, it should fall back to English. In case there is no translation for English, it should fall back to a name sent in delta feed.

### Recommended way of implementing translations

1. Once a new event is received, process it and cache it
2. Fetch translations by calling:

```
/Translations/all/event/{eventId}
```

This endpoint returns translations in all languages for the event, including competitors, sport, league, and location

* Cache these translations by `eventId` (or merge them into the existing event if only a single language is used)

3. When markets are received—either during event creation or later—do the following:

* Check whether the market already exists and has been translated (for example, using a field like `IsTranslated = true/false`)
* If the market is not translated, send a request to the following endpoint to retrieve translations:

  ```
  /Translations/{lang}/{eventId}/markets?m=1&m=2&m=3
  ```

  If no `m` parameter is provided, the endpoint will return translations for all markets
* Once the translations are received, store them for each market. If a single language is used, simply replace the translations in the main cached event’s markets

4. When a Market Update is received, first check whether the market has already been translated and stored in Redis (`IsTranslated = true/false`)

* If the market exists in the cache, only update the relevant fields such as odds, status, and settlement
* Use the `IsTranslated` flag to determine whether there is a need to fetch translations from the Odds88 API or whether the existing cached translation is sufficient

{% hint style="warning" %}
Both the odds feed and the translation API response always include the market ID and market type ID
{% endhint %}

### **Heartbeat Support** <a href="#id-5.-heartbeat-support" id="id-5.-heartbeat-support"></a>

The new endpoint supports heartbeat messages so it's possible to differentiate idle periods from technical issues.

**Heartbeat Timing**

* Heartbeat every **10 seconds**
* Expected flow: Delta **or** Heartbeat message

**Connection Timeout Rules**\
If there is no delta **or** heartbeat messages received for 30 seconds then it's required to close current connection and reconnect using **LastUpdatedTime** from last processed message.\
Our system closes stale connections automatically.

### **Message Wrapper Structure** <a href="#id-6.-message-wrapper-structure" id="id-6.-message-wrapper-structure"></a>

All messages (deltas or heartbeats) are wrapped in the following structure:

```json
{
  "Payload": "Nullable<DeltaDto>",      /// Message payload. Null for ping messages.
  "PingId": "Nullable<string>",         /// Non-null only for ping messages.
  "TimestampUtc": "DateTime",           /// UTC timestamp when the message was generated by the Odds88 engine.
  "PublishTimestampUtc": "DateTime"     /// UTC timestamp when the message was published to the client.
}
```


# Feed Message Compression

This feature includes every feed endpoints including:

* Delta Feed
* Settlement Feed
* Metadata Feed
* Pick'em Feed
* Translation Feed
* Cashout Feed

***

{% hint style="info" %}
**Compression is optional and disabled by default**\
Clients that want smaller and faster messages can **opt in**.\
Clients that do nothing will continue to work **exactly as before**.
{% endhint %}

### How It Works <a href="#how-it-works" id="how-it-works"></a>

* You can request compressed messages during the WebSocket connection setup
* If requested, the server:
  * Compresses each message using **GZip**
  * Sends messages as **binary WebSocket frames**
* If not requested:
  * Messages are sent as **plain text JSON**
  * No behavior change at all

This guarantees **full backward compatibility**.

***

### How to Enable Compression <a href="#how-to-enable-compression" id="how-to-enable-compression"></a>

To enable compression, you must send the following HTTP header **when opening the WebSocket connection**:

`X-Enable-Compression: true`

If the header is missing, compression is **not** used.

***

### What Changes When Compression Is Enabled <a href="#what-changes-when-compression-is-enabled" id="what-changes-when-compression-is-enabled"></a>

| Aspect                                    | Without Compression | With Compression          |
| ----------------------------------------- | ------------------- | ------------------------- |
| Message format                            | Text                | Binary                    |
| Payload                                   | Plain JSON          | GZip-compressed JSON      |
| Client action needed                      | None                | Decompress before parsing |
| Human readable in Postman / browser tools | Yes                 | No                        |

***

### Responsibilities <a href="#client-responsibilities" id="client-responsibilities"></a>

When compression is enabled:

* Messages arrive as **binary data**
* The data is **GZip-compressed**
* You must:
  1. Decompress the message
  2. Parse the resulting JSON

{% hint style="info" %}
**GZip is supported in all major programming languages**, so decompression is straightforward and widely available.
{% endhint %}

***

{% hint style="info" %}
Compression is applied **per WebSocket connection**, not per message
{% endhint %}

***

### Message Size Improvements <a href="#message-size-improvements" id="message-size-improvements"></a>

JSON data compresses very well because it contains many repeated field names and structured data.

**Typical Results**

| Original Message Size | After Compression | Size Reduction |
| --------------------- | ----------------- | -------------- |
| 20 KB                 | 4–6 KB            | \~70%          |
| 50 KB                 | 7–10 KB           | \~80–85%       |
| 120 KB                | \~18 KB           | \~85%          |
| 200 KB                | 20–30 KB          | \~85–90%       |

**What This Means for You**

* Much lower bandwidth usage
* Faster message delivery
* Lower latency on slow or mobile networks
* Better performance for high-frequency updates (e.g. odds or market changes)


# Optional features

Odds88 also offers additional optional features, which include:

* Cashout
* Pick'em
* Starting Price
* BetBuilder
* Fixed Exotics
* Alternative Odds


# Cashout Integration

This section of the document outlines the integration process for our Cashout feature. With risk management flow enabled, users can subscribe to a Cashout feed stream. This stream provides real-time updates regarding potential changes in the cashout amount for each bet the user follows. It also indicates whether cashout is currently available and the amount that can be cashed out. Updates are sent whenever Odds, Markets, Selection, or Event changes occur.<br>

The overall flow is as follows:

1. You must open the feed stream via WebSocket.
2. You can then subscribe or unsubscribe bets from this stream, initiating the receipt of updates for those bets.
3. When a user wishes to cash out a bet, you have to submit a cashout request. If the request is valid, the bet will be settled as cashed out in our system.

Cashout is currently supported only for standard bet types with some exclusions:

| Category                              | Cashout supported? | Notes                                               |
| ------------------------------------- | ------------------ | --------------------------------------------------- |
| Standard bets                         | ✅ Yes              |                                                     |
| BetBuilder bets                       | ❌ No               | Same-event correlated selections are not supported. |
| FixedExotics                          | ❌ No               | Non-Standard bet type.                              |
| StartingPrice                         | ❌ No               | Non-Standard bet type.                              |
| ToteExotics                           | ❌ No               | Non-Standard bet type.                              |
| Outright bets                         | ❌ No               | Not supported currently.                            |
| Fully refundable selections           | ❌ No               | Flat lines (e.g. `1.0`, `2.0`).                     |
| Quarter lines (`0.25`, `0.75`)        | ✅ Yes              |                                                     |
| Refundable markets (e.g. Draw No Bet) | ❌ No               | Markets that can refund a selection.                |


# Endpoint

**Endpoint:**

{% content-ref url="/pages/ivn3IWuh7XK7eWavHRnp" %}
[Cashout Feed](/odds88-client-api/odds88-feeds/cashout-feed)
{% endcontent-ref %}

Revision is **UNIX** timestamp seconds, in case you need to recover the availability of cashout and price value for existing bets. It can return data for max 3 days in past. But it will only return data for the bets that are in the subscription at the moment of connection.

{% hint style="warning" %}
The endpoint is rate-limited.
{% endhint %}

\
Stream message with cashout amount for a single bet:

```javascript
{
    playerId: "player1",
    betId: "id1",
    status: 1, //enum value, Available = 1, NotSupported = 2, CashedOut = 3
    reason: null, //string, reason if cashout is not available
    amount: {
        localAmount: 40000,
        precision: 4,
        currency: "USD",
    }
    timestamp: "2025-07-16T14:30:00Z",
}

```

### **Heartbeat Support** <a href="#id-5.-heartbeat-support" id="id-5.-heartbeat-support"></a>

The new endpoint supports heartbeat messages so it's possible to differentiate idle periods from technical issues.

**Heartbeat Timing**

* Heartbeat every **10 seconds**
* Expected flow: Delta **or** Heartbeat message

**Connection Timeout Rules**\
If there are no messages **or** heartbeat messages received for 30 seconds then it's required to close current connection and reconnect using **LastUpdatedTime** from last processed message.\
Our system closes stale connections automatically.


# Requests

Initiating a WebSocket stream with cashout amounts (identical to those for our other feeds)

{% content-ref url="/pages/CDyqERePHyDhrua9zyke" %}
[Cashout API](/odds88-client-api/odds88-api-endpoints/cashout-api)
{% endcontent-ref %}

Subscribe/unsubscribe requests:

```javascript
{
    betIds: ["id1","id2"]
}
```

Success response: code 200, no body<br>

Cashout request:

```javascript
{
    betId: "id1",
    priceChange: 1,
    amount: {
          localAmount: 40000,
          precision: 4,
          currency: "USD",
    }
}
```

When sending a cashout request make sure the currency you send is the same as the one you used to place a bet.

**PriceChange** field affects whether the odds changes that happened (odds change will affect the cashout amount) will be ignored, or block the cashout request. If you leave it as 1, it means any cashout amount changes will be a blocker and request will be rejected (if changes are above a threshold of 2%). For these changes to be detected we require you to send us the last cashout amount you received from us (the one you show to the user), which we compare with the latest cashout amount on our side. If you set **PriceChange** to 2, it will ignore any odds changes and won't reject cashout requests even if the amount was changed drastically in a short period of time.\
**Example:** Current odds are 2.0 and the player placed a bet of 100$. Now, for example, he is allowed to cashout 90$.\
You get this value from the feed and send a cashout request with it to us. By the time your request reaches us, the odds change not in the favour of the player (or vice versa) and the cashout amount is now 85$.\
We calculate the difference between 85 and 90 and check if it is under a certain threshold. If you sent us PriceChange 2 then we ignore any difference and odds and proceed with cashing out 85, as it was the actual latest value on our side. If PriceChange: 1 and the difference exceeds 2% then we reject the request.<br>

Success response:

```javascript
{
    success: true,
    reason: null,
    payload: {
        localAmount: 40000,
        betId: "id1",
    }
}
```

Rejection response:

```javascript
{
    Success: false,
    Reason: "Reason why cashout can not be made"
    Payload: {
        LocalAmount: 40000,
        BetId: "id1",
    }
}
```

<br>


# Pick’em Integration

This section of the document outlines the integration process for our Pick’em feed and what Pick'em exactly means.

In sports betting, a pick'em is when both teams/players or result of a total or handicap line are seen roughly as equal probability, and a bet on either of these selections would return the same amount of money. People generally use the term “Pick'em” loosely, meaning the odds don't always have to be exactly the same for a matchup to be regarded as a pick'em.\
\
Pick'em example of Player market:

<figure><img src="/files/9aNj58tWSs4zy4pbUEzE" alt=""><figcaption></figcaption></figure>

This is a normal market inside an Event. But it can be classifies as a Pick'em market as well due to the probabilities being exactly the same.

Pick'em example of Teams market:

<figure><img src="/files/8UnBTxmBrkc3kv1Vcm9M" alt=""><figcaption></figcaption></figure>

Same case with this one, a normal Winner market here, where the odds are not exactly the same but it can be classified as a Pick'em market.

Pick'em example of UI:

<figure><img src="/files/mjVtFz7VJCnbRtSw2mg8" alt=""><figcaption></figcaption></figure>

**Pick'em aka Pick Them** is essentially making a choice: Yes or No, Team 1 or Team 2, Over x.x or Under x.x etc\
\
This Pick'em stream provides four distinct types of deltas. Specific deltas can be identified by the “Type” field. Connecting to the feed stream is accomplished via WebSocket, the same protocol employed for our other feeds. This feed will exclusively transmit Pick’em events and markets.\
Bet placement will function identically to that of regular markets (with the exception of pre-match bets), albeit with market contingency on our end. We have configured the markets within an event for players to place so-called multi-bets. A novel field, “enum BetType,” has been introduced in the bet placement request. The value of 0 corresponds to standard bets, while 1 signifies Pick’em bets.

Pick'em markets use the same translations as the ones that come through our translations feed.


# Endpoint

**Endpoint:**

{% content-ref url="/pages/RUwFv9XgqKWOUDS2RIAF" %}
[Pick'em Feed](/odds88-client-api/odds88-feeds/pickem-feed)
{% endcontent-ref %}

`revision` number passed in the URL should correspond to **version** of the last received and processed delta message.

{% hint style="warning" %}
The endpoint is rate-limited.
{% endhint %}


# Delta types

**EventStatusChangedDelta:**

```javascript
{
  "Type": 1,
  "EventId": "long",
  "Version": "long",
  "CorrelationId": "string",
  "CreationTime": "string (ISO 8601 DateTime)",
  "SportId": "long",
  "LocationId": "long",
  "LeagueId": "long",
  "IsOutright": "boolean",
  "IsActive": "boolean"
}
```

**EventChangedDelta:**

```javascript
{
  "Type": 2,
  "EventId": "long",
  "Version": "long",
  "CorrelationId": "string",
  "CreationTime": "string (ISO 8601 DateTime)",
  "SportId": "long",
  "LocationId": "long",
  "LeagueId": "long",
  "IsOutright": "boolean",
  "EventInfo": "object (EventInfoDto)"
}
```

**EventSnapshotDelta:**

```javascript
{
  "Type": 3,
  "EventId": "long",
  "Version": "long",
  "CorrelationId": "string",
  "CreationTime": "string (ISO 8601 DateTime)",
  "SportId": "long",
  "LocationId": "long",
  "LeagueId": "long",
  "IsOutright": "boolean",
  "EventInfo": "object (EventInfoDto)",
  "Markets": "array of objects (MarketDto)"
}
```

**MarketsChangedDelta:**

```javascript
{
  "Type": 4,
  "EventId": "long",
  "Version": "long",
  "CorrelationId": "string",
  "CreationTime": "string (ISO 8601 DateTime)",
  "SportId": "long",
  "LocationId": "long",
  "LeagueId": "long",
  "IsOutright": "boolean",
  "Markets": "array of objects (MarketDto)"
}
```


# Market contingency

Some markets are connected to each other and should not be possible to combine in a Pick'em bet. The most important factors here are the Player and Competitors/Teams parameters. If, for example, the same Player is involved, then Pick'em selections should not be possible to add together.

With market contingency, the general recommended flow is as follows:

1. Player picks a market that has market contingency restrictions.
2. UI should now disable/hide other markets that clash with the initial market.
3. The same goes for every market the player picks after the first pick.

#### **UI Behaviour Rules**

**Case 1:**

* `ContingencyKey` overlaps
* One side the `ContingencyScope` is empty, the other is not empty
* **Result:** Reject

**Case 2:**

* `ContingencyKey` overlaps
* `ContingencyScope` has overlapping Ids
* **Result:** Reject

**Case 3:**

* `ContingencyKey` overlaps
* Both `ContingencyScope` s are empty
* **Result:** Reject

**Case 4:**

* `ContingencyKey` overlaps
* `ContingencyScope` disjoint (no overlap) - both are not empty
* **Result:** Allow

**Case 5:**

* `ContingencyKey` is empty
* **Result:** Allow

#### **Examples**

Example 1

```javascript
{
Id: 1500,
Name: "Team2 total",
IsActive: true,
ContingencyKey: [1001-MT3-MT3, 1001-MT3-MT4],
ContingencyScope: [C1112],
Selections: {…},
}
```

```javascript
{
Id: 1501,
Name: "Team1 total",
IsActive: true,
ContingencyKey: [1001-MT4-MT4, 1001-MT3-MT4],
ContingencyScope: [C1112],
Selections: {…},
}
```

Market 1500 and 1501 can not be combined since they have overlapping values in ContingencyKey and ContingencyScope

***

Example 2

```javascript
{
Id: 1300,
Name: "Haso runs",
IsActive: true,
ContingencyKey: [1001-MT1-MT1, 1001-MT1-MT2],
ContingencyScope: [P112],
Selections: {…},
}
,
{
Id: 1301,
Name: "Kako runs",
IsActive: true,
ContingencyKey: [1001-MT1-MT1, 1001-MT1-MT2],
ContingencyScope: [P1113],
Selections: {…},
}
```

```javascript
{
Id: 1400,
Name: "Total",
IsActive: true,
ContingencyKey: [1001-MT2-MT2, 1001-MT1-MT2],
ContingencyScope: [],
Selections: {…},
}
```

If Market 1400 is selected, Markets 1300 and 1301 should be considered invalid in the betslip (or removed from the Selection Deck in the UI) because they share overlapping ContingencyKeys, and Market 1400 has an empty ContingencyScope, which implies it applies to all scopes

In another scenario,

Markets 1301 and 1302 can be combined and accepted for betting because, although they share overlapping ContingencyKeys, their ContingencyScopes contain non-overlapping values.

***

Example 3

```javascript
{
Id: 1500,
Name: "Team2 total",
IsActive: true,
ContingencyKey: [1001-MT3-MT3, 1001-MT2-MT3],
ContingencyScope: [C1112],
Selections: {…},
}
```

```javascript
{
Id: 1600,
Name: "Total",
IsActive: true,
ContingencyKey: [1001-MT2-MT2, 1001-MT2-MT3],
ContingencyScope: [],
Selections: {…},
}
```

Markets 1500 and 1600 cannot be combined because they have overlapping ContingencyKeys, and Market 1600 has an empty ContingencyScope, which applies to all scopes.

<br>


# Bet request

**Example bet request:**

{% content-ref url="/pages/2l7cTFxJAk5U4UAqv2Er" %}
[Bets API](/odds88-client-api/odds88-api-endpoints/bets-api)
{% endcontent-ref %}

```javascript
{
  "id": "requestId",
  "player": {
    "deviceId": "deviceId",
    "languageId": "en",
    "ip": "01.0.0.1",
    "segmentId": 1000
  },
  "priceChange": "Any",
  "items": [
    {
      "eventId": 8876387,
      "marketId": 41,
      "selectionId": 20,
      "racingSelection": null,
      "price": 1.85,
      "betBuilderBetItems": null
    },
    {
      "eventId": 8876387,
      "marketId": 224126,
      "selectionId": 20,
      "racingSelection": null,
      "price": 1.85,
      "betBuilderBetItems": null
    }
  ],
  "alternativeOddsId": null,
  "alternativePrice": 0,
  "customPayoutMultiplier": 3.0,
  "betType": 1,
  "amount": {
    "currency": "EUR",
    "value": 0.144770348014712817127228143,
    "precision": 4
  }
}
```


# Metadata

{% content-ref url="/pages/gKP72bfeYJzaPQyaONPJ" %}
[Global Metadata API](/odds88-client-api/odds88-api-endpoints/global-metadata-api)
{% endcontent-ref %}

We also provide metadata (global metadata) for Pick'ems. We currently have these supported entities:

* Sport
* Location
* League
* Competitor
* Player

It is recommended to use the flow described in the Global Metadata API section for all entities. This way, you will get available metadata for all entities with the exact queries that are needed.


# BetBuilder Integration

This section of the document describes the integration process of the BetBuilder feature. BetBuilder is a feature which allows players to combine selections from different markets into a single bet. Simply put - a customisable combo bet.

The integration of BetBuilder is separated from the main integration process as it requires a specific flow of placing a bet and also requires some additional development. BetBuilder integration can be done in parallel with the main integration.

Current BetBuilder supported sports:

* American Football
* Baseball
* Basketball
* Cricket
* Football
* Ice Hockey
* MMA
* Rugby League
* Rugby Union
* Tennis


# Markets and Selections

\
Only a set of specific markets and selections are available in BetBuilder events.\
Available events, markets and selections have a unique property: **`isBetBuilderSupported: True`**.\
First check should be done on event level if property is **true** or **false**.\
If event level property is **true** then next check should be done on market/selection level.\
If event level property is **false** then BetBuilder is not available even if on market level property is true.\
\
It is recommended to give a visual specifier on UI which events, markets and selections are available for BetBuilder.


# Price Calculation

In order to calculate and display the resulting odds of selections made by the player, you need to call the BetBuilder price API endpoint with the specified parameters. You will be required to call this endpoint each time a player makes changes to their BetBuilder selections, you can find the endpoint in the Bets API section.

{% content-ref url="/pages/2l7cTFxJAk5U4UAqv2Er" %}
[Bets API](/odds88-client-api/odds88-api-endpoints/bets-api)
{% endcontent-ref %}

* `requestId` - unique key for request
* `eventId` - ID of selected event
* `bets` - List of markets and selections the player made

```javascript
{
  "requestId": "string",
  "segmentId": 1,
  "eventId": 1,
  "bets": [
    {
      "marketId": 0,
      "selectionId": 0
    },
    {
      "marketId": 1,
      "selectionId": 1
    }
  ]
}
```

In response, you will receive an answer with `requestId` and `price`:

```javascript
{
  "requestId": "string",
  "price": 0,
  "timeStamp": "2024-05-28T10:57:37.8963945+00:00",
  "rejectInfo": null
}
```

In case of request rejection, `rejectInfo` property will contain rejection information. Possible rejection reasons can be checked via the corresponding dictionary endpoint.

{% content-ref url="/pages/0BwLugNGCPLWrFx90Siq" %}
[Dictionary API](/odds88-client-api/odds88-api-endpoints/dictionary-api)
{% endcontent-ref %}


# Bet creation flow

After a player makes the first selection, it is not needed to send a request to the BetBuilder price endpoint. For a BetBuilder bet to be created **at least two** selections have to be made.

When a player makes a second and every following selection, you will need to send a request to the **bet-builder-price** endpoint with selections the player made. In response to this request you will receive a price or rejection reason.

On any update player does to the BetBuilder selections (adding or removing a selection), you have to fetch the new, updated price via **bet-builder-price** endpoint.

If, upon adding a new selection and fetching a new price, the price is left unchanged, the selection has no effect on the price and thus, should not be added to the betslip. In this case, a corresponding message is displayed to the player - “**added selection does not increase price/odds**”.\
**The new selection should then be removed from the betslip.**

If, upon adding a new selection and fetching a new price, the returned price is 0, the selections are in conflict and the combination is therefore impossible.\
**The new selection should then be removed from the betslip.**

After the player finishes building a bet, it is possible to add this bet to Bet Slip with the last received odds for selected combination. From now on BetBuilder bet is treated as any other bet and **can be used** as a leg of a multibet in combination with any other market or another BetBuilder bet from another event.


# Bet Placement

It’s important to note that while BetBuilder has a unique endpoint for fetching prices, the process of bet placement is still done via the betplacement endpoint.

{% content-ref url="/pages/2l7cTFxJAk5U4UAqv2Er" %}
[Bets API](/odds88-client-api/odds88-api-endpoints/bets-api)
{% endcontent-ref %}

To perform the placement of a bet, which includes BetBuilder, the client needs to specify the following parameters in the request. `marketId` and `selectionId` should be `-1`\
"**betBuilderBetItems**" should contain a list of markets and selections from BetBuilder bet.

Single BetBuilder bet placement request body example:

```json
{
  "id": "bet-id",
  "player": {...},
  "amount": {
    "currency": "USD",
    "value": 50000,
    "precision": 4
  },
  "priceChange": 1,
  "items": [
    {
      "eventId": 4780136,
      "marketId": -1,
      "selectionId": -1,
      "racingSelection": "",
      "betBuilderBetItems": [
        {
            "marketId": 1,
            "selectionId": 1
        },
        {
          "marketId": 67,
          "selectionId": 20
        }
      ],
    "price": 6.75
    }
  ]
}
```

Multibet bet placement with BetBuilder as one of the legs request example:

```json
{
  "id": "bet-id",
  "player": {...},
  "amount": {
    "currency": "USD",
    "value": 50000,
    "precision": 4
  },
  "priceChange": 1,
  "items": [
    {
      "eventId": 4780136,
      "marketId": -1,
      "selectionId": -1,
      "racingSelection": "",
      "betBuilderBetItems": [
        {
          "marketId": 1,
          "selectionId": 1
        },
        {
          "marketId": 67,
          "selectionId": 20
        }
      ],
      "price": 6.75
    },
    {
      "eventId": 4870489,
      "marketId": 1,
      "selectionId": 1,
      "racingSelection": "",
      "betBuilderBetItems": [],
      "price": 2.76
    }
  ]
}
```


# Bet Settlement

Information about bet settlement results are sent to the client as any other settlement information via **Settlement feed**

{% content-ref url="/pages/pCOsbPzku2QUbexzwct0" %}
[Settlement Feed](/odds88-client-api/odds88-feeds/settlement-feed)
{% endcontent-ref %}

Cashout for BetBuilder bets **is not supported**.

Example of bet settlement message from settlement feed:

```javascript
{
    "amount": {
        "currency": "EUR",
        "value": 889351,
        "precision": 4,
        "placementExchangeRate": 1.03165105434738,
        "settlementExchangeRate": 1.0325032007599223557593028538
    },
    "betId": "BetPusher_770:79277f3a-0b78-49d4-becc-8b2650a8a28a",
    "betSettlement": 2,
    "payoutMultiplier": 0.0,
    "isCancelled": false,
    "selections": [
        {
            "event": {
                "id": 7161284,
                "name": "Alexander Hejduk vs Petr Serak",
                "isLive": false,
                "startTime": "2025-02-10T09:30:00Z"
            },
            "market": {
                "id": 3985788,
                "type": 28779,
                "name": "Point handicap",
                "properties": {
                    "hcp": "-3.5"
                }
            },
            "selectionId": 47,
            "competitionId": 58036,
            "countryId": 44,
            "sportId": 2,
            "settlement": {
                "settlementResult": 1,
                "settlementTime": "2025-02-10T10:29:03.8759278Z",
                "settlementVersion": 1
            },
            "price": 1.9,
            "limitsRatingId": null,
            "limitsFactor": 1.0,
            "hasLineDeviation": false,
            "isOutright": false,
            "version": 1,
            "deadHeatFactor": 0.0,
            "parameters": {
                "hcp": "-3.5"
            },
            "manualPrice": null,
            "alternativePrice": null,
            "type": 1,
            "betBuilderItems": []
        },
        {
            "event": {
                "id": 7100103,
                "name": "Tommy Shelby @ Stud",
                "isLive": false,
                "startTime": "2025-02-10T10:56:00Z"
            },
            "market": {
                "id": 12322002,
                "type": 900828,
                "name": "dw:FX_MW_PLC",
                "properties": {
                    "isExotics": "false",
                    "isFixedExotics": "false",
                    "marketFeatures": "None",
                    "scratchedPositions": "[8,9]"
                }
            },
            "selectionId": 42723806,
            "competitionId": 10249,
            "countryId": 45,
            "sportId": 458,
            "settlement": {
                "settlementResult": 2,
                "settlementTime": "2025-02-10T11:00:26.2958696Z",
                "settlementVersion": 1
            },
            "price": 2.1,
            "limitsRatingId": null,
            "limitsFactor": 1.0,
            "hasLineDeviation": false,
            "isOutright": false,
            "version": 1,
            "deadHeatFactor": 0.0,
            "parameters": {
                "isExotics": "false",
                "isFixedExotics": "false",
                "marketFeatures": "None",
                "scratchedPositions": "[8,9]"
            },
            "manualPrice": null,
            "alternativePrice": null,
            "type": 1,
            "betBuilderItems": []
        },
        {
            "event": {
                "id": 7100103,
                "name": "Tommy Shelby @ Stud",
                "isLive": false,
                "startTime": "2025-02-10T10:56:00Z"
            },
            "market": {
                "id": 12322019,
                "type": 900831,
                "name": "dw:FX_MW_SHW",
                "properties": {
                    "isExotics": "false",
                    "isFixedExotics": "false",
                    "marketFeatures": "None",
                    "scratchedPositions": "[8,9]"
                }
            },
            "selectionId": 41704715,
            "competitionId": 10249,
            "countryId": 45,
            "sportId": 458,
            "settlement": {
                "settlementResult": 2,
                "settlementTime": "2025-02-10T11:00:26.3025749Z",
                "settlementVersion": 1
            },
            "price": 6.0,
            "limitsRatingId": null,
            "limitsFactor": 1.0,
            "hasLineDeviation": false,
            "isOutright": false,
            "version": 1,
            "deadHeatFactor": 0.0,
            "parameters": {
                "isExotics": "false",
                "isFixedExotics": "false",
                "marketFeatures": "None",
                "scratchedPositions": "[8,9]"
            },
            "manualPrice": null,
            "alternativePrice": null,
            "type": 1,
            "betBuilderItems": []
        }
    ],
    "isRejected": true,
    "settlementTime": "2025-02-10T11:00:26.590549Z",
    "payout": 0.0,
    "partialRefund": 0.0
}

```

<br>


# Starting Price Integration

Usually in the industry when placing a bet on Horse Racing you can select from two available pricing options:

-the price/odds the selection is at the time of bet placement\
-or **Starting Price (SP).**

When placing a bet on **SP**(**Starting Price) it** means that whatever odds your selection is at the start of the race, are the odds you will receive for your bet. The last available open and active odds.

**SP** is mainly targeted for Thoroughbred, Greyhounds and Harness - These are the Sports that we need support SP for.

Instead of having a bet only 6h before a horse racing event, you could already place it days before. Markets will open for betting significantly longer time period.

SP market is a market which has no price on time of bet placement. Such bets can be placed during the prematch phase of the event only.

Official SP is offered for UK & IRE races. For every other country, last available price is used.


# Markets

Starting Price (SP) markets are regular markets where the final odds are unknown at bet time.

### Identify an SP market

Check the `Market.ExtraParameters`.

* `Market.ExtraParameters : { "IsSp": "true" }` for SP markets.

Example:

<pre class="language-json"><code class="lang-json">{
  "extraParameters": {
    "MarketFeatures": "None",
    "ScratchedPositions": "[]",
    "IsExotics": "false",
    "IsFixedExotics": "false",
<strong>    "IsSp": "true"
</strong>  }
}
</code></pre>

### Selections in SP markets

Before the event starts, selection `price`/`startingPrice` is `null`.

You can still receive an indicative price. For example `originalPrice`. Do not treat it as the final SP odds.

Example:

<pre class="language-json"><code class="lang-json">{
  "id": 12345,
  "name": "Goway",
  "probability": 0.39130363,
<strong>  "price": null,
</strong>  "originalPrice": 2.15,
  "status": 0,
  "settlement": 0,
  "deadHeatFactor": 0,
  "extraParameters": {},
  "isBetBuilderSupported": false,
  "competitorId": 54321
<strong>  "startingPrice": null
</strong>}
</code></pre>


# Bet Placement

### Bet Placement Flow <a href="#bet-placement-flow" id="bet-placement-flow"></a>

{% content-ref url="/pages/2l7cTFxJAk5U4UAqv2Er" %}
[Bets API](/odds88-client-api/odds88-api-endpoints/bets-api)
{% endcontent-ref %}

Since a market can start as a **Starting Price (SP) market** and later become a **normal market** after a configured timepoint, bet placement should follow these rules:

* **Bet Placement Rules:**
  * Bet placement is allowed **only for single and multi bets** on Starting Price markets.
  * Starting Price bets should only be allowed when:

    `Market.ExtraParameters : { "IsSp": "true" }`
  * **Odds** are **not provided** during SP bet placement.
  * **Live events** are **not allowed** to accept bets for Starting Price markets.

Bet placement example:

<pre class="language-json"><code class="lang-json">{
  "id": "TestBet88",
  "player": {
    "deviceId": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.212 Safari/537.36",
    "languageId": "en",
    "ip": "0.0.0.0",
    "segmentId": 1000
  },
  "priceChange": 1,
  "items": [
    {
      "eventId": 12345,
      "marketId": 1,
      "selectionId": 2,
      "racingSelection": null,
<strong>      "price": null
</strong>    }
  ],
  "betType": 0,
  "amount": {
    "currency": "EUR",
    "value": 10000,
    "precision": 4
  }
}

</code></pre>


# Each-Way Betting Integration

**Each-Way markets have** <mark style="color:orange;">IsEW</mark> key in markets extraParameters:\
`Market.ExtraParameters : { "IsEW": "normal" or "handicap" }`\
Value "normal" or "handicap" is used for Place Terms calculation which is described below.

\
**Each-Way market** is mainly targeted for Thoroughbred, Greyhounds and Harness and is a form of wagering that consists of **two separate bets placed on the same racing events selection**:

1. **Win Bet** – the selection must finish **first**.
2. **Place Bet** – the selection must finish **within the specified placing positions.**

If a bettor places **€10 Each-Way**, the wager is structured as:

* **€10 on the selection to win**
* **€10 on the selection to place**

**Total stake:** <mark style="color:$danger;">€20</mark>

### Settlement of Each-Way Bets

The outcome of an Each-Way bet depends on the final finishing position of the selection.

#### 1. Selection Wins (1st Place)

Both parts of the bet are successful:

* The **win portion** is paid at the **full advertised odds**.
* The **place portion** is paid at **reduced odds**, a fraction of the win odds (e.g., 1/4 or 1/5)

#### 2. Selection Places but Does Not Win

* The **win portion loses**.
* The **place portion wins** at the applicable **place odds fraction**.

#### 3. Selection Finishes Outside the Place Positions

* Both the **win and place portions lose**.

#### 4. Selection is Scratched

* Both the **win and place portions are refunded**.

#### 5. A Scratching Happens in the Race

* Deductions get applied that **will affect the payout for 1. and 2. point above**.

### Place Terms

The number of finishing positions that qualify as a **place** depends on the **type of event and number of participants**.

The **place odds** are calculated as a **fraction of the win odds** (for example, 1/4 or 1/5).\
\
**Calculation formula** for Each-Way place odds:\
(Win Odds - 1) / Fraction Denominator + 1 = Place Odds

| Number of Participants  | Places Paid | Place Terms (Fraction Denominator) |
| ----------------------- | ----------- | ---------------------------------- |
| 1–4 Runners             | Top 1       | Win Only                           |
| 5–7 Runners             | Top 2       | 1/4th of the odds (4)              |
| Non Handicap 8+ Runners | Top 3       | 1/5th of the odds (5)              |
| Handicap 8-11 Runners   | Top 3       | 1/5th of the odds (5)              |
| Handicap 12-15 Runners  | Top 3       | 1/4th of the odds (4)              |
| Handicap 16+ Runners    | Top 4       | 1/4th of the odds (4)              |

## Scratchings and Deductions

If a **runner is scratched (withdrawn)** from the race **after a bet has been placed**, **deductions may apply**.

**Key principles:**

* **Deductions reduce potential winnings, not the original odds displayed at the time of the bet.**
* **Deductions apply separately to both the Win and Place parts of an Each-Way bet.**
* **If multiple runners are scratched, the deductions are cumulative and added together.**

These deductions are applied to **any returns** if the selection wins or places.

### Place Terms

**If the number of runners decreases after scratchings and fewer places are paid, the place portion of the bet is not automatically refunded.**

* The **stake and odds remain unchanged**
* Only the **number of paid placing positions and potential payout conditions change**

### Impact of Scratchings on Place Terms

#### 5–7 Runner Races

If a scratching reduces the field size so that **place betting no longer applies**:

* The **Place portion of the Each-Way bet is refunded**.
* The **Win portion remains valid**.

However:

* **Deductions still apply to the Win portion** due to the scratched runner.

#### 7–8 Runner Races

If the race originally qualifies for **Top 3 places** but **one runner is scratched**, reducing the field:

* The race may now only pay **Top 2 places**.
* The **Place part of the Each-Way bet remains active and is not refunded**.
* The selection must now finish **Top 2** to win the Place portion.

## Summary of Key Rules

* **Initial stake needs to be sent as doubled**
* **Each-Way bet = Win bet + Place bet**
* **Scratchings may trigger deductions**
* **Deductions reduce winnings, not the odds**
* **Deductions apply to both Win and Place parts**
* **Multiple scratchings result in cumulative deductions**
* **Place terms depend on the final number of runners**
* **Changes in field size can reduce the number of paid places**
* **Place bets are only refunded if the race no longer qualifies for place betting**

### API snapshot of Each-Way market:

```json
    {
      "id": 71356478,
      "name": "Each way",
      "tradingStatus": 0,
      "selections": [
        {
          "id": 43256028,
          "name": "Magic Carats",
          "probability": 0.46219265,
          "price": 0,
          "originalPrice": 0,
          "status": 1,                // Scratched selection
          "settlement": 0,
          "deadHeatFactor": 0,
          "extraParameters": {
            "CompetitorId": "864348",
            "EWPlacePrice": "0.8"
          },
          "isBetBuilderSupported": false,
          "competitorId": 864348
        },
        {
          "id": 41009286,
          "name": "Invasore",
          "probability": 0.07579959,
          "price": 5.5,               // Price that needs to be sent in Each-Way bet request
          "originalPrice": 5.5,
          "status": 0,
          "settlement": 0,
          "deadHeatFactor": 0,
          "extraParameters": {
            "CompetitorId": "651667",
            "EWPlacePrice": "1.9".    // Each-Way place price, used for Place calculation
          },
          "isBetBuilderSupported": false,
          "competitorId": 651667
        },
        {
          "id": 43001466,
          "name": "Ginger Fizz",
          "probability": 0.011647254,
          "price": 34,
          "originalPrice": 34,
          "status": 0,
          "settlement": 0,
          "deadHeatFactor": 0,
          "extraParameters": {
            "CompetitorId": "845302",
            "EWPlacePrice": "7.6"
          },
          "isBetBuilderSupported": false,
          "competitorId": 845302
        },
        {
          "id": 47631768,
          "name": "Newhaven Prince",
          "probability": 0.12987614,
          "price": 3.3,
          "originalPrice": 3.3,
          "status": 0,
          "settlement": 0,
          "deadHeatFactor": 0,
          "extraParameters": {
            "CompetitorId": "1094833",
            "EWPlacePrice": "1.46"
          },
          "isBetBuilderSupported": false,
          "competitorId": 1094833
        },
        {
          "id": 47609717,
          "name": "Billionaire's Row",
          "probability": 0.054076537,
          "price": 7.5,
          "originalPrice": 7.5,
          "status": 0,
          "settlement": 0,
          "deadHeatFactor": 0,
          "extraParameters": {
            "CompetitorId": "1093390",
            "EWPlacePrice": "2.3"
          },
          "isBetBuilderSupported": false,
          "competitorId": 1093390
        },
        {
          "id": 40526804,
          "name": "Luna Ballet",
          "probability": 0.12201886,
          "price": 3.5,
          "originalPrice": 3.5,
          "status": 0,
          "settlement": 0,
          "deadHeatFactor": 0,
          "extraParameters": {
            "CompetitorId": "621658",
            "EWPlacePrice": "1.5"
          },
          "isBetBuilderSupported": false,
          "competitorId": 621658
        },
        {
          "id": 39848162,
          "name": "I'm Back Baby",
          "probability": 0.004621926,
          "price": 91,
          "originalPrice": 91,
          "status": 0,
          "settlement": 0,
          "deadHeatFactor": 0,
          "extraParameters": {
            "CompetitorId": "548439",
            "EWPlacePrice": "19"
          },
          "isBetBuilderSupported": false,
          "competitorId": 548439
        },
        {
          "id": 47433661,
          "name": "Bambun Girl",
          "probability": 0.021260861,
          "price": 18,
          "originalPrice": 18,
          "status": 0,
          "settlement": 0,
          "deadHeatFactor": 0,
          "extraParameters": {
            "CompetitorId": "1088238",
            "EWPlacePrice": "4.4"
          },
          "isBetBuilderSupported": false,
          "competitorId": 1088238
        },
        {
          "id": 43645483,
          "name": "Queen Selyse",
          "probability": 0.100757994,
          "price": 4.2,
          "originalPrice": 4.2,
          "status": 0,
          "settlement": 0,
          "deadHeatFactor": 0,
          "extraParameters": {
            "CompetitorId": "885946",
            "EWPlacePrice": "1.64"
          },
          "isBetBuilderSupported": false,
          "competitorId": 885946
        },
        {
          "id": 46552572,
          "name": "Impending Lass",
          "probability": 0.009798484,
          "price": 41,
          "originalPrice": 41,
          "status": 0,
          "settlement": 0,
          "deadHeatFactor": 0,
          "extraParameters": {
            "CompetitorId": "981591",
            "EWPlacePrice": "9"
          },
          "isBetBuilderSupported": false,
          "competitorId": 981591
        },
        {
          "id": 47695612,
          "name": "Princess Toronado",
          "probability": 0.007949714,
          "price": 51,
          "originalPrice": 51,
          "status": 0,
          "settlement": 0,
          "deadHeatFactor": 0,
          "extraParameters": {
            "CompetitorId": "1097137",
            "EWPlacePrice": "11"
          },
          "isBetBuilderSupported": false,
          "competitorId": 1097137
        }
      ],
      "type": 16517745,
      "isBestLine": false,
      "parameters": {},
      "extraParameters": {
        "MarketFeatures": "EachWay",
        "LastScratchedAt": "2026-03-17T11:36:06.8270000Z",  // When last scratching happened
        "ScratchedPositions": "[0]",  // Showing competitor 1 as scratched, counting from 0
        "IsExotics": "false",
        "IsFixedExotics": "false",
        "IsEW": "normal",  // Each-Way market indicator. 
                           // Value "normal" or "handicap" is used for Place Terms
        "Runners": "11" // Amount of runners in event, used for Place Terms
      },
      "isBetBuilderSupported": false
    }
```


# Bet Placement

### Bet Placement Flow <a href="#bet-placement-flow" id="bet-placement-flow"></a>

{% content-ref url="/pages/2l7cTFxJAk5U4UAqv2Er" %}
[Bets API](/odds88-client-api/odds88-api-endpoints/bets-api)
{% endcontent-ref %}

* **Bet Placement Rules:**
  * Bets are allowed as single or multi bets on Each-Way markets.
  * Multi bets are allowed **only on** **different events** **with Each-Way markets**.
  * When including Each-Way selections in a multi bet, the bet is essentially **split into two parallel multi bets running simultaneously:**
    1. **Win multi** — using the win part of each selection
    2. **Place multi** — using the place part of each selection
  * Each-Way bets are only allowed for markets with extraParameter:
    * `Market.ExtraParameters : { "IsEW": "normal" or "handicap" }`
  * If a bettor places **€10 as Each-Way** bet **it needs to be sent as doubled** meaning <mark style="color:$danger;">**total stake is €20**</mark>

Single bet example with **total stake**:

<pre class="language-json"><code class="lang-json">{  
  "id": "TestBet88",
  "player": {
    "deviceId": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.212 Safari/537.36",
    "languageId": "en",
    "ip": "0.0.0.0",
    "segmentId": 1000
  },
  "priceChange": 1,
  "items": [
    {
      "eventId": 12345,
      "marketId": 71356478,
      "selectionId": 41009286,
<strong>      "price": 5.5
</strong>    }
  ],
  "betType": 0,
  "amount": {
    "currency": "EUR",
    "value": 200000,
    "precision": 4
  }
}
</code></pre>

Multi bet example with **total stake**:

<pre class="language-json"><code class="lang-json">{  
  "id": "TestBet88",
  "player": {
    "deviceId": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.212 Safari/537.36",
    "languageId": "en",
    "ip": "0.0.0.0",
    "segmentId": 1000
  },
  "priceChange": 1,
  "items": [
    {
      "eventId": 12345,
      "marketId": 71356478,
      "selectionId": 41009286,
<strong>      "price": 5.5
</strong>    },
    {
      "eventId": 54321,
      "marketId": 71356478,
      "selectionId": 37593953,
      "price": 2.5
    }
  ],
  "betType": 0,
  "amount": {
    "currency": "EUR",
    "value": 200000,
    "precision": 4
  }
}
</code></pre>


# Settlement

Information about bet settlement results are sent to the client as any other settlement information via **Settlement feed**

{% content-ref url="/pages/pCOsbPzku2QUbexzwct0" %}
[Settlement Feed](/odds88-client-api/odds88-feeds/settlement-feed)
{% endcontent-ref %}

Inside **selections** we have two properties for Each-Way settlements specifically:

`PlaceDeadHeatFactor` - representing place market dead heat factor for Each-Way bets. **It will be always null for non Each-Way bets.**

`EachWayPrice` - it is an object consisting of two sub-properties:

1. `Win` - represents win price
2. `Place` - represents place price

**Both will always be null for non Each-Way bets**

**Selections have a** **new settlement result value**: `PlaceWin (7)`\
Meaning for that selection **win market was lost** but **place market was won**.

Settlement example:

```json
{
  "amount": {
    "currency": "EUR",
    "value": 200000,
    "precision": 4,
    "placementExchangeRate": 1.15339322519887,
    "settlementExchangeRate": 1.1533932251988739
  },
  "betId": "TestBet88",
  "betSettlement": 1,
  "payoutMultiplier": 0.6696,
  "isCancelled": false,
  "selections": [
    {
      "event": {
        "id": 9817831,
        "name": "Hollywoodbets Durbanville Welcomes You Maiden Juve...",
        "isLive": false,
        "startTime": "2026-03-18T10:45:00"
      },
      "market": {
        "id": 71356478,
        "type": 16517745,
        "name": "Each way",
        "properties": {
          "IsEW": "normal",
          "Runners": "8",
          "IsExotics": "false",
          "IsFixedExotics": "false",
          "MarketFeatures": "EachWay",
          "LastScratchedAt": "03/18/2026 05:37:18",
          "RacingDeductions": "[{\"DeductionUnixTimestamp\":1773812238,\"DeductionPercent\":0.0}]",
          "ScratchedPositions": "[2]",
          "PlaceRacingDeductions": "[{\"DeductionUnixTimestamp\":1773812238,\"DeductionPercent\":0.0}]"
        }
      },
      "selectionId": 47554165,
      "competitionId": 17412,
      "countryId": 146,
      "sportId": 457,
      "settlement": {
        "settlementResult": 1,
        "settlementTime": "2026-03-18T10:53:23.9583851Z",
        "settlementVersion": 1
      },
      "price": 1.4,
      "eachWayPrice": {
        "win": 1.4,
        "place": 1.08
      },
      "limitsRatingId": 2017,
      "limitsFactor": 1.1,
      "hasLineDeviation": false,
      "isOutright": false,
      "version": 1,
      "deadHeatFactor": 0,
      "placeDeadHeatFactor": null,
      "parameters": {
        "IsEW": "normal",
        "Runners": "8",
        "IsExotics": "false",
        "IsFixedExotics": "false",
        "MarketFeatures": "EachWay",
        "LastScratchedAt": "03/18/2026 05:37:18",
        "RacingDeductions": "[{\"DeductionUnixTimestamp\":1773812238,\"DeductionPercent\":0.0}]",
        "ScratchedPositions": "[2]",
        "PlaceRacingDeductions": "[{\"DeductionUnixTimestamp\":1773812238,\"DeductionPercent\":0.0}]"
      },
      "manualPrice": null,
      "alternativePrice": null,
      "type": 7,
      "betBuilderItems": []
    },
    {
      "event": {
        "id": 9816109,
        "name": "Race 6",
        "isLive": false,
        "startTime": "2026-03-18T10:44:00"
      },
      "market": {
        "id": 71356478,
        "type": 16517745,
        "name": "Each way",
        "properties": {
          "IsEW": "normal",
          "Runners": "9",
          "IsExotics": "false",
          "IsFixedExotics": "false",
          "MarketFeatures": "EachWay",
          "LastScratchedAt": "2026-03-18T00:35:50.4933422Z",
          "RacingDeductions": "[{\"DeductionUnixTimestamp\":1773794150,\"DeductionPercent\":0.03}]",
          "ScratchedPositions": "[9]",
          "PlaceRacingDeductions": "[{\"DeductionUnixTimestamp\":1773794150,\"DeductionPercent\":0.03}]"
        }
      },
      "selectionId": 43136759,
      "competitionId": 10259,
      "countryId": 59,
      "sportId": 457,
      "settlement": {
        "settlementResult": 7,
        "settlementTime": "2026-03-18T10:54:10.4510358Z",
        "settlementVersion": 1
      },
      "price": 2.2,
      "eachWayPrice": {
        "win": 2.2,
        "place": 1.24
      },
      "limitsRatingId": 2017,
      "limitsFactor": 1.1,
      "hasLineDeviation": false,
      "isOutright": false,
      "version": 1,
      "deadHeatFactor": 0,
      "placeDeadHeatFactor": null,
      "parameters": {
        "IsEW": "normal",
        "Runners": "9",
        "IsExotics": "false",
        "IsFixedExotics": "false",
        "MarketFeatures": "EachWay",
        "LastScratchedAt": "2026-03-18T00:35:50.4933422Z",
        "RacingDeductions": "[{\"DeductionUnixTimestamp\":1773794150,\"DeductionPercent\":0.03}]",
        "ScratchedPositions": "[9]",
        "PlaceRacingDeductions": "[{\"DeductionUnixTimestamp\":1773794150,\"DeductionPercent\":0.03}]"
      },
      "manualPrice": null,
      "alternativePrice": null,
      "type": 7,
      "betBuilderItems": []
    }
  ],
  "isRejected": false,
  "settlementTime": "2026-03-18T10:54:10.545294",
  "payout": 133920,
  "partialRefund": 0
}
```


# Fixed Exotics Integration

This section of the document covers the integration of Racing Fixed Exotics.\
Racing Fixed Exotic markets follow a separate bet placement flow and have a dedicated endpoint for fetching prices which means they’ll need additional implementation from the main integration.


# Markets

Odds88 currently offers the following Fixed Exotics markets:

* Quinella - EX\_QNL

A **Quinella** bet involves selecting two horses in a race to finish in the top two positions, but the order in which they finish doesn't matter. As long as the two horses the player picked finish first and second, they win the bet.<br>

* Exacta - EX\_EXA

An **Exacta** bet involves selecting 2 horses in a race to finish in the top two positions where the player also has to correctly predict which is 1st and which is second.<br>

* Trifecta - EX\_TRI

A **Trifecta** is a type of bet where the player must correctly predict the first three horses to finish a race in the exact order.

\
These markets are only available in Thoroughbred, Greyhound and Harness racing events.

{% hint style="warning" %}
Fixed Exotics markets are not available for every event.
{% endhint %}


# Data Format

All Fixed Exotics markets have additional properties in “**extraParameters**”, that are needed to operate with them correctly.

* “**MarketFeatures**” - Replaces “**MarketType**” in Fixed Exotic markets
* “**ScratchedPositions**” - list of scratched competitors. The first competitor number is ‘0’.
* “**IsExotics**” - Identifier for Exotic markets
* “**IsFixedExotics**” - Identifier for Fixed Exotic markets.\\

Quinella market example:

```javascript
  {
  "id": 20714375,
        "name": "EX_QNL",
        "tradingStatus": 3,
        "selections": [
          {
            "id": 39907116,
            "name": "Fort William",
            "probability": 0,
            "price": 0,
            "originalPrice": 0,
            "status": 3,
            "settlement": 0,
            "deadHeatFactor": 0,
            "extraParameters": {}
          },
          {
            "id": 39964388,
            "name": "From The Basement",
            "probability": 0,
            "price": 0,
            "originalPrice": 0,
            "status": 3,
            "settlement": 0,
            "deadHeatFactor": 0,
            "extraParameters": {}
          },
          {
            "id": 39555108,
            "name": "Universal Harmony",
            "probability": 0,
            "price": 0,
            "originalPrice": 0,
            "status": 3,
            "settlement": 0,
            "deadHeatFactor": 0,
            "extraParameters": {}
          },
          {
            "id": 39263028,
            "name": "Sakowin",
            "probability": 0,
            "price": 0,
            "originalPrice": 0,
            "status": 3,
            "settlement": 0,
            "deadHeatFactor": 0,
            "extraParameters": {}
          },
          {
            "id": 41079594,
            "name": "Struggle Street",
            "probability": 0,
            "price": 0,
            "originalPrice": 0,
            "status": 3,
            "settlement": 0,
            "deadHeatFactor": 0,
            "extraParameters": {}
          },
          {
            "id": 41079595,
            "name": "Vanishing",
            "probability": 0,
            "price": 0,
            "originalPrice": 0,
            "status": 3,
            "settlement": 0,
            "deadHeatFactor": 0,
            "extraParameters": {}
          },
          {
            "id": 39533791,
            "name": "Winsome Flowers",
            "probability": 0,
            "price": 0,
            "originalPrice": 0,
            "status": 3,
            "settlement": 0,
            "deadHeatFactor": 0,
            "extraParameters": {}
          }
        ],
        "type": 2529113,
        "isBestLine": false,
        "parameters": {},
        "extraParameters": {
          "MarketFeatures": "FixedExoticsQuinella",
          "ScratchedPositions": "[]",
          "IsExotics": "false",
          "IsFixedExotics": "true"
        }
      }
```


# Price Calculation

All selections in Fixed Exotics markets have **“price”: 0**.\
In order to fetch the price for the selection a player made, you are required to make a request to the Fixed Exotics price API endpoint.

{% content-ref url="/pages/1qQEIIebgl2RiPxhObg0" %}
[Fixed Exotics API](/odds88-client-api/odds88-api-endpoints/fixed-exotics-api)
{% endcontent-ref %}

Request body must contain **eventId**, **marketId** and **racingSelection** like in the following example:

```javascript
{
  "eventId": 4183647,
  "marketId": 22369909,
  "racingSelection": "EXACTA 1/8"
}
```

**racingSelection** should contain the name of the market (**EXACTA**, **QUINELLA** or **TRIFECTA**), followed by the selection itself. In Quinella, selections are separated by dot **(.)** and the order of selections is not important ( **QUINELLA 1.8 = QUINELLA 8.1** ). In exacta and trifecta, selections are separated by **(/)** and the order of selections is important ( **EXACTA 1/8 != EXACTA 8/1** ), different orders will result in different prices for these markets.

Response for this request is the price for the specified selection:

```javascript
{
  "rejectReason": 0,
  "message": "Checks passed",
  "odds": 51
}
```

Possible rejection reasons can be checked via the corresponding dictionary endpoint.

{% content-ref url="/pages/0BwLugNGCPLWrFx90Siq" %}
[Dictionary API](/odds88-client-api/odds88-api-endpoints/dictionary-api)
{% endcontent-ref %}


# Bet Placement

In order for a bet to be placed, you are required to send a bet placement request to the betplacement API endpoint

{% content-ref url="/pages/2l7cTFxJAk5U4UAqv2Er" %}
[Bets API](/odds88-client-api/odds88-api-endpoints/bets-api)
{% endcontent-ref %}

The following properties are required to have specific value in order for the bet to be accepted:\
`eventId`: ID of the event\
`marketId`: ID of the market\
`selectionId`: `-1`\
`racingSelection`: name of market and combination. Example:

* `EXACTA 1/2`
* **`TRIFECTA 1/2/3`**
* **`QUINELLA 1.2`**

{% hint style="warning" %}
Fixed Exotics **cannot** be combined in a multibet and will be rejected by Odds88.
{% endhint %}

Example of placing bet on Greyhound Trifecta:

```json
{
  "id": "string",
  "player": {
    "deviceId": "string",
    "languageId": "English",
    "ip": "123.123.123.123",
    "segmentId": 1234,
    "channel": "string"
  },
  "amount": {
    "currency": "USD",
    "value": 50000,
    "precision": 4
  },
  "priceChange": 2,
  "items": [
    {
      "eventId": 400140,
      "marketId": 20714470,
      "selectionId": -1,
      "racingSelection": "TRIFECTA 3/4/1",
      "price": 501
    }
  ]
}

```


# UI Example

It is recommended to follow similar UI layouts for Racing Fixed Exotics as in the examples below. You are free to use your own UI layout.

Quinella:

<figure><img src="/files/RZwDUokH2HejdOns0jHu" alt=""><figcaption></figcaption></figure>

Exacta:

<figure><img src="/files/vc6jEauzs9B5j1iZQXs3" alt=""><figcaption></figcaption></figure>

Trifecta:

<figure><img src="/files/SK5njNHpmopCjKAnpOx3" alt=""><figcaption></figcaption></figure>


# Alternative Odds Integration

This part of the document aims to provide an overview of Alternative Odds and its integration. Alternative Odds is a feature whereby players who wish to bet amounts higher than the liability limit allows, are still allowed to do so but at a lower odds than the original price.

For example:

* A player wishes to bet 50k€ on Sinner to beat Alcaraz at odds of 2.2 but the liability for this kind of bet is too high.
* Normally this bet would simply be rejected and a high value player could be lost, but with Alternative Odds, we offer the player 2.1 odds instead.
* With Alternative Odds - the wagered amount will stay the same, but the odds price will be lowered.
* This means when the player tries to place the bet but the liability is too high - the player should be given an option to accept or decline the alternative odds.

{% hint style="warning" %}
Alternative odds is only triggered **after** any “odds change” during the bet placement, which means bet will still be accepted as normal if, for example, the player has “**Accept all odds changes**” enabled and odds change to a price which has been set up in the alternative odds configuration.
{% endhint %}

\
The BetPlacement flow with Alternative odds works as follows:

1. The player chooses the wager amount and presses the button for the bet placement process to begin.
2. We check if the wagered amount exceeds the liability limit on the selected price:
3. Liability limit is not exceeded the bet is accepted
4. Liability limit is exceeded:
5. We will return a rejection with the corresponding reason- **PlayerBetLimitExceeded**

<i class="fa-arrow-right-long">:arrow-right-long:</i> The rejection will contain 2 parameters:

<i class="fa-arrow-right-long">:arrow-right-long:</i> **AlternativeOddsId** (String) - Unique Key

<i class="fa-arrow-right-long">:arrow-right-long:</i> **AlternativePrice** (Decimal) - Adjusted odds price

<i class="fa-arrow-right-long">:arrow-right-long:</i> Player is presented with the option to either accept or decline the alternative odds:

<i class="fa-arrow-right-long">:arrow-right-long:</i> If it is declined - the bet placement flow ends and the bet is not placed

<i class="fa-arrow-right-long">:arrow-right-long:</i> If the player agrees to the new price, we need to receive a new BetPlacement request which contains the parameters corresponding to those previously sent in the rejection and the bet will be placed.

New properties:\
On **BetPlacement.BetRequestViewModel**:

1. alternativeOddsId (String) - Unique Key
2. alternativePrice (Decimal) - Adjusted odds price

On **BetPlacement.RejectInfoViewModel**:

1. Alternative odds specific rejection reasons:

<i class="fa-arrow-right-long">:arrow-right-long:</i> 62 = AlternativeOddsExpired (Alternative odds is expired or not available)

<i class="fa-arrow-right-long">:arrow-right-long:</i> 63 = AlternativeOddsPriceInvalid (Alternative odds price is invalid)

<i class="fa-arrow-right-long">:arrow-right-long:</i> 64 = AlternativeOddsBetItemsInvalid (Alternative odds bet item(s) are invalid)

<i class="fa-arrow-right-long">:arrow-right-long:</i> 65 = AlternativeOddsBetAmountInvalid (Alternative odds bet amount is invalid)

2. betItem\[]

<i class="fa-arrow-right-long">:arrow-right-long:</i> alternativePrice(Decimal)

3. alternativeOdds\[]

<i class="fa-arrow-right-long">:arrow-right-long:</i> id(String)

<i class="fa-arrow-right-long">:arrow-right-long:</i> alternativePrice(Decimal)

<i class="fa-arrow-right-long">:arrow-right-long:</i> createdAt(String) - Timestamp the offer was created

<i class="fa-arrow-right-long">:arrow-right-long:</i> expiredAt(String) - Timestamp the offer expires

{% hint style="warning" %}
Bets placed with Alternative Odds are still sent via the betplacement endpoint.\
It is only required to add the 2 additional parameters specified in the limit exceeded rejection.
{% endhint %}

{% content-ref url="/pages/2l7cTFxJAk5U4UAqv2Er" %}
[Bets API](/odds88-client-api/odds88-api-endpoints/bets-api)
{% endcontent-ref %}


# Statuses

This part describes what are existing statuses for different entities in Odds88 and what is the expected reaction to these statuses.


# Event status

Event in Odds88 feed has 2 status values:

* **status** which corresponds to sport event status from feed provider
* **tradingStatus** which corresponds to event display status and is aggregation of feed provider event status, feed status (up, down) for the feed provider and configuration inside the Odds88

Known values for **status** are listed in swagger under the EventStatus enumeration:

* 0 = Unknown (Event status is unknown)
* 1 = Planned (Event is scheduled to start at the kickoff time )
* 2 = SoonInPlay (Pre-live status transition to Live status)
* 3 = Live (Event is in play)
* 4 = Completed (Event finished)
* 5 = Cancelled (Event is cancelled)
* 6 = CoverageLost (Lost updates from provider, betting should be closed)
* 7 = Closed (Event closed end will not be reopened)
* 8 = Suspended (Event suspended and might be re opened)
* 9 = Postponed (Event did not start and will not be played due to weather conditions for example)
* 10 = Abandoned (Event abandoned)

These values can be used to understand what is the current progression of the sport event.

Known values for **tradingStatus** are listed in swagger under the TradingStatus enumeration:

* 0 = Open (Trading is active)
* 1 = Suspended (Trading is suspended, but keep event on site)
* 2 = Closed (Remove event from site)
* 3 = Inactive (Remove from site, but we can change the status to inplay/live and turn back this event on the site)

Trading status value describes how events should be processed and displayed.

* **Open** - event is active and available for trading.
* **Suspended** - event is temporarily not available for trading, but may become available at some point.
* **Closed** - event is closed for trading from our side or providers side.
* **Inactive** - event has finished or is missing configuration.


# Market status

Market in Odds88 has only a `tradingStatus` field which has the same type as event’s: TradingStatus enumeration.

Trading status value actually describes how markets should be processed and displayed.

* **Open** - market is active and available for trading.
* **Suspended** - market is temporarily not available for trading, but may become available at some point.
* **Closed** - market is closed, usually this is the final status but there is no guarantee it will not switch after some time.
* **Inactive** - market is not available for trading due to some reason (usually configuration). The market should be not visible to clients but may change its status at some moment.

Event’s trading status has higher priority than market’s meaning that even if the market inside an Inactive event is Open, bets will not be accepted.

At the same time if the event's trading status is Open but market’s is Inactive, bets will also not be accepted.

During some specific operations (like trading configuration change for events) the market may change its status quickly.

Example: Open → Inactive → Suspended → Open


# Selection status

Selection in Odds88 has a **`status`** field which has the same type as event’s and market’s trading status: **TradingStatus** enumeration.

Expected reaction for selection’s status should correspond to the market’s. Markets `tradingStatus` has higher priority than selection `status`**.**

Each selection also has a separate settlement field which corresponds to the result of the specific selection. The type of this field is **SettlementResult** enumeration.


# Test Cases

This is a collection of test cases that have to be checked during and after completion of integration to Odds88 API. Test cases are grouped by services to make it easier to select what tests to perform, depending on type of integration. Some tests may be skipped, if the functionality is not used by you.

To execute end-to-end tests Technical Integration Specialists will require an account with test funds on your platform. Testing can be started during integration still going, when certain components are fully integrated in your system, e.g. delta feed. The first round of tests is run during and after the completion of integration as a continuous process. Second round of testing is performed when you establish connection to the Odds88 production environment and are preparing for a launch.

\\


# General Tests

* Your are connected to all feeds that are meant to be used by integration.
* In case of disconnection, you automatically reconnect. Reconnect happens with appropriate revision. Zero revision reconnection should only happen in urgent cases.
* You receive a notification if disconnection from one of the feeds happens.
* Reconnect happens only for feeds that have lost connection.
* First level support is set up and reachable for you. Both operational and technical.


# Delta Feed

* You receive and processes all deltas sent by Odds88. Revision/version numbers should not have any blank spots and every next delta should have revision incrementing by one.
* One delta can have multiple messages, thus multiple revisions - one revision for every message. Messages are processed in incremental order, to ensure correct state for events on your side. If some revisions are missed, events can have incorrect status and won’t be available for betting.
* Event start time is correct.
* Score, time, period, cards and penalties data is correct.
* Events and markets are available and displayed in accordance to **status** and **tradingStatus** properties.
* Odds are updated timely.
* Correct results for markets are received and processed on your side. Related tickets are settled accordingly. In case risk management from Odds88 is not used.


# Metadata Feed

* All updates for sports are received and processed by you.
* Automatic reconnect to feed, if connection is lost. Appropriate revision is used.
* Metadata fields and properties can be **“”**(empty string) or **null**. Integration should be able to handle both cases.


# Bet Placement

* Bet can be placed on a single event.
* Bet can be placed on multiple events. Only Pre-Live, only Live and combination.
* Multibet odds are calculated correctly. Product of odds of all selections in ticket.
* For Live events specified LTD(Live Time Delay) is applied. In multibets LTD of live event with the biggest delay is applied or custom multibet LTD, which is configured on segment level.
* Advanced LTD. Bets placed during break time in a match are accepted without LTD.
* If odds change during bet processing or LTD, bet should be rejected.
* If the “accept all odds changes” option is used, bet should be accepted even if odds change. In ‘placed bets’ such bet should have correct odds
* Player ID is expected to match with regex **^\[0-9A-Za-z#\_-]\*.** Some exceptions may apply.
* Player Id should be consistent for the same player. Regardless of players currency, location, IP address and other factors that can change over time.
* If a ticket is rejected by Odds88, you receive the correct rejection reason.
* You are able to send a bet cancellation request in case it is required.
* Maximum bet size is calculated correctly for the player.
* Correct segment(s) is used by you to register bets.
* Cash out for live events has LTD implemented on the your side. **6 seconds**.
* Live time delay should be applied to cash out even if a bet was placed during pre match.
* Betplacement parameters “deviceId” and “ip” should have real values to reflect the player’s location and device from which the bet was placed.


# Settlement Feed

* You have a stable connection to settlement feed.
* You automatically reconnect the to feed in case of disconnection. Appropriate revision is used.
* Tickets that are cashed out are processed accordingly.
* Refunded tickets are processed.
* Settlement changes for tickets are processed.
* Tickets can be manually resettled from the Odds88 side. Integration should handle new settlement results. Payout amount/odds can be changed for resettled tickets.
* Resettlement can result in negative balance, if a player has 0 on a balance and previously settled as a win ticket, is resettled as lost. It should be possible to have a negative balance.


# Odds88 Client API

Information about external client API

Odds88 provides external API, which can be used to subscribe to feeds and send bets.

The API consists of 2 parts:

* REST API
* Feeds

{% content-ref url="/pages/tUs8I9T7DlcRHpPrvI2Q" %}
[Odds88 API Endpoints](/odds88-client-api/odds88-api-endpoints)
{% endcontent-ref %}

{% content-ref url="/pages/jFbuD8jgmZmFlDzigjTM" %}
[Odds88 Feeds](/odds88-client-api/odds88-feeds)
{% endcontent-ref %}


# Odds88 API Endpoints

Odds88 REST API

Odds88 provide a REST API for authorization, fetching various data and risk management.

Most of the endpoints require authorization, which can be performed with the login endpoint:

{% content-ref url="/pages/SXNEcNtOZ6g3So3KxjpR" %}
[Account API](/odds88-client-api/odds88-api-endpoints/account-api)
{% endcontent-ref %}

Bets API can be used to utilize risk management functionality of Odds88:

{% content-ref url="/pages/2l7cTFxJAk5U4UAqv2Er" %}
[Bets API](/odds88-client-api/odds88-api-endpoints/bets-api)
{% endcontent-ref %}

Cashout API can be used to configure Cashout Feed and perform cashout:

{% content-ref url="/pages/CDyqERePHyDhrua9zyke" %}
[Cashout API](/odds88-client-api/odds88-api-endpoints/cashout-api)
{% endcontent-ref %}

Currency Exchange API can be used to get information about supported currencies:

{% content-ref url="/pages/tAABok4kCnqCthSR0G3S" %}
[Currency Exchange API](/odds88-client-api/odds88-api-endpoints/currency-exchange-api)
{% endcontent-ref %}

Dictionary API can be used to get static values information:

{% content-ref url="/pages/0BwLugNGCPLWrFx90Siq" %}
[Dictionary API](/odds88-client-api/odds88-api-endpoints/dictionary-api)
{% endcontent-ref %}

Fixed Exotics API can be used to get odds for fixed exotics bet:

{% content-ref url="/pages/1qQEIIebgl2RiPxhObg0" %}
[Fixed Exotics API](/odds88-client-api/odds88-api-endpoints/fixed-exotics-api)
{% endcontent-ref %}

Feed API can be used to get event schedule and snapshots:

{% content-ref url="/pages/h3o5Gc9hfa2wPBJPwuMr" %}
[Feed API](/odds88-client-api/odds88-api-endpoints/feed-api)
{% endcontent-ref %}

Global metadata and metadata API can be used to get supplementary data for different entities and events:

{% content-ref url="/pages/gKP72bfeYJzaPQyaONPJ" %}
[Global Metadata API](/odds88-client-api/odds88-api-endpoints/global-metadata-api)
{% endcontent-ref %}

{% content-ref url="/pages/pwg5sZEvLfdflkvSxByU" %}
[Metadata API](/odds88-client-api/odds88-api-endpoints/metadata-api)
{% endcontent-ref %}

Ratings API can be used to get info about event and league ratings:

{% content-ref url="/pages/bxCZW1uy8wJglaNnLyFK" %}
[Ratings API](/odds88-client-api/odds88-api-endpoints/ratings-api)
{% endcontent-ref %}

Schema API can be used to get internal entities which exist in Odds88:

{% content-ref url="/pages/rHNx9WWnIBUWvPdJN4Ad" %}
[Schema API](/odds88-client-api/odds88-api-endpoints/schema-api)
{% endcontent-ref %}

Translations API can be used to fetch translations for various entities and events:

{% content-ref url="/pages/oWKeORcewlu5QLu5ank9" %}
[Translations API](/odds88-client-api/odds88-api-endpoints/translations-api)
{% endcontent-ref %}

{% hint style="warning" %}
Most of the endpoints are rate-limited.
{% endhint %}


# Account API

Authorization endpoints

Account API is used to authorize in the system.

It outputs access token, which can be used to access all other endpoints and feeds.

{% hint style="info" %}
Access token can and should be reused for up to 24 hours.
{% endhint %}

{% hint style="warning" %}
The endpoint is rate-limited to 12 requests per second.
{% endhint %}

## Log in to the system.

> \
> \*\*Rate Limits (per account):\*\*\
> \- \*\*5 req/1s\*\*

```json
{"openapi":"3.0.4","info":{"title":"[T728-STAGE] Odds88 API","version":"v1"},"tags":[{"name":"Account"}],"security":[],"paths":{"/api/Account/login":{"post":{"tags":["Account"],"summary":"Log in to the system.","description":"\n**Rate Limits (per account):**\n- **5 req/1s**","operationId":"Login","requestBody":{"description":"Credentials of client.","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/Marlin.SportsbetApi.Host.Authentication.LoginModel"}]}},"text/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/Marlin.SportsbetApi.Host.Authentication.LoginModel"}]}},"application/*+json":{"schema":{"allOf":[{"$ref":"#/components/schemas/Marlin.SportsbetApi.Host.Authentication.LoginModel"}]}}}},"responses":{"200":{"description":"OK","content":{"text/plain":{"schema":{"type":"string"}},"application/json":{"schema":{"type":"string"}},"text/json":{"schema":{"type":"string"}}}},"429":{"description":"Too many requests"}}}}},"components":{"schemas":{"Marlin.SportsbetApi.Host.Authentication.LoginModel":{"required":["clientId","password"],"type":"object","properties":{"clientId":{"minLength":1,"type":"string"},"password":{"minLength":1,"type":"string"}},"additionalProperties":false}}}}
```


# Bets API

Risk management endpoins

Bets API endpoints are used as a part of risk management service.

The most important endpoints are below.

## Bet Placement Endpoint

Can be used to send bets to Odds88.

The bet will be validated according to related event(s), market(s), selection(s) statuses, odds and liabilities.

The response will contain a recommendation whether to accept or reject the bet.

{% hint style="warning" %}
The endpoint should be called after the funds has been reserved on the player's account.

If the response it "accepted", the bet will be saved in Odds88 system.
{% endhint %}

{% hint style="warning" %}
This endpoint has a LTD (Live Time Delay) implemented for events which are Live. The bets will only be accepted after a predetermined period, depending on the event’s level and network latency.
{% endhint %}

{% hint style="info" %}
`playerId` must be consistent for the same player regardless of the currency that is used.
{% endhint %}

## PUT /api/players/{playerId}/Bets/V2

> Places bet from specific player (multi-currency).

```json
{"openapi":"3.0.4","info":{"title":"[T728-STAGE] Odds88 API","version":"v1"},"tags":[{"name":"Bets"}],"security":[{"Bearer":[]}],"components":{"securitySchemes":{"Bearer":{"type":"http","description":"JWT Authorization header using the Bearer scheme. Example: \"Authorization: Bearer {token}\"","scheme":"Bearer","bearerFormat":"JWT"}},"schemas":{"Marlin.SportsbetApi.Host.Models.BetPlacement.BetRequestViewModelV2":{"type":"object","properties":{"id":{"type":"string","description":"Unique request id (in the client's system);","nullable":true},"player":{"allOf":[{"$ref":"#/components/schemas/Marlin.SportsbetApi.Host.Models.BetPlacement.PlayerViewModel"}],"description":"Identification of the end user. Contains information about Ip, language and device from which bet was placed.","nullable":true},"priceChange":{"allOf":[{"$ref":"#/components/schemas/Marlin.SportsbetApi.Host.Models.BetPlacement.PriceChange"}],"description":"Price change auto acceptance. (None - 0, Any - 1, Higher - 2)\n\n* `0` - None\n* `1` - Any\n* `2` - Higher"},"items":{"type":"array","items":{"$ref":"#/components/schemas/Marlin.SportsbetApi.Host.Models.BetPlacement.BetItemRequestViewModel"},"description":"List of bet items","nullable":true},"alternativeOddsId":{"type":"string","description":"ID of alternative odds offer in case if liability was exceeded","nullable":true},"alternativePrice":{"type":"number","description":"Alternative odds offer value","format":"double","nullable":true},"customPayoutMultiplier":{"type":"number","description":"Custom payout multiplier","format":"double","nullable":true},"betType":{"type":"integer","description":"Bet Type. (Standard - 0, Pickem - 1)","format":"int32"},"freeBetType":{"type":"integer","description":"Free Bet Type. (NotFree = 0, BasicFreeBet = 1)","format":"int32"},"riskManagementOverride":{"allOf":[{"$ref":"#/components/schemas/Marlin.SportsbetApi.Host.Models.BetPlacement.RiskManagementOverrideViewModel"}],"description":"Optional risk-management override. When set, links this bet to a previously placed bet\n(via OriginalBetId) and disables specific validations (ValidationOverrides: 1 = limits,\n2 = price). Cannot be combined with AlternativeOddsId.","nullable":true},"amount":{"allOf":[{"$ref":"#/components/schemas/Marlin.SportsbetApi.Host.Models.BetPlacement.BetAmountRequestViewModel"}],"description":"Bet amount model","nullable":true}},"additionalProperties":false,"description":"Represents bet request."},"Marlin.SportsbetApi.Host.Models.BetPlacement.PlayerViewModel":{"type":"object","properties":{"deviceId":{"type":"string","description":"End user's device id","nullable":true},"languageId":{"type":"string","description":"ISO 639-1 language code","nullable":true},"ip":{"type":"string","description":"End user's IP","nullable":true},"segmentId":{"type":"integer","description":"End user's limit Id","format":"int32"}},"additionalProperties":false,"description":"Represents player data."},"Marlin.SportsbetApi.Host.Models.BetPlacement.PriceChange":{"enum":[0,1,2],"type":"integer","description":"Types of price change acceptance.\n\n* `0` - None\n* `1` - Any\n* `2` - Higher","format":"int32"},"Marlin.SportsbetApi.Host.Models.BetPlacement.BetItemRequestViewModel":{"type":"object","properties":{"eventId":{"type":"integer","description":"Event id on which the bet is placed.","format":"int64"},"marketId":{"type":"integer","description":"Market id on which the bet is placed. Should be `-1` for BetBuilder bet.","format":"int64"},"selectionId":{"type":"integer","description":"Selection id on which the bet is placed. Should be `-1` for exotics/BetBuilder bet.","format":"int64"},"racingSelection":{"type":"string","description":"Racing exotics selection.","nullable":true},"price":{"type":"number","description":"Price on which the bet is placed. Should be `null` for tote exotics and SP bet.","format":"double","nullable":true},"betBuilderBetItems":{"type":"array","items":{"$ref":"#/components/schemas/Marlin.SportsbetApi.Host.Models.BetPlacement.BetBuilderBetItemViewModel"},"nullable":true}},"additionalProperties":false,"description":"Represents item inside the bet in the request."},"Marlin.SportsbetApi.Host.Models.BetPlacement.BetBuilderBetItemViewModel":{"required":["marketId","selectionId"],"type":"object","properties":{"marketId":{"maximum":9223372036854776000,"minimum":1,"type":"integer","description":"Market id of the bet item.","format":"int64"},"selectionId":{"maximum":9223372036854776000,"minimum":1,"type":"integer","description":"Selection id of the bet item.","format":"int64"}},"additionalProperties":false,"description":"Represents bet item of BetBuilder."},"Marlin.SportsbetApi.Host.Models.BetPlacement.RiskManagementOverrideViewModel":{"type":"object","properties":{"originalBetId":{"type":"string","description":"The originally placed bet's id that this attempt is referencing.","nullable":true},"validationOverrides":{"type":"array","items":{"type":"integer","format":"int32"},"description":"Validation steps to skip. 1 = limits (disable liability check), 2 = price (accept stale prices).","nullable":true}},"additionalProperties":false,"description":"Risk management override payload — sent alongside a re-attempted bet whose original\nplacement was rejected."},"Marlin.SportsbetApi.Host.Models.BetPlacement.BetAmountRequestViewModel":{"required":["precision","value"],"type":"object","properties":{"currency":{"type":"string","description":"Currency ticker symbol","nullable":true},"value":{"type":"integer","description":"Amount in local currency","format":"int64"},"precision":{"type":"integer","description":"Precision value for the provided currency","format":"int32"}},"additionalProperties":false},"Marlin.SportsbetApi.Host.Models.ResponseViewModel`1[[Marlin.SportsbetApi.Host.Models.BetPlacement.BetResultViewModelV2, Marlin.SportsbetApi.Host, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null]]":{"type":"object","properties":{"payload":{"allOf":[{"$ref":"#/components/schemas/Marlin.SportsbetApi.Host.Models.BetPlacement.BetResultViewModelV2"}],"nullable":true},"responseCode":{"allOf":[{"$ref":"#/components/schemas/Marlin.SportsbetApi.Host.Models.ResponseCode"}],"description":"* `1` - Success\n* `2` - FormatError\n* `3` - PrecisionMismatch\n* `4` - UnsupportedCurrency\n* `5` - UnsupportedFeature"},"errorMessage":{"type":"string","nullable":true}},"additionalProperties":false},"Marlin.SportsbetApi.Host.Models.BetPlacement.BetResultViewModelV2":{"type":"object","properties":{"requestId":{"type":"string","description":"External request id which was sent by client","nullable":true},"resultType":{"type":"integer","description":"Acceptance status. (Pending - 1 , Accepted - 2, Rejected -3)","format":"int32"},"createdAt":{"type":"string","description":"Date and time of request creation in UTC","format":"date-time"},"cancellationStatus":{"allOf":[{"$ref":"#/components/schemas/Marlin.SportsbetApi.Host.Models.BetPlacement.CancellationStatusViewModel"}],"description":"Detailed info about cancellation progress","nullable":true},"betProcessor":{"allOf":[{"$ref":"#/components/schemas/TradeArt.BetPlacement.Contracts.Enums.BetProcessorType"}],"description":"* `1` - Internal\n* `2` - Betradar\n* `3` - Oddin\n* `4` - OddinMixedMulties"},"rejectInfo":{"allOf":[{"$ref":"#/components/schemas/Marlin.SportsbetApi.Host.Models.BetPlacement.RejectInfoViewModelV2"}],"description":"Information about rejection cause and rejected item","nullable":true},"acceptedBet":{"allOf":[{"$ref":"#/components/schemas/Marlin.SportsbetApi.Host.Models.BetPlacement.BetResponseResponseViewModelV2"}],"description":"Accepted bet","nullable":true}},"additionalProperties":false},"Marlin.SportsbetApi.Host.Models.BetPlacement.CancellationStatusViewModel":{"type":"object","properties":{"status":{"allOf":[{"$ref":"#/components/schemas/TradeArt.BetPlacement.Contracts.Enums.CancellationStatusType"}],"description":"Cancellation status\n\n* `1` - Accepted\n* `2` - Rejected"},"message":{"type":"string","description":"Cancellation rejection reason description","nullable":true}},"additionalProperties":false},"TradeArt.BetPlacement.Contracts.Enums.CancellationStatusType":{"enum":[1,2],"type":"integer","description":"* `1` - Accepted\n* `2` - Rejected","format":"int32"},"TradeArt.BetPlacement.Contracts.Enums.BetProcessorType":{"enum":[1,2,3,4],"type":"integer","description":"* `1` - Internal\n* `2` - Betradar\n* `3` - Oddin\n* `4` - OddinMixedMulties","format":"int32"},"Marlin.SportsbetApi.Host.Models.BetPlacement.RejectInfoViewModelV2":{"type":"object","properties":{"reason":{"allOf":[{"$ref":"#/components/schemas/TradeArt.BetPlacement.Contracts.Enums.RejectReason"}],"description":"Information about rejection cause\n\n* `0` - None: Checks passed\n* `1` - PriceChanged: Price Changed\n* `2` - PriceChangedLow: Price Changed Low\n* `3` - PriceChangedHigh: Price Changed High\n* `4` - MissingMandatoryFields: Missing Mandatory Fields\n* `5` - InvalidDataFormat: Invalid Data Format\n* `6` - EventsOrMarketsCannotBeCombined: Events Or Markets Cannot Be Combined\n* `7` - SelectionsFromSameMarket: Selections From Same Market\n* `8` - MultipleSelectionsInEvent: Multiple Selections In Event\n* `9` - DuplicateTeamIds: Duplicate Team Ids\n* `10` - EventNotFound: Event Not Found\n* `11` - EventNotActive: Event Not Active\n* `12` - MarketNotFound: Market Not Found\n* `13` - MarketNotActive: Market Not Active\n* `14` - SelectionNotFound: Selection Not Found\n* `15` - SelectionNotActive: Selection Not Active\n* `16` - AdminConsoleError: Admin Console Error\n* `17` - EventLimitExceeded: Event Limit Exceeded\n* `18` - MarketLimitExceeded: Market Limit Exceeded\n* `19` - BetLimitExceeded: Bet Limit Exceeded\n* `20` - PayoutLimitExceeded: Payout Limit Exceeded\n* `21` - EventVarLimitExceeded: Event CCF Limit Exceeded\n* `22` - MarketVarLimitExceeded: Market CCF Limit Exceeded\n* `23` - BetVarLimitExceeded: Bet CCF Limit Exceeded\n* `24` - PayoutVarLimitExceeded: Payout CCF Limit Exceeded\n* `25` - TooHighOdds: Total price was too large\n* `26` - SportRestricted: Sport restricted for placing bets\n* `27` - EventMarkedStale: Event has not received any updates from source for too long and bets cannot be accepted for it\n* `28` - ResponseTimeoutExceeded: Bet placement response timed out\n* `29` - ExoticSelectionInvalidFormat: Exotics selection has invalid format\n* `39` - ExoticTypeNotMatchWithMarket: Exotics selection type does not match with market type\n* `40` - ExoticsMultibetNotSupported: Exotics multibet is not supported\n* `50` - SelectionLimitExceeded: Prematch selection Limit Exceeded\n* `51` - SelectionVarLimitExceeded: Prematch selection CCF Limit Exceeded\n* `52` - MarketIsNotFixedExotics: Requested market is not Fixed Exotics market\n* `53` - FixedExoticsPriceNotFoundBySelection: The fixed exotics price was not found by selection\n* `54` - FixedExoticsSelectionContainsMultipleCombinations: Multiple combinations are not supported for fixed exotics\n* `55` - PlayerBetLimitExceeded: Liability is over player bet liability limit\n* `56` - StartingPriceMarketLive: Starting price market went live\n* `57` - StartingPriceMultibetNotSupported: Starting price multibet is not supported\n* `58` - StartingPriceMarketMatch: Starting price market bets should not contain price\n* `59` - NullBetPriceIsNotSupportedForThisMarket: Null bet price is not supported for this market\n* `60` - CombinationContainsScratchedCompetitorNumber: Racing selection contains scratched competitor\n* `61` - BetBuilderNotSupported: Bet Builder is not supported\n* `62` - AlternativeOddsExpired: Alternative odds is expired or not available\n* `63` - AlternativeOddsPriceInvalid: Alternative odds price is invalid\n* `64` - AlternativeOddsBetItemsInvalid: Alternative odds bet item(s) are invalid\n* `65` - AlternativeOddsBetAmountInvalid: Alternative odds bet amount is invalid\n* `66` - PlayerMultiBetLimitExceeded: Liability is over player multi bet liability limit\n* `67` - SegmentNotFound: Segment not found\n* `68` - LiveBetNotSupportedForPickem: Live betting not supported for Pickem bets\n* `69` - MarketIsContiguous: Market can't be mixed with other Pickem markets in this bet\n* `70` - SegmentIsDisabled: Segment is disabled\n* `71` - BetBuilderDuplicatedMarkets: Bet Builder bet item contained duplicated markets\n* `72` - StakeTooLow: Stake is too low\n* `73` - BetPlacementIsDisabled: Bet placement was manually disabled\n* `74` - NotAllLegsAreEachWay: Bet contains each-way leg along with standard leg(s)\n* `75` - PartnerMismatch: Bet segment does not belong to the configured partner\n* `76` - OverridesNotSupportedForThisContent: Validation overrides are not supported for this content\n* `77` - CannotMixAlternativeOddsAndRiskManagementOverride: Alternative odds offer and risk management override cannot be used together\n* `100` - UnexpectedError: Something went wrong"},"betItem":{"allOf":[{"$ref":"#/components/schemas/Marlin.SportsbetApi.Host.Models.BetPlacement.BetItemRequestViewModel"}],"description":"Rejected bet item","nullable":true},"message":{"type":"string","description":"Detailed information about rejection cause","nullable":true},"alternativeOdds":{"allOf":[{"$ref":"#/components/schemas/Marlin.SportsbetApi.Host.Models.BetPlacement.AlternativeOddsResultModel"}],"description":"Contains alternative offer in case if liability was exceeded","nullable":true},"maxBet":{"allOf":[{"$ref":"#/components/schemas/Marlin.SportsbetApi.Host.Models.BetPlacement.BetAmountResponseViewModel"}],"description":"Maximum allowed bet amount","nullable":true}},"additionalProperties":false},"TradeArt.BetPlacement.Contracts.Enums.RejectReason":{"enum":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,39,40,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,100],"type":"integer","description":"* `0` - None: Checks passed\n* `1` - PriceChanged: Price Changed\n* `2` - PriceChangedLow: Price Changed Low\n* `3` - PriceChangedHigh: Price Changed High\n* `4` - MissingMandatoryFields: Missing Mandatory Fields\n* `5` - InvalidDataFormat: Invalid Data Format\n* `6` - EventsOrMarketsCannotBeCombined: Events Or Markets Cannot Be Combined\n* `7` - SelectionsFromSameMarket: Selections From Same Market\n* `8` - MultipleSelectionsInEvent: Multiple Selections In Event\n* `9` - DuplicateTeamIds: Duplicate Team Ids\n* `10` - EventNotFound: Event Not Found\n* `11` - EventNotActive: Event Not Active\n* `12` - MarketNotFound: Market Not Found\n* `13` - MarketNotActive: Market Not Active\n* `14` - SelectionNotFound: Selection Not Found\n* `15` - SelectionNotActive: Selection Not Active\n* `16` - AdminConsoleError: Admin Console Error\n* `17` - EventLimitExceeded: Event Limit Exceeded\n* `18` - MarketLimitExceeded: Market Limit Exceeded\n* `19` - BetLimitExceeded: Bet Limit Exceeded\n* `20` - PayoutLimitExceeded: Payout Limit Exceeded\n* `21` - EventVarLimitExceeded: Event CCF Limit Exceeded\n* `22` - MarketVarLimitExceeded: Market CCF Limit Exceeded\n* `23` - BetVarLimitExceeded: Bet CCF Limit Exceeded\n* `24` - PayoutVarLimitExceeded: Payout CCF Limit Exceeded\n* `25` - TooHighOdds: Total price was too large\n* `26` - SportRestricted: Sport restricted for placing bets\n* `27` - EventMarkedStale: Event has not received any updates from source for too long and bets cannot be accepted for it\n* `28` - ResponseTimeoutExceeded: Bet placement response timed out\n* `29` - ExoticSelectionInvalidFormat: Exotics selection has invalid format\n* `39` - ExoticTypeNotMatchWithMarket: Exotics selection type does not match with market type\n* `40` - ExoticsMultibetNotSupported: Exotics multibet is not supported\n* `50` - SelectionLimitExceeded: Prematch selection Limit Exceeded\n* `51` - SelectionVarLimitExceeded: Prematch selection CCF Limit Exceeded\n* `52` - MarketIsNotFixedExotics: Requested market is not Fixed Exotics market\n* `53` - FixedExoticsPriceNotFoundBySelection: The fixed exotics price was not found by selection\n* `54` - FixedExoticsSelectionContainsMultipleCombinations: Multiple combinations are not supported for fixed exotics\n* `55` - PlayerBetLimitExceeded: Liability is over player bet liability limit\n* `56` - StartingPriceMarketLive: Starting price market went live\n* `57` - StartingPriceMultibetNotSupported: Starting price multibet is not supported\n* `58` - StartingPriceMarketMatch: Starting price market bets should not contain price\n* `59` - NullBetPriceIsNotSupportedForThisMarket: Null bet price is not supported for this market\n* `60` - CombinationContainsScratchedCompetitorNumber: Racing selection contains scratched competitor\n* `61` - BetBuilderNotSupported: Bet Builder is not supported\n* `62` - AlternativeOddsExpired: Alternative odds is expired or not available\n* `63` - AlternativeOddsPriceInvalid: Alternative odds price is invalid\n* `64` - AlternativeOddsBetItemsInvalid: Alternative odds bet item(s) are invalid\n* `65` - AlternativeOddsBetAmountInvalid: Alternative odds bet amount is invalid\n* `66` - PlayerMultiBetLimitExceeded: Liability is over player multi bet liability limit\n* `67` - SegmentNotFound: Segment not found\n* `68` - LiveBetNotSupportedForPickem: Live betting not supported for Pickem bets\n* `69` - MarketIsContiguous: Market can't be mixed with other Pickem markets in this bet\n* `70` - SegmentIsDisabled: Segment is disabled\n* `71` - BetBuilderDuplicatedMarkets: Bet Builder bet item contained duplicated markets\n* `72` - StakeTooLow: Stake is too low\n* `73` - BetPlacementIsDisabled: Bet placement was manually disabled\n* `74` - NotAllLegsAreEachWay: Bet contains each-way leg along with standard leg(s)\n* `75` - PartnerMismatch: Bet segment does not belong to the configured partner\n* `76` - OverridesNotSupportedForThisContent: Validation overrides are not supported for this content\n* `77` - CannotMixAlternativeOddsAndRiskManagementOverride: Alternative odds offer and risk management override cannot be used together\n* `100` - UnexpectedError: Something went wrong","format":"int32"},"Marlin.SportsbetApi.Host.Models.BetPlacement.AlternativeOddsResultModel":{"type":"object","properties":{"id":{"type":"string","description":"Alternative odds offer identifier","nullable":true},"alternativePrice":{"type":"number","description":"Alternative odds offer value","format":"double"},"createdAt":{"type":"string","description":"Timestamp the offer was created","format":"date-time"},"expiredAt":{"type":"string","description":"Timestamp the offer gets expired","format":"date-time"}},"additionalProperties":false},"Marlin.SportsbetApi.Host.Models.BetPlacement.BetAmountResponseViewModel":{"required":["precision","value"],"type":"object","properties":{"currency":{"type":"string","description":"Currency ticker symbol","nullable":true},"value":{"type":"integer","description":"Amount in local currency","format":"int64"},"precision":{"type":"integer","description":"Precision value for the provided currency","format":"int32"},"exchangeRate":{"type":"number","format":"double"}},"additionalProperties":false},"Marlin.SportsbetApi.Host.Models.BetPlacement.BetResponseResponseViewModelV2":{"type":"object","properties":{"id":{"type":"string","description":"Auto generated identifier of accepted bet","nullable":true},"player":{"allOf":[{"$ref":"#/components/schemas/Marlin.SportsbetApi.Host.Models.BetPlacement.PlayerViewModel"}],"description":"Identification of the end user. Contains information about Ip, language and device from which bet was placed.","nullable":true},"kind":{"type":"integer","description":"Bet kind. (Single - 0, Multiple - 1)","format":"int32"},"priceChange":{"type":"integer","description":"Price change auto acceptance. (None - 0, Any - 1, Higher - 2)","format":"int32"},"alternativePrice":{"type":"number","description":"Alternative price offered in special cases when liability was exceeded","format":"double","nullable":true},"originalBetId":{"type":"string","description":"Reference to a previously placed bet. Set when the bet uses alternative odds\nor carries a risk-management override.","nullable":true},"validationOverrides":{"type":"array","items":{"type":"integer","format":"int32"},"description":"Validation overrides applied to this bet. (1 - Limits, 2 - Price)","nullable":true},"customPayoutMultiplier":{"type":"number","description":"Custom payout multiplier","format":"double","nullable":true},"betType":{"allOf":[{"$ref":"#/components/schemas/TradeArt.BetPlacement.Contracts.Enums.BetType"}],"description":"Bet Type. (Standard - 0, Pickem - 1)\n\n* `0` - Standard\n* `1` - Pickem"},"freeBetType":{"allOf":[{"$ref":"#/components/schemas/TradeArt.BetPlacement.Contracts.Enums.FreeBetType"}],"description":"Free Bet Type. (NotFree = 0, BasicFreeBet = 1)\n\n* `0` - NotFree\n* `1` - BasicFreeBet"},"items":{"type":"array","items":{"$ref":"#/components/schemas/Marlin.SportsbetApi.Host.Models.BetPlacement.BetItemResponseViewModel"},"description":"List of bet items","nullable":true},"amount":{"allOf":[{"$ref":"#/components/schemas/Marlin.SportsbetApi.Host.Models.BetPlacement.BetAmountResponseViewModel"}],"description":"Bet amount with local currency information","nullable":true}},"additionalProperties":false},"TradeArt.BetPlacement.Contracts.Enums.BetType":{"enum":[0,1],"type":"integer","description":"* `0` - Standard\n* `1` - Pickem","format":"int32"},"TradeArt.BetPlacement.Contracts.Enums.FreeBetType":{"enum":[0,1],"type":"integer","description":"* `0` - NotFree\n* `1` - BasicFreeBet","format":"int32"},"Marlin.SportsbetApi.Host.Models.BetPlacement.BetItemResponseViewModel":{"type":"object","properties":{"eventId":{"type":"integer","description":"Event id on which the bet is placed.","format":"int64"},"marketId":{"type":"integer","description":"Market id on which the bet is placed. Should be `-1` for BetBuilder bet.","format":"int64"},"selectionId":{"type":"integer","description":"Selection id on which the bet is placed. Should be `-1` for exotics/BetBuilder bet.","format":"int64"},"racingSelection":{"type":"string","description":"Racing exotics selection.","nullable":true},"price":{"type":"number","description":"Price on which the bet is placed. Should be `null` for tote exotics and SP bet.","format":"double","nullable":true},"alternativePrice":{"type":"number","description":"Alternative price of a bet selection.","format":"double","nullable":true},"betBuilderBetItems":{"type":"array","items":{"$ref":"#/components/schemas/Marlin.SportsbetApi.Host.Models.BetPlacement.BetBuilderBetItemViewModel"},"description":"Bet builder items.","nullable":true}},"additionalProperties":false,"description":"Represents item inside the bet in the response"},"Marlin.SportsbetApi.Host.Models.ResponseCode":{"enum":[1,2,3,4,5],"type":"integer","description":"* `1` - Success\n* `2` - FormatError\n* `3` - PrecisionMismatch\n* `4` - UnsupportedCurrency\n* `5` - UnsupportedFeature","format":"int32"},"Microsoft.AspNetCore.Mvc.ProblemDetails":{"type":"object","properties":{"type":{"type":"string","nullable":true},"title":{"type":"string","nullable":true},"status":{"type":"integer","format":"int32","nullable":true},"detail":{"type":"string","nullable":true},"instance":{"type":"string","nullable":true}},"additionalProperties":{}}}},"paths":{"/api/players/{playerId}/Bets/V2":{"put":{"tags":["Bets"],"summary":"Places bet from specific player (multi-currency).","operationId":"Place bet V2","parameters":[{"name":"playerId","in":"path","description":"Id of player which places a bet.","required":true,"schema":{"type":"string"}}],"requestBody":{"description":"Bet request data.","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/Marlin.SportsbetApi.Host.Models.BetPlacement.BetRequestViewModelV2"}],"description":"Represents bet request."}},"text/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/Marlin.SportsbetApi.Host.Models.BetPlacement.BetRequestViewModelV2"}],"description":"Represents bet request."}},"application/*+json":{"schema":{"allOf":[{"$ref":"#/components/schemas/Marlin.SportsbetApi.Host.Models.BetPlacement.BetRequestViewModelV2"}],"description":"Represents bet request."}}}},"responses":{"200":{"description":"Returns results of bet placement request.","content":{"text/plain":{"schema":{"$ref":"#/components/schemas/Marlin.SportsbetApi.Host.Models.ResponseViewModel`1[[Marlin.SportsbetApi.Host.Models.BetPlacement.BetResultViewModelV2, Marlin.SportsbetApi.Host, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null]]"}},"application/json":{"schema":{"$ref":"#/components/schemas/Marlin.SportsbetApi.Host.Models.ResponseViewModel`1[[Marlin.SportsbetApi.Host.Models.BetPlacement.BetResultViewModelV2, Marlin.SportsbetApi.Host, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null]]"}},"text/json":{"schema":{"$ref":"#/components/schemas/Marlin.SportsbetApi.Host.Models.ResponseViewModel`1[[Marlin.SportsbetApi.Host.Models.BetPlacement.BetResultViewModelV2, Marlin.SportsbetApi.Host, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null]]"}}}},"400":{"description":"Request arguments are not valid.","content":{"text/plain":{"schema":{"$ref":"#/components/schemas/Microsoft.AspNetCore.Mvc.ProblemDetails"}},"application/json":{"schema":{"$ref":"#/components/schemas/Microsoft.AspNetCore.Mvc.ProblemDetails"}},"text/json":{"schema":{"$ref":"#/components/schemas/Microsoft.AspNetCore.Mvc.ProblemDetails"}}}},"401":{"description":"Unauthorized"},"403":{"description":"Forbidden"},"500":{"description":"Unexpected error occurred."}}}}}}
```

## Max Bet Endpoint

Can be used to get the max possible value for a particular bet for a particular player.

The bet will be validated according to related event(s), market(s), selection(s) statuses, odds and liabilities.

{% hint style="info" %}
The bet will not be saved in Odds88 system, so this endpoint can be called before locking funds on the player's account.
{% endhint %}

## POST /api/players/{playerId}/Bets/V2/max

> Gets max possible bet size for the specific player (multi-currency).

```json
{"openapi":"3.0.4","info":{"title":"[T728-STAGE] Odds88 API","version":"v1"},"tags":[{"name":"Bets"}],"security":[{"Bearer":[]}],"components":{"securitySchemes":{"Bearer":{"type":"http","description":"JWT Authorization header using the Bearer scheme. Example: \"Authorization: Bearer {token}\"","scheme":"Bearer","bearerFormat":"JWT"}},"schemas":{"Marlin.SportsbetApi.Host.Models.BetPlacement.BetRequestViewModelV2":{"type":"object","properties":{"id":{"type":"string","description":"Unique request id (in the client's system);","nullable":true},"player":{"allOf":[{"$ref":"#/components/schemas/Marlin.SportsbetApi.Host.Models.BetPlacement.PlayerViewModel"}],"description":"Identification of the end user. Contains information about Ip, language and device from which bet was placed.","nullable":true},"priceChange":{"allOf":[{"$ref":"#/components/schemas/Marlin.SportsbetApi.Host.Models.BetPlacement.PriceChange"}],"description":"Price change auto acceptance. (None - 0, Any - 1, Higher - 2)\n\n* `0` - None\n* `1` - Any\n* `2` - Higher"},"items":{"type":"array","items":{"$ref":"#/components/schemas/Marlin.SportsbetApi.Host.Models.BetPlacement.BetItemRequestViewModel"},"description":"List of bet items","nullable":true},"alternativeOddsId":{"type":"string","description":"ID of alternative odds offer in case if liability was exceeded","nullable":true},"alternativePrice":{"type":"number","description":"Alternative odds offer value","format":"double","nullable":true},"customPayoutMultiplier":{"type":"number","description":"Custom payout multiplier","format":"double","nullable":true},"betType":{"type":"integer","description":"Bet Type. (Standard - 0, Pickem - 1)","format":"int32"},"freeBetType":{"type":"integer","description":"Free Bet Type. (NotFree = 0, BasicFreeBet = 1)","format":"int32"},"riskManagementOverride":{"allOf":[{"$ref":"#/components/schemas/Marlin.SportsbetApi.Host.Models.BetPlacement.RiskManagementOverrideViewModel"}],"description":"Optional risk-management override. When set, links this bet to a previously placed bet\n(via OriginalBetId) and disables specific validations (ValidationOverrides: 1 = limits,\n2 = price). Cannot be combined with AlternativeOddsId.","nullable":true},"amount":{"allOf":[{"$ref":"#/components/schemas/Marlin.SportsbetApi.Host.Models.BetPlacement.BetAmountRequestViewModel"}],"description":"Bet amount model","nullable":true}},"additionalProperties":false,"description":"Represents bet request."},"Marlin.SportsbetApi.Host.Models.BetPlacement.PlayerViewModel":{"type":"object","properties":{"deviceId":{"type":"string","description":"End user's device id","nullable":true},"languageId":{"type":"string","description":"ISO 639-1 language code","nullable":true},"ip":{"type":"string","description":"End user's IP","nullable":true},"segmentId":{"type":"integer","description":"End user's limit Id","format":"int32"}},"additionalProperties":false,"description":"Represents player data."},"Marlin.SportsbetApi.Host.Models.BetPlacement.PriceChange":{"enum":[0,1,2],"type":"integer","description":"Types of price change acceptance.\n\n* `0` - None\n* `1` - Any\n* `2` - Higher","format":"int32"},"Marlin.SportsbetApi.Host.Models.BetPlacement.BetItemRequestViewModel":{"type":"object","properties":{"eventId":{"type":"integer","description":"Event id on which the bet is placed.","format":"int64"},"marketId":{"type":"integer","description":"Market id on which the bet is placed. Should be `-1` for BetBuilder bet.","format":"int64"},"selectionId":{"type":"integer","description":"Selection id on which the bet is placed. Should be `-1` for exotics/BetBuilder bet.","format":"int64"},"racingSelection":{"type":"string","description":"Racing exotics selection.","nullable":true},"price":{"type":"number","description":"Price on which the bet is placed. Should be `null` for tote exotics and SP bet.","format":"double","nullable":true},"betBuilderBetItems":{"type":"array","items":{"$ref":"#/components/schemas/Marlin.SportsbetApi.Host.Models.BetPlacement.BetBuilderBetItemViewModel"},"nullable":true}},"additionalProperties":false,"description":"Represents item inside the bet in the request."},"Marlin.SportsbetApi.Host.Models.BetPlacement.BetBuilderBetItemViewModel":{"required":["marketId","selectionId"],"type":"object","properties":{"marketId":{"maximum":9223372036854776000,"minimum":1,"type":"integer","description":"Market id of the bet item.","format":"int64"},"selectionId":{"maximum":9223372036854776000,"minimum":1,"type":"integer","description":"Selection id of the bet item.","format":"int64"}},"additionalProperties":false,"description":"Represents bet item of BetBuilder."},"Marlin.SportsbetApi.Host.Models.BetPlacement.RiskManagementOverrideViewModel":{"type":"object","properties":{"originalBetId":{"type":"string","description":"The originally placed bet's id that this attempt is referencing.","nullable":true},"validationOverrides":{"type":"array","items":{"type":"integer","format":"int32"},"description":"Validation steps to skip. 1 = limits (disable liability check), 2 = price (accept stale prices).","nullable":true}},"additionalProperties":false,"description":"Risk management override payload — sent alongside a re-attempted bet whose original\nplacement was rejected."},"Marlin.SportsbetApi.Host.Models.BetPlacement.BetAmountRequestViewModel":{"required":["precision","value"],"type":"object","properties":{"currency":{"type":"string","description":"Currency ticker symbol","nullable":true},"value":{"type":"integer","description":"Amount in local currency","format":"int64"},"precision":{"type":"integer","description":"Precision value for the provided currency","format":"int32"}},"additionalProperties":false},"Marlin.SportsbetApi.Host.Models.BetPlacement.MaxBetResultViewModelV2":{"type":"object","properties":{"rejectReason":{"type":"integer","description":"Information about rejection cause. (None - 0, UnknownError - 1, PriceChanged - 2, LimitExceeded - 3 , SelectionNotFound - 4 etc.)","format":"int32"},"amount":{"type":"integer","description":"Max bet amount in local currency","format":"int64"}},"additionalProperties":false},"Microsoft.AspNetCore.Mvc.ProblemDetails":{"type":"object","properties":{"type":{"type":"string","nullable":true},"title":{"type":"string","nullable":true},"status":{"type":"integer","format":"int32","nullable":true},"detail":{"type":"string","nullable":true},"instance":{"type":"string","nullable":true}},"additionalProperties":{}}}},"paths":{"/api/players/{playerId}/Bets/V2/max":{"post":{"tags":["Bets"],"summary":"Gets max possible bet size for the specific player (multi-currency).","operationId":"Get max bet amount V2","parameters":[{"name":"playerId","in":"path","description":"Id of player which places a bet.","required":true,"schema":{"type":"string"}}],"requestBody":{"description":"Bet request data.","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/Marlin.SportsbetApi.Host.Models.BetPlacement.BetRequestViewModelV2"}],"description":"Represents bet request."}},"text/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/Marlin.SportsbetApi.Host.Models.BetPlacement.BetRequestViewModelV2"}],"description":"Represents bet request."}},"application/*+json":{"schema":{"allOf":[{"$ref":"#/components/schemas/Marlin.SportsbetApi.Host.Models.BetPlacement.BetRequestViewModelV2"}],"description":"Represents bet request."}}}},"responses":{"200":{"description":"Returns results of max bet calculation.","content":{"text/plain":{"schema":{"$ref":"#/components/schemas/Marlin.SportsbetApi.Host.Models.BetPlacement.MaxBetResultViewModelV2"}},"application/json":{"schema":{"$ref":"#/components/schemas/Marlin.SportsbetApi.Host.Models.BetPlacement.MaxBetResultViewModelV2"}},"text/json":{"schema":{"$ref":"#/components/schemas/Marlin.SportsbetApi.Host.Models.BetPlacement.MaxBetResultViewModelV2"}}}},"400":{"description":"Request arguments are not valid.","content":{"text/plain":{"schema":{"$ref":"#/components/schemas/Microsoft.AspNetCore.Mvc.ProblemDetails"}},"application/json":{"schema":{"$ref":"#/components/schemas/Microsoft.AspNetCore.Mvc.ProblemDetails"}},"text/json":{"schema":{"$ref":"#/components/schemas/Microsoft.AspNetCore.Mvc.ProblemDetails"}}}},"401":{"description":"Unauthorized"},"403":{"description":"Forbidden"},"500":{"description":"Unexpected error occurred."}}}}}}
```

## Bet Builder Price Endpoint

Allows to get bet builder odds for the provided combination.

The endpoint will respond with potential odds or rejection information.

## POST /api/players/{playerId}/Bets/bet-builder-price

> Gets bet builder price.

```json
{"openapi":"3.0.4","info":{"title":"[T728-STAGE] Odds88 API","version":"v1"},"tags":[{"name":"Bets"}],"security":[{"Bearer":[]}],"components":{"securitySchemes":{"Bearer":{"type":"http","description":"JWT Authorization header using the Bearer scheme. Example: \"Authorization: Bearer {token}\"","scheme":"Bearer","bearerFormat":"JWT"}},"schemas":{"Marlin.SportsbetApi.Host.Models.BetPlacement.BetBuilderPriceRequestViewModel":{"required":["bets","eventId","requestId","segmentId"],"type":"object","properties":{"requestId":{"minLength":1,"type":"string","description":"Id of the requests."},"segmentId":{"maximum":9223372036854776000,"minimum":1,"type":"integer","description":"Segment of the price requesting player.","format":"int32"},"eventId":{"maximum":9223372036854776000,"minimum":1,"type":"integer","description":"Event id price is requested for.","format":"int64"},"bets":{"minItems":1,"type":"array","items":{"$ref":"#/components/schemas/Marlin.SportsbetApi.Host.Models.BetPlacement.BetBuilderBetItemViewModel"},"description":"Bet items price is requested for."}},"additionalProperties":false,"description":"Represents BetBuilder price request."},"Marlin.SportsbetApi.Host.Models.BetPlacement.BetBuilderBetItemViewModel":{"required":["marketId","selectionId"],"type":"object","properties":{"marketId":{"maximum":9223372036854776000,"minimum":1,"type":"integer","description":"Market id of the bet item.","format":"int64"},"selectionId":{"maximum":9223372036854776000,"minimum":1,"type":"integer","description":"Selection id of the bet item.","format":"int64"}},"additionalProperties":false,"description":"Represents bet item of BetBuilder."},"Marlin.SportsbetApi.Host.Models.BetPlacement.BetBuilderPriceResultViewModel":{"type":"object","properties":{"requestId":{"type":"string","description":"Id of the price request.","nullable":true},"price":{"type":"number","description":"Suggested price for the BetBuilder request.","format":"double","nullable":true},"timeStamp":{"type":"string","description":"Time stamp of the request.","format":"date-time"},"rejectInfo":{"allOf":[{"$ref":"#/components/schemas/Marlin.SportsbetApi.Host.Models.BetPlacement.RejectInfoViewModel"}],"description":"Request rejection information.\nPresented only when the request is rejected.","nullable":true}},"additionalProperties":false,"description":"Represents response to a BetBuilder price request."},"Marlin.SportsbetApi.Host.Models.BetPlacement.RejectInfoViewModel":{"type":"object","properties":{"reason":{"allOf":[{"$ref":"#/components/schemas/TradeArt.BetPlacement.Contracts.Enums.RejectReason"}],"description":"Information about rejection cause\n\n* `0` - None: Checks passed\n* `1` - PriceChanged: Price Changed\n* `2` - PriceChangedLow: Price Changed Low\n* `3` - PriceChangedHigh: Price Changed High\n* `4` - MissingMandatoryFields: Missing Mandatory Fields\n* `5` - InvalidDataFormat: Invalid Data Format\n* `6` - EventsOrMarketsCannotBeCombined: Events Or Markets Cannot Be Combined\n* `7` - SelectionsFromSameMarket: Selections From Same Market\n* `8` - MultipleSelectionsInEvent: Multiple Selections In Event\n* `9` - DuplicateTeamIds: Duplicate Team Ids\n* `10` - EventNotFound: Event Not Found\n* `11` - EventNotActive: Event Not Active\n* `12` - MarketNotFound: Market Not Found\n* `13` - MarketNotActive: Market Not Active\n* `14` - SelectionNotFound: Selection Not Found\n* `15` - SelectionNotActive: Selection Not Active\n* `16` - AdminConsoleError: Admin Console Error\n* `17` - EventLimitExceeded: Event Limit Exceeded\n* `18` - MarketLimitExceeded: Market Limit Exceeded\n* `19` - BetLimitExceeded: Bet Limit Exceeded\n* `20` - PayoutLimitExceeded: Payout Limit Exceeded\n* `21` - EventVarLimitExceeded: Event CCF Limit Exceeded\n* `22` - MarketVarLimitExceeded: Market CCF Limit Exceeded\n* `23` - BetVarLimitExceeded: Bet CCF Limit Exceeded\n* `24` - PayoutVarLimitExceeded: Payout CCF Limit Exceeded\n* `25` - TooHighOdds: Total price was too large\n* `26` - SportRestricted: Sport restricted for placing bets\n* `27` - EventMarkedStale: Event has not received any updates from source for too long and bets cannot be accepted for it\n* `28` - ResponseTimeoutExceeded: Bet placement response timed out\n* `29` - ExoticSelectionInvalidFormat: Exotics selection has invalid format\n* `39` - ExoticTypeNotMatchWithMarket: Exotics selection type does not match with market type\n* `40` - ExoticsMultibetNotSupported: Exotics multibet is not supported\n* `50` - SelectionLimitExceeded: Prematch selection Limit Exceeded\n* `51` - SelectionVarLimitExceeded: Prematch selection CCF Limit Exceeded\n* `52` - MarketIsNotFixedExotics: Requested market is not Fixed Exotics market\n* `53` - FixedExoticsPriceNotFoundBySelection: The fixed exotics price was not found by selection\n* `54` - FixedExoticsSelectionContainsMultipleCombinations: Multiple combinations are not supported for fixed exotics\n* `55` - PlayerBetLimitExceeded: Liability is over player bet liability limit\n* `56` - StartingPriceMarketLive: Starting price market went live\n* `57` - StartingPriceMultibetNotSupported: Starting price multibet is not supported\n* `58` - StartingPriceMarketMatch: Starting price market bets should not contain price\n* `59` - NullBetPriceIsNotSupportedForThisMarket: Null bet price is not supported for this market\n* `60` - CombinationContainsScratchedCompetitorNumber: Racing selection contains scratched competitor\n* `61` - BetBuilderNotSupported: Bet Builder is not supported\n* `62` - AlternativeOddsExpired: Alternative odds is expired or not available\n* `63` - AlternativeOddsPriceInvalid: Alternative odds price is invalid\n* `64` - AlternativeOddsBetItemsInvalid: Alternative odds bet item(s) are invalid\n* `65` - AlternativeOddsBetAmountInvalid: Alternative odds bet amount is invalid\n* `66` - PlayerMultiBetLimitExceeded: Liability is over player multi bet liability limit\n* `67` - SegmentNotFound: Segment not found\n* `68` - LiveBetNotSupportedForPickem: Live betting not supported for Pickem bets\n* `69` - MarketIsContiguous: Market can't be mixed with other Pickem markets in this bet\n* `70` - SegmentIsDisabled: Segment is disabled\n* `71` - BetBuilderDuplicatedMarkets: Bet Builder bet item contained duplicated markets\n* `72` - StakeTooLow: Stake is too low\n* `73` - BetPlacementIsDisabled: Bet placement was manually disabled\n* `74` - NotAllLegsAreEachWay: Bet contains each-way leg along with standard leg(s)\n* `75` - PartnerMismatch: Bet segment does not belong to the configured partner\n* `76` - OverridesNotSupportedForThisContent: Validation overrides are not supported for this content\n* `77` - CannotMixAlternativeOddsAndRiskManagementOverride: Alternative odds offer and risk management override cannot be used together\n* `100` - UnexpectedError: Something went wrong"},"betItem":{"allOf":[{"$ref":"#/components/schemas/Marlin.SportsbetApi.Host.Models.BetPlacement.BetItemRequestViewModel"}],"description":"Rejected bet item","nullable":true},"message":{"type":"string","description":"Detailed information about rejection cause","nullable":true},"alternativeOdds":{"allOf":[{"$ref":"#/components/schemas/Marlin.SportsbetApi.Host.Models.BetPlacement.AlternativeOddsResultModel"}],"description":"Contains alternative offer in case if liability was exceeded","nullable":true},"maxBet":{"type":"number","description":"Maximum allowed bet amount","format":"double","nullable":true}},"additionalProperties":false},"TradeArt.BetPlacement.Contracts.Enums.RejectReason":{"enum":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,39,40,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,100],"type":"integer","description":"* `0` - None: Checks passed\n* `1` - PriceChanged: Price Changed\n* `2` - PriceChangedLow: Price Changed Low\n* `3` - PriceChangedHigh: Price Changed High\n* `4` - MissingMandatoryFields: Missing Mandatory Fields\n* `5` - InvalidDataFormat: Invalid Data Format\n* `6` - EventsOrMarketsCannotBeCombined: Events Or Markets Cannot Be Combined\n* `7` - SelectionsFromSameMarket: Selections From Same Market\n* `8` - MultipleSelectionsInEvent: Multiple Selections In Event\n* `9` - DuplicateTeamIds: Duplicate Team Ids\n* `10` - EventNotFound: Event Not Found\n* `11` - EventNotActive: Event Not Active\n* `12` - MarketNotFound: Market Not Found\n* `13` - MarketNotActive: Market Not Active\n* `14` - SelectionNotFound: Selection Not Found\n* `15` - SelectionNotActive: Selection Not Active\n* `16` - AdminConsoleError: Admin Console Error\n* `17` - EventLimitExceeded: Event Limit Exceeded\n* `18` - MarketLimitExceeded: Market Limit Exceeded\n* `19` - BetLimitExceeded: Bet Limit Exceeded\n* `20` - PayoutLimitExceeded: Payout Limit Exceeded\n* `21` - EventVarLimitExceeded: Event CCF Limit Exceeded\n* `22` - MarketVarLimitExceeded: Market CCF Limit Exceeded\n* `23` - BetVarLimitExceeded: Bet CCF Limit Exceeded\n* `24` - PayoutVarLimitExceeded: Payout CCF Limit Exceeded\n* `25` - TooHighOdds: Total price was too large\n* `26` - SportRestricted: Sport restricted for placing bets\n* `27` - EventMarkedStale: Event has not received any updates from source for too long and bets cannot be accepted for it\n* `28` - ResponseTimeoutExceeded: Bet placement response timed out\n* `29` - ExoticSelectionInvalidFormat: Exotics selection has invalid format\n* `39` - ExoticTypeNotMatchWithMarket: Exotics selection type does not match with market type\n* `40` - ExoticsMultibetNotSupported: Exotics multibet is not supported\n* `50` - SelectionLimitExceeded: Prematch selection Limit Exceeded\n* `51` - SelectionVarLimitExceeded: Prematch selection CCF Limit Exceeded\n* `52` - MarketIsNotFixedExotics: Requested market is not Fixed Exotics market\n* `53` - FixedExoticsPriceNotFoundBySelection: The fixed exotics price was not found by selection\n* `54` - FixedExoticsSelectionContainsMultipleCombinations: Multiple combinations are not supported for fixed exotics\n* `55` - PlayerBetLimitExceeded: Liability is over player bet liability limit\n* `56` - StartingPriceMarketLive: Starting price market went live\n* `57` - StartingPriceMultibetNotSupported: Starting price multibet is not supported\n* `58` - StartingPriceMarketMatch: Starting price market bets should not contain price\n* `59` - NullBetPriceIsNotSupportedForThisMarket: Null bet price is not supported for this market\n* `60` - CombinationContainsScratchedCompetitorNumber: Racing selection contains scratched competitor\n* `61` - BetBuilderNotSupported: Bet Builder is not supported\n* `62` - AlternativeOddsExpired: Alternative odds is expired or not available\n* `63` - AlternativeOddsPriceInvalid: Alternative odds price is invalid\n* `64` - AlternativeOddsBetItemsInvalid: Alternative odds bet item(s) are invalid\n* `65` - AlternativeOddsBetAmountInvalid: Alternative odds bet amount is invalid\n* `66` - PlayerMultiBetLimitExceeded: Liability is over player multi bet liability limit\n* `67` - SegmentNotFound: Segment not found\n* `68` - LiveBetNotSupportedForPickem: Live betting not supported for Pickem bets\n* `69` - MarketIsContiguous: Market can't be mixed with other Pickem markets in this bet\n* `70` - SegmentIsDisabled: Segment is disabled\n* `71` - BetBuilderDuplicatedMarkets: Bet Builder bet item contained duplicated markets\n* `72` - StakeTooLow: Stake is too low\n* `73` - BetPlacementIsDisabled: Bet placement was manually disabled\n* `74` - NotAllLegsAreEachWay: Bet contains each-way leg along with standard leg(s)\n* `75` - PartnerMismatch: Bet segment does not belong to the configured partner\n* `76` - OverridesNotSupportedForThisContent: Validation overrides are not supported for this content\n* `77` - CannotMixAlternativeOddsAndRiskManagementOverride: Alternative odds offer and risk management override cannot be used together\n* `100` - UnexpectedError: Something went wrong","format":"int32"},"Marlin.SportsbetApi.Host.Models.BetPlacement.BetItemRequestViewModel":{"type":"object","properties":{"eventId":{"type":"integer","description":"Event id on which the bet is placed.","format":"int64"},"marketId":{"type":"integer","description":"Market id on which the bet is placed. Should be `-1` for BetBuilder bet.","format":"int64"},"selectionId":{"type":"integer","description":"Selection id on which the bet is placed. Should be `-1` for exotics/BetBuilder bet.","format":"int64"},"racingSelection":{"type":"string","description":"Racing exotics selection.","nullable":true},"price":{"type":"number","description":"Price on which the bet is placed. Should be `null` for tote exotics and SP bet.","format":"double","nullable":true},"betBuilderBetItems":{"type":"array","items":{"$ref":"#/components/schemas/Marlin.SportsbetApi.Host.Models.BetPlacement.BetBuilderBetItemViewModel"},"nullable":true}},"additionalProperties":false,"description":"Represents item inside the bet in the request."},"Marlin.SportsbetApi.Host.Models.BetPlacement.AlternativeOddsResultModel":{"type":"object","properties":{"id":{"type":"string","description":"Alternative odds offer identifier","nullable":true},"alternativePrice":{"type":"number","description":"Alternative odds offer value","format":"double"},"createdAt":{"type":"string","description":"Timestamp the offer was created","format":"date-time"},"expiredAt":{"type":"string","description":"Timestamp the offer gets expired","format":"date-time"}},"additionalProperties":false},"Microsoft.AspNetCore.Mvc.ProblemDetails":{"type":"object","properties":{"type":{"type":"string","nullable":true},"title":{"type":"string","nullable":true},"status":{"type":"integer","format":"int32","nullable":true},"detail":{"type":"string","nullable":true},"instance":{"type":"string","nullable":true}},"additionalProperties":{}}}},"paths":{"/api/players/{playerId}/Bets/bet-builder-price":{"post":{"tags":["Bets"],"summary":"Gets bet builder price.","operationId":"Get betbuilder price","parameters":[{"name":"playerId","in":"path","description":"Id of player which placed a bet.","required":true,"schema":{"type":"string"}}],"requestBody":{"description":"Bet price request.","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/Marlin.SportsbetApi.Host.Models.BetPlacement.BetBuilderPriceRequestViewModel"}],"description":"Represents BetBuilder price request."}},"text/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/Marlin.SportsbetApi.Host.Models.BetPlacement.BetBuilderPriceRequestViewModel"}],"description":"Represents BetBuilder price request."}},"application/*+json":{"schema":{"allOf":[{"$ref":"#/components/schemas/Marlin.SportsbetApi.Host.Models.BetPlacement.BetBuilderPriceRequestViewModel"}],"description":"Represents BetBuilder price request."}}}},"responses":{"200":{"description":"Returns price for potential betbuilder bet.","content":{"text/plain":{"schema":{"$ref":"#/components/schemas/Marlin.SportsbetApi.Host.Models.BetPlacement.BetBuilderPriceResultViewModel"}},"application/json":{"schema":{"$ref":"#/components/schemas/Marlin.SportsbetApi.Host.Models.BetPlacement.BetBuilderPriceResultViewModel"}},"text/json":{"schema":{"$ref":"#/components/schemas/Marlin.SportsbetApi.Host.Models.BetPlacement.BetBuilderPriceResultViewModel"}}}},"400":{"description":"Request arguments are not valid.","content":{"text/plain":{"schema":{"$ref":"#/components/schemas/Microsoft.AspNetCore.Mvc.ProblemDetails"}},"application/json":{"schema":{"$ref":"#/components/schemas/Microsoft.AspNetCore.Mvc.ProblemDetails"}},"text/json":{"schema":{"$ref":"#/components/schemas/Microsoft.AspNetCore.Mvc.ProblemDetails"}}}},"401":{"description":"Unauthorized"},"403":{"description":"Forbidden"},"500":{"description":"Unexpected error occurred."}}}}}}
```


# Cashout API

Controls cashout feed

Cashout API allows to control which bets are included in the Cashout Feed.

{% content-ref url="/pages/ivn3IWuh7XK7eWavHRnp" %}
[Cashout Feed](/odds88-client-api/odds88-feeds/cashout-feed)
{% endcontent-ref %}

As cashout real-time calculation can be very resource-consuming, we need to know which exact bets we should keep there.

## Subscribe Endpoint

Allows to subscribe to a potential cashout amount for specific bets.

`betIds` should contain only ids of the bets (without player id).

{% hint style="info" %}
Subscription will wear-out after 10 minutes.

In order to keep bets in the subscription, this endpoint should be called periodically to renew the subscription.
{% endhint %}

Potential cashout values will be sent via the Cashout Feed.

{% content-ref url="/pages/ivn3IWuh7XK7eWavHRnp" %}
[Cashout Feed](/odds88-client-api/odds88-feeds/cashout-feed)
{% endcontent-ref %}

## POST /api/Cashout/subscribe

> Subscribes to provided bets for realtime data

```json
{"openapi":"3.0.4","info":{"title":"[T728-STAGE] Odds88 API","version":"v1"},"tags":[{"name":"Cashout"}],"security":[{"Bearer":[]}],"components":{"securitySchemes":{"Bearer":{"type":"http","description":"JWT Authorization header using the Bearer scheme. Example: \"Authorization: Bearer {token}\"","scheme":"Bearer","bearerFormat":"JWT"}},"schemas":{"Marlin.SportsbetApi.Host.Models.Cashout.CashoutSubscriptionRequestModel":{"required":["betIds"],"type":"object","properties":{"betIds":{"type":"array","items":{"type":"string"},"nullable":true}},"additionalProperties":false}}},"paths":{"/api/Cashout/subscribe":{"post":{"tags":["Cashout"],"summary":"Subscribes to provided bets for realtime data","requestBody":{"description":"","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/Marlin.SportsbetApi.Host.Models.Cashout.CashoutSubscriptionRequestModel"}]}},"text/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/Marlin.SportsbetApi.Host.Models.Cashout.CashoutSubscriptionRequestModel"}]}},"application/*+json":{"schema":{"allOf":[{"$ref":"#/components/schemas/Marlin.SportsbetApi.Host.Models.Cashout.CashoutSubscriptionRequestModel"}]}}}},"responses":{"200":{"description":"OK"},"401":{"description":"Unauthorized"},"403":{"description":"Forbidden"},"500":{"description":"Internal Server Error"}}}}}}
```

## Unsubscribe Endpoint

Allows to unsibscribe from cashout values for specific bets.

`betIds` should contain only ids of the bets (without player id).

Should be called when real-time cashout amount for specific bets is not needed anymore (when player leaves the bet history page or moves to another page).

## POST /api/Cashout/unsubscribe

> Unsubscribes from provided bets to stop realtime data

```json
{"openapi":"3.0.4","info":{"title":"[T728-STAGE] Odds88 API","version":"v1"},"tags":[{"name":"Cashout"}],"security":[{"Bearer":[]}],"components":{"securitySchemes":{"Bearer":{"type":"http","description":"JWT Authorization header using the Bearer scheme. Example: \"Authorization: Bearer {token}\"","scheme":"Bearer","bearerFormat":"JWT"}},"schemas":{"Marlin.SportsbetApi.Host.Models.Cashout.CashoutSubscriptionRequestModel":{"required":["betIds"],"type":"object","properties":{"betIds":{"type":"array","items":{"type":"string"},"nullable":true}},"additionalProperties":false}}},"paths":{"/api/Cashout/unsubscribe":{"post":{"tags":["Cashout"],"summary":"Unsubscribes from provided bets to stop realtime data","requestBody":{"description":"","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/Marlin.SportsbetApi.Host.Models.Cashout.CashoutSubscriptionRequestModel"}]}},"text/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/Marlin.SportsbetApi.Host.Models.Cashout.CashoutSubscriptionRequestModel"}]}},"application/*+json":{"schema":{"allOf":[{"$ref":"#/components/schemas/Marlin.SportsbetApi.Host.Models.Cashout.CashoutSubscriptionRequestModel"}]}}}},"responses":{"200":{"description":"OK"},"401":{"description":"Unauthorized"},"403":{"description":"Forbidden"},"500":{"description":"Internal Server Error"}}}}}}
```

## Cashout Endpoint

Allows to perform cashout of the bet with risk management check.

Odds88 will perform validation of cashout possibility and cashout amount.

## POST /api/Cashout

> Tries to cashout a bet.

```json
{"openapi":"3.0.4","info":{"title":"[T728-STAGE] Odds88 API","version":"v1"},"tags":[{"name":"Cashout"}],"security":[{"Bearer":[]}],"components":{"securitySchemes":{"Bearer":{"type":"http","description":"JWT Authorization header using the Bearer scheme. Example: \"Authorization: Bearer {token}\"","scheme":"Bearer","bearerFormat":"JWT"}},"schemas":{"Marlin.SportsbetApi.Host.Models.Cashout.CashoutBetRequestModel":{"required":["amount","betId","priceChange"],"type":"object","properties":{"betId":{"type":"string","nullable":true},"priceChange":{"allOf":[{"$ref":"#/components/schemas/Marlin.SportsbetApi.Host.Models.Cashout.PriceChangeType"}],"description":"* `1` - None\n* `2` - Any"},"amount":{"allOf":[{"$ref":"#/components/schemas/Marlin.SportsbetApi.Host.Models.Cashout.AmountRequestModel"}],"nullable":true}},"additionalProperties":false},"Marlin.SportsbetApi.Host.Models.Cashout.PriceChangeType":{"enum":[1,2],"type":"integer","description":"* `1` - None\n* `2` - Any","format":"int32"},"Marlin.SportsbetApi.Host.Models.Cashout.AmountRequestModel":{"required":["currency","precision"],"type":"object","properties":{"localAmount":{"type":"number","format":"double","nullable":true},"precision":{"type":"integer","format":"int32"},"currency":{"type":"string","nullable":true}},"additionalProperties":false},"Marlin.SportsbetApi.Host.Models.Cashout.CashoutBetResponseModel":{"required":["payload","success"],"type":"object","properties":{"success":{"type":"boolean"},"reason":{"type":"string","nullable":true},"payload":{"allOf":[{"$ref":"#/components/schemas/Marlin.SportsbetApi.Host.Models.Cashout.CashoutBetResponsePayloadModel"}],"nullable":true}},"additionalProperties":false},"Marlin.SportsbetApi.Host.Models.Cashout.CashoutBetResponsePayloadModel":{"required":["betId"],"type":"object","properties":{"betId":{"type":"string","nullable":true},"localAmount":{"type":"number","format":"double","nullable":true}},"additionalProperties":false}}},"paths":{"/api/Cashout":{"post":{"tags":["Cashout"],"summary":"Tries to cashout a bet.","requestBody":{"description":"","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/Marlin.SportsbetApi.Host.Models.Cashout.CashoutBetRequestModel"}]}},"text/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/Marlin.SportsbetApi.Host.Models.Cashout.CashoutBetRequestModel"}]}},"application/*+json":{"schema":{"allOf":[{"$ref":"#/components/schemas/Marlin.SportsbetApi.Host.Models.Cashout.CashoutBetRequestModel"}]}}}},"responses":{"200":{"description":"OK","content":{"text/plain":{"schema":{"$ref":"#/components/schemas/Marlin.SportsbetApi.Host.Models.Cashout.CashoutBetResponseModel"}},"application/json":{"schema":{"$ref":"#/components/schemas/Marlin.SportsbetApi.Host.Models.Cashout.CashoutBetResponseModel"}},"text/json":{"schema":{"$ref":"#/components/schemas/Marlin.SportsbetApi.Host.Models.Cashout.CashoutBetResponseModel"}}}},"401":{"description":"Unauthorized"},"403":{"description":"Forbidden"},"500":{"description":"Internal Server Error"}}}}}}
```


# Currency Exchange API

Provides information about supported currencies

Currency Exchange API provides information about supported currencies and their precision to be used in Bet Placement and cashout process.

{% content-ref url="/pages/2l7cTFxJAk5U4UAqv2Er" %}
[Bets API](/odds88-client-api/odds88-api-endpoints/bets-api)
{% endcontent-ref %}

{% content-ref url="/pages/CDyqERePHyDhrua9zyke" %}
[Cashout API](/odds88-client-api/odds88-api-endpoints/cashout-api)
{% endcontent-ref %}

{% hint style="info" %}
The exact exchange rate is not provided.
{% endhint %}

## Active Currencies Endpoint

Gets the list of supported currencies by type.

{% hint style="warning" %}
The endpoint is rate-limited to **10 requests per 1 minute**.
{% endhint %}

## Gets active currencies for the given currency type

> \
> \*\*Rate Limits (per account):\*\*\
> \- \*\*10 req/1m\*\*

```json
{"openapi":"3.0.4","info":{"title":"[T728-STAGE] Odds88 API","version":"v1"},"tags":[{"name":"CurrencyExchange"}],"security":[{"Bearer":[]}],"components":{"securitySchemes":{"Bearer":{"type":"http","description":"JWT Authorization header using the Bearer scheme. Example: \"Authorization: Bearer {token}\"","scheme":"Bearer","bearerFormat":"JWT"}},"schemas":{"CurrencyExchange.Models.CurrencyType":{"enum":[1,2,3],"type":"integer","description":"* `1` - Fiat\n* `2` - Crypto\n* `3` - Custom","format":"int32"},"CurrencyExchange.Models.Currencies.OutboundDTO.ActiveCurrencyDto":{"type":"object","properties":{"symbol":{"type":"string","nullable":true},"type":{"allOf":[{"$ref":"#/components/schemas/CurrencyExchange.Models.CurrencyType"}],"description":"* `1` - Fiat\n* `2` - Crypto\n* `3` - Custom"},"precision":{"type":"integer","format":"int32"}},"additionalProperties":false}}},"paths":{"/api/CurrencyExchange/active-currencies":{"get":{"tags":["CurrencyExchange"],"summary":"Gets active currencies for the given currency type","description":"\n**Rate Limits (per account):**\n- **10 req/1m**","operationId":"Get active currencies","parameters":[{"name":"type","in":"query","description":"Currency type to filter (if null - returns all active currencies for all types)","schema":{"allOf":[{"$ref":"#/components/schemas/CurrencyExchange.Models.CurrencyType"}],"description":"* `1` - Fiat\n* `2` - Crypto\n* `3` - Custom"}}],"responses":{"200":{"description":"OK","content":{"text/plain":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/CurrencyExchange.Models.Currencies.OutboundDTO.ActiveCurrencyDto"}}},"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/CurrencyExchange.Models.Currencies.OutboundDTO.ActiveCurrencyDto"}}},"text/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/CurrencyExchange.Models.Currencies.OutboundDTO.ActiveCurrencyDto"}}}}},"401":{"description":"Unauthorized"},"403":{"description":"Forbidden"},"429":{"description":"Too many requests"},"500":{"description":"Internal Server Error"}}}}}}
```

## Currency Precision Endpoint

Gets precision value of the specified currency.

{% hint style="warning" %}
The endpoint is rate-limited to **1 request per 1 second**.
{% endhint %}

## Gets precision value for the given currency ticker symbol

> \
> \*\*Rate Limits (per account):\*\*\
> \- \*\*1 req/1s\*\*

```json
{"openapi":"3.0.4","info":{"title":"[T728-STAGE] Odds88 API","version":"v1"},"tags":[{"name":"CurrencyExchange"}],"security":[{"Bearer":[]}],"components":{"securitySchemes":{"Bearer":{"type":"http","description":"JWT Authorization header using the Bearer scheme. Example: \"Authorization: Bearer {token}\"","scheme":"Bearer","bearerFormat":"JWT"}},"schemas":{"CurrencyExchange.Models.Currencies.OutboundDTO.CurrencyPrecisionDto":{"type":"object","properties":{"precision":{"type":"integer","format":"int32"}},"additionalProperties":false}}},"paths":{"/api/CurrencyExchange/currency-precision":{"get":{"tags":["CurrencyExchange"],"summary":"Gets precision value for the given currency ticker symbol","description":"\n**Rate Limits (per account):**\n- **1 req/1s**","operationId":"Get precision of a currency","parameters":[{"name":"symbol","in":"query","description":"Currency ticker symbol","schema":{"type":"string"}}],"responses":{"200":{"description":"OK","content":{"text/plain":{"schema":{"$ref":"#/components/schemas/CurrencyExchange.Models.Currencies.OutboundDTO.CurrencyPrecisionDto"}},"application/json":{"schema":{"$ref":"#/components/schemas/CurrencyExchange.Models.Currencies.OutboundDTO.CurrencyPrecisionDto"}},"text/json":{"schema":{"$ref":"#/components/schemas/CurrencyExchange.Models.Currencies.OutboundDTO.CurrencyPrecisionDto"}}}},"401":{"description":"Unauthorized"},"403":{"description":"Forbidden"},"429":{"description":"Too many requests"},"500":{"description":"Internal Server Error"}}}}}}
```


# Dictionary API

Provides static values

Dictionary API can be used to get static values for reference.

## GET /api/Dictionary/reject-reasons

> Gets possible reject reasons that can exist.

```json
{"openapi":"3.0.4","info":{"title":"[T728-STAGE] Odds88 API","version":"v1"},"tags":[{"name":"Dictionary"}],"security":[{"Bearer":[]}],"components":{"securitySchemes":{"Bearer":{"type":"http","description":"JWT Authorization header using the Bearer scheme. Example: \"Authorization: Bearer {token}\"","scheme":"Bearer","bearerFormat":"JWT"}}},"paths":{"/api/Dictionary/reject-reasons":{"get":{"tags":["Dictionary"],"summary":"Gets possible reject reasons that can exist.","operationId":"Reject reasons","responses":{"200":{"description":"OK"},"401":{"description":"Unauthorized"},"403":{"description":"Forbidden"}}}}}}
```


# Fixed Exotics API

Used for fixed exotics bet placement

Fixed Exotics API can be used to get odds for fixed exotics bet.

## POST /api/FixedExotics/price

> Get fixed exotics prices by specified racing selection, event and market IDs

```json
{"openapi":"3.0.4","info":{"title":"[T728-STAGE] Odds88 API","version":"v1"},"tags":[{"name":"FixedExotics"}],"security":[{"Bearer":[]}],"components":{"securitySchemes":{"Bearer":{"type":"http","description":"JWT Authorization header using the Bearer scheme. Example: \"Authorization: Bearer {token}\"","scheme":"Bearer","bearerFormat":"JWT"}},"schemas":{"Marlin.SportsbetApi.Host.Models.BetPlacement.GetFixedExoticPricesViewModel":{"type":"object","properties":{"eventId":{"type":"integer","description":"Event ID.","format":"int64"},"marketId":{"type":"integer","description":"Market ID.","format":"int64"},"racingSelection":{"type":"string","description":"Racing selection.","nullable":true},"correlationId":{"type":"string","description":"Correlation ID (optional).","nullable":true}},"additionalProperties":false,"description":"A model containing information needed for requesting fixed exotic market prices."},"Microsoft.AspNetCore.Mvc.ProblemDetails":{"type":"object","properties":{"type":{"type":"string","nullable":true},"title":{"type":"string","nullable":true},"status":{"type":"integer","format":"int32","nullable":true},"detail":{"type":"string","nullable":true},"instance":{"type":"string","nullable":true}},"additionalProperties":{}}}},"paths":{"/api/FixedExotics/price":{"post":{"tags":["FixedExotics"],"summary":"Get fixed exotics prices by specified racing selection, event and market IDs","operationId":"Get fixed exotic price by racing selection","requestBody":{"description":"View model containing all the parameters.","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/Marlin.SportsbetApi.Host.Models.BetPlacement.GetFixedExoticPricesViewModel"}],"description":"A model containing information needed for requesting fixed exotic market prices."}},"text/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/Marlin.SportsbetApi.Host.Models.BetPlacement.GetFixedExoticPricesViewModel"}],"description":"A model containing information needed for requesting fixed exotic market prices."}},"application/*+json":{"schema":{"allOf":[{"$ref":"#/components/schemas/Marlin.SportsbetApi.Host.Models.BetPlacement.GetFixedExoticPricesViewModel"}],"description":"A model containing information needed for requesting fixed exotic market prices."}}}},"responses":{"200":{"description":"Getting prices successfully"},"400":{"description":"Request arguments are not valid.","content":{"text/plain":{"schema":{"$ref":"#/components/schemas/Microsoft.AspNetCore.Mvc.ProblemDetails"}},"application/json":{"schema":{"$ref":"#/components/schemas/Microsoft.AspNetCore.Mvc.ProblemDetails"}},"text/json":{"schema":{"$ref":"#/components/schemas/Microsoft.AspNetCore.Mvc.ProblemDetails"}}}},"401":{"description":"Unauthorized"},"403":{"description":"Forbidden"},"404":{"description":"Event or market are not found.","content":{"text/plain":{"schema":{"$ref":"#/components/schemas/Microsoft.AspNetCore.Mvc.ProblemDetails"}},"application/json":{"schema":{"$ref":"#/components/schemas/Microsoft.AspNetCore.Mvc.ProblemDetails"}},"text/json":{"schema":{"$ref":"#/components/schemas/Microsoft.AspNetCore.Mvc.ProblemDetails"}}}},"500":{"description":"Unexpected error occurred."}}}}}}
```


# Feed API

Getting sport events and their snapshots

Feed API endpoints can be used to get events schedule and particular event snapshot from Odds88.

## Schedule Endpoints

### Regular Events Schedule

The endpoint can be used to fetch events based on sports, locations and start date.

It returns the list of events with their details, but without markets.

{% hint style="warning" %}
The endpoint is rate-limited to **10 requests per second**.
{% endhint %}

## Gets list of non-outright event with specified UTC start date.

> \
> \*\*Rate Limits (per account):\*\*\
> \- \*\*10 req/1s\*\*

```json
{"openapi":"3.0.4","info":{"title":"[T728-STAGE] Odds88 API","version":"v1"},"tags":[{"name":"Feed"}],"security":[{"Bearer":[]}],"components":{"securitySchemes":{"Bearer":{"type":"http","description":"JWT Authorization header using the Bearer scheme. Example: \"Authorization: Bearer {token}\"","scheme":"Bearer","bearerFormat":"JWT"}},"schemas":{"Marlin.SportsbetApi.Host.Services.FeedFactory.QueryTradingEventModel":{"type":"object","properties":{"startDate":{"type":"string","description":"Starting date of event. If null returns Events with StartTime=null or from tomorrow","nullable":true},"sportIds":{"type":"array","items":{"type":"integer","format":"int64"},"description":"If not null filters by SportIds","nullable":true},"locationIds":{"type":"array","items":{"type":"integer","format":"int64"},"description":"If not null filters by LocationIds","nullable":true}},"additionalProperties":false},"TradeArt.TradeArtApi.Contracts.DeltaMessage.EventInfoViewModelV2":{"type":"object","properties":{"id":{"type":"integer","description":"TradeArt event id.","format":"int64"},"name":{"type":"string","description":"Event name.","nullable":true},"status":{"allOf":[{"$ref":"#/components/schemas/TradeArt.TradeArtApi.Contracts.DeltaMessage.Enums.EventStatus"}],"description":"Event status representing current status of the match.\n\n* `0` - Unknown\n* `1` - Planned\n* `2` - SoonInPlay\n* `3` - Live\n* `4` - Completed\n* `5` - Cancelled\n* `6` - CoverageLost\n* `7` - Closed\n* `8` - Suspended\n* `9` - Postponed\n* `10` - Abandoned"},"tradingStatus":{"allOf":[{"$ref":"#/components/schemas/TradeArt.TradeArtApi.Contracts.DeltaMessage.Enums.TradingStatus"}],"description":"Status of trading for the event showing how it should be processed.\n\n* `0` - Open\n* `1` - Suspended\n* `2` - Closed\n* `3` - Inactive"},"statusDescription":{"type":"string","description":"Free text event status description (optional).","nullable":true},"country":{"allOf":[{"$ref":"#/components/schemas/TradeArt.TradeArtApi.Contracts.DeltaMessage.ReferenceViewModelV2"}],"description":"Id and Name of event's country.","nullable":true},"sport":{"allOf":[{"$ref":"#/components/schemas/TradeArt.TradeArtApi.Contracts.DeltaMessage.ReferenceViewModelV2"}],"description":"Id and Name of event's sport.","nullable":true},"competition":{"allOf":[{"$ref":"#/components/schemas/TradeArt.TradeArtApi.Contracts.DeltaMessage.ReferenceViewModelV2"}],"description":"Id and Name of event's competition.","nullable":true},"season":{"allOf":[{"$ref":"#/components/schemas/TradeArt.TradeArtApi.Contracts.DeltaMessage.ReferenceViewModelV2"}],"description":"Id and Name of event's season. Can be null for not-outright events.","nullable":true},"competitors":{"type":"array","items":{"$ref":"#/components/schemas/TradeArt.TradeArtApi.Contracts.DeltaMessage.ReferenceViewModelV2"},"description":"Ids and Names of event's competitors.","nullable":true},"startTime":{"type":"string","description":"Start time of the event. Can be null.","format":"date-time","nullable":true},"isOutright":{"type":"boolean","description":"Flag which indicates that event is outright."},"customDisplayData":{"type":"object","additionalProperties":{"type":"string"},"description":"Custom display parameters of the event","nullable":true},"isBetBuilderSupported":{"type":"boolean","description":"Indicates whether this selection can be used in Bet Builder"},"mappingInfo":{"type":"array","items":{"$ref":"#/components/schemas/TradeArt.TradeArtApi.Contracts.DeltaMessage.MappingViewModel"},"description":"Represents information about external feeds","nullable":true}},"additionalProperties":false,"description":"Information about event (sport, country, statuses etc.)"},"TradeArt.TradeArtApi.Contracts.DeltaMessage.Enums.EventStatus":{"enum":[0,1,2,3,4,5,6,7,8,9,10],"type":"integer","description":"Status of event\n\n* `0` - Unknown\n* `1` - Planned\n* `2` - SoonInPlay\n* `3` - Live\n* `4` - Completed\n* `5` - Cancelled\n* `6` - CoverageLost\n* `7` - Closed\n* `8` - Suspended\n* `9` - Postponed\n* `10` - Abandoned","format":"int32"},"TradeArt.TradeArtApi.Contracts.DeltaMessage.Enums.TradingStatus":{"enum":[0,1,2,3],"type":"integer","description":"Status of trading\n\n* `0` - Open\n* `1` - Suspended\n* `2` - Closed\n* `3` - Inactive","format":"int32"},"TradeArt.TradeArtApi.Contracts.DeltaMessage.ReferenceViewModelV2":{"type":"object","properties":{"id":{"type":"integer","description":"Id of the referenced entity","format":"int64"},"name":{"type":"string","description":"Name of the referenced entity","nullable":true}},"additionalProperties":false,"description":"Contains reference data for entity"},"TradeArt.TradeArtApi.Contracts.DeltaMessage.MappingViewModel":{"type":"object","properties":{"feedId":{"type":"integer","description":"External Feed Id","format":"int32"},"id":{"type":"string","description":"External Event Id","nullable":true}},"additionalProperties":false,"description":"External mappings info"},"Microsoft.AspNetCore.Mvc.ProblemDetails":{"type":"object","properties":{"type":{"type":"string","nullable":true},"title":{"type":"string","nullable":true},"status":{"type":"integer","format":"int32","nullable":true},"detail":{"type":"string","nullable":true},"instance":{"type":"string","nullable":true}},"additionalProperties":{}}}},"paths":{"/api/events/schedule/v2":{"post":{"tags":["Feed"],"summary":"Gets list of non-outright event with specified UTC start date.","description":"\n**Rate Limits (per account):**\n- **10 req/1s**","requestBody":{"description":"Request","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/Marlin.SportsbetApi.Host.Services.FeedFactory.QueryTradingEventModel"}]}},"text/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/Marlin.SportsbetApi.Host.Services.FeedFactory.QueryTradingEventModel"}]}},"application/*+json":{"schema":{"allOf":[{"$ref":"#/components/schemas/Marlin.SportsbetApi.Host.Services.FeedFactory.QueryTradingEventModel"}]}}},"required":true},"responses":{"200":{"description":"OK","content":{"text/plain":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/TradeArt.TradeArtApi.Contracts.DeltaMessage.EventInfoViewModelV2"}}},"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/TradeArt.TradeArtApi.Contracts.DeltaMessage.EventInfoViewModelV2"}}},"text/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/TradeArt.TradeArtApi.Contracts.DeltaMessage.EventInfoViewModelV2"}}}}},"400":{"description":"Bad Request","content":{"text/plain":{"schema":{"$ref":"#/components/schemas/Microsoft.AspNetCore.Mvc.ProblemDetails"}},"application/json":{"schema":{"$ref":"#/components/schemas/Microsoft.AspNetCore.Mvc.ProblemDetails"}},"text/json":{"schema":{"$ref":"#/components/schemas/Microsoft.AspNetCore.Mvc.ProblemDetails"}}}},"401":{"description":"Unauthorized"},"403":{"description":"Forbidden"},"429":{"description":"Too many requests"},"500":{"description":"Internal Server Error"}}}}}}
```

### Outrights Endpoint

Can be used to fetch outright events based on sports and locations.

It returns the list of events with their details, but without markets.

{% hint style="warning" %}
The endpoint is rate-limited to **10 requests per second**.
{% endhint %}

## Fetch Outright Events

> \
> \*\*Rate Limits (per account):\*\*\
> \- \*\*10 req/1s\*\*

```json
{"openapi":"3.0.4","info":{"title":"[T728-STAGE] Odds88 API","version":"v1"},"tags":[{"name":"Feed"}],"security":[{"Bearer":[]}],"components":{"securitySchemes":{"Bearer":{"type":"http","description":"JWT Authorization header using the Bearer scheme. Example: \"Authorization: Bearer {token}\"","scheme":"Bearer","bearerFormat":"JWT"}},"schemas":{"Marlin.SportsbetApi.Host.Services.FeedFactory.QueryOutrightEventModel":{"type":"object","properties":{"sportIds":{"type":"array","items":{"type":"integer","format":"int64"},"description":"If not null filters by SportIds","nullable":true},"locationIds":{"type":"array","items":{"type":"integer","format":"int64"},"description":"If not null filters by LocationIds","nullable":true}},"additionalProperties":false},"TradeArt.TradeArtApi.Contracts.DeltaMessage.EventInfoViewModelV2":{"type":"object","properties":{"id":{"type":"integer","description":"TradeArt event id.","format":"int64"},"name":{"type":"string","description":"Event name.","nullable":true},"status":{"allOf":[{"$ref":"#/components/schemas/TradeArt.TradeArtApi.Contracts.DeltaMessage.Enums.EventStatus"}],"description":"Event status representing current status of the match.\n\n* `0` - Unknown\n* `1` - Planned\n* `2` - SoonInPlay\n* `3` - Live\n* `4` - Completed\n* `5` - Cancelled\n* `6` - CoverageLost\n* `7` - Closed\n* `8` - Suspended\n* `9` - Postponed\n* `10` - Abandoned"},"tradingStatus":{"allOf":[{"$ref":"#/components/schemas/TradeArt.TradeArtApi.Contracts.DeltaMessage.Enums.TradingStatus"}],"description":"Status of trading for the event showing how it should be processed.\n\n* `0` - Open\n* `1` - Suspended\n* `2` - Closed\n* `3` - Inactive"},"statusDescription":{"type":"string","description":"Free text event status description (optional).","nullable":true},"country":{"allOf":[{"$ref":"#/components/schemas/TradeArt.TradeArtApi.Contracts.DeltaMessage.ReferenceViewModelV2"}],"description":"Id and Name of event's country.","nullable":true},"sport":{"allOf":[{"$ref":"#/components/schemas/TradeArt.TradeArtApi.Contracts.DeltaMessage.ReferenceViewModelV2"}],"description":"Id and Name of event's sport.","nullable":true},"competition":{"allOf":[{"$ref":"#/components/schemas/TradeArt.TradeArtApi.Contracts.DeltaMessage.ReferenceViewModelV2"}],"description":"Id and Name of event's competition.","nullable":true},"season":{"allOf":[{"$ref":"#/components/schemas/TradeArt.TradeArtApi.Contracts.DeltaMessage.ReferenceViewModelV2"}],"description":"Id and Name of event's season. Can be null for not-outright events.","nullable":true},"competitors":{"type":"array","items":{"$ref":"#/components/schemas/TradeArt.TradeArtApi.Contracts.DeltaMessage.ReferenceViewModelV2"},"description":"Ids and Names of event's competitors.","nullable":true},"startTime":{"type":"string","description":"Start time of the event. Can be null.","format":"date-time","nullable":true},"isOutright":{"type":"boolean","description":"Flag which indicates that event is outright."},"customDisplayData":{"type":"object","additionalProperties":{"type":"string"},"description":"Custom display parameters of the event","nullable":true},"isBetBuilderSupported":{"type":"boolean","description":"Indicates whether this selection can be used in Bet Builder"},"mappingInfo":{"type":"array","items":{"$ref":"#/components/schemas/TradeArt.TradeArtApi.Contracts.DeltaMessage.MappingViewModel"},"description":"Represents information about external feeds","nullable":true}},"additionalProperties":false,"description":"Information about event (sport, country, statuses etc.)"},"TradeArt.TradeArtApi.Contracts.DeltaMessage.Enums.EventStatus":{"enum":[0,1,2,3,4,5,6,7,8,9,10],"type":"integer","description":"Status of event\n\n* `0` - Unknown\n* `1` - Planned\n* `2` - SoonInPlay\n* `3` - Live\n* `4` - Completed\n* `5` - Cancelled\n* `6` - CoverageLost\n* `7` - Closed\n* `8` - Suspended\n* `9` - Postponed\n* `10` - Abandoned","format":"int32"},"TradeArt.TradeArtApi.Contracts.DeltaMessage.Enums.TradingStatus":{"enum":[0,1,2,3],"type":"integer","description":"Status of trading\n\n* `0` - Open\n* `1` - Suspended\n* `2` - Closed\n* `3` - Inactive","format":"int32"},"TradeArt.TradeArtApi.Contracts.DeltaMessage.ReferenceViewModelV2":{"type":"object","properties":{"id":{"type":"integer","description":"Id of the referenced entity","format":"int64"},"name":{"type":"string","description":"Name of the referenced entity","nullable":true}},"additionalProperties":false,"description":"Contains reference data for entity"},"TradeArt.TradeArtApi.Contracts.DeltaMessage.MappingViewModel":{"type":"object","properties":{"feedId":{"type":"integer","description":"External Feed Id","format":"int32"},"id":{"type":"string","description":"External Event Id","nullable":true}},"additionalProperties":false,"description":"External mappings info"},"Microsoft.AspNetCore.Mvc.ProblemDetails":{"type":"object","properties":{"type":{"type":"string","nullable":true},"title":{"type":"string","nullable":true},"status":{"type":"integer","format":"int32","nullable":true},"detail":{"type":"string","nullable":true},"instance":{"type":"string","nullable":true}},"additionalProperties":{}}}},"paths":{"/api/events/outrights":{"post":{"tags":["Feed"],"summary":"Fetch Outright Events","description":"\n**Rate Limits (per account):**\n- **10 req/1s**","requestBody":{"description":"Request","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/Marlin.SportsbetApi.Host.Services.FeedFactory.QueryOutrightEventModel"}]}},"text/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/Marlin.SportsbetApi.Host.Services.FeedFactory.QueryOutrightEventModel"}]}},"application/*+json":{"schema":{"allOf":[{"$ref":"#/components/schemas/Marlin.SportsbetApi.Host.Services.FeedFactory.QueryOutrightEventModel"}]}}},"required":true},"responses":{"200":{"description":"OK","content":{"text/plain":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/TradeArt.TradeArtApi.Contracts.DeltaMessage.EventInfoViewModelV2"}}},"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/TradeArt.TradeArtApi.Contracts.DeltaMessage.EventInfoViewModelV2"}}},"text/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/TradeArt.TradeArtApi.Contracts.DeltaMessage.EventInfoViewModelV2"}}}}},"400":{"description":"Bad Request","content":{"text/plain":{"schema":{"$ref":"#/components/schemas/Microsoft.AspNetCore.Mvc.ProblemDetails"}},"application/json":{"schema":{"$ref":"#/components/schemas/Microsoft.AspNetCore.Mvc.ProblemDetails"}},"text/json":{"schema":{"$ref":"#/components/schemas/Microsoft.AspNetCore.Mvc.ProblemDetails"}}}},"401":{"description":"Unauthorized"},"403":{"description":"Forbidden"},"429":{"description":"Too many requests"},"500":{"description":"Internal Server Error"}}}}}}
```

### Event snapshot endpoint

Can be used to fetch the latest snapshot of a specified event or outright fixture with all markets.

This endpoint can be used to recover events in case a message or messages were missed.

{% hint style="warning" %}
This endpoint is rate-limited to **10 requests per second.**
{% endhint %}

## Get snapshot of the specific event.

> \
> \*\*Rate Limits (per account):\*\*\
> \- \*\*10 req/1s\*\*

```json
{"openapi":"3.0.4","info":{"title":"[T728-STAGE] Odds88 API","version":"v1"},"tags":[{"name":"Feed"}],"security":[{"Bearer":[]}],"components":{"securitySchemes":{"Bearer":{"type":"http","description":"JWT Authorization header using the Bearer scheme. Example: \"Authorization: Bearer {token}\"","scheme":"Bearer","bearerFormat":"JWT"}},"schemas":{"TradeArt.TradeArtApi.Contracts.DeltaMessage.Delta.EventSnapshotDeltaViewModelV2":{"type":"object","properties":{"type":{"allOf":[{"$ref":"#/components/schemas/TradeArt.TradeArtApi.Contracts.DeltaMessage.Enums.DeltaType"}],"description":"Type of delta\n\n* `0` - None\n* `1` - EventStatusChanged\n* `2` - EventChanged\n* `3` - MarketChanged\n* `4` - ScoreboardChanged\n* `5` - BetCancel\n* `6` - EventSnapshot\n* `7` - MarketsChanged"},"eventId":{"type":"integer","description":"Id of changed event","format":"int64"},"version":{"type":"integer","description":"Version of feed state","format":"int64"},"correlationId":{"type":"string","description":"Correlation id of the message to trace back.","nullable":true},"creationTime":{"type":"string","description":"Captures the timestamp the dto was created.","format":"date-time"},"sportId":{"type":"integer","description":"Id of the Sport","format":"int64"},"locationId":{"type":"integer","description":"Id of the Location","format":"int64"},"leagueId":{"type":"integer","description":"Id of the League","format":"int64"},"updateSequence":{"type":"integer","description":"Event delta sequence.\nIncremented with each sent delta.","format":"int64"},"lastUpdatedTime":{"type":"integer","description":"Event update time.\nIncremented with each valuable update.","format":"int64"},"eventInfo":{"allOf":[{"$ref":"#/components/schemas/TradeArt.TradeArtApi.Contracts.DeltaMessage.EventInfoViewModelV2"}],"description":"Fixture info containing basic event information.","nullable":true},"markets":{"type":"array","items":{"$ref":"#/components/schemas/TradeArt.TradeArtApi.Contracts.DeltaMessage.MarketViewModelV2"},"description":"Markets of the event.","nullable":true},"scoreboard":{"allOf":[{"$ref":"#/components/schemas/TradeArt.TradeArtApi.Contracts.DeltaMessage.Scoreboard.ScoreboardViewModel"}],"description":"Scoreboard of the event. Can be null.","nullable":true},"betCancellations":{"type":"array","items":{"$ref":"#/components/schemas/TradeArt.TradeArtApi.Contracts.DeltaMessage.BetCancellationViewModel"},"description":"List of bet cancellations on this event and certain market received from BetRadar. Can be null.","nullable":true}},"additionalProperties":false,"description":"Full snapshot of event data"},"TradeArt.TradeArtApi.Contracts.DeltaMessage.Enums.DeltaType":{"enum":[0,1,2,3,4,5,6,7],"type":"integer","description":"Known types of deltas\n\n* `0` - None\n* `1` - EventStatusChanged\n* `2` - EventChanged\n* `3` - MarketChanged\n* `4` - ScoreboardChanged\n* `5` - BetCancel\n* `6` - EventSnapshot\n* `7` - MarketsChanged","format":"int32"},"TradeArt.TradeArtApi.Contracts.DeltaMessage.EventInfoViewModelV2":{"type":"object","properties":{"id":{"type":"integer","description":"TradeArt event id.","format":"int64"},"name":{"type":"string","description":"Event name.","nullable":true},"status":{"allOf":[{"$ref":"#/components/schemas/TradeArt.TradeArtApi.Contracts.DeltaMessage.Enums.EventStatus"}],"description":"Event status representing current status of the match.\n\n* `0` - Unknown\n* `1` - Planned\n* `2` - SoonInPlay\n* `3` - Live\n* `4` - Completed\n* `5` - Cancelled\n* `6` - CoverageLost\n* `7` - Closed\n* `8` - Suspended\n* `9` - Postponed\n* `10` - Abandoned"},"tradingStatus":{"allOf":[{"$ref":"#/components/schemas/TradeArt.TradeArtApi.Contracts.DeltaMessage.Enums.TradingStatus"}],"description":"Status of trading for the event showing how it should be processed.\n\n* `0` - Open\n* `1` - Suspended\n* `2` - Closed\n* `3` - Inactive"},"statusDescription":{"type":"string","description":"Free text event status description (optional).","nullable":true},"country":{"allOf":[{"$ref":"#/components/schemas/TradeArt.TradeArtApi.Contracts.DeltaMessage.ReferenceViewModelV2"}],"description":"Id and Name of event's country.","nullable":true},"sport":{"allOf":[{"$ref":"#/components/schemas/TradeArt.TradeArtApi.Contracts.DeltaMessage.ReferenceViewModelV2"}],"description":"Id and Name of event's sport.","nullable":true},"competition":{"allOf":[{"$ref":"#/components/schemas/TradeArt.TradeArtApi.Contracts.DeltaMessage.ReferenceViewModelV2"}],"description":"Id and Name of event's competition.","nullable":true},"season":{"allOf":[{"$ref":"#/components/schemas/TradeArt.TradeArtApi.Contracts.DeltaMessage.ReferenceViewModelV2"}],"description":"Id and Name of event's season. Can be null for not-outright events.","nullable":true},"competitors":{"type":"array","items":{"$ref":"#/components/schemas/TradeArt.TradeArtApi.Contracts.DeltaMessage.ReferenceViewModelV2"},"description":"Ids and Names of event's competitors.","nullable":true},"startTime":{"type":"string","description":"Start time of the event. Can be null.","format":"date-time","nullable":true},"isOutright":{"type":"boolean","description":"Flag which indicates that event is outright."},"customDisplayData":{"type":"object","additionalProperties":{"type":"string"},"description":"Custom display parameters of the event","nullable":true},"isBetBuilderSupported":{"type":"boolean","description":"Indicates whether this selection can be used in Bet Builder"},"mappingInfo":{"type":"array","items":{"$ref":"#/components/schemas/TradeArt.TradeArtApi.Contracts.DeltaMessage.MappingViewModel"},"description":"Represents information about external feeds","nullable":true}},"additionalProperties":false,"description":"Information about event (sport, country, statuses etc.)"},"TradeArt.TradeArtApi.Contracts.DeltaMessage.Enums.EventStatus":{"enum":[0,1,2,3,4,5,6,7,8,9,10],"type":"integer","description":"Status of event\n\n* `0` - Unknown\n* `1` - Planned\n* `2` - SoonInPlay\n* `3` - Live\n* `4` - Completed\n* `5` - Cancelled\n* `6` - CoverageLost\n* `7` - Closed\n* `8` - Suspended\n* `9` - Postponed\n* `10` - Abandoned","format":"int32"},"TradeArt.TradeArtApi.Contracts.DeltaMessage.Enums.TradingStatus":{"enum":[0,1,2,3],"type":"integer","description":"Status of trading\n\n* `0` - Open\n* `1` - Suspended\n* `2` - Closed\n* `3` - Inactive","format":"int32"},"TradeArt.TradeArtApi.Contracts.DeltaMessage.ReferenceViewModelV2":{"type":"object","properties":{"id":{"type":"integer","description":"Id of the referenced entity","format":"int64"},"name":{"type":"string","description":"Name of the referenced entity","nullable":true}},"additionalProperties":false,"description":"Contains reference data for entity"},"TradeArt.TradeArtApi.Contracts.DeltaMessage.MappingViewModel":{"type":"object","properties":{"feedId":{"type":"integer","description":"External Feed Id","format":"int32"},"id":{"type":"string","description":"External Event Id","nullable":true}},"additionalProperties":false,"description":"External mappings info"},"TradeArt.TradeArtApi.Contracts.DeltaMessage.MarketViewModelV2":{"type":"object","properties":{"id":{"type":"integer","description":"Market Id","format":"int64"},"name":{"type":"string","description":"Market name","nullable":true},"tradingStatus":{"allOf":[{"$ref":"#/components/schemas/TradeArt.TradeArtApi.Contracts.DeltaMessage.Enums.TradingStatus"}],"description":"Market trading status\n\n* `0` - Open\n* `1` - Suspended\n* `2` - Closed\n* `3` - Inactive"},"selections":{"type":"array","items":{"$ref":"#/components/schemas/TradeArt.TradeArtApi.Contracts.DeltaMessage.SelectionViewModelV2"},"description":"Market selections","nullable":true},"type":{"type":"integer","description":"Market type Id","format":"int64"},"isBestLine":{"type":"boolean","description":"Is the main market?"},"parameters":{"type":"object","additionalProperties":{"type":"string"},"description":"Parameters of market. i.e. hcp = 2.5, total=1.5","nullable":true},"extraParameters":{"type":"object","additionalProperties":{"type":"string"},"description":"Additional market information (like score = 1:0)","nullable":true},"isBetBuilderSupported":{"type":"boolean","description":"Indicates whether this selection can be used in Bet Builder"}},"additionalProperties":false,"description":"Represents market data"},"TradeArt.TradeArtApi.Contracts.DeltaMessage.SelectionViewModelV2":{"type":"object","properties":{"id":{"type":"integer","description":"Selection Id","format":"int64"},"name":{"type":"string","description":"Selection name","nullable":true},"probability":{"type":"number","description":"Selection probability","format":"float","nullable":true},"price":{"type":"number","description":"Selection odds","format":"float","nullable":true},"originalPrice":{"type":"number","description":"Selection odds","format":"float","nullable":true},"status":{"allOf":[{"$ref":"#/components/schemas/TradeArt.TradeArtApi.Contracts.DeltaMessage.Enums.TradingStatus"}],"description":"Trading selection status\n\n* `0` - Open\n* `1` - Suspended\n* `2` - Closed\n* `3` - Inactive"},"settlement":{"allOf":[{"$ref":"#/components/schemas/TradeArt.TradeArtApi.Contracts.DeltaMessage.Enums.SettlementResult"}],"description":"Settlement result of the selection\n\n* `0` - None\n* `1` - Refund\n* `2` - Lose\n* `3` - Win\n* `4` - HalfLose\n* `5` - HalfWin"},"deadHeatFactor":{"type":"number","description":"Dead heat factor is a floating point number used when there is a tie in outrights","format":"double","nullable":true},"extraParameters":{"type":"object","additionalProperties":{"type":"string"},"description":"Additional selection information","nullable":true},"isBetBuilderSupported":{"type":"boolean","description":"Indicates whether this selection can be used in Bet Builder"},"competitorId":{"type":"integer","description":"Id of the competitor","format":"int64"},"startingPrice":{"type":"number","description":"Starting Price of the selection before turning to in-play.","format":"float","nullable":true}},"additionalProperties":false,"description":"Represents market selection information"},"TradeArt.TradeArtApi.Contracts.DeltaMessage.Enums.SettlementResult":{"enum":[0,1,2,3,4,5],"type":"integer","description":"Status of a selection settlement\n\n* `0` - None\n* `1` - Refund\n* `2` - Lose\n* `3` - Win\n* `4` - HalfLose\n* `5` - HalfWin","format":"int32"},"TradeArt.TradeArtApi.Contracts.DeltaMessage.Scoreboard.ScoreboardViewModel":{"type":"object","properties":{"time":{"type":"integer","description":"Current time of event (in seconds)","format":"int32"},"results":{"type":"array","items":{"$ref":"#/components/schemas/TradeArt.TradeArtApi.Contracts.DeltaMessage.Scoreboard.ResultViewModel"},"description":"Current event results per competitor (in seconds)","nullable":true},"periods":{"type":"array","items":{"$ref":"#/components/schemas/TradeArt.TradeArtApi.Contracts.DeltaMessage.Scoreboard.PeriodViewModel"},"description":"Current event periods with results and incidents","nullable":true},"incidents":{"type":"array","items":{"$ref":"#/components/schemas/TradeArt.TradeArtApi.Contracts.DeltaMessage.Scoreboard.IncidentCountViewModel"},"description":"Current event incident summary","nullable":true},"currentPeriodId":{"type":"integer","description":"Internal id of current period","format":"int32"},"lastUpdateTime":{"type":"string","description":"Last update time of the scoreboard","format":"date-time"},"homeGameScore":{"type":"string","description":"Current home team game score","nullable":true},"awayGameScore":{"type":"string","description":"Current away team game score","nullable":true},"extraData":{"type":"object","additionalProperties":{"type":"string"},"description":"Extra parameters of the score","nullable":true}},"additionalProperties":false,"description":"Represents event's scoreboard"},"TradeArt.TradeArtApi.Contracts.DeltaMessage.Scoreboard.ResultViewModel":{"type":"object","properties":{"competitorPosition":{"type":"integer","description":"Competitor position (e.g. 1 - Home, 2 - Away)","format":"int32"},"value":{"type":"string","description":"Result value","nullable":true}},"additionalProperties":false,"description":"Represents scoreboard result"},"TradeArt.TradeArtApi.Contracts.DeltaMessage.Scoreboard.PeriodViewModel":{"type":"object","properties":{"id":{"type":"integer","description":"Period Id","format":"int32"},"isFinished":{"type":"boolean","description":"Is period finished?"},"incidents":{"type":"array","items":{"$ref":"#/components/schemas/TradeArt.TradeArtApi.Contracts.DeltaMessage.Scoreboard.IncidentViewModel"},"description":"Incidents occurred in the period","nullable":true},"results":{"type":"array","items":{"$ref":"#/components/schemas/TradeArt.TradeArtApi.Contracts.DeltaMessage.Scoreboard.ResultViewModel"},"description":"Results of the period","nullable":true},"order":{"type":"integer","description":"The position of this period in a sorted sequence.","format":"int32"},"subPeriods":{"type":"array","items":{"$ref":"#/components/schemas/TradeArt.TradeArtApi.Contracts.DeltaMessage.Scoreboard.SubPeriodViewModel"},"description":"Sub periods of the period","nullable":true}},"additionalProperties":false,"description":"Represents period of the event"},"TradeArt.TradeArtApi.Contracts.DeltaMessage.Scoreboard.IncidentViewModel":{"type":"object","properties":{"type":{"type":"integer","description":"Incident type","format":"int32"},"time":{"type":"integer","description":"Event time","format":"int32"},"competitorPosition":{"type":"integer","description":"Index of the competitor in the EventInfo.Competitors array","format":"int32"}},"additionalProperties":false,"description":"Represents incident information"},"TradeArt.TradeArtApi.Contracts.DeltaMessage.Scoreboard.SubPeriodViewModel":{"type":"object","properties":{"isFinished":{"type":"boolean","description":"Is sub period finished?"},"results":{"type":"array","items":{"$ref":"#/components/schemas/TradeArt.TradeArtApi.Contracts.DeltaMessage.Scoreboard.ResultViewModel"},"description":"Results of the sub period","nullable":true},"order":{"type":"integer","description":"The position of this sub period in a sorted sequence.","format":"int32"}},"additionalProperties":false,"description":"Represents sub period of the event period"},"TradeArt.TradeArtApi.Contracts.DeltaMessage.Scoreboard.IncidentCountViewModel":{"type":"object","properties":{"type":{"type":"integer","description":"Incident type","format":"int32"},"competitorPosition":{"type":"integer","description":"Competitor position (e.g. 1 - Home, 2 - Away)","format":"int32"},"count":{"type":"integer","description":"Incident count","format":"int32"}},"additionalProperties":false,"description":"Incident count by type and competitor"},"TradeArt.TradeArtApi.Contracts.DeltaMessage.BetCancellationViewModel":{"type":"object","properties":{"marketId":{"type":"integer","description":"Affected MarketId","format":"int64"},"from":{"type":"string","description":"Cancel bets placed starting From this date. Equals DateTime.MinValue if no lower bound provided","format":"date-time"},"to":{"type":"string","description":"Cancel bets placed starting To this date. Equals DateTime.MaxValue if no upper bound provided","format":"date-time"},"isRolledBack":{"type":"boolean","description":"Flag pointing whether this cancellation should be rolled back"}},"additionalProperties":false,"description":"Information about bet cancellations on certain market between From and To dates"}}},"paths":{"/api/events/v2/{eventId}":{"get":{"tags":["Feed"],"summary":"Get snapshot of the specific event.","description":"\n**Rate Limits (per account):**\n- **10 req/1s**","operationId":"Get event snapshot V2","parameters":[{"name":"eventId","in":"path","description":"TradeArt event id.","required":true,"schema":{"type":"integer","format":"int64"}}],"responses":{"200":{"description":"OK","content":{"text/plain":{"schema":{"$ref":"#/components/schemas/TradeArt.TradeArtApi.Contracts.DeltaMessage.Delta.EventSnapshotDeltaViewModelV2"}},"application/json":{"schema":{"$ref":"#/components/schemas/TradeArt.TradeArtApi.Contracts.DeltaMessage.Delta.EventSnapshotDeltaViewModelV2"}},"text/json":{"schema":{"$ref":"#/components/schemas/TradeArt.TradeArtApi.Contracts.DeltaMessage.Delta.EventSnapshotDeltaViewModelV2"}}}},"401":{"description":"Unauthorized"},"403":{"description":"Forbidden"},"404":{"description":"Not Found","content":{"text/plain":{"schema":{"type":"string"}},"application/json":{"schema":{"type":"string"}},"text/json":{"schema":{"type":"string"}}}},"410":{"description":"Gone","content":{"text/plain":{"schema":{"type":"string"}},"application/json":{"schema":{"type":"string"}},"text/json":{"schema":{"type":"string"}}}},"429":{"description":"Too many requests"},"500":{"description":"Internal Server Error"}}}}}}
```


# Metadata API

Getting event supplementary data

Metadata API can be used to fetch supplementary information about specific sport event.

{% hint style="warning" %}
The endpoints are rate-limited.
{% endhint %}

## Gets metadata of specific type and version for a specific event.

> \
> \*\*Rate Limits (per account):\*\*\
> \- \*\*20 req/1s\*\*

```json
{"openapi":"3.0.4","info":{"title":"[T728-STAGE] Odds88 API","version":"v1"},"tags":[{"name":"Metadata"}],"security":[{"Bearer":[]}],"components":{"securitySchemes":{"Bearer":{"type":"http","description":"JWT Authorization header using the Bearer scheme. Example: \"Authorization: Bearer {token}\"","scheme":"Bearer","bearerFormat":"JWT"}},"schemas":{"Marlin.SportsbetApi.Metadata.Model.EventMetadataViewModel":{"type":"object","properties":{"eventId":{"type":"integer","format":"int64"},"sportId":{"type":"integer","format":"int64"},"dataType":{"type":"string","nullable":true},"version":{"type":"integer","format":"int64","nullable":true},"data":{"nullable":true},"creationTime":{"type":"string","format":"date-time"}},"additionalProperties":false},"Microsoft.AspNetCore.Mvc.ProblemDetails":{"type":"object","properties":{"type":{"type":"string","nullable":true},"title":{"type":"string","nullable":true},"status":{"type":"integer","format":"int32","nullable":true},"detail":{"type":"string","nullable":true},"instance":{"type":"string","nullable":true}},"additionalProperties":{}}}},"paths":{"/api/Metadata/event/{dataType}/{eventId}":{"get":{"tags":["Metadata"],"summary":"Gets metadata of specific type and version for a specific event.","description":"\n**Rate Limits (per account):**\n- **20 req/1s**","parameters":[{"name":"eventId","in":"path","description":"TradeArt event id.","required":true,"schema":{"type":"integer","format":"int64"}},{"name":"dataType","in":"path","description":"Metadata type.","required":true,"schema":{"type":"string"}},{"name":"version","in":"query","description":"Expected version of metadata. Will return latest if not specified.","schema":{"type":"integer","format":"int64"}}],"responses":{"200":{"description":"OK","content":{"text/plain":{"schema":{"$ref":"#/components/schemas/Marlin.SportsbetApi.Metadata.Model.EventMetadataViewModel"}},"application/json":{"schema":{"$ref":"#/components/schemas/Marlin.SportsbetApi.Metadata.Model.EventMetadataViewModel"}},"text/json":{"schema":{"$ref":"#/components/schemas/Marlin.SportsbetApi.Metadata.Model.EventMetadataViewModel"}}}},"401":{"description":"Unauthorized"},"403":{"description":"Forbidden"},"404":{"description":"Not Found","content":{"text/plain":{"schema":{"$ref":"#/components/schemas/Microsoft.AspNetCore.Mvc.ProblemDetails"}},"application/json":{"schema":{"$ref":"#/components/schemas/Microsoft.AspNetCore.Mvc.ProblemDetails"}},"text/json":{"schema":{"$ref":"#/components/schemas/Microsoft.AspNetCore.Mvc.ProblemDetails"}}}},"429":{"description":"Too many requests"}}}}}}
```

{% hint style="warning" %}
This endpoint is rate-limited to **20 requests per second.**
{% endhint %}

## Gets known metadata types for a specific sport.

> \
> \*\*Rate Limits (per account):\*\*\
> \- \*\*20 req/1s\*\*

```json
{"openapi":"3.0.4","info":{"title":"[T728-STAGE] Odds88 API","version":"v1"},"tags":[{"name":"Metadata"}],"security":[{"Bearer":[]}],"components":{"securitySchemes":{"Bearer":{"type":"http","description":"JWT Authorization header using the Bearer scheme. Example: \"Authorization: Bearer {token}\"","scheme":"Bearer","bearerFormat":"JWT"}}},"paths":{"/api/Metadata/sport/types/{sportId}":{"get":{"tags":["Metadata"],"summary":"Gets known metadata types for a specific sport.","description":"\n**Rate Limits (per account):**\n- **20 req/1s**","parameters":[{"name":"sportId","in":"path","description":"TradeArt sport id.","required":true,"schema":{"type":"integer","format":"int64"}}],"responses":{"200":{"description":"OK","content":{"text/plain":{"schema":{"type":"array","items":{"type":"string"}}},"application/json":{"schema":{"type":"array","items":{"type":"string"}}},"text/json":{"schema":{"type":"array","items":{"type":"string"}}}}},"401":{"description":"Unauthorized"},"403":{"description":"Forbidden"},"429":{"description":"Too many requests"}}}}}}
```

{% hint style="warning" %}
This endpoint is rate-limited to **20 requests per second.**
{% endhint %}

## Gets all latest metadata for a specific event.

> \
> \*\*Rate Limits (per account):\*\*\
> \- \*\*1 req/1s\*\*

```json
{"openapi":"3.0.4","info":{"title":"[T728-STAGE] Odds88 API","version":"v1"},"tags":[{"name":"Metadata"}],"security":[{"Bearer":[]}],"components":{"securitySchemes":{"Bearer":{"type":"http","description":"JWT Authorization header using the Bearer scheme. Example: \"Authorization: Bearer {token}\"","scheme":"Bearer","bearerFormat":"JWT"}},"schemas":{"Marlin.SportsbetApi.Metadata.Model.EventMetadataViewModel":{"type":"object","properties":{"eventId":{"type":"integer","format":"int64"},"sportId":{"type":"integer","format":"int64"},"dataType":{"type":"string","nullable":true},"version":{"type":"integer","format":"int64","nullable":true},"data":{"nullable":true},"creationTime":{"type":"string","format":"date-time"}},"additionalProperties":false}}},"paths":{"/api/Metadata/event/all/{eventId}":{"get":{"tags":["Metadata"],"summary":"Gets all latest metadata for a specific event.","description":"\n**Rate Limits (per account):**\n- **1 req/1s**","parameters":[{"name":"eventId","in":"path","description":"TradeArt event id.","required":true,"schema":{"type":"integer","format":"int64"}}],"responses":{"200":{"description":"OK","content":{"text/plain":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/Marlin.SportsbetApi.Metadata.Model.EventMetadataViewModel"}}},"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/Marlin.SportsbetApi.Metadata.Model.EventMetadataViewModel"}}},"text/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/Marlin.SportsbetApi.Metadata.Model.EventMetadataViewModel"}}}}},"401":{"description":"Unauthorized"},"403":{"description":"Forbidden"},"429":{"description":"Too many requests"}}}}}}
```

{% hint style="warning" %}
This endpoint is rate-limited to **1 request per second.**
{% endhint %}

## Gets all existing metadata types for a specific event.

> \
> \*\*Rate Limits (per account):\*\*\
> \- \*\*40 req/1s\*\*

```json
{"openapi":"3.0.4","info":{"title":"[T728-STAGE] Odds88 API","version":"v1"},"tags":[{"name":"Metadata"}],"security":[{"Bearer":[]}],"components":{"securitySchemes":{"Bearer":{"type":"http","description":"JWT Authorization header using the Bearer scheme. Example: \"Authorization: Bearer {token}\"","scheme":"Bearer","bearerFormat":"JWT"}}},"paths":{"/api/Metadata/event/types/{eventId}":{"get":{"tags":["Metadata"],"summary":"Gets all existing metadata types for a specific event.","description":"\n**Rate Limits (per account):**\n- **40 req/1s**","parameters":[{"name":"eventId","in":"path","description":"TradeArt event id.","required":true,"schema":{"type":"integer","format":"int64"}}],"responses":{"200":{"description":"OK","content":{"text/plain":{"schema":{"type":"array","items":{"type":"string"}}},"application/json":{"schema":{"type":"array","items":{"type":"string"}}},"text/json":{"schema":{"type":"array","items":{"type":"string"}}}}},"401":{"description":"Unauthorized"},"403":{"description":"Forbidden"},"429":{"description":"Too many requests"}}}}}}
```

{% hint style="warning" %}
This endpoint is rate-limited to **40 requests per second.**
{% endhint %}


# Global Metadata API

Getting global supplementary data

The global metadata API can be used to fetch supplementary information about shared entities like sport, location, league, or competitor.

{% hint style="warning" %}
The endpoints are rate-limited.
{% endhint %}

### Recommended Usage Pattern

To discover what types of metadata are available for a specific entity, it's recommended to call the `/types` endpoint **first**. This helps you query only the relevant data types afterward.

### Example:

* Get available metadata types for a team/competitor:

## GET /api/GlobalMetadata/sport/{sportId}/league/{leagueId}/competitor/{competitorId}/types

> \
> \*\*Rate Limits (per account):\*\*\
> \- \*\*40 req/1s\*\*

```json
{"openapi":"3.0.4","info":{"title":"[T728-STAGE] Odds88 API","version":"v1"},"tags":[{"name":"GlobalMetadata"}],"security":[{"Bearer":[]}],"components":{"securitySchemes":{"Bearer":{"type":"http","description":"JWT Authorization header using the Bearer scheme. Example: \"Authorization: Bearer {token}\"","scheme":"Bearer","bearerFormat":"JWT"}}},"paths":{"/api/GlobalMetadata/sport/{sportId}/league/{leagueId}/competitor/{competitorId}/types":{"get":{"tags":["GlobalMetadata"],"description":"\n**Rate Limits (per account):**\n- **40 req/1s**","parameters":[{"name":"sportId","in":"path","required":true,"schema":{"type":"integer","format":"int64"}},{"name":"leagueId","in":"path","required":true,"schema":{"type":"integer","format":"int64"}},{"name":"competitorId","in":"path","required":true,"schema":{"type":"integer","format":"int64"}}],"responses":{"200":{"description":"OK","content":{"text/plain":{"schema":{"type":"array","items":{"type":"string"}}},"application/json":{"schema":{"type":"array","items":{"type":"string"}}},"text/json":{"schema":{"type":"array","items":{"type":"string"}}}}},"401":{"description":"Unauthorized"},"403":{"description":"Forbidden"},"429":{"description":"Too many requests"}}}}}}
```

* Get available metadata for that specific metadata type:

## GET /api/GlobalMetadata/sport/{sportId}/league/{leagueId}/competitor/{competitorId}/{dataType}

> \
> \*\*Rate Limits (per account):\*\*\
> \- \*\*40 req/1s\*\*

```json
{"openapi":"3.0.4","info":{"title":"[T728-STAGE] Odds88 API","version":"v1"},"tags":[{"name":"GlobalMetadata"}],"security":[{"Bearer":[]}],"components":{"securitySchemes":{"Bearer":{"type":"http","description":"JWT Authorization header using the Bearer scheme. Example: \"Authorization: Bearer {token}\"","scheme":"Bearer","bearerFormat":"JWT"}},"schemas":{"Marlin.SportsbetApi.Host.Models.MetaData.GlobalMetadataViewModel":{"type":"object","properties":{"sportId":{"type":"integer","description":"ID of the sport.","format":"int64","nullable":true},"locationId":{"type":"integer","description":"ID of the location.","format":"int64","nullable":true},"leagueId":{"type":"integer","description":"ID of the league.","format":"int64","nullable":true},"competitorId":{"type":"integer","description":"ID of the Competitor.","format":"int64","nullable":true},"playerId":{"type":"integer","description":"ID of the Player.","format":"int64","nullable":true},"dataType":{"type":"string","description":"Type of data.","nullable":true},"version":{"type":"integer","description":"Version of the metadata.","format":"int64","nullable":true},"data":{"description":"The actual data.","nullable":true},"creationTime":{"type":"string","description":"Creation timestamp.","format":"date-time"},"feedSource":{"type":"integer","description":"ID of the feed source.","format":"int32"}},"additionalProperties":false,"description":"Metadata for an event."},"Microsoft.AspNetCore.Mvc.ProblemDetails":{"type":"object","properties":{"type":{"type":"string","nullable":true},"title":{"type":"string","nullable":true},"status":{"type":"integer","format":"int32","nullable":true},"detail":{"type":"string","nullable":true},"instance":{"type":"string","nullable":true}},"additionalProperties":{}}}},"paths":{"/api/GlobalMetadata/sport/{sportId}/league/{leagueId}/competitor/{competitorId}/{dataType}":{"get":{"tags":["GlobalMetadata"],"description":"\n**Rate Limits (per account):**\n- **40 req/1s**","parameters":[{"name":"sportId","in":"path","required":true,"schema":{"type":"integer","format":"int64"}},{"name":"leagueId","in":"path","required":true,"schema":{"type":"integer","format":"int64"}},{"name":"competitorId","in":"path","required":true,"schema":{"type":"integer","format":"int64"}},{"name":"dataType","in":"path","required":true,"schema":{"type":"string"}},{"name":"version","in":"query","schema":{"type":"integer","format":"int64"}}],"responses":{"200":{"description":"OK","content":{"text/plain":{"schema":{"$ref":"#/components/schemas/Marlin.SportsbetApi.Host.Models.MetaData.GlobalMetadataViewModel"}},"application/json":{"schema":{"$ref":"#/components/schemas/Marlin.SportsbetApi.Host.Models.MetaData.GlobalMetadataViewModel"}},"text/json":{"schema":{"$ref":"#/components/schemas/Marlin.SportsbetApi.Host.Models.MetaData.GlobalMetadataViewModel"}}}},"401":{"description":"Unauthorized"},"403":{"description":"Forbidden"},"404":{"description":"Not Found","content":{"text/plain":{"schema":{"$ref":"#/components/schemas/Microsoft.AspNetCore.Mvc.ProblemDetails"}},"application/json":{"schema":{"$ref":"#/components/schemas/Microsoft.AspNetCore.Mvc.ProblemDetails"}},"text/json":{"schema":{"$ref":"#/components/schemas/Microsoft.AspNetCore.Mvc.ProblemDetails"}}}},"429":{"description":"Too many requests"}}}}}}
```

*


# Player API

Provides information about player risk settings

Player API can be used to get player risk settings currently applied to a player.

Gets risk settings of the specific player: live time delay (LTD) and customer confidence\
factor (CCF), both general and per sport.
-----------------------------------------

> \
> \*\*Rate Limits (per account):\*\*\
> \- \*\*10 req/1s\*\*

```json
{"openapi":"3.0.4","info":{"title":"[T728-STAGE] Odds88 API","version":"v1"},"tags":[{"name":"Players"}],"security":[{"Bearer":[]}],"components":{"securitySchemes":{"Bearer":{"type":"http","description":"JWT Authorization header using the Bearer scheme. Example: \"Authorization: Bearer {token}\"","scheme":"Bearer","bearerFormat":"JWT"}},"schemas":{"Marlin.SportsbetApi.Host.Models.Players.PlayerSettingsViewModel":{"type":"object","properties":{"liveDelay":{"type":"integer","description":"General live time delay (LTD) of the player, in seconds.\nNull when no player-level delay is set, in which case the delay is taken from the event, market or segment.","format":"int32","nullable":true},"limitsFactor":{"type":"number","description":"General customer confidence factor (CCF) of the player, applied as a multiplier to the player's limits.","format":"double"},"previousLimitsFactor":{"type":"number","description":"Previous value of the general customer confidence factor (CCF). Null when it was never changed.","format":"double","nullable":true},"sportSettings":{"type":"array","items":{"$ref":"#/components/schemas/Marlin.SportsbetApi.Host.Models.Players.PlayerSportSettingsViewModel"},"description":"Per-sport overrides of the player's live time delay (LTD) and customer confidence factor (CCF).\nSports without an override are not listed and fall back to the general values.","nullable":true}},"additionalProperties":false,"description":"Risk settings applied to a player: live time delay (LTD) and customer confidence factor (CCF),\nboth at the general level and per sport."},"Marlin.SportsbetApi.Host.Models.Players.PlayerSportSettingsViewModel":{"type":"object","properties":{"sportId":{"type":"integer","description":"Id of the sport these settings apply to.","format":"int64"},"liveLimitsFactor":{"type":"number","description":"Customer confidence factor (CCF) applied to live bets of this sport. Null when not overridden.","format":"double","nullable":true},"prematchLimitsFactor":{"type":"number","description":"Customer confidence factor (CCF) applied to prematch bets of this sport. Null when not overridden.","format":"double","nullable":true},"liveDelay":{"type":"integer","description":"Live time delay (LTD) applied to this sport, in seconds. Null when not overridden.","format":"int32","nullable":true}},"additionalProperties":false,"description":"Risk settings applied to a player for a single sport."},"Microsoft.AspNetCore.Mvc.ProblemDetails":{"type":"object","properties":{"type":{"type":"string","nullable":true},"title":{"type":"string","nullable":true},"status":{"type":"integer","format":"int32","nullable":true},"detail":{"type":"string","nullable":true},"instance":{"type":"string","nullable":true}},"additionalProperties":{}}}},"paths":{"/api/players/{playerId}/settings":{"get":{"tags":["Players"],"summary":"Gets risk settings of the specific player: live time delay (LTD) and customer confidence\nfactor (CCF), both general and per sport.","description":"\n**Rate Limits (per account):**\n- **10 req/1s**","operationId":"Get player settings","parameters":[{"name":"playerId","in":"path","description":"Id of the player.","required":true,"schema":{"type":"string"}},{"name":"partnerId","in":"query","description":"Partner the player belongs to. A tenant can serve several partners and the same player id\nmay exist under more than one of them, so pass this to select the right player.\nWhen omitted, the player is resolved under partner 0.","schema":{"type":"integer","format":"int64"}}],"responses":{"200":{"description":"Returns risk settings of the requested player.","content":{"text/plain":{"schema":{"$ref":"#/components/schemas/Marlin.SportsbetApi.Host.Models.Players.PlayerSettingsViewModel"}},"application/json":{"schema":{"$ref":"#/components/schemas/Marlin.SportsbetApi.Host.Models.Players.PlayerSettingsViewModel"}},"text/json":{"schema":{"$ref":"#/components/schemas/Marlin.SportsbetApi.Host.Models.Players.PlayerSettingsViewModel"}}}},"400":{"description":"Request arguments are not valid.","content":{"text/plain":{"schema":{"$ref":"#/components/schemas/Microsoft.AspNetCore.Mvc.ProblemDetails"}},"application/json":{"schema":{"$ref":"#/components/schemas/Microsoft.AspNetCore.Mvc.ProblemDetails"}},"text/json":{"schema":{"$ref":"#/components/schemas/Microsoft.AspNetCore.Mvc.ProblemDetails"}}}},"401":{"description":"Unauthorized"},"403":{"description":"The requested partner is not allowed for this deployment.","content":{"text/plain":{"schema":{"$ref":"#/components/schemas/Microsoft.AspNetCore.Mvc.ProblemDetails"}},"application/json":{"schema":{"$ref":"#/components/schemas/Microsoft.AspNetCore.Mvc.ProblemDetails"}},"text/json":{"schema":{"$ref":"#/components/schemas/Microsoft.AspNetCore.Mvc.ProblemDetails"}}}},"429":{"description":"Too many requests"},"500":{"description":"Unexpected error occurred."}}}}}}
```


# Ratings API

Provides ratings information for events and leagues

Ratings API can be used to get rating of a particular league or event.

## Event Ratings Endpoint

Can be used to get ratings of a list of events.

{% hint style="warning" %}
The endpoint is rate-limited.
{% endhint %}

## Retrieves ratings for the specified events.

> \
> \*\*Rate Limits (per account):\*\*\
> \- \*\*10 req/1s\*\*

```json
{"openapi":"3.0.4","info":{"title":"[T728-STAGE] Odds88 API","version":"v1"},"tags":[{"name":"Ratings"}],"security":[{"Bearer":[]}],"components":{"securitySchemes":{"Bearer":{"type":"http","description":"JWT Authorization header using the Bearer scheme. Example: \"Authorization: Bearer {token}\"","scheme":"Bearer","bearerFormat":"JWT"}},"schemas":{"Marlin.SportsbetApi.Host.Models.Ratings.RatingsModel":{"type":"object","properties":{"id":{"type":"integer","format":"int64"},"prematchRatingName":{"type":"string","nullable":true},"liveRatingName":{"type":"string","nullable":true},"liveDelay":{"type":"integer","format":"int32","nullable":true}},"additionalProperties":false},"Microsoft.AspNetCore.Mvc.ProblemDetails":{"type":"object","properties":{"type":{"type":"string","nullable":true},"title":{"type":"string","nullable":true},"status":{"type":"integer","format":"int32","nullable":true},"detail":{"type":"string","nullable":true},"instance":{"type":"string","nullable":true}},"additionalProperties":{}}}},"paths":{"/api/Ratings/EventRatings":{"get":{"tags":["Ratings"],"summary":"Retrieves ratings for the specified events.","description":"\n**Rate Limits (per account):**\n- **10 req/1s**","operationId":"Get ratings by event IDs","parameters":[{"name":"eventID","in":"query","description":"EventIds, for which ratings are required.","schema":{"type":"array","items":{"type":"integer","format":"int64"}}}],"responses":{"200":{"description":"Returns Rating information about the requested EventIds.","content":{"text/plain":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/Marlin.SportsbetApi.Host.Models.Ratings.RatingsModel"}}},"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/Marlin.SportsbetApi.Host.Models.Ratings.RatingsModel"}}},"text/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/Marlin.SportsbetApi.Host.Models.Ratings.RatingsModel"}}}}},"400":{"description":"Request arguments are not valid.","content":{"text/plain":{"schema":{"$ref":"#/components/schemas/Microsoft.AspNetCore.Mvc.ProblemDetails"}},"application/json":{"schema":{"$ref":"#/components/schemas/Microsoft.AspNetCore.Mvc.ProblemDetails"}},"text/json":{"schema":{"$ref":"#/components/schemas/Microsoft.AspNetCore.Mvc.ProblemDetails"}}}},"401":{"description":"Unauthorized"},"403":{"description":"Forbidden"},"429":{"description":"Too many requests"},"500":{"description":"Unexpected error occurred."}}}}}}
```

## League Ratings Endpoint

Can be used to get ratings of a list of leagues.

{% hint style="warning" %}
The endpoint is rate-limited to **10 requests per second**.
{% endhint %}

## Retrieves ratings for the specified leagues.

> \
> \*\*Rate Limits (per account):\*\*\
> \- \*\*10 req/1s\*\*

```json
{"openapi":"3.0.4","info":{"title":"[T728-STAGE] Odds88 API","version":"v1"},"tags":[{"name":"Ratings"}],"security":[{"Bearer":[]}],"components":{"securitySchemes":{"Bearer":{"type":"http","description":"JWT Authorization header using the Bearer scheme. Example: \"Authorization: Bearer {token}\"","scheme":"Bearer","bearerFormat":"JWT"}},"schemas":{"Marlin.SportsbetApi.Host.Models.Ratings.RatingsModel":{"type":"object","properties":{"id":{"type":"integer","format":"int64"},"prematchRatingName":{"type":"string","nullable":true},"liveRatingName":{"type":"string","nullable":true},"liveDelay":{"type":"integer","format":"int32","nullable":true}},"additionalProperties":false},"Microsoft.AspNetCore.Mvc.ProblemDetails":{"type":"object","properties":{"type":{"type":"string","nullable":true},"title":{"type":"string","nullable":true},"status":{"type":"integer","format":"int32","nullable":true},"detail":{"type":"string","nullable":true},"instance":{"type":"string","nullable":true}},"additionalProperties":{}}}},"paths":{"/api/Ratings/LeagueRatings":{"get":{"tags":["Ratings"],"summary":"Retrieves ratings for the specified leagues.","description":"\n**Rate Limits (per account):**\n- **10 req/1s**","operationId":"Get ratings by league Ids","parameters":[{"name":"leagueId","in":"query","description":"LeagueIds, for which ratings are required.","schema":{"type":"array","items":{"type":"integer","format":"int64"}}}],"responses":{"200":{"description":"Returns Rating information about the requested LeagueIds.","content":{"text/plain":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/Marlin.SportsbetApi.Host.Models.Ratings.RatingsModel"}}},"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/Marlin.SportsbetApi.Host.Models.Ratings.RatingsModel"}}},"text/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/Marlin.SportsbetApi.Host.Models.Ratings.RatingsModel"}}}}},"400":{"description":"Request arguments are not valid.","content":{"text/plain":{"schema":{"$ref":"#/components/schemas/Microsoft.AspNetCore.Mvc.ProblemDetails"}},"application/json":{"schema":{"$ref":"#/components/schemas/Microsoft.AspNetCore.Mvc.ProblemDetails"}},"text/json":{"schema":{"$ref":"#/components/schemas/Microsoft.AspNetCore.Mvc.ProblemDetails"}}}},"401":{"description":"Unauthorized"},"403":{"description":"Forbidden"},"429":{"description":"Too many requests"},"500":{"description":"Unexpected error occurred."}}}}}}
```


# Schema API

Provides information about internal Odds88 entities

Schema API endpoints allow to get internal entities which exist in Odds88.

{% hint style="warning" %}
All endpoints in the API are rate-limited.
{% endhint %}

## Gets all existing leagues for a specific sport.

> \
> \*\*Rate Limits (per account):\*\*\
> \- \*\*20 req/1s\*\*

```json
{"openapi":"3.0.4","info":{"title":"[T728-STAGE] Odds88 API","version":"v1"},"tags":[{"name":"Schema"}],"security":[{"Bearer":[]}],"components":{"securitySchemes":{"Bearer":{"type":"http","description":"JWT Authorization header using the Bearer scheme. Example: \"Authorization: Bearer {token}\"","scheme":"Bearer","bearerFormat":"JWT"}},"schemas":{"Marlin.SportsbetApi.Host.Models.Schema.LeagueViewModel":{"type":"object","properties":{"id":{"type":"integer","format":"int64"},"name":{"type":"string","nullable":true},"sportId":{"type":"integer","format":"int64"},"locationId":{"type":"integer","format":"int64"}},"additionalProperties":false}}},"paths":{"/api/schema/leagues/{sportId}":{"get":{"tags":["Schema"],"summary":"Gets all existing leagues for a specific sport.","description":"\n**Rate Limits (per account):**\n- **20 req/1s**","operationId":"Get leagues","parameters":[{"name":"sportId","in":"path","description":"TradeArt sport id.","required":true,"schema":{"type":"integer","format":"int64"}}],"responses":{"200":{"description":"OK","content":{"text/plain":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/Marlin.SportsbetApi.Host.Models.Schema.LeagueViewModel"}}},"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/Marlin.SportsbetApi.Host.Models.Schema.LeagueViewModel"}}},"text/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/Marlin.SportsbetApi.Host.Models.Schema.LeagueViewModel"}}}}},"401":{"description":"Unauthorized"},"403":{"description":"Forbidden"},"429":{"description":"Too many requests"},"500":{"description":"Internal Server Error"}}}}}}
```

{% hint style="warning" %}
This endpoint is rate-limited to **20 requests per second.**
{% endhint %}

## Gets all existing locations for a specific sport.

> \
> \*\*Rate Limits (per account):\*\*\
> \- \*\*20 req/1s\*\*

```json
{"openapi":"3.0.4","info":{"title":"[T728-STAGE] Odds88 API","version":"v1"},"tags":[{"name":"Schema"}],"security":[{"Bearer":[]}],"components":{"securitySchemes":{"Bearer":{"type":"http","description":"JWT Authorization header using the Bearer scheme. Example: \"Authorization: Bearer {token}\"","scheme":"Bearer","bearerFormat":"JWT"}},"schemas":{"Marlin.SportsbetApi.Host.Models.Schema.LocationViewModel":{"type":"object","properties":{"id":{"type":"integer","format":"int64"},"name":{"type":"string","nullable":true}},"additionalProperties":false}}},"paths":{"/api/schema/locations":{"get":{"tags":["Schema"],"summary":"Gets all existing locations for a specific sport.","description":"\n**Rate Limits (per account):**\n- **20 req/1s**","operationId":"Get locations","parameters":[{"name":"sportId","in":"query","description":"TradeArt sport id. Will return all locations if not specified.","schema":{"type":"integer","format":"int64"}}],"responses":{"200":{"description":"OK","content":{"text/plain":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/Marlin.SportsbetApi.Host.Models.Schema.LocationViewModel"}}},"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/Marlin.SportsbetApi.Host.Models.Schema.LocationViewModel"}}},"text/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/Marlin.SportsbetApi.Host.Models.Schema.LocationViewModel"}}}}},"401":{"description":"Unauthorized"},"403":{"description":"Forbidden"},"429":{"description":"Too many requests"},"500":{"description":"Internal Server Error"}}}}}}
```

{% hint style="warning" %}
This endpoint is rate-limited to **20 requests per second.**
{% endhint %}

## Gets all existing market types for a specific sport.

> \
> \*\*Rate Limits (per account):\*\*\
> \- \*\*20 req/1s\*\*

```json
{"openapi":"3.0.4","info":{"title":"[T728-STAGE] Odds88 API","version":"v1"},"tags":[{"name":"Schema"}],"security":[{"Bearer":[]}],"components":{"securitySchemes":{"Bearer":{"type":"http","description":"JWT Authorization header using the Bearer scheme. Example: \"Authorization: Bearer {token}\"","scheme":"Bearer","bearerFormat":"JWT"}},"schemas":{"Marlin.SportsbetApi.Host.Models.Schema.MarketTypeViewModel":{"type":"object","properties":{"id":{"type":"integer","format":"int64"},"name":{"type":"string","nullable":true},"groups":{"type":"array","items":{"$ref":"#/components/schemas/Marlin.SportsbetApi.Host.Models.Schema.MarketGroupViewModel"},"nullable":true},"isMultilineMarket":{"type":"boolean"},"isFreeText":{"type":"boolean"}},"additionalProperties":false,"description":"Represents Market Type."},"Marlin.SportsbetApi.Host.Models.Schema.MarketGroupViewModel":{"type":"object","properties":{"id":{"type":"integer","format":"int64"},"name":{"type":"string","nullable":true},"order":{"type":"integer","format":"int32"},"sportId":{"type":"integer","format":"int64"}},"additionalProperties":false,"description":"Represents Market Group."}}},"paths":{"/api/schema/market-types":{"get":{"tags":["Schema"],"summary":"Gets all existing market types for a specific sport.","description":"\n**Rate Limits (per account):**\n- **20 req/1s**","operationId":"Get market types","parameters":[{"name":"sportId","in":"query","description":"TradeArt sport id. Will return all market types if not specified.","schema":{"type":"integer","format":"int64"}},{"name":"includeFreeText","in":"query","description":"A flag indicating whether the response should include free text types or not.","schema":{"type":"boolean","default":true}}],"responses":{"200":{"description":"OK","content":{"text/plain":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/Marlin.SportsbetApi.Host.Models.Schema.MarketTypeViewModel"}}},"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/Marlin.SportsbetApi.Host.Models.Schema.MarketTypeViewModel"}}},"text/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/Marlin.SportsbetApi.Host.Models.Schema.MarketTypeViewModel"}}}}},"401":{"description":"Unauthorized"},"403":{"description":"Forbidden"},"429":{"description":"Too many requests"},"500":{"description":"Internal Server Error"}}}}}}
```

{% hint style="warning" %}
This endpoint is rate-limited to **20 requests per second.**
{% endhint %}

## Gets all existing periods for a specific sport.

> \
> \*\*Rate Limits (per account):\*\*\
> \- \*\*20 req/1s\*\*

```json
{"openapi":"3.0.4","info":{"title":"[T728-STAGE] Odds88 API","version":"v1"},"tags":[{"name":"Schema"}],"security":[{"Bearer":[]}],"components":{"securitySchemes":{"Bearer":{"type":"http","description":"JWT Authorization header using the Bearer scheme. Example: \"Authorization: Bearer {token}\"","scheme":"Bearer","bearerFormat":"JWT"}},"schemas":{"Marlin.SportsbetApi.Host.Models.Schema.SportPeriodViewModel":{"type":"object","properties":{"id":{"type":"integer","format":"int64"},"name":{"type":"string","nullable":true},"sportId":{"type":"integer","format":"int64"}},"additionalProperties":false}}},"paths":{"/api/schema/periods":{"get":{"tags":["Schema"],"summary":"Gets all existing periods for a specific sport.","description":"\n**Rate Limits (per account):**\n- **20 req/1s**","operationId":"Get sport periods","parameters":[{"name":"sportId","in":"query","description":"TradeArt sport id. Will return all periods if not specified.","schema":{"type":"integer","format":"int64"}}],"responses":{"200":{"description":"OK","content":{"text/plain":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/Marlin.SportsbetApi.Host.Models.Schema.SportPeriodViewModel"}}},"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/Marlin.SportsbetApi.Host.Models.Schema.SportPeriodViewModel"}}},"text/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/Marlin.SportsbetApi.Host.Models.Schema.SportPeriodViewModel"}}}}},"401":{"description":"Unauthorized"},"403":{"description":"Forbidden"},"429":{"description":"Too many requests"},"500":{"description":"Internal Server Error"}}}}}}
```

{% hint style="warning" %}
This endpoint is rate-limited to **20 requests per second.**
{% endhint %}

## Gets all existing sports.

> \
> \*\*Rate Limits (per account):\*\*\
> \- \*\*1 req/1m\*\*

```json
{"openapi":"3.0.4","info":{"title":"[T728-STAGE] Odds88 API","version":"v1"},"tags":[{"name":"Schema"}],"security":[{"Bearer":[]}],"components":{"securitySchemes":{"Bearer":{"type":"http","description":"JWT Authorization header using the Bearer scheme. Example: \"Authorization: Bearer {token}\"","scheme":"Bearer","bearerFormat":"JWT"}},"schemas":{"Marlin.SportsbetApi.Host.Models.Schema.SportViewModel":{"type":"object","properties":{"id":{"type":"integer","format":"int64"},"name":{"type":"string","nullable":true}},"additionalProperties":false}}},"paths":{"/api/schema/sports":{"get":{"tags":["Schema"],"summary":"Gets all existing sports.","description":"\n**Rate Limits (per account):**\n- **1 req/1m**","operationId":"Get sports","responses":{"200":{"description":"OK","content":{"text/plain":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/Marlin.SportsbetApi.Host.Models.Schema.SportViewModel"}}},"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/Marlin.SportsbetApi.Host.Models.Schema.SportViewModel"}}},"text/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/Marlin.SportsbetApi.Host.Models.Schema.SportViewModel"}}}}},"401":{"description":"Unauthorized"},"403":{"description":"Forbidden"},"429":{"description":"Too many requests"},"500":{"description":"Internal Server Error"}}}}}}
```

{% hint style="warning" %}
This endpoint is rate-limited to **1 request per minute.**
{% endhint %}


# Translations API

Provides translations for different entities

Translations API endpoints can be used to fetch translations to different languages for the Odds88 entities.

Currently Odds88 support the following languages:

* English
* German
* Spanish
* Japanese
* Portuguese
* Russian
* Thai
* Turkish
* Vietnamese
* Chinese
* Korean
* French
* Afar
* Indonesian

{% hint style="warning" %}
These endpoints are rate-limited.
{% endhint %}

## Gets translations to specific language for specified sports.

> \
> \*\*Rate Limits (per account):\*\*\
> \- \*\*40 req/1s\*\*

```json
{"openapi":"3.0.4","info":{"title":"[T728-STAGE] Odds88 API","version":"v1"},"tags":[{"name":"Translations"}],"security":[{"Bearer":[]}],"components":{"securitySchemes":{"Bearer":{"type":"http","description":"JWT Authorization header using the Bearer scheme. Example: \"Authorization: Bearer {token}\"","scheme":"Bearer","bearerFormat":"JWT"}},"schemas":{"Marlin.SportsbetApi.Host.Models.Translations.TranslationViewModel":{"type":"object","properties":{"id":{"type":"integer","format":"int64"},"language":{"type":"string","nullable":true},"translation":{"type":"string","nullable":true}},"additionalProperties":false}}},"paths":{"/api/translations/{lang}/sports":{"get":{"tags":["Translations"],"summary":"Gets translations to specific language for specified sports.","description":"\n**Rate Limits (per account):**\n- **40 req/1s**","operationId":"Get sport translations","parameters":[{"name":"lang","in":"path","description":"Language code of translation.","required":true,"schema":{"type":"string"}},{"name":"sports","in":"query","description":"Sports which will be translated.","schema":{"type":"array","items":{"type":"integer","format":"int64"}}}],"responses":{"200":{"description":"OK","content":{"text/plain":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/Marlin.SportsbetApi.Host.Models.Translations.TranslationViewModel"}}},"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/Marlin.SportsbetApi.Host.Models.Translations.TranslationViewModel"}}},"text/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/Marlin.SportsbetApi.Host.Models.Translations.TranslationViewModel"}}}}},"401":{"description":"Unauthorized"},"403":{"description":"Forbidden"},"429":{"description":"Too many requests"}}}}}}
```

{% hint style="warning" %}
This endpoint is rate-limited to **40 requests per second.**
{% endhint %}

## Gets translations to specific language for specified regions.

> \
> \*\*Rate Limits (per account):\*\*\
> \- \*\*40 req/1s\*\*

```json
{"openapi":"3.0.4","info":{"title":"[T728-STAGE] Odds88 API","version":"v1"},"tags":[{"name":"Translations"}],"security":[{"Bearer":[]}],"components":{"securitySchemes":{"Bearer":{"type":"http","description":"JWT Authorization header using the Bearer scheme. Example: \"Authorization: Bearer {token}\"","scheme":"Bearer","bearerFormat":"JWT"}},"schemas":{"Marlin.SportsbetApi.Host.Models.Translations.TranslationViewModel":{"type":"object","properties":{"id":{"type":"integer","format":"int64"},"language":{"type":"string","nullable":true},"translation":{"type":"string","nullable":true}},"additionalProperties":false}}},"paths":{"/api/translations/{lang}/regions":{"get":{"tags":["Translations"],"summary":"Gets translations to specific language for specified regions.","description":"\n**Rate Limits (per account):**\n- **40 req/1s**","operationId":"Get regions translations","parameters":[{"name":"lang","in":"path","description":"Language code for translation.","required":true,"schema":{"type":"string"}},{"name":"regions","in":"query","description":"Regions which will be translated.","schema":{"type":"array","items":{"type":"integer","format":"int64"}}}],"responses":{"200":{"description":"OK","content":{"text/plain":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/Marlin.SportsbetApi.Host.Models.Translations.TranslationViewModel"}}},"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/Marlin.SportsbetApi.Host.Models.Translations.TranslationViewModel"}}},"text/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/Marlin.SportsbetApi.Host.Models.Translations.TranslationViewModel"}}}}},"401":{"description":"Unauthorized"},"403":{"description":"Forbidden"},"429":{"description":"Too many requests"}}}}}}
```

{% hint style="warning" %}
This endpoint is rate-limited to **40 requests per second.**
{% endhint %}

## Gets translations to specific language for specific leagues.

> \
> \*\*Rate Limits (per account):\*\*\
> \- \*\*40 req/1s\*\*

```json
{"openapi":"3.0.4","info":{"title":"[T728-STAGE] Odds88 API","version":"v1"},"tags":[{"name":"Translations"}],"security":[{"Bearer":[]}],"components":{"securitySchemes":{"Bearer":{"type":"http","description":"JWT Authorization header using the Bearer scheme. Example: \"Authorization: Bearer {token}\"","scheme":"Bearer","bearerFormat":"JWT"}},"schemas":{"Marlin.SportsbetApi.Host.Models.Translations.TranslationViewModel":{"type":"object","properties":{"id":{"type":"integer","format":"int64"},"language":{"type":"string","nullable":true},"translation":{"type":"string","nullable":true}},"additionalProperties":false}}},"paths":{"/api/translations/{lang}/leagues":{"get":{"tags":["Translations"],"summary":"Gets translations to specific language for specific leagues.","description":"\n**Rate Limits (per account):**\n- **40 req/1s**","operationId":"Get leagues translations","parameters":[{"name":"lang","in":"path","description":"Language code for translation.","required":true,"schema":{"type":"string"}},{"name":"leagues","in":"query","description":"Leagues which will be translated.","schema":{"type":"array","items":{"type":"integer","format":"int64"}}}],"responses":{"200":{"description":"OK","content":{"text/plain":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/Marlin.SportsbetApi.Host.Models.Translations.TranslationViewModel"}}},"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/Marlin.SportsbetApi.Host.Models.Translations.TranslationViewModel"}}},"text/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/Marlin.SportsbetApi.Host.Models.Translations.TranslationViewModel"}}}}},"401":{"description":"Unauthorized"},"403":{"description":"Forbidden"},"429":{"description":"Too many requests"}}}}}}
```

{% hint style="warning" %}
This endpoint is rate-limited to **40 requests per second.**
{% endhint %}

## Gets translation to specific language for specific markets.

> \
> \*\*Rate Limits (per account):\*\*\
> \- \*\*40 req/1s\*\*

```json
{"openapi":"3.0.4","info":{"title":"[T728-STAGE] Odds88 API","version":"v1"},"tags":[{"name":"Translations"}],"security":[{"Bearer":[]}],"components":{"securitySchemes":{"Bearer":{"type":"http","description":"JWT Authorization header using the Bearer scheme. Example: \"Authorization: Bearer {token}\"","scheme":"Bearer","bearerFormat":"JWT"}},"schemas":{"Marlin.SportsbetApi.Host.Models.Translations.MarketTranslationViewModel":{"type":"object","properties":{"marketTypeId":{"type":"integer","format":"int64"},"market":{"allOf":[{"$ref":"#/components/schemas/Marlin.SportsbetApi.Host.Models.Translations.TranslationViewModel"}],"nullable":true},"selections":{"type":"array","items":{"$ref":"#/components/schemas/Marlin.SportsbetApi.Host.Models.Translations.TranslationViewModel"},"nullable":true}},"additionalProperties":false},"Marlin.SportsbetApi.Host.Models.Translations.TranslationViewModel":{"type":"object","properties":{"id":{"type":"integer","format":"int64"},"language":{"type":"string","nullable":true},"translation":{"type":"string","nullable":true}},"additionalProperties":false},"Microsoft.AspNetCore.Mvc.ProblemDetails":{"type":"object","properties":{"type":{"type":"string","nullable":true},"title":{"type":"string","nullable":true},"status":{"type":"integer","format":"int32","nullable":true},"detail":{"type":"string","nullable":true},"instance":{"type":"string","nullable":true}},"additionalProperties":{}}}},"paths":{"/api/translations/{lang}/{eventId}/markets":{"get":{"tags":["Translations"],"summary":"Gets translation to specific language for specific markets.","description":"\n**Rate Limits (per account):**\n- **40 req/1s**","operationId":"Get markets translations","parameters":[{"name":"lang","in":"path","description":"Language code for translation.","required":true,"schema":{"type":"string"}},{"name":"eventId","in":"path","description":"TradeArt event id.","required":true,"schema":{"type":"integer","format":"int64"}},{"name":"markets","in":"query","description":"Markets which will be translated.","schema":{"type":"array","items":{"type":"integer","format":"int64"}}}],"responses":{"200":{"description":"OK","content":{"text/plain":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/Marlin.SportsbetApi.Host.Models.Translations.MarketTranslationViewModel"}}},"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/Marlin.SportsbetApi.Host.Models.Translations.MarketTranslationViewModel"}}},"text/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/Marlin.SportsbetApi.Host.Models.Translations.MarketTranslationViewModel"}}}}},"401":{"description":"Unauthorized"},"403":{"description":"Forbidden"},"404":{"description":"Not Found","content":{"text/plain":{"schema":{"$ref":"#/components/schemas/Microsoft.AspNetCore.Mvc.ProblemDetails"}},"application/json":{"schema":{"$ref":"#/components/schemas/Microsoft.AspNetCore.Mvc.ProblemDetails"}},"text/json":{"schema":{"$ref":"#/components/schemas/Microsoft.AspNetCore.Mvc.ProblemDetails"}}}},"429":{"description":"Too many requests"},"500":{"description":"Internal Server Error"}}}}}}
```

{% hint style="warning" %}
This endpoint is rate-limited to **40 requests per second.**
{% endhint %}

## Gets translations to specific language for specific competitors.

> \
> \*\*Rate Limits (per account):\*\*\
> \- \*\*40 req/1s\*\*

```json
{"openapi":"3.0.4","info":{"title":"[T728-STAGE] Odds88 API","version":"v1"},"tags":[{"name":"Translations"}],"security":[{"Bearer":[]}],"components":{"securitySchemes":{"Bearer":{"type":"http","description":"JWT Authorization header using the Bearer scheme. Example: \"Authorization: Bearer {token}\"","scheme":"Bearer","bearerFormat":"JWT"}},"schemas":{"Marlin.SportsbetApi.Host.Models.Translations.TranslationViewModel":{"type":"object","properties":{"id":{"type":"integer","format":"int64"},"language":{"type":"string","nullable":true},"translation":{"type":"string","nullable":true}},"additionalProperties":false}}},"paths":{"/api/translations/{lang}/competitors":{"get":{"tags":["Translations"],"summary":"Gets translations to specific language for specific competitors.","description":"\n**Rate Limits (per account):**\n- **40 req/1s**","operationId":"Get competitors translations","parameters":[{"name":"lang","in":"path","description":"Language code for translation.","required":true,"schema":{"type":"string"}},{"name":"competitors","in":"query","description":"Competitors which will be translated.","schema":{"type":"array","items":{"type":"integer","format":"int64"}}}],"responses":{"200":{"description":"OK","content":{"text/plain":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/Marlin.SportsbetApi.Host.Models.Translations.TranslationViewModel"}}},"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/Marlin.SportsbetApi.Host.Models.Translations.TranslationViewModel"}}},"text/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/Marlin.SportsbetApi.Host.Models.Translations.TranslationViewModel"}}}}},"401":{"description":"Unauthorized"},"403":{"description":"Forbidden"},"429":{"description":"Too many requests"}}}}}}
```

{% hint style="warning" %}
This endpoint is rate-limited to **40 requests per second.**
{% endhint %}

## Gets all existing translations for a specific sport.

> \
> \*\*Rate Limits (per account):\*\*\
> \- \*\*20 req/1s\*\*

```json
{"openapi":"3.0.4","info":{"title":"[T728-STAGE] Odds88 API","version":"v1"},"tags":[{"name":"Translations"}],"security":[{"Bearer":[]}],"components":{"securitySchemes":{"Bearer":{"type":"http","description":"JWT Authorization header using the Bearer scheme. Example: \"Authorization: Bearer {token}\"","scheme":"Bearer","bearerFormat":"JWT"}},"schemas":{"Marlin.SportsbetApi.Host.Models.Translations.EntityTranslationsViewModel":{"type":"object","properties":{"id":{"type":"integer","description":"ID of the entity.","format":"int64"},"translations":{"type":"object","additionalProperties":{"type":"string","nullable":true},"description":"Translations for the entity, where the key is the language code and the value is the translated text.","nullable":true}},"additionalProperties":false,"description":"Contains entity translation information."}}},"paths":{"/api/translations/all/sport/{sportId}":{"get":{"tags":["Translations"],"summary":"Gets all existing translations for a specific sport.","description":"\n**Rate Limits (per account):**\n- **20 req/1s**","operationId":"Get all sport translations","parameters":[{"name":"sportId","in":"path","description":"TradeArt sport id.","required":true,"schema":{"type":"integer","format":"int64"}}],"responses":{"200":{"description":"OK","content":{"text/plain":{"schema":{"$ref":"#/components/schemas/Marlin.SportsbetApi.Host.Models.Translations.EntityTranslationsViewModel"}},"application/json":{"schema":{"$ref":"#/components/schemas/Marlin.SportsbetApi.Host.Models.Translations.EntityTranslationsViewModel"}},"text/json":{"schema":{"$ref":"#/components/schemas/Marlin.SportsbetApi.Host.Models.Translations.EntityTranslationsViewModel"}}}},"401":{"description":"Unauthorized"},"403":{"description":"Forbidden"},"429":{"description":"Too many requests"}}}}}}
```

{% hint style="warning" %}
This endpoint is rate-limited to **20 requests per second.**
{% endhint %}

## Gets all existing translations for a specific event.

> \
> \*\*Rate Limits (per account):\*\*\
> \- \*\*40 req/1s\*\*

```json
{"openapi":"3.0.4","info":{"title":"[T728-STAGE] Odds88 API","version":"v1"},"tags":[{"name":"Translations"}],"security":[{"Bearer":[]}],"components":{"securitySchemes":{"Bearer":{"type":"http","description":"JWT Authorization header using the Bearer scheme. Example: \"Authorization: Bearer {token}\"","scheme":"Bearer","bearerFormat":"JWT"}},"schemas":{"Marlin.SportsbetApi.Host.Models.Translations.EventTranslationsViewModel":{"type":"object","properties":{"eventTranslation":{"allOf":[{"$ref":"#/components/schemas/Marlin.SportsbetApi.Host.Models.Translations.EntityTranslationsViewModel"}],"description":"Contains entity translation information.","nullable":true},"sport":{"allOf":[{"$ref":"#/components/schemas/Marlin.SportsbetApi.Host.Models.Translations.EntityTranslationsViewModel"}],"description":"Contains entity translation information.","nullable":true},"region":{"allOf":[{"$ref":"#/components/schemas/Marlin.SportsbetApi.Host.Models.Translations.EntityTranslationsViewModel"}],"description":"Contains entity translation information.","nullable":true},"league":{"allOf":[{"$ref":"#/components/schemas/Marlin.SportsbetApi.Host.Models.Translations.EntityTranslationsViewModel"}],"description":"Contains entity translation information.","nullable":true},"competitors":{"type":"array","items":{"$ref":"#/components/schemas/Marlin.SportsbetApi.Host.Models.Translations.EntityTranslationsViewModel"},"nullable":true}},"additionalProperties":false},"Marlin.SportsbetApi.Host.Models.Translations.EntityTranslationsViewModel":{"type":"object","properties":{"id":{"type":"integer","description":"ID of the entity.","format":"int64"},"translations":{"type":"object","additionalProperties":{"type":"string","nullable":true},"description":"Translations for the entity, where the key is the language code and the value is the translated text.","nullable":true}},"additionalProperties":false,"description":"Contains entity translation information."},"Microsoft.AspNetCore.Mvc.ProblemDetails":{"type":"object","properties":{"type":{"type":"string","nullable":true},"title":{"type":"string","nullable":true},"status":{"type":"integer","format":"int32","nullable":true},"detail":{"type":"string","nullable":true},"instance":{"type":"string","nullable":true}},"additionalProperties":{}}}},"paths":{"/api/translations/all/event/{eventId}":{"get":{"tags":["Translations"],"summary":"Gets all existing translations for a specific event.","description":"\n**Rate Limits (per account):**\n- **40 req/1s**","operationId":"Get all event translations","parameters":[{"name":"eventId","in":"path","description":"TradeArt event id.","required":true,"schema":{"type":"integer","format":"int64"}}],"responses":{"200":{"description":"OK","content":{"text/plain":{"schema":{"$ref":"#/components/schemas/Marlin.SportsbetApi.Host.Models.Translations.EventTranslationsViewModel"}},"application/json":{"schema":{"$ref":"#/components/schemas/Marlin.SportsbetApi.Host.Models.Translations.EventTranslationsViewModel"}},"text/json":{"schema":{"$ref":"#/components/schemas/Marlin.SportsbetApi.Host.Models.Translations.EventTranslationsViewModel"}}}},"401":{"description":"Unauthorized"},"403":{"description":"Forbidden"},"404":{"description":"Not Found","content":{"text/plain":{"schema":{"$ref":"#/components/schemas/Microsoft.AspNetCore.Mvc.ProblemDetails"}},"application/json":{"schema":{"$ref":"#/components/schemas/Microsoft.AspNetCore.Mvc.ProblemDetails"}},"text/json":{"schema":{"$ref":"#/components/schemas/Microsoft.AspNetCore.Mvc.ProblemDetails"}}}},"429":{"description":"Too many requests"}}}}}}
```

{% hint style="warning" %}
This endpoint is rate-limited to **40 requests per second.**
{% endhint %}

## Gets all existing translations for specific markets.

> \
> \*\*Rate Limits (per account):\*\*\
> \- \*\*40 req/1s (with query parameters)\*\*\
> \- \*\*1 req/10s\*\*

```json
{"openapi":"3.0.4","info":{"title":"[T728-STAGE] Odds88 API","version":"v1"},"tags":[{"name":"Translations"}],"security":[{"Bearer":[]}],"components":{"securitySchemes":{"Bearer":{"type":"http","description":"JWT Authorization header using the Bearer scheme. Example: \"Authorization: Bearer {token}\"","scheme":"Bearer","bearerFormat":"JWT"}},"schemas":{"Marlin.SportsbetApi.Host.Models.Translations.TranslatedMarketViewModel":{"type":"object","properties":{"marketTypeId":{"type":"integer","format":"int64"},"marketTranslations":{"allOf":[{"$ref":"#/components/schemas/Marlin.SportsbetApi.Host.Models.Translations.EntityTranslationsViewModel"}],"description":"Contains entity translation information.","nullable":true},"selections":{"type":"array","items":{"$ref":"#/components/schemas/Marlin.SportsbetApi.Host.Models.Translations.EntityTranslationsViewModel"},"nullable":true}},"additionalProperties":false},"Marlin.SportsbetApi.Host.Models.Translations.EntityTranslationsViewModel":{"type":"object","properties":{"id":{"type":"integer","description":"ID of the entity.","format":"int64"},"translations":{"type":"object","additionalProperties":{"type":"string","nullable":true},"description":"Translations for the entity, where the key is the language code and the value is the translated text.","nullable":true}},"additionalProperties":false,"description":"Contains entity translation information."},"Microsoft.AspNetCore.Mvc.ProblemDetails":{"type":"object","properties":{"type":{"type":"string","nullable":true},"title":{"type":"string","nullable":true},"status":{"type":"integer","format":"int32","nullable":true},"detail":{"type":"string","nullable":true},"instance":{"type":"string","nullable":true}},"additionalProperties":{}}}},"paths":{"/api/translations/all/{eventId}/markets":{"get":{"tags":["Translations"],"summary":"Gets all existing translations for specific markets.","description":"\n**Rate Limits (per account):**\n- **40 req/1s (with query parameters)**\n- **1 req/10s**","operationId":"Get all market translations","parameters":[{"name":"eventId","in":"path","description":"TradeArt event id.","required":true,"schema":{"type":"integer","format":"int64"}},{"name":"markets","in":"query","description":"Markets which will be translated.","schema":{"type":"array","items":{"type":"integer","format":"int64"}}}],"responses":{"200":{"description":"OK","content":{"text/plain":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/Marlin.SportsbetApi.Host.Models.Translations.TranslatedMarketViewModel"}}},"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/Marlin.SportsbetApi.Host.Models.Translations.TranslatedMarketViewModel"}}},"text/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/Marlin.SportsbetApi.Host.Models.Translations.TranslatedMarketViewModel"}}}}},"401":{"description":"Unauthorized"},"403":{"description":"Forbidden"},"404":{"description":"Not Found","content":{"text/plain":{"schema":{"$ref":"#/components/schemas/Microsoft.AspNetCore.Mvc.ProblemDetails"}},"application/json":{"schema":{"$ref":"#/components/schemas/Microsoft.AspNetCore.Mvc.ProblemDetails"}},"text/json":{"schema":{"$ref":"#/components/schemas/Microsoft.AspNetCore.Mvc.ProblemDetails"}}}},"429":{"description":"Too many requests"},"500":{"description":"Internal Server Error"}}}}}}
```

{% hint style="warning" %}
This endpoint is rate-limited to **40 requests per second with specific markets and 1 request per 10 seconds without specific markets.**
{% endhint %}

## Gets all existing translations for a specific region.

> \
> \*\*Rate Limits (per account):\*\*\
> \- \*\*20 req/1s\*\*

```json
{"openapi":"3.0.4","info":{"title":"[T728-STAGE] Odds88 API","version":"v1"},"tags":[{"name":"Translations"}],"security":[{"Bearer":[]}],"components":{"securitySchemes":{"Bearer":{"type":"http","description":"JWT Authorization header using the Bearer scheme. Example: \"Authorization: Bearer {token}\"","scheme":"Bearer","bearerFormat":"JWT"}},"schemas":{"Marlin.SportsbetApi.Host.Models.Translations.EntityTranslationsViewModel":{"type":"object","properties":{"id":{"type":"integer","description":"ID of the entity.","format":"int64"},"translations":{"type":"object","additionalProperties":{"type":"string","nullable":true},"description":"Translations for the entity, where the key is the language code and the value is the translated text.","nullable":true}},"additionalProperties":false,"description":"Contains entity translation information."}}},"paths":{"/api/translations/all/region/{regionId}":{"get":{"tags":["Translations"],"summary":"Gets all existing translations for a specific region.","description":"\n**Rate Limits (per account):**\n- **20 req/1s**","operationId":"Get all region translations","parameters":[{"name":"regionId","in":"path","description":"TradeArt region id.","required":true,"schema":{"type":"integer","format":"int64"}}],"responses":{"200":{"description":"OK","content":{"text/plain":{"schema":{"$ref":"#/components/schemas/Marlin.SportsbetApi.Host.Models.Translations.EntityTranslationsViewModel"}},"application/json":{"schema":{"$ref":"#/components/schemas/Marlin.SportsbetApi.Host.Models.Translations.EntityTranslationsViewModel"}},"text/json":{"schema":{"$ref":"#/components/schemas/Marlin.SportsbetApi.Host.Models.Translations.EntityTranslationsViewModel"}}}},"401":{"description":"Unauthorized"},"403":{"description":"Forbidden"},"429":{"description":"Too many requests"}}}}}}
```

{% hint style="warning" %}
This endpoint is rate-limited to **20 requests per second.**
{% endhint %}

## Gets all existing translations for a specific league.

> \
> \*\*Rate Limits (per account):\*\*\
> \- \*\*20 req/1s\*\*

```json
{"openapi":"3.0.4","info":{"title":"[T728-STAGE] Odds88 API","version":"v1"},"tags":[{"name":"Translations"}],"security":[{"Bearer":[]}],"components":{"securitySchemes":{"Bearer":{"type":"http","description":"JWT Authorization header using the Bearer scheme. Example: \"Authorization: Bearer {token}\"","scheme":"Bearer","bearerFormat":"JWT"}},"schemas":{"Marlin.SportsbetApi.Host.Models.Translations.EntityTranslationsViewModel":{"type":"object","properties":{"id":{"type":"integer","description":"ID of the entity.","format":"int64"},"translations":{"type":"object","additionalProperties":{"type":"string","nullable":true},"description":"Translations for the entity, where the key is the language code and the value is the translated text.","nullable":true}},"additionalProperties":false,"description":"Contains entity translation information."}}},"paths":{"/api/translations/all/league/{leagueId}":{"get":{"tags":["Translations"],"summary":"Gets all existing translations for a specific league.","description":"\n**Rate Limits (per account):**\n- **20 req/1s**","operationId":"Get all league translations","parameters":[{"name":"leagueId","in":"path","description":"TradeArt league id.","required":true,"schema":{"type":"integer","format":"int64"}}],"responses":{"200":{"description":"OK","content":{"text/plain":{"schema":{"$ref":"#/components/schemas/Marlin.SportsbetApi.Host.Models.Translations.EntityTranslationsViewModel"}},"application/json":{"schema":{"$ref":"#/components/schemas/Marlin.SportsbetApi.Host.Models.Translations.EntityTranslationsViewModel"}},"text/json":{"schema":{"$ref":"#/components/schemas/Marlin.SportsbetApi.Host.Models.Translations.EntityTranslationsViewModel"}}}},"401":{"description":"Unauthorized"},"403":{"description":"Forbidden"},"429":{"description":"Too many requests"}}}}}}
```

{% hint style="warning" %}
This endpoint is rate-limited to **20 requests per second.**
{% endhint %}

## Gets all existing translations for a specific competitor.

> \
> \*\*Rate Limits (per account):\*\*\
> \- \*\*20 req/1s\*\*

```json
{"openapi":"3.0.4","info":{"title":"[T728-STAGE] Odds88 API","version":"v1"},"tags":[{"name":"Translations"}],"security":[{"Bearer":[]}],"components":{"securitySchemes":{"Bearer":{"type":"http","description":"JWT Authorization header using the Bearer scheme. Example: \"Authorization: Bearer {token}\"","scheme":"Bearer","bearerFormat":"JWT"}},"schemas":{"Marlin.SportsbetApi.Host.Models.Translations.EntityTranslationsViewModel":{"type":"object","properties":{"id":{"type":"integer","description":"ID of the entity.","format":"int64"},"translations":{"type":"object","additionalProperties":{"type":"string","nullable":true},"description":"Translations for the entity, where the key is the language code and the value is the translated text.","nullable":true}},"additionalProperties":false,"description":"Contains entity translation information."}}},"paths":{"/api/translations/all/competitor/{competitorId}":{"get":{"tags":["Translations"],"summary":"Gets all existing translations for a specific competitor.","description":"\n**Rate Limits (per account):**\n- **20 req/1s**","operationId":"Get all competitor translations","parameters":[{"name":"competitorId","in":"path","description":"TradeArt competitor id.","required":true,"schema":{"type":"integer","format":"int64"}}],"responses":{"200":{"description":"OK","content":{"text/plain":{"schema":{"$ref":"#/components/schemas/Marlin.SportsbetApi.Host.Models.Translations.EntityTranslationsViewModel"}},"application/json":{"schema":{"$ref":"#/components/schemas/Marlin.SportsbetApi.Host.Models.Translations.EntityTranslationsViewModel"}},"text/json":{"schema":{"$ref":"#/components/schemas/Marlin.SportsbetApi.Host.Models.Translations.EntityTranslationsViewModel"}}}},"401":{"description":"Unauthorized"},"403":{"description":"Forbidden"},"429":{"description":"Too many requests"}}}}}}
```

{% hint style="warning" %}
This endpoint is rate-limited to **20 requests per second.**
{% endhint %}

## Gets selection translation templates for specific selections.

> \
> \*\*Rate Limits (per account):\*\*\
> \- \*\*10 req/1s\*\*

```json
{"openapi":"3.0.4","info":{"title":"[T728-STAGE] Odds88 API","version":"v1"},"tags":[{"name":"Translations"}],"security":[{"Bearer":[]}],"components":{"securitySchemes":{"Bearer":{"type":"http","description":"JWT Authorization header using the Bearer scheme. Example: \"Authorization: Bearer {token}\"","scheme":"Bearer","bearerFormat":"JWT"}},"schemas":{"Marlin.SportsbetApi.Host.Models.Translations.EntityTranslationsViewModel":{"type":"object","properties":{"id":{"type":"integer","description":"ID of the entity.","format":"int64"},"translations":{"type":"object","additionalProperties":{"type":"string","nullable":true},"description":"Translations for the entity, where the key is the language code and the value is the translated text.","nullable":true}},"additionalProperties":false,"description":"Contains entity translation information."},"Microsoft.AspNetCore.Mvc.ProblemDetails":{"type":"object","properties":{"type":{"type":"string","nullable":true},"title":{"type":"string","nullable":true},"status":{"type":"integer","format":"int32","nullable":true},"detail":{"type":"string","nullable":true},"instance":{"type":"string","nullable":true}},"additionalProperties":{}}}},"paths":{"/api/translations/templates/selections":{"get":{"tags":["Translations"],"summary":"Gets selection translation templates for specific selections.","description":"\n**Rate Limits (per account):**\n- **10 req/1s**","parameters":[{"name":"selections","in":"query","description":"Collection of selection ids (up to 100).","schema":{"type":"array","items":{"type":"integer","format":"int64"}}}],"responses":{"200":{"description":"OK","content":{"text/plain":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/Marlin.SportsbetApi.Host.Models.Translations.EntityTranslationsViewModel"}}},"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/Marlin.SportsbetApi.Host.Models.Translations.EntityTranslationsViewModel"}}},"text/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/Marlin.SportsbetApi.Host.Models.Translations.EntityTranslationsViewModel"}}}}},"400":{"description":"Bad Request","content":{"text/plain":{"schema":{"$ref":"#/components/schemas/Microsoft.AspNetCore.Mvc.ProblemDetails"}},"application/json":{"schema":{"$ref":"#/components/schemas/Microsoft.AspNetCore.Mvc.ProblemDetails"}},"text/json":{"schema":{"$ref":"#/components/schemas/Microsoft.AspNetCore.Mvc.ProblemDetails"}}}},"401":{"description":"Unauthorized"},"403":{"description":"Forbidden"},"429":{"description":"Too many requests"}}}}}}
```

{% hint style="warning" %}
This endpoint is rate-limited to 1**0 requests per second.**
{% endhint %}

## Gets market type translation template for a specific sport and market types.

> \
> \*\*Rate Limits (per account):\*\*\
> \- \*\*10 req/1s\*\*

```json
{"openapi":"3.0.4","info":{"title":"[T728-STAGE] Odds88 API","version":"v1"},"tags":[{"name":"Translations"}],"security":[{"Bearer":[]}],"components":{"securitySchemes":{"Bearer":{"type":"http","description":"JWT Authorization header using the Bearer scheme. Example: \"Authorization: Bearer {token}\"","scheme":"Bearer","bearerFormat":"JWT"}},"schemas":{"Marlin.SportsbetApi.Host.Models.Translations.EntityTranslationsViewModel":{"type":"object","properties":{"id":{"type":"integer","description":"ID of the entity.","format":"int64"},"translations":{"type":"object","additionalProperties":{"type":"string","nullable":true},"description":"Translations for the entity, where the key is the language code and the value is the translated text.","nullable":true}},"additionalProperties":false,"description":"Contains entity translation information."},"Microsoft.AspNetCore.Mvc.ProblemDetails":{"type":"object","properties":{"type":{"type":"string","nullable":true},"title":{"type":"string","nullable":true},"status":{"type":"integer","format":"int32","nullable":true},"detail":{"type":"string","nullable":true},"instance":{"type":"string","nullable":true}},"additionalProperties":{}}}},"paths":{"/api/translations/templates/market-types":{"get":{"tags":["Translations"],"summary":"Gets market type translation template for a specific sport and market types.","description":"\n**Rate Limits (per account):**\n- **10 req/1s**","parameters":[{"name":"sportId","in":"query","description":"Sport id.","schema":{"type":"integer","format":"int64"}},{"name":"marketTypes","in":"query","description":"Collection of market type ids (up to 100).","schema":{"type":"array","items":{"type":"integer","format":"int64"}}}],"responses":{"200":{"description":"OK","content":{"text/plain":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/Marlin.SportsbetApi.Host.Models.Translations.EntityTranslationsViewModel"}}},"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/Marlin.SportsbetApi.Host.Models.Translations.EntityTranslationsViewModel"}}},"text/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/Marlin.SportsbetApi.Host.Models.Translations.EntityTranslationsViewModel"}}}}},"400":{"description":"Bad Request","content":{"text/plain":{"schema":{"$ref":"#/components/schemas/Microsoft.AspNetCore.Mvc.ProblemDetails"}},"application/json":{"schema":{"$ref":"#/components/schemas/Microsoft.AspNetCore.Mvc.ProblemDetails"}},"text/json":{"schema":{"$ref":"#/components/schemas/Microsoft.AspNetCore.Mvc.ProblemDetails"}}}},"401":{"description":"Unauthorized"},"403":{"description":"Forbidden"},"429":{"description":"Too many requests"}}}}}}
```

{% hint style="warning" %}
This endpoint is rate-limited to 1**0 requests per second.**
{% endhint %}


# Odds88 Feeds

Feeds that Odds88 provide

Odds88 provide various real-time streams (feeds), each of them serving different data.

Delta Feed provides real time updates for sport events:

{% content-ref url="/pages/1d0GJsRhup2cWOSIE6bt" %}
[Delta Feed](/odds88-client-api/odds88-feeds/delta-feed)
{% endcontent-ref %}

Settlement Feed provides bet settlement information:

{% content-ref url="/pages/pCOsbPzku2QUbexzwct0" %}
[Settlement Feed](/odds88-client-api/odds88-feeds/settlement-feed)
{% endcontent-ref %}

Metadata Feed provides real time updates for event metadata:

{% content-ref url="/pages/HjCugoE6BZ6tHCAEI1Sg" %}
[Metadata Feed](/odds88-client-api/odds88-feeds/metadata-feed)
{% endcontent-ref %}

Translation Change Feed provides notification about translation change for different entities:

{% content-ref url="/pages/TqkGvEKMYF8mpmNGgDt9" %}
[Translation Change Feed](/odds88-client-api/odds88-feeds/translation-change-feed)
{% endcontent-ref %}

Cashout Feed provides real-time potential cashout values for bets:

{% content-ref url="/pages/ivn3IWuh7XK7eWavHRnp" %}
[Cashout Feed](/odds88-client-api/odds88-feeds/cashout-feed)
{% endcontent-ref %}

Pick'em Feed provides real time updates for Pick'em markets:

{% content-ref url="/pages/RUwFv9XgqKWOUDS2RIAF" %}
[Pick'em Feed](/odds88-client-api/odds88-feeds/pickem-feed)
{% endcontent-ref %}

{% hint style="warning" %}
All streams connections are rate-limited and there can be only 1 active connection to each stream at a time.
{% endhint %}


# Delta Feed - New Version

Contains live sport data updates

```
/feed/odds?revision={lastUpdatedTime}
```

Contains live sport data updates. Delivered in the form of "deltas" - differences from the previous state.

`revision` - Unix timestamp of last successfully processed delta message. Can be `0` for initial connection but we recommend using **Unix timestamp for the last 1 hour** to reduce load.

Upon connecting you will receive a set of "Snapshot" delta messages, containing full state of event.

{% hint style="warning" %}
The stream connection is rate-limited and there can be only 1 active connection at a time.
{% endhint %}

Rate limit configuration is the following:

* Connection attempt without revision - 5 connections per 1 hour
* Connection attempt with too small revision - 5 connections per 1 hour
* Connection attempt with proper revision - 5 connections per 5 minutes<br>

**Two additional** rate limits apply to all feeds that use a timestamp as the `revision` parameter. These limits apply specifically to **recovery requests made on reconnection**.

#### 1. Large recoveries (timestamp older than 1 hour)

If a client reconnects and requests recovery from a timestamp more than **1 hour** in the past, the request is subject to a hard limit:

> **Limit:** 5 requests per 30 minutes

#### 2. Small recoveries (timestamp within the last 1 hour)

If a client reconnects and requests recovery from a timestamp within the last hour, the length of the requested recovery period is added to a **leaking bucket**:

| Parameter       | Value                                       |
| --------------- | ------------------------------------------- |
| Bucket capacity | 1 hour (3,600 seconds)                      |
| Leak rate       | 4 seconds drained per 1 second of real time |

Once the bucket is full, further recovery requests are blocked until enough has drained.

#### Practical examples

**✅ Within limits** A client that drops and reconnects every **5 minutes** requesting a **10-minute** recovery will operate well under the limit and notice no impact.

**❌ Will be blocked** A client that reconnects every **5 minutes** requesting a **30-minute** recovery will fill the bucket faster than it can drain, and will eventually be blocked.

#### Summary

Frequent reconnects are fine — as long as the requested recovery window stays **proportionate to the reconnect interval**.


# Delta Feed Messages

All types of messages for Delta Feed

## Common Fields

Every Delta payload has the following fields:

* `type` - int - type of delta message. Possible values are:
  * `1` - Event Status Changed
  * `2` - Event Changed
  * `3` - Deprecated
  * `4` - Scoreboard Changed
  * `5` - Bets Cancellation
  * `6` - Event Snapshot
  * `7` - Markets Changed
* `eventId` - int64 - Id of changed sport event
* `sportId` - int64 - Id of a sport to which the affected event belongs
* `locationId` - int64 - Id of a location to which the affected event belongs
* `leagueId` - int64 - Id of a league to which the affected event belongs
* `lastUpdatedTime` - int64 - Unix timestamp of the message, used for feed recovery
* `creationTime` - date-time - timestamp when the message was created
* `correlationId` - string - GUID which can be used to trace back to the message source
* `updateSequence` - int64 - event update sequence. Incremented with each sent delta

## Specific Messages

## The TradeArt.TradeArtApi.Contracts.DeltaMessage.Delta.EventStatusChangedDeltaViewModelV2 object

```json
{"openapi":"3.0.4","info":{"title":"[T728-STAGE] Odds88 API","version":"v1"},"components":{"schemas":{"TradeArt.TradeArtApi.Contracts.DeltaMessage.Delta.EventStatusChangedDeltaViewModelV2":{"type":"object","properties":{"type":{"allOf":[{"$ref":"#/components/schemas/TradeArt.TradeArtApi.Contracts.DeltaMessage.Enums.DeltaType"}],"description":"Type of delta\n\n* `0` - None\n* `1` - EventStatusChanged\n* `2` - EventChanged\n* `3` - MarketChanged\n* `4` - ScoreboardChanged\n* `5` - BetCancel\n* `6` - EventSnapshot\n* `7` - MarketsChanged"},"eventId":{"type":"integer","description":"Id of changed event","format":"int64"},"version":{"type":"integer","description":"Version of feed state","format":"int64"},"correlationId":{"type":"string","description":"Correlation id of the message to trace back.","nullable":true},"creationTime":{"type":"string","description":"Captures the timestamp the dto was created.","format":"date-time"},"sportId":{"type":"integer","description":"Id of the Sport","format":"int64"},"locationId":{"type":"integer","description":"Id of the Location","format":"int64"},"leagueId":{"type":"integer","description":"Id of the League","format":"int64"},"updateSequence":{"type":"integer","description":"Event delta sequence.\nIncremented with each sent delta.","format":"int64"},"lastUpdatedTime":{"type":"integer","description":"Event update time.\nIncremented with each valuable update.","format":"int64"},"status":{"allOf":[{"$ref":"#/components/schemas/TradeArt.TradeArtApi.Contracts.DeltaMessage.Enums.EventStatus"}],"description":"Event status\n\n* `0` - Unknown\n* `1` - Planned\n* `2` - SoonInPlay\n* `3` - Live\n* `4` - Completed\n* `5` - Cancelled\n* `6` - CoverageLost\n* `7` - Closed\n* `8` - Suspended\n* `9` - Postponed\n* `10` - Abandoned"},"tradingStatus":{"allOf":[{"$ref":"#/components/schemas/TradeArt.TradeArtApi.Contracts.DeltaMessage.Enums.TradingStatus"}],"description":"Updated status of event trading\n\n* `0` - Open\n* `1` - Suspended\n* `2` - Closed\n* `3` - Inactive"}},"additionalProperties":false,"description":"Event status or trading status changed"},"TradeArt.TradeArtApi.Contracts.DeltaMessage.Enums.DeltaType":{"enum":[0,1,2,3,4,5,6,7],"type":"integer","description":"Known types of deltas\n\n* `0` - None\n* `1` - EventStatusChanged\n* `2` - EventChanged\n* `3` - MarketChanged\n* `4` - ScoreboardChanged\n* `5` - BetCancel\n* `6` - EventSnapshot\n* `7` - MarketsChanged","format":"int32"},"TradeArt.TradeArtApi.Contracts.DeltaMessage.Enums.EventStatus":{"enum":[0,1,2,3,4,5,6,7,8,9,10],"type":"integer","description":"Status of event\n\n* `0` - Unknown\n* `1` - Planned\n* `2` - SoonInPlay\n* `3` - Live\n* `4` - Completed\n* `5` - Cancelled\n* `6` - CoverageLost\n* `7` - Closed\n* `8` - Suspended\n* `9` - Postponed\n* `10` - Abandoned","format":"int32"},"TradeArt.TradeArtApi.Contracts.DeltaMessage.Enums.TradingStatus":{"enum":[0,1,2,3],"type":"integer","description":"Status of trading\n\n* `0` - Open\n* `1` - Suspended\n* `2` - Closed\n* `3` - Inactive","format":"int32"}}}}
```

## The TradeArt.TradeArtApi.Contracts.DeltaMessage.Delta.EventChangedDeltaViewModelV2 object

```json
{"openapi":"3.0.4","info":{"title":"[T728-STAGE] Odds88 API","version":"v1"},"components":{"schemas":{"TradeArt.TradeArtApi.Contracts.DeltaMessage.Delta.EventChangedDeltaViewModelV2":{"type":"object","properties":{"type":{"allOf":[{"$ref":"#/components/schemas/TradeArt.TradeArtApi.Contracts.DeltaMessage.Enums.DeltaType"}],"description":"Type of delta\n\n* `0` - None\n* `1` - EventStatusChanged\n* `2` - EventChanged\n* `3` - MarketChanged\n* `4` - ScoreboardChanged\n* `5` - BetCancel\n* `6` - EventSnapshot\n* `7` - MarketsChanged"},"eventId":{"type":"integer","description":"Id of changed event","format":"int64"},"version":{"type":"integer","description":"Version of feed state","format":"int64"},"correlationId":{"type":"string","description":"Correlation id of the message to trace back.","nullable":true},"creationTime":{"type":"string","description":"Captures the timestamp the dto was created.","format":"date-time"},"sportId":{"type":"integer","description":"Id of the Sport","format":"int64"},"locationId":{"type":"integer","description":"Id of the Location","format":"int64"},"leagueId":{"type":"integer","description":"Id of the League","format":"int64"},"updateSequence":{"type":"integer","description":"Event delta sequence.\nIncremented with each sent delta.","format":"int64"},"lastUpdatedTime":{"type":"integer","description":"Event update time.\nIncremented with each valuable update.","format":"int64"},"eventInfo":{"allOf":[{"$ref":"#/components/schemas/TradeArt.TradeArtApi.Contracts.DeltaMessage.EventInfoViewModelV2"}],"description":"Updated event info","nullable":true}},"additionalProperties":false,"description":"Event info has been changed or new event added"},"TradeArt.TradeArtApi.Contracts.DeltaMessage.Enums.DeltaType":{"enum":[0,1,2,3,4,5,6,7],"type":"integer","description":"Known types of deltas\n\n* `0` - None\n* `1` - EventStatusChanged\n* `2` - EventChanged\n* `3` - MarketChanged\n* `4` - ScoreboardChanged\n* `5` - BetCancel\n* `6` - EventSnapshot\n* `7` - MarketsChanged","format":"int32"},"TradeArt.TradeArtApi.Contracts.DeltaMessage.EventInfoViewModelV2":{"type":"object","properties":{"id":{"type":"integer","description":"TradeArt event id.","format":"int64"},"name":{"type":"string","description":"Event name.","nullable":true},"status":{"allOf":[{"$ref":"#/components/schemas/TradeArt.TradeArtApi.Contracts.DeltaMessage.Enums.EventStatus"}],"description":"Event status representing current status of the match.\n\n* `0` - Unknown\n* `1` - Planned\n* `2` - SoonInPlay\n* `3` - Live\n* `4` - Completed\n* `5` - Cancelled\n* `6` - CoverageLost\n* `7` - Closed\n* `8` - Suspended\n* `9` - Postponed\n* `10` - Abandoned"},"tradingStatus":{"allOf":[{"$ref":"#/components/schemas/TradeArt.TradeArtApi.Contracts.DeltaMessage.Enums.TradingStatus"}],"description":"Status of trading for the event showing how it should be processed.\n\n* `0` - Open\n* `1` - Suspended\n* `2` - Closed\n* `3` - Inactive"},"statusDescription":{"type":"string","description":"Free text event status description (optional).","nullable":true},"country":{"allOf":[{"$ref":"#/components/schemas/TradeArt.TradeArtApi.Contracts.DeltaMessage.ReferenceViewModelV2"}],"description":"Id and Name of event's country.","nullable":true},"sport":{"allOf":[{"$ref":"#/components/schemas/TradeArt.TradeArtApi.Contracts.DeltaMessage.ReferenceViewModelV2"}],"description":"Id and Name of event's sport.","nullable":true},"competition":{"allOf":[{"$ref":"#/components/schemas/TradeArt.TradeArtApi.Contracts.DeltaMessage.ReferenceViewModelV2"}],"description":"Id and Name of event's competition.","nullable":true},"season":{"allOf":[{"$ref":"#/components/schemas/TradeArt.TradeArtApi.Contracts.DeltaMessage.ReferenceViewModelV2"}],"description":"Id and Name of event's season. Can be null for not-outright events.","nullable":true},"competitors":{"type":"array","items":{"$ref":"#/components/schemas/TradeArt.TradeArtApi.Contracts.DeltaMessage.ReferenceViewModelV2"},"description":"Ids and Names of event's competitors.","nullable":true},"startTime":{"type":"string","description":"Start time of the event. Can be null.","format":"date-time","nullable":true},"isOutright":{"type":"boolean","description":"Flag which indicates that event is outright."},"customDisplayData":{"type":"object","additionalProperties":{"type":"string"},"description":"Custom display parameters of the event","nullable":true},"isBetBuilderSupported":{"type":"boolean","description":"Indicates whether this selection can be used in Bet Builder"},"mappingInfo":{"type":"array","items":{"$ref":"#/components/schemas/TradeArt.TradeArtApi.Contracts.DeltaMessage.MappingViewModel"},"description":"Represents information about external feeds","nullable":true}},"additionalProperties":false,"description":"Information about event (sport, country, statuses etc.)"},"TradeArt.TradeArtApi.Contracts.DeltaMessage.Enums.EventStatus":{"enum":[0,1,2,3,4,5,6,7,8,9,10],"type":"integer","description":"Status of event\n\n* `0` - Unknown\n* `1` - Planned\n* `2` - SoonInPlay\n* `3` - Live\n* `4` - Completed\n* `5` - Cancelled\n* `6` - CoverageLost\n* `7` - Closed\n* `8` - Suspended\n* `9` - Postponed\n* `10` - Abandoned","format":"int32"},"TradeArt.TradeArtApi.Contracts.DeltaMessage.Enums.TradingStatus":{"enum":[0,1,2,3],"type":"integer","description":"Status of trading\n\n* `0` - Open\n* `1` - Suspended\n* `2` - Closed\n* `3` - Inactive","format":"int32"},"TradeArt.TradeArtApi.Contracts.DeltaMessage.ReferenceViewModelV2":{"type":"object","properties":{"id":{"type":"integer","description":"Id of the referenced entity","format":"int64"},"name":{"type":"string","description":"Name of the referenced entity","nullable":true}},"additionalProperties":false,"description":"Contains reference data for entity"},"TradeArt.TradeArtApi.Contracts.DeltaMessage.MappingViewModel":{"type":"object","properties":{"feedId":{"type":"integer","description":"External Feed Id","format":"int32"},"id":{"type":"string","description":"External Event Id","nullable":true}},"additionalProperties":false,"description":"External mappings info"}}}}
```

## The TradeArt.TradeArtApi.Contracts.DeltaMessage.Delta.ScoreboardChangedDeltaViewModelV2 object

```json
{"openapi":"3.0.4","info":{"title":"[T728-STAGE] Odds88 API","version":"v1"},"components":{"schemas":{"TradeArt.TradeArtApi.Contracts.DeltaMessage.Delta.ScoreboardChangedDeltaViewModelV2":{"type":"object","properties":{"type":{"allOf":[{"$ref":"#/components/schemas/TradeArt.TradeArtApi.Contracts.DeltaMessage.Enums.DeltaType"}],"description":"Type of delta\n\n* `0` - None\n* `1` - EventStatusChanged\n* `2` - EventChanged\n* `3` - MarketChanged\n* `4` - ScoreboardChanged\n* `5` - BetCancel\n* `6` - EventSnapshot\n* `7` - MarketsChanged"},"eventId":{"type":"integer","description":"Id of changed event","format":"int64"},"version":{"type":"integer","description":"Version of feed state","format":"int64"},"correlationId":{"type":"string","description":"Correlation id of the message to trace back.","nullable":true},"creationTime":{"type":"string","description":"Captures the timestamp the dto was created.","format":"date-time"},"sportId":{"type":"integer","description":"Id of the Sport","format":"int64"},"locationId":{"type":"integer","description":"Id of the Location","format":"int64"},"leagueId":{"type":"integer","description":"Id of the League","format":"int64"},"updateSequence":{"type":"integer","description":"Event delta sequence.\nIncremented with each sent delta.","format":"int64"},"lastUpdatedTime":{"type":"integer","description":"Event update time.\nIncremented with each valuable update.","format":"int64"},"scoreboard":{"allOf":[{"$ref":"#/components/schemas/TradeArt.TradeArtApi.Contracts.DeltaMessage.Scoreboard.ScoreboardViewModel"}],"description":"Scoreboard of event","nullable":true}},"additionalProperties":false,"description":"Event score or time changed"},"TradeArt.TradeArtApi.Contracts.DeltaMessage.Enums.DeltaType":{"enum":[0,1,2,3,4,5,6,7],"type":"integer","description":"Known types of deltas\n\n* `0` - None\n* `1` - EventStatusChanged\n* `2` - EventChanged\n* `3` - MarketChanged\n* `4` - ScoreboardChanged\n* `5` - BetCancel\n* `6` - EventSnapshot\n* `7` - MarketsChanged","format":"int32"},"TradeArt.TradeArtApi.Contracts.DeltaMessage.Scoreboard.ScoreboardViewModel":{"type":"object","properties":{"time":{"type":"integer","description":"Current time of event (in seconds)","format":"int32"},"results":{"type":"array","items":{"$ref":"#/components/schemas/TradeArt.TradeArtApi.Contracts.DeltaMessage.Scoreboard.ResultViewModel"},"description":"Current event results per competitor (in seconds)","nullable":true},"periods":{"type":"array","items":{"$ref":"#/components/schemas/TradeArt.TradeArtApi.Contracts.DeltaMessage.Scoreboard.PeriodViewModel"},"description":"Current event periods with results and incidents","nullable":true},"incidents":{"type":"array","items":{"$ref":"#/components/schemas/TradeArt.TradeArtApi.Contracts.DeltaMessage.Scoreboard.IncidentCountViewModel"},"description":"Current event incident summary","nullable":true},"currentPeriodId":{"type":"integer","description":"Internal id of current period","format":"int32"},"lastUpdateTime":{"type":"string","description":"Last update time of the scoreboard","format":"date-time"},"homeGameScore":{"type":"string","description":"Current home team game score","nullable":true},"awayGameScore":{"type":"string","description":"Current away team game score","nullable":true},"extraData":{"type":"object","additionalProperties":{"type":"string"},"description":"Extra parameters of the score","nullable":true}},"additionalProperties":false,"description":"Represents event's scoreboard"},"TradeArt.TradeArtApi.Contracts.DeltaMessage.Scoreboard.ResultViewModel":{"type":"object","properties":{"competitorPosition":{"type":"integer","description":"Competitor position (e.g. 1 - Home, 2 - Away)","format":"int32"},"value":{"type":"string","description":"Result value","nullable":true}},"additionalProperties":false,"description":"Represents scoreboard result"},"TradeArt.TradeArtApi.Contracts.DeltaMessage.Scoreboard.PeriodViewModel":{"type":"object","properties":{"id":{"type":"integer","description":"Period Id","format":"int32"},"isFinished":{"type":"boolean","description":"Is period finished?"},"incidents":{"type":"array","items":{"$ref":"#/components/schemas/TradeArt.TradeArtApi.Contracts.DeltaMessage.Scoreboard.IncidentViewModel"},"description":"Incidents occurred in the period","nullable":true},"results":{"type":"array","items":{"$ref":"#/components/schemas/TradeArt.TradeArtApi.Contracts.DeltaMessage.Scoreboard.ResultViewModel"},"description":"Results of the period","nullable":true},"order":{"type":"integer","description":"The position of this period in a sorted sequence.","format":"int32"},"subPeriods":{"type":"array","items":{"$ref":"#/components/schemas/TradeArt.TradeArtApi.Contracts.DeltaMessage.Scoreboard.SubPeriodViewModel"},"description":"Sub periods of the period","nullable":true}},"additionalProperties":false,"description":"Represents period of the event"},"TradeArt.TradeArtApi.Contracts.DeltaMessage.Scoreboard.IncidentViewModel":{"type":"object","properties":{"type":{"type":"integer","description":"Incident type","format":"int32"},"time":{"type":"integer","description":"Event time","format":"int32"},"competitorPosition":{"type":"integer","description":"Index of the competitor in the EventInfo.Competitors array","format":"int32"}},"additionalProperties":false,"description":"Represents incident information"},"TradeArt.TradeArtApi.Contracts.DeltaMessage.Scoreboard.SubPeriodViewModel":{"type":"object","properties":{"isFinished":{"type":"boolean","description":"Is sub period finished?"},"results":{"type":"array","items":{"$ref":"#/components/schemas/TradeArt.TradeArtApi.Contracts.DeltaMessage.Scoreboard.ResultViewModel"},"description":"Results of the sub period","nullable":true},"order":{"type":"integer","description":"The position of this sub period in a sorted sequence.","format":"int32"}},"additionalProperties":false,"description":"Represents sub period of the event period"},"TradeArt.TradeArtApi.Contracts.DeltaMessage.Scoreboard.IncidentCountViewModel":{"type":"object","properties":{"type":{"type":"integer","description":"Incident type","format":"int32"},"competitorPosition":{"type":"integer","description":"Competitor position (e.g. 1 - Home, 2 - Away)","format":"int32"},"count":{"type":"integer","description":"Incident count","format":"int32"}},"additionalProperties":false,"description":"Incident count by type and competitor"}}}}
```

## The TradeArt.TradeArtApi.Contracts.DeltaMessage.Delta.BetCancelDeltaViewModelV2 object

```json
{"openapi":"3.0.4","info":{"title":"[T728-STAGE] Odds88 API","version":"v1"},"components":{"schemas":{"TradeArt.TradeArtApi.Contracts.DeltaMessage.Delta.BetCancelDeltaViewModelV2":{"type":"object","properties":{"type":{"allOf":[{"$ref":"#/components/schemas/TradeArt.TradeArtApi.Contracts.DeltaMessage.Enums.DeltaType"}],"description":"Type of delta\n\n* `0` - None\n* `1` - EventStatusChanged\n* `2` - EventChanged\n* `3` - MarketChanged\n* `4` - ScoreboardChanged\n* `5` - BetCancel\n* `6` - EventSnapshot\n* `7` - MarketsChanged"},"eventId":{"type":"integer","description":"Id of changed event","format":"int64"},"version":{"type":"integer","description":"Version of feed state","format":"int64"},"correlationId":{"type":"string","description":"Correlation id of the message to trace back.","nullable":true},"creationTime":{"type":"string","description":"Captures the timestamp the dto was created.","format":"date-time"},"sportId":{"type":"integer","description":"Id of the Sport","format":"int64"},"locationId":{"type":"integer","description":"Id of the Location","format":"int64"},"leagueId":{"type":"integer","description":"Id of the League","format":"int64"},"updateSequence":{"type":"integer","description":"Event delta sequence.\nIncremented with each sent delta.","format":"int64"},"lastUpdatedTime":{"type":"integer","description":"Event update time.\nIncremented with each valuable update.","format":"int64"},"marketId":{"type":"integer","description":"Market bets on which should be voided","format":"int64"},"from":{"type":"string","description":"Time from which bets should be voided. Equals DateTime.MinValue if no lower bound provided","format":"date-time"},"to":{"type":"string","description":"Time to which bets should be voided. Equals DateTime.MaxValue if no upper bound provided","format":"date-time"},"isRolledBack":{"type":"boolean","description":"Flag indicating whether current Delta rollback previous cancellation for this Market and lying within same From-To range"}},"additionalProperties":false,"description":"Bets placed within period of time must be voided"},"TradeArt.TradeArtApi.Contracts.DeltaMessage.Enums.DeltaType":{"enum":[0,1,2,3,4,5,6,7],"type":"integer","description":"Known types of deltas\n\n* `0` - None\n* `1` - EventStatusChanged\n* `2` - EventChanged\n* `3` - MarketChanged\n* `4` - ScoreboardChanged\n* `5` - BetCancel\n* `6` - EventSnapshot\n* `7` - MarketsChanged","format":"int32"}}}}
```

## The TradeArt.TradeArtApi.Contracts.DeltaMessage.Delta.EventSnapshotDeltaViewModelV2 object

```json
{"openapi":"3.0.4","info":{"title":"[T728-STAGE] Odds88 API","version":"v1"},"components":{"schemas":{"TradeArt.TradeArtApi.Contracts.DeltaMessage.Delta.EventSnapshotDeltaViewModelV2":{"type":"object","properties":{"type":{"allOf":[{"$ref":"#/components/schemas/TradeArt.TradeArtApi.Contracts.DeltaMessage.Enums.DeltaType"}],"description":"Type of delta\n\n* `0` - None\n* `1` - EventStatusChanged\n* `2` - EventChanged\n* `3` - MarketChanged\n* `4` - ScoreboardChanged\n* `5` - BetCancel\n* `6` - EventSnapshot\n* `7` - MarketsChanged"},"eventId":{"type":"integer","description":"Id of changed event","format":"int64"},"version":{"type":"integer","description":"Version of feed state","format":"int64"},"correlationId":{"type":"string","description":"Correlation id of the message to trace back.","nullable":true},"creationTime":{"type":"string","description":"Captures the timestamp the dto was created.","format":"date-time"},"sportId":{"type":"integer","description":"Id of the Sport","format":"int64"},"locationId":{"type":"integer","description":"Id of the Location","format":"int64"},"leagueId":{"type":"integer","description":"Id of the League","format":"int64"},"updateSequence":{"type":"integer","description":"Event delta sequence.\nIncremented with each sent delta.","format":"int64"},"lastUpdatedTime":{"type":"integer","description":"Event update time.\nIncremented with each valuable update.","format":"int64"},"eventInfo":{"allOf":[{"$ref":"#/components/schemas/TradeArt.TradeArtApi.Contracts.DeltaMessage.EventInfoViewModelV2"}],"description":"Fixture info containing basic event information.","nullable":true},"markets":{"type":"array","items":{"$ref":"#/components/schemas/TradeArt.TradeArtApi.Contracts.DeltaMessage.MarketViewModelV2"},"description":"Markets of the event.","nullable":true},"scoreboard":{"allOf":[{"$ref":"#/components/schemas/TradeArt.TradeArtApi.Contracts.DeltaMessage.Scoreboard.ScoreboardViewModel"}],"description":"Scoreboard of the event. Can be null.","nullable":true},"betCancellations":{"type":"array","items":{"$ref":"#/components/schemas/TradeArt.TradeArtApi.Contracts.DeltaMessage.BetCancellationViewModel"},"description":"List of bet cancellations on this event and certain market received from BetRadar. Can be null.","nullable":true}},"additionalProperties":false,"description":"Full snapshot of event data"},"TradeArt.TradeArtApi.Contracts.DeltaMessage.Enums.DeltaType":{"enum":[0,1,2,3,4,5,6,7],"type":"integer","description":"Known types of deltas\n\n* `0` - None\n* `1` - EventStatusChanged\n* `2` - EventChanged\n* `3` - MarketChanged\n* `4` - ScoreboardChanged\n* `5` - BetCancel\n* `6` - EventSnapshot\n* `7` - MarketsChanged","format":"int32"},"TradeArt.TradeArtApi.Contracts.DeltaMessage.EventInfoViewModelV2":{"type":"object","properties":{"id":{"type":"integer","description":"TradeArt event id.","format":"int64"},"name":{"type":"string","description":"Event name.","nullable":true},"status":{"allOf":[{"$ref":"#/components/schemas/TradeArt.TradeArtApi.Contracts.DeltaMessage.Enums.EventStatus"}],"description":"Event status representing current status of the match.\n\n* `0` - Unknown\n* `1` - Planned\n* `2` - SoonInPlay\n* `3` - Live\n* `4` - Completed\n* `5` - Cancelled\n* `6` - CoverageLost\n* `7` - Closed\n* `8` - Suspended\n* `9` - Postponed\n* `10` - Abandoned"},"tradingStatus":{"allOf":[{"$ref":"#/components/schemas/TradeArt.TradeArtApi.Contracts.DeltaMessage.Enums.TradingStatus"}],"description":"Status of trading for the event showing how it should be processed.\n\n* `0` - Open\n* `1` - Suspended\n* `2` - Closed\n* `3` - Inactive"},"statusDescription":{"type":"string","description":"Free text event status description (optional).","nullable":true},"country":{"allOf":[{"$ref":"#/components/schemas/TradeArt.TradeArtApi.Contracts.DeltaMessage.ReferenceViewModelV2"}],"description":"Id and Name of event's country.","nullable":true},"sport":{"allOf":[{"$ref":"#/components/schemas/TradeArt.TradeArtApi.Contracts.DeltaMessage.ReferenceViewModelV2"}],"description":"Id and Name of event's sport.","nullable":true},"competition":{"allOf":[{"$ref":"#/components/schemas/TradeArt.TradeArtApi.Contracts.DeltaMessage.ReferenceViewModelV2"}],"description":"Id and Name of event's competition.","nullable":true},"season":{"allOf":[{"$ref":"#/components/schemas/TradeArt.TradeArtApi.Contracts.DeltaMessage.ReferenceViewModelV2"}],"description":"Id and Name of event's season. Can be null for not-outright events.","nullable":true},"competitors":{"type":"array","items":{"$ref":"#/components/schemas/TradeArt.TradeArtApi.Contracts.DeltaMessage.ReferenceViewModelV2"},"description":"Ids and Names of event's competitors.","nullable":true},"startTime":{"type":"string","description":"Start time of the event. Can be null.","format":"date-time","nullable":true},"isOutright":{"type":"boolean","description":"Flag which indicates that event is outright."},"customDisplayData":{"type":"object","additionalProperties":{"type":"string"},"description":"Custom display parameters of the event","nullable":true},"isBetBuilderSupported":{"type":"boolean","description":"Indicates whether this selection can be used in Bet Builder"},"mappingInfo":{"type":"array","items":{"$ref":"#/components/schemas/TradeArt.TradeArtApi.Contracts.DeltaMessage.MappingViewModel"},"description":"Represents information about external feeds","nullable":true}},"additionalProperties":false,"description":"Information about event (sport, country, statuses etc.)"},"TradeArt.TradeArtApi.Contracts.DeltaMessage.Enums.EventStatus":{"enum":[0,1,2,3,4,5,6,7,8,9,10],"type":"integer","description":"Status of event\n\n* `0` - Unknown\n* `1` - Planned\n* `2` - SoonInPlay\n* `3` - Live\n* `4` - Completed\n* `5` - Cancelled\n* `6` - CoverageLost\n* `7` - Closed\n* `8` - Suspended\n* `9` - Postponed\n* `10` - Abandoned","format":"int32"},"TradeArt.TradeArtApi.Contracts.DeltaMessage.Enums.TradingStatus":{"enum":[0,1,2,3],"type":"integer","description":"Status of trading\n\n* `0` - Open\n* `1` - Suspended\n* `2` - Closed\n* `3` - Inactive","format":"int32"},"TradeArt.TradeArtApi.Contracts.DeltaMessage.ReferenceViewModelV2":{"type":"object","properties":{"id":{"type":"integer","description":"Id of the referenced entity","format":"int64"},"name":{"type":"string","description":"Name of the referenced entity","nullable":true}},"additionalProperties":false,"description":"Contains reference data for entity"},"TradeArt.TradeArtApi.Contracts.DeltaMessage.MappingViewModel":{"type":"object","properties":{"feedId":{"type":"integer","description":"External Feed Id","format":"int32"},"id":{"type":"string","description":"External Event Id","nullable":true}},"additionalProperties":false,"description":"External mappings info"},"TradeArt.TradeArtApi.Contracts.DeltaMessage.MarketViewModelV2":{"type":"object","properties":{"id":{"type":"integer","description":"Market Id","format":"int64"},"name":{"type":"string","description":"Market name","nullable":true},"tradingStatus":{"allOf":[{"$ref":"#/components/schemas/TradeArt.TradeArtApi.Contracts.DeltaMessage.Enums.TradingStatus"}],"description":"Market trading status\n\n* `0` - Open\n* `1` - Suspended\n* `2` - Closed\n* `3` - Inactive"},"selections":{"type":"array","items":{"$ref":"#/components/schemas/TradeArt.TradeArtApi.Contracts.DeltaMessage.SelectionViewModelV2"},"description":"Market selections","nullable":true},"type":{"type":"integer","description":"Market type Id","format":"int64"},"isBestLine":{"type":"boolean","description":"Is the main market?"},"parameters":{"type":"object","additionalProperties":{"type":"string"},"description":"Parameters of market. i.e. hcp = 2.5, total=1.5","nullable":true},"extraParameters":{"type":"object","additionalProperties":{"type":"string"},"description":"Additional market information (like score = 1:0)","nullable":true},"isBetBuilderSupported":{"type":"boolean","description":"Indicates whether this selection can be used in Bet Builder"}},"additionalProperties":false,"description":"Represents market data"},"TradeArt.TradeArtApi.Contracts.DeltaMessage.SelectionViewModelV2":{"type":"object","properties":{"id":{"type":"integer","description":"Selection Id","format":"int64"},"name":{"type":"string","description":"Selection name","nullable":true},"probability":{"type":"number","description":"Selection probability","format":"float","nullable":true},"price":{"type":"number","description":"Selection odds","format":"float","nullable":true},"originalPrice":{"type":"number","description":"Selection odds","format":"float","nullable":true},"status":{"allOf":[{"$ref":"#/components/schemas/TradeArt.TradeArtApi.Contracts.DeltaMessage.Enums.TradingStatus"}],"description":"Trading selection status\n\n* `0` - Open\n* `1` - Suspended\n* `2` - Closed\n* `3` - Inactive"},"settlement":{"allOf":[{"$ref":"#/components/schemas/TradeArt.TradeArtApi.Contracts.DeltaMessage.Enums.SettlementResult"}],"description":"Settlement result of the selection\n\n* `0` - None\n* `1` - Refund\n* `2` - Lose\n* `3` - Win\n* `4` - HalfLose\n* `5` - HalfWin"},"deadHeatFactor":{"type":"number","description":"Dead heat factor is a floating point number used when there is a tie in outrights","format":"double","nullable":true},"extraParameters":{"type":"object","additionalProperties":{"type":"string"},"description":"Additional selection information","nullable":true},"isBetBuilderSupported":{"type":"boolean","description":"Indicates whether this selection can be used in Bet Builder"},"competitorId":{"type":"integer","description":"Id of the competitor","format":"int64"},"startingPrice":{"type":"number","description":"Starting Price of the selection before turning to in-play.","format":"float","nullable":true}},"additionalProperties":false,"description":"Represents market selection information"},"TradeArt.TradeArtApi.Contracts.DeltaMessage.Enums.SettlementResult":{"enum":[0,1,2,3,4,5],"type":"integer","description":"Status of a selection settlement\n\n* `0` - None\n* `1` - Refund\n* `2` - Lose\n* `3` - Win\n* `4` - HalfLose\n* `5` - HalfWin","format":"int32"},"TradeArt.TradeArtApi.Contracts.DeltaMessage.Scoreboard.ScoreboardViewModel":{"type":"object","properties":{"time":{"type":"integer","description":"Current time of event (in seconds)","format":"int32"},"results":{"type":"array","items":{"$ref":"#/components/schemas/TradeArt.TradeArtApi.Contracts.DeltaMessage.Scoreboard.ResultViewModel"},"description":"Current event results per competitor (in seconds)","nullable":true},"periods":{"type":"array","items":{"$ref":"#/components/schemas/TradeArt.TradeArtApi.Contracts.DeltaMessage.Scoreboard.PeriodViewModel"},"description":"Current event periods with results and incidents","nullable":true},"incidents":{"type":"array","items":{"$ref":"#/components/schemas/TradeArt.TradeArtApi.Contracts.DeltaMessage.Scoreboard.IncidentCountViewModel"},"description":"Current event incident summary","nullable":true},"currentPeriodId":{"type":"integer","description":"Internal id of current period","format":"int32"},"lastUpdateTime":{"type":"string","description":"Last update time of the scoreboard","format":"date-time"},"homeGameScore":{"type":"string","description":"Current home team game score","nullable":true},"awayGameScore":{"type":"string","description":"Current away team game score","nullable":true},"extraData":{"type":"object","additionalProperties":{"type":"string"},"description":"Extra parameters of the score","nullable":true}},"additionalProperties":false,"description":"Represents event's scoreboard"},"TradeArt.TradeArtApi.Contracts.DeltaMessage.Scoreboard.ResultViewModel":{"type":"object","properties":{"competitorPosition":{"type":"integer","description":"Competitor position (e.g. 1 - Home, 2 - Away)","format":"int32"},"value":{"type":"string","description":"Result value","nullable":true}},"additionalProperties":false,"description":"Represents scoreboard result"},"TradeArt.TradeArtApi.Contracts.DeltaMessage.Scoreboard.PeriodViewModel":{"type":"object","properties":{"id":{"type":"integer","description":"Period Id","format":"int32"},"isFinished":{"type":"boolean","description":"Is period finished?"},"incidents":{"type":"array","items":{"$ref":"#/components/schemas/TradeArt.TradeArtApi.Contracts.DeltaMessage.Scoreboard.IncidentViewModel"},"description":"Incidents occurred in the period","nullable":true},"results":{"type":"array","items":{"$ref":"#/components/schemas/TradeArt.TradeArtApi.Contracts.DeltaMessage.Scoreboard.ResultViewModel"},"description":"Results of the period","nullable":true},"order":{"type":"integer","description":"The position of this period in a sorted sequence.","format":"int32"},"subPeriods":{"type":"array","items":{"$ref":"#/components/schemas/TradeArt.TradeArtApi.Contracts.DeltaMessage.Scoreboard.SubPeriodViewModel"},"description":"Sub periods of the period","nullable":true}},"additionalProperties":false,"description":"Represents period of the event"},"TradeArt.TradeArtApi.Contracts.DeltaMessage.Scoreboard.IncidentViewModel":{"type":"object","properties":{"type":{"type":"integer","description":"Incident type","format":"int32"},"time":{"type":"integer","description":"Event time","format":"int32"},"competitorPosition":{"type":"integer","description":"Index of the competitor in the EventInfo.Competitors array","format":"int32"}},"additionalProperties":false,"description":"Represents incident information"},"TradeArt.TradeArtApi.Contracts.DeltaMessage.Scoreboard.SubPeriodViewModel":{"type":"object","properties":{"isFinished":{"type":"boolean","description":"Is sub period finished?"},"results":{"type":"array","items":{"$ref":"#/components/schemas/TradeArt.TradeArtApi.Contracts.DeltaMessage.Scoreboard.ResultViewModel"},"description":"Results of the sub period","nullable":true},"order":{"type":"integer","description":"The position of this sub period in a sorted sequence.","format":"int32"}},"additionalProperties":false,"description":"Represents sub period of the event period"},"TradeArt.TradeArtApi.Contracts.DeltaMessage.Scoreboard.IncidentCountViewModel":{"type":"object","properties":{"type":{"type":"integer","description":"Incident type","format":"int32"},"competitorPosition":{"type":"integer","description":"Competitor position (e.g. 1 - Home, 2 - Away)","format":"int32"},"count":{"type":"integer","description":"Incident count","format":"int32"}},"additionalProperties":false,"description":"Incident count by type and competitor"},"TradeArt.TradeArtApi.Contracts.DeltaMessage.BetCancellationViewModel":{"type":"object","properties":{"marketId":{"type":"integer","description":"Affected MarketId","format":"int64"},"from":{"type":"string","description":"Cancel bets placed starting From this date. Equals DateTime.MinValue if no lower bound provided","format":"date-time"},"to":{"type":"string","description":"Cancel bets placed starting To this date. Equals DateTime.MaxValue if no upper bound provided","format":"date-time"},"isRolledBack":{"type":"boolean","description":"Flag pointing whether this cancellation should be rolled back"}},"additionalProperties":false,"description":"Information about bet cancellations on certain market between From and To dates"}}}}
```

## The TradeArt.TradeArtApi.Contracts.DeltaMessage.Delta.MarketsChangedDeltaViewModelV2 object

```json
{"openapi":"3.0.4","info":{"title":"[T728-STAGE] Odds88 API","version":"v1"},"components":{"schemas":{"TradeArt.TradeArtApi.Contracts.DeltaMessage.Delta.MarketsChangedDeltaViewModelV2":{"type":"object","properties":{"type":{"allOf":[{"$ref":"#/components/schemas/TradeArt.TradeArtApi.Contracts.DeltaMessage.Enums.DeltaType"}],"description":"Type of delta\n\n* `0` - None\n* `1` - EventStatusChanged\n* `2` - EventChanged\n* `3` - MarketChanged\n* `4` - ScoreboardChanged\n* `5` - BetCancel\n* `6` - EventSnapshot\n* `7` - MarketsChanged"},"eventId":{"type":"integer","description":"Id of changed event","format":"int64"},"version":{"type":"integer","description":"Version of feed state","format":"int64"},"correlationId":{"type":"string","description":"Correlation id of the message to trace back.","nullable":true},"creationTime":{"type":"string","description":"Captures the timestamp the dto was created.","format":"date-time"},"sportId":{"type":"integer","description":"Id of the Sport","format":"int64"},"locationId":{"type":"integer","description":"Id of the Location","format":"int64"},"leagueId":{"type":"integer","description":"Id of the League","format":"int64"},"updateSequence":{"type":"integer","description":"Event delta sequence.\nIncremented with each sent delta.","format":"int64"},"lastUpdatedTime":{"type":"integer","description":"Event update time.\nIncremented with each valuable update.","format":"int64"},"markets":{"type":"array","items":{"$ref":"#/components/schemas/TradeArt.TradeArtApi.Contracts.DeltaMessage.MarketViewModelV2"},"description":"Updated markets","nullable":true}},"additionalProperties":false,"description":"New markets added or odds changed"},"TradeArt.TradeArtApi.Contracts.DeltaMessage.Enums.DeltaType":{"enum":[0,1,2,3,4,5,6,7],"type":"integer","description":"Known types of deltas\n\n* `0` - None\n* `1` - EventStatusChanged\n* `2` - EventChanged\n* `3` - MarketChanged\n* `4` - ScoreboardChanged\n* `5` - BetCancel\n* `6` - EventSnapshot\n* `7` - MarketsChanged","format":"int32"},"TradeArt.TradeArtApi.Contracts.DeltaMessage.MarketViewModelV2":{"type":"object","properties":{"id":{"type":"integer","description":"Market Id","format":"int64"},"name":{"type":"string","description":"Market name","nullable":true},"tradingStatus":{"allOf":[{"$ref":"#/components/schemas/TradeArt.TradeArtApi.Contracts.DeltaMessage.Enums.TradingStatus"}],"description":"Market trading status\n\n* `0` - Open\n* `1` - Suspended\n* `2` - Closed\n* `3` - Inactive"},"selections":{"type":"array","items":{"$ref":"#/components/schemas/TradeArt.TradeArtApi.Contracts.DeltaMessage.SelectionViewModelV2"},"description":"Market selections","nullable":true},"type":{"type":"integer","description":"Market type Id","format":"int64"},"isBestLine":{"type":"boolean","description":"Is the main market?"},"parameters":{"type":"object","additionalProperties":{"type":"string"},"description":"Parameters of market. i.e. hcp = 2.5, total=1.5","nullable":true},"extraParameters":{"type":"object","additionalProperties":{"type":"string"},"description":"Additional market information (like score = 1:0)","nullable":true},"isBetBuilderSupported":{"type":"boolean","description":"Indicates whether this selection can be used in Bet Builder"}},"additionalProperties":false,"description":"Represents market data"},"TradeArt.TradeArtApi.Contracts.DeltaMessage.Enums.TradingStatus":{"enum":[0,1,2,3],"type":"integer","description":"Status of trading\n\n* `0` - Open\n* `1` - Suspended\n* `2` - Closed\n* `3` - Inactive","format":"int32"},"TradeArt.TradeArtApi.Contracts.DeltaMessage.SelectionViewModelV2":{"type":"object","properties":{"id":{"type":"integer","description":"Selection Id","format":"int64"},"name":{"type":"string","description":"Selection name","nullable":true},"probability":{"type":"number","description":"Selection probability","format":"float","nullable":true},"price":{"type":"number","description":"Selection odds","format":"float","nullable":true},"originalPrice":{"type":"number","description":"Selection odds","format":"float","nullable":true},"status":{"allOf":[{"$ref":"#/components/schemas/TradeArt.TradeArtApi.Contracts.DeltaMessage.Enums.TradingStatus"}],"description":"Trading selection status\n\n* `0` - Open\n* `1` - Suspended\n* `2` - Closed\n* `3` - Inactive"},"settlement":{"allOf":[{"$ref":"#/components/schemas/TradeArt.TradeArtApi.Contracts.DeltaMessage.Enums.SettlementResult"}],"description":"Settlement result of the selection\n\n* `0` - None\n* `1` - Refund\n* `2` - Lose\n* `3` - Win\n* `4` - HalfLose\n* `5` - HalfWin"},"deadHeatFactor":{"type":"number","description":"Dead heat factor is a floating point number used when there is a tie in outrights","format":"double","nullable":true},"extraParameters":{"type":"object","additionalProperties":{"type":"string"},"description":"Additional selection information","nullable":true},"isBetBuilderSupported":{"type":"boolean","description":"Indicates whether this selection can be used in Bet Builder"},"competitorId":{"type":"integer","description":"Id of the competitor","format":"int64"},"startingPrice":{"type":"number","description":"Starting Price of the selection before turning to in-play.","format":"float","nullable":true}},"additionalProperties":false,"description":"Represents market selection information"},"TradeArt.TradeArtApi.Contracts.DeltaMessage.Enums.SettlementResult":{"enum":[0,1,2,3,4,5],"type":"integer","description":"Status of a selection settlement\n\n* `0` - None\n* `1` - Refund\n* `2` - Lose\n* `3` - Win\n* `4` - HalfLose\n* `5` - HalfWin","format":"int32"}}}}
```


# Delta Feed

Contains live sport data updates

```
/api/v2/feed?revision=<revision>
```

Contains live sport data updates. Delivered in the form of "deltas" - differences from the previous state.

`revision` - version of last successfully processed delta message. Can be `0` for initial connection.

Upon connecting you will receive a set of "Snapshot" delta messages, containing full state of event.

{% hint style="warning" %}
The stream connection is rate-limited and there can be only 1 active connection at a time.
{% endhint %}

Rate limit configuration is the following:

* Connection attempt without revision - 5 connections per 1 hour
* Connection attempt with too small revision - 5 connections per 1 hour
* Connection attempt with proper revision - 5 connections per 5 minutes


# Delta Feed Messages

All types of messages for Delta Feed

## Common Fields

Every Delta Feed message has the following fields:

* `type` - int - type of delta message. Possible values are:
  * `1` - Event Status Changed
  * `2` - Event Changed
  * `3` - Deprecated
  * `4` - Scoreboard Changed
  * `5` - Bets Cancellation
  * `6` - Event Snapshot
  * `7` - Markets Changed
* `eventId` - int64 - Id of changed sport event
* `sportId` - int64 - Id of a sport to which the affected event belongs
* `locationId` - int64 - Id of a location to which the affected event belongs
* `leagueId` - int64 - Id of a league to which the affected event belongs
* `version` - int64 - version of the message, used for feed recovery
* `creationTime` - date-time - timestamp when the message was created
* `correlationId` - string - GUID which can be used to trace back to the message source

## Specific Messages

## The TradeArt.TradeArtApi.Contracts.DeltaMessage.Delta.EventStatusChangedDeltaViewModelV2 object

```json
{"openapi":"3.0.4","info":{"title":"[T728-STAGE] Odds88 API","version":"v1"},"components":{"schemas":{"TradeArt.TradeArtApi.Contracts.DeltaMessage.Delta.EventStatusChangedDeltaViewModelV2":{"type":"object","properties":{"type":{"allOf":[{"$ref":"#/components/schemas/TradeArt.TradeArtApi.Contracts.DeltaMessage.Enums.DeltaType"}],"description":"Type of delta\n\n* `0` - None\n* `1` - EventStatusChanged\n* `2` - EventChanged\n* `3` - MarketChanged\n* `4` - ScoreboardChanged\n* `5` - BetCancel\n* `6` - EventSnapshot\n* `7` - MarketsChanged"},"eventId":{"type":"integer","description":"Id of changed event","format":"int64"},"version":{"type":"integer","description":"Version of feed state","format":"int64"},"correlationId":{"type":"string","description":"Correlation id of the message to trace back.","nullable":true},"creationTime":{"type":"string","description":"Captures the timestamp the dto was created.","format":"date-time"},"sportId":{"type":"integer","description":"Id of the Sport","format":"int64"},"locationId":{"type":"integer","description":"Id of the Location","format":"int64"},"leagueId":{"type":"integer","description":"Id of the League","format":"int64"},"updateSequence":{"type":"integer","description":"Event delta sequence.\nIncremented with each sent delta.","format":"int64"},"lastUpdatedTime":{"type":"integer","description":"Event update time.\nIncremented with each valuable update.","format":"int64"},"status":{"allOf":[{"$ref":"#/components/schemas/TradeArt.TradeArtApi.Contracts.DeltaMessage.Enums.EventStatus"}],"description":"Event status\n\n* `0` - Unknown\n* `1` - Planned\n* `2` - SoonInPlay\n* `3` - Live\n* `4` - Completed\n* `5` - Cancelled\n* `6` - CoverageLost\n* `7` - Closed\n* `8` - Suspended\n* `9` - Postponed\n* `10` - Abandoned"},"tradingStatus":{"allOf":[{"$ref":"#/components/schemas/TradeArt.TradeArtApi.Contracts.DeltaMessage.Enums.TradingStatus"}],"description":"Updated status of event trading\n\n* `0` - Open\n* `1` - Suspended\n* `2` - Closed\n* `3` - Inactive"}},"additionalProperties":false,"description":"Event status or trading status changed"},"TradeArt.TradeArtApi.Contracts.DeltaMessage.Enums.DeltaType":{"enum":[0,1,2,3,4,5,6,7],"type":"integer","description":"Known types of deltas\n\n* `0` - None\n* `1` - EventStatusChanged\n* `2` - EventChanged\n* `3` - MarketChanged\n* `4` - ScoreboardChanged\n* `5` - BetCancel\n* `6` - EventSnapshot\n* `7` - MarketsChanged","format":"int32"},"TradeArt.TradeArtApi.Contracts.DeltaMessage.Enums.EventStatus":{"enum":[0,1,2,3,4,5,6,7,8,9,10],"type":"integer","description":"Status of event\n\n* `0` - Unknown\n* `1` - Planned\n* `2` - SoonInPlay\n* `3` - Live\n* `4` - Completed\n* `5` - Cancelled\n* `6` - CoverageLost\n* `7` - Closed\n* `8` - Suspended\n* `9` - Postponed\n* `10` - Abandoned","format":"int32"},"TradeArt.TradeArtApi.Contracts.DeltaMessage.Enums.TradingStatus":{"enum":[0,1,2,3],"type":"integer","description":"Status of trading\n\n* `0` - Open\n* `1` - Suspended\n* `2` - Closed\n* `3` - Inactive","format":"int32"}}}}
```

## The TradeArt.TradeArtApi.Contracts.DeltaMessage.Delta.EventChangedDeltaViewModelV2 object

```json
{"openapi":"3.0.4","info":{"title":"[T728-STAGE] Odds88 API","version":"v1"},"components":{"schemas":{"TradeArt.TradeArtApi.Contracts.DeltaMessage.Delta.EventChangedDeltaViewModelV2":{"type":"object","properties":{"type":{"allOf":[{"$ref":"#/components/schemas/TradeArt.TradeArtApi.Contracts.DeltaMessage.Enums.DeltaType"}],"description":"Type of delta\n\n* `0` - None\n* `1` - EventStatusChanged\n* `2` - EventChanged\n* `3` - MarketChanged\n* `4` - ScoreboardChanged\n* `5` - BetCancel\n* `6` - EventSnapshot\n* `7` - MarketsChanged"},"eventId":{"type":"integer","description":"Id of changed event","format":"int64"},"version":{"type":"integer","description":"Version of feed state","format":"int64"},"correlationId":{"type":"string","description":"Correlation id of the message to trace back.","nullable":true},"creationTime":{"type":"string","description":"Captures the timestamp the dto was created.","format":"date-time"},"sportId":{"type":"integer","description":"Id of the Sport","format":"int64"},"locationId":{"type":"integer","description":"Id of the Location","format":"int64"},"leagueId":{"type":"integer","description":"Id of the League","format":"int64"},"updateSequence":{"type":"integer","description":"Event delta sequence.\nIncremented with each sent delta.","format":"int64"},"lastUpdatedTime":{"type":"integer","description":"Event update time.\nIncremented with each valuable update.","format":"int64"},"eventInfo":{"allOf":[{"$ref":"#/components/schemas/TradeArt.TradeArtApi.Contracts.DeltaMessage.EventInfoViewModelV2"}],"description":"Updated event info","nullable":true}},"additionalProperties":false,"description":"Event info has been changed or new event added"},"TradeArt.TradeArtApi.Contracts.DeltaMessage.Enums.DeltaType":{"enum":[0,1,2,3,4,5,6,7],"type":"integer","description":"Known types of deltas\n\n* `0` - None\n* `1` - EventStatusChanged\n* `2` - EventChanged\n* `3` - MarketChanged\n* `4` - ScoreboardChanged\n* `5` - BetCancel\n* `6` - EventSnapshot\n* `7` - MarketsChanged","format":"int32"},"TradeArt.TradeArtApi.Contracts.DeltaMessage.EventInfoViewModelV2":{"type":"object","properties":{"id":{"type":"integer","description":"TradeArt event id.","format":"int64"},"name":{"type":"string","description":"Event name.","nullable":true},"status":{"allOf":[{"$ref":"#/components/schemas/TradeArt.TradeArtApi.Contracts.DeltaMessage.Enums.EventStatus"}],"description":"Event status representing current status of the match.\n\n* `0` - Unknown\n* `1` - Planned\n* `2` - SoonInPlay\n* `3` - Live\n* `4` - Completed\n* `5` - Cancelled\n* `6` - CoverageLost\n* `7` - Closed\n* `8` - Suspended\n* `9` - Postponed\n* `10` - Abandoned"},"tradingStatus":{"allOf":[{"$ref":"#/components/schemas/TradeArt.TradeArtApi.Contracts.DeltaMessage.Enums.TradingStatus"}],"description":"Status of trading for the event showing how it should be processed.\n\n* `0` - Open\n* `1` - Suspended\n* `2` - Closed\n* `3` - Inactive"},"statusDescription":{"type":"string","description":"Free text event status description (optional).","nullable":true},"country":{"allOf":[{"$ref":"#/components/schemas/TradeArt.TradeArtApi.Contracts.DeltaMessage.ReferenceViewModelV2"}],"description":"Id and Name of event's country.","nullable":true},"sport":{"allOf":[{"$ref":"#/components/schemas/TradeArt.TradeArtApi.Contracts.DeltaMessage.ReferenceViewModelV2"}],"description":"Id and Name of event's sport.","nullable":true},"competition":{"allOf":[{"$ref":"#/components/schemas/TradeArt.TradeArtApi.Contracts.DeltaMessage.ReferenceViewModelV2"}],"description":"Id and Name of event's competition.","nullable":true},"season":{"allOf":[{"$ref":"#/components/schemas/TradeArt.TradeArtApi.Contracts.DeltaMessage.ReferenceViewModelV2"}],"description":"Id and Name of event's season. Can be null for not-outright events.","nullable":true},"competitors":{"type":"array","items":{"$ref":"#/components/schemas/TradeArt.TradeArtApi.Contracts.DeltaMessage.ReferenceViewModelV2"},"description":"Ids and Names of event's competitors.","nullable":true},"startTime":{"type":"string","description":"Start time of the event. Can be null.","format":"date-time","nullable":true},"isOutright":{"type":"boolean","description":"Flag which indicates that event is outright."},"customDisplayData":{"type":"object","additionalProperties":{"type":"string"},"description":"Custom display parameters of the event","nullable":true},"isBetBuilderSupported":{"type":"boolean","description":"Indicates whether this selection can be used in Bet Builder"},"mappingInfo":{"type":"array","items":{"$ref":"#/components/schemas/TradeArt.TradeArtApi.Contracts.DeltaMessage.MappingViewModel"},"description":"Represents information about external feeds","nullable":true}},"additionalProperties":false,"description":"Information about event (sport, country, statuses etc.)"},"TradeArt.TradeArtApi.Contracts.DeltaMessage.Enums.EventStatus":{"enum":[0,1,2,3,4,5,6,7,8,9,10],"type":"integer","description":"Status of event\n\n* `0` - Unknown\n* `1` - Planned\n* `2` - SoonInPlay\n* `3` - Live\n* `4` - Completed\n* `5` - Cancelled\n* `6` - CoverageLost\n* `7` - Closed\n* `8` - Suspended\n* `9` - Postponed\n* `10` - Abandoned","format":"int32"},"TradeArt.TradeArtApi.Contracts.DeltaMessage.Enums.TradingStatus":{"enum":[0,1,2,3],"type":"integer","description":"Status of trading\n\n* `0` - Open\n* `1` - Suspended\n* `2` - Closed\n* `3` - Inactive","format":"int32"},"TradeArt.TradeArtApi.Contracts.DeltaMessage.ReferenceViewModelV2":{"type":"object","properties":{"id":{"type":"integer","description":"Id of the referenced entity","format":"int64"},"name":{"type":"string","description":"Name of the referenced entity","nullable":true}},"additionalProperties":false,"description":"Contains reference data for entity"},"TradeArt.TradeArtApi.Contracts.DeltaMessage.MappingViewModel":{"type":"object","properties":{"feedId":{"type":"integer","description":"External Feed Id","format":"int32"},"id":{"type":"string","description":"External Event Id","nullable":true}},"additionalProperties":false,"description":"External mappings info"}}}}
```

## The TradeArt.TradeArtApi.Contracts.DeltaMessage.Delta.ScoreboardChangedDeltaViewModelV2 object

```json
{"openapi":"3.0.4","info":{"title":"[T728-STAGE] Odds88 API","version":"v1"},"components":{"schemas":{"TradeArt.TradeArtApi.Contracts.DeltaMessage.Delta.ScoreboardChangedDeltaViewModelV2":{"type":"object","properties":{"type":{"allOf":[{"$ref":"#/components/schemas/TradeArt.TradeArtApi.Contracts.DeltaMessage.Enums.DeltaType"}],"description":"Type of delta\n\n* `0` - None\n* `1` - EventStatusChanged\n* `2` - EventChanged\n* `3` - MarketChanged\n* `4` - ScoreboardChanged\n* `5` - BetCancel\n* `6` - EventSnapshot\n* `7` - MarketsChanged"},"eventId":{"type":"integer","description":"Id of changed event","format":"int64"},"version":{"type":"integer","description":"Version of feed state","format":"int64"},"correlationId":{"type":"string","description":"Correlation id of the message to trace back.","nullable":true},"creationTime":{"type":"string","description":"Captures the timestamp the dto was created.","format":"date-time"},"sportId":{"type":"integer","description":"Id of the Sport","format":"int64"},"locationId":{"type":"integer","description":"Id of the Location","format":"int64"},"leagueId":{"type":"integer","description":"Id of the League","format":"int64"},"updateSequence":{"type":"integer","description":"Event delta sequence.\nIncremented with each sent delta.","format":"int64"},"lastUpdatedTime":{"type":"integer","description":"Event update time.\nIncremented with each valuable update.","format":"int64"},"scoreboard":{"allOf":[{"$ref":"#/components/schemas/TradeArt.TradeArtApi.Contracts.DeltaMessage.Scoreboard.ScoreboardViewModel"}],"description":"Scoreboard of event","nullable":true}},"additionalProperties":false,"description":"Event score or time changed"},"TradeArt.TradeArtApi.Contracts.DeltaMessage.Enums.DeltaType":{"enum":[0,1,2,3,4,5,6,7],"type":"integer","description":"Known types of deltas\n\n* `0` - None\n* `1` - EventStatusChanged\n* `2` - EventChanged\n* `3` - MarketChanged\n* `4` - ScoreboardChanged\n* `5` - BetCancel\n* `6` - EventSnapshot\n* `7` - MarketsChanged","format":"int32"},"TradeArt.TradeArtApi.Contracts.DeltaMessage.Scoreboard.ScoreboardViewModel":{"type":"object","properties":{"time":{"type":"integer","description":"Current time of event (in seconds)","format":"int32"},"results":{"type":"array","items":{"$ref":"#/components/schemas/TradeArt.TradeArtApi.Contracts.DeltaMessage.Scoreboard.ResultViewModel"},"description":"Current event results per competitor (in seconds)","nullable":true},"periods":{"type":"array","items":{"$ref":"#/components/schemas/TradeArt.TradeArtApi.Contracts.DeltaMessage.Scoreboard.PeriodViewModel"},"description":"Current event periods with results and incidents","nullable":true},"incidents":{"type":"array","items":{"$ref":"#/components/schemas/TradeArt.TradeArtApi.Contracts.DeltaMessage.Scoreboard.IncidentCountViewModel"},"description":"Current event incident summary","nullable":true},"currentPeriodId":{"type":"integer","description":"Internal id of current period","format":"int32"},"lastUpdateTime":{"type":"string","description":"Last update time of the scoreboard","format":"date-time"},"homeGameScore":{"type":"string","description":"Current home team game score","nullable":true},"awayGameScore":{"type":"string","description":"Current away team game score","nullable":true},"extraData":{"type":"object","additionalProperties":{"type":"string"},"description":"Extra parameters of the score","nullable":true}},"additionalProperties":false,"description":"Represents event's scoreboard"},"TradeArt.TradeArtApi.Contracts.DeltaMessage.Scoreboard.ResultViewModel":{"type":"object","properties":{"competitorPosition":{"type":"integer","description":"Competitor position (e.g. 1 - Home, 2 - Away)","format":"int32"},"value":{"type":"string","description":"Result value","nullable":true}},"additionalProperties":false,"description":"Represents scoreboard result"},"TradeArt.TradeArtApi.Contracts.DeltaMessage.Scoreboard.PeriodViewModel":{"type":"object","properties":{"id":{"type":"integer","description":"Period Id","format":"int32"},"isFinished":{"type":"boolean","description":"Is period finished?"},"incidents":{"type":"array","items":{"$ref":"#/components/schemas/TradeArt.TradeArtApi.Contracts.DeltaMessage.Scoreboard.IncidentViewModel"},"description":"Incidents occurred in the period","nullable":true},"results":{"type":"array","items":{"$ref":"#/components/schemas/TradeArt.TradeArtApi.Contracts.DeltaMessage.Scoreboard.ResultViewModel"},"description":"Results of the period","nullable":true},"order":{"type":"integer","description":"The position of this period in a sorted sequence.","format":"int32"},"subPeriods":{"type":"array","items":{"$ref":"#/components/schemas/TradeArt.TradeArtApi.Contracts.DeltaMessage.Scoreboard.SubPeriodViewModel"},"description":"Sub periods of the period","nullable":true}},"additionalProperties":false,"description":"Represents period of the event"},"TradeArt.TradeArtApi.Contracts.DeltaMessage.Scoreboard.IncidentViewModel":{"type":"object","properties":{"type":{"type":"integer","description":"Incident type","format":"int32"},"time":{"type":"integer","description":"Event time","format":"int32"},"competitorPosition":{"type":"integer","description":"Index of the competitor in the EventInfo.Competitors array","format":"int32"}},"additionalProperties":false,"description":"Represents incident information"},"TradeArt.TradeArtApi.Contracts.DeltaMessage.Scoreboard.SubPeriodViewModel":{"type":"object","properties":{"isFinished":{"type":"boolean","description":"Is sub period finished?"},"results":{"type":"array","items":{"$ref":"#/components/schemas/TradeArt.TradeArtApi.Contracts.DeltaMessage.Scoreboard.ResultViewModel"},"description":"Results of the sub period","nullable":true},"order":{"type":"integer","description":"The position of this sub period in a sorted sequence.","format":"int32"}},"additionalProperties":false,"description":"Represents sub period of the event period"},"TradeArt.TradeArtApi.Contracts.DeltaMessage.Scoreboard.IncidentCountViewModel":{"type":"object","properties":{"type":{"type":"integer","description":"Incident type","format":"int32"},"competitorPosition":{"type":"integer","description":"Competitor position (e.g. 1 - Home, 2 - Away)","format":"int32"},"count":{"type":"integer","description":"Incident count","format":"int32"}},"additionalProperties":false,"description":"Incident count by type and competitor"}}}}
```

## The TradeArt.TradeArtApi.Contracts.DeltaMessage.Delta.BetCancelDeltaViewModelV2 object

```json
{"openapi":"3.0.4","info":{"title":"[T728-STAGE] Odds88 API","version":"v1"},"components":{"schemas":{"TradeArt.TradeArtApi.Contracts.DeltaMessage.Delta.BetCancelDeltaViewModelV2":{"type":"object","properties":{"type":{"allOf":[{"$ref":"#/components/schemas/TradeArt.TradeArtApi.Contracts.DeltaMessage.Enums.DeltaType"}],"description":"Type of delta\n\n* `0` - None\n* `1` - EventStatusChanged\n* `2` - EventChanged\n* `3` - MarketChanged\n* `4` - ScoreboardChanged\n* `5` - BetCancel\n* `6` - EventSnapshot\n* `7` - MarketsChanged"},"eventId":{"type":"integer","description":"Id of changed event","format":"int64"},"version":{"type":"integer","description":"Version of feed state","format":"int64"},"correlationId":{"type":"string","description":"Correlation id of the message to trace back.","nullable":true},"creationTime":{"type":"string","description":"Captures the timestamp the dto was created.","format":"date-time"},"sportId":{"type":"integer","description":"Id of the Sport","format":"int64"},"locationId":{"type":"integer","description":"Id of the Location","format":"int64"},"leagueId":{"type":"integer","description":"Id of the League","format":"int64"},"updateSequence":{"type":"integer","description":"Event delta sequence.\nIncremented with each sent delta.","format":"int64"},"lastUpdatedTime":{"type":"integer","description":"Event update time.\nIncremented with each valuable update.","format":"int64"},"marketId":{"type":"integer","description":"Market bets on which should be voided","format":"int64"},"from":{"type":"string","description":"Time from which bets should be voided. Equals DateTime.MinValue if no lower bound provided","format":"date-time"},"to":{"type":"string","description":"Time to which bets should be voided. Equals DateTime.MaxValue if no upper bound provided","format":"date-time"},"isRolledBack":{"type":"boolean","description":"Flag indicating whether current Delta rollback previous cancellation for this Market and lying within same From-To range"}},"additionalProperties":false,"description":"Bets placed within period of time must be voided"},"TradeArt.TradeArtApi.Contracts.DeltaMessage.Enums.DeltaType":{"enum":[0,1,2,3,4,5,6,7],"type":"integer","description":"Known types of deltas\n\n* `0` - None\n* `1` - EventStatusChanged\n* `2` - EventChanged\n* `3` - MarketChanged\n* `4` - ScoreboardChanged\n* `5` - BetCancel\n* `6` - EventSnapshot\n* `7` - MarketsChanged","format":"int32"}}}}
```

## The TradeArt.TradeArtApi.Contracts.DeltaMessage.Delta.EventSnapshotDeltaViewModelV2 object

```json
{"openapi":"3.0.4","info":{"title":"[T728-STAGE] Odds88 API","version":"v1"},"components":{"schemas":{"TradeArt.TradeArtApi.Contracts.DeltaMessage.Delta.EventSnapshotDeltaViewModelV2":{"type":"object","properties":{"type":{"allOf":[{"$ref":"#/components/schemas/TradeArt.TradeArtApi.Contracts.DeltaMessage.Enums.DeltaType"}],"description":"Type of delta\n\n* `0` - None\n* `1` - EventStatusChanged\n* `2` - EventChanged\n* `3` - MarketChanged\n* `4` - ScoreboardChanged\n* `5` - BetCancel\n* `6` - EventSnapshot\n* `7` - MarketsChanged"},"eventId":{"type":"integer","description":"Id of changed event","format":"int64"},"version":{"type":"integer","description":"Version of feed state","format":"int64"},"correlationId":{"type":"string","description":"Correlation id of the message to trace back.","nullable":true},"creationTime":{"type":"string","description":"Captures the timestamp the dto was created.","format":"date-time"},"sportId":{"type":"integer","description":"Id of the Sport","format":"int64"},"locationId":{"type":"integer","description":"Id of the Location","format":"int64"},"leagueId":{"type":"integer","description":"Id of the League","format":"int64"},"updateSequence":{"type":"integer","description":"Event delta sequence.\nIncremented with each sent delta.","format":"int64"},"lastUpdatedTime":{"type":"integer","description":"Event update time.\nIncremented with each valuable update.","format":"int64"},"eventInfo":{"allOf":[{"$ref":"#/components/schemas/TradeArt.TradeArtApi.Contracts.DeltaMessage.EventInfoViewModelV2"}],"description":"Fixture info containing basic event information.","nullable":true},"markets":{"type":"array","items":{"$ref":"#/components/schemas/TradeArt.TradeArtApi.Contracts.DeltaMessage.MarketViewModelV2"},"description":"Markets of the event.","nullable":true},"scoreboard":{"allOf":[{"$ref":"#/components/schemas/TradeArt.TradeArtApi.Contracts.DeltaMessage.Scoreboard.ScoreboardViewModel"}],"description":"Scoreboard of the event. Can be null.","nullable":true},"betCancellations":{"type":"array","items":{"$ref":"#/components/schemas/TradeArt.TradeArtApi.Contracts.DeltaMessage.BetCancellationViewModel"},"description":"List of bet cancellations on this event and certain market received from BetRadar. Can be null.","nullable":true}},"additionalProperties":false,"description":"Full snapshot of event data"},"TradeArt.TradeArtApi.Contracts.DeltaMessage.Enums.DeltaType":{"enum":[0,1,2,3,4,5,6,7],"type":"integer","description":"Known types of deltas\n\n* `0` - None\n* `1` - EventStatusChanged\n* `2` - EventChanged\n* `3` - MarketChanged\n* `4` - ScoreboardChanged\n* `5` - BetCancel\n* `6` - EventSnapshot\n* `7` - MarketsChanged","format":"int32"},"TradeArt.TradeArtApi.Contracts.DeltaMessage.EventInfoViewModelV2":{"type":"object","properties":{"id":{"type":"integer","description":"TradeArt event id.","format":"int64"},"name":{"type":"string","description":"Event name.","nullable":true},"status":{"allOf":[{"$ref":"#/components/schemas/TradeArt.TradeArtApi.Contracts.DeltaMessage.Enums.EventStatus"}],"description":"Event status representing current status of the match.\n\n* `0` - Unknown\n* `1` - Planned\n* `2` - SoonInPlay\n* `3` - Live\n* `4` - Completed\n* `5` - Cancelled\n* `6` - CoverageLost\n* `7` - Closed\n* `8` - Suspended\n* `9` - Postponed\n* `10` - Abandoned"},"tradingStatus":{"allOf":[{"$ref":"#/components/schemas/TradeArt.TradeArtApi.Contracts.DeltaMessage.Enums.TradingStatus"}],"description":"Status of trading for the event showing how it should be processed.\n\n* `0` - Open\n* `1` - Suspended\n* `2` - Closed\n* `3` - Inactive"},"statusDescription":{"type":"string","description":"Free text event status description (optional).","nullable":true},"country":{"allOf":[{"$ref":"#/components/schemas/TradeArt.TradeArtApi.Contracts.DeltaMessage.ReferenceViewModelV2"}],"description":"Id and Name of event's country.","nullable":true},"sport":{"allOf":[{"$ref":"#/components/schemas/TradeArt.TradeArtApi.Contracts.DeltaMessage.ReferenceViewModelV2"}],"description":"Id and Name of event's sport.","nullable":true},"competition":{"allOf":[{"$ref":"#/components/schemas/TradeArt.TradeArtApi.Contracts.DeltaMessage.ReferenceViewModelV2"}],"description":"Id and Name of event's competition.","nullable":true},"season":{"allOf":[{"$ref":"#/components/schemas/TradeArt.TradeArtApi.Contracts.DeltaMessage.ReferenceViewModelV2"}],"description":"Id and Name of event's season. Can be null for not-outright events.","nullable":true},"competitors":{"type":"array","items":{"$ref":"#/components/schemas/TradeArt.TradeArtApi.Contracts.DeltaMessage.ReferenceViewModelV2"},"description":"Ids and Names of event's competitors.","nullable":true},"startTime":{"type":"string","description":"Start time of the event. Can be null.","format":"date-time","nullable":true},"isOutright":{"type":"boolean","description":"Flag which indicates that event is outright."},"customDisplayData":{"type":"object","additionalProperties":{"type":"string"},"description":"Custom display parameters of the event","nullable":true},"isBetBuilderSupported":{"type":"boolean","description":"Indicates whether this selection can be used in Bet Builder"},"mappingInfo":{"type":"array","items":{"$ref":"#/components/schemas/TradeArt.TradeArtApi.Contracts.DeltaMessage.MappingViewModel"},"description":"Represents information about external feeds","nullable":true}},"additionalProperties":false,"description":"Information about event (sport, country, statuses etc.)"},"TradeArt.TradeArtApi.Contracts.DeltaMessage.Enums.EventStatus":{"enum":[0,1,2,3,4,5,6,7,8,9,10],"type":"integer","description":"Status of event\n\n* `0` - Unknown\n* `1` - Planned\n* `2` - SoonInPlay\n* `3` - Live\n* `4` - Completed\n* `5` - Cancelled\n* `6` - CoverageLost\n* `7` - Closed\n* `8` - Suspended\n* `9` - Postponed\n* `10` - Abandoned","format":"int32"},"TradeArt.TradeArtApi.Contracts.DeltaMessage.Enums.TradingStatus":{"enum":[0,1,2,3],"type":"integer","description":"Status of trading\n\n* `0` - Open\n* `1` - Suspended\n* `2` - Closed\n* `3` - Inactive","format":"int32"},"TradeArt.TradeArtApi.Contracts.DeltaMessage.ReferenceViewModelV2":{"type":"object","properties":{"id":{"type":"integer","description":"Id of the referenced entity","format":"int64"},"name":{"type":"string","description":"Name of the referenced entity","nullable":true}},"additionalProperties":false,"description":"Contains reference data for entity"},"TradeArt.TradeArtApi.Contracts.DeltaMessage.MappingViewModel":{"type":"object","properties":{"feedId":{"type":"integer","description":"External Feed Id","format":"int32"},"id":{"type":"string","description":"External Event Id","nullable":true}},"additionalProperties":false,"description":"External mappings info"},"TradeArt.TradeArtApi.Contracts.DeltaMessage.MarketViewModelV2":{"type":"object","properties":{"id":{"type":"integer","description":"Market Id","format":"int64"},"name":{"type":"string","description":"Market name","nullable":true},"tradingStatus":{"allOf":[{"$ref":"#/components/schemas/TradeArt.TradeArtApi.Contracts.DeltaMessage.Enums.TradingStatus"}],"description":"Market trading status\n\n* `0` - Open\n* `1` - Suspended\n* `2` - Closed\n* `3` - Inactive"},"selections":{"type":"array","items":{"$ref":"#/components/schemas/TradeArt.TradeArtApi.Contracts.DeltaMessage.SelectionViewModelV2"},"description":"Market selections","nullable":true},"type":{"type":"integer","description":"Market type Id","format":"int64"},"isBestLine":{"type":"boolean","description":"Is the main market?"},"parameters":{"type":"object","additionalProperties":{"type":"string"},"description":"Parameters of market. i.e. hcp = 2.5, total=1.5","nullable":true},"extraParameters":{"type":"object","additionalProperties":{"type":"string"},"description":"Additional market information (like score = 1:0)","nullable":true},"isBetBuilderSupported":{"type":"boolean","description":"Indicates whether this selection can be used in Bet Builder"}},"additionalProperties":false,"description":"Represents market data"},"TradeArt.TradeArtApi.Contracts.DeltaMessage.SelectionViewModelV2":{"type":"object","properties":{"id":{"type":"integer","description":"Selection Id","format":"int64"},"name":{"type":"string","description":"Selection name","nullable":true},"probability":{"type":"number","description":"Selection probability","format":"float","nullable":true},"price":{"type":"number","description":"Selection odds","format":"float","nullable":true},"originalPrice":{"type":"number","description":"Selection odds","format":"float","nullable":true},"status":{"allOf":[{"$ref":"#/components/schemas/TradeArt.TradeArtApi.Contracts.DeltaMessage.Enums.TradingStatus"}],"description":"Trading selection status\n\n* `0` - Open\n* `1` - Suspended\n* `2` - Closed\n* `3` - Inactive"},"settlement":{"allOf":[{"$ref":"#/components/schemas/TradeArt.TradeArtApi.Contracts.DeltaMessage.Enums.SettlementResult"}],"description":"Settlement result of the selection\n\n* `0` - None\n* `1` - Refund\n* `2` - Lose\n* `3` - Win\n* `4` - HalfLose\n* `5` - HalfWin"},"deadHeatFactor":{"type":"number","description":"Dead heat factor is a floating point number used when there is a tie in outrights","format":"double","nullable":true},"extraParameters":{"type":"object","additionalProperties":{"type":"string"},"description":"Additional selection information","nullable":true},"isBetBuilderSupported":{"type":"boolean","description":"Indicates whether this selection can be used in Bet Builder"},"competitorId":{"type":"integer","description":"Id of the competitor","format":"int64"},"startingPrice":{"type":"number","description":"Starting Price of the selection before turning to in-play.","format":"float","nullable":true}},"additionalProperties":false,"description":"Represents market selection information"},"TradeArt.TradeArtApi.Contracts.DeltaMessage.Enums.SettlementResult":{"enum":[0,1,2,3,4,5],"type":"integer","description":"Status of a selection settlement\n\n* `0` - None\n* `1` - Refund\n* `2` - Lose\n* `3` - Win\n* `4` - HalfLose\n* `5` - HalfWin","format":"int32"},"TradeArt.TradeArtApi.Contracts.DeltaMessage.Scoreboard.ScoreboardViewModel":{"type":"object","properties":{"time":{"type":"integer","description":"Current time of event (in seconds)","format":"int32"},"results":{"type":"array","items":{"$ref":"#/components/schemas/TradeArt.TradeArtApi.Contracts.DeltaMessage.Scoreboard.ResultViewModel"},"description":"Current event results per competitor (in seconds)","nullable":true},"periods":{"type":"array","items":{"$ref":"#/components/schemas/TradeArt.TradeArtApi.Contracts.DeltaMessage.Scoreboard.PeriodViewModel"},"description":"Current event periods with results and incidents","nullable":true},"incidents":{"type":"array","items":{"$ref":"#/components/schemas/TradeArt.TradeArtApi.Contracts.DeltaMessage.Scoreboard.IncidentCountViewModel"},"description":"Current event incident summary","nullable":true},"currentPeriodId":{"type":"integer","description":"Internal id of current period","format":"int32"},"lastUpdateTime":{"type":"string","description":"Last update time of the scoreboard","format":"date-time"},"homeGameScore":{"type":"string","description":"Current home team game score","nullable":true},"awayGameScore":{"type":"string","description":"Current away team game score","nullable":true},"extraData":{"type":"object","additionalProperties":{"type":"string"},"description":"Extra parameters of the score","nullable":true}},"additionalProperties":false,"description":"Represents event's scoreboard"},"TradeArt.TradeArtApi.Contracts.DeltaMessage.Scoreboard.ResultViewModel":{"type":"object","properties":{"competitorPosition":{"type":"integer","description":"Competitor position (e.g. 1 - Home, 2 - Away)","format":"int32"},"value":{"type":"string","description":"Result value","nullable":true}},"additionalProperties":false,"description":"Represents scoreboard result"},"TradeArt.TradeArtApi.Contracts.DeltaMessage.Scoreboard.PeriodViewModel":{"type":"object","properties":{"id":{"type":"integer","description":"Period Id","format":"int32"},"isFinished":{"type":"boolean","description":"Is period finished?"},"incidents":{"type":"array","items":{"$ref":"#/components/schemas/TradeArt.TradeArtApi.Contracts.DeltaMessage.Scoreboard.IncidentViewModel"},"description":"Incidents occurred in the period","nullable":true},"results":{"type":"array","items":{"$ref":"#/components/schemas/TradeArt.TradeArtApi.Contracts.DeltaMessage.Scoreboard.ResultViewModel"},"description":"Results of the period","nullable":true},"order":{"type":"integer","description":"The position of this period in a sorted sequence.","format":"int32"},"subPeriods":{"type":"array","items":{"$ref":"#/components/schemas/TradeArt.TradeArtApi.Contracts.DeltaMessage.Scoreboard.SubPeriodViewModel"},"description":"Sub periods of the period","nullable":true}},"additionalProperties":false,"description":"Represents period of the event"},"TradeArt.TradeArtApi.Contracts.DeltaMessage.Scoreboard.IncidentViewModel":{"type":"object","properties":{"type":{"type":"integer","description":"Incident type","format":"int32"},"time":{"type":"integer","description":"Event time","format":"int32"},"competitorPosition":{"type":"integer","description":"Index of the competitor in the EventInfo.Competitors array","format":"int32"}},"additionalProperties":false,"description":"Represents incident information"},"TradeArt.TradeArtApi.Contracts.DeltaMessage.Scoreboard.SubPeriodViewModel":{"type":"object","properties":{"isFinished":{"type":"boolean","description":"Is sub period finished?"},"results":{"type":"array","items":{"$ref":"#/components/schemas/TradeArt.TradeArtApi.Contracts.DeltaMessage.Scoreboard.ResultViewModel"},"description":"Results of the sub period","nullable":true},"order":{"type":"integer","description":"The position of this sub period in a sorted sequence.","format":"int32"}},"additionalProperties":false,"description":"Represents sub period of the event period"},"TradeArt.TradeArtApi.Contracts.DeltaMessage.Scoreboard.IncidentCountViewModel":{"type":"object","properties":{"type":{"type":"integer","description":"Incident type","format":"int32"},"competitorPosition":{"type":"integer","description":"Competitor position (e.g. 1 - Home, 2 - Away)","format":"int32"},"count":{"type":"integer","description":"Incident count","format":"int32"}},"additionalProperties":false,"description":"Incident count by type and competitor"},"TradeArt.TradeArtApi.Contracts.DeltaMessage.BetCancellationViewModel":{"type":"object","properties":{"marketId":{"type":"integer","description":"Affected MarketId","format":"int64"},"from":{"type":"string","description":"Cancel bets placed starting From this date. Equals DateTime.MinValue if no lower bound provided","format":"date-time"},"to":{"type":"string","description":"Cancel bets placed starting To this date. Equals DateTime.MaxValue if no upper bound provided","format":"date-time"},"isRolledBack":{"type":"boolean","description":"Flag pointing whether this cancellation should be rolled back"}},"additionalProperties":false,"description":"Information about bet cancellations on certain market between From and To dates"}}}}
```

## The TradeArt.TradeArtApi.Contracts.DeltaMessage.Delta.MarketsChangedDeltaViewModelV2 object

```json
{"openapi":"3.0.4","info":{"title":"[T728-STAGE] Odds88 API","version":"v1"},"components":{"schemas":{"TradeArt.TradeArtApi.Contracts.DeltaMessage.Delta.MarketsChangedDeltaViewModelV2":{"type":"object","properties":{"type":{"allOf":[{"$ref":"#/components/schemas/TradeArt.TradeArtApi.Contracts.DeltaMessage.Enums.DeltaType"}],"description":"Type of delta\n\n* `0` - None\n* `1` - EventStatusChanged\n* `2` - EventChanged\n* `3` - MarketChanged\n* `4` - ScoreboardChanged\n* `5` - BetCancel\n* `6` - EventSnapshot\n* `7` - MarketsChanged"},"eventId":{"type":"integer","description":"Id of changed event","format":"int64"},"version":{"type":"integer","description":"Version of feed state","format":"int64"},"correlationId":{"type":"string","description":"Correlation id of the message to trace back.","nullable":true},"creationTime":{"type":"string","description":"Captures the timestamp the dto was created.","format":"date-time"},"sportId":{"type":"integer","description":"Id of the Sport","format":"int64"},"locationId":{"type":"integer","description":"Id of the Location","format":"int64"},"leagueId":{"type":"integer","description":"Id of the League","format":"int64"},"updateSequence":{"type":"integer","description":"Event delta sequence.\nIncremented with each sent delta.","format":"int64"},"lastUpdatedTime":{"type":"integer","description":"Event update time.\nIncremented with each valuable update.","format":"int64"},"markets":{"type":"array","items":{"$ref":"#/components/schemas/TradeArt.TradeArtApi.Contracts.DeltaMessage.MarketViewModelV2"},"description":"Updated markets","nullable":true}},"additionalProperties":false,"description":"New markets added or odds changed"},"TradeArt.TradeArtApi.Contracts.DeltaMessage.Enums.DeltaType":{"enum":[0,1,2,3,4,5,6,7],"type":"integer","description":"Known types of deltas\n\n* `0` - None\n* `1` - EventStatusChanged\n* `2` - EventChanged\n* `3` - MarketChanged\n* `4` - ScoreboardChanged\n* `5` - BetCancel\n* `6` - EventSnapshot\n* `7` - MarketsChanged","format":"int32"},"TradeArt.TradeArtApi.Contracts.DeltaMessage.MarketViewModelV2":{"type":"object","properties":{"id":{"type":"integer","description":"Market Id","format":"int64"},"name":{"type":"string","description":"Market name","nullable":true},"tradingStatus":{"allOf":[{"$ref":"#/components/schemas/TradeArt.TradeArtApi.Contracts.DeltaMessage.Enums.TradingStatus"}],"description":"Market trading status\n\n* `0` - Open\n* `1` - Suspended\n* `2` - Closed\n* `3` - Inactive"},"selections":{"type":"array","items":{"$ref":"#/components/schemas/TradeArt.TradeArtApi.Contracts.DeltaMessage.SelectionViewModelV2"},"description":"Market selections","nullable":true},"type":{"type":"integer","description":"Market type Id","format":"int64"},"isBestLine":{"type":"boolean","description":"Is the main market?"},"parameters":{"type":"object","additionalProperties":{"type":"string"},"description":"Parameters of market. i.e. hcp = 2.5, total=1.5","nullable":true},"extraParameters":{"type":"object","additionalProperties":{"type":"string"},"description":"Additional market information (like score = 1:0)","nullable":true},"isBetBuilderSupported":{"type":"boolean","description":"Indicates whether this selection can be used in Bet Builder"}},"additionalProperties":false,"description":"Represents market data"},"TradeArt.TradeArtApi.Contracts.DeltaMessage.Enums.TradingStatus":{"enum":[0,1,2,3],"type":"integer","description":"Status of trading\n\n* `0` - Open\n* `1` - Suspended\n* `2` - Closed\n* `3` - Inactive","format":"int32"},"TradeArt.TradeArtApi.Contracts.DeltaMessage.SelectionViewModelV2":{"type":"object","properties":{"id":{"type":"integer","description":"Selection Id","format":"int64"},"name":{"type":"string","description":"Selection name","nullable":true},"probability":{"type":"number","description":"Selection probability","format":"float","nullable":true},"price":{"type":"number","description":"Selection odds","format":"float","nullable":true},"originalPrice":{"type":"number","description":"Selection odds","format":"float","nullable":true},"status":{"allOf":[{"$ref":"#/components/schemas/TradeArt.TradeArtApi.Contracts.DeltaMessage.Enums.TradingStatus"}],"description":"Trading selection status\n\n* `0` - Open\n* `1` - Suspended\n* `2` - Closed\n* `3` - Inactive"},"settlement":{"allOf":[{"$ref":"#/components/schemas/TradeArt.TradeArtApi.Contracts.DeltaMessage.Enums.SettlementResult"}],"description":"Settlement result of the selection\n\n* `0` - None\n* `1` - Refund\n* `2` - Lose\n* `3` - Win\n* `4` - HalfLose\n* `5` - HalfWin"},"deadHeatFactor":{"type":"number","description":"Dead heat factor is a floating point number used when there is a tie in outrights","format":"double","nullable":true},"extraParameters":{"type":"object","additionalProperties":{"type":"string"},"description":"Additional selection information","nullable":true},"isBetBuilderSupported":{"type":"boolean","description":"Indicates whether this selection can be used in Bet Builder"},"competitorId":{"type":"integer","description":"Id of the competitor","format":"int64"},"startingPrice":{"type":"number","description":"Starting Price of the selection before turning to in-play.","format":"float","nullable":true}},"additionalProperties":false,"description":"Represents market selection information"},"TradeArt.TradeArtApi.Contracts.DeltaMessage.Enums.SettlementResult":{"enum":[0,1,2,3,4,5],"type":"integer","description":"Status of a selection settlement\n\n* `0` - None\n* `1` - Refund\n* `2` - Lose\n* `3` - Win\n* `4` - HalfLose\n* `5` - HalfWin","format":"int32"}}}}
```


# Delta Feed - Through Kafka

Describes specifics of integration with our Delta feed through Kafka.

{% hint style="warning" %}
Such feed integration requires extra setup and is not available out of the box.
{% endhint %}

This document assumes the client has already reviewed:

* Message types documentation
* Message sequencing rules
* API authentication documentation
* Snapshot endpoint documentation

This page only covers the Kafka protocol layer as an additional transport mechanism over the existing system.

## Overview

The **Odds88 Kafka Gateway** provides an alternative method for consuming the Odds88 odds stream, in addition to the existing socket connection.

The Kafka connection is available in:

* **Stage Environment** – Intended for integration and testing purposes.\
  The stage environment serves data similar in structure and behavior to production.
* **Production Environment** – Live production data.

This document describes the Kafka protocol layer. It assumes the client has already reviewed:

* Message types documentation
* Message sequencing rules
* API authentication flow

## Access & Network Requirements

Before connecting to Kafka, clients must:

1. Provide their **server public IP address(es)** to Odds88.
2. Wait for confirmation that IP whitelisting has been completed.

Only whitelisted IP addresses are allowed to connect.

## Kafka Connection Details

### Bootstrap Server (Stage)

```
kafka-feeds.tradingstage.io:9000
```

{% hint style="warning" %}
Production endpoint will be provided separately.
{% endhint %}

### Security Configuration

* **Security Protocol:** SASL\_SSL
* **SASL Mechanism:** SCRAM-SHA-512
* **Authentication:** Username and Password (provided by Odds88)
* **Encryption:** TLS enabled

Each client will receive:

* Username
* Password
* Dedicated topic
* Dedicated consumer group

{% hint style="warning" %}
The consumer group is assigned per client and cannot be changed.
{% endhint %}

## Topic & Partition Model

* Each client is provided with a **dedicated odds feed topic**.
* The topic contains **a single partition** by default.

### Important Implications

Because the topic has only one partition:

* Only **one active consumer instance** can consume messages at a time.
* Message order is strictly preserved.
* :warning:Parallel consumption is not supported

### High Availability Option

Clients may implement:

* One **primary consumer** (active)
* One **secondary consumer** (standby / backoff mode)

If the primary consumer disconnects, the secondary consumer may take over.

## Offset Management (Optional)

### Manual Offset Commit

We recommend using **manual offset committing** for advanced control.

This ensures that:

* Offsets are committed **only after** the message has been fully processed by the client system.
* If processing fails, the message is not marked as consumed.
* Upon restart, Kafka will redeliver uncommitted messages.

Each message includes a **sequence ID per event**. If the client detects a sequence gap they may call the dedicated API endpoint to fetch a fresh snapshot of the event: This endpoint allows the client to resynchronize event state.

### Automatic Offset Management (not recommended)

Kafka supports automatic offset committing, where the consumer periodically commits the latest processed offset at a defined interval.

When `enable.auto.commit = true`, Kafka will automatically mark messages as consumed after they are polled by the consumer, based on the configured commit interval.

While this simplifies implementation, it introduces certain risks:

* A message may be committed before it has been fully processed by the client system.
* If the client application crashes after the offset is committed but before processing completes, the message will not be redelivered.
* This may lead to data inconsistencies or missed updates.

For this reason, automatic offset management is suitable only when:

* The client system can tolerate occasional message loss, or
* The processing logic is idempotent and capable of handling recovery independently.

For mission-critical odds processing, **manual offset committing is strongly recommended**, as it provides full control over when a message is marked as successfully processed.

## Consumer Configuration

### Sample Configuration (.NET Example)

```csharp
var config = new ConsumerConfig
{
    BootstrapServers = "server address",
    SecurityProtocol = SecurityProtocol.SaslSsl,
    SaslMechanism = SaslMechanism.ScramSha512,
    SaslUsername = "username",
    SaslPassword = "password",
    GroupId = "groupid",
    AutoOffsetReset = AutoOffsetReset.Latest,
    EnableAutoCommit = false
};
```

Notes:

* `AutoOffsetReset = Latest` is recommended.
* Offset reset is only applied when the consumer group connects for the first time or their stored offset is not available anymore.
* After offsets are committed (manually or automatically), reconnections will resume from the last committed offset.

Kafka will continue delivering messages from the point of disconnection.

{% hint style="warning" %}
Messages are retained in the client’s topic for a maximum of **30 minutes**
{% endhint %}

## Data Flow Control API

After successful integration, two API endpoints are provided:

```
PUT /api/KafkaFeed/start
PUT /api/KafkaFeed/stop
```

### Start Endpoint

The client must call:

```
/api/KafkaFeed/start
```

This ensures that data flow to the client's Kafka topic is initiated.

This should be called **once** before starting consumption.

### Stop Endpoint

If the client intends to stop consuming Kafka messages for an extended period, they are advised to call:

```
/api/KafkaFeed/stop
```

This prevents unnecessary data accumulation in the topic.

{% hint style="info" %}
Calling `stop` is not mandatory but considered good practice.\
It should NOT be used for short disconnections or temporary reconnects.
{% endhint %}

## Message Handling

### Compression

All Kafka messages are compressed using **GZIP**.

Upon receiving a message, the client must:

1. Decompress the message using GZIP.
2. Parse the decompressed payload as JSON.
3. Process the message according to documented message types.

### Message Format

After the decompression, message format matches with the format for the latest delta WebSocket stream.

{% content-ref url="/pages/HRy49ilLiWndc5Ia9O41" %}
[Delta Feed Messages](/odds88-client-api/odds88-feeds/delta-feed-new-version/delta-feed-messages)
{% endcontent-ref %}


# Settlement Feed

Contains bet settlement results

```
/feed/settlement/v4?revision=<revision>
```

`revision` - Unix time stamp seconds of the moment, from which you want to get recovery. Can be `0` for initial connection. Max value - 3 days from current time.

If you are using Odds88 risk management endpoint for bet placement, you can connect to our settlement feed to receive the outcome of each bet, once it becomes available.

{% hint style="warning" %}
The stream connection is rate-limited and there can be only 1 active connection at a time.
{% endhint %}

Rate limit configuration is the following:

* Connection attempt without revision - 5 connections per 30 minutes
* Connection attempt with too small revision - 5 connections per 30 minutes
* Connection attempt with proper revision - 5 connections per 5 minutes

**Two additional** rate limits apply to all feeds that use a timestamp as the `revision` parameter. These limits apply specifically to **recovery requests made on reconnection**.

#### 1. Large recoveries (timestamp older than 1 hour)

If a client reconnects and requests recovery from a timestamp more than **1 hour** in the past, the request is subject to a hard limit:

> **Limit:** 5 requests per 30 minutes

#### 2. Small recoveries (timestamp within the last 1 hour)

If a client reconnects and requests recovery from a timestamp within the last hour, the length of the requested recovery period is added to a **leaking bucket**:

| Parameter       | Value                                       |
| --------------- | ------------------------------------------- |
| Bucket capacity | 1 hour (3,600 seconds)                      |
| Leak rate       | 4 seconds drained per 1 second of real time |

Once the bucket is full, further recovery requests are blocked until enough has drained.

#### Practical examples

**✅ Within limits** A client that drops and reconnects every **5 minutes** requesting a **10-minute** recovery will operate well under the limit and notice no impact.

**❌ Will be blocked** A client that reconnects every **5 minutes** requesting a **30-minute** recovery will fill the bucket faster than it can drain, and will eventually be blocked.

#### Summary

Frequent reconnects are fine — as long as the requested recovery window stays **proportionate to the reconnect interval**.

## Message Format

## The Marlin.SportsbetApi.Models.Settlement.SettlementFeedMessageDto object

```json
{"openapi":"3.0.4","info":{"title":"[T728-STAGE] Odds88 API","version":"v1"},"components":{"schemas":{"Marlin.SportsbetApi.Models.Settlement.SettlementFeedMessageDto":{"type":"object","properties":{"pingId":{"type":"string","description":"Message ping id, if the message is a ping","nullable":true},"data":{"allOf":[{"$ref":"#/components/schemas/Marlin.SportsbetApi.Models.Settlement.SettledBetViewModelV3"}],"description":"Message data","nullable":true}},"additionalProperties":false,"description":"Ping message wrapper for Marlin.SportsbetApi.Models.Settlement.SettledBetViewModelV3"},"Marlin.SportsbetApi.Models.Settlement.SettledBetViewModelV3":{"type":"object","properties":{"betId":{"type":"string","description":"Original bet id.","nullable":true},"betSettlement":{"allOf":[{"$ref":"#/components/schemas/Marlin.SportsbetApi.Models.Settlement.SettlementResult"}],"description":"Settlement of the bet.\n\n* `0` - None\n* `1` - Win\n* `2` - Lose\n* `3` - Refund\n* `4` - HalfWin\n* `5` - HalfLose\n* `6` - CashOut\n* `7` - PlaceWin"},"payoutMultiplier":{"type":"number","description":"Multiplier which was applied to the payout.","format":"double"},"isCancelled":{"type":"boolean","description":"Gets whether bet was cancelled or not."},"selections":{"type":"array","items":{"$ref":"#/components/schemas/Marlin.SportsbetApi.Models.Settlement.SettledBetItemViewModel"},"description":"List of bet items for which the bet was places.","nullable":true},"isRejected":{"type":"boolean","description":"Bet rejected flag."},"settlementTime":{"type":"string","description":"Bet settlement timestamp","format":"date-time"},"payout":{"type":"number","description":"Payout calculated from initial amount and settlement.","format":"double"},"partialRefund":{"type":"number","description":"Amount partially refunded (specific to exotic bets).","format":"double"},"settlementVersion":{"type":"integer","description":"Bet-level settlement version, incremented each time the bet is (re)settled.","format":"int32"},"amount":{"allOf":[{"$ref":"#/components/schemas/Marlin.SportsbetApi.Models.Settlement.BetAmountViewModel"}],"description":"Initial amount of the bet.","nullable":true}},"additionalProperties":false,"description":"Represents message about bet settlement."},"Marlin.SportsbetApi.Models.Settlement.SettlementResult":{"enum":[0,1,2,3,4,5,6,7],"type":"integer","description":"Settlement result of the bet.\n\n* `0` - None\n* `1` - Win\n* `2` - Lose\n* `3` - Refund\n* `4` - HalfWin\n* `5` - HalfLose\n* `6` - CashOut\n* `7` - PlaceWin","format":"int32"},"Marlin.SportsbetApi.Models.Settlement.SettledBetItemViewModel":{"type":"object","properties":{"event":{"allOf":[{"$ref":"#/components/schemas/Marlin.SportsbetApi.Models.Settlement.EventInfoViewModel"}],"description":"Event associated with the bet item.","nullable":true},"market":{"allOf":[{"$ref":"#/components/schemas/Marlin.SportsbetApi.Models.Settlement.MarketViewModel"}],"description":"Market associated with the bet item.","nullable":true},"selectionId":{"type":"integer","description":"Id of the selection to which the bet item was placed.","format":"int64"},"competitionId":{"type":"integer","description":"Id of the competition of the associated event.","format":"int64"},"countryId":{"type":"integer","description":"Id of the country of the associated event.","format":"int64"},"sportId":{"type":"integer","description":"Id of the sport of the associated event.","format":"int64"},"settlement":{"allOf":[{"$ref":"#/components/schemas/Marlin.SportsbetApi.Models.Settlement.SettlementInfoViewModel"}],"description":"Bet item settlement details.","nullable":true},"price":{"type":"number","description":"Original price for which the bet was placed.","format":"double","nullable":true},"eachWayPrice":{"allOf":[{"$ref":"#/components/schemas/Marlin.SportsbetApi.Models.Settlement.EachWayPriceModel"}],"description":"Each-Way price details for the bet item.\nWill be null if bet was not placed as Each-Way.","nullable":true},"limitsRatingId":{"type":"integer","description":"Limit id for which the bet was placed.","format":"int64","nullable":true},"limitsFactor":{"type":"number","description":"Factor of the corresponding limit id.","format":"double"},"hasLineDeviation":{"type":"boolean","description":"Gets whether bet has live deviation."},"isOutright":{"type":"boolean","description":"Gets whether bet was placed on outright event."},"version":{"type":"integer","description":"Gets version of the bet item.","format":"int32"},"deadHeatFactor":{"type":"number","description":"Gets dead heat factor of the bet item.","format":"double","nullable":true},"placeDeadHeatFactor":{"type":"number","description":"Gets dead heat factor for place market of the bet item.\nValid for each-way bets.","format":"double","nullable":true},"parameters":{"type":"object","additionalProperties":{"type":"string"},"description":"Gets parameters of the bet item selection.","nullable":true},"manualPrice":{"type":"number","description":"Manual price of the bet.","format":"double","nullable":true},"alternativePrice":{"type":"number","description":"Alternative price of the bet.","format":"double","nullable":true},"type":{"allOf":[{"$ref":"#/components/schemas/Marlin.SportsbetApi.Models.Settlement.BetItemType"}],"description":"Bet item type.\n\n* `1` - Standard\n* `2` - StartingPrice\n* `3` - ToteExotics\n* `4` - FixedExotics\n* `5` - BetBuilder\n* `6` - Pickem\n* `7` - EachWay\n* `8` - ToteSingleRunner"},"betBuilderItems":{"type":"array","items":{"$ref":"#/components/schemas/Marlin.SportsbetApi.Models.Settlement.SettledBetBuilderItemViewModel"},"description":"List of BetBuilder items.","nullable":true}},"additionalProperties":false,"description":"Represents a single bet item."},"Marlin.SportsbetApi.Models.Settlement.EventInfoViewModel":{"type":"object","properties":{"id":{"type":"integer","description":"Id of the event.","format":"int64"},"name":{"type":"string","description":"Name of the event.","nullable":true},"isLive":{"type":"boolean","description":"Whether event is live or prematch."},"startTime":{"type":"string","description":"Event start time (if available).","format":"date-time","nullable":true}},"additionalProperties":false,"description":"Represents event information for bet item."},"Marlin.SportsbetApi.Models.Settlement.MarketViewModel":{"type":"object","properties":{"id":{"type":"integer","description":"Id of the market for the associated bet item.","format":"int64"},"type":{"type":"integer","description":"Type id of the market for the associated bet item.","format":"int64"},"name":{"type":"string","description":"Name of the market for the associated bet item.","nullable":true},"properties":{"type":"object","additionalProperties":{"type":"string"},"description":"Extra properties of the market for the associated bet item.","nullable":true}},"additionalProperties":false,"description":"Represents market information for bet item."},"Marlin.SportsbetApi.Models.Settlement.SettlementInfoViewModel":{"type":"object","properties":{"settlementResult":{"allOf":[{"$ref":"#/components/schemas/Marlin.SportsbetApi.Models.Settlement.SettlementResult"}],"description":"Settlement result of the bet item.\n\n* `0` - None\n* `1` - Win\n* `2` - Lose\n* `3` - Refund\n* `4` - HalfWin\n* `5` - HalfLose\n* `6` - CashOut\n* `7` - PlaceWin"},"settlementTime":{"type":"string","description":"At what time did settlement happen.","format":"date-time","nullable":true},"settlementVersion":{"type":"integer","description":"Version of the settlement in case if bet was resettled.","format":"int32"},"isManualSettlement":{"type":"boolean","description":"Indicates if the settlement was done manually."}},"additionalProperties":false,"description":"Contains information about bet item settlement."},"Marlin.SportsbetApi.Models.Settlement.EachWayPriceModel":{"type":"object","properties":{"win":{"type":"number","description":"Price value for the win market","format":"double","nullable":true},"place":{"type":"number","description":"Price value for the place market","format":"double","nullable":true}},"additionalProperties":false,"description":"Contains information about each-way price of the bet item."},"Marlin.SportsbetApi.Models.Settlement.BetItemType":{"enum":[1,2,3,4,5,6,7,8],"type":"integer","description":"Type of the bet item.\n\n* `1` - Standard\n* `2` - StartingPrice\n* `3` - ToteExotics\n* `4` - FixedExotics\n* `5` - BetBuilder\n* `6` - Pickem\n* `7` - EachWay\n* `8` - ToteSingleRunner","format":"int32"},"Marlin.SportsbetApi.Models.Settlement.SettledBetBuilderItemViewModel":{"type":"object","properties":{"market":{"allOf":[{"$ref":"#/components/schemas/Marlin.SportsbetApi.Models.Settlement.MarketViewModel"}],"description":"Market associated with the BetBuilder item.","nullable":true},"selectionId":{"type":"integer","description":"Id of the selection to which the BetBuilder item was placed.","format":"int64"},"settlement":{"allOf":[{"$ref":"#/components/schemas/Marlin.SportsbetApi.Models.Settlement.SettlementInfoViewModel"}],"description":"Settlement details of the BetBuilder item.","nullable":true}},"additionalProperties":false,"description":"Represents a BetBuilder item."},"Marlin.SportsbetApi.Models.Settlement.BetAmountViewModel":{"type":"object","properties":{"currency":{"type":"string","description":"Currency ticker symbol","nullable":true},"value":{"type":"integer","description":"Amount in local currency","format":"int64"},"precision":{"type":"integer","description":"Precision value for the provided currency","format":"int32"},"placementExchangeRate":{"type":"number","description":"Exchange rate value when the bet is placed","format":"double"},"settlementExchangeRate":{"type":"number","description":"Exchange rate value when the bet is settled","format":"double","nullable":true}},"additionalProperties":false,"description":"Bet amount view model"}}}}
```


# Metadata Feed

Contains updates in the event metadata

```
/feed/metadata?revision={lastUpdatedTime}
```

`revision` - Unix time stamp seconds of the moment, from which you want to get recovery. Can be `0` for initial connection. Max value - 3 days from current time.

The feed contains metadata updates for events.

{% hint style="warning" %}
The stream connection is rate-limited and there can be only 1 active connection at a time.
{% endhint %}

Rate limit configuration is the following:

* Connection attempt without revision - 5 connections per 30 minutes
* Connection attempt with too small revision - 5 connections per 30 minutes
* Connection attempt with proper revision - 5 connections per 5 minutes

**Two additional** rate limits apply to all feeds that use a timestamp as the `revision` parameter. These limits apply specifically to **recovery requests made on reconnection**.

#### 1. Large recoveries (timestamp older than 1 hour)

If a client reconnects and requests recovery from a timestamp more than **1 hour** in the past, the request is subject to a hard limit:

> **Limit:** 5 requests per 30 minutes

#### 2. Small recoveries (timestamp within the last 1 hour)

If a client reconnects and requests recovery from a timestamp within the last hour, the length of the requested recovery period is added to a **leaking bucket**:

| Parameter       | Value                                       |
| --------------- | ------------------------------------------- |
| Bucket capacity | 1 hour (3,600 seconds)                      |
| Leak rate       | 4 seconds drained per 1 second of real time |

Once the bucket is full, further recovery requests are blocked until enough has drained.

#### Practical examples

**✅ Within limits** A client that drops and reconnects every **5 minutes** requesting a **10-minute** recovery will operate well under the limit and notice no impact.

**❌ Will be blocked** A client that reconnects every **5 minutes** requesting a **30-minute** recovery will fill the bucket faster than it can drain, and will eventually be blocked.

#### Summary

Frequent reconnects are fine — as long as the requested recovery window stays **proportionate to the reconnect interval**.

## Message Format


# Translation Change Feed

Contains notification about translation changes

```
/feed/translation?revision={lastUpdatedTime}
```

The feed contains notifications about translation update for different entities.

`revision`- Unix time stamp seconds of the moment, from which you want to get recovery. Can be `0` for initial connection.

{% hint style="warning" %}
The stream connection is rate-limited and there can be only 1 active connection at a time.
{% endhint %}

Rate limit configuration is the following:

* 5 connections per 5 minutes

**Two additional** rate limits apply to all feeds that use a timestamp as the `revision` parameter. These limits apply specifically to **recovery requests made on reconnection**.

#### 1. Large recoveries (timestamp older than 1 hour)

If a client reconnects and requests recovery from a timestamp more than **1 hour** in the past, the request is subject to a hard limit:

> **Limit:** 5 requests per 30 minutes

#### 2. Small recoveries (timestamp within the last 1 hour)

If a client reconnects and requests recovery from a timestamp within the last hour, the length of the requested recovery period is added to a **leaking bucket**:

| Parameter       | Value                                       |
| --------------- | ------------------------------------------- |
| Bucket capacity | 1 hour (3,600 seconds)                      |
| Leak rate       | 4 seconds drained per 1 second of real time |

Once the bucket is full, further recovery requests are blocked until enough has drained.

#### Practical examples

**✅ Within limits** A client that drops and reconnects every **5 minutes** requesting a **10-minute** recovery will operate well under the limit and notice no impact.

**❌ Will be blocked** A client that reconnects every **5 minutes** requesting a **30-minute** recovery will fill the bucket faster than it can drain, and will eventually be blocked.

#### Summary

Frequent reconnects are fine — as long as the requested recovery window stays **proportionate to the reconnect interval**.

## Message Format

You will receive a message that contains the ID of the entity, which translation changed and the type of this entity from following **enumeration**:

0 = Sport

1 = Location

2 = League

3 = Competitor

4 = Market

5 = Selection

6 = Event


# Cashout Feed

Contains real-time updated suggested cashout amounts for bets

```
/feed/cashout/v2?revision=<revision>
```

`revision` - Unix time stamp seconds of the moment, from which you want to get recovery. Can be `0` for initial connection. Max value - 3 days from current time.

The feed contains real-time updated suggested cashout values for bets.

{% hint style="warning" %}
The stream connection is rate-limited and there can be only 1 active connection at a time.
{% endhint %}

Rate limit configuration is the following:

* Connection attempt without revision - 5 connections per 30 minutes
* Connection attempt with too small revision - 5 connections per 30 minutes
* Connection attempt with proper revision - 5 connections per 5 minutes

**Two additional** rate limits apply to all feeds that use a timestamp as the `revision` parameter. These limits apply specifically to **recovery requests made on reconnection**.

#### 1. Large recoveries (timestamp older than 1 hour)

If a client reconnects and requests recovery from a timestamp more than **1 hour** in the past, the request is subject to a hard limit:

> **Limit:** 5 requests per 30 minutes

#### 2. Small recoveries (timestamp within the last 1 hour)

If a client reconnects and requests recovery from a timestamp within the last hour, the length of the requested recovery period is added to a **leaking bucket**:

| Parameter       | Value                                       |
| --------------- | ------------------------------------------- |
| Bucket capacity | 1 hour (3,600 seconds)                      |
| Leak rate       | 4 seconds drained per 1 second of real time |

Once the bucket is full, further recovery requests are blocked until enough has drained.

#### Practical examples

**✅ Within limits** A client that drops and reconnects every **5 minutes** requesting a **10-minute** recovery will operate well under the limit and notice no impact.

**❌ Will be blocked** A client that reconnects every **5 minutes** requesting a **30-minute** recovery will fill the bucket faster than it can drain, and will eventually be blocked.

#### Summary

Frequent reconnects are fine — as long as the requested recovery window stays **proportionate to the reconnect interval**.

## Message Format

## The Marlin.SportsbetApi.Models.Cashout.CashoutFeedMessage object

```json
{"openapi":"3.0.4","info":{"title":"[T728-STAGE] Odds88 API","version":"v1"},"components":{"schemas":{"Marlin.SportsbetApi.Models.Cashout.CashoutFeedMessage":{"type":"object","properties":{"pingId":{"type":"string","description":"Message ping id, if the message is a ping","nullable":true},"data":{"allOf":[{"$ref":"#/components/schemas/Marlin.SportsbetApi.Models.Cashout.CashoutViewModel"}],"description":"Message data","nullable":true}},"additionalProperties":false,"description":"Model representing cashout feed message"},"Marlin.SportsbetApi.Models.Cashout.CashoutViewModel":{"required":["betId","playerId","status","timestamp"],"type":"object","properties":{"playerId":{"type":"string","description":"Player id","nullable":true},"betId":{"type":"string","description":"Bet (request) id","nullable":true},"status":{"allOf":[{"$ref":"#/components/schemas/Marlin.SportsbetApi.Models.Cashout.CashoutStatus"}],"description":"Status of cashout\n\n* `1` - Available\n* `2` - NotSupported\n* `3` - CashedOut"},"reason":{"type":"string","description":"Reason, if the Marlin.SportsbetApi.Models.Cashout.CashoutViewModel.Status is something other than Marlin.SportsbetApi.Models.Cashout.CashoutStatus.Available","nullable":true},"amount":{"allOf":[{"$ref":"#/components/schemas/Marlin.SportsbetApi.Models.Cashout.CashoutAmountViewModel"}],"description":"Amount view model","nullable":true},"timestamp":{"type":"string","description":"Timestamp of the message","format":"date-time"}},"additionalProperties":false,"description":"Model representing cashout"},"Marlin.SportsbetApi.Models.Cashout.CashoutStatus":{"enum":[1,2,3],"type":"integer","description":"Enum representing different cashout statuses\n\n* `1` - Available\n* `2` - NotSupported\n* `3` - CashedOut","format":"int32"},"Marlin.SportsbetApi.Models.Cashout.CashoutAmountViewModel":{"required":["currency","localAmount","precision"],"type":"object","properties":{"localAmount":{"type":"number","description":"Cashout amount","format":"double"},"precision":{"type":"integer","description":"Precision value","format":"int32"},"currency":{"type":"string","description":"Currency ticker symbol","nullable":true}},"additionalProperties":false,"description":"View model representing amount"}}}}
```


# Pick'em Feed

Separate feed for Pick'em markets

```
/feed/pickems?revision={lastUpdatedTime}
```

Contains live sport data updates only for Pick'em markets. Delivered in the form of "deltas" - differences from the previous state.

`revision` - version of last successfully processed delta message. Can be `0` for initial connection.

{% hint style="warning" %}
The stream connection is rate-limited and there can be only 1 active connection at a time.
{% endhint %}

**Limits:**

* connection without revision, 5 connections per 1 hour
* connection with too small revision, 5 connections per 1 hour
* connection with proper revision, 5 connections per 5 minutes


# Pick'em Feed Messages

## Common Fields

Every Pick'em Delta payload has the following fields:

* `type` - int - type of delta message. Possible values are:
  * `1` - Event Status Changed
  * `2` - Event Changed
  * `3` - Event Snapshot
  * `4` - Markets Changed
* `eventId` - int64 - Id of changed sport event
* `sportId` - int64 - Id of a sport to which the affected event belongs
* `locationId` - int64 - Id of a location to which the affected event belongs
* `leagueId` - int64 - Id of a league to which the affected event belongs
* `version` - int64 - version of the message, used for feed recovery
* `creationTime` - date-time - timestamp when the message was created
* `correlationId` - string - GUID which can be used to trace back to the message source
* `isOutright` - boolean - whether the event is outright
* `updateSequence` - int64 - event update sequence. Incremented with each sent delta
* `lastUpdatedTime` - int64 - Unix timestamp of the message, used for feed recovery

## Specific Messages

## The TradeArt.TradeArtApi.Contracts.DeltaMessage.Delta.PickemDelta.PickemEventInfoViewModel object

```json
{"openapi":"3.0.4","info":{"title":"[T728-STAGE] Odds88 API","version":"v1"},"components":{"schemas":{"TradeArt.TradeArtApi.Contracts.DeltaMessage.Delta.PickemDelta.PickemEventInfoViewModel":{"type":"object","properties":{"id":{"type":"integer","description":"TradeArt event id.","format":"int64"},"name":{"type":"string","description":"Event name.","nullable":true},"isActive":{"type":"boolean","description":"Whether the event is active"},"country":{"allOf":[{"$ref":"#/components/schemas/TradeArt.TradeArtApi.Contracts.DeltaMessage.ReferenceViewModelV2"}],"description":"Id and Name of event's country.","nullable":true},"sport":{"allOf":[{"$ref":"#/components/schemas/TradeArt.TradeArtApi.Contracts.DeltaMessage.ReferenceViewModelV2"}],"description":"Id and Name of event's sport.","nullable":true},"competition":{"allOf":[{"$ref":"#/components/schemas/TradeArt.TradeArtApi.Contracts.DeltaMessage.ReferenceViewModelV2"}],"description":"Id and Name of event's competition.","nullable":true},"competitors":{"type":"array","items":{"$ref":"#/components/schemas/TradeArt.TradeArtApi.Contracts.DeltaMessage.ReferenceViewModelV2"},"description":"Ids and Names of event's competitors.","nullable":true},"startTime":{"type":"string","description":"Start time of the event. Can be null.","format":"date-time","nullable":true},"season":{"allOf":[{"$ref":"#/components/schemas/TradeArt.TradeArtApi.Contracts.DeltaMessage.ReferenceViewModelV2"}],"description":"Id and Name of event's season. Can be null for not-outright events.","nullable":true},"isOutright":{"type":"boolean","description":"Whether the event is outright"},"customDisplayData":{"type":"object","additionalProperties":{"type":"string"},"description":"Custom display parameters of the event","nullable":true}},"additionalProperties":false,"description":"Information about pickem event (sport, country, statuses etc.)"},"TradeArt.TradeArtApi.Contracts.DeltaMessage.ReferenceViewModelV2":{"type":"object","properties":{"id":{"type":"integer","description":"Id of the referenced entity","format":"int64"},"name":{"type":"string","description":"Name of the referenced entity","nullable":true}},"additionalProperties":false,"description":"Contains reference data for entity"}}}}
```

## The TradeArt.TradeArtApi.Contracts.DeltaMessage.Delta.PickemDelta.PickemEventChangedDeltaViewModel object

```json
{"openapi":"3.0.4","info":{"title":"[T728-STAGE] Odds88 API","version":"v1"},"components":{"schemas":{"TradeArt.TradeArtApi.Contracts.DeltaMessage.Delta.PickemDelta.PickemEventChangedDeltaViewModel":{"type":"object","properties":{"type":{"allOf":[{"$ref":"#/components/schemas/TradeArt.TradeArtApi.Contracts.DeltaMessage.Enums.PickemDeltaType"}],"description":"Captures the type of delta from a list of enums\n\n* `0` - Unknown\n* `1` - EventStatusChanged\n* `2` - EventChanged\n* `3` - EventSnapshot\n* `4` - MarketsChanged"},"eventId":{"type":"integer","description":"Id of the event","format":"int64"},"version":{"type":"integer","description":"Gets or sets delta version","format":"int64"},"correlationId":{"type":"string","description":"Gets or sets the correlation id of the message to trace back.","nullable":true},"creationTime":{"type":"string","description":"Captures the timestamp the dto was created.","format":"date-time"},"sportId":{"type":"integer","description":"Id of the sport","format":"int64"},"locationId":{"type":"integer","description":"Id of the location","format":"int64"},"leagueId":{"type":"integer","description":"Id of the league","format":"int64"},"isOutright":{"type":"boolean","description":"Whether the event is outright"},"updateSequence":{"type":"integer","description":"Event delta sequence.\nIncremented with each sent delta.","format":"int64"},"lastUpdatedTime":{"type":"integer","description":"Event update time.\nIncremented with each valuable update.","format":"int64"},"eventInfo":{"allOf":[{"$ref":"#/components/schemas/TradeArt.TradeArtApi.Contracts.DeltaMessage.Delta.PickemDelta.PickemEventInfoViewModel"}],"description":"Updated event info","nullable":true}},"additionalProperties":false,"description":"Pickem event info has been changed or new event added"},"TradeArt.TradeArtApi.Contracts.DeltaMessage.Enums.PickemDeltaType":{"enum":[0,1,2,3,4],"type":"integer","description":"Known types of deltas\n\n* `0` - Unknown\n* `1` - EventStatusChanged\n* `2` - EventChanged\n* `3` - EventSnapshot\n* `4` - MarketsChanged","format":"int32"},"TradeArt.TradeArtApi.Contracts.DeltaMessage.Delta.PickemDelta.PickemEventInfoViewModel":{"type":"object","properties":{"id":{"type":"integer","description":"TradeArt event id.","format":"int64"},"name":{"type":"string","description":"Event name.","nullable":true},"isActive":{"type":"boolean","description":"Whether the event is active"},"country":{"allOf":[{"$ref":"#/components/schemas/TradeArt.TradeArtApi.Contracts.DeltaMessage.ReferenceViewModelV2"}],"description":"Id and Name of event's country.","nullable":true},"sport":{"allOf":[{"$ref":"#/components/schemas/TradeArt.TradeArtApi.Contracts.DeltaMessage.ReferenceViewModelV2"}],"description":"Id and Name of event's sport.","nullable":true},"competition":{"allOf":[{"$ref":"#/components/schemas/TradeArt.TradeArtApi.Contracts.DeltaMessage.ReferenceViewModelV2"}],"description":"Id and Name of event's competition.","nullable":true},"competitors":{"type":"array","items":{"$ref":"#/components/schemas/TradeArt.TradeArtApi.Contracts.DeltaMessage.ReferenceViewModelV2"},"description":"Ids and Names of event's competitors.","nullable":true},"startTime":{"type":"string","description":"Start time of the event. Can be null.","format":"date-time","nullable":true},"season":{"allOf":[{"$ref":"#/components/schemas/TradeArt.TradeArtApi.Contracts.DeltaMessage.ReferenceViewModelV2"}],"description":"Id and Name of event's season. Can be null for not-outright events.","nullable":true},"isOutright":{"type":"boolean","description":"Whether the event is outright"},"customDisplayData":{"type":"object","additionalProperties":{"type":"string"},"description":"Custom display parameters of the event","nullable":true}},"additionalProperties":false,"description":"Information about pickem event (sport, country, statuses etc.)"},"TradeArt.TradeArtApi.Contracts.DeltaMessage.ReferenceViewModelV2":{"type":"object","properties":{"id":{"type":"integer","description":"Id of the referenced entity","format":"int64"},"name":{"type":"string","description":"Name of the referenced entity","nullable":true}},"additionalProperties":false,"description":"Contains reference data for entity"}}}}
```

## The TradeArt.TradeArtApi.Contracts.DeltaMessage.Delta.PickemDelta.PickemEventSnapshotDeltaViewModel object

```json
{"openapi":"3.0.4","info":{"title":"[T728-STAGE] Odds88 API","version":"v1"},"components":{"schemas":{"TradeArt.TradeArtApi.Contracts.DeltaMessage.Delta.PickemDelta.PickemEventSnapshotDeltaViewModel":{"type":"object","properties":{"type":{"allOf":[{"$ref":"#/components/schemas/TradeArt.TradeArtApi.Contracts.DeltaMessage.Enums.PickemDeltaType"}],"description":"Captures the type of delta from a list of enums\n\n* `0` - Unknown\n* `1` - EventStatusChanged\n* `2` - EventChanged\n* `3` - EventSnapshot\n* `4` - MarketsChanged"},"eventId":{"type":"integer","description":"Id of the event","format":"int64"},"version":{"type":"integer","description":"Gets or sets delta version","format":"int64"},"correlationId":{"type":"string","description":"Gets or sets the correlation id of the message to trace back.","nullable":true},"creationTime":{"type":"string","description":"Captures the timestamp the dto was created.","format":"date-time"},"sportId":{"type":"integer","description":"Id of the sport","format":"int64"},"locationId":{"type":"integer","description":"Id of the location","format":"int64"},"leagueId":{"type":"integer","description":"Id of the league","format":"int64"},"isOutright":{"type":"boolean","description":"Whether the event is outright"},"updateSequence":{"type":"integer","description":"Event delta sequence.\nIncremented with each sent delta.","format":"int64"},"lastUpdatedTime":{"type":"integer","description":"Event update time.\nIncremented with each valuable update.","format":"int64"},"eventInfo":{"allOf":[{"$ref":"#/components/schemas/TradeArt.TradeArtApi.Contracts.DeltaMessage.Delta.PickemDelta.PickemEventInfoViewModel"}],"description":"Fixture info containing basic event information.","nullable":true},"markets":{"type":"array","items":{"$ref":"#/components/schemas/TradeArt.TradeArtApi.Contracts.DeltaMessage.Delta.PickemDelta.PickemMarketViewModel"},"description":"Markets of the event.","nullable":true}},"additionalProperties":false,"description":"Full snapshot of pickem event data"},"TradeArt.TradeArtApi.Contracts.DeltaMessage.Enums.PickemDeltaType":{"enum":[0,1,2,3,4],"type":"integer","description":"Known types of deltas\n\n* `0` - Unknown\n* `1` - EventStatusChanged\n* `2` - EventChanged\n* `3` - EventSnapshot\n* `4` - MarketsChanged","format":"int32"},"TradeArt.TradeArtApi.Contracts.DeltaMessage.Delta.PickemDelta.PickemEventInfoViewModel":{"type":"object","properties":{"id":{"type":"integer","description":"TradeArt event id.","format":"int64"},"name":{"type":"string","description":"Event name.","nullable":true},"isActive":{"type":"boolean","description":"Whether the event is active"},"country":{"allOf":[{"$ref":"#/components/schemas/TradeArt.TradeArtApi.Contracts.DeltaMessage.ReferenceViewModelV2"}],"description":"Id and Name of event's country.","nullable":true},"sport":{"allOf":[{"$ref":"#/components/schemas/TradeArt.TradeArtApi.Contracts.DeltaMessage.ReferenceViewModelV2"}],"description":"Id and Name of event's sport.","nullable":true},"competition":{"allOf":[{"$ref":"#/components/schemas/TradeArt.TradeArtApi.Contracts.DeltaMessage.ReferenceViewModelV2"}],"description":"Id and Name of event's competition.","nullable":true},"competitors":{"type":"array","items":{"$ref":"#/components/schemas/TradeArt.TradeArtApi.Contracts.DeltaMessage.ReferenceViewModelV2"},"description":"Ids and Names of event's competitors.","nullable":true},"startTime":{"type":"string","description":"Start time of the event. Can be null.","format":"date-time","nullable":true},"season":{"allOf":[{"$ref":"#/components/schemas/TradeArt.TradeArtApi.Contracts.DeltaMessage.ReferenceViewModelV2"}],"description":"Id and Name of event's season. Can be null for not-outright events.","nullable":true},"isOutright":{"type":"boolean","description":"Whether the event is outright"},"customDisplayData":{"type":"object","additionalProperties":{"type":"string"},"description":"Custom display parameters of the event","nullable":true}},"additionalProperties":false,"description":"Information about pickem event (sport, country, statuses etc.)"},"TradeArt.TradeArtApi.Contracts.DeltaMessage.ReferenceViewModelV2":{"type":"object","properties":{"id":{"type":"integer","description":"Id of the referenced entity","format":"int64"},"name":{"type":"string","description":"Name of the referenced entity","nullable":true}},"additionalProperties":false,"description":"Contains reference data for entity"},"TradeArt.TradeArtApi.Contracts.DeltaMessage.Delta.PickemDelta.PickemMarketViewModel":{"type":"object","properties":{"id":{"type":"integer","description":"Market Id","format":"int64"},"name":{"type":"string","description":"Market name","nullable":true},"type":{"type":"integer","description":"Market type Id","format":"int64"},"parameters":{"type":"object","additionalProperties":{"type":"string"},"description":"Parameters of market","nullable":true},"lineParameterName":{"type":"string","description":"Market line parameter name","nullable":true},"isActive":{"type":"boolean","description":"Weather event is active"},"selections":{"type":"array","items":{"$ref":"#/components/schemas/TradeArt.TradeArtApi.Contracts.DeltaMessage.Delta.PickemDelta.PickemSelectionViewModel"},"description":"Market selections","nullable":true},"extraParameters":{"type":"object","additionalProperties":{"type":"string"},"description":"Additional market information","nullable":true},"displayOrder":{"type":"integer","description":"Display order","format":"int64"},"contingencyKey":{"type":"array","items":{"type":"string"},"description":"Contingency key","nullable":true},"contingencyScope":{"type":"array","items":{"type":"string"},"description":"Contingency scope","nullable":true}},"additionalProperties":false,"description":"Represents pickem market data"},"TradeArt.TradeArtApi.Contracts.DeltaMessage.Delta.PickemDelta.PickemSelectionViewModel":{"type":"object","properties":{"id":{"type":"integer","description":"Selection Id","format":"int64"},"name":{"type":"string","description":"Selection name","nullable":true},"price":{"type":"number","description":"Selection odds","format":"float"},"probability":{"type":"number","description":"Selection probability","format":"float"},"isActive":{"type":"boolean","description":"Selection Is Active"},"extraParameters":{"type":"object","additionalProperties":{"type":"string"},"description":"Additional selection information","nullable":true},"competitorId":{"type":"integer","description":"Id of the competitor","format":"int64"},"settlement":{"allOf":[{"$ref":"#/components/schemas/TradeArt.TradeArtApi.Contracts.DeltaMessage.Enums.PickemSettlementResult"}],"description":"Settlement result of the selection\n\n* `0` - None\n* `1` - Win\n* `2` - Lose\n* `3` - Refund\n* `4` - HalfWin\n* `5` - HalfLose"},"polarity":{"allOf":[{"$ref":"#/components/schemas/TradeArt.TradeArtApi.Contracts.DeltaMessage.Enums.PickemSelectionPolarity"}],"description":"Polarity of the selection\n\n* `0` - None\n* `1` - Positive\n* `2` - Negative"}},"additionalProperties":false,"description":"Represents market selection information"},"TradeArt.TradeArtApi.Contracts.DeltaMessage.Enums.PickemSettlementResult":{"enum":[0,1,2,3,4,5],"type":"integer","description":"Status of a pickem selection settlement\n\n* `0` - None\n* `1` - Win\n* `2` - Lose\n* `3` - Refund\n* `4` - HalfWin\n* `5` - HalfLose","format":"int32"},"TradeArt.TradeArtApi.Contracts.DeltaMessage.Enums.PickemSelectionPolarity":{"enum":[0,1,2],"type":"integer","description":"Known types of pickem selection polarity\n\n* `0` - None\n* `1` - Positive\n* `2` - Negative","format":"int32"}}}}
```

## The TradeArt.TradeArtApi.Contracts.DeltaMessage.Delta.PickemDelta.PickemMarketViewModel object

```json
{"openapi":"3.0.4","info":{"title":"[T728-STAGE] Odds88 API","version":"v1"},"components":{"schemas":{"TradeArt.TradeArtApi.Contracts.DeltaMessage.Delta.PickemDelta.PickemMarketViewModel":{"type":"object","properties":{"id":{"type":"integer","description":"Market Id","format":"int64"},"name":{"type":"string","description":"Market name","nullable":true},"type":{"type":"integer","description":"Market type Id","format":"int64"},"parameters":{"type":"object","additionalProperties":{"type":"string"},"description":"Parameters of market","nullable":true},"lineParameterName":{"type":"string","description":"Market line parameter name","nullable":true},"isActive":{"type":"boolean","description":"Weather event is active"},"selections":{"type":"array","items":{"$ref":"#/components/schemas/TradeArt.TradeArtApi.Contracts.DeltaMessage.Delta.PickemDelta.PickemSelectionViewModel"},"description":"Market selections","nullable":true},"extraParameters":{"type":"object","additionalProperties":{"type":"string"},"description":"Additional market information","nullable":true},"displayOrder":{"type":"integer","description":"Display order","format":"int64"},"contingencyKey":{"type":"array","items":{"type":"string"},"description":"Contingency key","nullable":true},"contingencyScope":{"type":"array","items":{"type":"string"},"description":"Contingency scope","nullable":true}},"additionalProperties":false,"description":"Represents pickem market data"},"TradeArt.TradeArtApi.Contracts.DeltaMessage.Delta.PickemDelta.PickemSelectionViewModel":{"type":"object","properties":{"id":{"type":"integer","description":"Selection Id","format":"int64"},"name":{"type":"string","description":"Selection name","nullable":true},"price":{"type":"number","description":"Selection odds","format":"float"},"probability":{"type":"number","description":"Selection probability","format":"float"},"isActive":{"type":"boolean","description":"Selection Is Active"},"extraParameters":{"type":"object","additionalProperties":{"type":"string"},"description":"Additional selection information","nullable":true},"competitorId":{"type":"integer","description":"Id of the competitor","format":"int64"},"settlement":{"allOf":[{"$ref":"#/components/schemas/TradeArt.TradeArtApi.Contracts.DeltaMessage.Enums.PickemSettlementResult"}],"description":"Settlement result of the selection\n\n* `0` - None\n* `1` - Win\n* `2` - Lose\n* `3` - Refund\n* `4` - HalfWin\n* `5` - HalfLose"},"polarity":{"allOf":[{"$ref":"#/components/schemas/TradeArt.TradeArtApi.Contracts.DeltaMessage.Enums.PickemSelectionPolarity"}],"description":"Polarity of the selection\n\n* `0` - None\n* `1` - Positive\n* `2` - Negative"}},"additionalProperties":false,"description":"Represents market selection information"},"TradeArt.TradeArtApi.Contracts.DeltaMessage.Enums.PickemSettlementResult":{"enum":[0,1,2,3,4,5],"type":"integer","description":"Status of a pickem selection settlement\n\n* `0` - None\n* `1` - Win\n* `2` - Lose\n* `3` - Refund\n* `4` - HalfWin\n* `5` - HalfLose","format":"int32"},"TradeArt.TradeArtApi.Contracts.DeltaMessage.Enums.PickemSelectionPolarity":{"enum":[0,1,2],"type":"integer","description":"Known types of pickem selection polarity\n\n* `0` - None\n* `1` - Positive\n* `2` - Negative","format":"int32"}}}}
```


