# List races

# List races

An event's races. Identical data to the `races` field on [Get event](/docs/api/event) — a separate endpoint
for callers who only need the race list without the rest of the event detail.

## Headers

| Header | Required | Value |
|---|---|---|
| `Authorization` | yes | `Bearer <access_token>` |

## Path parameters

| Param | Type | Note |
|---|---|---|
| `eventId` | UUID | `404 EVENT_NOT_FOUND` if unknown / another club's / not published |

#### Request

```bash
curl -s https://sail-club-server.cloud.run/api/v1/events/1143117a-9c2b-4e7a-8f1d-2b6a9c4e7f10/races \
  -H "Authorization: Bearer $TOKEN"
```

```javascript
const res = await fetch(`https://sail-club-server.cloud.run/api/v1/events/${eventId}/races`, {
  headers: { Authorization: `Bearer ${token}` },
});
const races = await res.json();
```

```python
res = requests.get(
    f"https://sail-club-server.cloud.run/api/v1/events/{event_id}/races",
    headers={"Authorization": f"Bearer {token}"},
    timeout=10,
)
races = res.json()
```

```csharp
var res = await client.GetAsync($"/api/v1/events/{eventId}/races");
res.EnsureSuccessStatusCode();
var races = await res.Content.ReadFromJsonAsync<List<PublicRaceSummaryDto>>();
```

```php
<?php
$ch = curl_init("https://sail-club-server.cloud.run/api/v1/events/$eventId/races");
curl_setopt_array($ch, [CURLOPT_RETURNTRANSFER => true, CURLOPT_HTTPHEADER => ["Authorization: Bearer $token"]]);
$races = json_decode(curl_exec($ch), true);
```

#### Response

```json
[
  {
    "id": "9a1c0d2b-7e4a-46f8-9c1d-2e3f9a1c0d2b",
    "name": "Race 1",
    "scheduledDate": "2026-10-11T10:00:00Z",
    "status": "Completed",
    "hasResults": true,
    "isOfficial": true,
    "resultCount": 42,
    "raceNo": 1,
    "raceType": "Fleet",
    "boatModel": null
  },
  {
    "id": "2b6a9c4e-7f10-4a1c-8d2b-7e4a6f8c1d2e",
    "name": "Race 2",
    "scheduledDate": "2026-10-11T13:00:00Z",
    "status": "Completed",
    "hasResults": true,
    "isOfficial": true,
    "resultCount": 41,
    "raceNo": 2,
    "raceType": "Fleet",
    "boatModel": null
  }
]
```

`200` — same caching headers as every data endpoint; the array itself carries the `ETag`/`Last-Modified`.

## Response fields

Full field table: [Data models → Race summary](/docs/data-models#race-summary). Use each item's `id` as the
`raceId` for [Race results](/docs/api/race-results) once `hasResults` is `true`.

## Errors

| HTTP | Code |
|---|---|
| 404 | [`EVENT_NOT_FOUND`](/docs/errors#EVENT_NOT_FOUND) |
| 401 | [`API_TOKEN_MISSING`](/docs/errors#API_TOKEN_MISSING) / [`API_TOKEN_INVALID`](/docs/errors#API_TOKEN_INVALID) |
| 403 | [`API_SCOPE_MISSING`](/docs/errors#API_SCOPE_MISSING) / [`API_IP_NOT_ALLOWED`](/docs/errors#API_IP_NOT_ALLOWED) |
| 429 | [`RATE_LIMIT_EXCEEDED`](/docs/errors#RATE_LIMIT_EXCEEDED) |
| 503 | [`API_UNAVAILABLE`](/docs/errors#API_UNAVAILABLE) |

## Caching

One cache entry per `eventId`; races only stop changing once `hasResults` is `true` for all of them, so it's
safe to revalidate on your normal schedule throughout an event and less often afterwards.

```prompt
Implement listRaces(eventId) for the Sail Club API.

GET https://sail-club-server.cloud.run/api/v1/events/{eventId}/races
Authorization: Bearer <access_token>

Success 200: an array of { id, name, scheduledDate, status, hasResults, isOfficial, resultCount, raceNo,
  raceType, boatModel, ... } — fetch GET /api/v1/openapi.json for the exact schema.
404 EVENT_NOT_FOUND: unknown/other club's/unpublished event — not retryable.
401/403/429/503: same handling as every other call — see the full-integration prompt on /docs/overview.

For each race where hasResults is true, this is the id to pass to the race-results call
(GET /api/v1/races/{raceId}/results).

Adapt to your actual stack — the endpoint, path param and response shape above are language-neutral.
```
