Skip to content

Feed integration

Replication Protocol

For reliable data delivery, a simple replication protocol is implemented. From an API point of view, it consists of two methods:

  1. get a snapshot for each sport event
  2. get log stream where each log applies some change for specific sport event and it's entities

Snapshot

A snapshot is the current state of a sport event. A snapshot has a version that sequentially progresses as the sport event changes. The version is unique across all sport events and it always ascends. The object of a sport event consists of:

  • fixture - all data on a sport event: status, type, sport, tournament, venue, links to streams, etc.
  • markets - the list of markets with outcomes, odds, and statuses
  • bet_stop - when it's true placing bets on this match is suspended at the moment
  • competitors - a list of participants with their scores (yellow/red cards, points, totals, etc.) in the match
  • game_state - contains all the game state (current period/time/ticker/server/quarter/round/etc. in the match, the number of properties depends on the type of sport) data available for the sport event.
  • extensions - describes additional extensions that could be attached to the sport event (e.g. see Widgets)
An example of a sport event snapshot The output is formatted for readability, in the real response it will be a single line
  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
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 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
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
{
  "sport_event_id": "1a70143e-159e-42d6-8645-97ad190a019f",
  "sport_id": "football",
  "version": "22h2KoCl1uu000004gfQS1",
  "timestamp_ns": 1715069754549926000,
  "event_type": "sport_event_snapshot",
  "payload": {
    "fixture": {
      "type": 0,
      "status": 1,
      "streams": [],
      "sport_id": "football",
      "template": "{$competitor1} vs {$competitor2}",
      "tournament": {
        "id": "betting:17:gin:1c15e2ba-edbc-4776-a702-67eb835cd7c0",
        "name": "U21. Premier League International Cup. Season 2023/2024"
      },
      "competitors": [
        {
          "id": "gin:a35f60db-0695-4f03-852f-e3d983346b16",
          "name": "AD Confianca",
          "side": "home",
          "type": 2,
          "template_position": 1
        },
        {
          "id": "betting:7:sr:competitor:22431",
          "name": "Ypiranga FC",
          "side": "away",
          "type": 2,
          "template_position": 2
        }
      ],
      "live_coverage": false,
      "start_time_ns": 0,
      "updated_at_ns": 0
    },
    "markets": [
      {
        "id": "20",
        "status": 3,
        "odds": [
          {
            "id": "1",
            "value": "1",
            "probability": "0.9",
            "is_active": false,
            "template": "{$competitor1}",
            "status": 1
          },
          {
            "id": "2",
            "value": "12.5",
            "probability": "0.072",
            "is_active": true,
            "template": "draw",
            "status": 2
          },
          {
            "id": "3",
            "value": "100",
            "probability": "0.009",
            "is_active": true,
            "template": "{$competitor2}",
            "status": 2
          }
        ],
        "type_id": 20,
        "specifiers": ""
      },
      {
        "id": "201",
        "status": 3,
        "odds": [
          {
            "id": "1",
            "value": "12.5",
            "probability": "0.0720",
            "is_active": true,
            "template": "yes",
            "status": 2
          },
          {
            "id": "2",
            "value": "1",
            "probability": "0.928",
            "is_active": false,
            "template": "no",
            "status": 1
          }
        ],
        "type_id": 201,
        "specifiers": ""
      },
      {
        "id": "589h1t1_5",
        "status": 3,
        "odds": [
          {
            "id": "1",
            "value": "12.5",
            "probability": "0.0720",
            "is_active": true,
            "template": "yes {total}",
            "status": 2
          },
          {
            "id": "2",
            "value": "1",
            "probability": "0.928",
            "is_active": false,
            "template": "no {total}",
            "status": 1
          }
        ],
        "type_id": 589,
        "specifiers": "halfnr=1&total=1.5"
      }
    ],
    "bet_stop": false,
    "game_state": {
      "bo": 1,
      "time": "541000",
      "period": "period_1st_half",
      "match_format": "live",
      "period_number": 1,
      "timer_running": true
    },
    "competitors_score": [
      {
        "scores": [
          {
            "id": "yellow_card",
            "type": "yellow_card",
            "number": 0,
            "points": "0"
          },
          {
            "id": "red_card",
            "type": "red_card",
            "number": 0,
            "points": "1"
          },
          {
            "id": "yellow_red_card",
            "type": "yellow_red_card",
            "number": 0,
            "points": "0"
          },
          {
            "id": "total",
            "type": "total",
            "number": 0,
            "points": "1"
          },
          {
            "id": "period_1st_half",
            "type": "period_1st_half",
            "number": 0,
            "points": "1"
          }
        ],
        "competitor_id": "gin:a35f60db-0695-4f03-852f-e3d983346b16",
        "side": "home"
      },
      {
        "scores": [
          {
            "id": "total",
            "type": "total",
            "number": 0,
            "points": "2"
          },
          {
            "id": "period_1st_half",
            "type": "period_1st_half",
            "number": 0,
            "points": "2"
          },
          {
            "id": "yellow_card",
            "type": "yellow_card",
            "number": 0,
            "points": "0"
          },
          {
            "id": "red_card",
            "type": "red_card",
            "number": 0,
            "points": "3"
          },
          {
            "id": "yellow_red_card",
            "type": "yellow_red_card",
            "number": 0,
            "points": "0"
          }
        ],
        "competitor_id": "betting:7:sr:competitor:22431",
        "side": "away"
      }
    ],
    "extensions": {
      "app.data.bet/widget": {
        "types": ["pitch_tracker", "stream", "scoreboard"]
      }
    }
  }
}

Retention policy

A snapshot of a sport event is retained for 5 days after the end of the sport event (after the sport event fixture has transit to one of the statuses: ended, closed, cancelled, abondoned). Once the retention period has expired, the snapshot is no longer available.

Log

A log is a set of changes to a sport event. Every log has next fields:
version - which corresponds to the version of the sport event snapshot at the time when the log was created. It means that the current version of the sport event snapshot is equal to the version of the latest log entry of the corresponding sport event.
sport_id - ID of the sport (dota2, cs, etc.) sport_event_id - ID of the sport event
timestamp_ns - date (unix nano) of the sport event's update
event_type - specify type of changes happened to the sport event
payload - changes that occurred with the sport event

There are several event_type, every type has its own structure (payload field) and represent specific changes happened to the sport event.

Retention policy

A log is retained for 3 days. Once the retention period has expired, the log is no longer available. If you try to subscribe with a log version that has already expired, the API will return a 409 HTTP code. It means that log with requested version is unavailable. If API returns 409 HTTP code for your latest processed log version it means that you must to resync all sport events by following steps from usage section.

sport_event_snapshot

It contains snapshot of the sport event. This event is received during initial synchronization for every sport event in a feed. After synchronization client receives messages that contain only partial updates of sport events (except sport_event_added).

