Skip to main content

Bifrost API Reference

Source: BFST-Bifrost API Public Documentation (2026-03-06)


1. Sports Identifiers

Sport NameSport ID
FOOTBALL1
CRICKET2
KABADDI19

2. Queue Architecture

All queue names are prefixed with {customerPrefix} — the customer's unique prefix assigned by Bifrost.

2.1 Outbound Queues (from Bifrost to customer)

Queue NameProducesDescription
{customerPrefix}.category.queueCategoryMessages containing category (Country or Competition) details.
{customerPrefix}.event.queueEventMessages containing full event details. Upon arrival, it should fully override the existing snapshot after version check.
{customerPrefix}.market-catalogue.queueMarketCatalogueMessages containing full market static details. Upon arrival, it should override the existing snapshot after the version check.
{customerPrefix}.market-book.queueMarketBookMessages containing full market dynamic details. Upon arrival, it should override the existing snapshot after the version check.

2.2 Broker Data Queues (bet lifecycle)

Bets (single bets)

Queue NameProducesDescription
{customerPrefix}.bets.snapshot.queueBetSnapshotMessages containing the Bet holding the current state of the bet. Covers: acceptance, rejections, voiding, size matching and cancellation. Upon arrival, fully override the existing snapshot after the version check.
{customerPrefix}.bets.cancel.queueBetSnapshotMessages containing cancelled bet. Upon arrival, should fully override existing snapshot after version check.

Multibets

Queue NameProducesDescription
{customerPrefix}.bets.multi-bet.snapshot.queueMultiBetSnapshotMessages containing the Multibet holding the current state of the bet. Covers: acceptance, rejections, voiding. Upon arrival, fully override the existing snapshot after the version check.
{customerPrefix}.bets.multi-bet.outcomes.queueMultiBetOutcomeMessages containing full bet outcome snapshot. Upon arrival, should fully override existing snapshot after version check.
{customerPrefix}.bets.multi-bet.price.queueMultibetPriceBetSnapshotMessages containing multibet price response.

Bet Outcomes (settlement)

Queue NameProducesDescription
{customerPrefix}.bets.outcomes.queueBetOutcomeMessages containing full bet outcome snapshot. Upon arrival, should fully override existing snapshot after version check.

3. Outbound Data Structures

3.1 Category

Queue: {customerPrefix}.category.queue

Routing patterns:

  • customerPrefix — customer unique prefix

Model

FieldData TypeDescription
idstringCategory id
parentIdstringLink to parent. Category should be treated as a hierarchy.
categoryTypestringType of category. e.g. 'Country' or 'Competition'
valuestringName of category. e.g. Country (England), Competition (Premier League)
sportIdstringSport Id

Proto

message Category {
string id = 1;
string parentId = 2;
string categoryType = 3;
string value = 4;
string sportId = 5;
}

3.2 Event

Queue: {customerPrefix}.event.queue

Routing patterns:

  • customerPrefix — customer unique prefix

Upon arrival, it should fully override the existing snapshot after version check.

Event Model

FieldData TypeDescription
eventIdstringA unique id for the event.
namestringA display name for the event.
startTimestringThe event start time in UTC zone. E.g. '2025-05-06T18:00'
sportIdstringSport id
categoryIdstringThe category/competition reference
competitorsCompetitor[]A list of competitors that are involved in this event.
externalIdsEventMapping[]A possibly empty list of other providers event ids. The list may change at any time as no mapping should be assumed as static nor unique. Example providers: Betfair, Sportradar.
statusstringEvent status enum. One of: CANCELLED — the game was cancelled; POSTPONED — the game was postponed.
versionlongVersion of event. This can be used for deduplication and ordering of updates downstream.

Event Proto

message Event {
string eventId = 1;
string name = 2;
string startTime = 3;
string categoryId = 4;
repeated Competitor competitors = 5;
repeated EventMapping externalIds = 6;
string status = 7;
int64 version = 8;
string sportId = 9;
}

EventMapping Model

FieldData TypeDescription
providerstringProvider of the id e.g. Betfair
eventIdstringThe id of the event for the provider.

EventMapping Proto

message EventMapping {
string provider = 1;
string eventId = 2;
}

3.3 Competitor / Team

Model

FieldData TypeDescription
idstringCompetitor id
shortNamestringCompetitor short name. e.g. 'ENG'
fullNamestringCompetitor full name. e.g. 'England'

Proto

message Competitor {
string id = 1;
string shortName = 2;
string fullName = 3;
}

3.4 MarketCatalogue

Queue: {customerPrefix}.market-catalogue.queue

Routing patterns:

  • customerPrefix — customer unique prefix

Messages containing full market static details. Upon arrival, it should override the existing snapshot after the version check.

MarketCatalogue Model

