Odds operations

Get the configuration for all platform interactions

The namespace is of course called odds. All methods return promises. The general design of the namespace follows this pattern unless stated otherwise:

📘

General call:

sdk.odds
  .someMethod()
  .then((response) => {
    // Handle response
  })
  .catch((error) => {
    // Handle error
  });

🚧

N.B

Odds are never returned for a match that has already finished. The SDK resolves the status of every match before requesting its odds and treats a finished match as a match without odds.


The responses are comprised of different objects you can find here.

Match related operations

Get odds for matches

Method: getByMatchIds(matchIds, filters?)

Model:

The method returns a Map instance where the keys are the match IDs and the values are Array instances of MatchOddsModel. Every requested match ID is present in the Map — a match without odds, including a match that has already finished, is an empty Array.

Filters object:

  • scopeType: ScopeTypeEnum.

    Specifies the time period of the match for which the odds are applicable. Options include:

    ScopeTypeEnum.ORDINARY_TIME: Regular match time without extra time or penalties
    ScopeTypeEnum.FULL_TIME: Full time match including the extra time and penalties

    Default value: ScopeTypeEnum.ORDINARY_TIME

  • oddFormat: OddFormatEnum.

    Defines the format in which odds values are presented. Options include:

    OddFormatEnum.DECIMAL: Odds displayed in decimal format (e.g., 1.50, 4.00)
    OddFormatEnum.FRACTIONAL: Odds displayed in fractional format (e.g., 1/2, 3/1)

    Default value: OddFormatEnum.DECIMAL

  • marketTypes: MatchOddsMarketType[].

    An array of market types to retrieve odds for. Options include:

    MatchOddsMarketEnum.FT_1X2: Full-time 1X2 odds (home win, draw, away win)
    MatchOddsMarketEnum.HT_1X2: Half-time 1X2 odds
    MatchOddsMarketEnum.DOUBLE_CHANCE: The match will finish 1 or X, 2 or X, 1 or 2
    MatchOddsMarketEnum.DRAW_NO_BET: The match winner, with the stake returned on a draw
    MatchOddsMarketEnum.HT_FT: How will finish the first half (1X2) and full time (1X2)
    MatchOddsMarketEnum.BOTH_TEAMS_SCORE: Both teams to score in the match
    MatchOddsMarketEnum.CORRECT_SCORE: The correct score of the match
    MatchOddsMarketEnum.TEAM_SCORE_FIRST_GOAL: Team to score the first goal in match
    MatchOddsMarketEnum.PLAYER_SCORE_FIRST_GOAL: Player to score the first goal in match
    MatchOddsMarketEnum.PLAYER_SCORE: Player to score in match
    MatchOddsMarketEnum.PLAYER_RED_CARD: Player to receive red card in match
    MatchOddsMarketEnum.PLAYER_YELLOW_CARD: Player to receive yellow card in match
    MatchOddsMarketEnum.OVER_GOALS_0_5: There will be at least 1 goal in match
    MatchOddsMarketEnum.OVER_GOALS_1_5: There will be at least 2 goals in match
    MatchOddsMarketEnum.OVER_GOALS_2_5: There will be at least 3 goals in match
    MatchOddsMarketEnum.OVER_GOALS_3_5: There will be at least 4 goals in match
    MatchOddsMarketEnum.OVER_GOALS_4_5: There will be at least 5 goals in match
    MatchOddsMarketEnum.OVER_GOALS_5_5: There will be at least 6 goals in match
    MatchOddsMarketEnum.OVER_GOALS_6_5: There will be at least 7 goals in match
    MatchOddsMarketEnum.OVER_CORNERS_6_5OVER_CORNERS_13_5: There will be at least 7 … 14 corners in match

    Operators publish new markets without an SDK release, so a market code the SDK does not know yet is accepted as a plain string and matched against the response as-is. Market codes are matched case-insensitively.

    Default value: [FT_1X2]

  • operators: string[].

    Restricts the response to specific operators, e.g. ["bookmaker-bg", "bookmaker2-bg"]. When omitted, every operator configured for your client is returned.

  • affiliateId: string.

    Affiliate ID substituted into every operator link that carries an {affiliate_id} placeholder.

  • affiliateIds: Record<string, string>.

    Affiliate IDs per operator, e.g. { "bookmaker-bg": "aff-123" }. Takes precedence over affiliateId for the operators it names, so a client that shows several operators can use a different affiliate arrangement with each.

  • language: string.

    BCP 47 language tag for the operator content, e.g. "EN" or "BG".

🚧

Validations

matchIds parameter is required. filters is optional, however when invalid filter is provided for any of scopeType, oddFormat and marketTypes, a warning message will be logged. Example:

