New at Cloudbet

Sports Betting GraphQL API With JavaScript (Nodejs)

In April 2021, Cloudbet released its public Sports RESTful API. We have updated it with several updates over the past year, and have also provided developer resources such as how to use the Cloudbet Betting REST API with Golang.

This year, our focus is on how to make the Cloudbet API accessible to more users and to make it as developer friendly as possible. With this goal in mind, we are releasing an early Alpha version of the Cloudbet Sports GraphQL API. GraphQL allows you to query for just the API response fields that you need rather than having to parse through a bucketload of irrelevant information. Furthermore, you can create bet placement requests more easily by consuming the Cloudbet Feed API in a more intuitive way.

In this article, @kgravenreuth walks you through the Cloudbet GraphQL API with Node.js JavaScript code examples.

Obtain your Cloudbet API Token

The Cloudbet GraphQL API uses the same API Key that you would use to interact with our RESTful API. The API Key is sent as the value of the X-API-Key header, just as with the REST API.

For further information about how to obtain the API Key from your Cloudbet website player account, please refer to our REST API article.

Cloudbet Trading API Key
Cloudbet Trading API Key

Brief introduction to GraphQL

GraphQL is a query and manipulation language for APIs and it provides a type system for describing data. Also, It allows clients to request the exact data that they need with a single API call as opposed to traditional REST APIs which return full payload entities on different API endpoints, resulting in excessive API calls.

Visit the Official GraphQL Documentation for more information.

Get started with the Cloudbet GraphQL API Explorer

One of the advantages of using GraphQL is that the API documentation comes built-in with every GraphQL API and is presented to you in a standardized way.

Both the GraphQL API documentation and GraphQL API endpoints are available at https://sports-api-graphql.cloudbet.com/graphql.

Visiting this endpoint directly will give you a GUI for interacting with our GraphQL API. We are using the Apollo GraphQL Explorer which provides interactive query building. After placing your API key as the value of X-API-KEY header in the Headers section of the GUI (refer to the screenshot), you can build your own GraphQL query and test it out easily.

Cloudbet GraphQL API Explorer

Also, you can navigate our GraphQL schema reference by clicking the “Schema” icon from the left sidebar. Then, you can see the detailed documentation about query/mutation/types defined in our GraphQL schema. Each of the request and response fields are documented in detail along with examples (refer to screenshot below).

Cloudbet GraphQL API Explorer Schema
Cloudbet GraphQL API Explorer Schema

Compared to our existing OpenAPI based Cloudbet REST API documentation, the GraphQL explorer GUI provides you clearer documentation and an interactive query builder to get started more easily.

Use GraphQL with Node.js

Pre-requisites

To query and place bets with Node.js + GraphQL, you’ll need the following:

  • Install Node.js on your machine. If you are on Windows, you can download it from the official site. If you are on Linux or Mac OS, you can use your Operating System’s package manager, such as Homebrew for MacOS.
  • Initialize your working directory with mkdir myapp && cd myapp
  • Create a new Node.js project with npm init
  • Install the axios Node.js library for making HTTP requests with npm install axios

Overview

In the following sections, we will walk you through the process of fetching odds for upcoming events and placing bets on the odds obtained. You can request odds by competition, or fetch fixtures for a given date. You can also fetch odds for a specific market for a given sport. Finally we will show you how to place bets on these fetched odds and check the bet status for bet settlement.

In general the process works as follows:

  1. Get details about upcoming events for your favorite sports. You can request fixtures information without odds if you so desire from the same endpoint with a different query structure for events several days in the future.
  2. Obtain odds from all events of a sport or a competition for a given market or line.

Query sport fixtures

