Race course
#Race course
The course actually applied to each of a race's start groups — the marks and lines an overlay draws under the
boats. Identical shape to the courses[] field on Race results; this is the same
data as its own call, usable before the race finishes (and without results:read).
Unlike the other three tracking:read endpoints, the delay does not apply here — a course doesn't change
every second, so there's nothing to hold back.
#Headers
| Header | Required | Value |
|---|---|---|
Authorization |
yes | Bearer <access_token> |
#Path parameters
| Param | Type | Note |
|---|---|---|
raceId |
UUID | from Event live status; unknown, malformed, or another club's ⇒ 404 RACE_NOT_FOUND |
#Request
curl -s https://sail-club-server.cloud.run/api/v1/races/9a1c0d2b-7e4a-46f8-9c1d-2e3f9a1c0d2b/course \
-H "Authorization: Bearer $TOKEN"const res = await fetch(`https://sail-club-server.cloud.run/api/v1/races/${raceId}/course`, {
headers: { Authorization: `Bearer ${token}` },
});
const course = await res.json();res = requests.get(
f"https://sail-club-server.cloud.run/api/v1/races/{race_id}/course",
headers={"Authorization": f"Bearer {token}"},
timeout=10,
)
course = res.json()var res = await client.GetAsync($"/api/v1/races/{raceId}/course");
res.EnsureSuccessStatusCode();
var course = await res.Content.ReadFromJsonAsync<PublicRaceCourseDto>();<?php
$ch = curl_init("https://sail-club-server.cloud.run/api/v1/races/$raceId/course");
curl_setopt_array($ch, [CURLOPT_RETURNTRANSFER => true, CURLOPT_HTTPHEADER => ["Authorization: Bearer $token"]]);
$course = json_decode(curl_exec($ch), true);#Response
{
"raceId": "9a1c0d2b-7e4a-46f8-9c1d-2e3f9a1c0d2b",
"startGroups": [
{
"startGroupId": "2b6a9c4e-7f10-4a1c-8d2b-7e4a6f8c1d2e",
"name": "Start A",
"courseVersion": 3,
"course": {
"marks": [{ "key": "M1", "label": "Windward", "lat": 40.99, "lon": 28.79 }],
"startLine": { "type": "LineSegment", "ends": [{ "lat": 40.97, "lon": 28.78 }, { "lat": 40.971, "lon": 28.781 }] },
"finishLine": { "type": "LineSegment", "ends": [{ "lat": 40.97, "lon": 28.78 }, { "lat": 40.971, "lon": 28.781 }] },
"route": ["START", "M1", "FIN"]
}
}
]
}200 — same caching headers as every data endpoint, a shared 5-second server-side cache per race.
#Response fields
| Field | Type | Null? | Note |
|---|---|---|---|
raceId |
uuid | no | |
startGroups[] |
array | no | one entry per start group of this race |
startGroups[].startGroupId / name |
uuid / string | no | matches Event live status |
startGroups[].courseVersion |
int | no | bumped every time the applied course changes — refetch when it differs from the value you last saw |
startGroups[].course |
object | yes | null until a course with placed marks has been applied to this start group. Full field table: Data models → Race results (same PublicCourseDto shape) |
#Errors
| HTTP | Code |
|---|---|
| 404 | RACE_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 entry per raceId, refreshed every 5 seconds. Compare courseVersion per start group before
redrawing marks — most polls will see no change at all.
Prompt for AI agents ready to paste into an agent
Implement getRaceCourse(raceId) for the Sail Club API.
GET https://sail-club-server.cloud.run/api/v1/races/{raceId}/course
Authorization: Bearer <access_token>
Scope required: tracking:read
Success 200: { raceId, startGroups: [ { startGroupId, name, courseVersion, course: PublicCourseDto | null } ] }
— course is the same shape as race-results' courses[] (marks, startLine, finishLine, route). Fetch
GET /api/v1/openapi.json for the exact schema.
404 RACE_NOT_FOUND: unknown/malformed/another club's race id — not retryable.
404 TRACKING_NOT_SHARED: sharing is off for this event — not retryable, needs an organiser change.
401/403/429/503: same handling as every other call — see the full-integration prompt on /docs/overview.
No delay applies to this endpoint. Only redraw marks/lines when courseVersion changes from what you last
stored for that startGroupId.
Adapt to your actual stack — the endpoint, path param and response shape above are language-neutral.