FieldData TypeDescription
idstringThe unique id of the market.
eventIdstringThe id of the event.
marketTypestringThe market type.
oddsTypestringOdds type.
namestringThe market name.
startTimestringThe market start time.
prematchOnlybooleanBoolean flag indicating whether the market will be open during prematch only or will go live on game start.
sortOrderlongRecommended sort order of the market.
runnersRunnerCatalogue[]The set of betable selections on the market.
metadataMarketMetadataThe market metadata.
versionlongVersion of market. This can be used for deduplication and ordering of updates downstream.
sportIdstringThe id of the sport.
tradingMarketTypestringOriginal market type (from Bifrost trading system internals).

MarketCatalogue Proto

message MarketCatalogue {
string id = 1;
string eventId = 2;
string marketType = 3;
string name = 4;
string startTime = 5;
string oddsType = 6;
bool prematchOnly = 7;
int64 sortOrder = 8;
repeated RunnerCatalogue runner = 9;
MarketMetadata metadata = 10;
int64 version = 11;
string sportId = 12;
string tradingMarketType = 13;
}

RunnerCatalogue Model

FieldData TypeDescription
idlongThe id of the runner.
namestringThe name of the runner.
sortPriorityintegerThe recommended positional order of the selection when being displayed.
metadatamap<String, String>The metadata of the runner.

RunnerCatalogue Proto

message RunnerCatalogue {
int64 id = 1;
string name = 2;
int32 sortPriority = 3;
map<string, string> metadata = 4;
}

MarketMetadata Model

FieldData TypeDescription
competitorsMarketCompetitorMetadataMarket competitors metadata.

MarketMetadata Proto

message MarketMetadata {
repeated MarketCompetitorMetadata competitor = 1;
}

MarketCompetitorMetadata Model

FieldData TypeDescription
namestringMarket competitor full name.
shortNamestringMarket competitor short name.

MarketCompetitorMetadata Proto

message MarketCompetitorMetadata {
string name = 1;
string shortName = 2;
}

3.5 MarketBook

Queue: {customerPrefix}.market-book.queue

Routing patterns:

  • customerPrefix — customer unique prefix

Messages containing full market dynamic details. Upon arrival, it should override the existing snapshot after the version check.

MarketBook Model

FieldData TypeDescription
marketIdstringThe unique id of the market.
marketStatusstringThe status of the market. One of: INACTIVE, OPEN, BALL_RUNNING, SUSPENDED, CLOSED, SETTLED. Note: BALL_RUNNING is currently supported but is planned for deprecation.
maxMarketdoubleMax market liability per b2b client member in HKD.
maxMarketCurrenciesmap<string, double>Max market liability per b2b client member in provided currencies.
runnersRunner[]The set of betable selections on the market.
variablesmap<string, string>The market variables.
versionLongThe version of market. This can be used for deduplication and ordering of updates downstream.
sportIdstringThe id of the sport.
minStakedouble (optional)Minimum stake.
minStakeCurrenciesmap<string, double>Minimum stake in provided currencies.
tradingMarketTypestringOriginal market type (from Bifrost trading system internals).
oddsTypestringThe odds type, one of: HAAR_JEET, DECIMAL. Authoritative pricing format — use this field (not MarketCatalogue.oddsType) to determine how to interpret runner prices.

marketStatus Values

ValueMeaning
INACTIVEMarket is not available for bet placement.
OPENMarket is available for bet placement.
BALL_RUNNINGMarket is currently in ball-running state. Currently supported but planned for deprecation.
SUSPENDEDMarket is not available for bet placement.
CLOSEDMarket is not available for bet placement.
SETTLEDMarket is fully settled.

MarketBook Proto

message MarketBook {
string marketId = 1;
string marketStatus = 2;
double maxMarket = 3;
map<string, double> maxMarketCurrencies = 4;
repeated Runner runner = 5;
map<string, string> variables = 6;
int64 version = 7;
string sportId = 8;
optional double minStake = 9;
map<string, double> minStakeCurrencies = 10;
string tradingMarketType = 11;
string oddsType = 12;
}

3.6 Runner / RunnerPriceLadder / RunnerPriceSize

Runner Model

FieldData TypeDescription
idstringThe id of the runner that should be provided when placing a bet.
statusstringThe bettable status of the runner.
priceLadderRunnerPriceLadderThe prices ladder of the runner.
versionlongThe runner version.

Runner Proto

message Runner {
int64 id = 1;
string status = 2;
RunnerPriceLadder priceLadder = 3;
int64 version = 4;
}

RunnerPriceLadder Model

FieldData TypeDescription
availableToBackRunnerPriceSize[]The available BACK prices and available max stake to bet at that price.
availableToLayRunnerPriceSize[]The available LAY prices and available max stake to bet at that price. Only populated for exchange markets.

RunnerPriceLadder Proto

