====== API Help ====== This manual is intended to help in accessing and downloading data from the cosinuss° Health Platform using a RESTful API. First, you will have an overview of the data structure and further below the API commands to download the respective data. ===== Data structure ===== ==== Basics ==== Every Gateway creates one data file per day. As soon as the day is over, the respective data file is "closed" and will be no longer modified. The data files have names (hash IDs) like "WSJJU7.HJZ3E3", where the first part is the serial of the Gateway which created it (here: WSJJU7), the second part (HJZ3E3) just a randomly created key. ==== Meta information ==== For each data file there is meta data that you can download separately. The following meta information is available: * hash_id: (Hash) Identifier of this data file consisting of their serial of the Gateway and 6 random characters. * project: The hash ID of the project. * person: The hash ID of the person to which the data belongs. * receiver: The serial of the Gateway * device: The serial of the in-ear sensor that was used for recording the data. * status_closed: If true, then that day is over and no data will be added. * duration: The duration from the start of the data file to the last data point. * cols: List of available data types ("columns"). * date_time_start: Date and time when the data file was created. * date_time_end: Date and time when the data file was closed. An example for date_time_start would be: "Sat, 27 Jun 2020 20:04:29 GMT" That means the data file was created on the 27th of June 2020 at 8:04 p.m. and 29 seconds in Greenwich Mean Time (GMT). All downloadable x values are given in seconds relative to date_time_start. So if x is for example x = 70.0 s then the corresponding time stamp will be at 20:05 p.m. and 39.0 seconds. ==== Data Types ==== There are several data types that can come with a data file like heart rate, battery level, temperature, … The meta information "cols" tells you, which data types are available in each specific data file. See here the complete list of data types with a short description: **x** For all datatypes, **x** is the time in s, relative to the start of this data file (**date_time_start** from the meta information). ---- **heart_rate ** * Heart Rate * Heart rate is the average number of heartbeats measured by the number of contractions of the heart per minute (bpm). * y: values in bpm **rr_int ** * Beat-to-beat intervals * The time intervals elapsing between two consecutive R waves in the electrocardiogram. It can be used to calculate the heart rate variability, stress level and fatigue among others. It is a measure for the time interval changes between successsive heartbeats. * y: values in ms **spo2 ** * SpO2 * SpO2 is a measure for the oxygen saturation of the blood. It is the fraction of oxygen-saturated hemoglobin relative to total hemoglobin. * y: values in % **acc_x ** * Accelleration x-axis * Accelleration of the sensor in forward/backward direction (when worn on the ear). * y: values in g **acc_y ** * Accelleration y-axis * Accelleration of the sensor in upward/downward direction (when worn on the ear). * y: values in g **acc_z ** * Accelleration z-axis * Accelleration of the sensor in right/left direction (when worn on the ear). * y: values in g **ppg_green (Only for cosinuss° Three)** * PPG Green * Photopletysmogram (PPG) measured with a green LED. PPG can detect blood volume changes inside the tissue. * y: values in a.u. **ppg_ir ** * PPG Infrared * Photopletysmogram (PPG) measured with an infrared LED. PPG can detect blood volume changes inside the tissue. The red and infrared PPG signals are used for calculating the oxygen saturation of the blood. * y: values in a.u. **ppg_red ** * PPG Red * Photopletysmogram (PPG) measured with a red LED. PPG can detect blood volume changes inside the tissue. The red and infrared PPG signals are used for calculating the oxygen saturation of the blood. * y: values in a.u. **ppg_ambient ** * PPG Ambient * Ambient light measured with a photo diod when the other LEDs are switched off. If this value is high, the sensor is not properly sitting in the ear. The ambient light by default gets subtracted from the other ppg values (red, infrared, green). * y: values in a.u. **battery ** * Battery * The battery level of the in-ear sensor in %. * y: values in % **temperature ** * In-ear core body temperature. * The temperature measured by the in-ear sensors in °C. If the sensor is properly applied in the ear, it measures the core body temperature. If the temperature is lower than the expected body temperature, this can be a sign that the sensor is not applied right or the wrong size. * y: values in °C **temperature_ct (Only for c-med° alpha)** * Additional contact thermometer temperature, only for technical functionalities! * y: values in °C **temp_ir_ambient (Only for c-med° alpha)** * Additional ambient temperature measured by infrared thermometer, only for technical functionalities! * y: values in °C **perfusion_ir ** * Perfusion infrared. * A ppg signal's amplitude (AC) is typically atlernating around an offset (DC). The AC part of the signal is for example used for detecting the heart beat. The ratio of AC/DC of the infrared PPG signal is called Perfusion. It could be described as an indicator of how 'strong' the pulse is that is currently measured and therefore an indicator for the signal quality. * y: values in % **quality ** * Quality * Quality index calculated on the in-ear sensor. It is a measure for the reliability of the currently calculated heart rate values. * y: values in a.u. **respiration_rate ** * Respiration Rate * Respiration rate in 1/min (brpm). * y: values in brpm **ppg_quality ** * PPG Quality * Quality assessing reliability of the respiration rate and blood oxygen saturation. * y: values in a.u. **ppg_med ** * PPG Medical * High pass filtered ppg signal that shows the ppg signal like typically used to be shown by other medical devices. * y: values in a.u. **ble_packet_counter ** * BLE Packet Counter * A counter for the received Bluetooth Low Energy (BLE) packages. 1 Counter value per package. One package can contain about 50-75 PPG values. This can be used as an indicator for lost packages. * y: values in a.u. **ble_sample_counter ** * BLE Sample Counter * A counter for the received samples that were transferred via BLE. This is an indicator for lost samples. * y: values in a.u. **ble_sample_amount ** * BLE Sample Amount * The amount of samples in one BLE package. * y: values in a.u. ===== API Use ===== This brief tutorial shows the basic RESTful API requests with a curl example. The return is always JSON. You may use your favorite HTTP/REST library available for your programming language to make HTTP calls to our API. The **BASE-URL** is https://health.cosinuss.com/api/v3/ ==== Token Authentication ==== **Note**: Before a specific user account can use the API, an admin user must assign * the **role "api"** * and the **projects** to be accessed to the API user account by selecting the user from the [[https://health.cosinuss.com/admin/users|overview]] and then clicking "edit user". If that is not done then, the API user has no access or might not receive all data. The login route is simply BASE-URL/login Add **username** and **password** to the headers. Before the first request you need to login with a valid user account: curl -H "username: alice" -H "password: Sec7e1Passw0rd" https://health.cosinuss.com/api/v3/login You will get back a temporary token for authentication (expire time, a few hours): { "x_auth_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VybmFtZSI6InVzZXIudmlld2VyIiwiZXhwIjoxNTkzNDcwODkxfQ.wq_ohjm7aTo225dRdbgvFFO7lmAb2BvceffdAwCI69k" } For any further request use this token in the header: curl -H "X-AUTH-TOKEN: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VybmFtZSI6InVzZXIudmlld2VyIiwiZXhwIjoxNTkzNDcwODkxfQ.wq_ohjm7aTo225dRdbgvFFO7lmAb2BvceffdAwCI69k" https://health.cosinuss.com/api/v3/data_files You can try all following API routes by simply using the base URL and the given API routes with the command line tool **curl** or any other library (e.g. [[https://pypi.org/project/requests/|requests]] in Python). The upper line would be curl -H "X-AUTH-TOKEN: " BASE-URL/date_files ==== Positive and negative responses ==== For most routes the response JSON may either contain the keywords ''success'' for positive outcomes or ''fail'' if something went wrong (e.g. failed authentication or a a file was not found). { "status": "success", "message": "", "data": ... } or { "status": "fail", "message": "some error message", "data": {} } ==== Get Project IDs ==== Get a list of all project IDs: BASE-URL/projects ==== Get People IDs ==== Get a list of all people IDs: BASE-URL/people Get a list of all people IDs of one project: BASE-URL/people/project/ ==== Get People Meta Data ==== Get a list of people's meta data from all projects BASE-URL/people/meta Only get the meta data of people from a specific project BASE-URL/people/meta/project/ Get the meta data of one specific person BASE-URL/person/meta/ person id is the combination of project id and person Pseudonym generated by the server. You need to enter them both as person id like: **project_id.person Pseudonym**, for example: if A1B2 is project_id and ABCD is the person Pseudonym, then the person_id is: **A1B2.ABCD** Example: { "data": { "hash_id": "A1B2.ABCD", "label": "patient001", "active": true, "project": "A1B2", "devices": [ "333YC2" ], "time_c": "2021-03-17 13:29:35.434000+01:00", "trigger_recording": null, "continuous_recording": false, "receivers": [ "ABC123" ] } } ==== Get Data File IDs ==== Get a list of all data file IDs: BASE-URL/data_files Get a list of all data file IDs of one project: BASE-URL/data_files/project/ Get a list of all data file IDs of one person: BASE-URL/data_files/person/ Get a list of all data file IDs, which have been modified since a specific date and time (time_m in UTC): BASE-URL/data_files/time_m/ please pay attention to the required format of <**year-month-day**> or <**year-month-day**T**hour:minutes:seconds**>, otherwise you would get a error message as: {"error":"wrong format for time_m (example: 2022-01-11T10:25:40)"} And use UTC for time_m! ==== Get a Data File and Meta Information ==== Get meta data of one data file: BASE-URL/data_file//meta Example: BASE-URL/data_file/G1C2B5.UV4M1D/meta Response (formatted): { "data": { "cols": [ "battery", "ble_packet_counter", "ble_sample_amount", "ble_sample_counter", "heart_rate", "perfusion_ir", "ppg_ambient", "ppg_ir", "ppg_quality", "ppg_red", "quality", "respiration_rate", "rr_int", "spo2", "temperature" ], "comments": [], "date_time_end": "Sat, 27 Jun 2020 20:04:29 GMT", "date_time_start": "Fri, 26 Jun 2020 10:17:08 GMT", "device": "X6EE0F", "device_model": "two", "duration": 7412.4355829999995, "hash_id": "G1C2B5.UV4M1D", "person": "0RFM.5JW1", "person_label": "Testperson01", "project": "0RFM", "receiver": "G1C2B5", "status_closed": true } } Get data for a given 'data type': BASE-URL/data_file///data The available data types are listed in the meta data of each data file e.g.: 'battery', 'ble_packet_counter', 'ble_sample_amount', 'ble_sample_counter', 'heart_rate', 'perfusion_ir', 'ppg_ambient', 'ppg_ir', 'ppg_quality', 'ppg_red', 'quality', 'respiration_rate', 'rr_int', 'spo2', 'temperature', … Example: BASE-URL/data_file/G1C2B5.UV4M1D/heart_rate/data Response (formatted): { "data": { "x": [ 72.02425384521484, 72.85407257080078, 73.8526382446289, ..., 7408.6787109375, 7409.45751953125, 7410.48681640625 ], "y": [ 70.0, 69.0, 68.0, ..., 85.0, 86.0, 86.0 ] } } ==== Get Data Chunk Statistic ==== The data get recorded in data chunks (default 15 min) and for every single chunk you can get a statistic of the contained data. So you get mean, max, min, median, etc. for each data chunk and data type. **For a known data file hash:** BASE-URL/data_file//chunks The shorted result will be a string like BASE-URL/data_file/G1C2B5.UV4M1D/chunks { "data": [ { "battery": { "lower_quartile": 100.0, "max": 100.0, "mean": 100.0, "median": 100.0, "min": 100.0, "samples": 1, "upper_quartile": 100.0 }, "date_time_start": "2020-08-26 11:13:55.902000+02:00", "duration": 142.75, "heart_rate": { "lower_quartile": 52.0, "max": 52.0, "mean": 52.0, "median": 52.0, "min": 52.0, "samples": 1, "upper_quartile": 52.0 }, ..., "temperature": { "lower_quartile": 35.5, "max": 35.7, "mean": 35.55, "median": 35.6, "min": 35.4, "samples": 174, "upper_quartile": 35.6 }, "time_offset": 1092.808687 }, { "battery": { "lower_quartile": null, "max": null, "mean": null, "median": null, "min": null, "samples": 0, "upper_quartile": null }, "date_time_start": "2020-08-26 11:19:04.565000+02:00", "duration": 147.0, "heart_rate": { "lower_quartile": null, "max": null, "mean": null, "median": null, "min": null, "samples": 0, "upper_quartile": null }, ... }, ... ] } ==== Get Data by Chunk ==== This route is similar to [[#get_data_chunk_statistic|Get Data Chunk Statistic]] but with this request you get kind of aggregated data, one data point per chunk and data type. For spo2 it's the max, for perfusion_ir it's the min and for all other data types it's the median. **For a known data file hash:** BASE-URL/data_file//data_by_chunk The result will be a string like BASE-URL/data_file/G1C2B5.UV4M1D/data_by_chunk { "data": { "date_time_start": [ "2020-08-26 11:13:55.902000+02:00", "2020-08-26 11:19:04.565000+02:00", ... "2020-08-26 23:38:25.300000+02:00", "2020-08-26 23:41:51.694000+02:00" ], "heart_rate": [ 52.0, null, ... 55.0, 55.0 ], "perfusion_ir": [ 0.26, 0.13, ... 0.55, null ], "ppg_quality": [ null, null, ... 37.0, null ], "quality": [ 50.0, null, ... 27.0, 19.0 ], "respiration_rate": [ null, null, ... null, null ], "rr_int": [ null, null, ... 445.0, 1330.0 ], "spo2": [ 92.0, 94.0, ... 69.0, null ], "temperature": [ 35.6, 36.0, ... 37.0, 36.95 ], "time_offset": [ 1092.808687, 1401.471482, ... 45762.206182, 45968.60086 ], "duration": [ 142.75, 142.0, ... 142.2, 142.15 ] } } ==== Get Last Vital Parameters ==== You can get the parameters which are displayed on the Dash view of the cosinuss° Health Platform either for a single person or for all persons in a project. In the default setting of the Gateway, these values do not represent a single measurement point but either the minimum, maximum or median of all values that were recorded during the last recording cycle. If the receiver is set to send live data points (feature on request), the data will be the last recorded data point. The data is only available for 6 hours after it has been recorded and can then no longer be downloaded using this API call. The following abbreviations are used in the results JSON string and the square brackets indicate the calculation method based on the corresponding recording cycle. * "spo2": SpO2 [maximum], * "rr": Respiration rate [median], * "pi": Perfusion index [minimum], * "hr": Heart rate [median], * "q": Quality [median], * "temp": Temperature [median], * "bat": Battery percentage [median], * "XXX_time": ("spo2_time", "hr_time", ...) each data type above has an individual unix timestamp. It marks the time when that specific data point was received (or recorded in live mode). * "seconds": Unix timestamp when the last data points were received by the server. **For a specific person (any device):** BASE-URL/vitals/person/ The result will be a string like { "data": { "bat": 17, "bat_time": 1645020003.586026, "hr": 74, "hr_time": 1645020010.2649384, "person_label": null, "pi": 0.13, "pi_time": 1645020008.7545307, "q": 28, "q_time": 1645020010.271199, "rr": 30.0, "rr_time": 1645019978.5482578, "seconds": 1645020011.2, "spo2": 95, "spo2_time": 1645020008.7074695, "temp": 35.62, "temp_time": 1645020003.9922724 } } If there is no data for this person or if the last data for this person was received more than 6 hours ago, then the result will be empty. { "data": {} } **For a specific person and specific device:** BASE-URL/vitals/person// **For all persons in one project:** BASE-URL/vitals/project/ In this case the data of each person (here K4EXT1E4QP.17MV.251Z and K4EXT1E4QP.17MV.4URG) is listed under results. If the data of a person is older than 6 hours or not available, that person's data will be empty: { "data": { "0RFM.6UAX": {}, "0RFM.81LJ": { "bat": 17, "bat_time": 1645020003.586026, "hr": 74, "hr_time": 1645020010.2649384, "person_label": null, "pi": 0.13, "pi_time": 1645020008.7545307, "q": 28, "q_time": 1645020010.271199, "rr": 30.0, "rr_time": 1645019978.5482578, "seconds": 1645020011.2, "spo2": 95, "spo2_time": 1645020008.7074695, "temp": 35.62, "temp_time": 1645020003.9922724 }, "0RFM.AK13K": {}, } } ==== Get Person Events ==== If you have created [[public:cosinuss_health#people|Person Events]] you can get them with the following URLs for either all persons, all persons in a project or for a specific person: **For all persons** BASE-URL/person_events **For all persons in a project** BASE-URL/person_events/project/ **For a single person** BASE-URL/person_events/person/ The result will be a string like { "data": [ { "label": "Running", "person": "QNEV69NM1R.QGB0.8HRL", "project": "QNEV69NM1R.QGB0", "time": "2021-03-17 13:29:35.434000+01:00" }, { "label": "Walking", "person": "QNEV69NM1R.QGB0.8HRL", "project": "QNEV69NM1R.QGB0", "time": "2021-03-17 13:29:37.655000+01:00" }, { "label": "Sleeping", "person": "QNEV69NM1R.QGB0.8HRL", "project": "QNEV69NM1R.QGB0", "time": "2021-03-17 13:29:40.813000+01:00" } ] } If there are no Person Events found, the result will be empty. ==== Get Observation Events ==== You can download any submitted [[public:cosinuss_health#people|Observation Events]] using the following URLs for either all persons, all persons in a project or for a specific person: **For all persons** BASE-URL/observations **For all persons in a project** BASE-URL/observations/project/ **For a single person** BASE-URL/observations/person/ The result will be a string like { "data":[ { "comment":"spo2 value test", "data_type":"Spo2", "data_unit":"%", "data_value_1":95.0, "data_value_2":null, "device":"Finger clip", "person":"A7JR15WK56.JB50.1K04", "project":"A7JR15WK56.JB50", "time_created":"2021-09-28 14:31:12.758000+02:00", "time_recorded":"2021-09-28 08:30:52" }, { "comment":"BP test", "data_type":"systolic BP, diastolic BP", "data_unit":"mmHg", "data_value_1":120.0, "data_value_2":80.0, "device":"Blood pressure monitor", "person":"A7JR15WK56.JB50.1K04", "project":"A7JR15WK56.JB50", "time_created":"2021-09-28 14:33:50.577000+02:00", "time_recorded":"2021-09-23 08:31:47" } ] } If no Observation is submitted, the result will be empty. ==== Trigger a Recording ==== You can trigger a new recording for a specific person with a specified duration in seconds. The record will start the next time the Gateway is in contact with the server, which is by default once every 3 minutes. BASE-URL/trigger_record// The result will be a string like { "data": "trigger record 120 seconds of receiver "WSJJU7" from person "L6EH.EZ6Q"" } ==== Special APIs ==== This APIs have to be activated by cosinuss°. === Add a new person to a project === You can add a new person to a project. BASE-URL/person/new/ The result will be the created person id { "data": { "person_id": "A1B2.ABCD" } } === Edit a person === You can edit the following attributes of a person: * ''active'': true/false (boolean) * ''continuous_recording'': true/false (boolean) BASE-URL/person/edit The json-data of the following ''POST-request'' should follow this structure: { "person_id": "A1B2.ABCD", "active": false, "continuous_recording": false } === Relate a device or receiver to a person === You can relate a device or receiver to a person. BASE-URL/person//relate/ === Release a device or receiver from a person === You can release a device or receiver from a person. BASE-URL/person//release/ === Pull PPG-Med === You can pull the current ppg-med data of the last 10 seconds. BASE-URL/ppg_med// The result will look like this if ppg-med data available { "data": { "ppg_data": [[0.0, 0.4146428], [0.025, 0.39928573], [0.05, 0.36857146], [0.075, 0.33785713], [0.1, 0.30714285], ...] "min": -0.5912499999999999, "max": 0.7095, "time": "1694598676.7803364" } } The result will look like this if no ppg-med data available { "data": { "ppg_data": [[0, 0]] "min": 0, "max": 0, "time": 0 } } The result attributes will follow this structure: * ''ppg_data'': Array of datapoints (float) [[x1, y1], [x2, y2], ...] * ''min'': minimum used for plotting (float) * ''max'': maximum used for plotting (float) * ''time'': timestamp when data processed (integer or string) ===== Also Helpful ===== You may also be interested to download the Python example scripts and work with them in order to get an impression how the API works. [[public:api_python|API Help: Python Guidelines]] helps you step by step on how to use python to work with API and learn more about its work flow. You can fill in your user data and the script will download all available files and store it as .csv.