API overview¶
Product boundary¶
The API is a primary product. It must be designed and implemented by the team as HTTP endpoints. Generated database endpoints must not be used as the application API. Supabase may provide managed authentication, but application data must pass through the handwritten backend.
Initial conventions¶
- Base path:
/api/v1 - Format: JSON unless returning a documented dataset file
- Stable identifiers: opaque, immutable, non-recycled string identifiers
- Pagination: cursor pagination for Basic collection endpoints
- Filtering: explicit documented camelCase query parameters
- Sorting: endpoint-specific whitelisted fields with deterministic tie-breaking
- Errors: consistent machine-readable code, safe message, and optional field or event details
- Authentication: established provider/library for users; separate API-consumer credentials when introduced
- Versioning: URI major version only;
v1is supported at/api/v1, confirmed by theAPI-Version: v1response header, and unsupported major versions return404 UNSUPPORTED_API_VERSION
The version-controlled API contract is published in the OpenAPI specification.
ADR-016 defines the implemented canonical cricket-resource hierarchy with optional API-key identification. Requester-owned consumer access remains follow-up issue #822.
Live development API¶
The deployed development backend is hosted on Azure Container Apps:
- Base URL: https://statsthegame-dev-api.calmground-aa50efe2.southafricanorth.azurecontainerapps.io
- API base URL: https://statsthegame-dev-api.calmground-aa50efe2.southafricanorth.azurecontainerapps.io/api/v1
- Health check: https://statsthegame-dev-api.calmground-aa50efe2.southafricanorth.azurecontainerapps.io/api/v1/health
The deployment guides and Sprint evidence retain the deployment/acceptance trail. Availability is verified as part of milestone close-out rather than inferred from this documentation page.
See API versioning and deprecation for compatibility, deprecation and retirement rules.
See Shared API Contracts for the complete identifier, response, error, filtering, sorting, date/time, event-ordering, and pagination conventions.
Interactive API Explorer¶
The public frontend exposes an interactive API Explorer at /api. It loads the authoritative
/openapi.yaml document from the backend at runtime rather than keeping a frontend copy of the
contract. The page identifies v1 as the currently supported API major version and exposes the
contract-defined bearer-token and consumer API-key authorization controls.
Implemented operations are available for normal exploration. Planned operations are hidden by default; users may reveal them explicitly, but interactive submission is disabled while the planned view is active.
The Explorer is discoverable from the Stat'sTheGame primary public navigation as API. The bottom-of-page API entry opens the in-app Explorer, while a separate API Documentation link continues to expose the extended MkDocs documentation.
Before the operation list, the Explorer distinguishes anonymous public reads, API-key-authenticated
consumer operations and bearer-authenticated application/administrator operations. It explains that
consumer keys are administrator-issued, tells prospective external consumers to request access from
a Stat'sTheGame administrator or project administrator under the current access model, identifies
the X-API-Key request header and consumer limits, and links directly to the
consumer-key guidance. A consumer key authorizes only documented consumer
operations and never grants administrator, submission or batch access.
The Explorer makes both deferred stages visible: the route-level lazy module and the backend OpenAPI specification request each show the same labelled progress indicator until their associated content is ready. A specification failure replaces that indicator with an explicit retryable error state, so an unfinished or failed Explorer is not presented as a blank page.
Signed-in administrators manage external API consumers through /admin/api-consumers. That
frontend uses the existing handwritten list, issue, rotate and individual-key revoke operations and
links back to the API Explorer; it complements rather than duplicates the API documentation. A
selected consumer's detail view uses the owner-scoped, bearer-authenticated GET
/api/v1/admin/api-consumers/{consumerId}/usage operation for safe historical aggregates. The
consumer-self GET /api/v1/consumer/usage operation remains API-key authenticated and scoped to
the calling consumer.
Current endpoints¶
GET /api/v1/health
Example response:
{
"status": "ok",
"service": "sport-analytics-api",
"timestamp": "2026-08-04T19:00:00.000Z"
}
This endpoint is scaffold infrastructure only.
Current user profile¶
GET /api/v1/auth/me
Authorization: Bearer <supabase-access-token>
Successful response:
{
"user": {
"id": "42",
"subject": "<supabase-user-id>",
"displayName": "Example User",
"role": "submitter",
"approvalState": "approved",
"requestedCompetition": {
"competitionId": "7",
"name": "Premier T20"
},
"competitionIds": ["7", "12"]
}
}
Missing, malformed, invalid, expired or revoked tokens receive:
HTTP/1.1 401 Unauthorized
WWW-Authenticate: Bearer
The API verifies the Supabase identity, creates or synchronizes the local account, and returns
server-owned authorization state. Authentication does not promote a user, approve submission, or
grant competition scope. A disabled account receives 403 Forbidden.
Account deletion¶
An authenticated user can permanently delete their own account through:
DELETE /api/v1/account
Authorization: Bearer <supabase-access-token>
Content-Type: application/json
{"confirmation":"DELETE"}
The endpoint accepts no target account identifier, requires a sign-in no more than 15 minutes old,
and returns 422 unless the confirmation is exactly DELETE. A successful request disables the
local account, revokes its role, approval and competition grants, hard-deletes the Supabase Auth
user, and replaces local identity fields with a tombstone.
The backend requires a separate server-only SUPABASE_SECRET_KEY for that provider operation. If it
is not configured, the route returns 501 ACCOUNT_DELETION_UNAVAILABLE before changing local state;
other routes and health checks remain available.
Submissions, fixtures, deliveries, derived statistics and their stable app_user_id provenance
remain. If Auth deletion or local finalization fails, the API returns 503; the account remains
disabled and retry is idempotent. See Privacy and retention.
Application registration is handled by Supabase Auth; there is no backend registration or profile
mutation endpoint that accepts application_role. New application accounts are synchronized as
viewer, and only a trusted administrative backend process may change the role to submitter or
admin.
Submitter access requests¶
An authenticated viewer who does not already hold a submission-capable role can request submitter access through:
POST /api/v1/submitter-access-requests
Authorization: Bearer <supabase-access-token>
Content-Type: application/json
{"competitionId":"7"}
A successful request validates and persists the selected competition and changes the authenticated
application account's server-owned approval state to pending:
{
"data": {
"accountId": "42",
"approvalState": "pending",
"requestedCompetition": {
"competitionId": "7",
"name": "Premier T20"
}
}
}
The endpoint returns 401 Unauthorized when no valid authentication is supplied and 422
Unprocessable Entity when the body or competition identifier is invalid.
A 409 Conflict is returned when the account already has a pending request, has the legacy
approved request state, or already holds the submitter/admin role. A previously rejected
viewer may submit a new request.
The requested competition and request state are stored on the provider-neutral application account
and exposed through /api/v1/auth/me and the administrator user list. They are not authorization
grants: approval must atomically assign application_role = submitter and grant exactly the stored
competition. The backend uses the authoritative role plus granted competition scope for submission
decisions.
Administrator submitter-access decisions¶
Administrators can list active application users through:
GET /api/v1/admin/users
Authorization: Bearer <supabase-access-token>
The endpoint is restricted to the admin role and provides the account state needed for
submitter-access review and administration. Each user includes the safe email address required by
the administration interface. The backend obtains this value with its server-only Supabase Admin
client and returns no provider metadata, credentials, or tokens. If that server-only configuration
is unavailable or the provider lookup fails, the endpoint returns a controlled 503 response.
Only an authoritative admin may manage another active, non-administrator account. Approval and
scope replacement use PATCH /api/v1/admin/users/{userId}/submitter-access; approval requires a
pending viewer and exactly the valid competition stored on that request, while scope replacement
for an approved submitter requires at least one valid competition. A legacy pending request without
a stored competition cannot be approved and must be rejected before the viewer submits a corrected
request. Sending approved: false revokes an approved submitter, removes every scope, and retains
the historical approved request decision.
Rejecting a pending request is a separate action:
POST /api/v1/admin/users/{userId}/submitter-access/rejection
Authorization: Bearer <supabase-access-token>
An administrator may promote an active non-administrator through
PATCH /api/v1/admin/users/{userId}/role with {"role":"admin"}. The route validates the
role value server-side and prohibits self-management, disabled targets, and administrator
demotion. Direct viewer and submitter changes are rejected: those states must use the
submitter-access lifecycle so that approval and competition scopes remain consistent.
Rejection keeps the account as a viewer, writes rejected, clears all scopes, and allows the user
to request again. Invalid lifecycle changes return 409 INVALID_SUBMITTER_ACCESS_TRANSITION and
leave the account's role, request state, scopes, and audit fields unchanged.
Public read¶
The following endpoints are available without authentication:
GET /api/v1/competitions
GET /api/v1/competitions/{competitionId}
GET /api/v1/seasons
GET /api/v1/seasons/{seasonId}
GET /api/v1/fixtures
GET /api/v1/fixtures/{fixtureId}
GET /api/v1/fixtures/{fixtureId}/events
GET /api/v1/fixtures/{fixtureId}/events/{eventId}
GET /api/v1/fixtures/{fixtureId}/events/export.json
GET /api/v1/fixtures/{fixtureId}/events/export.csv
GET /api/v1/fixtures/{fixtureId}/statistics
GET /api/v1/fixtures/{fixtureId}/statistics/{statisticId}
GET /api/v1/fixtures/{fixtureId}/statistics/{statisticId}/events/export.json
GET /api/v1/fixtures/{fixtureId}/statistics/{statisticId}/events/export.csv
GET /api/v1/competitors
GET /api/v1/competitors/{competitorId}
GET /api/v1/participants
GET /api/v1/participants/{participantId}
GET /api/v1/participants/{participantId}/fixtures
See Public Read API for filters, pagination, deterministic ordering and example responses.
Direct event submission¶
Administrators can use the privileged legacy direct-import endpoint:
POST /api/v1/submissions
See Direct Event Submissions for the versioned request schema, provenance response, validation errors, payload limit, and rate limit.
File event submission¶
POST /api/v1/submissions/uploads
Administrators may use this legacy synchronous JSON/CSV import path. Ordinary submitter uploads
use the staged /api/v1/batches pipeline so validation and review occur before publication. See Direct Event Submissions for the
file types, CSV columns, limits, and errors.
Weather integration¶
The backend exposes the course-required runtime external API integration through:
GET /api/v1/weather
The endpoint accepts documented location and date parameters, calls Open-Meteo server-side, validates the provider response, applies a bounded timeout, and maps upstream failures to safe application errors.
See Weather API for the request parameters, response format, provider behaviour, and current limitations.
Consumer API keys¶
Administrators can issue, rotate and revoke external-consumer API keys. Applicable canonical cricket reads accept a valid key and apply consumer-wide request-rate, UTC daily quota and usage accounting without changing the resource URL or response schema. See Consumer API keys, rate limits and quotas.
Intermediate API areas¶
The Intermediate tier is implemented through the same handwritten /api/v1 boundary and is included
in the version-controlled OpenAPI contract.
Batch ingestion, review and publication¶
Whole-season and back-catalogue packages use the asynchronous batch API. The implemented surface covers receipt, status, reports, report downloads, reference mapping, published-delivery conflict resolution, reviewer decisions, correction resubmission and publication.
See Batch ingestion receipt API for the lifecycle and authorisation rules.
Corrections and audit history¶
Accepted delivery corrections create immutable revisions rather than overwriting published data. Authorised users can submit a correction and retrieve the retained revision history.
See Direct Event Submissions and Protected provenance and audit API.
Participant aggregates¶
The public API derives season, competition and career aggregates from current accepted delivery revisions:
GET /api/v1/participants/{participantId}/statistics
GET /api/v1/participants/{participantId}/statistics/{statisticId}
See Participant aggregate calculations.
Season and competition leaderboards¶
GET /api/v1/statistics/leaderboards returns a bounded, server-ranked participant table for one
explicit season or competition. Supply scope=season&seasonId=... or
scope=competition&competitionId=..., a supported metric, and an optional limit from 1 to 50
(default 10). Invalid scope/identifier combinations, metrics and bounds return 400; a scope that
does not exist returns 404.
Total metrics are most_runs, most_wickets, most_fours and most_sixes. Qualified rate metrics
are highest_batting_average, highest_strike_rate, best_bowling_average,
best_economy_rate and best_bowling_strike_rate. Every response names the scope and metric,
returns stable participant identifiers and readable names, and carries the applicable qualification
rule. See Participant aggregate calculations.
Analytics query evaluation and natural-language questions¶
POST /api/v1/query-definitions/evaluate answers a structured query definition from the statistics
above. It requires no authentication, computes nothing of its own, and returns the published
leaderboard or participant-aggregate resource unchanged, together with the endpoint and statistic
identifiers the answer came from. A name that matches nothing or more than one entity is reported as
an outcome rather than an error.
POST /api/v1/natural-language-queries answers the same questions written in words. It translates
the question into a definition with a server-side language-model adapter, evaluates that definition
through the operation above, and returns what was interpreted alongside the answer. It is anonymous
too, and is protected instead by a durable per-client rate limit and daily quota, a global daily cap
and a 300-character question bound.
See Analytics query for the outcomes, the name-resolution rules, the limits and the recorded limitations.
Dataset releases¶
Administrators can queue immutable versioned dataset releases. Public consumers can discover release metadata and download the exact checksum-backed JSON artifact.
See Dataset exports.
API consumer protections¶
Administrators can issue, rotate and revoke consumer API keys. Keyed consumer requests are protected by configurable per-minute rate limits and durable UTC daily quotas. Anonymous canonical reads use lower per-source and global durable minute limits, so omitting a key is not unrestricted fallback.
See Consumer API keys, rate limits and quotas.
Caching and response-time behaviour¶
Repeated fixture-statistics reads use a versioned 60-second server-side cache-aside path. Contributor traces bypass the cache, and accepted changes advance the fixture version so stale cached statistics are no longer reachable.
The reproducible workload, response-time targets and measurement commands are documented in Representative-scale API performance baseline.
The OpenAPI specification remains the authoritative request/response contract for all implemented endpoints.
Remaining future API areas¶
The following belong to later Advanced-tier work rather than the implemented Intermediate surface:
- analyst-defined statistic definitions, validation, sandboxing and versioning;
- late and out-of-order live-feed replay;
- bitemporal/as-of statistic queries and release comparisons;
- larger asynchronous analytical jobs and change-feed functionality where not already implemented for dataset-release generation.
Related reading paths¶
- Product & API — human-facing entry point for API, submission, statistics and export documentation.
- Architecture & Data — persistence, ingestion and security boundaries behind the API.
- Testing & Quality — API contract, browser and performance verification.
AI Declaration¶
The preceding API overview was reviewed and updated for the Intermediate implementation with the assistance of ChatGPT-Web[GPT-5.6 Sol]. The issue #635 public leaderboard endpoint and qualification summary were documented with the assistance of Codex[GPT-5]. The Issue #660 public API Explorer workflow was reviewed and documented with the assistance of ChatGPT-Web[GPT-5.6 Sol]. The Issue #661 public API Explorer discoverability and production UX guidance was reviewed and documented with the assistance of ChatGPT-Web[GPT-5.6 Sol]. The Issue #726 API Explorer loading-feedback guidance was updated with the assistance of Codex[GPT-5]. The documentation reading-path links were added with the assistance of ChatGPT-Web[GPT-5.6 Sol]. The issue #775 administrator consumer-management frontend boundary was documented with the assistance of Codex[GPT-5.6 Sol]. The issue #776 administrator per-consumer usage workflow was documented with the assistance of Codex[GPT-5.6 Sol]. The issue #783 public API consumer-onboarding guidance was documented with the assistance of Codex[GPT-5]. The issue #820 accepted API consumer access-model link and current/future boundary were documented with the assistance of Codex[GPT-5]. The issue #821 canonical optional-key implementation was documented with the assistance of Codex[GPT-5]. The issue #813 analytics query evaluation endpoint was documented with the assistance of Claude-Code[Claude Opus 5 (1M context)]. The issue #815 natural-language query endpoint was documented with the assistance of Claude-Code[Claude Opus 5 (1M context)].