Skip to content
Developers
OpenAPI

Quickstart

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

#Quickstart

#1. Get credentials from your club admin

Only a club admin can create API credentials, in the panel under Settings → API access. Ask them to:

  1. Open Settings → API access and click Create client.
  2. Give it a name (e.g. "Club website"), pick scopes (events:read, results:read), optionally restrict caller IPs, accept the API Terms the first time.
  3. Copy the client ID and client secret shown on the confirmation screen — the secret is shown once and cannot be retrieved again (only rotated, which invalidates the old one).

Store both as environment variables (SAIL_CLUB_CLIENT_ID, SAIL_CLUB_CLIENT_SECRET). Never commit them, never send them to a browser.

#2. Get a token

Prompt for AI agents ready to paste into an agent
Exchange a Sail Club API client_id/client_secret for a bearer token: POST
https://sail-club-server.cloud.run/api/v1/oauth/token as application/x-www-form-urlencoded, with
grant_type=client_credentials and the client_id/client_secret sent as HTTP Basic auth. Cache the returned
access_token in memory for its expires_in seconds; do not fetch a new one per call.

#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
const creds = Buffer.from(`${process.env.SAIL_CLUB_CLIENT_ID}:${process.env.SAIL_CLUB_CLIENT_SECRET}`).toString('base64');
const res = await fetch('https://sail-club-server.cloud.run/api/v1/oauth/token', {
  method: 'POST',
  headers: { Authorization: `Basic ${creds}`, 'Content-Type': 'application/x-www-form-urlencoded' },
  body: 'grant_type=client_credentials',
});
const { access_token, expires_in } = await res.json();
import os, requests

res = requests.post(
    "https://sail-club-server.cloud.run/api/v1/oauth/token",
    auth=(os.environ["SAIL_CLUB_CLIENT_ID"], os.environ["SAIL_CLUB_CLIENT_SECRET"]),
    data={"grant_type": "client_credentials"},
)
token = res.json()["access_token"]
using var client = new HttpClient { BaseAddress = new Uri("https://sail-club-server.cloud.run") };
var clientId = Environment.GetEnvironmentVariable("SAIL_CLUB_CLIENT_ID");
var clientSecret = Environment.GetEnvironmentVariable("SAIL_CLUB_CLIENT_SECRET");
var authHeader = Convert.ToBase64String(Encoding.UTF8.GetBytes($"{clientId}:{clientSecret}"));
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Basic", authHeader);
var res = await client.PostAsync("/api/v1/oauth/token",
    new FormUrlEncodedContent(new Dictionary<string, string> { ["grant_type"] = "client_credentials" }));
var body = await res.Content.ReadFromJsonAsync<JsonElement>();
var token = body.GetProperty("access_token").GetString();
<?php
$clientId = getenv('SAIL_CLUB_CLIENT_ID');
$clientSecret = getenv('SAIL_CLUB_CLIENT_SECRET');
$ch = curl_init('https://sail-club-server.cloud.run/api/v1/oauth/token');
curl_setopt_array($ch, [
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_USERPWD => "$clientId:$clientSecret",
    CURLOPT_POST => true,
    CURLOPT_POSTFIELDS => 'grant_type=client_credentials',
]);
$token = json_decode(curl_exec($ch), true)['access_token'];

Full reference: POST /api/v1/oauth/token.

#3. Make your first call

curl -s https://sail-club-server.cloud.run/api/v1/events \
  -H "Authorization: Bearer $TOKEN"

You'll get back the club's published events, the same list its public results pages show — see List events for the full shape.

#4. Next