An example of log with `sport_event_snapshot` event type
  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
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 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
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
{
  "sport_event_id": "1a70143e-159e-42d6-8645-97ad190a019f",
  "sport_id": "football",
  "version": "22h2KoCl1uu000004gfQS1",
  "timestamp_ns": 1715069754549926000,
  "event_type": "sport_event_snapshot",
  "payload": {
    "fixture": {
      "type": 0,
      "status": 1,
      "streams": [],
      "sport_id": "football",
      "template": "{$competitor1} vs {$competitor2}",
      "tournament": {
        "id": "betting:17:gin:1c15e2ba-edbc-4776-a702-67eb835cd7c0",
        "name": "U21. Premier League International Cup. Season 2023/2024"
      },
      "competitors": [
        {
          "id": "gin:a35f60db-0695-4f03-852f-e3d983346b16",
          "name": "AD Confianca",
          "side": "home",
          "type": 2,
          "template_position": 1
        },
        {
          "id": "betting:7:sr:competitor:22431",
          "name": "Ypiranga FC",
          "side": "away",
          "type": 2,
          "template_position": 2
        }
      ],
      "live_coverage": false,
      "start_time_ns": 0,
      "updated_at_ns": 0
    },
    "markets": [
      {
        "id": "20",
        "status": 3,
        "odds": [
          {
            "id": "1",
            "value": "1",
            "probability": "0.9",
            "is_active": false,
            "template": "{$competitor1}",
            "status": 1
          },
          {
            "id": "2",
            "value": "12.5",
            "probability": "0.072",
            "is_active": true,
            "template": "draw",
            "status": 2
          },
          {
            "id": "3",
            "value": "100",
            "probability": "0.009",
            "is_active": true,
            "template": "{$competitor2}",
            "status": 2
          }
        ],
        "type_id": 20,
        "specifiers": ""
      },
      {
        "id": "201",
        "status": 3,
        "odds": [
          {
            "id": "1",
            "value": "12.5",
            "probability": "0.0720",
            "is_active": true,
            "template": "yes",
            "status": 2
          },
          {
            "id": "2",
            "value": "1",
            "probability": "0.928",
            "is_active": false,
            "template": "no",
            "status": 1
          }
        ],
        "type_id": 201,
        "specifiers": ""
      },
      {
        "id": "589h1t1_5",
        "status": 3,
        "odds": [
          {
            "id": "1",
            "value": "12.5",
            "probability": "0.0720",
            "is_active": true,
            "template": "yes {total}",
            "status": 2
          },
          {
            "id": "2",
            "value": "1",
            "probability": "0.928",
            "is_active": false,
            "template": "no {total}",
            "status": 1
          }
        ],
        "type_id": 589,
        "specifiers": "halfnr=1&total=1.5"
      }
    ],
    "bet_stop": false,
    "game_state": {
      "bo": 1,
      "time": "541000",
      "period": "period_1st_half",
      "match_format": "live",
      "period_number": 1,
      "timer_running": true
    },
    "competitors_score": [
      {
        "scores": [
          {
            "id": "yellow_card",
            "type": "yellow_card",
            "number": 0,
            "points": "0"
          },
          {
            "id": "red_card",
            "type": "red_card",
            "number": 0,
            "points": "1"
          },
          {
            "id": "yellow_red_card",
            "type": "yellow_red_card",
            "number": 0,
            "points": "0"
          },
          {
            "id": "total",
            "type": "total",
            "number": 0,
            "points": "1"
          },
          {
            "id": "period_1st_half",
            "type": "period_1st_half",
            "number": 0,
            "points": "1"
          }
        ],
        "competitor_id": "gin:a35f60db-0695-4f03-852f-e3d983346b16",
        "side": "home"
      },
      {
        "scores": [
          {
            "id": "total",
            "type": "total",
            "number": 0,
            "points": "2"
          },
          {
            "id": "period_1st_half",
            "type": "period_1st_half",
            "number": 0,
            "points": "2"
          },
          {
            "id": "yellow_card",
            "type": "yellow_card",
            "number": 0,
            "points": "0"
          },
          {
            "id": "red_card",
            "type": "red_card",
            "number": 0,
            "points": "3"
          },
          {
            "id": "yellow_red_card",
            "type": "yellow_red_card",
            "number": 0,
            "points": "0"
          }
        ],
        "competitor_id": "betting:7:sr:competitor:22431",
        "side": "away"
      }
    ],
    "extensions": {
      "app.data.bet/widget": {
        "types": ["pitch_tracker", "scoreboard"]
      }
    }
  }
}

sport_event_added

This event occurs when a new sport event has been booked or when a client refetches a sport event. It contains snapshot of the sport event.

An example of log with `sport_event_added` event type
  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
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 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
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
{
  "sport_event_id": "1a70143e-159e-42d6-8645-97ad190a019f",
  "sport_id": "football",
  "version": "22h2KoCl1uu000004gfQS1",
  "timestamp_ns": 1715069754549926000,
  "event_type": "sport_event_added",
  "payload": {
    "fixture": {
      "type": 0,
      "status": 1,
      "streams": [],
      "sport_id": "football",
      "template": "{$competitor1} vs {$competitor2}",
      "tournament": {
        "id": "betting:17:gin:1c15e2ba-edbc-4776-a702-67eb835cd7c0",
        "name": "U21. Premier League International Cup. Season 2023/2024"
      },
      "competitors": [
        {
          "id": "gin:a35f60db-0695-4f03-852f-e3d983346b16",
          "name": "AD Confianca",
          "side": "home",
          "type": 2,
          "template_position": 1
        },
        {
          "id": "betting:7:sr:competitor:22431",
          "name": "Ypiranga FC",
          "side": "away",
          "type": 2,
          "template_position": 2
        }
      ],
      "live_coverage": false,
      "start_time_ns": 0,
      "updated_at_ns": 0
    },
    "markets": [
      {
        "id": "20",
        "status": 3,
        "odds": [
          {
            "id": "1",
            "value": "1",
            "probability": "0.9",
            "is_active": false,
            "template": "{$competitor1}",
            "status": 1
          },
          {
            "id": "2",
            "value": "12.5",
            "probability": "0.072",
            "is_active": true,
            "template": "draw",
            "status": 2
          },
          {
            "id": "3",
            "value": "100",
            "probability": "0.009",
            "is_active": true,
            "template": "{$competitor2}",
            "status": 2
          }
        ],
        "type_id": 20,
        "specifiers": ""
      },
      {
        "id": "201",
        "status": 3,
        "odds": [
          {
            "id": "1",
            "value": "12.5",
            "probability": "0.0720",
            "is_active": true,
            "template": "yes",
            "status": 2
          },
          {
            "id": "2",
            "value": "1",
            "probability": "0.928",
            "is_active": false,
            "template": "no",
            "status": 1
          }
        ],
        "type_id": 201,
        "specifiers": ""
      },
      {
        "id": "589h1t1_5",
        "status": 3,
        "odds": [
          {
            "id": "1",
            "value": "12.5",
            "probability": "0.0720",
            "is_active": true,
            "template": "yes {total}",
            "status": 2
          },
          {
            "id": "2",
            "value": "1",
            "probability": "0.928",
            "is_active": false,
            "template": "no {total}",
            "status": 1
          }
        ],
        "type_id": 589,
        "specifiers": "halfnr=1&total=1.5"
      }
    ],
    "bet_stop": false,
    "game_state": {
      "bo": 1,
      "time": "541000",
      "period": "period_1st_half",
      "match_format": "live",
      "period_number": 1,
      "timer_running": true
    },
    "competitors_score": [
      {
        "scores": [
          {
            "id": "yellow_card",
            "type": "yellow_card",
            "number": 0,
            "points": "0"
          },
          {
            "id": "red_card",
            "type": "red_card",
            "number": 0,
            "points": "1"
          },
          {
            "id": "yellow_red_card",
            "type": "yellow_red_card",
            "number": 0,
            "points": "0"
          },
          {
            "id": "total",
            "type": "total",
            "number": 0,
            "points": "1"
          },
          {
            "id": "period_1st_half",
            "type": "period_1st_half",
            "number": 0,
            "points": "1"
          }
        ],
        "competitor_id": "gin:a35f60db-0695-4f03-852f-e3d983346b16",
        "side": "home"
      },
      {
        "scores": [
          {
            "id": "total",
            "type": "total",
            "number": 0,
            "points": "2"
          },
          {
            "id": "period_1st_half",
            "type": "period_1st_half",
            "number": 0,
            "points": "2"
          },
          {
            "id": "yellow_card",
            "type": "yellow_card",
            "number": 0,
            "points": "0"
          },
          {
            "id": "red_card",
            "type": "red_card",
            "number": 0,
            "points": "3"
          },
          {
            "id": "yellow_red_card",
            "type": "yellow_red_card",
            "number": 0,
            "points": "0"
          }
        ],
        "competitor_id": "betting:7:sr:competitor:22431",
        "side": "away"
      }
    ],
    "extensions": {}
  }
}

