For developers & AI agents
Run your league with your AI agent
Everything the in-app AI assistant can do is available to your agents: create leagues and seasons, add teams and rosters, generate round-robin schedules, record scores, and read standings — over MCP, a REST API, or the CLI.
1. Get an API key
In the dashboard, open Settings → API & Agents and create a key. Keys are scoped to your rink (organization) and come in two roles: admin (full league operations) and scorekeeper (read + record scores). Send the key as a bearer token:
Authorization: Bearer rk_...
Reads work on any plan; write operations require an active subscription — the same rules as the dashboard.
2. Connect over MCP (recommended)
The remote MCP server at https://hockeylineapp.com/api/mcp (streamable HTTP) exposes the tools below. Claude Code:
claude mcp add --transport http hockey-line https://hockeylineapp.com/api/mcp \ --header "Authorization: Bearer rk_..."
Claude Desktop, Cursor, or any MCP client (JSON config):
{
"mcpServers": {
"hockey-line": {
"url": "https://hockeylineapp.com/api/mcp",
"headers": { "Authorization": "Bearer rk_..." }
}
}
}Then just talk to your agent: “Set up a Winter 2027 season for the Sunday beer league with the same teams as last season and generate a weekly schedule starting January 10 at 8pm and 9:15pm.”
3. Or use the REST API
The same tools are exposed as RPC endpoints. Discover them at /api/v1/tools (JSON Schemas included), then invoke:
curl -X POST https://hockeylineapp.com/api/v1/tools/get_org_overview \
-H "Authorization: Bearer rk_..." \
-H "Content-Type: application/json" \
-d '{}'
curl -X POST https://hockeylineapp.com/api/v1/tools/record_score \
-H "Authorization: Bearer rk_..." \
-H "Content-Type: application/json" \
-d '{"gameId": "...", "homeScore": 4, "awayScore": 2, "isOvertime": true}'An OpenAPI 3.1 spec is generated from the same catalog.
4. Or the CLI
A tiny agent-friendly CLI (JSON in, JSON out) wraps the REST API — handy for scripts and terminal-based agents:
export HOCKEY_LINE_API_KEY=rk_...
npx hockey-line-cli me
npx hockey-line-cli tools
npx hockey-line-cli call get_org_overview
npx hockey-line-cli call add_teams '{"seasonId":"...","teamNames":["Ice Holes","Puck Hogs"]}'Available tools
Identical across MCP, REST, and CLI. Write tools need an active subscription; scorekeeper-role keys can only call reads and record_score.
| Tool | Type | Description |
|---|---|---|
| get_org_overview | read | List the org's existing leagues, seasons, and teams so you can reference real IDs. Call this before creating things that depend on existing entities. |
| create_league | write | Create a new league within the organization. |
| create_season | write | Create a season within a league. Teams join with the league's evergreen join code, which always points at the current season. Set carryOverTeams to bring all of the league's returning teams (with divisions, app links and rosters) into the new season. |
| add_teams | write | Add one or more teams to a season. |
| update_team | write | Rename a team or change its division or color (hex, e.g. "#1d4ed8"). Name and color changes carry to the team's persistent identity across seasons. |
| add_players | write | Add players to a team's roster. |
| set_season_status | write | Change a season's status: "setup" (pre-launch), "active" (in play, visible publicly), or "completed" (season over). |
| generate_round_robin | write | Generate a round-robin schedule for a season. Games are placed on game nights (every intervalDays) in the rink's local timezone, filling the night's time slots (gameTimes) without any team playing twice in one night. Teams only play opponents in their own division. Set replaceExisting to regenerate (deletes the season's scheduled-but-unplayed games first). |
| get_league | read | League detail: name, sport, public slug, evergreen join code (teams use it to self-join the active season), and its seasons with status and join codes. |
| get_standings | read | Current standings for a season (per division): W/L/T/OTL, goals for/against, points, streak. Computed from finalized games using the season's configured point values. |
| get_schedule | read | A season's schedule and results: every game with date (UTC ISO — the rink's local timezone is in get_org_overview), teams, location, status, and score. |
| get_game | read | Full detail for one game: score, goals with scorers/assists, penalties, period shots, goalie stats. |
| get_roster | read | A team's roster: players with jersey numbers, positions, type, and eligibility. |
| get_player_stats | read | Season stat leaders: skaters (GP, G, A, P, PIM) and goalies (GP, W/L, GA, GAA, SV%, SO), each sorted by the usual leaderboard order. |
| get_playoffs | read | The season's playoff bracket: rounds, series, seeds, per-series game results, and the champion once decided. |
| get_suspensions | read | The season's suspensions (player, reason, games total/served, active flag) and its automatic penalty→suspension rules. |
| update_league | write | Rename a league (the public URL slug follows the name) or change its sport. |
| delete_league | write | Permanently delete a league and everything in it — all seasons, teams, players, games, and stats. Irreversible; confirm with your user first. |
| update_season | write | Update a season's name, start/end dates, or standings point values (win/loss/tie/OTL). Use set_season_status to change its status. |
| delete_season | write | Permanently delete a season with its teams, games, and stats. The league and its other seasons remain. Irreversible; confirm with your user first. |
| delete_team | write | Remove a team from its season. The team's games (and their box scores) are deleted with it. Irreversible; confirm with your user first. |
| merge_teams | write | Merge a duplicate team into another team in the same season. Roster, app link, and game references move to the target; the source entry is removed. Use when a team self-joined from the app and duplicated an existing entry. |
| update_player | write | Update a rostered player's jersey number, position, name, or eligibility. |
| remove_player | write | Remove a player from a team's roster. Their goals come off the board (scores adjust); assists on others' goals are kept without attribution. To keep stats, use merge_players instead. |
| merge_players | write | Merge a duplicate roster player into another on the same team. All box-score history (goals, assists, penalties, stats, suspensions) is re-pointed at the target, then the duplicate is deleted. Unlike remove_player, no scoring history is lost. |
| schedule_game | write | Schedule a single game between two teams in a season. Date/time is ISO 8601 (UTC or with offset). |
| update_game | write | Reschedule a game, change its location, or mark it postponed/cancelled. |
| delete_game | write | Delete a game and its box score entirely. To keep it on the schedule, mark it postponed/cancelled with update_game instead. |
| record_score | write | Record a game's final score and mark it final — the quick path when you only track scores, not individual goals. Set isOvertime/isShootout when the game went past regulation (drives W vs OTL in standings). For goal-by-goal box scores use record_goal + finalize_game instead. Updates standings, playoff series, and suspension served-counts. |
| start_game | write | Start live scoring: mark a scheduled game in progress (period 1, score 0-0 unless already set). |
| set_game_period | write | Advance (or correct) the current period of a live game. |
| record_goal | write | Record a goal in a game's box score (scorer, up to two assists, period, time, type). The team's score increments automatically and player stats update. Suspended/ineligible players are rejected. |
| remove_goal | write | Undo a recorded goal (find its id in get_game). The team's score decrements and player stats update. |
| record_penalty | write | Record a penalty in a game's box score. If the season's suspension rules map this penalty type to automatic games, a suspension is created automatically. |
| remove_penalty | write | Undo a recorded penalty (find its id in get_game). Any suspension it auto-created is removed too. |
| set_period_shots | write | Set both teams' shots on goal for one period (upserts, so re-calling corrects the count). |
| set_game_roster | write | Set which players dressed for a team in a game (drives games-played counts and suspension serving). Replaces the team's previous game roster. |
| set_game_goalie | write | Set a team's starting goalie for a game (drives goalie W/L, GA, SV%, and shutout stats on finalize). |
| finalize_game | write | Finalize a live-scored game: the score comes from its recorded goals, player and goalie stats are synced, standings/playoffs/suspensions update. Set isOvertime/isShootout when it went past regulation. For score-only entry use record_score instead. |
| reopen_game | write | Reopen a finalized game for corrections (reverses suspension served-counts and clears goalie decisions). Finalize again when done. |
| create_playoffs | write | Create a single-elimination playoff bracket (4 or 8 teams) seeded from the season's current standings. Games played between bracket teams then advance the series automatically. |
| set_playoff_winner | write | Manually set the winner of a playoff series (find seriesId in get_playoffs) — e.g. after a forfeit. Advances them to the next round. |
| delete_playoffs | write | Delete the season's playoff bracket (regular-season games and standings are untouched). |
| create_suspension | write | Manually suspend a player for a number of games. They can't be added to goals, penalties, or game rosters until it's served or lifted; it counts down as their team finalizes games they'd have played. |
| update_suspension | write | Edit a suspension's length, served count, or reason — or lift it immediately with lift: true (find suspensionId in get_suspensions). |
| delete_suspension | write | Delete a suspension record entirely. To end one but keep it on record, use update_suspension with lift: true. |
| set_suspension_rules | write | Set the season's automatic penalty→suspension rules: for each penalty type, how many games recording it triggers (0 = none). Replaces the full rule set. |
Notes for agents
- Never invent IDs — call
get_org_overviewfirst. - Typical setup flow: create_league → create_season → add_teams → add_players → generate_round_robin.
- Dates are ISO 8601; schedule times are interpreted in the rink's local timezone.
- Mutations return
{ ok: true, ... }or{ ok: false, error }with a human-readable reason. - Public, no-auth league data (standings, schedules, rosters) is also on each rink's public page at
/r/{slug}.