message RunnerPriceLadder {
repeated RunnerPriceSize availableToBack = 1;
repeated RunnerPriceSize availableToLay = 2;
}

RunnerPriceSize Model

FieldData TypeDescription
pricedoubleThe price at which this runner can be bettable by customer.
midPricedoubleThe mid price.
sizedouble(field 3 in proto)
linedoubleThe runner line.
midLinedoubleThe runner mid line.
priceIndexintegerThe position order of the line.
maxStakedoubleThe maximum stake size of a bet at this price.
maxStakeCurrenciesmap<string, double>The maximum stake size of a bet at this price in provided currencies.

RunnerPriceSize Proto

message RunnerPriceSize {
double price = 1;
double midPrice = 2;
double size = 3;
double line = 4;
double midLine = 5;
int32 priceIndex = 6;
double maxStake = 7;
map<string, double> maxStakeCurrencies = 8;
}

3.7 FootballStatistics

Note: Football-specific live statistics message.

FootballStatistics Model

FieldTypeDescription
eventIdStringUnique identifier for the event
matchPhaseStringCurrent phase of the match
phaseMinuteIntegerMinute within the current phase
homeTeamNameStringName of the home team
awayTeamNameStringName of the away team
goalsHalfTimeStateStatisticGoals scored by half-time
goalsFullTimeStateStatisticGoals scored by full-time
goalsOvertimeHalfTimeStateStatisticGoals scored by overtime half-time
goalsOvertimeFullTimeStateStatisticGoals scored by overtime full-time
goalsPenaltyKicksStateStatisticGoals scored by penalty kicks
cornersHalfTimeStateStatisticCorners taken by half-time
cornersFullTimeStateStatisticCorners taken by full-time
cornersOvertimeHalfTimeStateStatisticCorners taken by overtime half-time
cornersOvertimeFullTimeStateStatisticCorners taken by overtime full-time
yellowCardsHalfTimeStateStatisticYellow cards by half-time
yellowCardsFullTimeStateStatisticYellow cards by full-time
yellowCardsOvertimeHalfTimeStateStatisticYellow cards by overtime half-time
yellowCardsOvertimeFullTimeStateStatisticYellow cards by overtime full-time
redCardsHalfTimeStateStatisticRed cards by half-time
redCardsFullTimeStateStatisticRed cards by full-time
redCardsOvertimeHalfTimeStateStatisticRed cards by overtime half-time
redCardsOvertimeFullTimeStateStatisticRed cards by overtime full-time

FootballStatistics Proto

message FootballStatistics {
string eventId = 1;
string matchPhase = 3;
int32 phaseMinute = 4;
string homeTeamName = 5;
string awayTeamName = 6;
StateStatistic goalsHalfTime = 7;
StateStatistic goalsFullTime = 8;
StateStatistic goalsOvertimeHalfTime = 9;
StateStatistic goalsOvertimeFullTime = 10;
StateStatistic goalsPenaltyKicks = 11;
StateStatistic cornersHalfTime = 12;
StateStatistic cornersFullTime = 13;
StateStatistic cornersOvertimeHalfTime = 14;
StateStatistic cornersOvertimeFullTime = 15;
StateStatistic yellowCardsHalfTime = 16;
StateStatistic yellowCardsFullTime = 17;
StateStatistic yellowCardsOvertimeHalfTime = 18;
StateStatistic yellowCardsOvertimeFullTime = 19;
StateStatistic redCardsHalfTime = 20;
StateStatistic redCardsFullTime = 21;
StateStatistic redCardsOvertimeHalfTime = 22;
StateStatistic redCardsOvertimeFullTime = 23;
}

StateStatistic Model

FieldTypeDescription
homeStringStatistic for the home team
awayStringStatistic for the away team

StateStatistic Proto

message StateStatistic {
int32 home = 1;
int32 away = 2;
}

3.8 BetSnapshot

Queue: {customerPrefix}.bets.snapshot.queue

Covers: acceptance, rejections, voiding, size matching and cancellation.

BetSnapshot Model

