Skip to end of metadata
Go to start of metadata

You are viewing an old version of this page. View the current version.

Compare with Current View Page History

Version 1 Next »

Overview

OddsFeed Ingestion API is a push API allowing both external and internal customers to integrate Fixtures and Odds Feed data with OIS. The data flow afterwards is the same as for our Pull Infrastructure:

  • Fixtures and markets gets matched/classified

  • Data is distributed using:

    • Internal message broker (CoreRMQ)

    • OddsFeedAPI (pull API)

URLs

Use Cases

Authorization

As a user I want to be able to make requests to OddsFeed Ingestion API

Step 1:

  • Auth0 clientId and client secret for the customer are created

  • Done by SBIT team

Step 2:

  • API Key is created (by OIS squad)

Step 3:

  • The customer of the API obtains a valid token using its:

    • Auth0 clientId

    • Auth0 secret

Step 4:

  • Customer can use the API using the obtained token and API Key

Source Fixtures

As a user I want to send a new fixture

A new fixture (event) is created using the ‘SourceFixtures’ POST endpoint.

The endpoint expects three mandatory parameters:

  • SourceId - provided by Genius Sports

  • SourceFixtureId - this is the source event Id (provided the integrating team)

  • Body of the request, with the following mandatory fields:

    • name - the name of the event. E.g. ‘Barcelona vs. Real Madrid’

    • sportId - Can be retrieved from Fixtures API sports

    • startTime - the start date and time of an event

    • hasInPlay - indicates if the event and its markets/prices are offered In-Play

    • hasPreMatch - indicates if the event and its markets/prices are offered Pre-Match

SourceFixtureId must be unique across one source.

 Example 'Body' of the post request
{
    "name":"Young Africans vs Marumo Gallants FC",
    "sportId":10,
    "startTime":"2023-05-11T13:00:00Z",
    "hasInPlay":"Unspecified",
    "hasPreMatch":"Unspecified",
    "venue":null,
    "competition":
    {
        "id":"1958",
        "name":"CAF Confederation Cup"
    },
    "season":
    {
        "id":"115417",
        "name":"2022/2023 CAF Confederation Cup"
     },
    "round":
    {
        "id":"1037502",
        "name":"Marumo Gallants FC v Young Africans"
    },
    "competitors":
    [
        {
            "id":"471464",
            "name":"Young Africans",
            "isHome":true,
            "lineup":null
        },
        {
            "id":"1002214",
            "name":"Marumo Gallants FC",
            "isHome":false,
            "lineup":null
        }
    ]
}

As a user I want to update an existing fixture

Updating an existing fixture must happen in cases where there has been a significant change to it. For instance:

  • start time has changed

  • competitors have changed

  • sportId was wrong and the correct one is sent

  • etc.

Making an update is no different than creating a new fixture in term of what request should be made to the API. The last request will overwrite the previous one’s data.

Please do not change the SourceFixtureId when making updates.

As a user, I want to invalidate existing fixture

A Fixture can be invalidated using the ‘SourceFixtures' DELETE endpoint. This will not actually delete the fixture, but mark it as 'Unavailable’, so that downstream consumers of this data are aware it is not relevant.

You would want to 'Delete' a fixture if it is not relevant anymore. For instance:

  • The event has ended

  • The event has been cancelled

  • etc.

The expected parameters are sourceId and sourceFixtureId.

As a user I want to see what information has been sent for a specific fixture

In case a user of the API is interested what fixtures data has been pushed, he can use the 'SourceFixtures' GET endpoint.

This will return the 'Raw' data that has been integrated, before any processing (e.g. matching) is done.

The expected parameters are sourceId and sourceFixtureId.

Source Markets

In most cases market updates must be done when the price of any of the selections has changed. The API allows other fields to be changed as well (new selection, handicap boolean, selection name, etc.), but these should be rather fixed and rarely updated.

As a user I want to send a new market

A new market (event) is sent using the ‘SourceMarkets’ POST endpoint.