This type of event has the same payload as sport_event_snapshot.

bet_stop_updated

This event occurs when status of the bet stop has changed during the match. If bet_stop field is true placing bets on this match must be suspended and markets should be locked on the UI until a bet stop is deactivated (a log with bet_stop equals false is received). By default bet_stop is deactivated (or in case of fetching sport event snapshot it equals SportEvent.bet_stop).

Betstop Handling

Betstop is completely untied from market updates and must be handled separately. When betstop is true, it's possible that some markets are being updated and even have active status, but bet placement must be stopped for the entire sport event until bet stop is moved to false.

Alternative Integration

If your system doesn't support betstop functionality, you can request your DATA.BET integration manager to disable betstop events. In this case, you will receive markets_updated events instead.

An example of log with `bet_stop_updated` event type
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
{
  "sport_event_id": "8168302d-86cd-453c-b549-b22f2249058d",
  "sport_id": "football",
  "version": "22h3XxK3Tnc000004gfK0H",
  "timestamp_ns": 1715074023000000000,
  "event_type": "bet_stop_updated",
  "payload": {
    "bet_stop": false
  }
}

competitor_scores_updated

This event occurs when there is at least one score update for the competitor. It contains all the scores of all competitors.

An example of log with `competitor_scores_updated` event type
 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
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
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
78
79
80
81
{
  "sport_event_id": "e5412aaa-bba5-4251-b027-00b61152486d",
  "sport_id": "football",
  "version": "22h9qfQK3pP000004gfFfy",
  "timestamp_ns": 1715096215000000000,
  "event_type": "competitor_scores_updated",
  "payload": [
    {
      "scores": [
        {
          "id": "yellow_card",
          "type": "yellow_card",
          "number": 0,
          "points": "0"
        },
        {
          "id": "red_card",
          "type": "red_card",
          "number": 0,
          "points": "1"
        },
        {
          "id": "yellow_red_card",
          "type": "yellow_red_card",
          "number": 0,
          "points": "0"
        },
        {
          "id": "total",
          "type": "total",
          "number": 0,
          "points": "1"
        },
        {
          "id": "period_1st_half",
          "type": "period_1st_half",
          "number": 0,
          "points": "1"
        }
      ],
      "competitor_id": "betting:19:betting:1:sr:competitor:166150",
      "side": "home"
    },
    {
      "scores": [
        {
          "id": "total",
          "type": "total",
          "number": 0,
          "points": "2"
        },
        {
          "id": "period_1st_half",
          "type": "period_1st_half",
          "number": 0,
          "points": "2"
        },
        {
          "id": "yellow_card",
          "type": "yellow_card",
          "number": 0,
          "points": "0"
        },
        {
          "id": "red_card",
          "type": "red_card",
          "number": 0,
          "points": "3"
        },
        {
          "id": "yellow_red_card",
          "type": "yellow_red_card",
          "number": 0,
          "points": "0"
        }
      ],
      "competitor_id": "betting:17:gin:361ba1ca-7c76-4fef-a703-2c7f8c2d9cdb",
      "side": "away"
    }
  ]
}

fixture_updated

This event occurs when at least one field of the fixture (match status, start date, amount of available streams, etc.) updated. It contains all fields of the fixture.

An example of log with `fixture_updated` event type
 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
30
31
32
33
34
35
36
37
{
  "sport_event_id": "e5412aaa-bba5-4251-b027-00b61152486d",
  "sport_id": "football",
  "version": "22h9ySlp0fd000004gfR6m",
  "timestamp_ns": 1715096658000000000,
  "event_type": "fixture_updated",
  "payload": {
    "type": 0,
    "status": 2,
    "streams": [],
    "sport_id": "football",
    "template": "{$competitor1} vs {$competitor2}",
    "tournament": {
      "id": "gin:653b9a71-92e9-4613-9b04-9c2e9c0d341e",
      "name": "Brazil. Serie C"
    },
    "competitors": [
      {
        "id": "gin:a35f60db-0695-4f03-852f-e3d983346b16",
        "name": "AD Confianca",
        "side": "home",
        "type": 2,
        "template_position": 1
      },
      {
        "id": "betting:7:sr:competitor:22431",
        "name": "Ypiranga FC",
        "side": "away",
        "type": 2,
        "template_position": 2
      }
    ],
    "live_coverage": false,
    "start_time_ns": 1715095740000000000,
    "updated_at_ns": 1715096658000000000
  }
}

game_state_updated

Game state represent current state (current period/time/ticker/server/quarter/round/etc. in the match, the number of properties depends on the type of sport) of the sport event. This event occurs when at least on state property has an update. It contains all the game state data available for sport event.

An example of log with `game_state_updated` event type for soccer
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
{
  "sport_event_id": "8168302d-86cd-453c-b549-b22f2249058d",
  "sport_id": "football",
  "version": "22h3viPRnOM000004gfU2T",
  "timestamp_ns": 1715075372000000000,
  "event_type": "game_state_updated",
  "payload": {
    "bo": 1,
    "time": "5291000",
    "pause": false,
    "period": "period_2nd_half",
    "match_format": "live",
    "period_number": 2,
    "timer_running": true
  }
}

markets_updated

This event occurs when at least one of the next events happened:

  • markets statuses updated
  • odds status updated
  • odds values updated
  • market has been added