The filter "scopeType" is NOT valid and therefore it will be set to ORDINARY_TIME. The VALID values are : ORDINARY_TIME, FULL_TIME


📘

Example call:

import { ScopeTypeEnum, OddFormatEnum, MatchOddsMarketEnum } from "fansunited-sdk-esm";

const filters = {
  scopeType: ScopeTypeEnum.ORDINARY_TIME,
  oddFormat: OddFormatEnum.DECIMAL,
  marketTypes: [MatchOddsMarketEnum.FT_1X2],
  affiliateId: "aff-123"
};

const matchIds = ["id", "id2"];

sdk.odds
  .getByMatchIds(matchIds, filters)
  .then((response) => {
    // Handle response
  })
  .catch((error) => {
    // Handle error
  });

Example result

{
  id: [
    {
      bookmaker: {
        id: "bookmaker-bg",
        name: "Bookmaker",
        url: "https://bookmaker.com",
        assets: [
          {
            logo: "https://assets.lsdapi.com/images/76ab21dd58330c56e346d8be7f5fc5df.svg",
            type: "LOGO",
            transparentBackgroundUrl: "https://assets.lsdapi.com/images/76ab21dd58330c56e346d8be7f5fc5df.svg",
            backgroundColor: "#0D4AB0"
          }
        ],
        links: [
          {
            appType: "desktop",
            selectionTemplateUrl: "https://bookmaker.com/event/team-a-team-b-3094093?aff=aff-123",
            eventTemplateUrl: "https://bookmaker.com/event/team-a-team-b-3094093?aff=aff-123",
            homepageUrl: "https://bookmaker.com"
          },
          {
            appType: "mobile",
            selectionTemplateUrl: "https://bookmaker.com/event/team-a-team-b-3094093?aff=aff-123",
            eventTemplateUrl: "https://bookmaker.com/event/team-a-team-b-3094093?aff=aff-123",
            homepageUrl: "https://bookmaker.com"
          }
        ],
        branding: {
          backgroundColor: "#0954b9",
          textColor: "#fce34c",
          hoverBackgroundColor: "#074394",
          borderColor: "#0954b9"
        },
        eventUrls: [
          {
            url: "https://bookmaker.com/event/team-a-team-b-3094093?aff=aff-123",
            appType: "desktop"
          },
          {
            url: "https://bookmaker.com/event/team-a-team-b-3094093?aff=aff-123",
            appType: "mobile"
          }
        ],
        betslipUrlTemplate: [
          {
            url: "https://bookmaker.com/sports?betType=Multiple&selectionIds={betslip_ids}&aff=aff-123",
            appType: "desktop"
          },
          {
            url: "https://bookmaker.com/sports?betType=Multiple&selectionIds={betslip_ids}&aff=aff-123",
            appType: "mobile"
          }
        ],
        betslipIdSeparator: "|",
        stakesDisclaimer: "18+ risk of addiction",
        domainName: "bookmaker.com"
      },
      type: "PRE_EVENT",
      startTime: "2026-09-10T18:45:00Z",
      updatedAt: "2026-09-09T11:04:52Z",
      markets: [
        {
          type: {
            id: "FT_1X2",
            name: "FT_1X2",
            code: "FT_1X2",
            entityType: "market_type"
          },
          scope: {
            id: "ORDINARY_TIME",
            type: "ordinary_time",
            name: "ORDINARY TIME",
            entityType: "market_scope"
          },
          selections: [
            {
              id: "1",
              name: "1",
              code: "1",
              value: "Team A",
              odds: "1.50",
              urls: [
                {
                  url: "https://bookmaker.com/event/team-a-team-b-3094093?aff=aff-123",
                  appType: "desktop"
                },
                {
                  url: "https://bookmaker.com/event/team-a-team-b-3094093?aff=aff-123",
                  appType: "mobile"
                }
              ],
              movement: "UP",
              oddsOld: "1.45",
              entityType: "market_selection",
              additionalInfo: null,
              providerInfo: {
                selectionId: "sr:market:72221154:1:1",
                eventId: "sr:match:72221154",
                marketId: "sr:market:72221154:1",
                competitionId: "sr:tournament:17"
              }
            },
            {
              id: "X",
              name: "X",
              code: "X",
              value: "Draw",
              odds: "4.00",
              urls: [
                {
                  url: "https://bookmaker.com/event/team-a-team-b-3094093?aff=aff-123",
                  appType: "desktop"
                },
                {
                  url: "https://bookmaker.com/event/team-a-team-b-3094093?aff=aff-123",
                  appType: "mobile"
                }
              ],
              movement: "DOWN",
              oddsOld: "4.20",
              entityType: "market_selection",
              additionalInfo: null,
              providerInfo: {
                selectionId: "sr:market:72221154:1:2",
                eventId: "sr:match:72221154",
                marketId: "sr:market:72221154:1",
                competitionId: "sr:tournament:17"
              }
            },
            {
              id: "2",
              name: "2",
              code: "2",
              value: "Team B",
              odds: "5.50",
              urls: [
                {
                  url: "https://bookmaker.com/event/team-a-team-b-3094093?aff=aff-123",
                  appType: "desktop"
                },
                {
                  url: "https://bookmaker.com/event/team-a-team-b-3094093?aff=aff-123",
                  appType: "mobile"
                }
              ],
              movement: "DOWN",
              oddsOld: "5.75",
              entityType: "market_selection",
              additionalInfo: null,
              providerInfo: {
                selectionId: "sr:market:72221154:1:3",
                eventId: "sr:match:72221154",
                marketId: "sr:market:72221154:1",
                competitionId: "sr:tournament:17"
              }
            }
          ]
        }
      ]
    }
  ],
  id2: []
}
📘