The endpoint expects three mandatory parameters:

  • sourceId - provided by Genius Sports

  • sourceMarketId - this is the source market Id (provided the integrating team)

  • Body of the request, with the following mandatory fields:

    • sourceFixtureId - the event id provided by the integrating team.

    • name - name of the market (e.g. 'Money Line')

    • isHandicap - indicates whether this is a handicap market or not

    • selections, with the following mandatory fields:

      • id - this is the source id of the selection.

      • name - the source name of the selection (e.g. ‘Over', ‘Under’, ‘Home competitor name’, ‘Away competitor name', 'Draw’, etc.)

      • price

  • sourceMarketId must be unique across one source

  • selection Ids must be unique across one source

  • At least one of the decimalPrice, fractionalPrice or americanPrice properties should be set. A combination of all of them is also a valid.

Selections are tightly coupled with the type of the market. Hence the number of selections and the data will vary depending on the market type. For instance:

  • For market ‘Both team to score’ we will expect:

    • 2 selections

    • selection name 1 - 'Yes'

    • selection name 2 - 'No'

  • For market '1x2' we will expect:

    • 3 selections

    • selection name 1 - Home competitor name

    • selection name 2 - Away competitor name

    • selection name 3 - Draw

 Example body for '1x2' market
{
  "sourceFixtureId": "1234",
  "name": "1x2",
  "isHandicap": false,
  "isSuspended": false,
  "selections": [
    {
      "id": "1234",
      "name": "Espérance ST(Sportive de Tunis)",
      "isSuspended": false,
      "handicap": null,
      "price": {
        "decimal": 2,
        "fractional": {
          "denominator": 1,
          "numerator": 1
        },
        "american": 100
      },
      "range": {
        "min": 1,
        "max": 2
      }
    },
    {
      "id": "1235",
      "name": "Al Ahli Cairo",
      "isSuspended": false,
      "handicap": null,
      "price": {
        "decimal": 3
      },
      "range": {
        "min": 1,
        "max": 2
      }
    },
    {
      "id": "1236",
      "name": "Draw",
      "isSuspended": false,
      "handicap": null,
      "price": {
        "decimal": 2.5
      },
      "range": {
        "min": 1,
        "max": 2
      }
    }
  ]
}

 Example body of a 'Spread' market
{
  "sourceFixtureId": "1234",
  "name": "Spread",
  "isHandicap": true,
  "isSuspended": false,
  "selections": [
    {
      "id": "12345",
      "name": "Espérance ST(Sportive de Tunis)",
      "isSuspended": false,
      "handicap": 1,
      "price": {
        "decimal": 2,
        "fractional": {
          "denominator": 1,
          "numerator": 1
        },
        "american": 100
      },
      "range": {
        "min": 1,
        "max": 2
      }
    },
    {
      "id": "12356",
      "name": "Al Ahli Cairo",
      "isSuspended": false,
      "handicap": -1,
      "price": {
        "decimal": 3
      },
      "range": {
        "min": 1,
        "max": 2
      }
    }
  ]
}
 Example body of a 'Player props market'
{
  "sourceFixtureId": "1234",
  "name": "Tom Brady Total Passing Yards",
  "isHandicap": true,
  "isSuspended": false,
  "selections": [
    {
      "id": "12345",
      "name": "Tom Brady_Over",
      "isSuspended": false,
      "handicap": 300,
      "price": {
        "decimal": 2,
        "fractional": {
          "denominator": 1,
          "numerator": 1
        },
        "american": 100
      },
      "range": {
        "min": 1,
        "max": 2
      }
    },
    {
      "id": "12356",
      "name": "Tom Brady_Under",
      "isSuspended": false,
      "handicap": 300,
      "price": {
        "decimal": 3
      },
      "range": {
        "min": 1,
        "max": 2
      }
    }
  ]
}

Handicap Markets

  • Separate handicap markets should be created for each handicap line.

    • One market for -0.5/+0.5, one market for -1.5/+1.5, etc.

  • About handicap markets, It's also important the selections to have the handicap property set

As a user I want to update the prices of a market

If a price update of an existing market must be made, the POST endpoint should be used. The value that must be changed is the 'price' field, which is part of the selection.

Each selection has its own price, thus you need to make sure to pass the correct selection Id and Name, so that the correct selection price is updated.

As a user I want to suspend a market

In the case where bets are not accepted temporarily for a market, the state of the market can be marked as ‘Suspended'. Once the market is open to accept bets once again, a new update should be made to remove the 'suspended state’.

This is done using the SourceMarkets POST endpoint passing:

  • sourceId

  • sourceMarketId

  • Request Body

    • where isSuspended is true

 Example Request Body
{
  "sourceFixtureId": "1234",
  "name": "Spread",
  "isHandicap": true,
  "isSuspended": true,
  "selections": 

As a user I want to invalidate an existing market

In addition to suspending a market, the user can also invalidate it using the ‘SourceMarkets' DELETE endpoint. This will not actually delete the market, but mark it as ‘Unavailable’, so that the downstream consumers of this data are aware its data is not relevant and shouldn’t be used.

The main use case for invalidating a market is when it has been permanently closed for the event. This differs from the suspended state, which indicates that the punter temporarily cannot place bets on that market.

The expected parameters are sourceId and sourceMarketId.

As a user I want to suspend a selection

There is also the option to suspend only a specific selection in a market, if there’s a good reason for that. Such update should be rather rare, because most time the whole market would be suspended.

To make this change the user should use the SourceMarkets POST endpoint passing:

  • sourceId

  • sourceMarketId

  • Body

    • where the selections' isSuspended parameter is set to ‘true’

 Example Request Body
"selections": [
    {
      "id": "1234",
      "name": "Espérance ST(Sportive de Tunis)",
      "isSuspended": true,
      "handicap": null,
      "price": {
        "decimal": 2,
        "fractional": {
          "denominator": 1,
          "numerator": 1
        },
        "american": 100
      },
      "range": {
        "min": 1,
        "max": 2
      }
    },

As a user I want to see what information was sent for a specific market

In case a user of the API is interested what market data has been sent, he can use the 'SourceMarkets' GET endpoint.

This will return the 'Raw' market data that has been integrated, before any processing (e.g. matching) is done.

The expected parameters are sourceId and sourceMarketId.

FAQ

 For how long is the access_token valid?
  • The access_token is valid for 86400 seconds (24h) for all environments

 Why do I get an error 'Decimal Price must be bigger than 1 (one) !' ?

In betting the decimal betting price is set higher than one to account for both the original stake and the potential profit, ensuring that bettors receive a positive return when their bets are successful. Thus, there is a validation not allowing any prices equal to or lower than 1.

 Can I use the same sourceFixtureId across multiple different events?

Due to additional internal processing of the received data, all events (external) in a source should have unique sourceFixtureIds.

 Can I use the same sourceMarketId across multiple different events?

Due to additional internal processing of the received data, all markets (external) in a source should have unique sourceMarketIds.

 Can I use the same selection Ids across multiple different events?

Due to additional internal processing of the received data, all selections (external) in a source should have unique selection Ids.

 When updating a fixture and/or market can I use a different sourceFixtureId, sourceMarketId, selection Ids?

On update of existing fixture and/or market the sourceFixtureId, sourceMarketId and selection Ids must be kept the same.

 What is the 'range' field in the selections used for?

The field is only applicable for range markets, e.g. ‘Number of goals’.

 What are hasInPlay and hasPreMatch fields used for?

They are used to indicate whether the event and its markets and prices are available for PreMatch or InPlay betting.

 Can I send markets before fixtures

This is a valid case. However, markets' data won’t be distributed to downstream consumers, unless the market is part of a fixture.

 Can I see to what GS entities have the fixtures and markets been matched/classified to?

OddsFeed Ingestion API is built explicitly for the ingestion of external data. It has no knowledge whatsoever how this data is then process down the pipeline.

 What does the 'Response code' mean?

There is a description in swagger what each Response code means. If further clarity is needed you can refer to this page.

  • No labels