Rune Labs Data API
Rune Labs Data API
The Rune Labs data API allows patient datasets to be uploaded to the Rune platform from a mobile device, or any other environment. Data can be uploaded directly and securely via HTTPS from anywhere, given proper authentication. It also allows read access to patient upload statistics.
Each endpoint is documented in detail, below.
Overview
Key Concepts
Patient
The person about whom data was measured. This may include a StrivePD user, a person with a neural implant, etc. Each patient has a unique identifier ("patient ID"). Patient IDs are generated by Rune and cannot be changed.
Device
The sensor serving as the data source (e.g. a DBS implant, iOS application, wearable device, etc.). A patient may have multiple devices: each one has a unique identifier ("device ID"). Device IDs are generated by Rune and cannot be changed. They do not correspond to any identifier or information from the device itself.
Client
Refers to the patient-facing app itself. A client accesses data programmatically, on behalf of a patient.
A client is associated with exactly one patient. Patients may have multiple clients, depending on how many apps are sending or accessing data. Patients and clients are resources in the Rune platform with unique identifiers, and they are used to control access to patient data.
Dataset
A dataset is a collection of files containing data recorded by a patient's device, over some period of time.
Each dataset has a schema that broadly identifies its contents. The schema_id serves as a typing system for datasets. Supported schema IDs include:
medtronic-percept-1medtronic-rcs-1strivestudy-applewatch-1strivestudy-applewatch-md-1strivestudy-healthkit-1strivestudy-healthkit-2strivestudy-spiraltest-1
Schemas specify the number of files that each dataset of a particular type contains, as well as the semantics of each of those files (i.e. what the file is expected to contain). This is used to parse and ingest data after upload.
For example, the strivestudy-applewatch-md-1 dataset schema is used for data collected by the StrivePD app, from the Apple Watch Movement Disorder Kit. Per the schema definition, 3 files must be uploaded for each dataset:
tremor- Tremor datadyskinetic- Dyskinesia datametadata- Assorted metadata
Authentication
Authentication is required for all API requests. There are several authentication methods:
Client Keys
Client keys provide read and write access to one patient.
To use a client key pair for authentication, the HTTP request must include two headers:
X-Rune-Client-Key-Id- client key IDX-Rune-Client-Access-Key- client access key (secret)
Note that each client may only fetch data for its associated patient.
Register a New Client
- Log in to the Rune web app as an admin user.
- Find the patient you want to access data for, and open Patient Settings.
- Open the Clients section.
- Create a new client. You can name it anything, though typically it is named after your app.
- A default client key pair will be created with the new client. Copy the key ID and the access key before closing the page. The access key will never be shown again.
Create New Client Keys
You can create any number of client keys for a given client, through the Rune web app. If you forget a key, you can always create a new key pair and disable the old.
It is highly recommended that you "rotate" keys for a patient every 3-6 months, by creating a new client key, configuring it in the client (e.g. the patient's app), then disabling the old key. You should do this immediately if you believe the key may have been compromised (e.g. stolen from the device, posted over any insecure/public communication channel, etc).
User Access Tokens
Access tokens are long-lived tokens that belong to a single user of the Rune platform, granting access to any patient in that user's active organization. Only admin users have access to the Data API.
To use an access token for authentication, the HTTP request must include the following headers:
X-Rune-User-Access-Token-Id- access token IDX-Rune-User-Access-Token-Secret- access token secretX-Rune-Patient-Id- patient ID for the data being accessed
Create a New Access Token
- Log in to the Rune web app
- Click on the profile icon in the top right corner.
- Click on User Settings.
- On the left sidebar, click on Access Tokens.
- Click CREATE ACCESS TOKEN.
- Copy the token ID and the token secret before closing the page. The secret will never be shown again.
It is highly recommended that you "rotate" user access tokens every 3-6 months, by creating a new token and deactivating the old one. Store your access tokens securely, and do not share them.
JWT
JWTs are generated by the Rune web app upon login. This is not a recommended authentication method for API users.
To use a JWT for authentication, the HTTP request must include two headers:
X-Rune-User-Access-Token- JWTX-Rune-Patient-Id- patient ID for the data being accessed
Response Format
All endpoints return JSON-formatted data.
Errors
Standard HTTP status codes are used to indicate success or failure. In the event of most errors, the response body is JSON that includes additional information, with the following format:
{
"success": false,
"error": {
"code": "EnumeratedErrorKind"
"message": "Human-readable error description",
"should_retry": false
}
}
Dataset Upload
Endpoints to initiate a dataset upload or check on the status of an existing dataset.
Initiate Dataset Upload
Initiate uploading a dataset to the Rune platform.
A dataset may consist of one or multiple files. The schema_id is used to determine how many files each dataset contains. See Key Concepts for details about dataset schemas.
For a dataset upload to be considered complete, all files expected by a dataset schema must be uploaded. An empty file may be used as a placeholder.
A successful request contains an "upload_urls" key, with a set of pre-signed URLs: one for each file in the requested schema.
To upload each file in the dataset, POST a Multipart-encoded file to the corresponding pre-signed "url". This request must include form fields, with the values of the "fields" key.
In addition to the pre-signed URLs, the response also contains:
- The maximum size for each individual file (by default, 2GiB).
- An expiration time (by default, 3h). After this time, uploads will not be accepted to the pre-signed URLs. If the URLs expire, the upload can be retried by making a new request to the endpoint, with the same inputs.
Please contact Rune Support if you need an exception to either of these constraints.
To check the status of an existing dataset upload, use the Dataset Status endpoint.
Query Parameters
| device_id required |
string Example:device_id=wwxBBbbD ID of the patient device that recorded this dataset. |
| schema_id required |
string Example:schema_id=medtronic-percept-1 Dataset schema ID. See Key Concepts for details about valid schema IDs. |
| session_id required |
string[1 .. 512 characters] A string that uniquely identifies the recording session. Requests are considered duplicate if they have the same device_id, session_id, and schema_id.Duplicate requests will return new upload URLs if the upload is not complete. Once the upload is complete, however, a duplicate request will result in an error. |
| start_time | float Optional Unix timestamp, when data collection began. This is only used for record-keeping; it is not validated or used during data parsing. |
| end_time | float Optional Unix timestamp, when data collection ended. This is only used for record-keeping; it is not validated or used during data parsing. |
| tags | any A map of key-value pairs describing the dataset as a whole. These values will be stored along with the raw data and used to annotate it for future use. Tags should not be used to store configuration relevant to parsing or interpreting the dataset: that should be included in the file contents. Tag keys are strings ([1..128] characters). Tag values may be numeric or strings ([1..1024] characters). |
Responses
200
A dataset for this device_id, schema_id, and session_id existed, but the upload was not completed. The response contains new upload URLs.
201 A new dataset has been created.
400 Bad request
401 Not authorized to perform the request
404 Not found
409
A dataset has already been successfully uploaded for this combination of device_id, schema_id and session_id.
500 Internal server error
Dataset Status
Get the status of a dataset upload.
Once a dataset upload is complete, the status is only visible for 24h after the last file was uploaded. After this time, attempting to fetch the status of the dataset will result in a 404 response.
Path Parameters
| dataset_id required |
string Example:37a2a3dc70c825d9ed1dc5bfcc3137b7c63c84f42c89b075975fb99bfb81c105 ID of the dataset |
Responses
200 Successful request
400 Bad request
401 Not authorized to perform the request
404 Not found
500 Internal server error
Upload Dataset In a Single Request
Upload all data for a dataset in a single request (AKA "single-shot dataset upload").
For a dataset upload to be considered complete, all files expected by a dataset schema must be uploaded. An empty file may be used as a placeholder.
A successful request contains at least the schema ID, the device ID, and the file contents for each file (one for each "stream" associated with the schema). The file contents should be base64 encoded.
Request Body schema: application/json
| device_id required |
string ID of the patient device that recorded this stream data. |
| schema_id required |
string Dataset schema ID. See Key Concepts for details about valid schema IDs. |
| stream_data required |
object File contents for each for each of the streams in the dataset schema. Keys are the stream name and values are the base64-encoded contents of the file. |
| start_time | float Optional Unix timestamp, when data collection began. This is only used for record-keeping; it is not validated or used during data parsing. |
| end_time | float Optional Unix timestamp, when data collection ended. This is only used for record-keeping; it is not validated or used during data parsing. |
| tags | object A map of key-value pairs describing the dataset as a whole. These values will be stored along with the raw data and used to annotate it for future use. Tags should not be used to store configuration relevant to parsing or interpreting the dataset: that should be included in the file contents. Tag keys are strings ([1..128] characters). Tag values may be numeric or strings ([1..1024] characters). |
Responses
201 A new dataset has been created.
400 Bad request
401 Not authorized to perform the request
404 Not found
409
A dataset has already been successfully uploaded for this combination of device_id, schema_id and session_id.
500 Internal server error
Events and Spans
Create an event or span, which can later be queried via the Stream API.
These endpoints only accept Client Key authentication.
Events and spans cannot be deleted. However, they will be overwritten, if the following values are identical:
- Patient ID (determined via authentication credentials)
- Device ID
- All timestamps (1 for events; 4 for spans)
- Classification
Create an Event
An event is an item that occurs at a moment in time, which is associated with a payload.
Request Body schema: application/json
| time required |
float Unix timestamp when the event occurred. |
| classification required |
string A string with 2 or 3 period-delimited elements, in the form <namespace>.<type> or <namespace>.<type>.<enum>.The three elements form a hierarchical classification: - namespace- the general source of the event. This must be one of:- clinical - a clinical measure, e.g. a UPDRS result- device - an event generated/detected by the device or sensor itself- patient - an event reported by the patient- type - the classification of the event, within the namespace.- enum ( optional) - a specific enumeration within the type. |
| created_time | float Time that the event was created. If this is present, it is added to the payload, under the key "created_time". |
| ongoing | bool Indicates if the event continues in time indefinitely. Typically, this is used for patient-reported items (e.g. if they log that they are currently experiencing a symptom). When this is true, "ongoing": true is set in the payload of the event.For an item that lasts for a finite duration of time, create a span (which has a start and end time). |
| device_id required |
string ID of the patient device that recorded this event. |
| device_version required |
string A string that describes the version of the device that recorded the event (e.g. the Strive iOS app version). This value is not currently used, though it may be in the future. |
| payload required |
object A map to associate with the event. There is no validation. |
Responses
200 Successful request.
400 Bad request
401 Not authorized to perform the request
404 Not found
413 Payload too large. The entire request body must be at most 512 KiB.
500 Internal server error
Create a Span
A span is a special type of event, capturing something that occurred over a range of time. Like an event, each span is associated with a payload.
Request Body schema: application/json
| start_time_min | float Unix timestamp; the earliest time when the span could have started. |
| start_time required |
float Unix timestamp, when the span started (with high confidence). |
| end_time required |
float Unix timestamp, when the span ended (with high confidence). |
| end_time_max | float Unix timestamp; the latest time when the span could have ended. |
| classification required |
string A string with 2 or 3 period-delimited elements, in the form <namespace>.<type> or <namespace>.<type>.<enum>.The three elements form a hierarchical classification: - namespace- the general source of the span. This must be one of:- clinical - a clinical measure, e.g. a UPDRS result- device - a span generated/detected by the device or sensor itself- patient - a span reported by the patient- type - the classification of the span, within the namespace.- enum ( optional) - a specific enumeration within the type. |
| created_time | float Time that the span was created. If this is present, it is added to the payload, under the key "created_time". |
| device_id required |
string ID of the patient device that recorded this span. |
| device_version required |
string A string that describes the version of the device that recorded the span (e.g. the Strive iOS app version). This value is not currently used, though it may be in the future. |
| payload required |
object A map to associate with the span. There is no validation. |
Responses
200 Successful request.
400 Bad request
401 Not authorized to perform the request
404 Not found
413 Payload too large. The entire request body must be at most 512 KiB.
500 Internal server error
Patient Upload Summary Statistics
Query patient upload statistics per schema_id which include:
- Total bytes of raw data uploaded
- Number datasets uploaded
- Creation time of the latest dataset
- Creation time of the earliest dataset
Patient Upload Summary Statistics
A successful request returns a JSON object, with a data key containing the upload summary statistics per schema_id uploaded.
The response can contain all upload summary statistics for a patient, or the upload summary statistics for a patient related to a single schema_id.
The patient_id is a path param in the url. The endpoint accepts a single query param: schema_id.
Path Parameters
| patient_id required |
string Example:patient-123456789 The ID of the patient. |
Query Parameters
| schema_id | string Example:schema_id=medtronic-percept-1 Dataset schema ID. See Key Concepts for details about valid schema IDs. |
Responses
200 Successful request
400 Bad request
401 Not authorized to perform the request
404 Not found
500 Internal server error
Example Response
{
"success": true,
"data": {
"statistics": {
"medtronic-percept-1": {
"bytes_uploaded": 2913131,
"first_upload_created_at": 1661799353.3680818,
"last_upload_created_at": 1661799453.3680818,
"number_of_uploads": 1
},
"strivestudy-healthkit-2": {
"bytes_uploaded": 67694947,
"first_upload_created_at": 1661799200.3680818,
"last_upload_created_at": 1661799453.3680818,
"number_of_uploads": 12
},
"strivestudy-applewatch-1": {
"bytes_uploaded": 94847584,
"first_upload_created_at": 1661799200.3680818,
"last_upload_created_at": 1661799453.3680818,
"number_of_uploads": 21
}
}
}
}