FieldData TypeRequiredDescription
requestIdStringYesA request unique identifier. It could be generated on the customer side.
betIdLongYesUnique identifier for the placed bet. Generated on Public API level.
memberCodeStringYesCode identifying the member placing the bet.
statusStringYesBet status enum. One of: PENDING — the bet placement request has been sent, waiting for provider's response; FAILED — the bet placement has failed; PLACED — the bet was successfully placed (fully matched); VOIDED — the bet was voided by the provider/operator; PARTIALLY_MATCHED — part of the bet has been matched, the rest is waiting in the market; UNMATCHED — the bet is in the market but has not been matched yet; CANCEL_PENDING — the client requested to cancel the bet (or remaining part), but the provider has not yet confirmed the cancellation; CANCELLED — the bet (or its unmatched portion) was canceled by the user; LAPSED — the bet automatically expired because the market closed or conditions were no longer valid.
sideStringYesSide enum. One of: BACK — selection occurrence side selection; LAY — selection non-occurrence side selection.
marketIdStringYesIdentifier for the specific market within an event.
runnerIdLongYesIdentifier for the specific runner within a market.
sizedoubleYesBet size requested for placement in customer currency.
sizeMatcheddoubleYesBet size matched at the time of bet request placement. Applicable for Exchange markets.
oddsdoubleOptionalAccepted bet odds.
lineintOptionalThe bet line, can be empty.
errorMessageStringOptionalMessage from a provider accompanying failed or voided bet; empty if a bet is placed.
errorCodeStringOptionalCode from a provider accompanying failed or voided bet; empty if a bet is placed.
versionlongYesTimestamp when the bet was placed (UTC).
sizeRemainingdoubleYesThe remaining unmatched portion of the bet that is still active in the market. Applicable for Exchange markets.
sizeLapseddoubleYesThe portion of the bet that has lapsed (i.e. was not matched before the market closed or the event started) and was automatically removed. Applicable for Exchange markets.
sizeCancelleddoubleYesThe portion of the bet that was cancelled by the user or system before being matched. Applicable for Exchange markets.
sizeVoideddoubleYesThe portion of the bet that was voided (e.g. due to event cancellation or market rule changes). Applicable for Exchange markets.
averageOddsdoubleYesThe weighted average odds at which the bet was matched. If the bet is partially matched at different odds, this value reflects the overall effective odds based on matched sizes. Applicable for Exchange markets.
voidReasonStringOptionalMessage from operator accompanying failed or voided bet.

BetSnapshot Proto

message BetSnapshot {
string requestId = 1;
int64 betId = 2;
string marketId = 3;
int64 runnerId = 4;
double size = 5;
optional double odds = 6;
optional int32 line = 7;
string side = 8;
string memberCode = 9;
string status = 10;
optional string errorMessage = 11;
optional string errorCode = 12;
int64 version = 13;
double sizeMatched = 14;
double sizeRemaining = 15;
double sizeLapsed = 16;
double sizeCancelled = 17;
double sizeVoided = 18;
double averageOdds = 19;
optional string voidReason = 20;
}

3.9 BetOutcomeSnapshot

Queue: {customerPrefix}.bets.outcomes.queue

Settlement information. Upon arrival, should fully override existing snapshot after version check.

BetOutcomeSnapshot Model

FieldData TypeDescription
requestIdString(from BetSnapshot.requestId)
betIdlongBet id.
outcomestringBet outcome enum. One of: WON — the bet has won; LOST — the bet has lost; VOID — the bet was voided.
pnldoubleBet profit and loss outcome.
versionLongTimestamp when the bet was settled (UTC).
sizeSettleddoubleProvider matched size in the case of a partial match.

BetOutcome Proto

message BetOutcomeSnapshot {
string requestId = 1;
int64 betId = 2;
string outcome = 3;
double pnl = 4;
int64 version = 5;
double sizeSettled = 6;
}

3.10 MultiBetSnapshot

Queue: {customerPrefix}.bets.multi-bet.snapshot.queue

Covers: acceptance, rejections, voiding.

MultiBetSnapshot Model

FieldData TypeRequiredDescription
requestIdStringYesA request unique identifier. It could be generated on the customer side.
betIdLongYesUnique identifier for the placed bet. Generated on Public API level.
statusStringYesBet status enum: PENDING, FAILED, PLACED, VOIDED.
errorMessageStringOptionalMessage from a provider accompanying failed or voided bet.
errorCodeStringOptionalCode accompanying failed or voided bet.
versionlongYesTimestamp when the bet was placed (UTC).
stakedoubleOptionalStake.
multibetPricedoubleOptionalMultibet price.
memberCodeStringYesCode identifying the member placing the bet.
voidReasonStringOptionalMessage from operator accompanying failed or voided bet.
multibetLegsList<MultibetLegSnapshot>YesList of multibet legs.

MultiBetSnapshot Proto

message MultiBetSnapshot {
string requestId = 1;
int64 betId = 2;
string status = 3;
optional string errorMessage = 4;
optional string errorCode = 5;
optional double stake = 6;
optional double multibetPrice = 7;
string memberCode = 8;
optional string voidReason = 9;
repeated MultibetLegSnapshot multibetLeg = 10;
int64 version = 11;
}

message MultibetLegSnapshot {
string eventId = 1;
string marketId = 2;
int64 selectionId = 3;
string side = 4;
double requestedOdds = 5;
double odds = 6;
}

MultibetLegSnapshot Model

