Skip to main content
Two copy/paste calls to verify your key and see real data. Both are read-only.

1. Set your key

export WHISTLE_API_KEY="whk_your_key_here"   # from tommy@huddleup-sports.com

2. Call the authenticated index

GET /api/v1 is the recommended first call — it verifies your key and describes the whole surface:
curl -s https://whistle.huddleup-sports.com/api/v1 \
  -H "Authorization: Bearer $WHISTLE_API_KEY"
Expected response (200, abridged):
{
  "data": {
    "version": "v1",
    "auth": "Authorization: Bearer <WHISTLE_API_KEY>",
    "endpoints": ["GET /api/v1/leagues", "POST /api/v1/leagues", "…"],
    "mcp": "/api/mcp (HTTP MCP transport — same tools, bearer-authed)",
    "webhookEvents": ["game.created", "game.updated", "…"],
    "notes": { "idempotency": "…", "money": "…", "signatures": "…" }
  }
}
Without a valid key you get exactly a 401 with this body:
{"error": "unauthorized"}

3. Make a read-only request

curl -s https://whistle.huddleup-sports.com/api/v1/leagues \
  -H "Authorization: Bearer $WHISTLE_API_KEY"
This lists the leagues in your key’s scope — leagues in your source namespace plus any granted to your key (see Authentication). A brand-new key sees an empty array until you create your first league. Expected response (200):
{
  "data": [
    {
      "id": "cmc1a2b3c4d5e6f7g8h9i0j1",
      "name": "Springfield Little League",
      "paymentMode": "offline",
      "currency": "usd",
      "source": "huddleup",
      "externalId": "org_123",
      "createdAt": "2026-06-15T14:03:22.118Z",
      "gameCount": 42,
      "memberCount": 9
    }
  ]
}

The response envelope

Every response uses one of two shapes:
  • Success: {"data": …} — status 200 (reads, updates, deletes) or 201 (creates, including idempotent upserts that updated an existing row).
  • Error: {"error": "<code>"} — a single snake_case code, statuses 400, 401, 404, or 409 only. See Errors & agent safety.

Next steps

Last modified on July 10, 2026