#!/usr/bin/env python3 """ TheSportsDB API Discovery — walk the API top-down, save raw responses. Uses V1 free key ('3') for basic structure validation. With a premium key, also tests V2 endpoints. Workflow: 1. Search for leagues (MLS, Premier League) → IDs 2. Search for teams (Toronto FC, Arsenal) → IDs 3. Get team schedules (next + previous matches) → event IDs 4. Get match detail, stats, lineup, timeline for a finished match 5. Get squad roster + sample player detail 6. Get standings (V1) 7. Get events by date (V1) 8. Get livescores Saves every response to docs/api_samples/sportsdb/{step}_{endpoint}.json """ import sys import json from pathlib import Path sys.path.insert(0, str(Path(__file__).resolve().parent.parent)) from nike import config from nike import sportsdb as api SAMPLES_DIR = Path(__file__).resolve().parent.parent / "docs" / "api_samples" / "sportsdb" SAMPLES_DIR.mkdir(parents=True, exist_ok=True) # Track API calls _call_count = 0 def save(name: str, data) -> None: """Save raw API response to a JSON file.""" global _call_count _call_count += 1 path = SAMPLES_DIR / f"{name}.json" with open(path, "w") as f: json.dump(data, f, indent=2, default=str) size_kb = path.stat().st_size / 1024 print(f" ✓ Saved {path.name} ({size_kb:.1f} KB)") def show_keys(data, label="response"): """Print top-level structure of a response.""" if isinstance(data, dict): for k, v in data.items(): if isinstance(v, list): print(f" {label}.{k}: list ({len(v)} items)") if v and isinstance(v[0], dict): print(f" [0] keys: {list(v[0].keys())}") elif isinstance(v, dict): print(f" {label}.{k}: dict ({len(v)} keys)") elif v is None: print(f" {label}.{k}: null") else: print(f" {label}.{k}: {str(v)[:80]}") elif isinstance(data, list): print(f" {label}: list ({len(data)} items)") if data and isinstance(data[0], dict): print(f" [0] keys: {list(data[0].keys())}") elif data is None: print(f" {label}: null") def extract_items(data: dict, key: str) -> list: """Safely extract a list from a response dict.""" items = data.get(key) return items if isinstance(items, list) else [] def main(): is_premium = config.SPORTSDB_KEY not in ('3', '') print("=" * 60) print(" TheSportsDB API Discovery") print(f" Key: {'Premium' if is_premium else 'Free (V1 only)'}") print("=" * 60) # ══════════════════════════════════════════════════════ # STEP 1: Search for leagues (V1 free works for search) # ══════════════════════════════════════════════════════ print("\n[1/8] Searching for leagues...") mls_id = None epl_id = None if is_premium: # V2 search mls = api.search_leagues("MLS") save("01_v2_search_leagues_mls", mls) show_keys(mls) items = extract_items(mls, "search") if items: mls_id = items[0].get("idLeague") print(f" → MLS: {items[0].get('strLeague')} (ID: {mls_id})") epl = api.search_leagues("Premier League") save("01_v2_search_leagues_epl", epl) items = extract_items(epl, "search") if items: epl_id = items[0].get("idLeague") print(f" → EPL: {items[0].get('strLeague')} (ID: {epl_id})") else: print(" (V2 search requires premium — using V1 search)") # Also try V1 search (works on free key) mls_v1 = api.v1_search_teams("Toronto FC") save("01_v1_search_teams_tfc", mls_v1) show_keys(mls_v1) teams = extract_items(mls_v1, "teams") tfc_id = None if teams: tfc_id = teams[0].get("idTeam") mls_id = mls_id or teams[0].get("idLeague") print(f" → Toronto FC: ID={tfc_id}, league={teams[0].get('strLeague')} " f"(leagueID={teams[0].get('idLeague')})") ars_v1 = api.v1_search_teams("Arsenal") save("01_v1_search_teams_arsenal", ars_v1) teams = extract_items(ars_v1, "teams") ars_id = None if teams: ars_id = teams[0].get("idTeam") epl_id = epl_id or teams[0].get("idLeague") print(f" → Arsenal: ID={ars_id}, league={teams[0].get('strLeague')} " f"(leagueID={teams[0].get('idLeague')})") # ══════════════════════════════════════════════════════ # STEP 2: Team detail # ══════════════════════════════════════════════════════ print("\n[2/8] Fetching team details...") if tfc_id: tfc_detail = api.v1_lookup_team(int(tfc_id)) save("02_v1_team_detail_tfc", tfc_detail) teams = extract_items(tfc_detail, "teams") if teams: t = teams[0] print(f" → {t.get('strTeam')}: {t.get('strStadium')}, " f"{t.get('strStadiumLocation')}") print(f" Keys: {list(t.keys())[:15]}...") # ══════════════════════════════════════════════════════ # STEP 3: Schedule — next + previous matches # ══════════════════════════════════════════════════════ print("\n[3/8] Fetching team schedules...") event_id = None if tfc_id: # V1 previous (last 5) prev = api.v1_previous_team(int(tfc_id)) save("03_v1_previous_tfc", prev) results = extract_items(prev, "results") print(f" Previous matches: {len(results)}") for m in results[:3]: eid = m.get("idEvent") home = m.get("strHomeTeam", "?") away = m.get("strAwayTeam", "?") hscore = m.get("intHomeScore", "?") ascore = m.get("intAwayScore", "?") date = m.get("dateEvent", "?") print(f" {date} {home} {hscore}-{ascore} {away} (eventID: {eid})") if not event_id and hscore is not None: event_id = int(eid) # V1 next (next 5) nxt = api.v1_next_team(int(tfc_id)) save("03_v1_next_tfc", nxt) events = extract_items(nxt, "events") print(f" Upcoming matches: {len(events)}") for m in events[:3]: home = m.get("strHomeTeam", "?") away = m.get("strAwayTeam", "?") date = m.get("dateEvent", "?") print(f" {date} {home} vs {away}") if is_premium and tfc_id: # V2 schedule endpoints prev_v2 = api.schedule_previous_team(int(tfc_id)) save("03_v2_previous_tfc", prev_v2) show_keys(prev_v2) next_v2 = api.schedule_next_team(int(tfc_id)) save("03_v2_next_tfc", next_v2) show_keys(next_v2) # ══════════════════════════════════════════════════════ # STEP 4: Match detail (V2 lookup for a finished match) # ══════════════════════════════════════════════════════ print("\n[4/8] Fetching match detail...") if event_id: print(f" Using event ID: {event_id}") # V1 event lookup (works on free) ev1 = api.v1_event_results(event_id) save("04_v1_event_detail", ev1) events = extract_items(ev1, "events") if events: e = events[0] print(f" V1 event keys: {list(e.keys())[:15]}...") print(f" → {e.get('strHomeTeam')} {e.get('intHomeScore')}-" f"{e.get('intAwayScore')} {e.get('strAwayTeam')}") print(f" Venue: {e.get('strVenue')}, Referee: {e.get('strOfficial')}") if is_premium: # V2 event detail ev2 = api.lookup_event(event_id) save("04_v2_event_detail", ev2) show_keys(ev2) # V2 stats stats = api.lookup_event_stats(event_id) save("04_v2_event_stats", stats) show_keys(stats) stat_items = extract_items(stats, "lookup") if stat_items: print(f" Stats sample:") for s in stat_items[:5]: print(f" {s.get('strStat')}: " f"Home={s.get('intHome')} Away={s.get('intAway')}") # V2 timeline timeline = api.lookup_event_timeline(event_id) save("04_v2_event_timeline", timeline) show_keys(timeline) tl_items = extract_items(timeline, "lookup") if tl_items: print(f" Timeline events: {len(tl_items)}") for t in tl_items[:5]: print(f" {t.get('intTime')}' {t.get('strTimeline')}: " f"{t.get('strPlayer')} ({t.get('strTeam')})") # V2 lineup lineup = api.lookup_event_lineup(event_id) save("04_v2_event_lineup", lineup) show_keys(lineup) lineup_items = extract_items(lineup, "lookup") if lineup_items: print(f" Lineup entries: {len(lineup_items)}") for p in lineup_items[:3]: print(f" #{p.get('intSquadNumber')} {p.get('strPlayer')} " f"({p.get('strPosition')}) " f"home={p.get('strHome')} sub={p.get('strSubstitute')}") else: print(" ⚠ No event ID found — skipping") # ══════════════════════════════════════════════════════ # STEP 5: Squad roster + player detail # ══════════════════════════════════════════════════════ print("\n[5/8] Fetching squad & player detail...") player_id = None if is_premium and tfc_id: squad = api.list_players(int(tfc_id)) save("05_v2_squad_tfc", squad) show_keys(squad) players = extract_items(squad, "list") if players: p = players[0] player_id = p.get("idPlayer") print(f" Squad size: {len(players)}") print(f" Sample player: {p.get('strPlayer')} " f"(#{p.get('strNumber')}, {p.get('strPosition')})") print(f" Player keys: {list(p.keys())[:15]}...") if player_id: pdetail = api.lookup_player(int(player_id)) save("05_v2_player_detail", pdetail) show_keys(pdetail) else: # V1 player search players_v1 = api.v1_search_players("Bernardeschi") save("05_v1_search_player", players_v1) show_keys(players_v1) items = extract_items(players_v1, "player") if items: player_id = items[0].get("idPlayer") print(f" → {items[0].get('strPlayer')} (ID: {player_id})") print(f" Keys: {list(items[0].keys())[:15]}...") # ══════════════════════════════════════════════════════ # STEP 6: Standings (V1) # ══════════════════════════════════════════════════════ print("\n[6/8] Fetching standings...") if epl_id: # EPL should have current season data standings = api.v1_standings(int(epl_id), "2025-2026") save("06_v1_standings_epl", standings) table = extract_items(standings, "table") print(f" EPL standings: {len(table)} teams") if table: print(f" [0] keys: {list(table[0].keys())}") for row in table[:3]: print(f" #{row.get('intRank')} {row.get('strTeam')} " f"P:{row.get('intPlayed')} W:{row.get('intWin')} " f"D:{row.get('intDraw')} L:{row.get('intLoss')} " f"Pts:{row.get('intPoints')}") if mls_id: standings_mls = api.v1_standings(int(mls_id), "2026") save("06_v1_standings_mls", standings_mls) table = extract_items(standings_mls, "table") print(f" MLS standings: {len(table)} teams") if table: for row in table[:3]: print(f" #{row.get('intRank')} {row.get('strTeam')} " f"Pts:{row.get('intPoints')}") # ══════════════════════════════════════════════════════ # STEP 7: Events by date (V1) # ══════════════════════════════════════════════════════ print("\n[7/8] Fetching events by date...") events_today = api.v1_events_by_date("2026-03-09") save("07_v1_events_today", events_today) ev_list = extract_items(events_today, "events") print(f" Soccer events today: {len(ev_list)}") if ev_list: print(f" [0] keys: {list(ev_list[0].keys())[:15]}...") for e in ev_list[:3]: print(f" {e.get('strLeague')}: {e.get('strHomeTeam')} vs " f"{e.get('strAwayTeam')} ({e.get('strStatus')})") if mls_id: mls_events = api.v1_events_by_date_league("2026-03-09", int(mls_id)) save("07_v1_events_today_mls", mls_events) ev_list = extract_items(mls_events, "events") print(f" MLS events today: {len(ev_list)}") for e in ev_list[:5]: print(f" {e.get('strHomeTeam')} vs {e.get('strAwayTeam')} " f"({e.get('strStatus')})") # ══════════════════════════════════════════════════════ # STEP 8: Livescores (V2 premium only) # ══════════════════════════════════════════════════════ print("\n[8/8] Fetching livescores...") if is_premium: live = api.livescores_soccer() save("08_v2_livescores", live) show_keys(live) games = extract_items(live, "livescore") print(f" Live soccer matches: {len(games)}") for g in games[:3]: print(f" {g.get('strHomeTeam')} {g.get('intHomeScore')}-" f"{g.get('intAwayScore')} {g.get('strAwayTeam')} " f"({g.get('strStatus')} {g.get('strProgress')}')") else: print(" (Livescores require premium key)") # ══════════════════════════════════════════════════════ # Summary # ══════════════════════════════════════════════════════ print("\n" + "=" * 60) files = sorted(SAMPLES_DIR.glob("*.json")) print(f" Saved {len(files)} response samples to docs/api_samples/sportsdb/") for f in files: size_kb = f.stat().st_size / 1024 print(f" {f.name:.<55} {size_kb:.1f} KB") print("=" * 60) print(f"\n API calls made: {_call_count}") print(f" Key type: {'Premium (V1+V2)' if is_premium else 'Free (V1 only)'}") print(f"\n Discovered IDs:") print(f" MLS league ID : {mls_id}") print(f" EPL league ID : {epl_id}") print(f" Toronto FC team ID : {tfc_id}") print(f" Arsenal team ID : {ars_id}") if event_id: print(f" Sample event ID : {event_id}") if player_id: print(f" Sample player ID : {player_id}") print() if __name__ == "__main__": main()