FieldData TypeDescription
eventIdStringIdentifier for the specific event within a multibet event.
marketIdStringIdentifier for the specific market within a multibet event.
selectionIdLongIdentifier for the specific selection within a multibet event.
sideStringSide enum. BACK — selection occurrence side selection.
requestedOddsdoubleThe requested odds within a multibet event.
oddsdoubleThe accepted odds within a multibet event.
memberCodeStringCode identifying the member placing the bet.
voidReasonStringMessage from operator accompanying failed or voided bet.

3.11 MultiBetOutcomeSnapshot

Queue: {customerPrefix}.bets.multi-bet.outcomes.queue

MultiBetOutcomeSnapshot Model

FieldData TypeDescription
requestIdStringA request unique identifier. It could be generated on the customer side.
betIdlongBet id.
outcomestringBet outcome enum: WON, LOST, VOID.
pnldoubleBet profit and loss outcome.
versionLongTimestamp when the bet was settled (UTC).
sizeSettleddoubleProvider matched size in the case of a partial match.
voidReasonstringMessage from operator accompanying failed or voided bet.
unvoidReasonstringMessage from operator accompanying failed or unvoided bet.

MultiBetOutcome Proto

message MultiBetOutcomeSnapshot {
string requestId = 1;
int64 betId = 2;
string outcome = 3;
double pnl = 4;
int64 version = 5;
double sizeSettled = 6;
string voidReason = 7;
string unvoidReason = 8;
}

3.12 MultibetPriceSnapshot

Queue: {customerPrefix}.bets.multi-bet.price.queue

MultibetPriceSnapshot Model

FieldData TypeDescription
requestIdstringA request unique identifier.
marginedOddsdoubleMargined odds of multibet price request.
successbooleanStatus of the multibet price request.
errorMessagestringError message.

MultibetPriceSnapshot Proto

message MultiBetPriceSnapshot {
string requestId = 1;
double marginedOdds = 2;
string success = 3;
optional string errorMessage = 4;
}

4. REST Betting API

Base URL: Provided by Bifrost on customer onboarding.

Authentication: All endpoints require Authorization: Bearer YOUR_API_TOKEN.

Content-Type: application/json


4.1 Place Bet

Endpoint: POST /api/v1/bets/place

Description: Allows the customer to place a new bet on an event.

Note: All successful bet responses will be returned with PENDING status. After the provider processes the bet placement, results (placed or not) will be provided in the RabbitMQ queue.

Request Headers

Authorization: Bearer YOUR_API_TOKEN
Content-Type: application/json

PlaceBetRequest Fields

FieldTypeRequiredDescription
sportIdStringYesSport identifier.
marketIdStringYesIdentifier for the specific market within an event.
runnerIdLongYesIdentifier for the specific runner within a market.
priceIndexIntegerNoThe index of the price level on the price ladder within the selection. For example, if a selection had prices 1.91 and 1.90 then a price_level_index of 0 would be 1.91 and 1 would be for 1.90.
sizeBigDecimalYesBet size requested for placement.
memberSizeBigDecimalYesBet size initially requested by the member (before PT).
oddsBigDecimalYesBet odds requested for placement.
lineIntegerNoBet line, for line fancy markets only.
sideSideYesSide enum. One of: BACK — selection occurrence side selection; LAY — selection non-occurrence side selection.
memberCodeStringYesCode identifying the member placing the bet.
ipAddressStringYesIP address of the client placing the bet.
currencyStringNoCurrency code (e.g., "USD").
requestIdStringNoA unique identifier that can be generated on the customer side for the request to ensure idempotency.

Request Body Example

{
"sportId": "2",
"marketId": "9.1223445",
"runnerId": 100123,
"priceIndex": 0,
"size": 50,
"memberSize": 50,
"odds": 100,
"line": 10,
"side": "BACK",
"memberCode": "member_code",
"currency": "HKD",
"ipAddress": "member_ip_address",
"requestId": "123456789"
}

PlaceBetResponse Fields

FieldTypeDescription
betIdLongUnique identifier for the placed bet.
requestIdStringA request unique identifier.
memberCodeStringCode identifying the member placing the bet.
statusBetStatusBet status enum: PENDING, FAILED, PLACED, VOIDED.
sideSideBACK or LAY.
sizeBigDecimalBet size requested for placement.
oddsBigDecimalBet odds requested for placement.
lineIntegerBet line requested for placement.
versionlongTimestamp when the bet was placed (UTC).

Response Example — Success (201 Created)

{
"id": 3,
"requestId": "123456789",
"memberCode": "member_code",
"status": "PENDING",
"side": "BACK",
"size": 5,
"memberSize": 5,
"odds": 100,
"line": 10,
"version": 1727702890748
}

PlaceBetErrorResponse Fields

FieldTypeDescription
errorCodeStringCode representing the type of error.
errorMessageStringHuman-readable message describing the error.
versionStringTimestamp when the error was returned.

