Firstbeat Cloud API (1.0.0)

Download OpenAPI specification:Download

Overview

This page contains the documentation on how to access First Sports data via API.

First Steps

As a first step, please carefully read through this document.

Is API the right choice for me?

If you are unsure what the Sports API can do and how it works, please contact sports-cloud-api@firstbeat.com. There are use cases that the API does not support and it is better to check your requirements with us before starting the implementation of your API client.

Sports API is available for Sports Premium+ customers.

An lternative method for getting data out from Firstbeat Sports is the Data Export functionality in Sports Cloud (premium feature).

Possible limitations to be aware of:

  • Some automated tools might not work out of the box with the encoded and compressed query results or are not able to generate the needed API tokens.
  • The concepts used in your software might be different (measurement, session, etc.) and mapping of the query results might not be straightforward.
  • All metrics in the Firstbeat Sports are not available via API. Please refer to this documentation for the list of available metrics.
  • All metric names in the Sports API and Cloud Data export are not the same.

Getting Support

In case you have any questions about the Sports API please contact sports-cloud-api@firstbeat.com. We are happy to help you with any questions you might have.

For general Firstbeat Sports questions, please contact support@firstbeat.com.

Trying and Testing the Sports API

It is possible to try the Sports API with a test account. Registering as an API user is needed for a test account, too.

After registering as an API user, you will also get access to a test account that you can use for development and testing purposes.

You will receive an e-mail after you have been granted access to a test account (APITEST) with consumerName and id.

Test Account is a sandbox meant only for testing purposes.

Please see the Getting Started guide in this documentation on how to register as an API consumer.

Getting Started

Registering as a new API Consumer

To get started, you need to register as a Sports API consumer.

First, you need to select your API consumerName and then make an API request to account/register endpoint to create id and sharedSecret.

Your API consumerName can be anything but please use something that resembles your team or organization name. Later, your API consumerName will be visible in the Sports Cloud.

Base URI of the API is:

https://api.firstbeat.com/v1/

Example:

curl 'https://api.firstbeat.com/v1/account/register' \
    --data '{"consumerName": "your_api_consumer_name"}' \
    --header 'Content-Type:application/json'

On Windows command prompt you need a workaround for the single quotes:

curl -d "{"consumerName": "your_api_consumer_name"}" https://api.firstbeat.com/v1/account/register -H "Content-Type: application/json"

After a successful API call you should get a response similar to:

