API documentation
Hyrox Result API is a versioned JSON HTTP API for HYROX race data: seasons, events, results, athlete search, split times, division statistics, and simulator benchmarks.
Interactive OpenAPI explorer
Try endpoints, inspect schemas, and export the contract.
Use these docs with an LLM
Copy the full API reference as plain text (llms.txt) and paste it into ChatGPT, Claude, or Cursor to build against the API.
Quick start
- Register and subscribe , then create an API token under API tokens.
- Search for an athlete by surname and given name.
- Copy the race ID (
idfield) from a search hit. - Fetch race detail and split times with that race ID.
# 1. Search
curl -sS "https://hyroxresultapi.com/api/v1/athletes/search?last=McIntyre&first=Hunter" \
-H "Authorization: Bearer YOUR_TOKEN" \
-H "Accept: application/json"
# 2. Detail (use the id field from the search response)
curl -sS "https://hyroxresultapi.com/api/v1/athletes/RACE_ID_FROM_SEARCH" \
-H "Authorization: Bearer YOUR_TOKEN" \
-H "Accept: application/json"
# 3. Splits (same race ID)
curl -sS "https://hyroxresultapi.com/api/v1/athletes/RACE_ID_FROM_SEARCH/splits" \
-H "Authorization: Bearer YOUR_TOKEN" \
-H "Accept: application/json"
Identifiers
The API returns opaque strings for athlete lookups. Pass them back exactly as received. Do not decode or construct them.
| Name | Where you get it | Use on |
|---|---|---|
| Race ID | id on search hits |
Detail, splits, and single race results |
| Person ref | person_ref on search hits |
Result history and splits (not detail) |
| Stored athlete ID | athlete_id on ingested result rows |
All athlete routes; optional result_id on splits |
| Event ID | id on event resources |
Division results and event statistics |
Base URL
Product endpoints live under /api/v1 on your deployment host. Examples use https://hyroxresultapi.com.
Authentication
Protected routes require a bearer token and an active subscription. Send both headers on every request:
Authorization: Bearer <your-token>
Accept: application/json
GET /api/user (no /v1 prefix) returns your plan and rate limit. It requires a token but not a subscription.
Rate limits
Limits apply per account based on your plan. Exceeding the limit returns 429 Too Many Requests with Retry-After and X-RateLimit-* headers.
- Starter: 30 requests per minute
- Pro: 100 requests per minute
- Scale: 1,000 requests per minute
Response format
{
"data": …,
"meta": { "data_source": "database" | "live", … },
"errors": null
}
Athlete routes set meta.data_source to database (catalog) or live (on demand). Errors return errors.title, errors.detail, and errors.status.
Endpoints
Paths are relative to /api/v1 unless noted.
Public
GET /api/v1/health: service and database statusGET /api/v1/openapi.yaml: OpenAPI specification
Catalog
| Endpoint | Description |
|---|---|
| GET /seasons | List HYROX seasons. Use each slug to filter events. |
| GET /events | List events. Filter by season, country, or date range. |
| GET /events/{slug} | Single event by slug. |
| GET /events/{slug}/divisions | Divisions for an event. Division id equals the event id. |
| GET /divisions/{id}/results | Paginated finishers with cursor support. id is the event integer ID. |
Athletes
| Endpoint | Description | Accepts |
|---|---|---|
| GET /athletes/search | Search by q (surname) and first (given name). Returns race ID and person ref per hit. |
Query params |
| GET /athletes/{id} | Race detail for one result. | Race ID, stored athlete ID |
| GET /athletes/{id}/results | Result history for an athlete. | Person ref, race ID, stored athlete ID |
| GET /athletes/{id}/splits | Station split times. | Race ID, person ref, stored athlete ID |
Stats & simulator
| Endpoint | Description |
|---|---|
| GET /stats/divisions/{id} | Precomputed event statistics, bucketed by division × gender × age group. Per-station field medians (buckets[].splits) are Scale-only; on other plans the object is present but empty and meta.field_splits.included is false. |
| GET /stats/divisions/{id}/splits | Scale plan. Per-station medians for a whole race field. The first request for an event queues the harvest and returns 202; poll until 200. |
| GET /simulator/benchmarks | Event-specific simulator benchmarks from stored aggregates. |
| GET /simulator/division-benchmarks | Global division benchmarks by code (e.g. HYROX_MEN). Station means across all races, not one event. |
| GET /events/{slug}/ingest-status | How far this event has progressed through ingestion — rankings and field splits — so you can stop polling blind after a race. Includes the division's own race day within a multi-day race weekend (race.race_date, race.phase), so an empty ranking that simply has not raced yet is distinguishable from a stalled ingest. |
Admin ingestion and maintenance routes under /api/v1/admin/* are documented in OpenAPI and require an admin token.
Interactive docs
Explore and try endpoints in
Swagger UI.
The OpenAPI contract file is at GET /api/v1/openapi.yaml.
CORS
For browser clients, set CORS_ALLOWED_ORIGINS in .env to a comma separated list of allowed origins.