Architecture
API Schema

API Schema & Data Models

Complete API schema documentation with GraphQL-style relationship diagrams, data model visualizations, and type definitions.

πŸ—‚οΈ Core Data Models

Entity Relationship Diagram


πŸ”— GraphQL-Style Schema Relationships

League β†’ Teams β†’ Players Graph

Relationships Explained:

  • Solid Lines - Primary relationships (owns/contains)
  • Dashed Lines - Historical relationships (traded, played for)
  • Colors - Entity types (Red=League, Blue=Team, Green=Player, Purple=Stats)

πŸ“‹ Type Definitions

Backend Models (Python/Pydantic)

from pydantic import BaseModel, Field
from typing import Optional, List
from datetime import datetime
from enum import Enum
 
class LeagueTier(int, Enum):
    TIER_1 = 1  # Premier leagues
    TIER_2 = 2  # Major leagues
    TIER_3 = 3  # Regional leagues
    TIER_4 = 4  # Local leagues
    TIER_5 = 5  # Emerging leagues
 
class LeagueStatus(str, Enum):
    ACTIVE = "active"
    PENDING = "pending"
    INACTIVE = "inactive"
    ARCHIVED = "archived"
 
class League(BaseModel):
    """
    League entity representing a sports organization.
    
    Stored in: Supabase (metadata), Neo4j (relationships)
    """
    id: str = Field(..., description="Unique identifier")
    name: str = Field(..., min_length=3, max_length=100)
    sport: str = Field(..., description="Sport type (basketball, football, etc.)")
    tier: LeagueTier = Field(..., description="League classification tier (1-5)")
    status: LeagueStatus = Field(default=LeagueStatus.PENDING)
    
    # Metadata
    founded: Optional[int] = Field(None, description="Year founded")
    headquarters: Optional[str] = Field(None)
    website: Optional[str] = Field(None)
    
    # Relationships (populated from Neo4j)
    team_count: int = Field(default=0)
    player_count: int = Field(default=0)
    
    # Timestamps
    created_at: datetime = Field(default_factory=datetime.utcnow)
    updated_at: datetime = Field(default_factory=datetime.utcnow)
    
    class Config:
        use_enum_values = True
        json_schema_extra = {
            "example": {
                "id": "league_abc123",
                "name": "Elite Basketball Association",
                "sport": "basketball",
                "tier": 1,
                "status": "active",
                "founded": 2020,
                "team_count": 12
            }
        }

πŸ”„ Data Flow Through Models

Request β†’ Validation β†’ Storage β†’ Response


🎯 API Endpoint Schema

Complete API Structure


πŸ” Authentication & Authorization Flow

User Authentication Journey

Permission Levels


πŸ“Š Data Storage Strategy

Multi-Database Architecture

Storage Decision Matrix

Data TypePrimary StoreReasonBackup/Sync
League MetadataSupabaseStructured, indexedNeo4j (graph)
Team InfoSupabaseRelational queriesNeo4j
Player ProfilesSupabaseComplex queriesNeo4j
RelationshipsNeo4jGraph traversalsSupabase (denormalized)
Career PathsNeo4jHistorical graphN/A
Live ScoresFirebaseReal-time syncSupabase (final)
User SessionsFirebaseAuth + real-timeN/A
DocumentsChromaDBSemantic searchCloud Storage

πŸ” Query Patterns

Neo4j Cypher Query Examples

Find all players who played for multiple teams:

MATCH (l:League {id: $leagueId})-[:HAS_TEAM]->(t:Team)
MATCH (t)-[:HAS_PLAYER]->(p:Player)
WITH p, count(DISTINCT t) AS team_count, collect(DISTINCT t.name) AS teams
WHERE team_count > 1
RETURN p.name, team_count, teams
ORDER BY team_count DESC
LIMIT 20

Visual representation:

Supabase SQL Query Examples

Get league standings:

SELECT 
    t.id,
    t.name,
    COUNT(CASE WHEN g.winner_id = t.id THEN 1 END) as wins,
    COUNT(CASE WHEN g.winner_id != t.id THEN 1 END) as losses,
    SUM(CASE WHEN g.winner_id = t.id THEN 3 ELSE 0 END) as points
FROM teams t
LEFT JOIN games g ON (g.home_team_id = t.id OR g.away_team_id = t.id)
WHERE t.league_id = $1 
  AND g.status = 'completed'
GROUP BY t.id, t.name
ORDER BY points DESC, wins DESC
LIMIT 10;

Result structure:


πŸ“‘ API Response Schemas

Standard Response Envelope

Success Response Example:

