Skip to content
Developers
OpenAPI

Scopes

API v1 Last updated 2026-09-30 View as Markdown

#Scopes

A client holds one or more scopes, chosen by the club admin when it's created (or changed later). A token inherits its client's scopes, optionally narrowed with scope= at the token request. Calling an endpoint without the scope it requires is 403 API_SCOPE_MISSING.

Scope Grants Endpoints
events:read the club's published events, event detail, race list GET /api/v1/events · GET /api/v1/events/{eventId} · GET /api/v1/events/{eventId}/races
results:read race results, event (series) results GET /api/v1/races/{raceId}/results · GET /api/v1/events/{eventId}/results

Both are read-only — there is no write scope today. New endpoint families get new scopes as they ship; an existing scope never silently widens to cover new data.

#Checking a token's scopes

Full reference: Check a token.

curl -s https://sail-club-server.cloud.run/api/v1/token-info \
  -H "Authorization: Bearer $TOKEN"
{ "client_id": "scc_3f9a…", "club_id": "TRX1001CL", "scope": "events:read results:read", "expires_at": "2026-09-30T10:00:00Z" }

Any valid token can call this — it needs no scope of its own, and is never rate-limited the way data calls are. Useful for a health check or for debugging "why am I getting 403s."

#Narrowing a request

curl -s -X POST https://sail-club-server.cloud.run/api/v1/oauth/token \
  -u "$SAIL_CLUB_CLIENT_ID:$SAIL_CLUB_CLIENT_SECRET" \
  -d grant_type=client_credentials -d "scope=events:read"

Requesting a scope the client doesn't hold is 400 invalid_scope (API_SCOPE_INVALID). Omitting scope entirely returns a token with every scope the client has.

#Changing scopes

The club admin can add or remove scopes for a client at any time (Settings → API access → the client → Edit). A removed scope is also removed from the client's live tokens within 60 seconds — you don't need to wait for the token to expire to see the change.