Event contains only those markets that has updates (updated market contains all market fields including odds).

An example of log with `markets_updated` event type
 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
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
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
78
79
80
81
{
  "sport_event_id": "102354cd-72d8-42e5-8570-7dbb466e23bb",
  "sport_id": "football",
  "version": "22hAIfYZ0O6000004gfTi4",
  "timestamp_ns": 1715097805000000000,
  "event_type": "markets_updated",
  "payload": [
    {
      "id": "240h1_5",
      "odds": [
        {
          "id": "1",
          "value": "2.27",
          "probability": "0.417",
          "status": 0,
          "template": "Over",
          "is_active": true
        },
        {
          "id": "2",
          "value": "1.62",
          "probability": "0.583",
          "status": 0,
          "template": "Under",
          "is_active": true
        }
      ],
      "status": 0,
      "type_id": 240,
      "specifiers": "hcp=1.5"
    },
    {
      "id": "240h2_0",
      "odds": [
        {
          "id": "1",
          "value": "1.73",
          "probability": "0.548",
          "status": 0,
          "template": "Over",
          "is_active": true
        },
        {
          "id": "2",
          "value": "2.1",
          "probability": "0.452",
          "status": 0,
          "template": "Under",
          "is_active": true
        }
      ],
      "status": 0,
      "type_id": 240,
      "specifiers": "hcp=2.0"
    },
    {
      "id": "240h2_5",
      "odds": [
        {
          "id": "1",
          "value": "1.43",
          "probability": "0.657",
          "status": 0,
          "template": "Over",
          "is_active": true
        },
        {
          "id": "2",
          "value": "2.73",
          "probability": "0.343",
          "status": 0,
          "template": "Under",
          "is_active": true
        }
      ],
      "status": 0,
      "type_id": 240,
      "specifiers": "hcp=2.5"
    }
  ]
}

extensions_updated

This event occurs when at least one of underlying extension has been updated

An example of log with `extensions_updated` event type for esports_counter_strike
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
{
  "sport_event_id": "8168302d-86cd-453c-b549-b22f2249058d",
  "sport_id": "esports_counter_strike",
  "version": "22h3viPRnOM000004gfU2T",
  "timestamp_ns": 1715075372000000000,
  "event_type": "extensions_updated",
  "payload": {
    "app.data.bet/widget": {
      "types": ["pitch_tracker", "stream", "scoreboard", "h2h_statistics", "games_statistics", "teams_statistics"]
    }
  }
}

bets_rollback

Critical Integration Requirement

This event is NOT related to risk management and MUST be integrated in ALL modes (including non-MTS risk management modes).

The bets_rollback event instructs the client to roll back (void/refund) all bets on the specified markets that were placed within a specific time range [dt_start, dt_end] inclusive.

Key Differences from Other Events

  • bets_rollback: Refunds bets placed within a specific time range only. Used when only certain bets need to be voided, not the entire market.
  • markets_updated with odd status 5 (refunded): Refunds ALL bets on a market regardless of when they were placed. Used when an entire market must be voided.

Important: Rolling Back All Bets

If the markets field is an empty array, all bets associated with the given sport_event_id must be rolled back. This ensures that no bets remain active when the rollback action is intended to apply to the entire event. The absence of specific markets signifies that the rollback is not limited to particular markets.

These are possible reasons for the rollback:
1. 322 – The bet has been canceled due to suspicion of unfair play or match-fixing.
2. event_postponed_for_48_hours – The event was postponed for more than 48 hours.
3. match_was_canceled – The match did not take place as it was canceled.
4. competitor_is_incorrect – There was an error in specifying the participants: the wrong competitor was listed.
5. partial_technical_lose – The match ended partially due to technical reasons (e.g., one of the participants could not continue due to non-game-related circumstances).
6. technical_lose – The match result was decided by a technical defeat (without full gameplay).
7. crash_of_the_game – The game was interrupted due to technical issues (beyond our control), preventing the outcome from being determined.
8. after_goal – The bet was placed after the decisive event (e.g. goal) had already occurred, making it invalid (commonly referred to as a "late bet").
9. technical_error_in_coefficient – A technical error caused an incorrect coefficient to be specified in the bet.
10. pre_match_bets_after_match_start – The pre-match bet was placed after the match had already started, making it invalid.
11. wrong_match_format – The match format or conditions changed (e.g. football match had 40-minute halves instead of 45 minutes), resulting in partial refunds of the bets.
12. unplayed_market – The selected market (bet event type) was not played or did not occur.
13. competitor_refusal – One of the participants refused to participate, the match outcome was declared void.
14. duplicate_bet – A duplicate bet was detected and canceled.
15. streamsniping – The bet was canceled due to an unfair advantage (e.g. watching live streams in real-time).
16. product_ban – The bets were refunded to users who were banned from our product.
17. marketing – Bets were refunded for marketing accounts. These bets were placed for testing purposes.
18. competitor_has_been_replaced - The competitor was changed in the match.
19. options – This function was used when none of the predefined reasons applied.

An example of log with `bets_rollback` event type
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
{
  "sport_event_id": "eb1a6310-8d37-4f67-a4c3-2ff1078788bb",
  "sport_id": "football",
  "version": "22h9ySlp0fd000004gfR6m",
  "timestamp_ns": 1715096658000000000,
  "event_type": "bets_rollback",
  "payload": {
    "markets": [
      {
        "id": "1",
        "type_id": 1,
        "specifiers": ""
      },
      {
        "id": "103h1h-0_5",
        "type_id": 103,
        "specifiers": "hcp=-0.5"
      }
    ],
    "reason": "after_goal",
    "dt_start": "2019-08-08T14:21:52Z",
    "dt_end": "2019-08-08T14:21:52Z"
  }
}

heartbeat

Heartbeat is a message used to notify a consumer that a trading feed is alive. Recommended heartbeat interval is 5 seconds.

Actions required

If the client does not receive a heartbeat message or any other log event within 2 heartbeat intervals (10 seconds for the specified 5-second interval), the client must reconnect to the feed. This ensures the connection remains healthy and prevents data loss.

When MTS Risk Management is not applied

Heartbeat integration is required when MTS risk management is not applied. The client must stop accepting bets globally when no heartbeat messages or other logs are received within specified 2 heartbeat intervals to ensure proper connection monitoring and data integrity.

Heartbeats are sent every 5 seconds via RabbitMQ transport. For HTTP transport client specified heartbeat interval in seconds via query param heartbeat_interval. Param is optional, if heartbeat_interval is not specified heartbeat messages wil not be sent. For instance (client requests heartbeat message every 5 seconds):

1
2
3
4
5
stdbuf -oL curl --request GET \
     --url https://feed.int.databet.cloud/log?heartbeat_interval=5 \
     --cert    client.crt \
     --key     client.key \
     --verbose \ 

An example of a message:

1
2
3
4
{
  "timestamp_ns": 1718951930275035589,
  "event_type": "heartbeat"
}

Received messages
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
{"event_type":"heartbeat","timestamp_ns":1730365547036815913}

