<!DOCTYPE html> <html lang="en" data-theme="light"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>SportsVisio Public API Documentation</title> <link rel="preconnect" href="https://fonts.googleapis.com"> <link href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700&family=JetBrains+Mono:wght@400;500&display=swap" rel="stylesheet"> <style> :root { /* SportsVisio Brand Colors */ --sv-red: #FF4C57; --sv-black-1: #151515; --sv-black-2: #202020; --sv-gray-1: #666666; --sv-gray-2: #999999; --sv-gray-3: #C4C4C4; --sv-gray-4: #DDDDDD; --sv-cream: #FBF1D0; --sv-orange: #FEC679; --sv-coral: #FA7368; --bg: #ffffff; --bg-secondary: #f5f5f5; --bg-sidebar: var(--sv-black-1); --bg-sidebar-hover: var(--sv-black-2); --bg-code: var(--sv-black-1); --text: var(--sv-black-1); --text-secondary: var(--sv-gray-1); --text-sidebar: var(--sv-gray-3); --text-sidebar-active: #ffffff; --accent: var(--sv-red); --accent-light: #fff0f1; --border: var(--sv-gray-4); --card-bg: #ffffff; --card-shadow: 0 1px 3px rgba(0,0,0,0.08), 0 1px 2px rgba(0,0,0,0.06); --card-shadow-hover: 0 4px 12px rgba(0,0,0,0.12); --get: #22c55e; --get-bg: #f0fdf4; --post: var(--sv-red); --post-bg: #fff0f1; --put: var(--sv-orange); --put-bg: #fef9f0; --delete: #ef4444; --delete-bg: #fef2f2; --patch: var(--sv-coral); --patch-bg: #fff5f4; } [data-theme="dark"] { --bg: var(--sv-black-1); --bg-secondary: var(--sv-black-2); --bg-sidebar: #0a0a0a; --bg-sidebar-hover: var(--sv-black-1); --bg-code: #0a0a0a; --text: #e8e8e8; --text-secondary: var(--sv-gray-2); --border: #333333; --card-bg: #000000; --card-shadow: 0 1px 3px rgba(0,0,0,0.4); --card-shadow-hover: 0 4px 12px rgba(0,0,0,0.5); --accent-light: #2a1516; --get-bg: #0f291a; --post-bg: #2a1516; --put-bg: #2a2010; --delete-bg: #2a0f0f; --patch-bg: #2a1514; } * { margin: 0; padding: 0; box-sizing: border-box; } html { scroll-behavior: smooth; } body { font-family: 'Roobert', 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif; background: var(--bg); color: var(--text); line-height: 1.6; } code, pre, .endpoint-path, .param-name { font-family: 'JetBrains Mono', 'SF Mono', 'Fira Code', monospace; } /* Layout */ .layout { display: flex; min-height: 100vh; } .sidebar { width: 280px; background: var(--bg-sidebar); position: fixed; top: 0; left: 0; bottom: 0; overflow-y: auto; z-index: 100; transition: transform 0.3s; } .main { margin-left: 280px; flex: 1; min-width: 0; } /* Sidebar */ .sidebar-header { padding: 24px 20px; border-bottom: 1px solid rgba(255,255,255,0.08); } .sidebar-logo { font-size: 20px; font-weight: 700; color: #fff; letter-spacing: -0.5px; } .sidebar-logo span { color: var(--sv-red); } .sidebar-subtitle { font-size: 11px; color: var(--text-sidebar); margin-top: 4px; text-transform: uppercase; letter-spacing: 1px; } .sidebar-nav { padding: 12px 0; } .sidebar-section { padding: 8px 20px 4px; font-size: 10px; font-weight: 600; text-transform: uppercase; letter-spacing: 1.5px; color: rgba(255,255,255,0.35); margin-top: 8px; } .sidebar-link { display: flex; align-items: center; padding: 8px 20px 8px 24px; color: var(--text-sidebar); text-decoration: none; font-size: 13px; font-weight: 400; transition: all 0.15s; border-left: 3px solid transparent; } .sidebar-link:hover { background: var(--bg-sidebar-hover); color: #fff; } .sidebar-link.active { color: var(--text-sidebar-active); background: var(--bg-sidebar-hover); border-left-color: var(--accent); font-weight: 500; } .sidebar-link .link-badge { margin-left: auto; font-size: 10px; padding: 1px 6px; border-radius: 10px; font-weight: 600; } .sidebar-link .link-badge.get { background: var(--get); color: #fff; } .sidebar-link .link-badge.post { background: var(--post); color: #fff; } .sidebar-link .link-badge.mixed { background: var(--accent); color: #fff; } /* Top bar */ .topbar { position: sticky; top: 0; background: var(--bg); border-bottom: 1px solid var(--border); padding: 0 32px; height: 56px; display: flex; align-items: center; justify-content: space-between; z-index: 50; backdrop-filter: blur(8px); } .topbar-left { display: flex; align-items: center; gap: 12px; } .hamburger { display: none; background: none; border: none; color: var(--text); font-size: 24px; cursor: pointer; padding: 4px; } .search-box { position: relative; } .search-box input { padding: 8px 12px 8px 36px; border: 1px solid var(--border); border-radius: 8px; font-size: 13px; font-family: inherit; background: var(--bg-secondary); color: var(--text); width: 280px; outline: none; transition: border-color 0.2s; } .search-box input:focus { border-color: var(--accent); } .search-box::before { content: "\1F50D"; position: absolute; left: 10px; top: 50%; transform: translateY(-50%); font-size: 14px; opacity: 0.5; } .topbar-right { display: flex; align-items: center; gap: 12px; } #themeBtn { background: none; border: 1px solid var(--border); border-radius: 8px; padding: 6px 10px; cursor: pointer; font-size: 16px; color: var(--text); transition: background 0.2s; } #themeBtn:hover { background: var(--bg-secondary); } .version-badge { font-size: 11px; font-weight: 600; padding: 4px 10px; border-radius: 12px; background: var(--accent-light); color: var(--sv-red); } /* Content */ .content { max-width: 960px; margin: 0 auto; padding: 32px; } .section { margin-bottom: 48px; scroll-margin-top: 72px; } /* Hero */ .hero { background: linear-gradient(135deg, var(--sv-cream) 0%, var(--sv-orange) 33%, var(--sv-coral) 66%, var(--sv-red) 100%); border-radius: 16px; padding: 48px 40px; color: var(--sv-black-1); margin-bottom: 40px; scroll-margin-top: 72px; } .hero h1 { font-family: 'Lateral Compressed', 'Roobert', 'Inter', sans-serif; font-size: 36px; font-weight: 900; letter-spacing: 0.5px; text-transform: uppercase; margin-bottom: 8px; color: var(--sv-black-1); } .hero p { color: var(--sv-black-2); font-size: 16px; max-width: 600px; font-weight: 500; } .hero-meta { display: flex; gap: 24px; margin-top: 20px; font-size: 13px; } .hero-meta-item { display: flex; align-items: center; gap: 6px; color: var(--sv-gray-1); } .hero-meta-item strong { color: var(--sv-black-1); } /* Quick links */ .quick-links { display: grid; grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); gap: 16px; margin-bottom: 40px; } .quick-link { display: block; padding: 20px; background: var(--card-bg); border: 1px solid var(--border); border-radius: 12px; text-decoration: none; color: var(--text); transition: all 0.2s; box-shadow: var(--card-shadow); } .quick-link:hover { box-shadow: var(--card-shadow-hover); border-color: var(--accent); transform: translateY(-2px); } .quick-link-icon { font-size: 24px; margin-bottom: 8px; } .quick-link-title { font-size: 14px; font-weight: 600; margin-bottom: 4px; } .quick-link-desc { font-size: 12px; color: var(--text-secondary); } /* Section headers */ h2 { font-family: 'Roobert', 'Inter', sans-serif; font-size: 24px; font-weight: 700; letter-spacing: -0.3px; margin-bottom: 16px; padding-bottom: 12px; border-bottom: 2px solid var(--sv-red); } h3 { font-size: 18px; font-weight: 600; margin-bottom: 12px; } h4 { font-size: 14px; font-weight: 600; margin-bottom: 8px; } p { margin-bottom: 12px; font-size: 14px; } /* Code blocks */ .code-block { background: var(--bg-code); border-radius: 10px; overflow: hidden; margin: 12px 0; } .code-block-header { display: flex; justify-content: space-between; align-items: center; padding: 8px 16px; background: rgba(255,255,255,0.05); border-bottom: 1px solid rgba(255,255,255,0.08); font-size: 12px; color: #94a3b8; } .copy-btn { background: rgba(255,255,255,0.1); border: none; color: #94a3b8; padding: 3px 10px; border-radius: 4px; font-size: 11px; cursor: pointer; font-family: inherit; transition: background 0.2s; } .copy-btn:hover { background: rgba(255,255,255,0.2); color: #fff; } pre { padding: 16px; overflow-x: auto; font-size: 13px; line-height: 1.5; color: #e2e8f0; } code { font-size: 13px; } p code, li code, td code { background: var(--bg-secondary); padding: 2px 6px; border-radius: 4px; font-size: 12px; color: var(--sv-red); border: 1px solid var(--border); } /* Method badges */ .method-badge { display: inline-block; padding: 3px 10px; border-radius: 6px; font-size: 11px; font-weight: 700; font-family: 'JetBrains Mono', monospace; text-transform: uppercase; letter-spacing: 0.5px; flex-shrink: 0; } .method-badge.get { background: var(--get-bg); color: var(--get); } .method-badge.post { background: var(--post-bg); color: var(--post); } .method-badge.put { background: var(--put-bg); color: var(--put); } .method-badge.delete { background: var(--delete-bg); color: var(--delete); } /* Endpoint cards */ .tag-group { margin-bottom: 32px; scroll-margin-top: 72px; } .tag-group-header { display: flex; align-items: center; justify-content: space-between; margin-bottom: 16px; } .tag-group-header h3 { margin-bottom: 0; } .tag-count { font-size: 12px; color: var(--text-secondary); background: var(--bg-secondary); padding: 3px 10px; border-radius: 12px; } .endpoint-card { background: var(--card-bg); border: 1px solid var(--border); border-radius: 10px; margin-bottom: 10px; overflow: hidden; transition: box-shadow 0.2s; } .endpoint-card:hover { box-shadow: var(--card-shadow-hover); } .endpoint-header { display: flex; align-items: center; gap: 12px; padding: 14px 18px; cursor: pointer; user-select: none; transition: background 0.15s; } .endpoint-header:hover { background: var(--bg-secondary); } .endpoint-path { font-size: 13px; font-weight: 500; color: var(--text); flex: 1; } .endpoint-summary { font-size: 12px; color: var(--text-secondary); margin-right: 8px; } .endpoint-chevron { font-size: 10px; color: var(--text-secondary); transition: transform 0.2s; } .endpoint-card.open .endpoint-chevron { transform: rotate(90deg); } .endpoint-body { display: none; padding: 0 18px 18px; border-top: 1px solid var(--border); } .endpoint-card.open .endpoint-body { display: block; padding-top: 18px; } .endpoint-desc { font-size: 13px; color: var(--text-secondary); margin-bottom: 16px; } /* Parameter tables */ .param-table { width: 100%; border-collapse: collapse; font-size: 13px; margin-bottom: 16px; } .param-table th { text-align: left; padding: 8px 12px; background: var(--bg-secondary); font-weight: 600; font-size: 11px; text-transform: uppercase; letter-spacing: 0.5px; color: var(--text-secondary); border-bottom: 2px solid var(--border); } .param-table td { padding: 8px 12px; border-bottom: 1px solid var(--border); vertical-align: top; } .param-table tr:last-child td { border-bottom: none; } .param-name { font-weight: 500; color: var(--sv-red); font-size: 12px; } .param-type { font-size: 11px; color: var(--text-secondary); background: var(--bg-secondary); padding: 1px 6px; border-radius: 4px; } .param-in { font-size: 11px; padding: 1px 6px; border-radius: 4px; background: var(--bg-secondary); color: var(--text-secondary); } .param-required { color: var(--delete); font-weight: 700; margin-left: 2px; } /* Response codes */ .response-codes { display: flex; gap: 8px; flex-wrap: wrap; margin-bottom: 12px; } .response-code { font-size: 12px; padding: 4px 10px; border-radius: 6px; font-weight: 500; } .response-code.success { background: var(--get-bg); color: var(--get); } .response-code.client-error { background: var(--delete-bg); color: var(--delete); } /* Scenario section */ .scenario-step { background: var(--card-bg); border: 1px solid var(--border); border-radius: 10px; padding: 20px; margin-bottom: 16px; } .scenario-step-header { display: flex; align-items: center; gap: 12px; margin-bottom: 12px; } .step-number { width: 28px; height: 28px; border-radius: 50%; background: var(--accent); color: #fff; display: flex; align-items: center; justify-content: center; font-size: 13px; font-weight: 700; flex-shrink: 0; } .scenario-step h4 { margin-bottom: 0; } /* Info boxes */ .info-box { padding: 16px 20px; border-radius: 8px; margin: 16px 0; font-size: 13px; border-left: 4px solid; } .info-box.info { background: var(--post-bg); border-color: var(--post); } .info-box.warning { background: var(--put-bg); border-color: var(--put); } .info-box.tip { background: var(--get-bg); border-color: var(--get); } /* Changelog */ .changelog-entry { padding: 16px 0; border-bottom: 1px solid var(--border); } .changelog-entry:last-child { border-bottom: none; } .changelog-date { font-size: 12px; font-weight: 600; color: var(--sv-red); margin-bottom: 4px; } .changelog-version { font-size: 11px; background: var(--accent-light); color: var(--sv-red); padding: 2px 8px; border-radius: 4px; font-weight: 600; margin-left: 8px; } .changelog-items { padding-left: 20px; margin-top: 8px; } .changelog-items li { font-size: 13px; margin-bottom: 4px; color: var(--text-secondary); } .changelog-tag { font-size: 10px; font-weight: 600; padding: 1px 6px; border-radius: 4px; text-transform: uppercase; margin-right: 6px; } .changelog-tag.added { background: var(--get-bg); color: var(--get); } .changelog-tag.changed { background: var(--put-bg); color: var(--put); } .changelog-tag.fixed { background: var(--post-bg); color: var(--post); } /* Hidden endpoint cards */ .endpoint-card.hidden { display: none; } #no-results { text-align: center; padding: 40px; color: var(--text-secondary); font-size: 14px; display: none; } #no-results.visible { display: block; } /* Footer */ .footer { text-align: center; padding: 32px; border-top: 1px solid var(--border); color: var(--text-secondary); font-size: 12px; margin-top: 48px; } .footer a { color: var(--sv-red); text-decoration: none; } /* Back to top */ .back-to-top { position: fixed; bottom: 24px; right: 24px; width: 40px; height: 40px; border-radius: 50%; background: var(--accent); color: #fff; border: none; cursor: pointer; font-size: 18px; display: flex; align-items: center; justify-content: center; opacity: 0; transform: translateY(10px); transition: all 0.3s; z-index: 50; box-shadow: 0 4px 12px rgba(255,76,87,0.4); } .back-to-top.visible { opacity: 1; transform: translateY(0); } /* Responsive */ @media (max-width: 900px) { .sidebar { transform: translateX(-100%); } .sidebar.open { transform: translateX(0); box-shadow: 4px 0 24px rgba(0,0,0,0.3); } .main { margin-left: 0; } .hamburger { display: block; } .content { padding: 20px; } .hero { padding: 32px 24px; } .hero h1 { font-size: 24px; } .search-box input { width: 180px; } .endpoint-header { flex-wrap: wrap; } .endpoint-summary { display: none; } } </style> </head> <body> <div class="layout"> <!-- Sidebar --> <nav class="sidebar" id="sidebar"> <div class="sidebar-header"> <div class="sidebar-logo">Sports<span>Visio</span></div> <div class="sidebar-subtitle">Public API</div> </div> <div class="sidebar-nav"> <div class="sidebar-section">Getting Started</div> <a href="#overview" class="sidebar-link active" onclick="closeMobile()">Overview</a> <a href="#authentication" class="sidebar-link" onclick="closeMobile()">Authentication</a> <a href="#league-integration" class="sidebar-link" onclick="closeMobile()">League Integration Guide</a> <div class="sidebar-section">API Reference</div> <a href="#tag-users" class="sidebar-link" onclick="closeMobile()">Users <span class="link-badge get">1</span></a> <a href="#tag-programs" class="sidebar-link" onclick="closeMobile()">Programs <span class="link-badge get">1</span></a> <a href="#tag-program-divisions" class="sidebar-link" onclick="closeMobile()">Program Divisions <span class="link-badge post">1</span></a> <a href="#tag-teams" class="sidebar-link" onclick="closeMobile()">Teams <span class="link-badge post">1</span></a> <a href="#tag-team-players" class="sidebar-link" onclick="closeMobile()">Team Players <span class="link-badge mixed">3</span></a> <a href="#tag-scheduled-games" class="sidebar-link" onclick="closeMobile()">Scheduled Games <span class="link-badge mixed">3</span></a> <a href="#tag-game-team-assignment" class="sidebar-link" onclick="closeMobile()">Game Roster Assn <span class="link-badge post">1</span></a> <a href="#tag-annotation-statistics" class="sidebar-link" onclick="closeMobile()">Annotation Stats <span class="link-badge get">1</span></a> <a href="#tag-devices" class="sidebar-link" onclick="closeMobile()">Devices <span class="link-badge mixed">5</span></a> <a href="#tag-uploads" class="sidebar-link" onclick="closeMobile()">Uploads <span class="link-badge post">1</span></a> <a href="#tag-multipart-uploads" class="sidebar-link" onclick="closeMobile()">Multipart Uploads <span class="link-badge post">1</span></a> <div class="sidebar-section">More</div> <a href="#changelog" class="sidebar-link" onclick="closeMobile()">Changelog</a> </div> </nav> <!-- Main --> <div class="main"> <!-- Top bar --> <div class="topbar"> <div class="topbar-left"> <button class="hamburger" onclick="toggleSidebar()">☰</button> <div class="search-box"> <input type="text" placeholder="Search endpoints..." oninput="filterEndpoints(this.value)"> </div> </div> <div class="topbar-right"> <span class="version-badge">v1.0</span> <button id="themeBtn" onclick="toggleTheme()">☾</button> </div> </div> <div class="content"> <!-- Hero --> <div class="hero section" id="overview"> <h1>SportsVisio Public API</h1> <p>Public RESTful API for accessing SportsVisio's computer vision-powered sports data. Schedules, stats, game insights, player leaderboards, and more.</p> <div class="hero-meta"> <div class="hero-meta-item"><strong>Base URL</strong> https://api.sportsvisio.com</div> <div class="hero-meta-item"><strong>Version</strong> 1.0</div> <div class="hero-meta-item"><strong>Auth</strong> Bearer JWT</div> </div> </div> <!-- Quick Links --> <div class="quick-links"> <a href="#authentication" class="quick-link"> <div class="quick-link-icon">🔒</div> <div class="quick-link-title">Authentication</div> <div class="quick-link-desc">Set up JWT bearer tokens to access the API</div> </a> <a href="#league-integration" class="quick-link"> <div class="quick-link-icon">🏆</div> <div class="quick-link-title">League Integration</div> <div class="quick-link-desc">Common scenario: schedules, standings, stats</div> </a> <a href="#tag-scheduled-games" class="quick-link"> <div class="quick-link-icon">🏀</div> <div class="quick-link-title">Games & Stats</div> <div class="quick-link-desc">Game records, insights, and player statistics</div> </a> <a href="#tag-devices" class="quick-link"> <div class="quick-link-icon">📷</div> <div class="quick-link-title">Devices & Upload</div> <div class="quick-link-desc">Register cameras and upload game footage</div> </a> </div> <!-- Authentication --> <section class="section" id="authentication"> <h2>Authentication</h2> <p>All API requests require a valid JWT bearer token in the <code>Authorization</code> header. Tokens are issued when a user authenticates with SportsVisio.</p> <div class="info-box info"> <strong>Header Format:</strong> Include your token in every request as shown below. </div> <div class="code-block"> <div class="code-block-header"><span>HTTP Header</span><button class="copy-btn" onclick="copyCode(this)">Copy</button></div> <pre><code>Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VySWQiOiJIYWkhIiwiaWF0IjoxNTg5OTk4MjA3fQ</code></pre> </div> <h4>Making Your First Request</h4> <p>Verify your token works by fetching the current user:</p> <div class="code-block"> <div class="code-block-header"><span>curl</span><button class="copy-btn" onclick="copyCode(this)">Copy</button></div> <pre><code>curl -X GET "https://api.sportsvisio.com/users/" \ -H "Authorization: Bearer YOUR_TOKEN"</code></pre> </div> <div class="info-box tip"> <strong>Tip:</strong> If you receive a <code>401 Unauthorized</code> response, your token may be expired. Re-authenticate to get a fresh token. </div> </section> <!-- League Integration Guide --> <section class="section" id="league-integration"> <h2>League Integration Guide</h2> <p>The most common use case: a league displaying <strong>schedules, standings, game results, and player leaderboards</strong> using SportsVisio data. Follow these steps to build a complete league experience.</p> <div class="scenario-step"> <div class="scenario-step-header"> <span class="step-number">1</span> <h4>Get Your League / Program</h4> </div> <p>First, retrieve your program (league) record. Use the <code>programType</code> filter set to <code>league</code>.</p> <div class="code-block"> <div class="code-block-header"><span>curl</span><button class="copy-btn" onclick="copyCode(this)">Copy</button></div> <pre><code>curl -X GET "https://api.sportsvisio.com/programs/list/{accountId}?programType=league&limit=10" \ -H "Authorization: Bearer YOUR_TOKEN"</code></pre> </div> <div class="code-block"> <div class="code-block-header"><span>Example Response</span><button class="copy-btn" onclick="copyCode(this)">Copy</button></div> <pre><code>{ "items": [ { "id": "a1b2c3d4-5678-9012-abcd-ef1234567890", "name": "BYLD Elite Northeast League", "programType": "league", "sportId": "basketball", "createdAt": "2025-09-15T14:00:00Z" } ], "meta": { "total": 1, "limit": 10, "start": 0 } }</code></pre> </div> </div> <div class="scenario-step"> <div class="scenario-step-header"> <span class="step-number">2</span> <h4>Get Team Rosters</h4> </div> <p>For each team in a division, fetch the player roster. This gives you jersey numbers, names, and player IDs for building roster pages.</p> <div class="code-block"> <div class="code-block-header"><span>curl</span><button class="copy-btn" onclick="copyCode(this)">Copy</button></div> <pre><code>curl -X GET "https://api.sportsvisio.com/teams/players/division/list/{teamId}/{programId}/{eventId}/{divisionId}?limit=25" \ -H "Authorization: Bearer YOUR_TOKEN"</code></pre> </div> <div class="code-block"> <div class="code-block-header"><span>Example Response</span><button class="copy-btn" onclick="copyCode(this)">Copy</button></div> <pre><code>{ "items": [ { "id": "player-uuid-001", "firstName": "Marcus", "lastName": "Williams", "jerseyNumber": "23", "position": "PG", "isActive": true }, { "id": "player-uuid-002", "firstName": "Ciaran", "lastName": "Murphy", "jerseyNumber": "11", "position": "SG", "isActive": true } ], "meta": { "total": 12, "limit": 25, "start": 0 } }</code></pre> </div> </div> <div class="scenario-step"> <div class="scenario-step-header"> <span class="step-number">3</span> <h4>Get Game Schedule & Results</h4> </div> <p>Fetch individual game records for scores, status, and team assignments. Use the scheduled game ID to get full details.</p> <div class="code-block"> <div class="code-block-header"><span>curl</span><button class="copy-btn" onclick="copyCode(this)">Copy</button></div> <pre><code>curl -X GET "https://api.sportsvisio.com/scheduled-games/{scheduledGameId}" \ -H "Authorization: Bearer YOUR_TOKEN"</code></pre> </div> <div class="code-block"> <div class="code-block-header"><span>Example Response</span><button class="copy-btn" onclick="copyCode(this)">Copy</button></div> <pre><code>{ "id": "game-uuid-001", "name": "Warriors vs Celtics", "scheduledDate": "2026-02-15T19:00:00Z", "status": "completed", "teams": [ { "teamId": "team-uuid-001", "teamName": "Bay Area Warriors", "score": 78, "isHome": true }, { "teamId": "team-uuid-002", "teamName": "Boston Celtics Elite", "score": 72, "isHome": false } ], "court": { "name": "Court 1", "arenaName": "SportsVisio Arena" } }</code></pre> </div> </div> <div class="scenario-step"> <div class="scenario-step-header"> <span class="step-number">4</span> <h4>Get Game Insights</h4> </div> <p>Pull AI-generated game insights including trends and performance analytics from SportsVisio's computer vision engine.</p> <div class="code-block"> <div class="code-block-header"><span>curl</span><button class="copy-btn" onclick="copyCode(this)">Copy</button></div> <pre><code>curl -X GET "https://api.sportsvisio.com/scheduled-games/insights/{scheduledGameId}" \ -H "Authorization: Bearer YOUR_TOKEN"</code></pre> </div> </div> <div class="scenario-step"> <div class="scenario-step-header"> <span class="step-number">5</span> <h4>Build Player Leaderboards</h4> </div> <p>Use the game-player-rollup endpoint to get per-player stats for each game. Aggregate across games to build season leaderboards for points, rebounds, assists, and more.</p> <div class="code-block"> <div class="code-block-header"><span>curl</span><button class="copy-btn" onclick="copyCode(this)">Copy</button></div> <pre><code>curl -X GET "https://api.sportsvisio.com/annotations/stats/game-player-rollup/{scheduledGameId}" \ -H "Authorization: Bearer YOUR_TOKEN"</code></pre> </div> <div class="code-block"> <div class="code-block-header"><span>Example Response</span><button class="copy-btn" onclick="copyCode(this)">Copy</button></div> <pre><code>[ { "playerId": "player-uuid-001", "playerName": "Marcus Williams", "teamName": "Bay Area Warriors", "jerseyNumber": "23", "stats": { "points": 24, "rebounds": 8, "assists": 6, "steals": 3, "blocks": 1, "turnovers": 2, "fgMade": 9, "fgAttempted": 18, "fgPercentage": 50.0, "threePtMade": 3, "threePtAttempted": 7, "ftMade": 3, "ftAttempted": 4, "minutesPlayed": 32 } }, { "playerId": "player-uuid-002", "playerName": "Ciaran Murphy", "teamName": "Bay Area Warriors", "jerseyNumber": "11", "stats": { "points": 18, "rebounds": 4, "assists": 9, "steals": 2, "blocks": 0, "turnovers": 3, "fgMade": 7, "fgAttempted": 15, "fgPercentage": 46.7, "threePtMade": 2, "threePtAttempted": 5, "ftMade": 2, "ftAttempted": 2, "minutesPlayed": 34 } } ]</code></pre> </div> <div class="info-box tip"> <strong>Tip:</strong> To build season leaderboards, call this endpoint for each completed game in the division and aggregate the stats per player across all games. </div> </div> </section> <!-- API Reference --> <section class="section" id="api-reference"> <h2>API Reference</h2> <p>Complete reference for all available endpoints. Click any endpoint to expand details.</p> <div id="no-results">No endpoints match your search.</div> <!-- Users --> <div class="tag-group" id="tag-users"> <div class="tag-group-header"><h3>Users</h3><span class="tag-count">1 endpoint</span></div> <div class="endpoint-card" data-search="get users userid profile authenticated"> <div class="endpoint-header" onclick="toggleEndpoint(this)"> <span class="method-badge get">GET</span> <span class="endpoint-path">/users/{userId}</span> <span class="endpoint-summary">Get User</span> <span class="endpoint-chevron">▶</span> </div> <div class="endpoint-body"> <p class="endpoint-desc">Returns User record of the currently authenticated user, unless optional userId is specified.</p> <h4>Parameters</h4> <table class="param-table"><thead><tr><th>Name</th><th>In</th><th>Type</th><th>Required</th><th>Description</th></tr></thead><tbody> <tr><td><span class="param-name">userId</span></td><td><span class="param-in">path</span></td><td><span class="param-type">string</span></td><td>No</td><td>Optional user UUID. If omitted, returns authenticated user.</td></tr> </tbody></table> <div class="response-codes"><span class="response-code success">200 User found</span></div> <div class="code-block"><div class="code-block-header"><span>curl</span><button class="copy-btn" onclick="copyCode(this)">Copy</button></div> <pre><code>curl -X GET "https://api.sportsvisio.com/users/{userId}" \ -H "Authorization: Bearer YOUR_TOKEN"</code></pre></div> </div></div> </div> <!-- Programs --> <div class="tag-group" id="tag-programs"> <div class="tag-group-header"><h3>Programs</h3><span class="tag-count">1 endpoint</span></div> <div class="endpoint-card" data-search="get programs list accountid league club tournament paginated"> <div class="endpoint-header" onclick="toggleEndpoint(this)"> <span class="method-badge get">GET</span> <span class="endpoint-path">/programs/list/{accountId}</span> <span class="endpoint-summary">Get Paginated List of Programs</span> <span class="endpoint-chevron">▶</span> </div> <div class="endpoint-body"> <p class="endpoint-desc">Returns paginated programs for the specified account or currently authenticated user. Supports filtering by sport, type, and more.</p> <h4>Parameters</h4> <table class="param-table"><thead><tr><th>Name</th><th>In</th><th>Type</th><th>Required</th><th>Description</th></tr></thead><tbody> <tr><td><span class="param-name">accountId</span></td><td><span class="param-in">path</span></td><td><span class="param-type">string</span></td><td>No</td><td>Optional account UUID</td></tr> <tr><td><span class="param-name">column</span></td><td><span class="param-in">query</span></td><td><span class="param-type">string</span></td><td>No</td><td>Sort column (default: createdAt)</td></tr> <tr><td><span class="param-name">direction</span></td><td><span class="param-in">query</span></td><td><span class="param-type">string</span></td><td>No</td><td>ASC or DESC (default: DESC)</td></tr> <tr><td><span class="param-name">limit</span></td><td><span class="param-in">query</span></td><td><span class="param-type">number</span></td><td>No</td><td>Max records to return</td></tr> <tr><td><span class="param-name">start</span></td><td><span class="param-in">query</span></td><td><span class="param-type">number</span></td><td>No</td><td>Starting offset</td></tr> <tr><td><span class="param-name">sportId</span></td><td><span class="param-in">query</span></td><td><span class="param-type">string</span></td><td>No</td><td>Filter by sport (default: basketball)</td></tr> <tr><td><span class="param-name">search</span></td><td><span class="param-in">query</span></td><td><span class="param-type">string</span></td><td>No</td><td>Search by program name or id</td></tr> <tr><td><span class="param-name">programType</span></td><td><span class="param-in">query</span></td><td><span class="param-type">string</span></td><td>No</td><td>generic, club, association, tournament, league, or tree</td></tr> <tr><td><span class="param-name">assigned</span></td><td><span class="param-in">query</span></td><td><span class="param-type">boolean</span></td><td>No</td><td>Only programs assigned to current user</td></tr> <tr><td><span class="param-name">havingGames</span></td><td><span class="param-in">query</span></td><td><span class="param-type">boolean</span></td><td>No</td><td>Only programs with scheduled games</td></tr> <tr><td><span class="param-name">isApiClient</span></td><td><span class="param-in">query</span></td><td><span class="param-type">boolean</span></td><td>No</td><td>Only programs flagged as API clients</td></tr> </tbody></table> <div class="response-codes"><span class="response-code success">200 Paginated program list</span></div> <div class="code-block"><div class="code-block-header"><span>curl</span><button class="copy-btn" onclick="copyCode(this)">Copy</button></div> <pre><code>curl -X GET "https://api.sportsvisio.com/programs/list/{accountId}?programType=league&limit=20" \ -H "Authorization: Bearer YOUR_TOKEN"</code></pre></div> </div></div> </div> <!-- Program Divisions --> <div class="tag-group" id="tag-program-divisions"> <div class="tag-group-header"><h3>Program Divisions</h3><span class="tag-count">1 endpoint</span></div> <div class="endpoint-card" data-search="post programs divisions teams bulk add division"> <div class="endpoint-header" onclick="toggleEndpoint(this)"> <span class="method-badge post">POST</span> <span class="endpoint-path">/programs/divisions/teams/{programId}/{eventId}/{divisionId}/bulk</span> <span class="endpoint-summary">Add Teams to Division</span> <span class="endpoint-chevron">▶</span> </div> <div class="endpoint-body"> <p class="endpoint-desc">Creates multiple division team assignment records in bulk.</p> <h4>Parameters</h4> <table class="param-table"><thead><tr><th>Name</th><th>In</th><th>Type</th><th>Required</th><th>Description</th></tr></thead><tbody> <tr><td><span class="param-name">programId</span></td><td><span class="param-in">path</span></td><td><span class="param-type">string</span></td><td>Yes<span class="param-required">*</span></td><td>UUID of Program</td></tr> <tr><td><span class="param-name">eventId</span></td><td><span class="param-in">path</span></td><td><span class="param-type">string</span></td><td>Yes<span class="param-required">*</span></td><td>UUID of Event</td></tr> <tr><td><span class="param-name">divisionId</span></td><td><span class="param-in">path</span></td><td><span class="param-type">string</span></td><td>Yes<span class="param-required">*</span></td><td>UUID of Division</td></tr> </tbody></table> <div class="response-codes"><span class="response-code success">200 Teams added</span><span class="response-code client-error">404 Division not found</span></div> <div class="code-block"><div class="code-block-header"><span>curl</span><button class="copy-btn" onclick="copyCode(this)">Copy</button></div> <pre><code>curl -X POST "https://api.sportsvisio.com/programs/divisions/teams/{programId}/{eventId}/{divisionId}/bulk" \ -H "Authorization: Bearer YOUR_TOKEN" \ -H "Content-Type: application/json" \ -d '{"teamIds": ["team-uuid-1", "team-uuid-2"]}'</code></pre></div> </div></div> </div> <!-- Teams --> <div class="tag-group" id="tag-teams"> <div class="tag-group-header"><h3>Teams</h3><span class="tag-count">1 endpoint</span></div> <div class="endpoint-card" data-search="post teams create new team programid"> <div class="endpoint-header" onclick="toggleEndpoint(this)"> <span class="method-badge post">POST</span> <span class="endpoint-path">/teams/{programId}/{eventId}/{divisionId}</span> <span class="endpoint-summary">Create Team</span> <span class="endpoint-chevron">▶</span> </div> <div class="endpoint-body"> <p class="endpoint-desc">Creates a new Team record within the specified program event division.</p> <h4>Parameters</h4> <table class="param-table"><thead><tr><th>Name</th><th>In</th><th>Type</th><th>Required</th><th>Description</th></tr></thead><tbody> <tr><td><span class="param-name">programId</span></td><td><span class="param-in">path</span></td><td><span class="param-type">string</span></td><td>Yes<span class="param-required">*</span></td><td>UUID of Program</td></tr> <tr><td><span class="param-name">eventId</span></td><td><span class="param-in">path</span></td><td><span class="param-type">string</span></td><td>Yes<span class="param-required">*</span></td><td>UUID of Event</td></tr> <tr><td><span class="param-name">divisionId</span></td><td><span class="param-in">path</span></td><td><span class="param-type">string</span></td><td>Yes<span class="param-required">*</span></td><td>UUID of Division</td></tr> </tbody></table> <div class="response-codes"><span class="response-code success">200 Team created</span></div> <div class="code-block"><div class="code-block-header"><span>curl</span><button class="copy-btn" onclick="copyCode(this)">Copy</button></div> <pre><code>curl -X POST "https://api.sportsvisio.com/teams/{programId}/{eventId}/{divisionId}" \ -H "Authorization: Bearer YOUR_TOKEN" \ -H "Content-Type: application/json" \ -d '{"name": "Bay Area Warriors", "abbreviation": "BAW"}'</code></pre></div> </div></div> </div> <!-- Team Players --> <div class="tag-group" id="tag-team-players"> <div class="tag-group-header"><h3>Team Players</h3><span class="tag-count">3 endpoints</span></div> <div class="endpoint-card" data-search="post teams players create teamid player"> <div class="endpoint-header" onclick="toggleEndpoint(this)"> <span class="method-badge post">POST</span> <span class="endpoint-path">/teams/players/{teamId}/{programId}/{eventId}/{divisionId}</span> <span class="endpoint-summary">Create TeamPlayer</span> <span class="endpoint-chevron">▶</span> </div> <div class="endpoint-body"> <p class="endpoint-desc">Creates a TeamPlayer record associated with a Team.</p> <h4>Parameters</h4> <table class="param-table"><thead><tr><th>Name</th><th>In</th><th>Type</th><th>Required</th><th>Description</th></tr></thead><tbody> <tr><td><span class="param-name">teamId</span></td><td><span class="param-in">path</span></td><td><span class="param-type">string</span></td><td>Yes<span class="param-required">*</span></td><td>UUID of Team</td></tr> <tr><td><span class="param-name">programId</span></td><td><span class="param-in">path</span></td><td><span class="param-type">string</span></td><td>Yes<span class="param-required">*</span></td><td>UUID of Program</td></tr> <tr><td><span class="param-name">eventId</span></td><td><span class="param-in">path</span></td><td><span class="param-type">string</span></td><td>Yes<span class="param-required">*</span></td><td>UUID of Event</td></tr> <tr><td><span class="param-name">divisionId</span></td><td><span class="param-in">path</span></td><td><span class="param-type">string</span></td><td>Yes<span class="param-required">*</span></td><td>UUID of Division</td></tr> </tbody></table> <div class="response-codes"><span class="response-code success">200 Player created</span></div> <div class="code-block"><div class="code-block-header"><span>curl</span><button class="copy-btn" onclick="copyCode(this)">Copy</button></div> <pre><code>curl -X POST "https://api.sportsvisio.com/teams/players/{teamId}/{programId}/{eventId}/{divisionId}" \ -H "Authorization: Bearer YOUR_TOKEN" \ -H "Content-Type: application/json" \ -d '{"firstName": "Marcus", "lastName": "Williams", "jerseyNumber": "23"}'</code></pre></div> </div></div> <div class="endpoint-card" data-search="get teams players division list roster teamid"> <div class="endpoint-header" onclick="toggleEndpoint(this)"> <span class="method-badge get">GET</span> <span class="endpoint-path">/teams/players/division/list/{teamId}/{programId}/{eventId}/{divisionId}</span> <span class="endpoint-summary">Get Team Players (Division Roster)</span> <span class="endpoint-chevron">▶</span> </div> <div class="endpoint-body"> <p class="endpoint-desc">Returns a paginated list of Team Players for the specified team and Program Event Division roster.</p> <h4>Parameters</h4> <table class="param-table"><thead><tr><th>Name</th><th>In</th><th>Type</th><th>Required</th><th>Description</th></tr></thead><tbody> <tr><td><span class="param-name">teamId</span></td><td><span class="param-in">path</span></td><td><span class="param-type">string</span></td><td>Yes<span class="param-required">*</span></td><td>Team UUID</td></tr> <tr><td><span class="param-name">programId</span></td><td><span class="param-in">path</span></td><td><span class="param-type">string</span></td><td>Yes<span class="param-required">*</span></td><td>UUID of Program</td></tr> <tr><td><span class="param-name">eventId</span></td><td><span class="param-in">path</span></td><td><span class="param-type">string</span></td><td>Yes<span class="param-required">*</span></td><td>UUID of Event</td></tr> <tr><td><span class="param-name">divisionId</span></td><td><span class="param-in">path</span></td><td><span class="param-type">string</span></td><td>Yes<span class="param-required">*</span></td><td>UUID of Division</td></tr> <tr><td><span class="param-name">column</span></td><td><span class="param-in">query</span></td><td><span class="param-type">string</span></td><td>No</td><td>Sort column</td></tr> <tr><td><span class="param-name">direction</span></td><td><span class="param-in">query</span></td><td><span class="param-type">string</span></td><td>No</td><td>ASC or DESC</td></tr> <tr><td><span class="param-name">limit</span></td><td><span class="param-in">query</span></td><td><span class="param-type">number</span></td><td>No</td><td>Max records</td></tr> <tr><td><span class="param-name">search</span></td><td><span class="param-in">query</span></td><td><span class="param-type">string</span></td><td>No</td><td>Filter by name</td></tr> <tr><td><span class="param-name">hideInactive</span></td><td><span class="param-in">query</span></td><td><span class="param-type">boolean</span></td><td>No</td><td>Skip inactive players</td></tr> </tbody></table> <div class="response-codes"><span class="response-code success">200 Paginated player list</span></div> <div class="code-block"><div class="code-block-header"><span>curl</span><button class="copy-btn" onclick="copyCode(this)">Copy</button></div> <pre><code>curl -X GET "https://api.sportsvisio.com/teams/players/division/list/{teamId}/{programId}/{eventId}/{divisionId}?limit=25" \ -H "Authorization: Bearer YOUR_TOKEN"</code></pre></div> </div></div> <div class="endpoint-card" data-search="post teams players division add roster assignment"> <div class="endpoint-header" onclick="toggleEndpoint(this)"> <span class="method-badge post">POST</span> <span class="endpoint-path">/teams/players/division/{teamId}/{programId}/{eventId}/{divisionId}</span> <span class="endpoint-summary">Add TeamPlayers to Division Roster</span> <span class="endpoint-chevron">▶</span> </div> <div class="endpoint-body"> <p class="endpoint-desc">Adds existing TeamPlayers to the specified Program Event Division roster.</p> <h4>Parameters</h4> <table class="param-table"><thead><tr><th>Name</th><th>In</th><th>Type</th><th>Required</th><th>Description</th></tr></thead><tbody> <tr><td><span class="param-name">teamId</span></td><td><span class="param-in">path</span></td><td><span class="param-type">string</span></td><td>Yes<span class="param-required">*</span></td><td>Team UUID</td></tr> <tr><td><span class="param-name">programId</span></td><td><span class="param-in">path</span></td><td><span class="param-type">string</span></td><td>Yes<span class="param-required">*</span></td><td>UUID of Program</td></tr> <tr><td><span class="param-name">eventId</span></td><td><span class="param-in">path</span></td><td><span class="param-type">string</span></td><td>Yes<span class="param-required">*</span></td><td>UUID of Event</td></tr> <tr><td><span class="param-name">divisionId</span></td><td><span class="param-in">path</span></td><td><span class="param-type">string</span></td><td>Yes<span class="param-required">*</span></td><td>UUID of Division</td></tr> </tbody></table> <div class="response-codes"><span class="response-code success">201 Players added to roster</span></div> <div class="code-block"><div class="code-block-header"><span>curl</span><button class="copy-btn" onclick="copyCode(this)">Copy</button></div> <pre><code>curl -X POST "https://api.sportsvisio.com/teams/players/division/{teamId}/{programId}/{eventId}/{divisionId}" \ -H "Authorization: Bearer YOUR_TOKEN" \ -H "Content-Type: application/json" \ -d '[{"teamPlayerId": "player-uuid-1"}, {"teamPlayerId": "player-uuid-2"}]'</code></pre></div> </div></div> </div> <!-- Scheduled Games --> <div class="tag-group" id="tag-scheduled-games"> <div class="tag-group-header"><h3>Scheduled Games</h3><span class="tag-count">3 endpoints</span></div> <div class="endpoint-card" data-search="get scheduled games scheduledgameid details score"> <div class="endpoint-header" onclick="toggleEndpoint(this)"> <span class="method-badge get">GET</span> <span class="endpoint-path">/scheduled-games/{scheduledGameId}</span> <span class="endpoint-summary">Get ScheduledGame</span> <span class="endpoint-chevron">▶</span> </div> <div class="endpoint-body"> <p class="endpoint-desc">Returns full ScheduledGame record including teams, rosters, device assignments, and game status.</p> <h4>Parameters</h4> <table class="param-table"><thead><tr><th>Name</th><th>In</th><th>Type</th><th>Required</th><th>Description</th></tr></thead><tbody> <tr><td><span class="param-name">scheduledGameId</span></td><td><span class="param-in">path</span></td><td><span class="param-type">string</span></td><td>Yes<span class="param-required">*</span></td><td>Scheduled Game UUID</td></tr> </tbody></table> <div class="response-codes"><span class="response-code success">200 Game details</span></div> <div class="code-block"><div class="code-block-header"><span>curl</span><button class="copy-btn" onclick="copyCode(this)">Copy</button></div> <pre><code>curl -X GET "https://api.sportsvisio.com/scheduled-games/{scheduledGameId}" \ -H "Authorization: Bearer YOUR_TOKEN"</code></pre></div> </div></div> <div class="endpoint-card" data-search="post scheduled games create schedule new game"> <div class="endpoint-header" onclick="toggleEndpoint(this)"> <span class="method-badge post">POST</span> <span class="endpoint-path">/scheduled-games/{programId}/{eventId}/{divisionId}</span> <span class="endpoint-summary">Create ScheduledGame</span> <span class="endpoint-chevron">▶</span> </div> <div class="endpoint-body"> <p class="endpoint-desc">Creates a ScheduledGame record within the specified program event division.</p> <h4>Parameters</h4> <table class="param-table"><thead><tr><th>Name</th><th>In</th><th>Type</th><th>Required</th><th>Description</th></tr></thead><tbody> <tr><td><span class="param-name">programId</span></td><td><span class="param-in">path</span></td><td><span class="param-type">string</span></td><td>Yes<span class="param-required">*</span></td><td>UUID of Program</td></tr> <tr><td><span class="param-name">eventId</span></td><td><span class="param-in">path</span></td><td><span class="param-type">string</span></td><td>Yes<span class="param-required">*</span></td><td>UUID of Event</td></tr> <tr><td><span class="param-name">divisionId</span></td><td><span class="param-in">path</span></td><td><span class="param-type">string</span></td><td>Yes<span class="param-required">*</span></td><td>UUID of Division</td></tr> </tbody></table> <div class="response-codes"><span class="response-code success">200 Game created</span></div> <div class="code-block"><div class="code-block-header"><span>curl</span><button class="copy-btn" onclick="copyCode(this)">Copy</button></div> <pre><code>curl -X POST "https://api.sportsvisio.com/scheduled-games/{programId}/{eventId}/{divisionId}" \ -H "Authorization: Bearer YOUR_TOKEN" \ -H "Content-Type: application/json" \ -d '{"name": "Warriors vs Celtics", "scheduledDate": "2026-03-15T19:00:00Z"}'</code></pre></div> </div></div> <div class="endpoint-card" data-search="get scheduled games insights ai analytics"> <div class="endpoint-header" onclick="toggleEndpoint(this)"> <span class="method-badge get">GET</span> <span class="endpoint-path">/scheduled-games/insights/{scheduledGameId}</span> <span class="endpoint-summary">Get ScheduledGame Insights</span> <span class="endpoint-chevron">▶</span> </div> <div class="endpoint-body"> <p class="endpoint-desc">Returns AI-generated insights for the game including analytics, trends, and performance summaries from SportsVisio's computer vision pipeline.</p> <h4>Parameters</h4> <table class="param-table"><thead><tr><th>Name</th><th>In</th><th>Type</th><th>Required</th><th>Description</th></tr></thead><tbody> <tr><td><span class="param-name">scheduledGameId</span></td><td><span class="param-in">path</span></td><td><span class="param-type">string</span></td><td>Yes<span class="param-required">*</span></td><td>Scheduled Game UUID</td></tr> </tbody></table> <div class="response-codes"><span class="response-code success">200 Game insights</span></div> <div class="code-block"><div class="code-block-header"><span>curl</span><button class="copy-btn" onclick="copyCode(this)">Copy</button></div> <pre><code>curl -X GET "https://api.sportsvisio.com/scheduled-games/insights/{scheduledGameId}" \ -H "Authorization: Bearer YOUR_TOKEN"</code></pre></div> </div></div> </div> <!-- Scheduled Game Team Assignment --> <div class="tag-group" id="tag-game-team-assignment"> <div class="tag-group-header"><h3>Scheduled Game Team Assignment</h3><span class="tag-count">1 endpoint</span></div> <div class="endpoint-card" data-search="post scheduled games assigned roster player assignment"> <div class="endpoint-header" onclick="toggleEndpoint(this)"> <span class="method-badge post">POST</span> <span class="endpoint-path">/scheduled-games/assigned/{scheduledGameTeamAssnId}/roster</span> <span class="endpoint-summary">Assign TeamPlayer to Game Roster</span> <span class="endpoint-chevron">▶</span> </div> <div class="endpoint-body"> <p class="endpoint-desc">Assigns TeamPlayers to a specific game roster via the scheduled game team assignment.</p> <h4>Parameters</h4> <table class="param-table"><thead><tr><th>Name</th><th>In</th><th>Type</th><th>Required</th><th>Description</th></tr></thead><tbody> <tr><td><span class="param-name">scheduledGameTeamAssnId</span></td><td><span class="param-in">path</span></td><td><span class="param-type">string</span></td><td>Yes<span class="param-required">*</span></td><td>Game Team Assignment UUID</td></tr> </tbody></table> <div class="response-codes"><span class="response-code success">200 Roster assigned</span></div> <div class="code-block"><div class="code-block-header"><span>curl</span><button class="copy-btn" onclick="copyCode(this)">Copy</button></div> <pre><code>curl -X POST "https://api.sportsvisio.com/scheduled-games/assigned/{scheduledGameTeamAssnId}/roster" \ -H "Authorization: Bearer YOUR_TOKEN" \ -H "Content-Type: application/json" \ -d '[{"teamPlayerId": "player-uuid", "jerseyNumber": "23"}]'</code></pre></div> </div></div> </div> <!-- Annotation Statistics --> <div class="tag-group" id="tag-annotation-statistics"> <div class="tag-group-header"><h3>Annotation Statistics</h3><span class="tag-count">1 endpoint</span></div> <div class="endpoint-card" data-search="get annotations stats game player rollup statistics leaderboard"> <div class="endpoint-header" onclick="toggleEndpoint(this)"> <span class="method-badge get">GET</span> <span class="endpoint-path">/annotations/stats/game-player-rollup/{scheduledGameId}</span> <span class="endpoint-summary">Rollup Stats for Game Players</span> <span class="endpoint-chevron">▶</span> </div> <div class="endpoint-body"> <p class="endpoint-desc">Returns aggregated rollup statistics for each player in the specified game. Includes points, rebounds, assists, steals, blocks, turnovers, shooting percentages, and minutes played -- generated by SportsVisio's AI annotation engine.</p> <h4>Parameters</h4> <table class="param-table"><thead><tr><th>Name</th><th>In</th><th>Type</th><th>Required</th><th>Description</th></tr></thead><tbody> <tr><td><span class="param-name">scheduledGameId</span></td><td><span class="param-in">path</span></td><td><span class="param-type">string</span></td><td>Yes<span class="param-required">*</span></td><td>Scheduled Game UUID</td></tr> </tbody></table> <div class="response-codes"><span class="response-code success">200 Array of player stat summaries</span></div> <div class="code-block"><div class="code-block-header"><span>curl</span><button class="copy-btn" onclick="copyCode(this)">Copy</button></div> <pre><code>curl -X GET "https://api.sportsvisio.com/annotations/stats/game-player-rollup/{scheduledGameId}" \ -H "Authorization: Bearer YOUR_TOKEN"</code></pre></div> </div></div> </div> <!-- Devices --> <div class="tag-group" id="tag-devices"> <div class="tag-group-header"><h3>Devices</h3><span class="tag-count">5 endpoints</span></div> <div class="endpoint-card" data-search="get devices list accountid camera recording"> <div class="endpoint-header" onclick="toggleEndpoint(this)"> <span class="method-badge get">GET</span> <span class="endpoint-path">/devices/list/{accountId}</span> <span class="endpoint-summary">Get a List of Devices</span> <span class="endpoint-chevron">▶</span> </div> <div class="endpoint-body"> <p class="endpoint-desc">Returns a paginated list of Device records. Supports search by device name, model, macAddress, or manufacturer.</p> <h4>Parameters</h4> <table class="param-table"><thead><tr><th>Name</th><th>In</th><th>Type</th><th>Required</th><th>Description</th></tr></thead><tbody> <tr><td><span class="param-name">accountId</span></td><td><span class="param-in">path</span></td><td><span class="param-type">string</span></td><td>No</td><td>Optional account ID</td></tr> <tr><td><span class="param-name">column</span></td><td><span class="param-in">query</span></td><td><span class="param-type">string</span></td><td>No</td><td>Sort column</td></tr> <tr><td><span class="param-name">direction</span></td><td><span class="param-in">query</span></td><td><span class="param-type">string</span></td><td>No</td><td>ASC or DESC</td></tr> <tr><td><span class="param-name">limit</span></td><td><span class="param-in">query</span></td><td><span class="param-type">number</span></td><td>No</td><td>Max records</td></tr> <tr><td><span class="param-name">start</span></td><td><span class="param-in">query</span></td><td><span class="param-type">number</span></td><td>No</td><td>Starting offset</td></tr> <tr><td><span class="param-name">search</span></td><td><span class="param-in">query</span></td><td><span class="param-type">string</span></td><td>No</td><td>Filter by name, model, macAddress, manufacturer</td></tr> </tbody></table> <div class="response-codes"><span class="response-code success">200 Paginated device list</span></div> <div class="code-block"><div class="code-block-header"><span>curl</span><button class="copy-btn" onclick="copyCode(this)">Copy</button></div> <pre><code>curl -X GET "https://api.sportsvisio.com/devices/list/{accountId}?limit=10" \ -H "Authorization: Bearer YOUR_TOKEN"</code></pre></div> </div></div> <div class="endpoint-card" data-search="post devices register new camera accountid"> <div class="endpoint-header" onclick="toggleEndpoint(this)"> <span class="method-badge post">POST</span> <span class="endpoint-path">/devices/register/{accountId}</span> <span class="endpoint-summary">Register a New Device</span> <span class="endpoint-chevron">▶</span> </div> <div class="endpoint-body"> <p class="endpoint-desc">Creates a Device record and registers it to the specified account.</p> <h4>Parameters</h4> <table class="param-table"><thead><tr><th>Name</th><th>In</th><th>Type</th><th>Required</th><th>Description</th></tr></thead><tbody> <tr><td><span class="param-name">accountId</span></td><td><span class="param-in">path</span></td><td><span class="param-type">string</span></td><td>No</td><td>Optional account ID</td></tr> </tbody></table> <div class="response-codes"><span class="response-code success">200 Device registered</span></div> <div class="code-block"><div class="code-block-header"><span>curl</span><button class="copy-btn" onclick="copyCode(this)">Copy</button></div> <pre><code>curl -X POST "https://api.sportsvisio.com/devices/register/{accountId}" \ -H "Authorization: Bearer YOUR_TOKEN" \ -H "Content-Type: application/json" \ -d '{"name": "Court 1 Camera", "model": "SportsVisio Lens"}'</code></pre></div> </div></div> <div class="endpoint-card" data-search="post devices attach game recording scheduledgameid"> <div class="endpoint-header" onclick="toggleEndpoint(this)"> <span class="method-badge post">POST</span> <span class="endpoint-path">/devices/attach/{scheduledGameId}</span> <span class="endpoint-summary">Attach Device to Game</span> <span class="endpoint-chevron">▶</span> </div> <div class="endpoint-body"> <p class="endpoint-desc">Attaches a registered device to a scheduled game for recording.</p> <h4>Parameters</h4> <table class="param-table"><thead><tr><th>Name</th><th>In</th><th>Type</th><th>Required</th><th>Description</th></tr></thead><tbody> <tr><td><span class="param-name">scheduledGameId</span></td><td><span class="param-in">path</span></td><td><span class="param-type">string</span></td><td>Yes<span class="param-required">*</span></td><td>UUID of scheduled game</td></tr> </tbody></table> <div class="response-codes"><span class="response-code success">200 Device attached</span><span class="response-code client-error">404 Not found</span></div> <div class="code-block"><div class="code-block-header"><span>curl</span><button class="copy-btn" onclick="copyCode(this)">Copy</button></div> <pre><code>curl -X POST "https://api.sportsvisio.com/devices/attach/{scheduledGameId}" \ -H "Authorization: Bearer YOUR_TOKEN" \ -H "Content-Type: application/json" \ -d '{"deviceId": "device-uuid"}'</code></pre></div> </div></div> <div class="endpoint-card" data-search="get devices upload token media scheduledgameid deviceid"> <div class="endpoint-header" onclick="toggleEndpoint(this)"> <span class="method-badge get">GET</span> <span class="endpoint-path">/devices/upload-token/{scheduledGameId}/{deviceId}</span> <span class="endpoint-summary">Get Upload Token</span> <span class="endpoint-chevron">▶</span> </div> <div class="endpoint-body"> <p class="endpoint-desc">Returns an upload token to upload source media for AI processing.</p> <h4>Parameters</h4> <table class="param-table"><thead><tr><th>Name</th><th>In</th><th>Type</th><th>Required</th><th>Description</th></tr></thead><tbody> <tr><td><span class="param-name">scheduledGameId</span></td><td><span class="param-in">path</span></td><td><span class="param-type">string</span></td><td>Yes<span class="param-required">*</span></td><td>Scheduled Game UUID</td></tr> <tr><td><span class="param-name">deviceId</span></td><td><span class="param-in">path</span></td><td><span class="param-type">string</span></td><td>Yes<span class="param-required">*</span></td><td>Device UUID</td></tr> </tbody></table> <div class="response-codes"><span class="response-code success">200 Upload token</span></div> <div class="code-block"><div class="code-block-header"><span>curl</span><button class="copy-btn" onclick="copyCode(this)">Copy</button></div> <pre><code>curl -X GET "https://api.sportsvisio.com/devices/upload-token/{scheduledGameId}/{deviceId}" \ -H "Authorization: Bearer YOUR_TOKEN"</code></pre></div> </div></div> <div class="endpoint-card" data-search="post devices init upload multipart s3 large video"> <div class="endpoint-header" onclick="toggleEndpoint(this)"> <span class="method-badge post">POST</span> <span class="endpoint-path">/devices/init-upload-multipart/{scheduledGameId}/{deviceId}</span> <span class="endpoint-summary">Initiate Multipart Upload</span> <span class="endpoint-chevron">▶</span> </div> <div class="endpoint-body"> <p class="endpoint-desc">Creates a multipart upload session for direct S3 upload of source media. Use for large video files.</p> <h4>Parameters</h4> <table class="param-table"><thead><tr><th>Name</th><th>In</th><th>Type</th><th>Required</th><th>Description</th></tr></thead><tbody> <tr><td><span class="param-name">scheduledGameId</span></td><td><span class="param-in">path</span></td><td><span class="param-type">string</span></td><td>Yes<span class="param-required">*</span></td><td>Scheduled Game UUID</td></tr> <tr><td><span class="param-name">deviceId</span></td><td><span class="param-in">path</span></td><td><span class="param-type">string</span></td><td>Yes<span class="param-required">*</span></td><td>Device UUID</td></tr> </tbody></table> <div class="response-codes"><span class="response-code success">201 Multipart session created</span></div> <div class="code-block"><div class="code-block-header"><span>curl</span><button class="copy-btn" onclick="copyCode(this)">Copy</button></div> <pre><code>curl -X POST "https://api.sportsvisio.com/devices/init-upload-multipart/{scheduledGameId}/{deviceId}" \ -H "Authorization: Bearer YOUR_TOKEN" \ -H "Content-Type: application/json" \ -d '{"filename": "game-2026-03-15.mp4", "contentType": "video/mp4"}'</code></pre></div> </div></div> </div> <!-- Uploads --> <div class="tag-group" id="tag-uploads"> <div class="tag-group-header"><h3>Uploads</h3><span class="tag-count">1 endpoint</span></div> <div class="endpoint-card" data-search="post upload image cdn filestack"> <div class="endpoint-header" onclick="toggleEndpoint(this)"> <span class="method-badge post">POST</span> <span class="endpoint-path">/upload</span> <span class="endpoint-summary">Upload Image to CDN</span> <span class="endpoint-chevron">▶</span> </div> <div class="endpoint-body"> <p class="endpoint-desc">Uploads an image to FileStack CDN and returns a storable URL for team logos, player images, etc.</p> <div class="response-codes"><span class="response-code success">201 Image uploaded</span></div> <div class="code-block"><div class="code-block-header"><span>curl</span><button class="copy-btn" onclick="copyCode(this)">Copy</button></div> <pre><code>curl -X POST "https://api.sportsvisio.com/upload" \ -H "Authorization: Bearer YOUR_TOKEN" \ -H "Content-Type: application/json" \ -d '{"imageData": "base64-encoded-data", "fileName": "team-logo.png"}'</code></pre></div> </div></div> </div> <!-- Multipart Uploads --> <div class="tag-group" id="tag-multipart-uploads"> <div class="tag-group-header"><h3>Multipart Uploads</h3><span class="tag-count">1 endpoint</span></div> <div class="endpoint-card" data-search="post upload multipart complete finalize sha256"> <div class="endpoint-header" onclick="toggleEndpoint(this)"> <span class="method-badge post">POST</span> <span class="endpoint-path">/upload/multipart/{uploadId}/complete</span> <span class="endpoint-summary">Complete Multipart Upload</span> <span class="endpoint-chevron">▶</span> </div> <div class="endpoint-body"> <p class="endpoint-desc">Completes the multipart upload and returns the final file URL. Optionally validates SHA256 checksum.</p> <h4>Parameters</h4> <table class="param-table"><thead><tr><th>Name</th><th>In</th><th>Type</th><th>Required</th><th>Description</th></tr></thead><tbody> <tr><td><span class="param-name">uploadId</span></td><td><span class="param-in">path</span></td><td><span class="param-type">string</span></td><td>Yes<span class="param-required">*</span></td><td>Multipart upload ID</td></tr> </tbody></table> <div class="response-codes"><span class="response-code success">200 Upload completed</span></div> <div class="code-block"><div class="code-block-header"><span>curl</span><button class="copy-btn" onclick="copyCode(this)">Copy</button></div> <pre><code>curl -X POST "https://api.sportsvisio.com/upload/multipart/{uploadId}/complete" \ -H "Authorization: Bearer YOUR_TOKEN" \ -H "Content-Type: application/json" \ -d '{"sha256": "optional-checksum"}'</code></pre></div> </div></div> </div> </section> <!-- Changelog --> <section class="section" id="changelog"> <h2>Changelog</h2> <p>Track changes and updates to the SportsVisio Public API.</p> <div class="changelog-entry"> <div><span class="changelog-date">February 6, 2026</span><span class="changelog-version">v1.0.0</span></div> <ul class="changelog-items"> <li><span class="changelog-tag added">Added</span> Initial public API release with 18 endpoints</li> <li><span class="changelog-tag added">Added</span> League Integration Guide with step-by-step walkthrough</li> <li><span class="changelog-tag added">Added</span> Game player rollup stats endpoint for leaderboard support</li> <li><span class="changelog-tag added">Added</span> Game Insights endpoint for AI-generated analytics</li> <li><span class="changelog-tag added">Added</span> Multipart upload support for large video files</li> <li><span class="changelog-tag added">Added</span> Device management endpoints (register, attach, upload tokens)</li> </ul> </div> <div class="changelog-entry"> <div><span class="changelog-date">January 2026</span><span class="changelog-version">v0.9.0-beta</span></div> <ul class="changelog-items"> <li><span class="changelog-tag added">Added</span> Beta release for partner testing (PlayHQ, BYLD Sports)</li> <li><span class="changelog-tag added">Added</span> JWT bearer token authentication</li> <li><span class="changelog-tag added">Added</span> Core endpoints: Users, Programs, Teams, Scheduled Games</li> </ul> </div> </section> <footer class="footer"> <p>SportsVisio Public API v1.0 — <a href="mailto:api@sportsvisio.com">api@sportsvisio.com</a></p> <p style="margin-top:8px">Copyright 2026 Sports Visio Inc. All rights reserved.</p> </footer> </div> </div> </div> <button class="back-to-top" id="backToTop" onclick="window.scrollTo({top:0,behavior:'smooth'})" aria-label="Back to top">↑</button> <script> function toggleTheme(){var h=document.documentElement,c=h.getAttribute('data-theme'),n=c==='dark'?'light':'dark';h.setAttribute('data-theme',n);localStorage.setItem('sv-api-theme',n);document.getElementById('themeBtn').innerHTML=n==='dark'?'☼':'☾'} (function(){var s=localStorage.getItem('sv-api-theme');if(s){document.documentElement.setAttribute('data-theme',s);if(s==='dark')document.getElementById('themeBtn').innerHTML='☼'}})(); function toggleEndpoint(h){h.parentElement.classList.toggle('open')} function copyCode(b){var p=b.closest('.code-block').querySelector('pre');navigator.clipboard.writeText(p.textContent).then(function(){b.textContent='Copied!';setTimeout(function(){b.textContent='Copy'},2000)}).catch(function(){var r=document.createRange();r.selectNodeContents(p);var s=window.getSelection();s.removeAllRanges();s.addRange(r);document.execCommand('copy');s.removeAllRanges();b.textContent='Copied!';setTimeout(function(){b.textContent='Copy'},2000)})} function filterEndpoints(q){var lq=q.toLowerCase().trim(),cards=document.querySelectorAll('.endpoint-card'),groups=document.querySelectorAll('.tag-group'),nr=document.getElementById('no-results'),vc=0;cards.forEach(function(c){var sd=c.getAttribute('data-search')||'',pt=c.querySelector('.endpoint-path').textContent.toLowerCase(),sm=c.querySelector('.endpoint-summary').textContent.toLowerCase(),m=!lq||sd.includes(lq)||pt.includes(lq)||sm.includes(lq);c.classList.toggle('hidden',!m);if(m)vc++});groups.forEach(function(g){g.style.display=g.querySelectorAll('.endpoint-card:not(.hidden)').length>0?'':'none'});nr.classList.toggle('visible',vc===0&&lq.length>0)} (function(){var secs=document.querySelectorAll('.section,.tag-group,.hero'),links=document.querySelectorAll('.sidebar-link'),obs=new IntersectionObserver(function(entries){entries.forEach(function(e){if(e.isIntersecting){var id=e.target.id;links.forEach(function(l){l.classList.toggle('active',l.getAttribute('href')==='#'+id)})}})},{rootMargin:'-80px 0px -60% 0px',threshold:0});secs.forEach(function(s){if(s.id)obs.observe(s)})})(); function toggleSidebar(){document.getElementById('sidebar').classList.toggle('open')} function closeMobile(){if(window.innerWidth<=900)document.getElementById('sidebar').classList.remove('open')} document.addEventListener('click',function(e){var sb=document.getElementById('sidebar'),hb=document.querySelector('.hamburger');if(window.innerWidth<=900&&sb.classList.contains('open')&&!sb.contains(e.target)&&!hb.contains(e.target))sb.classList.remove('open')}); window.addEventListener('scroll',function(){document.getElementById('backToTop').classList.toggle('visible',window.scrollY>400)}); document.querySelectorAll('.quick-link').forEach(function(l){l.addEventListener('click',function(e){e.preventDefault();var t=document.querySelector(this.getAttribute('href'));if(t)t.scrollIntoView({behavior:'smooth'})})}); </script> </body> </html>