Files
kempe-backend/API_GUIDE.md
Michael Simard c10fdd594d Add REST API endpoints for team player statistics
Implemented complete REST API to retrieve NHL player statistics for entire teams:

Application Layer:
- Created DTOs for Player, SkaterStats, GoalieStats, and PlayerWithStatsDTO
- Implemented GetTeamPlayerStatsUseCase that orchestrates data retrieval
- Transforms domain entities to API-friendly DTOs

Presentation Layer:
- Created /api/v1/teams/{team_id}/players endpoint (all players)
- Created /api/v1/teams/{team_id}/players/skaters endpoint (skaters only)
- Created /api/v1/teams/{team_id}/players/goalies endpoint (goalies only)
- Integrated routes into main FastAPI application

Features:
- Retrieves complete roster for any NHL team by abbreviation
- Aggregates current season statistics for each player
- Differentiates between skater and goalie statistics
- Proper error handling with 404 for invalid teams
- Follows CLEAN architecture with dependency injection

Documentation:
- Created comprehensive API_GUIDE.md with usage examples
- Includes setup instructions, endpoint documentation
- Python, JavaScript, and cURL examples
- Complete list of NHL team abbreviations

Testing:
- Added test scripts for both direct adapter testing and REST API testing
- Verified functionality with Toronto Maple Leafs data

The REST API is now ready for integration with fantasy hockey analysis tools.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-23 22:44:39 -06:00

6.2 KiB

REST API Guide - Project Kempe

This guide explains how to set up and use the REST API to retrieve NHL player statistics for entire teams.

Setup Instructions

1. Install Dependencies

cd /Users/michaelsimard/dev/services/project-kempe-backend

# Install all required packages
pip3 install -r requirements.txt

###2. Start the FastAPI Server

# Option 1: Using uvicorn directly
uvicorn src.presentation.api.main:app --reload --host 0.0.0.0 --port 8000

# Option 2: Using python module
python3 -m uvicorn src.presentation.api.main:app --reload --host 0.0.0.0 --port 8000

The server will start on http://localhost:8000

3. Verify Server is Running

Open your browser and visit:

Available Endpoints

Get All Players with Stats for a Team

Endpoint: GET /api/v1/teams/{team_id}/players

Example:

curl http://localhost:8000/api/v1/teams/TOR/players

Response: JSON array of all players (forwards, defensemen, goalies) with their current season statistics.

Response Structure:

[
  {
    "player": {
      "id": "8478104",
      "first_name": "Sammy",
      "last_name": "Blais",
      "full_name": "Sammy Blais",
      "jersey_number": 79,
      "position": "F",
      "team_id": "TOR"
    },
    "stats": {
      "player_id": "8478104",
      "games_played": 8,
      "goals": 1,
      "assists": 2,
      "points": 3,
      "plus_minus": -2,
      "penalty_minutes": 4,
      "shots": 12,
      "shooting_percentage": 8.33,
      "time_on_ice_per_game": 14.5,
      "powerplay_goals": 0,
      "powerplay_points": 0,
      "shorthanded_goals": 0,
      "game_winning_goals": 0,
      "faceoff_percentage": null,
      "hits": 15,
      "blocked_shots": 3
    },
    "stats_type": "skater"
  }
]

Get Only Skaters for a Team

Endpoint: GET /api/v1/teams/{team_id}/players/skaters

Example:

curl http://localhost:8000/api/v1/teams/TOR/players/skaters

Response: JSON array of only forwards and defensemen with their statistics.

Get Only Goalies for a Team

Endpoint: GET /api/v1/teams/{team_id}/players/goalies

Example:

curl http://localhost:8000/api/v1/teams/TOR/players/goalies

Response: JSON array of only goalies with their statistics.

Goalie Stats Structure:

