# 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. |

#### 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 |

#### 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
----