{ "id": "87a05c83-d5b7-46ba-aa4a-32f56cd284d5", "consumerName":"your_api_consumer_name", "sharedSecret":"8d5b6d12-61c5-4303-9ae3-c1837a15034b" }`
  • The generated id field is the primary field used for identifying you as an API user.

  • sharedSecretis used later for generating a token to access the API.

Please store this information securely.

Note: You can’t make requests to Sports API yet. We need to approve your account first. Also, you need to create JWT Token and API keys (see next steps).

When you have completed the registration, please copy and paste the consumerName and id field to email and send them to sports-cloud-api@firstbeat.com. The id field is used to approve your API account.

After you have received an e-mail that your id has been approved by the Sports API Support, you are ready to proceed to the next step.

Approve API Consumer Access to Your Account Data

Next, your API consumer needs to be granted access to the Sports account you are accessing with your API client. This is done at Sports Cloud.

Successful requests to API cannot be made before completing this step.

If you don’t have access to Sports Cloud, please ask a person who owns the account to complete the steps below.

In Sports Cloud, do the following:

  1. Click the settings menu on the top left corner of the screen. Go to the Cloud API section of the screen.

  2. Read and accept the license agreement.

  3. Select the API consumer from the list to grant access to account data (select the account checkbox).

  4. Finally, save settings.

After the access has been approved, you can proceed to create JWT Tokens and adding an API Key.

Creating a JWT Token

The API token is needed for creating an API key and for making request to the Sports API.

Every Firstbeat Cloud API endpoint (except /register) will require authentication in the form of JWT Token (JSON Web Token) in the Authorization header.

The format for passing the token in headers is as follows:

Authorization Bearer xxxxxxxxxxxxxxxx.yyyyyyyyyyyyy.zzzzzzzzzzzzzzz

JWT Token is a standardized way of generating a token. Currently, Firstbeat Cloud API supports HMACSHA256 encoded JWT tokens, with a shared secret. The token should be valid at the most five minutes after generation.

JWT Token format consists of three parts separated by a . (dot). The first part is the Base64 encoded header information, the second part is Base64 encoded Payload data and the last part is HMAC – encoded combination of HMACSHA256 encoding the headers, payload, and a shared secret text string.

For more information about JWT Tokens, check https://jwt.io/

You need your id and sharedSecret to create an API token.

Examples of how to create a JWT token are provided in the next chapter.

As a result, you should have a token generated. A token looks like this (your token will be unique).

eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJjMzhlMjU2ZC0xMWVlLTRmNWQtYWI0NS1iNjJkMDU3NGE3ZmQiLCJpYXQiOjE1ODg2NzQxNzYsImV4cCI6MTU4ODY3NDQ3Nn0.BQpPdmyM4KikNFIRisKdOkFRCADCA1bQpKUzBUWy3QA

Note: Token is valid only for five minutes at a time. After five minutes, the token expires and you need to create a new token to access the API.

Exaples for Generating the JWT Token

Here are some examples with commonly used programming languages on how to generate a JWT Token with the help of some open source JWT libraries:

Java

Create a JWT token with Java (java-jwt):

import java.util.Date;
import com.auth0.jwt.JWT;
import com.auth0.jwt.algorithms.Algorithm;

try {
Algorithm algorithm = Algorithm.HMAC256("YOUR_SHARED_SECRET");
Date now = new Date();
Date expires = new Date();
expires.setSeconds(expires.getSeconds() + 300);

String token = JWT.create()
    .withIssuer("YOUR_CONSUMER_ID")
    .withIssuedAt(now)
    .withExpiresAt(expires)
    .sign(algorithm);
} catch (UnsupportedEncodingException exception){
//UTF-8 encoding not supported
} catch (JWTCreationException exception){
//Invalid Signing configuration / Couldn't convert Claims.
}

Node.js / JavaScript

Create a JWT token with Node.js (jsonwebtoken):

'use strict';

const jwt = require('jsonwebtoken');
const SECRET = 'YOUR_SHARED_SECRET';
const issuedAt = Date.now() / 1000;
const payload = {
iss: 'YOUR_CONSUMER_ID',
iat: issuedAt,
exp: issuedAt + 300
};

// default algorithm (HMAC SHA256)

const token = jwt.sign(payload, SECRET);

Python

Create a JWT token with Python (pyJwt):

import jwt
import time

secret = 'YOUR_SHARED_SECRET'
now = int(time.time())
expires = now + 300

payload = {
    'iss': 'YOUR_CONSDUMER_ID',
    'iat': now,
    'exp': expires
}

token = jwt.encode(payload, secret)

Adding an API Key

Next, create your API key using the account/api-key endpoint.

For this step, you need a valid API token you generated earlier. Please remember the five minute expiration period for the token. Generate a new token in case more than five minutes have passed.

You create an API key only once.

Example curl command:

curl 'https://api.firstbeat.com/v1/account/api-key' \
    --request GET \
    --header 'Authorization: Bearer
eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJjMzhlMjU2ZC0xMWVlLTRmNWQtYWI0NS1iNjJkMDU3NGE3ZmQiLCJpYXQiOjE1ODg2NzQxNzYsImV4cCI6MTU4ODY3NDQ3Nn0.BQpPdmyM4KikNFIRisKdOkFRCADCA1bQpKUzBUWy3QB' \
    --header 'Content-Type: application/json'

For this command, you make a GET request with a header “Bearer token” string.

If the request is successful, you get an API key as a response:

{"apikey":"cXvpCBUzG64orvHXA5taA2Et2hWGr6Gh1LqL90hx"}

Testing your API Access

At this point:

  1. You have registered as a Sports API user and your account has been approved by Firstbeat
  2. API consumer has been granted access to Sports account data sharing from Sports Cloud
  3. You have generated an API token to add an API key

Now you can programmatically access Sports API.

Each API request needs to include an API key and a valid token in the header.

Example curl command to list accounts linked for your API consumer:

curl 'https://api.firstbeat.com/v1/sports/accounts' \
    --request GET \
    --header 'Authorization: Bearer
eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJjMzhlMjU2ZC0xMWVlLTRmNWQtYWI0NS1iNjJkMDU3NGE3ZmQiLCJpYXQiOjE1ODg2NzQxNzYsImV4cCI6MTU4ODY3NDQ3Nn0.BQpPdmyM4KikNFIRisKdOkFRCADCA1bQpKUzBUWy3QA' \
    --header 'x-api-key: cXvpCBUzG64orvHXA5taA2Et2hWGr6Gh1LqL90hx'

Successful operation returns:

{
    "accounts": [
    {
        "accountId": "1-1",
        "name": "Some account",
        "authorizedBy": {
        "coachId": 0
        }
    }
    ]
}

API Usage Limits

Each API consumer will have usage limits of how frequently it is allowed for the consumer to request Firstbeat Cloud API resources.

If the consumer will not follow the usage limits, the account will be first throttled for a moment and denied access to the resources. If, despite being cautioned by Firstbeat, API consumer continues to disuse the API in ways that stress the service excessively Firstbeat reserves the right to disable the consumer access permanently.

Currently, API consumer-specific limits are as follows, and should be honored:

  • Max. 60 requests / minute.
  • Max. 5000 requests / day.

Result pagination

Some endpoints are limited to 1000 results per request. To fetch more results, the API provides an attribute “more” with the results.

If “more: true” attribute is appended to the returned JSON data, you may request the next set of data by providing a query parameter ?offset=OFFSET_NUMBER to the request, to get the next set of data.

OFFSET_NUMBER = The amount of already fetched documents. For example 1000.

Result variables

Below is listed the full list of available result variables. There are two types of variables:

  • Scalers
  • Time series vectors

Time series vectors are Base64 encoded and zlib compressed. You may also always use the query parameter list option, to get the data in an uncompressed format.

Scalar variables

Name Unit Description
heartRateLowest 1/min The lowest heart rate value achieved during the measurement.
heartRateMinimumPercentage % -
heartRatePeak 1/min The highest heart rate value achieved during the measurement. Heart rate values are individually determined and affected for example by the person's fitness level and age. The same heart rate value does not necessarily mean the same exercise intensity for different persons.
heartRatePeakPercentage % -
heartRateAverage 1/min The average heart rate value for the measurement. Heart rate values are individually determined and affected for example by the person's fitness level and age. The same heart rate value does not necessarily mean the same exercise intensity for different persons.
heartRateAveragePercentage % -
quickRecoveryTestScore - The 0-100% score of the personalized result of the Quick Recovery Test (QRT). The score is derived from a 3-min measurement, and it describes the recovery state of the person based on the assessment of the autonomic nervous system balance through analysis of heart rate and heart rate variability. A score of 100% means the person's recovery state and readiness to perform is excellent, whereas a score of 0% means poor recovery and readiness.
quickRecoveryScaledScore -
rmssd ms -
oxygenConsumptionAverage ml/kg/min -
oxygenConsumptionPeak ml/kg/min The highest rate of oxygen consumption achieved during the measurement. Oxygen consumption is calculated in proportion to the person's weight. The higher the value, the higher the peak intensity of exercise.
zone1Time min The overall time spent in heart rate zone1 during the measurement. The exercise intensities are categorized into different zones based on the percentage of personal maximal heart rate (%Hrmax).
zone2Time min The overall time spent in heart rate zone2 during the measurement. The exercise intensities are categorized into different zones based on the percentage of personal maximal heart rate (%Hrmax).
zone3Time min The overall time spent in heart rate zone3 during the measurement. The exercise intensities are categorized into different zones based on the percentage of personal maximal heart rate (%Hrmax).
zone4Time min The overall time spent in heart rate zone4 during the measurement. The exercise intensities are categorized into different zones based on the percentage of personal maximal heart rate (%Hrmax).
zone5Time min The overall time spent in heart rate zone5 during the measurement. The exercise intensities are categorized into different zones based on the percentage of personal maximal heart rate (%Hrmax).
aerobicTrainingEffect,
anaerobicTrainingEffect - The 0-5 score of the personalized impact of the training session on fitness development. A score 0-0.9 is defined as "no effect", 1.0-1.9 as "minor effect", 2.0-2.9 as "maintaining effect", 3.0-3.9 as "improving effect", 4.0-4.9 as "highly improving effect", and 5.0 as "overreaching effect". A balanced training program consists of training sessions with varying training effects.
trimp - -
epocPeak ml/kg The highest EPOC (Excess Post-Exercise Oxygen Consumption) value achieved during the measurement. EPOC describes the magnitude of disturbance of the body's homeostasis reflected in oxygen demand after exercise. The estimated increased oxygen consumption of the person due to exercise is calculated in proportion to the person's weight. In principle, the higher the EPOC the more demanding the exercise session has been.
trimpPerMinute 1/min -
respirationRateAverage 1/min -
respirationRatePeak 1/min -
energyConsumptionFats kcal -
energyConsumptionTotal kcal The overall energy (kilocalorie) consumption during the measurement.
sdnn ms -
lfHfRatio ms^2 -
lfAverage ms^2 -
hfAverage ms^2 -
vlfAverage ms^2 -
recoveryStateTime min The overall time spent in recovery state during the measurement. Recovery is detected when the autonomic nervous system is dominated by parasympathetic activity. Recovery is typically detected during relaxing activities such as sleeping.
stressStateTime min The overall time spent in stress state during the measurement. Stress is detected when the autonomic nervous system is dominated by sympathetic activity. Body stress can be caused by numerous internal and external factors (stressors).
sleepStateTime min -
sleepRecoveryIndexAbsolute -
acuteTrainingLoad -
chronicTrainingLoad -
acwr -
scaledQrtWeeklyMean % -
playerStatusScore -
vo2max ml/kg/min -
oxygenConsumptionMaximumPercentage % -
oxygenConsumptionAveragePercentage % -
energyConsumptionCarbs kcal -
underZonesTime min -
daysSinceLastGoodRecovery days -

Time series vectors

Name Unit Sampling Rate (Hz) Type Bits Description
rmssd1MinSeries * ms 0.02 Float 64 -
artifactCorrectedRrVector * ms 1 Float 64 -
vlfSeries * ms^2 1 Float 64 -
lfSeries * ms^2 1 Float 64 -
hfSeries * ms^2 1 Float 64 -
heartRateSeries 1/min 0.2 Unsigned 8 The time series showing the momentary, second-by-second, value of heart rate during the measurement.
epocSeries ml/kg 0.2 Float 64 The time series showing the momentary, second-by-second, value of EPOC during the measurement.
energyConsumptionSeries kcal/h 0.2 Unsigned 16 The time series showing the momentary, second-by-second, value of energy (kilocalorie) consumption rate as kcal/h during the measurement. The totalEnergyConsumption is calculated by multiplying the duration of the measurement in hours by the average of seriesEnergyConsumption.
trimpSeries 0.2 Float 64 The time series showing the momentary, second-by-second, value of TRIMP during the measurement.
trimpPerMinuteSeries * 1/min 0.2 Float 64 -
heartRatePercentageSeries * 0.2 Float 64 -

NOTE: TimeSeries variables marked with an * need to be explicitly requested from the /results endpoints due to their data-heavy nature. To request them, iuse the ?var= query parameter.

For example: .../results?var=trimpPerMinuteSeries,heartRatePercentageSeries

Calculating session results

Currently the /sessions/{sessionId}/results endpoint will return a set of measurement results. To calculate a single session results you need to either sum or calculate an average of the invidual athlete's results. You will find this from the Session results section for each variable.

Session results

For the moment our Cloud API does not offer aggregate session results. Here are some key variables listed, how we calculate and show session aggregate results in our other Sports products:

For the moment our Cloud API does not offer aggregate session results. Here are some key variables listed, how we calculate and show session aggregate results in our other Sports products:

Variable name Session results
heartRateLowest Athlete's min. from measurements, average from athlete results.
heartRateMinimumPercentage Athlete's avg. from measurements, average from athlete results.
heartRatePeak Athlete's avg. from measurements, average from athlete results.
heartRatePeakPercentage Athlete's avg. from measurements, average from athlete results.
heartRateAverage Athlete's max. from measurements, average from athlete results.
heartRateAveragePercentage Athlete's avg. from measurements, average from athlete results.
quickRecoveryScaledScore Athlete's max. from measurements, average from athlete results.
rmssd Athlete's avg. from measurements, average from athlete results.
oxygenConsumptionAverage Athlete's avg. from measurements, average from athlete results.
oxygenConsumptionPeak Athlete's max. from measurements, average from athlete results.
zone1Time,
zone2Time,
zone3Time,
zone4Time,
zone5Time Athlete's summed results from measurements, average from athlete results.
aerobicTrainingEffect,
anaerobicTrainingEffect Athlete's cumulative result from measurements, average from athlete results.
trimp Athlete's cumulative result from measurements, average from athlete results.
epocPeak Athlete's summed results from measurements, average from athlete results.
trimpPerMinute Athlete's cumulative result from measurements, average from athlete results.
respirationRateAverage Athlete's avg. from measurements, average from athlete results.
respirationRatePeak Athlete's max. from measurements, average from athlete results.
energyConsumptionFats Athlete's cumulative result from measurements, average from athlete results.
energyConsumptionTotal Athlete's cumulative result from measurements, average from athlete results.
stressStateTime Athlete's summed results from measurements, average from athlete results.
sleepStateTime Athlete's summed results from measurements, average from athlete results.
sleepRecoveryIndexAbsolute Athlete's avg. from measurements, average from athlete results.
acuteTrainingLoad Athlete's avg. from measurements, average from athlete results.
chronicTrainingLoad Athlete's avg. from measurements, average from athlete results.
acwr Athlete's avg. from measurements, average from athlete results.
scaledQrtWeeklyMean Athlete's max. from measurements, average from athlete results.
playerStatusScore Athlete's avg. from measurements, average from athlete results.
vo2max Athlete's avg. from measurements, average from athlete results.
daysSinceLastGoodRecovery Amount of days since athlete's last good qrt result (QRT Score >= 70)

account

Register as an API consumer

Registers a new API consumer

Request Body schema: */*

Created API Consumer object

consumerName
required
string

Responses

Response samples

Content type
application/json
{
  • "id": "0df33d4b-f526-4040-ad6e-447589f810f5",
  • "consumerName": "Firstbeat Cloud API User",
  • "sharedSecret": "5e03d766-4d55-4c88-a011-f0785bccb671"
}

Request an api-key

Generate consumer specific api-key needed to access other Cloud API endpoints

header Parameters
Authorization
required
string

format: Bearer YOUR_TOKEN

Responses

Response samples

Content type
application/json
{
  • "apiKey": "uBncM0LcXT40ncZfZYSkW448cAdPAgLCKHiJ2fG6"
}

sports/accounts

Ge