{
  "player": {
    "id": "8471679",
    "first_name": "Joseph",
    "last_name": "Woll",
    "full_name": "Joseph Woll",
    "jersey_number": 60,
    "position": "G",
    "team_id": "TOR"
  },
  "stats": {
    "player_id": "8471679",
    "games_played": 10,
    "games_started": 10,
    "wins": 6,
    "losses": 2,
    "overtime_losses": 2,
    "saves": 285,
    "shots_against": 308,
    "goals_against": 23,
    "save_percentage": 92.53,
    "goals_against_average": 2.30,
    "shutouts": 1,
    "time_on_ice": 600.5
  },
  "stats_type": "goalie"
}

NHL Team Abbreviations

Use these three-letter abbreviations when making API calls:

Atlantic Division:

  • TOR - Toronto Maple Leafs
  • BOS - Boston Bruins
  • FLA - Florida Panthers
  • TBL - Tampa Bay Lightning
  • BUF - Buffalo Sabres
  • DET - Detroit Red Wings
  • OTT - Ottawa Senators
  • MTL - Montréal Canadiens

Metropolitan Division:

  • CAR - Carolina Hurricanes
  • NYR - New York Rangers
  • NJD - New Jersey Devils
  • PHI - Philadelphia Flyers
  • PIT - Pittsburgh Penguins
  • WSH - Washington Capitals
  • NYI - New York Islanders
  • CBJ - Columbus Blue Jackets

Central Division:

  • DAL - Dallas Stars
  • COL - Colorado Avalanche
  • WPG - Winnipeg Jets
  • MIN - Minnesota Wild
  • NSH - Nashville Predators
  • STL - St. Louis Blues
  • CHI - Chicago Blackhawks
  • UTA - Utah Mammoth

Pacific Division:

  • VGK - Vegas Golden Knights
  • EDM - Edmonton Oilers
  • LAK - Los Angeles Kings
  • VAN - Vancouver Canucks
  • SEA - Seattle Kraken
  • CGY - Calgary Flames
  • ANA - Anaheim Ducks
  • SJS - San Jose Sharks

Using the API in Your Application

Python Example

import httpx
import asyncio

async def get_team_stats(team_id: str):
    async with httpx.AsyncClient() as client:
        response = await client.get(
            f"http://localhost:8000/api/v1/teams/{team_id}/players"
        )
        return response.json()

# Get Toronto Maple Leafs stats
stats = asyncio.run(get_team_stats("TOR"))
for player_data in stats:
    player = player_data["player"]
    print(f"{player['full_name']}: {player_data['stats_type']}")

JavaScript Example

async function getTeamStats(teamId) {
  const response = await fetch(
    `http://localhost:8000/api/v1/teams/${teamId}/players`
  );
  const data = await response.json();
  return data;
}

// Get Toronto Maple Leafs stats
getTeamStats('TOR').then(players => {
  players.forEach(playerData => {
    console.log(`${playerData.player.full_name}: ${playerData.stats_type}`);
  });
});

cURL Example

# Get all players for Toronto Maple Leafs
curl http://localhost:8000/api/v1/teams/TOR/players | jq '.'

# Get only top scorers (skaters)
curl http://localhost:8000/api/v1/teams/TOR/players/skaters | jq '.[] | select(.stats.points > 10)'

# Get goalie stats
curl http://localhost:8000/api/v1/teams/TOR/players/goalies | jq '.[] | .stats'

Error Handling

Team Not Found (404)

{
  "detail": "No players found for team XYZ. Please verify the team abbreviation."
}

Server Error (500)

Check server logs for detailed error information.

Architecture

This REST API follows CLEAN architecture principles:

  1. Domain Layer: Pure business entities (Player, Stats)
  2. Application Layer: Use cases orchestrating business logic
  3. Infrastructure Layer: NHL API adapter (swappable)
  4. Presentation Layer: FastAPI REST endpoints

You can swap the NHL data source by changing the dependency injection configuration in src/presentation/api/dependencies.py without modifying any business logic or API endpoints.

Next Steps

  • Add authentication for private endpoints
  • Implement caching for frequently requested data
  • Add filtering and sorting query parameters
  • Create endpoints for player comparisons
  • Integrate Yahoo Fantasy API data