Response Example — Error (4xx)

[
{
"error_code": "some_error_code",
"errorMessage": "Member code is missing",
"version": "2024-10-10T12:21:00.995612Z"
}
]

4.2 Cancel Bet

Endpoint: POST /api/v1/bets/cancel

Note: Cancel bet is only supported by exchanges.

Description: Allows the customer to cancel a bet.

Note: All successful cancel responses will be returned with CANCEL_PENDING status. After the provider has processed the bet results (cancelled or not), they will be sent to the RabbitMQ queue.

Request Headers

Authorization: Bearer YOUR_API_TOKEN
Content-Type: application/json

Request Body

FieldTypeDescription
marketIdStringMarket identifier.
betIdStringBet identifier.

Request Body Example

{
"marketId": "9.1223445",
"betId": "2"
}

Response Example — Success (201 Created)

{
"id": 3,
"status": "CANCEL_PENDING",
"version": 1727702890748
}

Response Example — Error (4xx)

[
{
"error_code": "some_error_code",
"errorMessage": "Cancel bet request is not valid",
"version": "2024-10-10T12:21:00.995612Z"
}
]

4.3 Get Outcomes

Endpoint: POST /api/v1/bets/outcomes

Description: Allows the customer to request bet outcomes with optional filtering by market ID and pagination support.

Request Headers

Authorization: Bearer YOUR_API_TOKEN
Content-Type: application/json

Request Parameters

FieldTypeRequiredDescription
marketIdStringNoFilter results by specific market ID. If not provided, returns outcomes for all markets.
pageSizeIntegerNoNumber of results per page. Default is 1000 if not specified.
pageNumberIntegerNoPage number starting from 0. Default is 0 if not specified.

Request Body Example

{
"marketId": "14.780243_3",
"pageSize": 20,
"pageNumber": 0
}

Response — Success (200 OK)

FieldTypeDescription
contentArrayArray of bet outcome objects (BetOutcomeSnapshot).
pageNumberIntegerCurrent page number (0-based).
pageSizeIntegerNumber of items per page.
totalElementsLongTotal number of bet outcomes available.
totalPagesIntegerTotal number of pages.
firstBooleanTrue if this is the first page.
lastBooleanTrue if this is the last page.
emptyBooleanTrue if the content array is empty.

Content item fields:

  • requestId (String): Original request ID from the bet.
  • betId (Long): Unique bet identifier.
  • outcome (String): WON, LOST, VOID, etc.
  • pnl (BigDecimal): Customer profit/loss amount.
  • sizeSettled (BigDecimal): Amount that was settled.
  • version (Long): Version timestamp.

Response Example — Success (200 OK)

{
"content": [
{
"requestId": "1e28c0ab-d799-48d0-bb0f-c1c0ef7bfd78",
"betId": 12345,
"outcome": "WON",
"pnl": 150.50,
"sizeSettled": 100.00,
"version": 1704067260995
},
{
"requestId": "2f39d1bc-e8aa-59e1-cc1g-d2d1fg8cgd89",
"betId": 12346,
"outcome": "LOST",
"pnl": -75.25,
"sizeSettled": 75.25,
"version": 1704067261123
}
],
"pageNumber": 0,
"pageSize": 20,
"totalElements": 150,
"totalPages": 8,
"first": true,
"last": false,
"empty": false
}

Notes

  • Authentication Required: Valid Bearer token with appropriate betting permissions.
  • Pagination: Default page size 1000. Use pageSize and pageNumber to control.
  • Market Filtering: Without marketId, all bet outcomes for the customer are returned.
  • Ordering: Results are ordered by bet ID in descending order (newest first).
  • Customer Scope: Only returns bet outcomes for the authenticated customer.
  • Performance: For better performance, use pagination with smaller page sizes for large result sets.

Error Responses

// 4xx
[{ "error_code": "INVALID_REQUEST", "errorMessage": "Invalid pagination parameters", "version": "2025-01-10T12:21:00.995612Z" }]

// 401 Unauthorized
[{ "error_code": "UNAUTHORIZED", "errorMessage": "Invalid or missing authorization token", "version": "2025-01-10T12:21:00.995612Z" }]

// 403 Forbidden
[{ "error_code": "INSUFFICIENT_PERMISSIONS", "errorMessage": "User does not have permission to access bet outcomes", "version": "2025-01-10T12:21:00.995612Z" }]

4.4 Get Multibet Price

Endpoint: POST /api/v1/bets/multibet/requestprice

Description: Allows the customer to request a price on a multibet.

Note: All successful price requests will have MULTIBET_PRICE_REQUESTED status and all successful price responses will have MULTIBET_PRICE_FILLED status and will be sent into the RabbitMQ queue.

Request Headers

