API documentation
Hyrox Result API is a versioned JSON HTTP API for HYROX race data: seasons, events, divisions, results, athlete search, per-athlete results and splits, division-level statistics, and race-simulator benchmarks (stored and live-backed where configured). Use it from mobile apps, training platforms, and internal tools without maintaining your own scrapers.
Base URL and versioning
All product endpoints are under the /api/v1 prefix on the host where you deploy this application. Examples below use https://hyroxresultapi.com — replace that host with your real public origin (no trailing slash).
Authentication
Protected routes need a Sanctum personal access token and an active API subscription (or an operator account). After you register and subscribe, create a token under API tokens and send it on every request:
Authorization: Bearer <your-token>
Accept: application/json
Rate limits
Authenticated API traffic is throttled per token (default 120 requests per minute; configurable via API_RATE_LIMIT_PER_MINUTE). Expect 429 Too Many Requests when exceeded.
Subscription and access
Without an active plan, protected endpoints return 402 Payment Required with a pointer to pricing. Operator (is_admin) accounts bypass the consumer subscription for API data access.
Public endpoints
No token required:
GET /api/v1/health— liveness and database connectivityGET /api/v1/openapi.yaml— OpenAPI 3.1 specification (same contract as interactive docs)
Protected endpoints (overview)
All of the following require a valid bearer token and subscription (unless admin). Paths are relative to /api/v1.
| Method & path | What it does |
|---|---|
| GET /seasons | List HYROX seasons / year catalog. |
| GET /events | List events (filter by season and other params per OpenAPI). |
| GET /events/{slug} | Single event by slug. |
| GET /events/{slug}/divisions | Divisions for an event (age groups / categories). |
| GET /divisions/{id}/results | Leaderboard-style results for a division. |
| GET /athletes/search | Search athletes by name (see parameters below). |
| GET /athletes/{id} | Athlete profile / metadata. |
| GET /athletes/{id}/results | Race results history for an athlete. |
| GET /athletes/{id}/splits | Station splits for an athlete where available. |
| GET /stats/divisions/{id} | Aggregated division statistics. |
| GET /simulator/benchmarks | Simulator benchmark data from your pipeline / DB. |
| GET /simulator/hyresult-benchmarks | Simulator benchmarks resolved via hyresult-style upstream when enabled. |
| GET /hyresult/athletes/{slug} | Resolve athlete by hyresult slug (live or cached per deployment). |
| GET /user | Current authenticated user (Sanctum). |
Admin-only sync and maintenance routes under /api/v1/admin/* are documented in OpenAPI for operators; they require an admin token.
Response shape
Successful payloads use a shared envelope. The meta object often includes data_source set to database or live so clients know whether rows came from your stored snapshot or a live upstream call.
{
"data": …,
"meta": { "data_source": "database" | "live", … },
"errors": null
}
Errors
Errors use HTTP 4xx/5xx with a structured body including errors.title, errors.detail, and errors.status where applicable.
Example requests
Replace the host with your deployment and paste a token from your dashboard.
curl -sS "https://hyroxresultapi.com/api/v1/seasons" \
-H "Authorization: Bearer YOUR_TOKEN" \
-H "Accept: application/json"
curl -sS "https://hyroxresultapi.com/api/v1/events?season=YOUR_SEASON_SLUG" \
-H "Authorization: Bearer YOUR_TOKEN" \
-H "Accept: application/json"
Athlete search
Search expects query parameters documented in OpenAPI — typically surname q and given name first, with optional season and event to narrow results.
OpenAPI and interactive docs
The machine-readable contract is at GET /api/v1/openapi.yaml. In the browser you can explore and try calls with Swagger UI at the interactive docs (protected operations still require a bearer token).
CORS
If you call the API from a browser SPA, set CORS_ALLOWED_ORIGINS in .env to a comma-separated list of allowed origins (see config/cors.php).