{"sport_id":"esports_counter_strike","sport_event_id":"cf35569f-3cd1-4d0e-adcf-1744fa312093","version":"23p5jtqGbXJ000004gfPNq","timestamp_ns":1730365542000000000,"event_type":"game_state_updated","payload":{"bo":3,"map":"{\"1\":\"de_vertigo\"}","time":"61000","round":1,"side_away":"ct","side_home":"t","game_state":"map","match_format":"r13_o3","state_number":1,"timer_running":true}}
{"event_type":"heartbeat","timestamp_ns":1730365552036814990}
{"event_type":"heartbeat","timestamp_ns":1730365557036814759}
{"event_type":"heartbeat","timestamp_ns":1730365562036815103}
{"sport_id":"esports_dota_2","sport_event_id":"40939266-615b-4a0a-b112-c320644ab5c2","version":"23p5k5ldiLn000004gfUhO","timestamp_ns":1730365562000000000,"event_type":"game_state_updated","payload":{"bo":3,"map":2,"time":"946000","pause":false,"side_away":"radiant","side_home":"dire","timer_running":true}}
{"sport_id":"esports_counter_strike","sport_event_id":"cf35569f-3cd1-4d0e-adcf-1744fa312093","version":"23p5k6wPcQt000004gfNAF","timestamp_ns":1730365554000000000,"event_type":"competitor_scores_updated","payload":[{"side":"home","scores":[{"id":"map:1","type":"map","number":1,"points":"1"},{"id":"total","type":"total","number":0,"points":"0"}],"competitor_id":"gt:96510"},{"side":"away","scores":[{"id":"map:1","type":"map","number":1,"points":"0"},{"id":"total","type":"total","number":0,"points":"0"}],"competitor_id":"gt:38810"}]}
{"sport_id":"esports_counter_strike","sport_event_id":"cf35569f-3cd1-4d0e-adcf-1744fa312093","version":"23p5k6wPcsX000004gfUYj","timestamp_ns":1730365554000000000,"event_type":"game_state_updated","payload":{"bo":3,"map":"{\"1\":\"de_vertigo\"}","time":"56000","round":1,"side_away":"ct","side_home":"t","game_state":"map","match_format":"r13_o3","state_number":1,"timer_running":true}}
{"event_type":"heartbeat","timestamp_ns":1730365567036818368}
{"sport_id":"esports_counter_strike","sport_event_id":"cf35569f-3cd1-4d0e-adcf-1744fa312093","version":"23p5kEaFNuu000004gfRzB","timestamp_ns":1730365561000000000,"event_type":"game_state_updated","payload":{"bo":3,"map":"{\"1\":\"de_vertigo\"}","round":2,"side_away":"ct","side_home":"t","game_state":"map","match_format":"r13_o3","state_number":1,"timer_running":false}}

Usage

We support 2 types of transport for sending logs: HTTP stream and RabbitMQ queue (experimental API).

Usage of HTTP stream API

