Skip to content

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 offset parameter to retrieve subsequent pages
  • Offset value should equal the number of results already retrieved

How Pagination Works

To retrieve all results:

  1. Make an initial request without an offset parameter or use offset=0
  2. Check the "more" field in the response
  3. If "more": true, make another request with ?offset=1000 or the count of results received
  4. Repeat until "more": false or 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
Example API response with pagination
{
    "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.

Retrieve all measurements using pagination
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:

  1. zlib compressed
  2. 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.