Racey Public API v1
Build integrations, overlays, bots, and analytics tools with programmatic access to Racey league data. Read-only API with API key authentication.
Authenticate with Bearer tokens. Create and manage keys from your settings.
200 read requests/min and 60 write requests/min per API key.
Restrict keys by scope (read/write/admin) and optionally limit to specific leagues.
Authentication
All API requests must include your API key in the Authorization header as a Bearer token.
Getting an API Key
- Sign in to your Racey account
- Go to Settings → API Keys
- Click “Create API Key” and give it a name
- Copy the key immediately — it will only be shown once
Using Your Key
Authorization: Bearer rk_live_a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6Base URL & Response Format
https://your-domain.com/api/v1All responses follow a consistent envelope format:
{
"success": true,
"data": { ... }
}{
"success": false,
"error": "Error message",
"code": "ERROR_CODE"
}Paginated endpoints return an additional wrapper:
{
"success": true,
"data": {
"data": [ ... ],
"total": 42,
"page": 1,
"limit": 20,
"totalPages": 3
}
}Rate Limits
| Tier | Limit | Window |
|---|---|---|
| Read (GET) | 200 requests | per minute |
| Write (POST/PATCH/DELETE) | 60 requests | per minute |
When rate limited, the API returns HTTP 429. Wait until the reset window before retrying.
Endpoints Reference
/api/v1/leaguesList leagues accessible to the authenticated user. Supports search and filtering.
Parameters
| Name | Type | Description |
|---|---|---|
| page | number | Page number (default: 1) |
| limit | number | Items per page (default: 20, max: 100) |
| search | string | Search by league name |
| status | string | Filter by status (draft, active, paused, archived) |
Example Response
{
"success": true,
"data": {
"data": [
{
"id": "clx1abc...",
"name": "Sunday Road Racing",
"slug": "sunday-road-racing",
"discipline": "road",
"region": "na",
"status": "active",
"seasonCount": 3,
"staffCount": 5
}
],
"total": 1,
"page": 1,
"limit": 20,
"totalPages": 1
}
}/api/v1/leagues/:leagueIdGet detailed information about a specific league including its current season.
Example Response
{
"success": true,
"data": {
"id": "clx1abc...",
"name": "Sunday Road Racing",
"slug": "sunday-road-racing",
"description": "Weekly road racing league",
"discipline": "road",
"region": "na",
"status": "active",
"currentSeason": {
"id": "clx2def...",
"name": "Season 3",
"status": "active"
},
"seasonCount": 3,
"staffCount": 5
}
}/api/v1/seasons/:seasonIdGet season details with the full rounds schedule.
Example Response
{
"success": true,
"data": {
"id": "clx2def...",
"name": "Season 3",
"status": "active",
"league": { "id": "clx1abc...", "name": "Sunday Road Racing" },
"rounds": [
{
"id": "clx3ghi...",
"roundNumber": 1,
"name": "Daytona Road Course",
"trackName": "Daytona International Speedway",
"status": "completed"
}
],
"registrationCount": 24,
"standingsCount": 24
}
}/api/v1/standings/:seasonIdFull championship standings for a season.
Parameters
| Name | Type | Description |
|---|---|---|
| carClassId | string | Filter by car class (optional) |
Example Response
{
"success": true,
"data": {
"season": { "id": "clx2def...", "name": "Season 3", "status": "active" },
"standings": [
{
"position": 1,
"userId": "clx4jkl...",
"driverName": "Casey Brooks",
"totalPoints": 245,
"wins": 3,
"podiums": 7,
"dnfs": 0
}
]
}
}/api/v1/results/:roundIdRace results for all sessions in a round, including points breakdown.
Example Response
{
"success": true,
"data": {
"round": {
"id": "clx3ghi...",
"roundNumber": 1,
"name": "Daytona Road Course",
"status": "completed"
},
"sessions": [
{
"sessionId": "clx5mno...",
"type": "race",
"results": [
{
"position": 1,
"driverName": "Casey Brooks",
"startPosition": 3,
"lapsCompleted": 45,
"finishStatus": "running",
"gap": null,
"points": {
"position": 25,
"bonus": { "fastestLap": 1 },
"penalty": 0,
"total": 26
}
}
]
}
]
}
}/api/v1/drivers/:userIdDriver profile with career statistics across all seasons.
Example Response
{
"success": true,
"data": {
"id": "clx4jkl...",
"displayName": "Casey Brooks",
"avatar": null,
"preferredNumber": 42,
"careerStats": {
"seasonsRaced": 5,
"totalWins": 12,
"totalPodiums": 28,
"championships": 2,
"totalPoints": 1250.5
},
"simProfiles": [
{ "platform": "iracing", "iRating": 3200, "safetyRating": 4.5 }
]
}
}Code Examples
curl
curl -H "Authorization: Bearer rk_live_YOUR_KEY_HERE" \
"https://your-domain.com/api/v1/standings/SEASON_ID"JavaScript / TypeScript
const API_KEY = 'rk_live_YOUR_KEY_HERE';
const BASE_URL = 'https://your-domain.com/api/v1';
async function getStandings(seasonId: string) {
const res = await fetch(`${BASE_URL}/standings/${seasonId}`, {
headers: {
'Authorization': `Bearer ${API_KEY}`,
'Content-Type': 'application/json',
},
});
if (!res.ok) {
throw new Error(`API error: ${res.status}`);
}
const json = await res.json();
if (!json.success) {
throw new Error(json.error);
}
return json.data;
}
// Usage
const data = await getStandings('clx2def...');
console.log(data.standings);Python
import requests
API_KEY = "rk_live_YOUR_KEY_HERE"
BASE_URL = "https://your-domain.com/api/v1"
def get_standings(season_id: str):
response = requests.get(
f"{BASE_URL}/standings/{season_id}",
headers={"Authorization": f"Bearer {API_KEY}"},
)
response.raise_for_status()
data = response.json()
if not data["success"]:
raise Exception(data["error"])
return data["data"]
# Usage
standings = get_standings("clx2def...")
for entry in standings["standings"]:
print(f"{entry['position']}. {entry['driverName']} - {entry['totalPoints']} pts")Error Codes
| HTTP Status | Code | Description |
|---|---|---|
| 401 | INVALID_API_KEY | Missing, invalid, expired, or revoked API key |
| 403 | INSUFFICIENT_SCOPE | API key lacks the required scope for this endpoint |
| 403 | LEAGUE_ACCESS_DENIED | API key restricted to specific leagues that don't include the requested league |
| 404 | NOT_FOUND | Requested resource does not exist |
| 429 | RATE_LIMIT_EXCEEDED | Too many requests; wait for the rate limit window to reset |
| 500 | INTERNAL_ERROR | Unexpected server error |
Ready to Build?
Create an API key and start building integrations in minutes.