Authorization: Bearer YOUR_API_TOKEN
Content-Type: application/json

Request Body

FieldTypeRequiredDescription
requestIdStringNoOptional, random UUID will be generated if not included.
multibetLegsArrayYesFrom 2 to 20 legs. Each leg has: eventId, marketId, side, selectionId.

Request Body Example

{
"requestId": "testRequestId1",
"multibetLegs": [
{
"eventId": "14.221657_1",
"marketId": "14.780243_3",
"side": "BACK",
"selectionId": 2084382
},
{
"eventId": "14.221657_1",
"marketId": "14.780244_3",
"side": "LAY",
"selectionId": 2084370
}
]
}

Response — Success (201 Created)

{
"requestId": "1e28c0ab-d799-48d0-bb0f-c1c0ef7bfd78",
"legs": [
{
"eventId": "14.221657_1",
"marketId": "14.780243_3",
"selectionId": "2084382",
"side": "Back"
},
{
"eventId": "14.221657_1",
"marketId": "14.780244_3",
"selectionId": "2084370",
"side": "Back"
}
]
}

Response — Error (4xx)

[
{
"error_code": "some_error_code",
"errorMessage": "Event id is missing",
"version": "2025-04-10T12:21:00.995612Z"
}
]

4.5 Place Multibet

Endpoint: POST /api/v1/bets/multibet/place

Description: Allows the customer to place a new multibet on an event.

Note: All successful bet responses will be returned with PENDING status. After the provider processes the bet placement, results (placed or not) will be provided in the RabbitMQ queue.

Request Headers

Authorization: Bearer YOUR_API_TOKEN
Content-Type: application/json

Request Body

FieldTypeRequiredDescription
stakenumberYesStake amount.
currencyStringYesCurrency code (e.g., "hkd").
memberCodeStringYesCode identifying the member placing the bet.
accountStringYesAccount identifier.
ipStringYesIP address of the client.
stakeFactornumberYesStake factor.
multiBetLegsArrayYesList of legs. Each leg has: marketId, runnerId, side, requestedOdds, expectedOperatorOdds, priceLevelIndex, tolerancePercentage, eventId.
multiBetPricenumberYesCombined multibet price.
positionTakevalue or nullNoPosition take.
fixedPendingUntilvalue or nullNoFixed pending until.
turnoverRebatePercentagevalue or nullNoTurnover rebate percentage.
requestIdStringNoOptional request identifier for idempotency.
placedDatenumberNoTimestamp of placement.

Request Body Example

{
"stake": 10,
"currency": "hkd",
"memberCode": "testCustomer11",
"account": "testCustomer",
"ip": "127.0.0.1",
"stakeFactor": 10,
"multiBetLegs": [
{
"requestedOdds": 2.16,
"expectedOperatorOdds": 2.16,
"priceLevelIndex": 0,
"tolerancePercentage": 0
},
{
"requestedOdds": 9.00,
"expectedOperatorOdds": 9.00,
"priceLevelIndex": 0,
"tolerancePercentage": 0
}
],
"multiBetPrice": 101.626319807,
"positionTake": null,
"fixedPendingUntil": null,
"turnoverRebatePercentage": null,
"requestId": "8c9a42c2-0784-4481-a2b4-97ff528daa08",
"placedDate": 1747396906880
}

Response — Success (201 Created)

Returns the full multibet snapshot including all leg details, multiBetPrice, and a placedTime.

Response — Error (4xx)

[
{
"error_code": "some_error_code",
"errorMessage": "Event id is missing",
"version": "2025-04-10T12:21:00.995612Z"
}
]

5. Key Domain Rules

5.1 oddsType Semantics

MarketCatalogue.oddsType (string) — represents market STRUCTURE:

  • Values seen in practice: LINE, ODDS
  • LINE: Line/session markets (have a target runs/value). Example: Over/Under session markets in cricket.
  • ODDS: Standard odds markets with multiple runners.
  • Note: Both LINE and ODDS markets use haar jeet (paise) pricing in practice.

MarketBook.oddsType (string) — represents PRICING FORMAT (authoritative for display):

  • HAAR_JEET: Price is in paise. e.g. 100 = even money (2.0 decimal), 172 = 2.72 decimal.
  • DECIMAL: Standard decimal odds (e.g. 2.72 means 2.72).
  • Always prefer MarketBook.oddsType over MarketCatalogue.oddsType for determining how to interpret runner prices.

5.2 marketStatus Lifecycle

INACTIVE → OPEN → SUSPENDED → OPEN (can oscillate)
→ CLOSED → SETTLED
BALL_RUNNING (deprecated, treat as suspended/not available)
  • Only OPEN status allows bet placement.
  • BALL_RUNNING is currently supported but planned for deprecation.
  • SUSPENDED and INACTIVE do not allow bets.
  • CLOSED and SETTLED are terminal states.

