FIBA API for game results

application programming interface
Updated: 2023-09-30

A. Introduction

The FIBA [1] World Cup [2] is a prestigious basketball event that takes place every four years. This year, the championship was co-hosted by three countries: Indonesia, Japan and the Philippines. The top 32 teams from different zones such as Africa, Americas, Asia and Europe competed for the title after qualifying through the designated qualification [3, 4, 5, 6] events.

This article will show you how to create an API [7] or Application Programming Interface endpoint that can return game matches results. I will use the FastAPI [8] framework and host it for free on fly.io [9], a cloud platform.

B. Collecting Game Results

I use the Playwright framework to scrape a specific FIBA page and save the game results to a csv file. This csv file is then used in the API. You can check the game results on the FIBA world cup page [2] website.

C. FastAPI Codes and Files

The code can also be found in my github FIBA API [10] repository. The code in github now includes world cup 2019 data. Also include code to limit 5 requests per minute.

main.py

from typing import Optional, List, Dict

from fastapi import FastAPI, HTTPException
from fastapi.responses import HTMLResponse
import pandas as pd


ZONES = ['africa', 'americas', 'asia', 'europe']


app = FastAPI()


@app.get("/worldcup/2023/championship")
async def wordcup_2023_championship(team: Optional[str] = None) -> List[Dict]:
    """## Gets FIBA world cup 2023 championship game results.

    If team is not specified, all results will be returned.

    Args:  
        team: The country code according to IOC such as USA, ESP, AUS, etc.

    Returns:  
        A dataframe of match results.    
    """
    csvfn = './data/worldcup/2023/championship/worldcup_2023.csv'
    df = pd.read_csv(csvfn)
    if team is None:
        df = df.sort_values(by=['DP', 'GI'], ascending=[True, True])
        return df.to_dict('records')

    df_left = df.loc[df['C1'].str.lower() == team.lower()]
    df_right = df.loc[df['C2'].str.lower() == team.lower()]
    df_all = pd.concat([df_left, df_right], ignore_index=True)

    if len(df_all) <= 0:
        raise HTTPException(
            status_code=404,
            detail=f"Team {team} is not found."
        )

    df_all = df_all.sort_values(by=['DP', 'GI'], ascending=[True, True])
    return df_all.to_dict('records')


@app.get("/worldcup/2023/qualifier")
async def wordcup_2023_qualifier(
    team: Optional[str] = None,
    zone: Optional[str] = None
) -> List[Dict]:
    """## Gets FIBA world cup 2023 qualifier game results by zone or by team.

    If team and zone are not specified, all results will be returned.

    Args:  
        team: The country code according to IOC such as USA, etc.  
        zone: The zone name [Africa, Americas, Asia and Europe].

    Returns:
        A dataframe of match results.    
    """
    csvfn = './data/worldcup/2023/qualifier/worldcup_2023_qualifier.csv'
    df = pd.read_csv(csvfn)
    if team is None:
        if zone is None:
            df = df.sort_values(by=['DP', 'GI'], ascending=[True, True])
            return df.to_dict('records')
        else:
            if not zone.lower() in ZONES:
                raise HTTPException(
                    status_code=404,
                    detail=f"The zone {zone} is not found. Available \
                             values are {ZONES}."
                )

            df_zone = df.loc[df['ZONE'].str.lower() == zone.lower()]
            df_zone = df_zone.sort_values(
                by=['DP', 'GI'],
                ascending=[True, True]
            )
            return df_zone.to_dict('records')
    else:
        df_left = df.loc[df['C1'].str.lower() == team.lower()]
        df_right = df.loc[df['C2'].str.lower() == team.lower()]
        df_all = pd.concat([df_left, df_right], ignore_index=True)

        if len(df_all) <= 0:
            raise HTTPException(
                status_code=404,
                detail=f"The team {team} is not found."
            )

        df_all = df_all.sort_values(by=['DP', 'GI'], ascending=[True, True])
        return df_all.to_dict('records')

requirements.txt

fastapi[all]
pandas

Dockerfile

FROM python:3-alpine

WORKDIR /app

COPY requirements.txt ./
RUN pip install --no-cache-dir -r requirements.txt

COPY . .

EXPOSE 8080

CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "8080"]

fly.toml

The fly cli can also generate this file automatically.

app = "apifiba"
primary_region = "hkg"

[build]

