The v1 compatibility promise
The v1 contract is additive-only. Concretely, these never change within v1:- Existing response field names and types
- Status string values (
open/claimed/completed/cancelled, payment statuses, membership statuses) - Webhook event names, the delivery envelope (
{id, event, createdAt, data}), headers, and the HMAC-SHA256 signing scheme - The
source+externalIdidempotency semantics - The
{data}/{error}response envelopes
- New endpoints and new MCP tools
- New optional fields on existing responses and request bodies
- New webhook event names (subscribe by explicit event list if you can’t tolerate unknown events; an empty
eventssubscription receives new events automatically) - New error codes and new enum values (write your handlers to tolerate unrecognized codes/values)
/api/v2 — v1 is never mutated in place.
Deprecation process
If a v1 behavior is ever deprecated, it keeps working for the life of v1; its replacement lands additively (or in v2) and the deprecation is announced on this page and in the affected reference pages. There are no silent removals.How to detect change
- This page is the canonical changelog for the developer surface.
GET /api/v1(the index) enumerates current endpoints and webhook events at runtime — an agent can diff it against expectations cheaply.- The OpenAPI spec is versioned with the docs and updated with every surface change; pin and diff it in CI if you want machine-checkable notice.
- These docs’
llms.txtindexes every developer page for AI-agent consumption.
Changelog
2026-07 — Scoped partner keys (tenant isolation)
- Partner API keys are now source-bound principals: each key reads and mutates only leagues in its
sourcenamespace plus explicit grants. Out-of-scope resources answer404identically to nonexistent ones (non-enumeration). Additive for correctly-behaved integrations; contact support if a previously visible league disappears from your listings. - Write
sourceis derived from the key — omit it or echo your own value; other values return the new400 source_mismatch. - New
409 external_id_conflicton game imports: re-using a gameexternalIdunder a different league is refused instead of updating the existing game. - Webhook endpoints are owned by the registering key’s
source— list/delete/deliveries are scoped, and event fan-out delivers only events for leagues in your scope. - The MCP server now forwards your bearer token to the REST layer, so tool calls run with your key’s scope and attribution.
2026-07 — Developer documentation launch
- Published this developer section: authentication, REST + MCP quickstarts, task recipes, resource model, webhooks, error/agent-safety guidance.
- Published the real Whistle OpenAPI 3.1 specification at
/docs/api-reference/openapi.json, replacing a placeholder spec that had been served at that URL. - Documented current surface: 21 REST operations (the index plus 20 resource operations), remote HTTP MCP server with 20 tools, 12 webhook events.
The API itself predates this changelog; entries begin at documentation launch. Current limitations are tracked in the integration status note.