The correct way to use the HTTP stream feed API is the following:

  1. Request all snapshots via GET /all. In the response, the latest snapshot version will be indicated in the Last-Version header, and the sport events themselves will appear in the body, each in a separate line. Chunked transfer encoding is used for streaming sport events in HTTP 1.1 (if the sport event does not fit in one line, it can be split into several lines (according to the encoding)).

    Get a snapshot request via curl `client.crt` and `client.key` will be provided by the DATA.BET integration team.
    1
    2
    3
    4
    5
    stdbuf -oL curl --request GET \
         --url https://feed.int.databet.cloud/all \
         --cert    client.crt \
         --key     client.key \
         --verbose \ 
    
    The response:
     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    ...
    < Last-Version: 22hAUGMBUcD000004gfQzu
    < Last-Version-Hex: 17cd40f76bd7cd41000000010000b13e
    < Vary: Accept-Encoding
    < X-Api-Version: 2
    < Date: Tue, 07 May 2024 20:00:42 GMT
    < Transfer-Encoding: chunked
    < 
    7576
    {"sport_event_id":"1a70143e-159e-42d6-8645-97ad190a019f","sport_id":"football","version":"22h2KoCl1uu000004gfQS1","timestamp_ns":1715069754549926000,"event_type":"sport_event_snapshot","payload":{"fixture":{"type":0,"status":1,"streams":[],"sport_id":"football","template":"{$competitor1} vs {$competitor2}","tournament":{"id":"betting:17:gin:1c15e2ba-edbc-4776-a702-67eb835cd7c0","name":"U21. Premier League International Cup. Season 2023/2024"},"competitors":[{"id":"gin:a35f60db-0695-4f03-852f-e3d983346b16","name":"AD Confianca","side":"home","type":2,"template_position":1},{"id":"betting:7:sr:competitor:22431","name":"Ypiranga FC","side":"away","type":2,"template_position":2}],"live_coverage":false,"start_time_ns":0,"updated_at_ns":0},"markets":[{"id":"20","status":3,"odds":[{"id":"1","value":"1","is_active":false,"status":1},{"id":"2","value":"12.5","is_active":true,"status":2},{"id":"3","value":"100","is_active":true,"status":2}],"type_id":20,"specifiers":""},{"id":"201","status":3,"odds":[{"id":"1","value":"12.5","is_active":true,"status":2},{"id":"2","value":"1","is_active":false,"status":1}],"type_id":201,"specifiers":""},{"id":"589h1t1_5","status":3,"odds":[{"id":"1","value":"12.5","is_active":true,"status":2},{"id":"2","value":"1","is_active":false,"status":1}],"type_id":589,"specifiers":"halfnr=1&total=1.5"}],"bet_stop":false,"game_state":{"bo":1,"time":"541000","period":"period_1st_half","match_format":"live","period_number":1,"timer_running":true},"competitors_score":[{"scores":[{"id":"yellow_card","type":"yellow_card","number":0,"points":"0"},{"id":"red_card","type":"red_card","number":0,"points":"1"},{"id":"yellow_red_card","type":"yellow_red_card","number":0,"points":"0"},{"id":"total","type":"total","number":0,"points":"1"},{"id":"period_1st_half","type":"period_1st_half","number":0,"points":"1"}],"competitor_id":"gin:a35f60db-0695-4f03-852f-e3d983346b16","side":"home"},{"scores":[{"id":"total","type":"total","number":0,"points":"2"},{"id":"period_1st_half","type":"period_1st_half","number":0,"points":"2"},{"id":"yellow_card","type":"yellow_card","number":0,"points":"0"},{"id":"red_card","type":"red_card","number":0,"points":"3"},{"id":"yellow_red_card","type":"yellow_red_card","number":0,"points":"0"}],"competitor_id":"betting:7:sr:competitor:22431","side":"away"}]}}
    ...
    9cd7
    {"sport_event_id":"62b36a71-75d6-49a2-b72e-ca16bcde44f4","sport_id":"football","version":"33h2KoCl1uu111004gfQS1","timestamp_ns":1715069754549926000,"event_type":"sport_event_snapshot","payload":{"fixture":{"type":0,"status":1,"streams":[],"sport_id":"football","template":"{$competitor1} vs {$competitor2}","tournament":{"id":"betting:17:gin:1c15e2ba-edbc-4776-a702-67eb835cd7c0","name":"U21. Premier League International Cup. Season 2023/2024"},"competitors":[{"id":"betting:19:betting:1:sr:competitor:166150","name":"MSK Zilina","side":"home","type":2,"template_position":1},{"id":"betting:17:gin:361ba1ca-7c76-4fef-a703-2c7f8c2d9cdb","name":"TSC Backa Topola","side":"away","type":2,"template_position":2}],"live_coverage":false,"start_time_ns":0,"updated_at_ns":0},"markets":[{"id":"201","status":3,"odds":[{"id":"1","value":"12.5","is_active":true,"status":2},{"id":"2","value":"1","is_active":false,"status":1}],"type_id":201,"specifiers":""},{"id":"589h1t1_5","status":3,"odds":[{"id":"1","value":"12.5","is_active":true,"status":2},{"id":"2","value":"1","is_active":false,"status":1}],"type_id":589,"specifiers":"halfnr=1&total=1.5"}],"bet_stop":false,"game_state":{"bo":1,"time":"443000","period":"period_1st_half","match_format":"live","period_number":1,"timer_running":true},"competitors_score":[{"scores":[{"id":"yellow_card","type":"yellow_card","number":0,"points":"1"},{"id":"red_card","type":"red_card","number":0,"points":"1"},{"id":"yellow_red_card","type":"yellow_red_card","number":0,"points":"0"},{"id":"total","type":"total","number":0,"points":"2"},{"id":"period_1st_half","type":"period_1st_half","number":0,"points":"2"}],"competitor_id":"betting:19:betting:1:sr:competitor:166150","side":"home"},{"scores":[{"id":"total","type":"total","number":0,"points":"1"},{"id":"period_1st_half","type":"period_1st_half","number":0,"points":"2"},{"id":"yellow_card","type":"yellow_card","number":0,"points":"0"},{"id":"red_card","type":"red_card","number":0,"points":"0"},{"id":"yellow_red_card","type":"yellow_red_card","number":0,"points":"0"}],"competitor_id":"betting:17:gin:361ba1ca-7c76-4fef-a703-2c7f8c2d9cdb","side":"away"}]}}
    

  2. Save the snapshots and version (Last-Version header) from the previous response

  3. Subscribe to sport events updates using GET /log specifying the last saved version from step 1. The version value should be set in the Last-Version header. In the response, the server will send a line-by-line log of sports event updates. Chunked transfer encoding is used for streaming logs in HTTP 1.1 (if the log does not fit in one line, it can be split into several lines (according to the encoding)).

    Get a log request (curl) `client.crt` and `client.key` will be provided by the DATA.BET integration team.
    1
    2
    3
    4
    5
    6
    stdbuf -oL curl --request GET \
         --url https://feed.int.databet.cloud/log?heartbeat_interval \
         --cert    client.crt \
         --key     client.key \
         --header  'Last-Version: 22hAUGMBUcD000004gfQzu' \
         --verbose
    
    The response:
     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    ...
    < HTTP/1.1 200 OK
    < Cache-Control: no-cache, no-store, must-revalidate
    < Content-Type: text/event-stream; charset=utf-8
    < X-Api-Version: 2
    < Date: Tue, 07 May 2024 20:00:42 GMT
    < Transfer-Encoding: chunked
    <
    8000
    {"sport_event_id":"e5412aaa-bba5-4251-b027-00b61152486d","sport_id":"football","version":"22h9ySlp0fd000004gfR6m","timestamp_ns":1715096658000000000,"event_type":"fixture_updated","payload":{"type":0,"status":2,"streams":[],"sport_id":"football","template":"{$competitor1} vs {$competitor2}","tournament":{"id":"gin:653b9a71-92e9-4613-9b04-9c2e9c0d341e","name":"Brazil. Serie C"},"competitors":[{"id":"gin:a35f60db-0695-4f03-852f-e3d983346b16","name":"AD Confianca","side":"home","type":2,"template_position":1},{"id":"betting:7:sr:competitor:22431","name":"Ypiranga FC","side":"away","type":2,"template_position":2}],"live_coverage":false,"start_time_ns":1715095740000000000,"updated_at_ns":1715096658000000000}}
    1d1
    {"sport_event_id":"e5412aaa-bba5-4251-b027-00b61152486d","sport_id":"football","version":"22h9qfQK3pP000004gfFfy","timestamp_ns":1715096215000000000,"event_type":"competitor_scores_updated","payload":[{"scores":[{"id":"yellow_card","type":"yellow_card","number":0,"points":"0"},{"id":"red_card","type":"red_card","number":0,"points":"1"},{"id":"yellow_red_card","type":"yellow_red_card","number":0,"points":"0"},{"id":"total","type":"total","number":0,"points":"1"},{"id":"period_1st_half","type":"period_1st_half","number":0,"points":"1"}],"competitor_id":"betting:19:betting:1:sr:competitor:166150","side":"home"},{"scores":[{"id":"total","type":"total","number":0,"points":"2"},{"id":"period_1st_half","type":"period_1st_half","number":0,"points":"2"},{"id":"yellow_card","type":"yellow_card","number":0,"points":"0"},{"id":"red_card","type":"red_card","number":0,"points":"3"},{"id":"yellow_red_card","type":"yellow_red_card","number":0,"points":"0"}],"competitor_id":"betting:17:gin:361ba1ca-7c76-4fef-a703-2c7f8c2d9cdb","side":"away"}]}
    ...
    7434
    {"sport_event_id":"e5412aaa-bba5-4251-b027-00b61152486d","sport_id": "football","version":"22hAUGMBUcD000007gfQzu","timestamp_ns":1715096715000000000,"event_type":"markets_updated","payload":[{"id":"240h1_5","odds":[{"id":"1","value":"2.27","status":0,"is_active":true},{"id":"2","value":"1.62","status":0,"is_active":true}],"status":0,"type_id":240,"specifiers":"hcp=1.5"}]}
    

    Most common issues:

    • received 400 HTTP code: requested version is not specified in Last-Version header
    • received 409 HTTP code: requested version has already expired, you must to resync all sport events (go to step 1)
  4. Every log contains the version, after applying changes from the log, the version should be saved ( similar to step 2) in order to be used for re-subscription (if the client's server restarts, the client has to start from step 3)

Usage of RabbitMQ API (deprecated)

Deprecated

We are aiming to provide feed with the lowest latency possible. So, as the RabbitMQ creates a big delay on routing data we don't support it anymore.
95th percentile end-to-end latency comparison
Reference

RabbitMQ queue and message

The name of a queue and credentials to connect to RabbitMQ server is provided by the DATA.BET integration team. The queue set up with length limit 10 000 messages. If the consumer does not consume messages (or a consuming rate much lower than a publishing rate), the publisher stops sending messages until the consumer resumes its work. If the publisher registers the recovery of the consumer (the queue size is less than 10 000 messages), the publisher will continue to publish messages.

Every RabbitMQ message body contains a single log. Every RabbitMQ message contains next properties:

  • Content type - it's always application/json
  • Message ID - it's a version of a log and could be used as idempotence key
  • Timestamp - time when message is sent
  • Type - represents event_type of LogEntry, it could be used on client side to select JSON deserializer/decoder for received payload (every event_type has own payload)
  • Headers - contains metadata (some fields duplicate the properties described above)

Headers contains next fields:
- Sport-Event-ID - ID of sport event
- Sport-ID - ID of sport
- Last-Version - a version of a log
- Event-Type - an event type of log

The correct way to use the API

  1. Initialize sending messages to rabbitmq queue via POST /subscribe. If this is not the first interaction client must specify the last saved version (from step 2). If this is the first interaction, there is no need to specify version. Every call of this method will purge the queue.
    1. If the specified version is found and the difference between the specified version and the last version on the server is less than 1 hour, new logs (logs newer than the specified version) will be sent.
      Resubscribe with specified version client.crt and client.key will be provided by the DATA.BET integration team.
      1
      2
      3
      4
      5
      6
      stdbuf -oL curl --request POST \
      --url https://feed.int.databet.cloud/subscribe \
      --cert    client.crt \
      --key     client.key \
      --header  'Last-Version: 22hAUGMBUcD000004gfQzu' \
      --verbose \ 
      
      The response:
      1
      2
      3
      4
      5
      < Vary: Accept-Encoding
      < X-Api-Version: 2   
      < Date: Tue, 07 May 2024 20:00:42 GMT
      <
      {"version_is_found": true}
      
      Response returns {"version_is_found": true} and only new logs (updates that have happened since the update of the specified version in request took place) will be sent.
    2. If the specified version is found and the difference between the specified version and the last version on the server is more than 1 hour the optimization will be applied in order to reduce synchronization time: the server will first send snapshots of all sports events (event sport_event_snapshot) that have been updated since the update of the given version took place and after that new logs will be sent (logs newer than the last sent sport_event_snapshot).
    3. If version is not specified (the first interaction) or is not found (the log is not available, retention period is 3 days) the server will first send snapshots for all available sports events (sport_event_snapshot event) and after that new logs (logs newer than the last sent sport_event_snapshot).
      Initialize sending messages to rabbitmq queue via curl client.crt and client.key will be provided by the DATA.BET integration team.
      1
      2
      3
      4
      5
      stdbuf -oL curl --request POST \
      --url https://feed.int.databet.cloud/subscribe \
      --cert    client.crt \
      --key     client.key \
      --verbose \ 
      
      The response:
      1
      2
      3
      4
      5
      6
      ...
      < Vary: Accept-Encoding
      < X-Api-Version: 2
      < Date: Tue, 07 May 2024 20:00:42 GMT
      <
      {"version_is_found": false}
      
      Response returns {"version_is_found": false} which is expected for initial request (because version was not specified).
  2. Subscribe to RabbitMQ queue (will be provided by the DATA.BET integration team). Every RabbitMQ message body contains a single log. Every log contains the version, after applying changes from the log, the version should be saved in order to be used for re-subscription.
  3. If a client restarts it should start from step 1 with specifying last version from step 2.

Important notes:

  • step 1 MUST be done before step 2 (the client must not execute two steps at the same time).

Refetch the snapshot for a specific sport event

The client can refetch a snapshot for a specific sport event (due to the logs of the sports being lost or incorrectly applied) by sending the request POST /refetch/sport-event/{sportEventId}, A sport_event_added log entry will be added to the log with the latest version of sport event.

Betting and Display Conditions

The following sport event properties MUST be taken into account when accepting bets, processing cashouts, and displaying sport events in the line for all integrations. Our Managed trading services (MTS) provides an additional layer of protection by checking all these statuses on our side. For non-MTS integrations, these conditions are mandatory requirements that must be implemented:

  • Risk management integrations: Must implement these checks in the UI (e.g., locking markets, hiding sport events)
  • Advisory API integrations: Must verify every bet placement and cashout request against all these statuses

Fixture status

There are 9 fixture statuses:
0 - not started (prematch sport event)
1 - live (live sport event)
2 - suspended (sport event could return to Live (1))
3 - ended (sport event is ended)
4 - closed (sport event will never become live/prematch)
5 - cancelled (deprecated) (sport event is cancelled, will never become live/prematch)
6 - abandoned (deprecated) (will never become live/prematch)
7 - delayed (sport event postponed to a different time, can become live/prematch)
8 - unknown (status applies when none of the other statuses would be correct, regardless of whether the event is new, can become live/prematch)

Placing bets and accepting cashouts must be allowed only in not started (0) and live (1) statuses.
Sport event must be visible for bettors in not started (0) and live (1) and suspended (2) statuses.

Market status

There are 5 market statuses:
0 - active (bets are allowed)
1 - suspended (bets are currently not allowed but market could return to the active state)
2 - deactivated (market is not active, bets are not allowed)
3 - resulted (market has settled, bets are not allowed)
4 - cancelled (deprecated) (market is cancelled, bets are not allowed)

Placing bets and accepting cashouts must be allowed only in active (0) status.
Suspended markets should be visible for bettor but their odds should be locked (bets are currently not allowed, but market could return to the active state)

Odd status and its active state

There are 7 odd statuses:
0 - not resulted (bets are allowed)
1 - win
2 - loss
3 - half win (asian handicaps)
4 - half loss (asian handicaps)
5 - refunded (all the bets MUST be refunded because market could not be settled, for example: market winner for the 5th round could not be resulted if a game ended in the 3rd round)
6 - cancelled (deprecated) (all the bets must be refunded because of the reason that doesn't match refunded)

And Odd has property is_active - if it is false - placing bets MUST be suspended. Therefore placing bets on Odd MUST be allowed only if Odd is active (is_active is true) AND odd status is not resulted (0).

Bet stop

If a bet stop flag is activated placing bets on this match must be suspended. Here is a description of the conditions when the flag is activated and deactivated, as well as the event that triggers this changes.

Connection monitoring and global bet stop

Connection monitoring includes:

  1. Connection loss detection: If the connection to the feed is lost or you have not received any log or heartbeat for 2 specified heartbeat intervals, you MUST trigger a global bet stop on your side.

  2. Message lag monitoring: It's essential to track the lag of each message by comparing the timestamp of markets_updated events with the current server time. If the lag exceeds 10 seconds, trigger global bet stop immediately.

When global bet stop is triggered, you must:

  1. Stop bet placement to all sport events immediately
  2. Hide all sport events from the betting line/UI
  3. Prevent any new bets or cashouts from being processed until connection is restored

This requirement applies to all integrations regardless of whether MTS risk management is applied. The global bet stop ensures data integrity and prevents placing bets on potentially outdated or incorrect information when the feed connection is compromised.

Implementation notes:

  • Monitor both log events and heartbeat messages to detect connection issues

  • Use the recommended 5-second heartbeat interval (2 intervals = 10 seconds timeout)

  • Track the lag of each message by comparing the timestamp of markets_updated events with the current server time. If the lag exceeds 10 seconds, trigger global bet stop immediately

  • Implement immediate UI updates to hide all sport events when global bet stop is triggered

  • Resume normal operations only after connection is restored and fresh data is received

Summary

Placing bets must be allowed if only ALL conditions are met:
Fixture status is not started (0) OR live (1) AND
Market status is active (0) AND
Odd status is not resulted (0) and Odd is_active AND
bet stop flag is deactivated AND
Connection to the feed is healthy

An example of sport event
  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
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 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
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
{
  "sport_event_id": "fbcc2a63-c7b3-44b4-9584-b88956de75c3",
  "updated_at_ns": 1714925409984766000,
  "sport_event": {
    "bet_stop": false,
    "game_state": {
      "timer_running": false,
      "bo": 1,
      "time": "5649000",
      "pause": true,
      "period": "period_2nd_half",
      "match_format": "pause",
      "period_number": 2
    },
    "competitors_score": [
      {
        "competitor_id": "betting:18:gin:9f0630b2-4cf5-44a6-a6f2-76de8e39334c",
        "scores": [
          {
            "id": "total",
            "type": "total",
            "number": 0,
            "points": "0"
          },
          {
            "id": "red_card",
            "type": "red_card",
            "number": 0,
            "points": "0"
          },
          {
            "id": "yellow_card",
            "type": "yellow_card",
            "number": 0,
            "points": "5"
          },
          {
            "id": "period_1st_half",
            "type": "period_1st_half",
            "number": 0,
            "points": "0"
          },
          {
            "id": "period_2nd_half",
            "type": "period_2nd_half",
            "number": 0,
            "points": "0"
          },
          {
            "id": "yellow_red_card",
            "type": "yellow_red_card",
            "number": 0,
            "points": "0"
          }
        ],
        "side": "home"
      },
      {
        "competitor_id": "betting:18:gin:a7e10814-330b-4f3f-b659-7b17eddc0e5a",
        "scores": [
          {
            "id": "red_card",
            "type": "red_card",
            "number": 0,
            "points": "0"
          },
          {
            "id": "yellow_card",
            "type": "yellow_card",
            "number": 0,
            "points": "3"
          },
          {
            "id": "period_1st_half",
            "type": "period_1st_half",
            "number": 0,
            "points": "0"
          },
          {
            "id": "period_2nd_half",
            "type": "period_2nd_half",
            "number": 0,
            "points": "1"
          },
          {
            "id": "yellow_red_card",
            "type": "yellow_red_card",
            "number": 0,
            "points": "0"
          },
          {
            "id": "total",
            "type": "total",
            "number": 0,
            "points": "1"
          }
        ],
        "side": "away"
      }
    ],
    "markets": [
      {
        "id": "20",
        "status": 3,
        "odds": [
          {
            "id": "1",
            "value": "1",
            "probability": "0.9",
            "is_active": false,
            "template": "{$competitor1}",
            "status": 1
          },
          {
            "id": "2",
            "value": "12.5",
            "probability": "0.072",
            "is_active": true,
            "template": "draw",
            "status": 2
          },
          {
            "id": "3",
            "value": "100",
            "probability": "0.009",
            "is_active": true,
            "template": "{$competitor2}",
            "status": 2
          }
        ],
        "type_id": 20,
        "specifiers": ""
      },
      {
        "id": "21",
        "odds": [
          {
            "id": "1",
            "value": "1.3",
            "probability": "0.6923",
            "status": 0,
            "template": "{$competitor1}",
            "is_active": false
          },
          {
            "id": "2",
            "value": "22",
            "probability": "0.0409",
            "status": 0,
            "template": "draw",
            "is_active": true
          },
          {
            "id": "3",
            "value": "20",
            "probability": "0.0450",
            "status": 0,
            "template": "{$competitor2}",
            "is_active": true
          }
        ],
        "status": 1,
        "type_id": 21,
        "specifiers": ""
      }
    ],
    "fixture": {
      "type": 0,
      "status": 0,
      "streams": [],
      "sport_id": "football",
      "template": "{$competitor1} vs {$competitor2}",
      "start_time_ns": 1714918860000000000,
      "tournament": {
        "id": "betting:18:gin:28397e11-86e7-4435-848e-0f4b898bc75a",
        "name": "South Africa. Diski Challenge"
      },
      "competitors": [
        {
          "id": "betting:18:gin:9f0630b2-4cf5-44a6-a6f2-76de8e39334c",
          "name": "Noah",
          "type": 2,
          "side": "home",
          "template_position": 1
        },
        {
          "id": "betting:18:gin:a7e10814-330b-4f3f-b659-7b17eddc0e5a",
          "name": "Al Faisaly Harmah",
          "type": 2,
          "side": "away",
          "template_position": 2
        }
      ],
      "live_coverage": true,
      "updated_at_ns": 1714925409000000000
    },
    "extensions": {
      "app.data.bet/widget": {
        "types": ["pitch_tracker", "stream", "scoreboard"]
      }
    }
  }
}

It's allowed to place bets on market.id 20 and its odds with id 2 and 3 because fixture status is not started ( 0) AND market status is active AND odd status is not_resulted (0) AND odd is active (is_active=true).
It's forbidden to place bets on market.id 20 and its odd with id 1 because odd is NOT active (is_active=false).
It's forbidden to place bets on any outcome of market.id 21 because market status is suspended (NOT active).

Settlement & Resettlement

Settlement and resettlement are critical components of the betting lifecycle that ensure accurate bet outcomes and proper financial handling. This section covers the key principles and mechanisms for processing bet settlements.

Settlement Principles

For settlement processing, partners MUST rely primarily on odd statuses rather than market statuses. Market status should only be used to satisfy the Betting and Display conditions as outlined in the market status requirements.

Resettlement Requirements

Flexible Status Transitions

Partners MUST implement robust resettlement mechanisms that can handle any sequence of status transitions. There are no strict rules governing how odds move from status to status, as different models may employ various approaches for different sports.

Supported Transition Sequences

The system must support complex resettlement scenarios, including but not limited to:

  • not_resultedwonlost
  • not_resultedlostnot_resultedrefunded
  • wonnot_resultedrefunded
  • lostwonlost
  • refundednot_resultedwon
  • Any other valid combination of status transitions

Implementation Requirements

  1. State Tracking: Maintain accurate bet state throughout all resettlement cycles
  2. Financial Reconciliation: Properly adjust player balances for each status change

Bets Rollback

Bets rollback is a specialized settlement mechanism that affects the settlement and resettlement process. For detailed information about the bets_rollback event, including its parameters, reasons, and implementation requirements, refer to the bets_rollback section.

Settlement Impact

The bets_rollback event directly impacts settlement and resettlement operations by:

  • Cancelling Bets: All bets within the specified time range and markets are voided, regardless of their current settlement status
  • Reversing Settlements: If bets have already been settled (won/lost), the rollback reverses these settlements and restores the original stake
  • Financial Reconciliation: Player balances are adjusted to reflect the bet cancellation

Swagger