Event live status
#Event live status
The event's races and start groups, with the live flags a broadcast overlay needs to decide what to poll next. Start here, then call Race live for whichever race is actually live.
Requires both the tracking:read scope and the event's organiser having turned on Share live tracking
with API partners (panel: Advanced settings → Mobile broadcast & tracking) — sharing off answers
404 TRACKING_NOT_SHARED for every call below, scope or no scope.
#Headers
| Header | Required | Value |
|---|---|---|
Authorization |
yes | Bearer <access_token> |
#Path parameters
| Param | Type | Note |
|---|---|---|
eventId |
UUID or legacy id | from List events; another club's, unpublished, or unknown ⇒ 404 EVENT_NOT_FOUND |
#Request
curl -s https://sail-club-server.cloud.run/api/v1/events/1143117a-9c2b-4e7a-8f1d-2b6a9c4e7f10/live \
-H "Authorization: Bearer $TOKEN"const res = await fetch(`https://sail-club-server.cloud.run/api/v1/events/${eventId}/live`, {
headers: { Authorization: `Bearer ${token}` },
});
if (res.status === 404) { /* not found, not published, or sharing is off for this event */ }
const live = await res.json();res = requests.get(
f"https://sail-club-server.cloud.run/api/v1/events/{event_id}/live",
headers={"Authorization": f"Bearer {token}"},
timeout=10,
)
live = res.json()var res = await client.GetAsync($"/api/v1/events/{eventId}/live");
res.EnsureSuccessStatusCode();
var live = await res.Content.ReadFromJsonAsync<PublicEventLiveDto>();<?php
$ch = curl_init("https://sail-club-server.cloud.run/api/v1/events/$eventId/live");
curl_setopt_array($ch, [CURLOPT_RETURNTRANSFER => true, CURLOPT_HTTPHEADER => ["Authorization: Bearer $token"]]);
$live = json_decode(curl_exec($ch), true);#Response
{
"eventId": "1143117a-9c2b-4e7a-8f1d-2b6a9c4e7f10",
"delaySeconds": 30,
"dataAsOf": "2027-05-01T12:00:00.000Z",
"races": [
{
"raceId": "9a1c0d2b-7e4a-46f8-9c1d-2e3f9a1c0d2b",
"raceNo": 1,
"name": "Race 1",
"status": "Started",
"isLive": true,
"startGroups": [
{
"startGroupId": "2b6a9c4e-7f10-4a1c-8d2b-7e4a6f8c1d2e",
"name": "Start A",
"state": "Started",
"startTimeUtc": "2027-05-01T11:30:00Z",
"finishTimeUtc": null,
"courseVersion": 3
}
]
}
]
}200 — same caching headers as every data endpoint, a shared 5-second server-side cache per event.
#Response fields
| Field | Type | Null? | Note |
|---|---|---|---|
eventId |
string | no | canonical event id |
delaySeconds |
int | no | 0–600, the organiser's current delay for this event |
dataAsOf |
date-time (UTC) | no | when this body was built; also X-Data-As-Of |
races[] |
array | no (may be empty) | every race of the event, in raceNo order — filter on isLive for an overlay |
races[].raceId / raceNo / name / status |
uuid / int / string / string | no | status is PublicRaceItemDto.status |
races[].isLive |
bool | no | the race's mobile-broadcast live flag |
races[].startGroups[] |
array | no | start order within the race |
startGroups[].startGroupId / name |
uuid / string | no | pass startGroupId to Track |
startGroups[].state |
string | no | Scheduled, StartSequence, Started, Finished, Postponed, GeneralRecall, Abandoned, APEarly, StartLineReady, PostponedAshore, PostponedToday, AbandonedAshore, AbandonedToday |
startGroups[].startTimeUtc |
date-time | yes | null before a gun time is set |
startGroups[].finishTimeUtc |
date-time | yes | null while racing |
startGroups[].courseVersion |
int | no | increments on every course change — refetch Course when it does |
#Errors
| HTTP | Code |
|---|---|
| 404 | EVENT_NOT_FOUND |
| 404 | TRACKING_NOT_SHARED |
| 401 | API_TOKEN_MISSING / API_TOKEN_INVALID |
| 403 | API_SCOPE_MISSING / API_IP_NOT_ALLOWED |
| 429 | RATE_LIMIT_EXCEEDED |
| 503 | API_UNAVAILABLE |
#Caching
One shared cache entry per eventId, refreshed every 5 seconds. Poll this one call to decide which race to
follow; don't poll it faster than its own Cache-Control: max-age — see Rate limits for
the separate, higher tracking:read bucket (120/min) this endpoint shares with the other three tracking calls.
Prompt for AI agents ready to paste into an agent
Implement getEventLive(eventId) for the Sail Club API.
GET https://sail-club-server.cloud.run/api/v1/events/{eventId}/live
Authorization: Bearer <access_token>
Scope required: tracking:read
Success 200: { eventId, delaySeconds, dataAsOf, races: [ { raceId, raceNo, name, status, isLive,
startGroups: [ { startGroupId, name, state, startTimeUtc, finishTimeUtc, courseVersion } ] } ] } — fetch
GET /api/v1/openapi.json for the exact schema.
404 EVENT_NOT_FOUND: unknown/other club's/unpublished event — not retryable.
404 TRACKING_NOT_SHARED: the organiser hasn't turned on live tracking sharing for this event — not retryable,
not fixable by the caller; the organiser must enable it in their panel.
401/403/429/503: same handling as every other call — see the full-integration prompt on /docs/overview.
For each race where isLive is true, call GET /api/v1/races/{raceId}/live for boat positions, wind and the
unofficial order; use startGroups[].startGroupId with GET /api/v1/races/{raceId}/track for the 1Hz trail.
Adapt to your actual stack — the endpoint, path param and response shape above are language-neutral.