{
  "data": {
    "id": "league_abc123",
    "name": "Elite Basketball Association",
    "tier": 1,
    "sport": "basketball",
    "teams": 12,
    "created_at": "2025-11-11T10:00:00Z"
  },
  "metadata": {
    "timestamp": "2025-11-11T10:30:00Z",
    "version": "1.0.0",
    "request_id": "req_xyz789"
  }
}

Error Response Example:

{
  "error": "validation_error",
  "message": "League name must be at least 3 characters",
  "details": {
    "field": "name",
    "provided": "AB",
    "minimum": 3
  },
  "docs": "https://docs.altsportsleagues.ai/api/reference#create-league"
}

πŸ”„ State Management Flow

Frontend State Architecture

Code Implementation:

// Zustand Store (Global State)
import { create } from 'zustand';
 
export const useLeagueStore = create<LeagueStore>((set) => ({
  selectedLeague: null,
  filters: { sport: 'all', tier: 'all' },
  
  setLeague: (league) => set({ selectedLeague: league }),
  updateFilters: (filters) => set((state) => ({
    filters: { ...state.filters, ...filters }
  })),
}));
 
// React Query (Server State)
import { useQuery, useMutation } from '@tanstack/react-query';
 
export function useLeagues() {
  return useQuery({
    queryKey: ['leagues'],
    queryFn: () => fetch('/api/v1/leagues').then(r => r.json()),
    staleTime: 5 * 60 * 1000, // 5 minutes
  });
}
 
export function useCreateLeague() {
  return useMutation({
    mutationFn: (data) => 
      fetch('/api/v1/leagues', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify(data)
      }).then(r => r.json()),
    onSuccess: () => {
      queryClient.invalidateQueries({ queryKey: ['leagues'] });
    }
  });
}
 
// Firebase Real-Time (Live Updates)
import { onSnapshot, collection } from 'firebase/firestore';
 
useEffect(() => {
  const unsubscribe = onSnapshot(
    collection(db, 'live_games'),
    (snapshot) => {
      const games = snapshot.docs.map(doc => ({
        id: doc.id,
        ...doc.data()
      }));
      updateLiveGames(games);
    }
  );
  
  return () => unsubscribe();
}, []);

🎨 Frontend Type Definitions

TypeScript Interfaces (Auto-Generated from Backend)

// Generated from Pydantic models via sync-types script
 
export interface League {
  id: string;
  name: string;
  sport: string;
  tier: 1 | 2 | 3 | 4 | 5;
  status: 'active' | 'pending' | 'inactive' | 'archived';
  founded?: number;
  headquarters?: string;
  website?: string;
  team_count: number;
  player_count: number;
  created_at: string;
  updated_at: string;
}
 
export interface Team {
  id: string;
  league_id: string;
  name: string;
  city?: string;
  founded?: number;
  colors?: string[];
  logo_url?: string;
  wins: number;
  losses: number;
  created_at: string;
}
 
export interface Player {
  id: string;
  name: string;
  birth_date?: string;
  position: string;
  current_team_id?: string;
  jersey_number?: number;
  attributes: Record<string, number>;
  total_games: number;
  career_points: number;
}
 
// API Response types
export interface LeagueListResponse {
  leagues: League[];
  total: number;
  page: number;
  per_page: number;
  pages: number;
}
 
export interface ApiError {
  error: string;
  message: string;
  details?: Record<string, any>;
  docs?: string;
}

Type Generation Flow

Run type sync:

cd clients/frontend
npm run sync-types
 
# Reads from: ../../data_layer/schemas/
# Generates to: types/generated/

πŸ”„ Data Consistency Patterns

Event-Driven Consistency

Implementation:

from fastapi import BackgroundTasks
 
@app.post("/v1/leagues", response_model=League)
async def create_league(
    league: LeagueCreate,
    background_tasks: BackgroundTasks
):
    # Primary write (Supabase)
    league_data = await supabase.create_league(league)
    
    # Background sync (eventual consistency)
    background_tasks.add_task(sync_to_neo4j, league_data)
    background_tasks.add_task(sync_to_firebase, league_data)
    background_tasks.add_task(invalidate_cache, 'leagues')
    background_tasks.add_task(trigger_webhook, 'league.created', league_data)
    
    return league_data

πŸ”— Related Schema Documentation

Platform

Documentation

Community

Support

partnership@altsportsdata.comdev@altsportsleagues.ai

2025 Β© AltSportsLeagues.ai. Powered by AI-driven sports business intelligence.

πŸ€– AI-Enhancedβ€’πŸ“Š Data-Drivenβ€’βš‘ Real-Time