Byteflies Cloud API
CE mark
The Byteflies Cloud API is developed using a serverless infrastructure and documented using an OpenAPI 3.0 specification. This API is optimized for the purpose of retrieving health data in a structured and readable format.
Table of contents
Overview
The Byteflies Cloud gathers sample-level Recordings from Sensor Dots via the Docking Station, which are associated with a User Account. It is an integral part of the Byteflies Kit (Model 1)**. Its instructions are discussed in a separate section for readability reasons but one cannot be used without the other. If you have not already done so, please review the IFU for the Byteflies Kit first which focuses on the hardware components of the system. All legal & regulatory information are linked in that document.
- Signal
- A physiologic or motion signal, as recorded by a Sensor Dot (e.g. ECG).
- Channel
- A Sensor Dot can record two biopotential Signals simultaneously and has two pairs of electrode connectors that each form a Channel.
- Recording
- The combination of all data recorded by a single Sensor Dot is grouped in a Recording.
- Group
- A Group combines one or more Docking Stations that are assigned to a specific study.
- Patient ID
- A unique string used to identify a study subject.
- Patient Record
- A list of pre-configured Patient IDs and the hardware they are associated with.
- User Account
- A Byteflies Cloud account that can contain one or more Groups and can only be accessed with a specific username and password.
Recording
Whenever a Sensor Dot is configured to start a Recording, the device initializes its sensors to start gathering data on all specified channels. At this specific point in time, the Sensor Dot captures the Recording timestamp, also known as startDate
. The specifics of a Recording are discussed further.
Docking Station
The Docking Station can be thought as a relay of Recordings to the Byteflies Cloud. It reads a Recording from the Sensor Dot’s memory, and uploads it once it is online. It’s also used to calibrate and configure the Sensor Dot, and charge its batteries.
The Calibration function is only available to admin User Accounts.
Do not use the Calibration function without explicit instructions from Byteflies to do so. When in doubt, contact us.
Getting Started
In this manual, we introduce curl
commands for interacting with the API. To execute curl
commands, the MacOS terminal, Linux console, or Windows Command Prompt can be used. This software enables a User Account to send HTTP requests or data to web servers using HTTP methods, like GET
or POST
.
Breaking down a curl
HTTP request
curl -X GET \
-H 'Authorization: <id token>' \
https://api.cloud.byteflies.net/{endpoint}
-X specifies the HTTP Request method to use when sending, in this case it is the GET
HTTP method.
-H specifies an HTTP Request header to be used when sending the request, in this case it is a header named Authorization
. More information can be found on curl
’s official documentation.
The last parameter is the URL endpoint where the HTTP request will be sent, in this case https://api.cloud.byteflies.net/{endpoint}
.
Breaking down a JSON Response
{
"AuthenticationResult": {
"AccessToken": "eyJ..",
"ExpiresIn": 3600,
"IdToken": "eyJ..",
"RefreshToken": "eyJ...",
"TokenType": "Bearer"
},
"ChallengeParameters": {}
}
This response specifies a JSON object that contains the following name/value pairs:
AuthenticationResult
ChallengeParameters
Within the AuthenticationResult
the following name/value pairs appear:
AccessToken
ExpiresIn
IdToken
RefreshToken
TokenType
A name/value pair is separated by a colon :
, where the name is to the left of the colon and the value to the right. A more in-depth explanation can be found here.
Byteflies Cloud RESTful API
The sandbox API is available at the following URI:
https://api.cloud.byteflies.net
and currently has the following endpoints:
HTTP Method | Endpoint | Description |
---|---|---|
GET | /groups | Retrieve all Groups connected to your account |
GET | /groups/{groupId}/recordings | Returns all Recordings of a specific Group |
GET | /groups/{groupId}/recordings/{recordingId} | Retrieve the Recording details |
GET | /groups/{groupId}/recordings/{recordingId}/algorithms/{algorithmId} | Retrieve algorithm details |
PUT | /docks/{dockName}/config | Switch a Docking Station to configuration mode |
Authentication
The access to the API is secured by authentication tokens generated by Amazon Cognito. This means that when someone makes a request without an authentication token, our API will refuse the request with a 403 Forbidden
response. Valid requests can be sent to the API using these tokens on the HTTP Header Authentication
, ensuring the restricted access to the resources on the Byteflies Cloud.
Retrieving an Authentication Token IdToken
In order to retrieve an authentication token, specifically the IdToken
, the User Account has to log in the API with a username and password. You should have received a username and password from Byteflies to access your account. If you did not, contact us.
Byteflies Cloud accounts are only available for Trained Operators!
For demonstration purposes we have created a demo account with the following credentials:
username: demo@byteflies.com
password: 16yV&dXP
To login into our API, the following curl
command can be executed:
curl -X POST \
--data '{
"ClientId": "5kgqk7n83evq9cbqnam1biqnbr",
"AuthFlow": "USER_PASSWORD_AUTH",
"AuthParameters": {"USERNAME": "demo@byteflies.com", "PASSWORD": "16yV&dXP"}}' \
-H 'X-Amz-Target: AWSCognitoIdentityProviderService.InitiateAuth' \
-H 'Content-Type: application/x-amz-json-1.1' \
https://cognito-idp.eu-west-1.amazonaws.com
The curl
command sends a POST
request to the https://cognito-idp.eu-west-1.amazonaws.com
endpoint. This endpoint is part of the Amazon Cognito service from AWS, which handles the authentication of Byteflies Cloud users. To authenticate a User Account, the endpoint requires some parameters to be sent on the POST
request data. Such parameters can be seen in the --data
section of the request.
Noteworthy, on this line:
"AuthParameters": {"USERNAME": "demo@byteflies.com", "PASSWORD": "16yV&dXP"}}' \
The login credentials are included. To login as a different user, the USERNAME
and PASSWORD
fields need to be changed accordingly. To login to the environment, the ClientId
field needs to be set to 5kgqk7n83evq9cbqnam1biqnbr
.
As a response, this command gets the following JSON Response:
{
"AuthenticationResult": {
"AccessToken": "eyJ..",
"ExpiresIn": 3600,
"IdToken": "eyJ..",
"RefreshToken": "eyJ...",
"TokenType": "Bearer"
},
"ChallengeParameters": {}
}
This response includes the parameter "IdToken": "eyJ..",
, this value is required to make further requests to the API.
Making requests to the API Endpoints
Once the IdToken
parameter is retrieved using the authentication steps above, the User Account can start making HTTP requests to the API endpoints.
For example, to request the list of Docking Stations associated with a User Account, the following command can be executed replacing <id token>
with the value eyJ...
retrieved in the "IdToken": "eyJ..",
parameter from the previous response:
curl -X GET \
-H 'Authorization: <id token>' \
https://api.cloud.byteflies.net/groups/
This command sends a HTTP GET
request to the https://api.cloud.byteflies.net/groups/
endpoint, which returns the list of Docking Stations associated with the User Account.
Token Expiration
Authentication Tokens are valid for the amount of time specified in the JSON response when authenticating. For instance, if the authentication responded with the following JSON response:
{
"AuthenticationResult": {
"AccessToken": "eyJ..",
"ExpiresIn": 3600,
"IdToken": "eyJ..",
"RefreshToken": "eyJ...",
"TokenType": "Bearer"
},
"ChallengeParameters": {}
}
The response includes the "ExpiresIn": 3600
name/value pair. The value 3600
specifies the amount of time in seconds that the authentication tokens are valid from the time of authentication. If the tokens have expired, the API will respond with:
{
"message": "The incoming token has expired"
}
If that is the case, re-authenticating and retrieving a new token will be necessary.
Exploring the API Endpoints
The /groups
Endpoint
The list of Groups associated with a User Account
When sending a GET
request to the /groups
endpoint:
curl -X GET \
https://api.cloud.byteflies.net/groups/ \
-H 'Authorization: <id token>'
The endpoint responds with a JSON response:
[
{
"id": "1234",
"name": "TestGroup",
"description": "Description of group"
}
]
This response includes a list of JSON Objects that include the Group associated with your User Account. In this particular response, there is only one Group named TestGroup
associated with the User Account.
The /groups/{groupId}/recordings
Endpoint
The list of Recordings associated to a Group
When sending a GET
request to the /groups/{groupId}/recordings
endpoint, the path parameter groupId
needs to be swapped with the ID of a Group. Using the Group ID retrieved above with the /groups
endpoint, the following command can be executed:
curl -X GET \
-H 'Authorization: <id token>' \
https://api.cloud.byteflies.net/groups/1234/recordings
The endpoint will respond with a list of recordings, for example:
[
{
"id": "33d8951c-999f-11e9-a2a3-2a2ae2dbcce4",
"dotId": "24deb6f2e360",
"dockName": "Dock-1234",
"patient": "patient-ID",
"signals": [
{
"id": "995f3a71-71c2-11eb-9f2c-be58546669d4",
"type":"EEG",
"quality":"FAIL",
"channel": 2,
"rawData": "https://..."
},
{
"id": "995e4cb7-71c2-11eb-9f2c-be58546669d4",
"type":"ACC",
"rawData": "https://..."
}
],
"startDate": 1526919822.1422584,
"endDate": 1526919921.5267422,
"uploadDate": 1526939822.453,
"duration": 99.384483839,
"status": "done"
}
]
This response includes a list of one Recording with the following values:
Name | Description |
---|---|
id | A unique identifier of the Recording |
dotId | A unique identifier of the Sensor Dot that performed the Recording |
dockName | A unique identifier of the Docking Station that was used to upload the Recording |
patient | A patient identifier |
signals | A list of Signal objects available in the Recording |
signals.type | The type of Signal |
signals.quality | The quality of the Signal. Can be PASS, CHECK or FAIL* |
signals.channel | The Channel number as described in the Byteflies Kit IFU |
signals.rawData | A link to download the data |
startDate | A UNIX timestamp in (fractional) seconds indicating the start of the Recording |
endDate | A UNIX timestamp in (fractional) seconds indicating the end of the Recording |
uploadDate | A UNIX timestamp in (fractional) seconds indicating the time of data upload |
duration | Total duration of a Recording in (fractional) seconds |
status | Indicates if the Byteflies Cloud is ready with generating the Insights |
*Refer to the Clinical Insights section for more information.
The /groups/{groupId}/recordings/{recordingId}
Endpoint
The details of a particular Recording
When sending a GET
request to the /groups/{groupId}/recordings/{recordingId}
, the path parameter {recordingId}
needs to be swapped with the id
of a Recording. The parameter {groupId}
needs to be swapped with the id
of the group in which this Recording was uploaded. Taking the recordingId
33d8951c-999f-11e9-a2a3-2a2ae2dbcce4
of the previous endpoint, the following command can be executed:
curl -X GET \
-H 'Authorization: <id token>' \
https://api.cloud.byteflies.net/groups/1234/recordings/33d8951c-999f-11e9-a2a3-2a2ae2dbcce4
The endpoint sends back a JSON response:
{
"id": "33d8951c-999f-11e9-a2a3-2a2ae2dbcce4",
"dockName": "Dock-8e6bde5ac7e7191caaf7e3c9",
"dotId": "24deb6f2e360",
"patient": "patient-ID",
"groupid": "16bc09e1-4107-11ea-959c-ad5917d09f85",
"startDate": 1526919822.1422584,
"endDate": 1526957192.6380,
"uploadDate": 1526939822.453,
"duration": 37370.4958
"firmwareVersion": "1.22.0",
"signals": [...]
}
This response includes the following:
Name | Description |
---|---|
id | A unique identifier of the Recording |
dotId | A unique identifier of the Sensor Dot that performed the Recording |
dockName | A unique identifier of the Docking Station that was used to upload the Recording |
patient | A patient identifier |
signals | A list of Signal objects available in the Recording |
startDate | A UNIX timestamp in (fractional) seconds indicating the start of the Recording |
endDate | A UNIX timestamp in (fractional) seconds indicating the end of the Recording |
uploadDate | A UNIX timestamp in (fractional) seconds indicating the time of data upload |
duration | Total duration of a Recording in (fractional) seconds |
firmwareVersion | The version of the firmware that was on the Sensor Dot at the time of the Recording |
The specifics of signals
will be explained in detail in the next section.
Update the patient identifier
You can associate a Patient Identifier with your recording with this endpoint. To do so, make a PUT
request to the /groups/{groupId}/recordings/{recordingId}
endpoint.
The payload of the body should look like this :
{
"patient": "Patient Identifier"
}
Rerun algorithms for all signals in a recording
You can rerun algorithms for all Signals in a specific Recording. This might be useful in case a new version of the algorithm was deployed or if for some reason, the algorithm was never triggered. You cannot choose which algorithm to run, this is linked to the Signal type. To (re)run the algorithms, make a PUT
request to the /groups/{groupId}/recordings/{recordingId}
endpoint.
The payload of the body should look like this :
{
"triggerAlgorithms": true
}
Available Signals in a Recording
For each Recording, a list of signals is included in the response:
{
...
"signals": [
{
"id": "d030cb6b-71c4-11eb-a965-9efcfcdd45da",
"type": "ACC",
"rawData": "https://...",
"samplingRate": "25",
"conversionFactor":0.000244140625
},
{
"id": "d030cb6b-71c4-11eb-a965-9efcfcdd45da",
"type": "EEG",
"channel": 1,
"quality": "CHECK",
"rawData": "https://...",
"samplingRate": "250",
"conversionFactor":0.4808108585052719,
"algorithms":[
{
"type":"EEG_ARTFCTS",
"id":"09cdf800-7268-11ea-a8d6-a7682dc8f48c",
"added": 1613637847
}
]
},
{
"id": "d035f333-71c4-11eb-a965-9efcfcdd45da",
"type": "ECG",
"quality": "CHECK",
"channel": 2,
"rawData": "https://...",
"samplingRate": "250",
"conversionFactor":1.4424325755158156
},
{
"id": "d036c3fd-71c4-11eb-a965-9efcfcdd45da",
"type": "GYR",
"rawData": "https://...",
"samplingRate": "200",
"conversionFactor":0.030517578125
}
]
}
This signals
list includes an entry for each of the Signals available in a Recording. In this particular example, there is an ACC, EEG, ECG, and a GYR signal available.
The response includes the following information:
Name | Description |
---|---|
type | The type of Signal |
id | A unique identifier of the Signal or Algorithm |
channel | The Channel number as described in the Byteflies Kit IFU |
rawData | A URL for the sample-level (raw) data |
samplingRate | The number of samples per second for the Signal |
algorithms | a list of available algorithm outputs containing the type of algorithm, the algorithmId and a UNIX timestamp when it was added |
quality | The quality of the Signal. Can be PASS, CHECK or FAIL* |
conversionFactor | a value to convert the sample-level data to physical units through multiplication |
With this information, we know that the recording 33d8951c-999f-11e9-a2a3-2a2ae2dbcce4
has sample-level data in CSV format of Signal type ACC
, which can be downloaded using the URL available in rawData
. For example using the wget
command:
wget \
-O 33d8951c-999f-11e9-a2a3-2a2ae2dbcce4.csv \
'https://bc-iot-platform-parseduploadsbucket-khbvk362f8kf.s3.eu-west-1.amazonaws.com/2018/05/21/33d8951c-999f-11e9-a2a3-2a2ae2dbcce4/719a0254-99a1-11e9-a2a3-2a2ae2dbcce4?AWSAccessKeyId=ASIA4GCJNCPO6RIVNIRY&Expires=1567770981&Signature=PwbiPzjeziQ9DGUQaGG504Kwoi0%3D&x-amz-security-token=AgoJb3JpZ2luX2VjEKT%2F%2F%2F%2F%2F%2F%2F%2F%2F%2FwEaCWV1LXdlc3QtMSJIMEYCIQCgUhSo3YP6MaUsdHvKJwLAzNiHQvOVwsWJ1ngWlE9XrQIhAOz1Ja%2FcthQA7Wfc0Wnqx0XLfv%2FSbQtyynKMdlmsclXdKq4CCF0QABoMODM3NjcyNTcxODY5IgyWMiRcTX04GhdA4HIqiwKA4d2yKrQrzA2%2F4Sw%2FnevDMsXL1%2FCmzvszLpCha7pctguogMZ5RgMGtI8yc6jFAG900halbX8dtqwVI6Jfa3chE17pwJgAEQ%2BJ%2F%2BAkapORxcJ5sdxHY3cTzZo4KNezwbWEYpyUa5GlTbRLmqQNaarbKNqol1AA%2BtD3%2BbwUdNBUMeq5Ph16D4bZvC23a52bb4S8iSFUUdFvxfFng4jouPpssbnIIJixxzXNmQvNMLhEz9zVPTpuvqBe8VMGd22BeT%2F4kin9YyLqrU3d8lEemW8jY9EtX5CKe3hO3l6Wg079DGyMkIhg1nN22LEbDK0zp68Y8ANMUaUdoC6up02o%2FNbHGfDJmuEqDqPn02Awio7J6wU6swET3qHT342B1zNlp0kDKySNJch4iAADF1TzEVSZCzhC3p6RCMrPP8eLjaeUMECwxqSgfNeXVxXqqwK4UvNiof1%2F7QcX3a%2BWlSSJZbzbPsy0fppjMP1lB6GfBCv7qlROWhwN59NzRc7v7n2foFjGzRPh90pUmraGHPXWuaFUrzo2LqurLitNrSdcz1kdGtwNTvuW%2FcvOz4mCGKTbVKYghmUCaEY1YnUTzrIGzg0aJLiXFjgRmg%3D%3D'
This will download the file using the name 33d8951c-999f-11e9-a2a3-2a2ae2dbcce4.csv
. Please note that this URL includes temporary credentials for downloading, which are only valid for 10 minutes.
Sample-level data (i.e. raw waveform data) for each Signal that is available for a Recording can be downloaded in Comma-Separated Value (CSV) format. Clinical Insights derived from sample-level data can also be downloaded as CSV files, as specified in the Clinical Insights documentation..
Units of measurement
The units of measurements depend on the signal type.
Type | SI Unit | Description |
---|---|---|
ExG | nV | nanovolt |
ACC | g | g-force |
GYR | °/s | degrees per second |
BAT | % | % of total battery capacity |
The /groups/{groupId}/recordings/{recordingId}/algorithms/{algorithmId}
Endpoint
The details of a particular Algorithm
When sending a GET
request to the /groups/{groupId}/recordings/{recordingId}/algorithms/{algorithmId}
, the path parameter {recordingId}
needs to be swapped with the id
of a recording. The parameter {groupId}
needs to be swapped with the id
of the group in which this recording was uploaded. The parameter {algorithmId}
needs to be swapped with the id
of the algorithm.
Taking the recordingId 33d8951c-999f-11e9-a2a3-2a2ae2dbcce4
of the previous endpoint, and the algorithmId 09cdf800-7268-11ea-a8d6-a7682dc8f48c
the following command can be executed:
curl -X GET \
-H 'Authorization: <id token>' \
https://api.cloud.byteflies.net/groups/1234/recordings/33d8951c-999f-11e9-a2a3-2a2ae2dbcce4/algorithms/09cdf800-7268-11ea-a8d6-a7682dc8f48c
This will download the file using the name 09cdf800-7268-11ea-a8d6-a7682dc8f48c-EEG_ARTFCTS.csv
. Please note that this URL includes temporary credentials for downloading, which are only valid for 10 minutes.
The /docks/{dockName}/config
Endpoint
You can set a Docking Station in one of your groups to CONFIGURATION or NORMAL mode. To do so, make a PUT
request to the /docks/{dockName}/config
endpoint.
The payload of the body should look like this to enter CONFIGURATION mode:
{
"mode": "configuration",
"configSignals": [
{"type": "ECG", "fs": 250, "channel": 1},
{"type": "EEG", "fs": 250, "channel": 2},
{"type": "ACC", "fs": 25},
{"type": "GYR", "fs": 25},
]
}
- In case you do not want to measure a certain Signal, simple omit it.
- Allowed signal types are: EEG, ECG, EOG, EMG, ACC, or GYR.
- For any biopotential (ExG) Signal, you should define a Channel number (1 or 2) and the sampling frequency should be 250 Hz.
- For ACC or GYR Signals, no Channel needs to be specified and the sampling frequency can be 25, 50, 100 or 200 Hz.
Follow the next steps in order to configure Sensor Dots:
- Indicate the Signal type and sampling frequency for Channel 1 and 2.
- Add the ACC and GYR Signals as desired and select the sample rate (25, 50, 100, or 200 Hz).
- Make sure all Sensor Dot(s) you wish to (re)configure are on the Docking Station.
- Enable the Configuration Mode of the Docking Station, indicated by a purple status LED on the back of the Docking Station.
- The status LED of the docked Sensor Dot(s) will blink green rapidly to indicate the new configuration has been set.
- Revert the Docking Stationback to normal interface to exit Configuration Mode. The Sensor Dot LEDs should turn solid green, or blinking green if the battery is still charging.
- Repeat this process if you need to send different configurations to other Sensor Dots (only one configuration can be send per configuration cycle).
To revert the Docking Station to NORMAL mode, set the payload as follows:
{
"mode : "normal"
}
If, after attempting a configuration, a Sensor Dot’s LED is Red when taking it out of the Docking Station, the configuration may not have been correctly stored. Please try again. If that does not solve the issue, contact us.