Response notes

type is PRE_EVENT or LIVE, derived from the status of the match. It is null only when the status could not be resolved.

market.type carries the Fans United market code in id, name and code, and market.scope carries the scope in id, type and name.

odds and oddsOld are strings for decimal odds, and the fractional notation (e.g. "5/2") when oddFormat is FRACTIONAL.

url, links and eventUrls are built from the resolved operator links. A link the API could not fully resolve is omitted rather than returned partially substituted.

Every OVER_GOALS_* market returns both the over and the under selection, because each goal line is its own market.

Get odds for a match

Method: getByMatchId(matchId, filters?)

Model:

The method returns an EventOddsModel instance — the odds of a single match, grouped per operator. It accepts the same filters object as getByMatchIds.

🚧

Validations

matchId parameter is required. When there are no odds for the match, including when the match has already finished, the method rejects with a 404 error and status odds_not_found. The error is shaped by the errorHandlingMode of your SDK configuration.

📘

Example call:

import { MatchOddsMarketEnum } from "fansunited-sdk-esm";

sdk.odds
  .getByMatchId("id", { marketTypes: [MatchOddsMarketEnum.FT_1X2], affiliateId: "aff-123" })
  .then((response) => {
    // Handle response
  })
  .catch((error) => {
    // Handle error
  });

Example result

{
  eventId: "id",
  startTime: "2026-09-10T18:45:00Z",
  updatedAt: "2026-09-09T11:04:52Z",
  odds: [
    {
      operator: {
        id: "bookmaker-bg",
        name: "Bookmaker",
        domainName: "bookmaker.com",
        stakesDisclaimer: "18+ risk of addiction",
        branding: {
          backgroundColor: "#0954b9",
          textColor: "#fce34c",
          hoverBackgroundColor: "#074394",
          borderColor: "#0954b9"
        },
        assets: [
          {
            type: "LOGO",
            logo: "https://assets.lsdapi.com/images/76ab21dd58330c56e346d8be7f5fc5df.svg",
            transparentBackgroundUrl: "https://assets.lsdapi.com/images/76ab21dd58330c56e346d8be7f5fc5df.svg",
            backgroundColor: "#0D4AB0"
          }
        ],
        betslipUrlTemplate: {
          desktop: "https://bookmaker.com/sports?betType=Multiple&selectionIds={betslip_ids}&aff=aff-123",
          mobile: "https://bookmaker.com/sports?betType=Multiple&selectionIds={betslip_ids}&aff=aff-123"
        },
        betslipIdSeparator: "|"
      },
      urls: {
        desktop: "https://bookmaker.com/event/team-a-team-b-3094093?aff=aff-123",
        mobile: "https://bookmaker.com/event/team-a-team-b-3094093?aff=aff-123"
      },
      markets: [
        {
          meta: {
            market: "FT_1X2",
            scope: "ORDINARY_TIME"
          },
          selections: [
            {
              code: "1",
              value: "Team A",
              odds: 1.5,
              oddsOld: 1.45,
              movement: "UP",
              urls: {
                desktop: "https://bookmaker.com/event/team-a-team-b-3094093?aff=aff-123",
                mobile: "https://bookmaker.com/event/team-a-team-b-3094093?aff=aff-123"
              },
              additionalInfo: null,
              operatorInfo: {
                selectionId: "sr:market:72221154:1:1",
                eventId: "sr:match:72221154",
                marketId: "sr:market:72221154:1",
                competitionId: "sr:tournament:17"
              }
            },
            {
              code: "X",
              value: "Draw",
              odds: 4,
              oddsOld: 4.2,
              movement: "DOWN",
              urls: {
                desktop: "https://bookmaker.com/event/team-a-team-b-3094093?aff=aff-123",
                mobile: "https://bookmaker.com/event/team-a-team-b-3094093?aff=aff-123"
              },
              additionalInfo: null,
              operatorInfo: {
                selectionId: "sr:market:72221154:1:2",
                eventId: "sr:match:72221154",
                marketId: "sr:market:72221154:1",
                competitionId: "sr:tournament:17"
              }
            },
            {
              code: "2",
              value: "Team B",
              odds: 5.5,
              oddsOld: 5.75,
              movement: "DOWN",
              urls: {
                desktop: "https://bookmaker.com/event/team-a-team-b-3094093?aff=aff-123",
                mobile: "https://bookmaker.com/event/team-a-team-b-3094093?aff=aff-123"
              },
              additionalInfo: null,
              operatorInfo: {
                selectionId: "sr:market:72221154:1:3",
                eventId: "sr:match:72221154",
                marketId: "sr:market:72221154:1",
                competitionId: "sr:tournament:17"
              }
            }
          ]
        }
      ]
    }
  ]
}
📘

