# LibreView API Doc for App ## Get OAuth URL Get the OAuth URL for connecting LibreView account. ###### tags: libreview ### Request #### Method `GET /api/wearables/libreview/oauth_url` #### Header N/A #### URL Params N/A #### Body Params N/A ### Response #### Success **Code:** `200 (OK)` **Content:** `JSON` ```json { "status": 0, "error": null, "message": null, "data": { "oauth_url": "https://oauth-sandbox.adc-phoenix.com/oauth2/auth?response_type=code&client_id=2ebf0e5b-9440-4eb9-8db6-c1809fd69030&redirect_uri=https://dev.health2sync.com/libreview_connect/callback&scope=offline+openid+read.glucose+read.glucometrics+write.insulin&state=thisIsMyState" }, "return_code": 0 } ``` #### Failure **Code:** `404 (Not Found)` **Content:** `JSON` ```json { "status": 5, "error": "resource_not_available", "message": "Not Found", "data": {}, "return_code": 5 } ``` When authentication is completed, it will provide redirect URL for app to check status. The URL would be the format: health2sync://libreview/{status}. | status | description | | ------ | ----------- | | finished | libreview connect successfully | | replace_and_finished | overwrite others and connect successfully | | consent_request_denied | user denied the consent request | | unexpected_error | | ---- ## Disconnect Disconnect from LibreView account. ###### tags: libreview ### Request #### Method `POST /api/wearables/libreview/disconnect` #### Header | Field | Type | Value | | --- | --- | --- | #### URL Params N/A #### Body Params N/A ### Response #### Success **Code:** `200 (OK)` **Content:** `JSON` ```json { "return_code": 0 "status": 0, "error": null, "message": null, "data": {} } ``` #### Failure **Code:** `404 (Not Found)` **Content:** `JSON` ```json { "status": 5, "error": "resource_not_available", "message": "Not Found", "data": {}, "return_code": 5 } ``` ---- ## Get connection status Get current status of LibreView connection ###### tags: libreview ### Request #### Method `GET /api/wearables/libreview/status` #### Header | Field | Type | Value | | --- | --- | --- | #### URL Params N/A #### Body Params N/A ### Response #### Success **Code:** `200 (OK)` **Content:** `JSON` ```json { "return_code": 0 "status": 0, "error": null, "message": null, "data": { "is_connected": true } } ``` | Field | Type | Description | | ----- | ---- | ----------- | | is_connected | boolean | `true` if connected to a LibreView account, else `false` | #### Failure **Code:** `404 (Not Found)` **Content:** `JSON` ```json { "status": 5, "error": "resource_not_available", "message": "Not Found", "data": {}, "return_code": 5 } ``` ---- ## Get all connections status Get current status of all connection ###### tags: libreview ### Request #### Method `GET /api/wearables/status` #### Header | Field | Type | Value | | --- | --- | --- | #### URL Params N/A #### Body Params N/A ### Response #### Success **Code:** `200 (OK)` **Content:** `JSON` ```json { "return_code": 0 "status": 0, "error": null, "message": null, "data": { "wearables": [ { "name": "fitbit", "is_connected": false }, { "name": "libreview", "is_connected": true } ] } } ``` | Field | Type | Description | | ----- | ---- | ----------- | | wearables[i].name | string | The name of wearable device | | wearables[i].is_connected | boolean | `true` if connected to a LibreView account, else `false` | #### Failure N/A ---- ## Get settings Get personal CGM data settings ###### tags: `libreview` ### Request #### Method `GET /api/wearables/libreview/cgm/settings` #### Header | Field | Type | Value | | --- | --- | --- | #### URL Params N/A #### Body Params N/A ### Response #### Success **Code:** `200 (OK)` **Content:** `JSON` ```json { "return_code": 0 "status": 0, "error": null, "message": null, "data": { "unit": "mg/dL", "target_range_low": 90, "target_range_high": 180 } } ``` | Field | Type | Description | | ----- | ---- | ----------- | | unit | string | `mg/dL` or `mmol/L` | | target_range_low | float | | | target_range_high | float | | **Mapping Table of Region and Unit** | Region | Unit | | ------ | ---- | | Japan | mg/dL | | Australia | mmol/L | | Singapore | mmol/L | | Hong Kong | mmol/L | #### Failure N/A ---- ## Put settings Update personal CGM data settings ###### tags: `libreview` ### Request #### Method `PUT /api/wearables/libreview/cgm/settings` #### Header | Field | Type | Value | | --- | --- | --- | | Content-Type | string | application/json | #### URL Params N/A #### Body Params ```json= { "target_range_low": 90, "target_range_high": 180 } ``` | Field | Type | Decription | | ----- | ---- | ---------- | | target_range_low `required` | float | | | target_range_high `required` | float | | ### Response #### Success **Code:** `200 (OK)` **Content:** `JSON` ```json { "return_code": 0 "status": 0, "error": null, "message": null, "data": { "target_range_low": 90, "target_range_high": 180 } } ``` | Field | Type | Description | | ----- | ---- | ----------- | | target_range_low | float | | | target_range_high | float | | #### Failure **Code:** `400 (Bad Request)` **Content:** `JSON` ```json { "status": 1, "error": "invalid_request", "message": "Invalid Request", "data": {}, "return_code": 1 } ``` **Code:** `403 (Forbidden)` **Content:** `JSON` ```json { "status": 6, "error": "libreview_not_connect", "message": "Forbidden", "data": {}, "return_code": 6 } ``` **Code:** `404 (Not Found)` **Content:** `JSON` ```json { "status": 5, "error": "resource_not_available", "message": "Not Found", "data": {}, "return_code": 5 } ``` ---- ## Get daily data Get daily data, including time in range and glucose values. ###### tags: `libreview` ### Request #### Method `POST /api/wearables/libreview/cgm/daily_data` #### Header | Field | Type | Value | | --- | --- | --- | | Content-Type | string | application/json | #### URL Params N/A #### Body Params ```json { "date_specific": "2021-05-01" } ``` | Field | Type | Description | | ----- | ---- | ----------- | | date_specific | string | The date you want to get the data, format is `YYYY-mm-dd` in local time | ### Response #### Success **Code:** `200 (OK)` **Content:** `JSON` ```json { "return_code": 0 "status": 0, "error": null, "message": null, "data": { "time_in_range": { "very_high": 14, "high": 19, "target_range": 54, "low": 7, "very_low": 6 }, "continuous_glucose": { "unit": "mg/dL", "entries": [ { "timestamp": 1619140923, "value": 136 }, ... ] } } } ``` | Field | Type | Description | | ----- | ---- | ----------- | | time_in_range | object | percentile for time in range, if no data can be shown, it will set `null` | | time_in_range.very_high | integer | Proportion of values greater than `high glucose threshold` | | time_in_range.high | integer | Proportion of values between `high glucose threshold` and `target range high limit` | | time_in_range.target_range | integer | Proportion of values between `target range high limit` and `target range low limit` | | time_in_range.low | integer | Proportion of values between `low glucose threshold` and `target range low limit` | | time_in_range.very_low | integer | Proportion of values less than `low glucose threshold` | | continuous_glucose.unit | string | The unit of glucose. `mg/dL` or `mmol/L` | | continuous_glucose.entries | array | A list of glucose entries, it sorts by timestamp in `ascending` order | continuous_glucose.entries[i].timestamp | integer | The UNIX timestamp of the entry in UTC | | continuous_glucose.entries[i].value | float or integer | The glucose value of the record. | ![](https://i.imgur.com/M1aZQPO.png) #### Failure N/A ---- ## Get trend data Get trend data, including time in range, glucose ranges and targets, average glucose, glucose variablility (%CV), estimated a1c, glucose count and AGP. ###### tags: `libreview` ### Request #### Method `POST /api/wearables/libreview/cgm/trend_data` #### Header | Field | Type | Value | | --- | --- | --- | | Content-Type | string | application/json | #### URL Params N/A #### Body Params ```json { "date_from": "2021-05-01", "date_to": "2021-05-30" } ``` | Field | Type | Description | | ----- | ---- | ----------- | | date_from | string | The start date of trend data, format is `YYYY-mm-dd` in local time | | date_to | string | The end date of trend data, format is `YYYY-mm-dd` in local time | ### Response #### Success **Code:** `200 (OK)` **Content:** `JSON` ```json { "return_code": 0 "status": 0, "error": null, "message": null, "data": { "time_in_range": { "very_high": 14, "high": 19, "target_range": 54, "low": 7, "very_low": 6 }, "agp": [ { "time": "00:00", "percentile_05": 96.0, "percentile_25": 116.9, "percentile_50": 194.25, "percentile_75": 244.2, "percentile_95": 275.7 }, { "time": "00:15", "percentile_05": 99.3, "percentile_25": 115.3, "percentile_50": 192.42, "percentile_75": 241.3, "percentile_95": 272.7 }, ... ], "glucose_statistics": { "estimated_a1c": 9.1, "cv": 42.3, "average": 196, "count": 802, "ranges_and_targets": [ { "target_range": 50.6, "below_range": 4.6, "above_range": 44.8, "median": 186.0 }, { "target_range": 51.0, "below_range": 5.0, "above_range": 44.0, "median": 191.0 }, ... ] } } } ``` | Field | Type | Description | | ----- | ---- | ----------- | | time_in_range.very_high | integer | Proportion of values greater than `upper target threshold` | | time_in_range.high | integer | Proportion of values between `upper target threshold` and `upper target range` | | time_in_range.target_range | integer | Proportion of values between `upper target range` and `lower target range` | | time_in_range.low | integer | Proportion of values between `lower target threshold` and `lower target range` | | time_in_range.very_low | integer | Proportion of values less than `lower target threshold` | | agp | array | Ambulatory Glucose Profile. It should have 96 records (1 record per 15 minutes) | | agp[i].time | string | The time period | | agp[i].percentile_05 | float or integer | The average of the smoothed, 5th percentile values in every 15 minutes bin. The standard display for this value is integer for mg/dL, one decimal place for mmol/L. | | agp[i].percentile_25 | float or integer | The average of the smoothed, 25th percentile values in every 15 minutes bin. The standard display for this value is integer for mg/dL, one decimal place for mmol/L. | | agp[i].percentile_75 | float or integer | The average of the smoothed, 75th percentile values in every 15 minutes bin. The standard display for this value is integer for mg/dL, one decimal place for mmol/L. | | agp[i].percentile_95 | float or integer | The average of the smoothed, 95th percentile values in every 15 minutes bin. The standard display for this value is integer for mg/dL, one decimal place for mmol/L. | | agp[i].percentile_50 | float or integer | The median | | glucose_statistics.estimated_a1c | float | The estimated HbA1c | | glucose_statistics.cv | float | The coefficient of variation | | glucose_statistics.average | float or integer | The mean of the glucose measurements | | glucose_statistics.count | integer | The count of glucose values | | glucose_statistics.ranges_and_targets | array | The percentile of range and target distribution, and median. It should have 24 records (1 record per hour) | glucose_statistics.ranges_and_targets[i].target_range | float | The glucose percentile in the target range | | glucose_statistics.ranges_and_targets[i].below_range | float | The glucose percentile below the target range | | glucose_statistics.ranges_and_targets[i].above_range | float | The glucose percentile above the target range | | glucose_statistics.ranges_and_targets[i].median | float or integer | The median of the glucose values | ![](https://i.imgur.com/JN6o0Y9.png) #### Failure N/A ---- ## Get dates with data Get a list of date that have glucose data ###### tags: `libreview` ### Request #### Method `GET /api/wearables/libreview/cgm/dates_with_data` #### Header | Field | Type | Value | | --- | --- | --- | #### URL Params N/A #### Body Params N/A ### Response #### Success **Code:** `200 (OK)` **Content:** `JSON` ```json { "return_code": 0 "status": 0, "error": null, "message": null, "data": { "dates_with_data": [ "2021-10-10", "2021-09-18", "2021-07-07", "2021-06-04", "2021-03-29", "2021-02-28", "2021-01-01", ... ] } } ``` | Field | Type | Description | | ----- | ---- | ----------- | #### Failure **Code:** `404 (Not Found)` **Content:** `JSON` ```json { "status": 5, "error": "resource_not_available", "message": "Not Found", "data": {}, "return_code": 5 } ``` ---- ## Get subscription plan (removed) Get a list of subscription plan ###### tags: `libreview` ### Request #### Method `GET /api/wearables/libreview/cgm/subscription/plan` #### Header N/A #### URL Params N/A #### Body Params N/A ### Response #### Success **Code:** `200 (OK)` **Content:** `JSON` ```json { "return_code": 0 "status": 0, "error": null, "message": null, "data": { "plans": [ { "id": 1, "days": 7, "product_id": "dev.com.h2.subscription.cgm.free_trial" }, { "id": 2, "days": 30, "product_id": "dev.com.h2.subscription.cgm.one_month" }, { "id": 3, "days": 60, "product_id": "dev.com.h2.subscription.cgm.two_month" }, { "id": 4, "days": 90, "product_id": "dev.com.h2.subscription.cgm.three_month" } ] } } ``` | Field | Type | Description | | ----- | ---- | ----------- | | plans[i].id | integer | plan id. If the user has any subscriptions history, the `free_trial` plan will not be shown. | | plans[i].days | integer | the subscription days of the plan | | plans[i].product_id | string | the In App Purchase's Product ID | **plan list for dev:** | id | value | description | | -- | ----- | ----------- | | 1 | dev.com.h2.subscription.cgm.free_trial | 7 days trial | | 2 | dev.com.h2.subscription.cgm.one_month | 1 month subscription | | 3 | dev.com.h2.subscription.cgm.two_month | 2 months subscription | | 4 | dev.com.h2.subscription.cgm.three_month | 3 months subscription | **plan list for prod:** | id | value | description | | -- | ----- | ----------- | | 1 | prod.com.h2.subscription.cgm.free_trial | 7 days trial | | 2 | prod.com.h2.subscription.cgm.one_month | 1 month subscription | | 3 | prod.com.h2.subscription.cgm.two_month | 2 months subscription | | 4 | prod.com.h2.subscription.cgm.three_month | 3 months subscription | #### Failure N/A ---- ## Get subscription (removed) Get a list of subscription history ###### tags: `libreview` ### Request #### Method `GET /api/wearables/libreview/cgm/subscription` #### Header N/A #### URL Params N/A #### Body Params N/A ### Response #### Success **Code:** `200 (OK)` **Content:** `JSON` ```json { "return_code": 0 "status": 0, "error": null, "message": null, "data": { "is_active": true, "subscriptions": [ { "id": 168, "plan_id": 4, "start_date": "2021-06-25", "due_date": "2021-09-25", "purchase_date": "2021-05-01", "currency": "TWD", "amount": 300 }, { "id": 57, "plan_id": 3, "start_date": "2021-04-24", "due_date": "2021-06-24", "purchase_date": "2021-04-24", "currency": "USD", "amount": 200 }, { "id": 30, "plan_id": 2, "start_date": "2021-03-23", "due_date": "2021-04-23", "purchase_date": "2021-03-23", "currency": "JPY", "amount": 300 }, { "id": 13, "plan_id": 1, "start_date": "2021-03-15", "due_date": "2021-03-22", "purchase_date": "2021-03-15", "currency": "TWD", "amount": 0 }, ... ] } } ``` | Field | Type | Description | | ----- | ---- | ----------- | | is_active | boolean | the subscription status | | subscriptions[i].id | integer | the subscription id | | subscriptions[i].plan_id | integer | the subscription plan id | | subscriptions[i].start_date | string | the start date of the subscription | | subscriptions[i].due_date | string | the due date of the subscription | | subscriptions[i].purchase_date | string | the purchase date of the subscription | | subscriptions[i].currency | string | the currency code of the transaction | | subscriptions[i].amount | float | the amount of the transaction | #### Failure N/A ---- ## POST subscription (removed) Create a subscription ###### tags: `libreview` ### Request #### Method `POST /api/wearables/libreview/cgm/subscription` #### Header | Field | Type | Value | | --- | --- | --- | | Content-Type | String | application/json | #### URL Params N/A #### Body Params ```json <iOS Sample> { "plan_id": 2, "platform": "iOS", "currency": "TWD", "amount": 100, "receipt": "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" } ``` ```json <Android Sample> { "plan_id": 2, "platform": "Android", "currency": "TWD" "amount": 100, "receipt": "{\"orderId\": \"GPA.3382-7356-0878-23339\", \"purchaseToken\": \"idjljlipnedhiedhcahidagf.AO-J1OxN_RTzYNY0VM_GxJzLqYUrN6xtz5ZbBQAEJtJsEXNVXzTG_Bf7wFY4WHodWP7whP1jtnxvCQp8_5w9nf73ZopNStWZV2S2Dyc-ajpj5E0YWs-BBHkOw9-ilx4dQtIbqmj6F9ij2EoKE-gGcWQOt1iGmXvd-Q\", \"packageName\": \"com.h2sync.android.h2syncapp\", \"purchaseState\": 0, \"purchaseTime\": 1505446136283, \"productId\": \"com.h2.subscription.cgm.one_month\"}", "signature": "Im27prAnxYwdRoug..." } ``` | Field | Type | Description | | ----- | ---- | ----------- | | plan_id | integer | the subscription plan id | | platform | string | the platform name. Accepted string: `iOS` and `Android` (case-sensitive) | | currency | string | the currency code of the transaction | | amount | float | the amount of the transaction | | receipt | string | the receipt of the transaction. The receipt data from `iOS` should be encoded in Base64 | | signature `optional` | string | the signature is only required for `Android` | | reason `optional` | string | the extra comment to describe this subscription | ### Response #### Success **Code:** `200 (OK)` **Content:** `JSON` ```json { "return_code": 0 "status": 0, "error": null, "message": null, "data": { "id": "235", "plan_id": 2, "start_date": "2021-03-19", "due_date": "2021-04-19", "purchase_date": "2021-03-19", "currency": "TWD", "amount": 100 } } ``` | Field | Type | Description | | ----- | ---- | ----------- | | id | integer | the subscription id | | plan_id | integer | the subscription plan id | | start_date | string | the start date of the subscription | | due_date | string | the due date of the subscription | | purchase_date | string | the purchase date of the subscription | | currency | string | the currency code of the transaction | | amount | float | the amount of the transaction | #### Failure **Code:** `400 (Bad Request)` **Content:** `JSON` ```json { "status": 1, "error": "invalid_request", "message": "Invalid Request", "data": {}, "return_code": 1 } ``` **Code:** `400 (Bad Request)` **Content:** `JSON` ```json { "status": 1, "error": "invalid_receipt", "message": "Invalid Request", "data": {}, "return_code": 1 } ``` **Code:** `400 (Bad Request)` **Content:** `JSON` ```json { "status": 1, "error": "invalid_plan", "message": "Invalid Request", "data": {}, "return_code": 1 } ``` **Code:** `400 (Bad Request)` **Content:** `JSON` ```json { "status": 1, "error": "duplicate_free_trial", "message": "Invalid Request", "data": {}, "return_code": 1 } ``` **Code:** `400 (Bad Request)` **Content:** `JSON` ```json { "status": 1, "error": "duplicate_order_id", "message": "Invalid Request", "data": {}, "return_code": -130 } ``` ---- ## v4 payment subscriptions (removed) Get all payment subscriptions history ###### tags: ### Request #### Method `GET /api/v4/payment/subscriptions` #### Header N/A #### URL Params N/A #### Body Params N/A ### Response #### Success **Code:** `200 (OK)` **Content:** `JSON` ```json { "return_code": 0 "status": 0, "error": null, "message": "payment subscriptions", "data": { "coach": [...], "clinic": [...], "premium": [...], "cgm": [ { "id": 168, "os": "iOS", "price": 100, "currency_code": "TWD", "title": "plan_id_1", "status": "active", "start_date": "2021-06-22", "due_date": "2021-09-22", "paid_dates": ["2021-05-01"], "order_dates": ["2021-05-01"], "reason": null }, ... ] } } ``` #### Failure N/A ----