Files
SportstimeAPI/.planning/codebase/INTEGRATIONS.md
2026-01-18 16:55:09 -06:00

6.6 KiB

External Integrations

Analysis Date: 2026-01-18

APIs & External Services

Apple CloudKit (Primary Data Source):

  • Purpose: Sync game schedules, teams, stadiums, league structure to all users
  • Container: iCloud.com.sportstime.app
  • Database: Public (read-only for users, admin writes via Python uploader)
  • Client: Core/Services/CloudKitService.swift
  • Sync: Core/Services/CanonicalSyncService.swift
  • Record types: Game, Team, Stadium, LeagueStructure, TeamAlias, StadiumAlias, Sport
  • Auth: User iCloud account (automatic), server-to-server JWT (Python uploader)

Apple MapKit:

  • Purpose: Geocoding, routing, map snapshots, EV charger search, POI search
  • Services used:
    • MKLocalSearch - Address and POI search (LocationService.swift)
    • MKDirections - Driving routes and ETA (LocationService.swift)
    • MKMapSnapshotter - Static map images for PDF (Export/Services/MapSnapshotService.swift)
    • MKLocalPointsOfInterestRequest - EV chargers (EVChargingService.swift)
  • Client: Core/Services/LocationService.swift, Core/Services/EVChargingService.swift
  • Auth: Automatic via Apple frameworks
  • Rate limits: Apple's standard MapKit limits

Apple StoreKit 2:

  • Purpose: In-app subscriptions (Pro tier)
  • Products: com.sportstime.pro.monthly, com.sportstime.pro.annual
  • Client: Core/Store/StoreManager.swift
  • Features gated: Trip limit (1 free, unlimited Pro)

Sports League APIs (Official):

API URL Sport Reliability Client
MLB Stats API https://statsapi.mlb.com/api/v1 MLB Official ScoreAPIProviders/MLBStatsProvider.swift
NHL Stats API https://api-web.nhle.com/v1 NHL Official ScoreAPIProviders/NHLStatsProvider.swift
NBA Stats API https://stats.nba.com/stats NBA Unofficial ScoreAPIProviders/NBAStatsProvider.swift

NBA Stats API Notes:

  • Requires specific headers to avoid 403 (User-Agent, Referer, x-nba-stats-origin, x-nba-stats-token)
  • May break without notice (unofficial)

Sports Reference Sites (Scraping Fallback):

Site URL Pattern Sport Client
Baseball-Reference baseball-reference.com/boxes/?month=M&day=D&year=Y MLB HistoricalGameScraper.swift
Basketball-Reference basketball-reference.com/boxscores/?month=M&day=D&year=Y NBA HistoricalGameScraper.swift
Hockey-Reference hockey-reference.com/boxscores/?month=M&day=D&year=Y NHL HistoricalGameScraper.swift
Pro-Football-Reference pro-football-reference.com/boxscores/... NFL HistoricalGameScraper.swift
  • Uses SwiftSoup for HTML parsing
  • On-device scraping (no server costs, unlimited scale)
  • Cached per-session to avoid redundant requests

Data Storage

SwiftData (Local):

  • Purpose: Offline-first data storage, user trips, preferences
  • Location: App sandbox (automatic)
  • CloudKit sync: Disabled (cloudKitDatabase: .none)
  • Schema: See SportsTimeApp.swift ModelContainer configuration

CloudKit Public Database (Remote):

  • Purpose: Shared schedule data for all users
  • Container: iCloud.com.sportstime.app
  • Access: Read (all users), Write (admin via Python uploader)
  • Sync method: Date-based delta sync (modificationDate filtering)

URLCache (Images):

  • Purpose: Cache team logos and stadium photos
  • Memory: 50 MB
  • Disk: 100 MB
  • Path: ImageCache
  • Client: Export/Services/RemoteImageService.swift

File Storage:

  • Local filesystem only for PDF export (temporary)
  • Photo library access for visit photo imports

Caching:

  • In-memory game score cache: ScoreResolutionCache.swift
  • In-memory scraper cache: HistoricalGameScraper.swift
  • URLSession cache: Team logos, stadium photos

Authentication & Identity

iCloud (Automatic):

  • Users authenticate via their iCloud account
  • Required for: CloudKit sync, poll voting identity
  • Optional: App works offline without iCloud

CloudKit Server-to-Server (Python Uploader):

  • JWT authentication with ECDSA P-256 key
  • Key ID and team ID from Apple Developer portal
  • Used by Scripts/sportstime_parser/uploaders/cloudkit.py

Monitoring & Observability

Error Tracking:

  • None (no Sentry, Crashlytics, etc.)
  • Errors logged to console via os.Logger

Logs:

  • os.Logger subsystem: com.sportstime.app
  • Categories: BackgroundSyncManager, NetworkMonitor
  • Rich console output in Python scraper

CI/CD & Deployment

Hosting:

  • iOS App Store (planned)
  • CloudKit public database (Apple infrastructure)

CI Pipeline:

  • None configured (no GitHub Actions, Xcode Cloud, etc.)

Data Pipeline:

  • Python CLI (sportstime-parser) scrapes schedules
  • Uploads to CloudKit via CloudKit Web Services API
  • iOS apps sync from CloudKit automatically

Background Processing

BGTaskScheduler:

  • Refresh task: com.sportstime.app.refresh (periodic CloudKit sync)
  • Processing task: com.sportstime.app.db-cleanup (overnight heavy sync)
  • Manager: Core/Services/BackgroundSyncManager.swift

Network Monitoring:

  • NWPathMonitor triggers sync on connectivity restoration
  • Debounce: 2.5 seconds (handles WiFi/cellular handoffs)
  • Manager: Core/Services/NetworkMonitor.swift

Push Notifications:

  • CloudKit subscriptions for data changes
  • Silent notifications (shouldSendContentAvailable)
  • Subscription IDs: game-updates, league-structure-updates, team-alias-updates, stadium-alias-updates

Environment Configuration

Required Environment Variables:

iOS App:

  • None required (CloudKit container ID hardcoded)

Python Uploader:

  • CloudKit key ID (or in config)
  • CloudKit team ID (or in config)
  • ECDSA private key path

Secrets Location:

  • iOS: Entitlements file (SportsTime.entitlements)
  • Python: Environment variables or local config file

Webhooks & Callbacks

Incoming:

  • CloudKit silent push notifications (background sync trigger)
  • Deep links: sportstime://poll/{shareCode} (poll sharing)

Outgoing:

  • None

Rate Limiting

Internal Rate Limiter:

  • Core/Services/RateLimiter.swift
  • Per-provider keys: mlb_stats, nba_stats, nhl_stats
  • Prevents API abuse when resolving historical game scores

Provider Auto-Disable:

  • Official APIs: Never auto-disabled
  • Unofficial APIs: Disabled after 3 failures (24h cooldown)
  • Scraped sources: Disabled after 2 failures (24h cooldown)

Polls (Group Trip Planning)

CloudKit-Based Polling:

  • Record type: TripPoll, PollVote
  • Share codes: 6-character uppercase alphanumeric
  • Deep link: sportstime://poll/{shareCode}
  • Service: Core/Services/PollService.swift

Integration audit: 2026-01-18