Old API overview¶
These examples show how to authenticate and give a few examples for working with our old APIs. This won't be supported forever, so please switch over to the new approach
Old APIs, case and style difference¶
Since summer 2020, OpenTrack is using a new API gateway at https://test-api.opentrack.run/ (remove the "test-" to work on live).
This uses the FastAPI web framework, connected to the main OpenTrack application database. This implements the OpenAPI specification, so there is a rich family of tools to help you use it.
We are also exporting static files nightly, initially competition calendars such as the file which powers the European Athletics web calendar; these are the same json as retrieved through the API
Prior even to that, we had an old API for downloading results, and one endpoint for uploading results; two federations have written code to export against this. We used 'camelCase' variables because we were advised this was more normal in the Javascript world, but this created headaches.
However, internally our databasec and Django code uses the under_score_separated
convention, and the API tools work with this automatically, so all APIs going forward will use the new style
Remember:
On data.opentrack.run -> 'fullName', 'ageGroups' etc
On api.opentrack.run -> 'full_name', 'age_groups' etc
On file.opentrack.run (static exports): -> 'full_name', 'age_groups' etc
Getting access¶
To access the API, you need an account on OpenTrack, so if you have not used it before, go to our site and sign up. The API generates a documentation page which you can click on and explore from a browser, to try the various queries. This is available in Swagger and ReDoc formats; we use the first one in screenshots below.
Connecting and making queries¶
We have illustrated our examples with the Unix CURL command, but you can also call APIs with wget
or libraries in any language.
A very simple query you can do is to call our 'ping' API, to check it's alive; this requires no authentication:
$ curl -X GET "https://test-api.opentrack.run/api/v1/ping/" -H "accept: application/json"
{
"reply": "pong",
"enviroment": "otr_0"
}
Or, with Python's requests
library,
Authorizing and getting a token¶
Almost all API calls require a token. You make an initial request for a token, sending your username and password; and then use this token as a request header on subsequent requests. Tokens are valid for 24 hours.
Here is a complete runnable script to query competitions, with some filter parameters, using a token, and Python's requests
library.
import requests
EMAIL = '<your email>'
PASSWORD = '<your password>'
r = requests.post(
"https://test-api.opentrack.run/api/v1/auth/token",
data={"username": EMAIL, "password": PASSWORD})
resp = r.json()
token = resp["access_token"]
headers = {'Authorization': 'Bearer %s' % token}
r = requests.get(
"https://test-api.opentrack.run/api/v1/competitions/",
params=dict(country="MLT", from_date="2020-09-01"),
headers=headers
)
competitions = r.json()
print("Retrieved %d competitions in Malta" % len(competitions))
API Examples¶
If you visit opentrack-docs/api_examples/ you will see several files, the code in the above example can be run by calling
python
import authorise_api
authorise_api.example_test()
Alternatively there are several other tests that can be run detailed below, however before running them there is something important to do and to know.
1. For testing purposes make sure to use test-api.opentrack.run instead of api.opentrack.run, this will make sure you don't accidently delete anything important.
2. Create a file in the /api_examples/ folder called secrets.py containing the following 2 lines, this will be needed for testing, just fill in your email and password.
EMAIL = '<your email>'
PASSWORD = '<your password>'
Querying competition calendar entries¶
Our competition calendar has light, simple records for each competition. You can query these easily with request parameters. For example, this returns all competitions in Norway since 1st August 2020:
GET https://test-api.opentrack.run/api/v1/competitions?country=MLT&from_date=2020-08-01&to_date=2020-08-10
[
{
'full_name': '2020 MAAA Championships Young Athletes / Challenge 2 Senior',
'short_name': 'MAAA Champ Young - Chall 2 Sen',
'slug': 'championships-young-20-chal-2',
'name_local': '',
'country_id': 'MLT',
'address': '',
'city': '',
'venue_id': 'ebd3ec4b-4782-41ca-9895-3c298971c711',
'latitude': None,
'longitude': None,
'altitude': None,
'date': '2020-08-01',
'finish_date': '2020-08-02',
'wa_rankings_category_id': 15,
'age_groups': ['U12,U14,U16,U18,U20,U23,SEN'],
'national_id': '',
'basic_description': '',
'contact_details': '',
'organiser_id': '19c65443-9b0f-444d-b874-1e74d97310fb',
'website': None,
'entry_link': None,
'results_link': None,
'override_token': None,
'id': '0279cc68-ccff-4ca3-bd1d-0da86fa05cc0',
'year': 2020,
'events': None
},
.... # competitions omitted
]
Alternatively run python get_competitions.py whilst in the /api_examples/ directory after having set up the secrets.py file described previously to run a get request for some Malta competitions.
If you wish to power a calendar and load data without authenticating, we also offer files built every night and stored in Amazon in exactly the same format. We publish these for the CURRENT and FOLLOWING year.
https://file.opentrack.run/live/euroath/european_calendar_2020.json
https://file.opentrack.run/live/euroath/european_calendar_2021.json
https://file.opentrack.run/live/euroath/domestic_calendar_GBR_2020.json
https://file.opentrack.run/live/euroath/domestic_calendar_GBR_2021.json
These are suitable for embedding or calling from other off-site pages (i.e. the storage bucket has no CORS headers), and will be available even when we are doing server maintenance
Creating new competitions and calendar entries¶
We can expose the API to national-level systems providers. In many countries (e.g. Germany, Spain, Italy, France) there is a "national system" which contains most or all competitions; we aim to make it easy for these people to register a competition in Opentrack, tell us their ID, and get our ID for the competition.
Your user account needs to be given admin privileges for the country in question. We do ths by assigning your user to a group called ADMIN_XXX on the server, where XXX is the ISO country code. Thus, if you want rights for Estonia, your user must be in the ADMIN_EST group.
Conceptually there MIGHT be a two-step process, although it is usually one, as we need to check very carefully that we are not creating duplicates.
The following example can be called from the opentrack-docs/api_examples directory by calling python create_competition_and_calendar_entries.py after having activated your virtual environment and creating the secrets.py file described in step 2 of API Examples
Example¶
import requests
import json
EMAIL = '<your email>'
PASSWORD = '<your password>'
r = requests.post(
"https://test-api.opentrack.run/api/v1/auth/token",
data={"username": EMAIL, "password": PASSWORD})
resp = r.json()
token = resp["access_token"]
headers = {'Authorization': 'Bearer %s' % token}
comp = {
"full_name": "EAP - Malta International Meet",
"short_name": "",
"slug": "malta-inter-meet",
"name_local": "",
"country_id": "MLT",
"address": "Marsa Sports Complex MRS 9065 Aldo Moro Road, Marsa, Malta 12. Matthew Micallef St John Stadium Mars",
"city": "",
"venue_id": None,
"latitude": None,
"longitude": None,
"altitude": None,
"date": "2021-05-08",
"finish_date": "2021-05-08",
"wa_rankings_category_id": 10,
"age_groups": None,
"national_id": "",
"basic_description": "",
"contact_details": "malta@eap-circuit.org",
"organiser_id": "19c65443-9b0f-444d-b874-1e74d97310fb",
"website": None,
"entry_link": None,
"results_link": None,
"override_token": None,
"id": "ef59d4b4-4d16-49ae-b824-7a23e8a0027d",
"year": 2021,
"events": []
}
r = requests.post(
"https://test-api.opentrack.run/api/v1/competitions/",
data=json.dumps(comp),
headers=headers
)
print("Created competiton with status_code %d" % r.status_code)
parsed = json.loads(r.text)
print(json.dumps(parsed, indent=4, sort_keys=False))
Duplicates¶
As mentioned before, the API carefully checks there are not similar competitions already in our database. If it is the case, a special error message will be returned.
{
"detail": {
"error": "A competition with the same name and date exists",
"override_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE2MjgzNDc1NjkuOTgxODY3LCJuYmYiOjE2MTI3OTkxNjl9.6c0UtY6TM4-3aZf1Zo51M05IFr5HDVEaLdXSIiJH7LQ",
"mathing_competitions": [
{
"full_name": "EAP - Malta International Meet",
"short_name": "",
"slug": "malta-inter-meet",
"name_local": "",
"country_id": "MLT",
"address": "Marsa Sports Complex MRS 9065 Aldo Moro Road, Marsa, Malta 12. Matthew Micallef St John Stadium Mars",
"city": "",
"venue_id": null,
"latitude": null,
"longitude": null,
"altitude": null,
"date": "2021-05-08",
"finish_date": "2021-05-08",
"wa_rankings_category_id": 10,
"age_groups": null,
"national_id": "",
"basic_description": "",
"contact_details": "malta@eap-circuit.org",
"organiser_id": "19c65443-9b0f-444d-b874-1e74d97310fb",
"website": null,
"entry_link": null,
"results_link": null,
"override_token": null,
"id": "ef59d4b4-4d16-49ae-b824-7a23e8a0027d",
"year": 2021,
"events": null
}
]
}
}
If this happens you have two options.
- Option 1: the competition you wanted to create is a duplicate.
Use the provided id (
ef59d4b4-4d16-49ae-b824-7a23e8a0027d
in the example) and use one of the other API endpoints to update the competition - Option 2: the competition you wanted to create is new.
Use the provided override_token (
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE2MjgzMzY1MjAuMDUyOTQxLCJuYmYiOjE2MTI3ODgxMjB9.qmDtJvolitfcQ8YDyst2f3b1yAUqvGF5mhcjGbA_SBg
in the example) and add it as a new field in the comp dictionary above. NOTE: the token has a 3 days validity.
Query, Update, Delete a known competition¶
If you know the id of a competition, you can interact directly with the competition.
Query a competition¶
import requests
EMAIL = '<your email>'
PASSWORD = '<your password>'
r = requests.post(
"https://test-api.opentrack.run/api/v1/auth/token",
data={"username": EMAIL, "password": PASSWORD})
resp = r.json()
token = resp["access_token"]
headers = {'Authorization': 'Bearer %s' % token}
comp_id = "868aadc8-f9bb-49bc-952f-25c16eadb69e"
r = requests.get(
f"https://test-api.opentrack.run/api/v1/competitions/{comp_id}",
headers=headers
)
Update a competition¶
An important part is to remember to get the id of the country based on how it is on the competition url. So if your competition has /year/country_id/slug/ in the url on our website, you need to use the 3 letters in that url where country_id is within update_comp below, replacing id_of_country.
import requests
import json
EMAIL = '<your email>'
PASSWORD = '<your password>'
r = requests.post(
"https://test-api.opentrack.run/api/v1/auth/token",
data={"username": EMAIL, "password": PASSWORD})
resp = r.json()
token = resp["access_token"]
headers = {'Authorization': 'Bearer %s' % token}
update_comp = {
'full_name': 'new_name',
'country_id': 'id_of_country'
}
comp_id = "868aadc8-f9bb-49bc-952f-25c16eadb69e"
r = requests.post(
f"https://test-api.opentrack.run/api/v1/competitions/{comp_id}",
data=json.dumps(update_comp),
headers=headers
)
Delete a competition¶
import requests
EMAIL = '<your email>'
PASSWORD = '<your password>'
r = requests.post(
"https://test-api.opentrack.run/api/v1/auth/token",
data={"username": EMAIL, "password": PASSWORD})
resp = r.json()
token = resp["access_token"]
headers = {'Authorization': 'Bearer %s' % token}
comp_id = "868aadc8-f9bb-49bc-952f-25c16eadb69e"
r = requests.delete(
f"https://test-api.opentrack.run/api/v1/competitions/{comp_id}",
headers=headers
)
Test hardness endpoint¶
We provide a test endpoint to check whether your input respects our competition schema. The API call does not create a database entry, so feel free to use it intensively.
import requests
import json
EMAIL = '<your email>'
PASSWORD = '<your password>'
r = requests.post(
"https://test-api.opentrack.run/api/v1/auth/token",
data={"username": EMAIL, "password": PASSWORD})
resp = r.json()
token = resp["access_token"]
headers = {'Authorization': 'Bearer %s' % token}
comp = {
'full_name': 'Trond Mohn Games',
'short_name': 'TMG',
'slug': 'trond-mohn-games',
'name_local': 'Trond Mohn Games',
'country_id': 'NOR',
'address': 'Grimseidvegen 60, 5239 RĂ¥dal, Norge',
'city': 'Bergen',
'venue_id': 'c3c87364-0ab4-44b5-a518-b143f574c086',
'latitude': 60.2905,
'longitude': 5.3178,
'altitude': 60,
'date': '2021-05-29',
'finish_date': '2021-05-29',
'wa_rankings_category_id': None,
'age_groups': ['Men, women'],
'national_id': 'NOR',
'basic_description': '',
'contact_details': 'Dag Rydland drydland@broadpark.no',
'organiser_id': 'e893fa86-8c2e-4f99-a9f1-b6fcfb0a787c',
'website': 'https://www.trondmohngames.no',
'entry_link': 'http://www.trondmohngames.no',
'results_link': 'http://en.trondmohngames.no/live-results/'
}
r = requests.post(
"https://test-api.opentrack.run/api/v1/competitions/test",
data=json.dumps(comp),
headers=headers
)