Querying the API¶
Filtering Results¶
The API supports filtering for measurements, sessions, and laps using query parameters. Filters can be applied by time range, exercise type, measurement type, sports discipline, or event type. Multiple filters can be combined in a single request.
Filter Parameters for Measurements¶
| Parameter | Format | Description |
|---|---|---|
fromTime |
RFC3339 (ISO 8601) | Return measurements that start at or after the specified time |
toTime |
RFC3339 (ISO 8601) | Return measurements that start before the specified time |
exerciseType |
String | Filter by exercise title (e.g., "Football", "Training") |
measurementType |
Enum | Filter by measurement category (see Measurement Types) |
sportsType |
String (comma-separated) | Filter by sports discipline (e.g., "football,iceHockey") |
eventType |
String (comma-separated) | Filter by event category (e.g., "game,training") |
Filter Parameters for Sessions¶
| Parameter | Format | Description |
|---|---|---|
fromTime |
RFC3339 (ISO 8601) | Return sessions that start at or after the specified time |
toTime |
RFC3339 (ISO 8601) | Return sessions that start before the specified time |
type |
String | Filter by session type (session title) |
sportsType |
String (comma-separated) | Filter by sports discipline (e.g., "football,iceHockey") |
eventType |
String (comma-separated) | Filter by event category (e.g., "game,training") |
Filter Parameters for Laps¶
| Parameter | Format | Description |
|---|---|---|
fromTime |
RFC3339 (ISO 8601) | Return laps that start at or after the specified time |
toTime |
RFC3339 (ISO 8601) | Return laps that start before the specified time |
Time format
All time parameters use RFC3339 format (ISO 8601): YYYY-MM-DDTHH:MM:SSZ
Example: 2024-02-01T12:00:00Z represents February 1st, 2024 at 12:00 PM UTC
Measurement Types¶
The measurementType parameter is a fundamental categorization that determines how Firstbeat Sports processes and analyzes a measurement. This filter only applies to measurements (not sessions or laps).
| Value | Description |
|---|---|
exercise |
Regular measurement from training, games, etc. |
quickRecoveryTest |
Short measurement used for estimating an athlete's recovery level |
night |
Long, often overnight measurement for stress and recovery |
manual |
Manual record that contains no device data |
Filtering Examples¶
Filter measurements by time range¶
Retrieve all measurements for an athlete between February 1-7, 2024:
GET https://api.firstbeat.com/v1/sports/accounts/{accountId}/athletes/{athleteId}/measurements?fromTime=2024-02-01T00:00:00Z&toTime=2024-02-08T00:00:00Z
Filter by measurement type¶
Get quick recovery tests for athlete:
GET https://api.firstbeat.com/v1/sports/accounts/{accountId}/athletes/{athleteId}/measurements?measurementType=quickRecoveryTest
Filter sessions by sports type¶
Retrieve all football sessions for a team:
GET https://api.firstbeat.com/v1/sports/accounts/{accountId}/teams/{teamId}/sessions?sportsType=football
Combine multiple filters¶
Get football sessions for January 2024:
GET https://api.firstbeat.com/v1/sports/accounts/{accountId}/teams/{teamId}/sessions?sportsType=football&eventType=game&fromTime=2024-01-01T00:00:00Z&toTime=2024-02-01T00:00:00Z
Sports Type and Event Type¶
Measurements and sessions can be categorized based on sports discipline and type of event. Availability of this data depends on data tagging done by Coaches.
Getting current values via API
The authoritative list of valid values can be retrieved from:
- Sports types:
GET https://api.firstbeat.com/v1/sports/sports-types - Event types:
GET https://api.firstbeat.com/v1/sports/event-types
Event Type¶
Event type indicates what kind of event the measurement is from. Possible values:
- race
- game
- rehab
- recovery
- training
Sports Type¶
Sports type indicates the sports discipline practised during the measurement. The list of sports types is hard coded in the system and will get periodic updates, but users cannot add custom sports types.
Possible values:
- football
- americanFootball
- rugbySevens
- rugbyUnion
- rugbyLeague
- fieldHockey
- iceHockey
- ringette
- baseball
- basketball
- futsal
- volleyball
- beachVolleyball
- floorball
- handball
- lacrosse
- softball
- gaelicFootball
- australianFootball
- cricket
- tennis
- badminton
- squash
- ultimate
- trailRunning
- running
- treadmillRunning
- orienteering
- strength
- cardio
- xcSkiing
- biathlon
- roadCycling
- indoorCycling
- mountainBiking
- bmx
- alpineSkiing
- swimming
- walking
- nordicWalking
- snowboarding
- rowing
- mountaineering
- hiking
- multisport
- triathlon
- golf
- inlineSkating
- climbing
- iceSkating
- taekwondo
Pagination¶
When a response from the API contains more than 1000 results, the API automatically paginates and returns only the first 1000 results. The response includes a "more" attribute to indicate whether additional results are available.
Pagination summary
- Default page size: 1000 results
- Pagination triggers when total results exceed 1000
- Use
offsetparameter to retrieve subsequent pages - Offset value should equal the number of results already retrieved
How Pagination Works¶
To retrieve all results:
- Make an initial request without an
offsetparameter or useoffset=0 - Check the
"more"field in the response - If
"more": true, make another request with?offset=1000or the count of results received - Repeat until
"more": falseor the field is absent
Example Response¶
Example response showing more results are available:
GET https://api.firstbeat.com/v1/sports/accounts/{accountId}/athletes/{athleteId}/measurements?offset=1000
{
"more": true,
"measurements": [
{
"athleteId": 416370,
"endTime": "2022-01-03T17:28:15Z",
"exerciseType": "XC Ski",
"measurementId": 8885319,
"sessionId": 0,
"startTime": "2022-01-03T15:53:09Z"
}
// ... additional results
]
}
Code Example¶
Here's a Python example showing how to retrieve all measurements for an athlete using pagination:
Note
This example is simplified to help understand how the pagination works. Production code should also handle authentication, rate limiting, error handling, and retries.
def fetch_all_measurements(account_id, athlete_id):
"""Simplified example showing pagination logic."""
base_url = f"https://api.firstbeat.com/v1/sports/accounts/{account_id}/athletes/{athlete_id}/measurements"
all_measurements = []
offset = 0
while True:
# Build URL with offset parameter (skip for first request)
url = f"{base_url}?offset={offset}" if offset > 0 else base_url
# Make API request with authentication headers
response = requests.get(url, headers=get_auth_headers())
data = response.json()
# Add measurements from this page to our collection
all_measurements.extend(data.get("measurements", []))
# Check if more results are available
if not data.get("more", False):
break
# Increment offset for next page
offset += len(data.get("measurements", []))
return all_measurements
Decoding Time Series Data¶
By default, Cloud API returns time series data in zlib compressed and Base64-encoded format.
GET https://api.firstbeat.com/v1/sports/accounts/{accountId}/athletes/{athleteId}/measurements/{measurementId}/results?var=artifactCorrectedRrVector
{
"athleteId": 416370,
"endTime": "2025-10-16T06:41:04Z",
"measurementId": 14522946,
"measurementType": "quickRecoveryTest",
"sessionId": 0,
"startTime": "2025-10-16T06:38:04Z",
"variables": [
{
"bits": 64,
"name": "artifactCorrectedRrVector",
"type": "Float",
"unit": "ms",
"value": "eJx1lE1IVFEUx6cPYUgXLipeMJFBCwNDoQLBJ5w2MlSQhJto0yhCX0TuBgRtEcPYu19Ri1lkFEi4kIwQmlbJbBKKnljgbPogyIZWAy9pCJR43P958S44m9+cd88595z/OVwyc5n4R2YJXACfgBXQB/ssdTXGLtJ1S5PB905LWQdXLdUVsAw/zlNGnnnQyauX4XcVNpPjbuPcgA3Uk0vXa3pw3kJcw7nvDs6LsAn1cv1NnGfBLpDjKum6Ej1Ql/HAXLoe0wFm0rbGvRrfVQMchq5VsAh2pymgi8D8BL4H0DNAfwGfYz6S++Z5tdJM9OF+Wf8V2E2nP+4LuhnoZvodPY4hT9O5h/eC51t17s2kqVbAb47NewT9knjkN3tRR6dTx/IO93KeLkenPHSELTF3wcw7NuYqy04c7lfYX8VzRl/yc8krlA6RXCjEf0hO+lHo/yZ51iuUvFGSXhT60SqJn6EfhYMkyjvsRdbZD+QPoFuA+sTFjefXNxZJzPSubfV+JPGm+EcXWyQ2a7mjtRzJnnZaaj9DcnRkfGhknGRldqY+e4/kBxun2mycGrBxasLGqXkbp77YOJ6bnv70/fLjLdIPsgfUWh/pZwP5WtsY6de3Jjf7K6TfP13svvGO9NfYb5t0ZP3MnsNzhd0vyXS8Gvz76DyZg8PrD0//IHPk18SJcIrM8bv73l7zyJyEnw+/IfhdiP2myVyC3xj8bsZ+5/6/f/yu8D6fsry/Hzb0S95P3nN+P1rpvUv2i/t/kfr+D34sRjI="
}
]
}
To decompress and decode the data, you have two options:
Server-side decoding¶
Use the format=list parameter to decompress and decode the data on the server.
GET https://api.firstbeat.com/v1/sports/accounts/{accountId}/athletes/{athleteId}/measurements/{measurementId}/results?var=artifactCorrectedRrVector&format=list
{
"athleteId": 416370,
"endTime": "2025-10-16T06:41:04Z",
"measurementId": 14522946,
"measurementType": "quickRecoveryTest",
"sessionId": 0,
"startTime": "2025-10-16T06:38:04Z",
"variables": [
{
"bits": 64,
"name": "artifactCorrectedRrVector",
"type": "Float",
"unit": "ms",
"value": [
1065,
1069,
1067,
1064,
1062,
1039,
1036,
1015.0000000000001,
1019.0000000000001,
1024,
994,
955,
954,
972,
977
]
}
]
}
(additional values omitted for brevity)
Client-side decoding¶
The time series value field is:
zlibcompressed- Base64-encoded
See the sample code repository for a working example: timeseries_decode.
What decoding option to use?
Using format=list parameter is fine, but decoding the data on the client-side is preferred to save bandwidth and avoid possible problems of hitting the max 6MB response payload size.