[http_service]
  internal_port = 8080
  force_https = true
  auto_stop_machines = true
  auto_start_machines = true
  min_machines_running = 0
  processes = ["app"]

D. Deploy the FIBA API in the cloud

Fly.io [9] provides a free tier to host the API. You may read their documentation on how to deploy it. There is also a nice article [11] on how to deploy fastapi in flyio.

E. API endpoints

There are two endpoints of this API.

  1. https://apifiba.fly.dev/worldcup/2023/championship
  2. https://apifiba.fly.dev/worldcup/2023/qualifier

1. The championship endpoint

The championship endpoint returns all the game results of the world cup 2023.

https://apifiba.fly.dev/worldcup/2023/championship

The endpoint point also provides a team query parameter. The values can be "usa", "phi", etc. To return the usa's game match results, use the team parameter with "usa" as value.

https://apifiba.fly.dev/worldcup/2023/championship?team=usa

The output would look like this.

[
  {
    "C1": "USA",
    "C1S": 99,
    "C2": "NZL",
    "C2S": 72,
    "GI": 1,
    "DP": "2023.08.26",
    "LOC": "City, Arena: Manila (PHI), Mall of Asia Arena",
    "EVENT": "FIBA World Cup 2023"
  },
  {
    "C1": "GRE",
    "C1S": 81,
    "C2": "USA",
    "C2S": 109,
    "GI": 2,
    "DP": "2023.08.28",
    "LOC": "City, Arena: Manila (PHI), Mall of Asia Arena",
    "EVENT": "FIBA World Cup 2023"
  },
  {
    "C1": "USA",
    "C1S": 110,
    "C2": "JOR",
    "C2S": 62,
    "GI": 3,
    "DP": "2023.08.30",
    "LOC": "City, Arena: Manila (PHI), Mall of Asia Arena",
    "EVENT": "FIBA World Cup 2023"
  },
  {
    "C1": "USA",
    "C1S": 85,
    "C2": "MNE",
    "C2S": 73,
    "GI": 4,
    "DP": "2023.09.01",
    "LOC": "City, Arena: Manila (PHI), Mall of Asia Arena",
    "EVENT": "FIBA World Cup 2023"
  },
  {
    "C1": "USA",
    "C1S": 104,
    "C2": "LTU",
    "C2S": 110,
    "GI": 5,
    "DP": "2023.09.03",
    "LOC": "City, Arena: Manila (PHI), Mall of Asia Arena",
    "EVENT": "FIBA World Cup 2023"
  },
  
  ...
]

2. The qualifier endpoint

This is similar to the championship endpoint except the game results are from world cup 2023 qualifier games. It also has two query parameters, "zone" and "team".

To get all the game results from qualifier.

https://apifiba.fly.dev/worldcup/2023/qualifier

To get all the game results from europe zone.

https://apifiba.fly.dev/worldcup/2023/qualifier?zone=europe

To get all the game results of Germany, use the team parameter.

https://apifiba.fly.dev/worldcup/2023/qualifier?team=ger

You can also visit the doc page at https://apifiba.fly.dev/docs and even use it to get the results you need.

F. Sample request script

"""Get FIBA world cup 2023 championship game results.

You need to install requests with "pip install requests."
"""

import requests

# Define the endpoint.
url = "https://apifiba.fly.dev/worldcup/2023/championship"

# Make a request to the endpoint.
response = requests.get(url)

# Print results if request is successful otherwise print the status code.
if response.status_code == 200:
    print(response.json())
else:
    print(f"Request failed with status code {response.status_code}")

G. References

[1]. FIBA Basketball official page (accessed 2023-09-25)
[2]. FIBA World Cup 2023 (accessed 2023-09-25)
[3]. FIBA World Cup 2023 Qualifier - Africa (accessed 2023-09-25)
[4]. FIBA World Cup 2023 Qualifier - Americas (accessed 2023-09-25)
[5]. FIBA World Cup 2023 Qualifier - Asia (accessed 2023-09-25)
[6]. FIBA World Cup 2023 Qualifier - Europe (accessed 2023-09-25)
[7]. API by Wikipedia (accessed 2023-09-25)
[8]. FastAPI (accessed 2023-09-25)
[9]. Fly.io cloud platform (accessed 2023-09-25)
[10]. Github FIBA API (accessed 2023-09-28)
[11]. How to deploy fastapi in flyio (accessed 2023-09-28)

Comments