Skip to content

Competitions API

This API endpoint provides access to competitions on OpenTrack. Each record represents a single competition (e.g., a track meet, road race, or cross country event), including its name, dates, venue, type, and metadata.

Specifically, this refers to our SQL Competitions table, which is basically the main calendar entry. There are parallel records in MongoDB, which store a lot of settings for the competition setup; this Mongo record is created when a SQL competition is saved, and they share the same id. You cannot manipulate the latter through this API

Common Tasks with this API

  • find upcoming competitions
  • embed a calendar in your site for a specific region or club, using OpenTrack as the storage engine
  • find a competition containing a specific event
  • create a new competition

Endpoint URL: https://{domain}/api/competitions/

For example: https://test-data.opentrack.run/api/competitions/

Federation sites also have access to their own competitions API filtered by their country by default:

https://saaf.opentrack.run/api/competitions/

Saudi Athletics Upcoming Competitions


Quick Start Examples

Authentication and Query a Competition by Natural Key

Every competition has a natural key URL built from its year, country and slug — far easier to read and remember than a UUID. Get a token first, then use the natural key to fetch the competition and list its events:

Pass the token via the Authorization: Token ... header:

TOKEN=$(curl -s -X POST "https://test-data.opentrack.run/api/get-auth-token/" \
  -H "Content-Type: application/x-www-form-urlencoded" \
  -d 'username=api-test@mailinator.com&password=apitest' | python3 -c "import sys,json;print(json.load(sys.stdin)['token'])")

# Fetch a competition by natural key: /api/x/{year}/{country}/{slug}/
curl "https://test-data.opentrack.run/api/x/2026/GBR/lac-open-2/" \
  -H "Authorization: Token $TOKEN"

# List the events in that competition
curl "https://test-data.opentrack.run/api/x/2026/GBR/lac-open-2/event/" \
  -H "Authorization: Token $TOKEN"
import requests

# Obtain a token first
resp = requests.post("https://test-data.opentrack.run/api/get-auth-token/",
                     data={"username": "api-test@mailinator.com",
                           "password": "apitest"})
token = resp.json()["token"]

headers = {"Authorization": f"Token {token}"}

# Fetch a competition by natural key: /api/x/{year}/{country}/{slug}/
r = requests.get("https://test-data.opentrack.run/api/x/2026/GBR/lac-open-2/",
                 headers=headers)
comp = r.json()
print(f'{comp["date"]} - {comp["full_name"]} ({comp["country"]})')

# List the events in that competition
r = requests.get("https://test-data.opentrack.run/api/x/2026/GBR/lac-open-2/event/",
                 headers=headers)
for ev in r.json()["results"]:
    print(f'{ev["event_id"]} - {ev["name"]}')

Example output:

2026-06-19 - Livingston Open Meeting (GBR)
F01 - Long Jump | U16-SEN
F02 - Long Jump | U12
F03 - Long Jump | U14
T01 - 150m | U12
...


API Playground

The API uses Django REST Framework's browsable API interface, which provides an interactive playground when accessed via a web browser. The playground allows you to:

  • Filter competitions using interactive form controls
  • Search across competition names
  • Order results by various fields
  • Test different pagination limits
  • View results in JSON or HTML format
  • Try different HTTP methods (GET, POST, etc.)

To access the playground, simply navigate to the API URL while logged in with the appropriate credentials.


HTTP Methods

Method Endpoint Description
GET /api/competitions/ List all competitions (paginated)
POST /api/competitions/ Create a new competition
GET /api/competitions/{uuid}/ Retrieve a specific competition
PUT /api/competitions/{uuid}/ Fully update a specific competition
PATCH /api/competitions/{uuid}/ Partially update a specific competition
DELETE /api/competitions/{uuid}/ Delete a specific competition
GET /api/x/{year}/{country}/{slug}/ Retrieve a competition by natural key

Natural Key URL Pattern

Competitions can be referenced by their UUID, but there is also a much more readable natural key URL pattern based on the competition's year, country and slug:

/api/x/{year}/{country}/{slug}/

For example:

https://test-data.opentrack.run/api/x/2026/GBR/lac-open-2/

Example URLs use the test server

The example URLs in this section deliberately point at the test server (test-data.opentrack.run) so you can experiment with write operations (PATCH, PUT, DELETE) without risking live data. Use the live server domain or federation domain when you are ready to make real changes.

The three components are:

Component Example Description
year 2026 The year of the competition (4 digits)
country GBR The ISO 3-letter country code
slug lac-open-2 The competition's URL slug

The natural key is unique for every competition, and is also the basis for the events and units API URLs, which are nested under it:

/api/x/{year}/{country}/{slug}/event/
/api/x/{year}/{country}/{slug}/event/{event_id}/
/api/x/{year}/{country}/{slug}/event/{event_id}/rounds/