EventOddsModel vs MatchOddsModel

getByMatchIds returns MatchOddsModel, which keeps the shape it has always had. getByMatchId and getByDateRange return EventOddsModel, which follows the structure of the API: odds grouped per operator, the market code and scope in meta, numeric odds, and links as { desktop, mobile } objects.

Get odds for fixtures in a date range

Method: getByDateRange(filters)

Model:

The method returns an EventsOddsPaginationModel instance: data is an Array of EventOddsModel ordered by start time ascending, and meta carries total, limit and page.

Filters object — everything getByMatchIds accepts, plus:

  • dateFrom: string. Required. Start of the range (inclusive), ISO 8601 datetime, e.g. "2026-09-10T00:00:00Z".

  • dateTo: string. Required. End of the range (inclusive), ISO 8601 datetime. At most 7 days after dateFrom.

  • sport: SportEnum. Options include SportEnum.FOOTBALL, SportEnum.BASKETBALL, SportEnum.TENNIS, SportEnum.AMERICAN_FOOTBALL, SportEnum.FORMULA_1, SportEnum.HOCKEY.

    Default value: SportEnum.FOOTBALL

  • competitionId: string. Restricts the result to a single competition, e.g. "fb:c:1".

  • limit: number. Items per page. Defaults to 50, maximum 200.

  • page: number. Page number, 1-based.

🚧

Validations

dateFrom and dateTo are required, must be valid ISO 8601 datetimes with dateTo after dateFrom, and the range must not exceed 7 days. Otherwise the method rejects with a 400 error and status invalid_date_range.


🚧

Finished fixtures and pagination

meta.total is the number of fixtures the API holds odds for in the range, and it includes fixtures that have already finished. Those are removed from data, so a page that covers past days can contain far fewer entries than limit. Query forward-looking ranges to avoid it.

📘

Example call:

import { SportEnum, MatchOddsMarketEnum } from "fansunited-sdk-esm";

const filters = {
  dateFrom: "2026-09-10T00:00:00Z",
  dateTo: "2026-09-16T23:59:59Z",
  sport: SportEnum.FOOTBALL,
  competitionId: "fb:c:1",
  marketTypes: [MatchOddsMarketEnum.FT_1X2],
  affiliateId: "aff-123",
  limit: 50,
  page: 1
};

sdk.odds
  .getByDateRange(filters)
  .then((response) => {
    // Handle response
  })
  .catch((error) => {
    // Handle error
  });

Example result

{
  data: [
    {
      eventId: "id",
      startTime: "2026-09-10T18:45:00Z",
      updatedAt: "2026-09-09T11:04:52Z",
      odds: [
        // Same structure as the getByMatchId result above
      ]
    },
    {
      eventId: "id2",
      startTime: "2026-09-11T16:00:00Z",
      updatedAt: "2026-09-09T11:05:14Z",
      odds: [
        // ...
      ]
    }
  ],
  meta: {
    total: 124,
    limit: 50,
    page: 1
  }
}

Errors

CodeStatusWhen
400invalid_match_idsgetByMatchIds called without a non-empty Array of match IDs
400invalid_match_idgetByMatchId called without a match ID
400invalid_date_rangegetByDateRange called without dateFrom/dateTo, with an invalid range, or with a range wider than 7 days
404match_ids_not_foundgetByMatchId called with a match ID that has no mapping in the configured ID schema
404odds_not_foundgetByMatchId called for a match with no odds, or for a match that has already finished

Did this page help you?