You can start by querying what sports we are offering currently. You can use the following “sports” query to find different sports and what categories we are offering per sport. Categories refer to grouping of competitions, e.g. all Soccer competitions in England would be under the “England” category.


 const axios = require("axios").default;
 const sportsGraphqlApiBaseUrl = "https://sports-api-graphql.cloudbet.com";
 const apiKey = "YOUR_API_KEY";
 
 const query = `query Sports {
   sports {
     key
     name
     competitionCount
     eventCount
     categories {
       key
       name
     }
   }
 }`;
 
 axios
   .post(
     `${sportsGraphqlApiBaseUrl}/graphql`,
     {
       query,
     },
     {
       headers: {
         "Content-Type": "application/json",
         Accept: "application/json",
         "X-API-KEY": apiKey,
       },
     }
   )
   .then((resp) => resp.data)
   .then((data) => console.log("data:", JSON.stringify(data)));

Save the above file as example_1.js and run it with the command node example_1.js after replacing “YOUR_API_KEY” with the value of your actual API Key.

This would give you a JSON response similar to the following with a list of sports and categories.


{
  "data": {
    "sports": [
      {
        "key": "american-football",
        "name": "American Football",
        "competitionCount": 4,
        "eventCount": 89,
        "categories": [
          {
            "key": "usa",
            "name": "USA"
          }
        ]
      },
      {
        "key": "archery",
        "name": "Archery",
        "competitionCount": 0,
        "eventCount": 0,
        "categories": []
      },
.
.
.

Query odds for a category

After knowing all the available sports, you may want to get the latest odds and data for a specific sport or competition.

Let’s say you want to query odds for all English soccer competitions on 16th April 2022. You can query the categoryKey “england” and the sportKey “soccer” obtained from the previous sports query to list all the available competitions for the given date.

Competitions provide a list of events and events provide a list of markets on which odds are being offered. For each market, there is a list of submarkets and submarkets are broken down by event periods e.g. full time, 1st half, etc.Inside each submarket, there are several selections. Each selection has a different market URL which uniquely identifies it. The market URL is composed as <marketkey>/<outcome>?<params> and can be used to place bets through GraphQL API directly.


 // ...
 const sportKey = "soccer";
 const categoryKey = "england";
 const date = "2022-04-16";
 const query = `query Sport($sportKey: String!, $categoryKey: String, $date: Date) {
   sport(sportKey: $sportKey, categoryKey: $categoryKey, date: $date) {
     key
     name
     categories {
       key
       name
       competitions {
         key
         name
         events {
           id
           key
           name
           status
           cutoffTime
           markets {
             marketKey
             submarkets {
               submarketKey
               selections {
                 id
                 marketUrl
                 price
                 probability
                 minStake
                 maxStake
                 side
                 status
               }
             }
           }
         }
       }
     }
   }
 }`;
 
 axios
   .post(
     `${sportsGraphqlApiBaseUrl}/graphql`,
     {
       query,
       variables: { sportKey, categoryKey, date },
     },
     {
       headers: {
         "Content-Type": "application/json",
         Accept: "application/json",
         "X-API-KEY": apiKey,
       },
     }
   )
   .then((resp) => resp.data)
   .then((data) => console.log("data:", JSON.stringify(data)));

This would give you the odds for all English competitions on the given date, similar to the following sample response.


{
 "data": {
   "sport": {
     "key": "soccer",
     "name": "Soccer",
     "categories": [
       {
         "key": "england",
         "name": "England",
         "competitions": [
           {
             "key": "soccer-england-premier-league",
             "name": "Premier League",
             "events": [
               {
                 "id": "7535420",
                 "key": "relegation",
                 "name": "Relegation",
                 "status": "TRADING",
                 "cutoffTime": "2022-04-16T11:30:00.000Z",
                 "markets": [
                   {
                     "marketKey": "soccer.outright",
                     "submarkets": [
                       {
                         "submarketKey": "market_name=Premier%20League%20-%20Relegation",
                         "selections": [
                           {
                             "id": "7535420/soccer.outright/outcome=Watford%20FC?market_name=Premier%20League%20-%20Relegation",
                             "marketUrl": "soccer.outright/outcome=Watford%20FC?market_name=Premier%20League%20-%20Relegation",
                             "price": "1.046",
                             "probability": "0.304",
                             "minStake": "0.1",
                             "maxStake": "835130.43376",
                             "side": "BACK",
                             "status": "SELECTION_ENABLED"
                           },
.
.
.

In general, responses for the rest of the odds queries follow the response structure mentioned above for markets, submarkets, selections and price etc.

Query odds for a specific competition

With the query above, you can get odds for all English soccer competitions on a specific date.

If instead, you are only interested in the English Premier League and only in some specific markets, you can use the competition query for live and upcoming events by specifying competition key, market key and date.


 // ...
 const competitionKey = "soccer-england-premier-league";
 const markets = ["soccer.asian_handicap"];
 const date = "2022-04-16";
 const query = `query Competition($competitionKey: String!, $markets: [String!], $date: Date) {
   competition(competitionKey: $competitionKey, markets: $markets, date: $date) {
     key
     name
     events {
       id
       key
       name
       status
       cutoffTime
       markets {
         marketKey
         submarkets {
           submarketKey
           selections {
             id
             marketUrl
             price
             probability
             minStake
             maxStake
             side
             status
           }
         }
       }
     }
   }
 }`;
 
 axios
   .post(
     `${sportsGraphqlApiBaseUrl}/graphql`,
     {
       query,
       variables: { competitionKey, markets, date },
     },
     {
       headers: {
         "Content-Type": "application/json",
         Accept: "application/json",
         "X-API-KEY": apiKey,
       },
     }
   )
   .then((resp) => resp.data)
   .then((data) => console.log("data:", JSON.stringify(data)));

Query odds for specific line

A line consists of a set of interdependent selections whose total implied probability is > 100%. With our GraphQL API, you can odds for a specific line with a line query.

Let’s say you are only interested in an Asian Handicap line with the parameter handicap value = -1. You can query a specific line by the line id. The line id is composed of <event-id>/<market-key>?<params>, e.g. 9855572/soccer.asian_handicap?handicap=-1 in the example, or 9855572/soccer.total_goals if the market does not have any params (i.e. params are optional for some markets). It will return a list of selection odds for this specific line.


 // ...
 const lineId = "9855572/soccer.asian_handicap?handicap=-1";
 const query = `query Line($lineId: ID!) {
   line(id: $lineId) {
     id
     marketUrl
     price
     probability
     minStake
     maxStake
     side
     status
   }
 }`;
 
 axios
   .post(
     `${sportsGraphqlApiBaseUrl}/graphql`,
     {
       query,
       variables: { lineId },
     },
     {
       headers: {
         "Content-Type": "application/json",
         Accept: "application/json",
         "X-API-KEY": apiKey,
       },
     }
   )
   .then((resp) => resp.data)
   .then((data) => console.log("data:", JSON.stringify(data)));

Sample response:


{
  "data": {
    "line": [
      {
        "id": "9855572/soccer.asian_handicap/home?handicap=-1",
        "marketUrl": "soccer.asian_handicap/home?handicap=-1",
        "price": "3.307",
        "probability": "0.291",
        "minStake": "0.1",
        "maxStake": "10559.36672",
        "side": "BACK",
        "status": "SELECTION_ENABLED"
      },
      {
        "id": "10963275/soccer.asian_handicap/away?handicap=-1",
        "marketUrl": "soccer.asian_handicap/away?handicap=-1",
        "price": "1.356",
        "probability": "0.709",
        "minStake": "0.1",
        "maxStake": "28538.83872",
        "side": "BACK",
        "status": "SELECTION_ENABLED"
      }
    ]
  }
}

‍Get account balances

Before placing a sports bet, you may want to check available currencies that you can place bets with.

Using the following query you will get a list of account balances for each currency you have currently.


// ...
 const query = `query AccountBalances {
   accountBalances {
     currency
     amount
   }
 }`;
 
 axios
   .post(
     `${sportsGraphqlApiBaseUrl}/graphql`,
     {
       query,
     },
     {
       headers: {
         "Content-Type": "application/json",
         Accept: "application/json",
         "X-API-KEY": apiKey,
       },
     }
   )
   .then((resp) => resp.data)
   .then((data) => console.log("data:", JSON.stringify(data)));

‍Place sports bet

To place a sports bet, you need to construct the following input payload by specifying the reference id in uuid format, event id, market URL that describes the market selection, available price offered, the desired stake with the currency you want to place with. You can obtain all this information from the feed queries like “sport”, “competition”, “event”, etc. Compared to our existing REST API, you do not need to construct the market URL by yourself now and can obtain the market URL from the feed directly.

Also, we separate the bet error code from the existing bet status so it is much easier for users to distinguish between the accepted and rejected bets.


 // ...
 const input = {
   referenceId: "7b7e345a-79b7-44ba-86b2-e9048f3b4ce4",
   eventId: "9688827",
   price: "4.158",
   currency: "BTC",
   marketUrl: "soccer.asian_handicap/home?handicap=-1.25",
   stake: "0.00001",
 };
 const query = `mutation PlaceBet($input: PlaceBetInput!) {
   placeBet(input: $input) {
     referenceId
     eventId
     marketUrl
     currency
     price
     stake
     betStatus
     side
     betErrorCode
   }
 }`;
 
 axios
   .post(
     `${sportsGraphqlApiBaseUrl}/graphql`,
     {
       query,
       variables: { input },
     },
     {
       headers: {
         "Content-Type": "application/json",
         Accept: "application/json",
         "X-API-KEY": apiKey,
       },
     }
   )
   .then((resp) => resp.data)
   .then((data) => console.log("data:", JSON.stringify(data)));

Check placed bet & settlement

After placing a bet, you can query the bet by reference id to check the bet status. Usually, pre-match bets are accepted or rejected within a few seconds. During in-play betting, the bet may take a longer time to get accepted or rejected depending on the state of the live event.


 // ...
 const referenceId = "bfadf217-1af4-46ce-b491-d58864874366";
 const query = `query Bet($referenceId: String!) {
   bet(referenceId: $referenceId) {
     referenceId
     sportsKey
     categoryKey
     eventId
     eventName
     marketUrl
     currency
     price
     stake
     side
     returnAmount
     betStatus
     betErrorCode
   }
 }`;
 
 axios
   .post(
     `${sportsGraphqlApiBaseUrl}/graphql`,
     {
       query,
       variables: { referenceId },
     },
     {
       headers: {
         "Content-Type": "application/json",
         Accept: "application/json",
         "X-API-KEY": apiKey,
       },
     }
   )
   .then((resp) => resp.data)
   .then((data) => console.log("data:", JSON.stringify(data)));

With our GraphQL API, you can query a chronological bet history of all your accepted bets. Here, we will make use of GraphQL to combine accountBalances and bets queries together so you can get your account balances for all currencies along with the bet history with a single network request. In the following example, you can use the “limit” argument to request how many bets to be shown starting from the last placed bet.


 // ...
 const limit = 5;
 const query = `query Query($limit: Int) {
   accountBalances {
     currency
     amount
   }
   bets(limit: $limit) {
     referenceId
     categoryKey
     sportsKey
     eventId
     eventName
     marketUrl
     currency
     price
     stake
     side
     returnAmount
     betStatus
     betErrorCode
   }
 }`;
 
 axios
   .post(
     `${sportsGraphqlApiBaseUrl}/graphql`,
     {
       query,
       variables: { limit },
     },
     {
       headers: {
         "Content-Type": "application/json",
         Accept: "application/json",
         "X-API-KEY": apiKey,
       },
     }
   )
   .then((resp) => resp.data)
   .then((data) => console.log("data:", JSON.stringify(data)));

Conclusion

Compared to the existing Cloudbet REST API, the GraphQL API allows you to query Cloudbet odds feed in a flexible way since our REST API may have data which is irrelevant to your specific needs. Now you can query the exact data that you need by specifying the desired fields. Also, you can now query all live and upcoming event odds under a specific sport using a single query which would usually take multiple REST API calls to construct otherwise.

Finally, you can place bets and query your account details and bet history by querying a single GraphQL endpoint which makes creating a Trading Bot easier than ever.

Additional resources

These are some additional resources for you to explore the Cloudbet API further.

Feedback & Q/A

Feel free to ask questions on our Github discussion forum at https://github.com/Cloudbet/docs/discussions.

Share this post

Share on Facebook Share on X