5.3 tradingMarketType

The tradingMarketType field appears in both MarketCatalogue and MarketBook. It represents the original market type string from Bifrost's internal trading system. It is informational — Hannibal does not need to parse or act on this field for routing or settlement decisions.

5.4 Version Field Usage

The version field on all messages (Category, Event, MarketCatalogue, MarketBook, BetSnapshot, etc.) is a monotonically increasing value used for deduplication and ordering. Upon receiving a message, the consumer should only process and store it if the incoming version is greater than the stored version. Never process a lower version — it is a stale update.

5.5 MarketCatalogue + MarketBook Correlation

  • MarketCatalogue.id == MarketBook.marketId — this is the only join key.
  • MarketCatalogue provides static metadata: market type, name, start time, runner names.
  • MarketBook provides dynamic data: prices, status, limits.
  • A market is valid and bettable only when BOTH MarketCatalogue AND MarketBook are present.

5.6 Side Values

ValueMeaning
BACKSelection occurrence side — bet FOR the selection to happen.
LAYSelection non-occurrence side — bet AGAINST the selection happening. Only supported on exchange markets.

5.7 Cancel Bet Constraint

Cancel bet (POST /api/v1/bets/cancel) is only supported by exchanges. Non-exchange markets (bookmaker/sportsbook type markets within Bifrost) do not support cancellation.


6. Hannibal Integration Notes

OddsType Semantics (Confirmed with Michael Cheremuhin, 2026-03-09)

  • MarketCatalogue.oddsType: LINE or ODDS — represents market STRUCTURE (trading system internals).
    • LINE: line/session markets (have a target runs value).
    • ODDS: standard odds markets (multiple runners).
    • Both LINE and ODDS use haar jeet (paise) pricing.
  • MarketBook.oddsType: HAAR_JEET or DECIMAL — represents PRICING FORMAT (authoritative for display).
    • Prefer MarketBook.oddsType over MarketCatalogue.oddsType for display decisions.
    • If MarketBook.oddsType = HAAR_JEET: price is in paise (e.g. 100 = even money, 172 = 2.72 decimal).
    • If MarketBook.oddsType = DECIMAL: standard decimal odds.

Queue Usage

  • bets.snapshot.queue: ALL bet status updates (acceptance, rejection, cancellation, voiding, size matching).
  • bets.outcomes.queue: Settlement information only.
  • bets.cancel.queue: Cancelled bet snapshots (also BetSnapshot, but separate queue for cancellation flow).
  • NO separate "bets.cancel.queue" carries a different message type — it still produces BetSnapshot.

PlaceBet: providerId field

NOT in current API spec. Was removed. Do not send.

MarketCatalogue + MarketBook Correlation

  • MC.id == MB.marketId (only join key).
  • MC: static metadata (market type, name, start time, runner names).
  • MB: dynamic data (prices, status, limits).
  • A market is valid/bettable only when BOTH MC and MB are present.
  • Michael: "we recommend to store both entities and consider market to be correct and available for betting if both parts are present."

LAY Bets on 9.x Markets

  • Bifrost API supports side: LAY syntactically.
  • LAY is defined as: selection non-occurrence side selection.
  • Cancel bet is exchange-only (9.x markets are exchange markets in Bifrost's classification).
  • All LAY bets currently fail with error code 0.1001 — under investigation with Bifrost.

Odds Conversion (Hannibal Internal)

  • All canonical odds stored as decimal in Hannibal DB.
  • BifrostAdapter converts at API boundary: haarJeetToDecimal() on read, decimalToHaarJeet() on write.
  • Haar jeet formula:
    • decimal = 1 + (haarJeet / 100)
    • haarJeet = (decimal - 1) * 100
  • Example: haarJeet = 100decimal = 2.0 (even money); haarJeet = 172decimal = 2.72.

Currency

  • Bifrost operates in HKD. Exchange rate: 10 (1 FP = 0.1 HKD). Configured in the providers table.
  • The currency field in PlaceBetRequest is optional per API spec.

memberCode

  • MUST be order.userId (the Hannibal user's UUID). NOT a static platform config value.
  • Using a static memberCode breaks per-user risk management on Bifrost's side.

Bet Status Mapping (Bifrost → Hannibal)

Bifrost BetSnapshot.statusHannibal Order Status
PENDINGsubmitted
PLACEDaccepted
PARTIALLY_MATCHEDpartially_accepted
FAILEDdeclined
CANCELLEDcancelled
LAPSEDlapsed
VOIDEDsettled (settlementOutcome: void)

Settlement Mapping (Bifrost → Hannibal)

Bifrost BetOutcomeSnapshot.outcomeHannibal settlementOutcome
WONwin
LOSTlose
VOIDvoid