Skip to content
Developers
OpenAPI
GET /api/v1/races/{raceId}/coursescope: tracking:read

Race course

API v1 Last updated 2026-10-01 View as Markdown

#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.