The natural key is especially useful when you know the competition you want to work with (e.g. you can read it straight from the competition's public URL) and want to avoid looking up its UUID first.

Demo competitions

Competitions set up as demos (the is_demo flag) are excluded from list endpoints — they do not appear in /api/competitions/ or any filtered list, so they never clutter browsing or search for real users. They are still retrievable directly by their exact natural key (/api/x/{year}/{country}/{slug}/), because a natural-key fetch is an explicit lookup for a known competition, not a discovery query. So a demo competition's data (and its events/units) is reachable if you know its URL, but it will not show up in lists.


Response Fields

Each competition record in the response contains the following fields:

Basic Information

Field Type Description
url URL Link to this specific competition record
full_name String Full name of the competition
short_name String Short/abbreviated name
name_local String Localised name in the native language
name_local_short String Short localised name
slug String URL slug identifier
year Integer Year of the competition

Dates

Field Type Description
date Date Start date of the competition (e.g., "2025-01-17")
finish_date Date End/finish date of the competition
created Datetime Timestamp when the competition was created

Location & Venue

Field Type Description
venue URL Link to the venue detail endpoint (nullable)
address String Street address of the venue
city String City where the competition is held
country String ISO country code (e.g., "GBR", "SAU", "USA")
latitude Decimal Latitude coordinate (nullable)
longitude Decimal Longitude coordinate (nullable)
altitude Integer Altitude in metres (nullable)

Type & Classification

Field Type Description
type String Competition type: TRACK, ROAD, CROSSCOUNTRY, INDOOR, WALK, VIRTUAL, or empty
wa_rankings_category URL Link to the World Athletics rankings category/level (nullable)
wa_id String World Athletics identifier (nullable)

Organiser & Contact

Field Type Description
organiser URL Link to the organising club/org detail endpoint (nullable)
contact_name String Name of the contact person
contact_details String Contact details (email, phone, etc.)

Description

Field Type Description
basic_description String Short description of the competition
summary_text String HTML summary text with full details

Statistics (Read-Only)

Field Type Description
num_competitors Integer Number of competitors entered (read-only)
num_results Integer Number of results recorded (read-only)
Field Type Description
home_page_url URL Link to the competition's public home page

Fetching Competitions

List All Competitions

GET /api/competitions/

Returns a paginated list of competitions.

Retrieve a Specific Competition

By natural key (recommended):

GET /api/x/{year}/{country}/{slug}/

Example: GET /api/x/2026/GBR/lac-open-2/

Returns a single competition record by its natural key (year, country, slug).

By UUID:

GET /api/competitions/{uuid}/

Example: GET /api/competitions/00042340-ea29-41f4-9e26-05732e20b6c9/

Returns a single competition record by its UUID. Both patterns return the same competition record.


Creating Competitions

Create a New Competition

POST /api/competitions/

Requires authentication. The request body should be a JSON object with the relevant fields.

Permission required

Your account must have explicit permission to create competitions for the competition's country (granted by OpenTrack or your federation), or have federation admin rights. Contact OpenTrack if you are not sure your account has the necessary permissions.

Example:

{
    "full_name": "My Track Meet 2026",
    "short_name": "MTM 2026",
    "date": "2026-06-15",
    "finish_date": "2026-06-15",
    "type": "TRACK",
    "country": "GBR",
    "city": "London",
    "address": "London Stadium, Queen Elizabeth Olympic Park",
    "basic_description": "An open track meet for all ages"
}

Updating Competitions

Full Update (PUT)

PUT /api/competitions/{uuid}/

Replaces the entire competition record. All required fields must be provided.

Partial Update (PATCH)

PATCH /api/competitions/{uuid}/

Only updates the fields provided in the request body.

Example - Update competition name and date:

{
    "full_name": "My Track Meet 2026 - Rescheduled",
    "date": "2026-07-01",
    "finish_date": "2026-07-01"
}

Deleting Competitions

Delete a Competition

DELETE /api/competitions/{uuid}/

Deletes the competition and all associated data (events, entries, results). This action is irreversible.


Filtering

You can filter the competitions list using the following query parameters:

Parameter Type Description Example
country String Filter by ISO country code ?country=GBR
type String Filter by competition type ?type=TRACK
year Integer Filter by competition year ?year=2025
date Date Filter by exact start date ?date=2025-01-17
when String Filter by timeframe (future, past) ?when=future
my_competitions Flag Scope to competitions you administer ?my_competitions=1

Filter Examples

Get all competitions in the UK:

/api/competitions/?country=GBR

Get all track competitions in 2025:

/api/competitions/?type=TRACK&year=2025

Get upcoming competitions (future dates):

/api/competitions/?when=future

Get past road races:

/api/competitions/?type=ROAD&when=past


Searching

The API supports text search across competition names using the search parameter:

Parameter Description Example
search Search in full name, short name, and local name fields ?search=championships

Search Example

Find all competitions with "marathon" in the name:

/api/competitions/?search=marathon


Ordering

You can order the results using the ordering parameter. Prefix with - for descending order.

Field Description
date Order by start date
-date Order by start date (descending, most recent first)
full_name Order by full name (A to Z)
-full_name Order by full name (Z to A)
year Order by year
-year Order by year (descending)
created Order by creation date
-created Order by creation date (most recently created first)

Default ordering: -date (most recent first)

Ordering Examples

Order by date (oldest first):

/api/competitions/?ordering=date

Order by date (most recent first):

/api/competitions/?ordering=-date

Order by name:

/api/competitions/?ordering=full_name

Order by most recently created:

/api/competitions/?ordering=-created


Pagination

The API uses limit/offset pagination to control the number of results returned.

Parameter Type Description Default
limit Integer Number of records to return 50
offset Integer Starting position in the result set 0

Pagination Examples

Get the first 10 competitions:

/api/competitions/?limit=10

Get competitions 21-30 (second page of 10):

/api/competitions/?limit=10&offset=20

Get 100 competitions in the UK:

/api/competitions/?limit=100&country=GBR


Response Structure

Paginated responses include:

{
  "count": 14677,
  "next": "https://test-data.opentrack.run/api/competitions/?limit=50&offset=50",
  "previous": null,
  "results": [
    {
      "url": "https://test-data.opentrack.run/api/competitions/00042340-ea29-41f4-9e26-05732e20b6c9/",
      "venue": null,
      "created": "2021-06-16T18:26:08+01:00",
      "full_name": "Jeugdmedaillemeeting - Kan/Ben - AFGELAST !!!",
      "short_name": "Jeugdmedaillemeeting - Kan/Ben - AFGELAST !!!",
      "name_local": "",
      "name_local_short": "",
      "slug": "21329",
      "address": "Atletiekweg, 9400 Ninove",
      "city": "",
      "date": "2021-05-24",
      "finish_date": "2021-05-24",
      "type": "",
      "latitude": 50.82768,
      "longitude": 4.01302,
      "altitude": null,
      "wa_id": null,
      "year": 2021,
      "basic_description": "",
      "summary_text": "",
      "contact_name": "",
      "contact_details": "",
      "num_competitors": 0,
      "num_results": 0,
      "country": "BEL",
      "wa_rankings_category": null,
      "organiser": null,
      "home_page_url": "https://test-data.opentrack.run/en-gb/x/2021/BEL/21329/"
    }
  ]
}
  • count: Total number of results available
  • next: URL for the next page (null if on last page)
  • previous: URL for the previous page (null if on first page)
  • results: Array of competition records for the current page

Combined Query Example

Get the first 20 upcoming track competitions in Great Britain:

/api/competitions/?country=GBR&type=TRACK&when=future&limit=20

Get all cross country competitions from 2024 onwards, ordered by date:

/api/competitions/?type=CROSSCOUNTRY&year__gte=2024&ordering=date

Get past road races in the USA with athlete results:

/api/competitions/?country=USA&type=ROAD&when=past&num_results__gt=0


Permissions

All API endpoints require authentication — there are no public endpoints. Log in with a valid API token or session cookie to access them.

Access Level Permission
Authenticated user Read access — list all competitions and view any competition's details
Competition Director/Admin Full CRUD access to competitions they manage, but write operations (POST/PUT/PATCH/DELETE) are only permitted until 7 days after the competition finishes
Federation Admin Access to all competitions within their federation

Permissions by Method

Method Permission Required
GET (list) Any authenticated user
GET (detail) Any authenticated user
POST Director/Admin of the competition (or federation admin for their federation), within 7 days after the competition finishes
PUT / PATCH Director/Admin of the competition (or federation admin for their federation), within 7 days after the competition finishes
DELETE Director/Admin of the competition (or federation admin for their federation), within 7 days after the competition finishes

Notes

  • Competitions are identified by UUID (e.g., 00042340-ea29-41f4-9e26-05732e20b6c9/) in the standard API, or by their natural key (/api/x/{year}/{country}/{slug}/), which is more readable and is recommended when you know the competition you want
  • The type field uses OpenTrack's internal competition type constants (TRACK, ROAD, CROSSCOUNTRY, INDOOR, WALK, VIRTUAL)
  • Federation-specific API URLs (e.g., https://saaf.opentrack.run/api/competitions/) will automatically filter results to competitions within that federation's country
  • The playground interface is only available when accessing via a web browser with proper authentication