> For the complete documentation index, see [llms.txt](https://docs.habit.io/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.habit.io/how-to-create-a-custom-mobile-app-with-habit-analytics.md).

# How to create a custom mobile app with Habit Analytics

## Authentication

In order to interact with our API, clients must authenticate using the OAuth 2.0 protocol, in particular the [Resource Owner Password Credentials](https://tools.ietf.org/html/rfc6749#page-9) flow.

### **Account creation with mail (without mail validation)**

A **POST** call must be made using the /**v3/legacy/account** endpoint, providing the following parameters:

* *appId,* corresponding to the pre-generated ***client\_id*** that you should get from your previously created project on Selfcare
* *device,* indicating if is and 'android' or 'ios'
* *email*, indicating your user's mail
* *name*, indicating your user's name
* *password*, indicating your user's password
* *type,* should always be 'account'

The response will be populated with several attributes, mainly **authToken** and **id** (that corresponds to the *user-id*).

#### Call POST /**v3/legacy/account**

* Request (application/json)

```javascript
{
    "appId":"{application-namespace}",
    "device":"{android|ios}",
    "email":"{user-mail}",
    "name":"{user-name}",
    "password":"{password}",
    "type":"account"
}
```

* Response 200 (application/json)

```javascript
{
    "message":"user created and signed in",
    "success":true,
    "user":{
        "authToken":"{token}",
        "clientId":"{mobile-application-client-id}",
        "email":"{user-mail}",
        "id":"{user-id}",
        "name":"{user-name}",
        "newUser":true,
        "photoUrl":"https:\/\/cdn.muzzley.com\/users\/default.png",
        "token":"{access-token}"
    }
}
```

A **GET** call to **/v3/auth/authorize** should be immediately done to obtain all the other needed authentication information.

The response will be populated with, at least, 4 main attributes:

* *access\_token*, the actual token to be used in subsequent calls
* *expires*, the validity of the returned tokens
* *refresh\_token*, for refreshing this information, before *expires* is reached
* *endpoints*, an object containing the *HTTP* and *MQTT* base URLs assigned to the requesting client

#### Call GET **/v3/auth/authorize**

* Request parameters:
  * *response\_type* *\*\**&#x73;hould be *password* (required, string)
  * *scope* should be *application,user* (required, string)
  * *client\_id* is your application client-id generated by Selfcare (required, string)
  * *username*  (required, string)
  * password (required, string)&#x20;
* Response 200 (application/json)

```javascript
{
    "_id":"\/v3\/tokens\/{token}",
    "access_token":"{token}",
    "client_id":"{client-id}",
    "code":"{code}",
    "created":"2020-03-17T15:52:52.484+0000",
    "endpoints":
    {
            "http":"https:\/\/api.platform.muzzley.com",
            "mqtt":"mqtts:\/\/api.platform.muzzley.com:8881",
            "uploader":"https:\/\/assets.ci.habit.io"
    },
    "expires":"2020-06-15T15:52:51.618+0000",
    "grant_type":"password",
    "href":"\/v3\/tokens\/{token}",
    "id":"{id}",
    "owner_id":"{user-id}",
    "refresh_token":"{refresh-token}",
    "scope":["application","user"],
    "updated":"2020-03-17T15:52:52.484+0000"
}
```

For this first 2 calls the host to be used should be <https://api.platform.muzzley.com/> but all subsequent calls must be directed to the base URL provided in ***endpoints.http*** and an *Authorization* header must be added to every API call, in the form:

```
    Authorization: Bearer {access_token}
```

### **Account Sign in with the mail**

The response will be populated with, at least, 4 main attributes:

* *access\_token*, the actual token to be used in subsequent calls
* *expires*, the validity of the returned tokens
* *refresh\_token*, for refreshing this information, before *expires* is reached
* *endpoints*, an object containing the *HTTP* and *MQTT* base URLs assigned to the requesting client

#### Call GET /v3/auth/authorize

* Request parameters:
  * *client\_id* (required, string)
  * *refresh\_token* (required, string)
  * *grant\_type* (required, string)
  * *redirect\_uri* (optional, string)
* Response 200 (application/json)

```javascript
{
    "_id":"\/v3\/users\/{user-id}",
    "_rev":"3-94c1450541b80ec43c7503d7b2ec8e6c",
    "active_ts":"2019-05-24T09:58:16.824+0000",
    "cdata":null,
    "confirmation_hash":"qweqweqwe",
    "created":"2019-05-24T09:58:15.841+0000",
    "email":"{user-mail}",
    "href":"\/v3\/users\/{user-id}",
    "id":"{user-id}",
    "inactive_ts":"1970-01-01T00:00:00.000+0000",
    "name":"{user-name}",
    "namespace":"qweqweqwe",
    "secret":"qweqweqwe",
    "state":"active",
    "target_id":"{applciation-client-id}",
    "type":"users",
    "updated":"2019-05-24T09:58:16.825+0000"
}
```

## API Usage

For this first call the host to be used should be <https://api.platform.muzzley.com/> but all subsequent calls must be directed to the base URL provided in ***endpoints.http*** and an *Authorization* header must be added to every API call, in the form:

```
Authorization: Bearer {access_token}
```

### **Retrieve User**

The response will be populated with, at least, 4 main attributes:

* *id*, the user ID
* *name*, the user full name
* *namespace*, unique user namespace
* *state*, state of the user in the platform
* *target\_id*, application ID that the user belongs

#### Call GET /v3/users/\[me|:user-id]

* Response 200 (application/json)

```javascript
{
    "_id":"\/v3\/users\/{user-id}",
    "_rev":"3-94c1450541b80ec43c7503d7b2ec8e6c",
    "active_ts":"2019-05-24T09:58:16.824+0000",
    "cdata":null,
    "confirmation_hash":"qweqweqwe",
    "created":"2019-05-24T09:58:15.841+0000",
    "email":"{user-mail}",
    "href":"\/v3\/users\/{user-id}",
    "id":"{user-id}",
    "inactive_ts":"1970-01-01T00:00:00.000+0000",
    "name":"{user-name}",
    "namespace":"qweqweqwe",
    "secret":"qweqweqwe",
    "state":"active",
    "target_id":"{application-id}",
    "type":"users",
    "updated":"2019-05-24T09:58:16.825+0000"
}
```

### **List User Channels**

Channel Instance Ontology:

* *profileId* : Profile id of the database document.
* *channelId* : Channel instance id.
* *component* : An array of the parts that make up the actual channel instance.
* *id* : Component id such as "bulb-3"
* *type* : Component type (described in the channel spec).
* *label* : Channel component label such as "Nightstand Left".
* *property* : An array of properties listed in the channel spec.

#### Call GET /v3/legacy/users/{user-id}/channels

* Request parameters:
  * *include* (optional, string) # ex: channelProperties,context,capabilities
* Response 200 (application/json)

```javascript
{
   "_id":"\/v3\/legacy\/users\/{user-id}\/channels",
   "_rev":"9-3d8b450212eafb9a9e02e192349b6a8b",
   "channels":[
      {
         "_rev":"3-66beebb3261617dee4d80a789563bbd2",
         "categories":[
            "5478934836f3f24465ca061d"
         ],
         "components":[
            {
               "classes":[
                  "com.muzzley.components.sensor.smoke"
               ],
               "id":"smoke_sensor",
               "label":"Smoke Detector",
               "type":"smoke_sensor"
            }
         ],
         "content":"Device",
         "id":"9fc96b08-c654-11e8-8567-000d3a38a46d",
         "interface":{
            "etag":"0",
            "native":[

            ],
            "src":"",
            "url":"",
            "uuid":"bf76f033-d36a-4ce2-af5e-9208ddd3b7e0"
         },
         "isActionable":false,
         "isStateful":false,
         "isTriggerable":true,
         "photoUrl":"https:\/\/cdn.muzzley.com\/things\/profiles\/nest-v3\/allianz\/allianz-nest-protect-centered.jpg",
         "profileId":"3a200576-04e1-11e8-9059-6e8e8fac3ec8",
         "properties":[
            {
               "actions":[

               ],
               "agentLabel":"",
               "classes":[
                  "com.muzzley.properties.level.power.battery"
               ],
               "components":[
                  "smoke_sensor"
               ],
               "controlInterfaces":[
                  {
                     "config":{
                        "options":[
                           {
                              "label":"OK",
                              "value":"ok"
                           },
                           {
                              "label":"Replace",
                              "value":"replace"
                           },
                           {
                              "label":"Low",
                              "value":"low"
                           },
                           {
                              "label":"Full",
                              "value":"full"
                           }
                        ]
                     },
                     "controlInterface":"text-picker",
                     "id":"ci1"
                  }
               ],
               "id":"battery_health",
               "io":"rs",
               "isActionable":false,
               "isStateful":false,
               "isTriggerable":true,
               "label":"Batterie",
               "mainActionPriority":0,
               "mainInformationPriority":0,
               "onChange":false,
               "rateLimit":0,
               "requiredCapabilities":[

               ],
               "schema":"https:\/\/ontology.muzzley.com\/schemas\/v1\/battery-status-string",
               "schemaExtension":{

               },
               "states":[

               ],
               "triggers":[
                  {
                     "condition":"equals",
                     "id":"3054a645-3ddf-48e5-9cf3-6956ea68264e",
                     "inputs":[
                        {
                           "controlInterfaceId":"ci1",
                           "id":"value",
                           "path":[
                              {
                                 "source":"selection.value",
                                 "target":"data.value"
                              }
                           ]
                        }
                     ],
                     "inputsLabel":"{{value}}",
                     "label":"",
                     "predicateLabel":"is equal to"
                  }
               ],
               "unitsOptions":{
                  "muzzleyUnit":"",
                  "targetImperial":"",
                  "targetMetric":""
               }
            },
            {
               "actions":[

               ],
               "agentLabel":"",
               "classes":[
                  "com.muzzley.properties.status.co",
                  "com.muzzley.properties.status.co"
               ],
               "components":[
                  "smoke_sensor"
               ],
               "controlInterfaces":[
                  {
                     "config":{
                        "options":[
                           {
                              "label":"OK",
                              "value":"ok"
                           },
                           {
                              "label":"Warning",
                              "value":"warning"
                           },
                           {
                              "label":"Emergency",
                              "value":"emergency"
                           }
                        ]
                     },
                     "controlInterface":"text-picker",
                     "id":"ci1"
                  }
               ],
               "id":"co_status",
               "io":"rs",
               "isActionable":false,
               "isStateful":false,
               "isTriggerable":true,
               "label":"Statut CO",
               "mainActionPriority":0,
               "mainInformationPriority":0,
               "onChange":false,
               "rateLimit":0,
               "requiredCapabilities":[

               ],
               "schema":"https:\/\/ontology.muzzley.com\/schemas\/v1\/alarm-status",
               "schemaExtension":{

               },
               "states":[

               ],
               "triggers":[
                  {
                     "condition":"equals",
                     "id":"170547a5-9dc1-4f10-9328-5ba034d5e02a",
                     "inputs":[
                        {
                           "controlInterfaceId":"ci1",
                           "id":"value",
                           "path":[
                              {
                                 "source":"selection.value",
                                 "target":"data.value"
                              }
                           ]
                        }
                     ],
                     "inputsLabel":"{{value}}",
                     "label":"",
                     "predicateLabel":"is equal to"
                  }
               ],
               "unitsOptions":{
                  "muzzleyUnit":"",
                  "targetImperial":"",
                  "targetMetric":""
               }
            },
            {
               "actions":[

               ],
               "agentLabel":"",
               "classes":[
                  "com.muzzley.properties.status.smoke"
               ],
               "components":[
                  "smoke_sensor"
               ],
               "controlInterfaces":[
                  {
                     "config":{
                        "options":[
                           {
                              "label":"OK",
                              "value":"ok"
                           },
                           {
                              "label":"Warning",
                              "value":"warning"
                           },
                           {
                              "label":"Emergency",
                              "value":"emergency"
                           }
                        ]
                     },
                     "controlInterface":"text-picker",
                     "id":"ci1"
                  }
               ],
               "id":"smoke_status",
               "io":"rs",
               "isActionable":false,
               "isStateful":false,
               "isTriggerable":true,
               "label":"Statut Fum\u00e9e",
               "mainActionPriority":0,
               "mainInformationPriority":0,
               "onChange":false,
               "rateLimit":0,
               "requiredCapabilities":[

               ],
               "schema":"https:\/\/ontology.muzzley.com\/schemas\/v1\/alarm-status",
               "schemaExtension":{

               },
               "states":[

               ],
               "triggers":[
                  {
                     "condition":"equals",
                     "id":"51ed5e32-633a-49b6-9f84-8d6d358812cc",
                     "inputs":[
                        {
                           "controlInterfaceId":"ci1",
                           "id":"value",
                           "path":[
                              {
                                 "source":"selection.value",
                                 "target":"data.value"
                              }
                           ]
                        }
                     ],
                     "inputsLabel":"{{value}}",
                     "label":"",
                     "predicateLabel":"is equal to"
                  }
               ],
               "unitsOptions":{
                  "muzzleyUnit":"",
                  "targetImperial":"",
                  "targetMetric":""
               }
            },
            {
               "actions":[

               ],
               "agentLabel":"",
               "classes":[
                  "com.muzzley.properties.status.color"
               ],
               "components":[
                  "smoke_sensor"
               ],
               "controlInterfaces":[

               ],
               "id":"color_status",
               "io":"rs",
               "isActionable":false,
               "isStateful":false,
               "isTriggerable":false,
               "label":"Statut de Couleur",
               "mainActionPriority":0,
               "mainInformationPriority":0,
               "onChange":false,
               "rateLimit":0,
               "requiredCapabilities":[

               ],
               "schema":"https:\/\/ontology.muzzley.com\/schemas\/v1\/color-name",
               "schemaExtension":{

               },
               "states":[

               ],
               "triggers":[

               ],
               "unitsOptions":{
                  "muzzleyUnit":"",
                  "targetImperial":"",
                  "targetMetric":""
               }
            }
         ],
         "remoteId":"9fc96b08-c654-11e8-8567-000d3a38a46d",
         "tilePhotoUrl":"https:\/\/cdn.muzzley.com\/things\/profiles\/nest-v3\/nest-smoke_center.jpg",
         "user":"{user-id}"
      }
   ],
   "href":"\/v3\/legacy\/users\/{user-id}\/channels",
   "id":"channels"
}
```

### **List User Tiles**

Tiles are meant to represent a visual rendering of the most important properties and actions that physical devices can have, like a temperature reading, or an on/off switch.

#### Call GET /v3/legacy/users/{user-id}/tiles

* Request parameters:
  * *include* (optional, string) # ex: specs
* Response 200 (application/json)

```javascript
{
   "tiles":[
      {
         "_rev":"2-2cb3794172f6a8acd45607d176292c0e",
         "actions":[

         ],
         "channel":"{channel-id}",
         "channelInfo":{
            "backgroundPhotoUrl":"https:\/\/cdn.nest-protect-tiles.jpg",
            "id":"{id}",
            "photoUrl":"https:\/\/cdn.nest-protect-tiles.jpg",
            "profileId":"{channeltemplate-id}",
            "remoteId":"{remote-id}"
         },
         "components":[
            {
               "id":"smoke_sensor",
               "type":"smoke_sensor"
            }
         ],
         "groups":[
            "{group-id}"
         ],
         "href":"\/v3\/legacy\/tiles\/{tile-id}",
         "id":"{tile-id}",
         "information":[
            {
               "componentType":"smoke_sensor",
               "options":{
                  "inputPath":"data.value",
                  "mathExpression":"x * 100",
                  "prefix":"",
                  "suffix":"%"
               },
               "property":"battery_health",
               "type":"text-expression"
            }
         ],
         "isGroupable":false,
         "kind":"device",
         "label":"Device",
         "overlayUrl":"",
         "photoUrl":"https:\/\/cdn.nest-protect-tiles.jpg",
         "photoUrlAlt":"https:\/\/cdn.nest-protect-tiles.jpg",
         "profile":"{channeltemplate-id}",
         "user":"{user-id}"
      },
      {
         "_rev":"2-7d3cbf7f7647b28ccb9a95c4366d530a",
         "actions":[

         ],
         "channel":"{channel-id}",
         "channelInfo":{
            "backgroundPhotoUrl":"https:\/\/cdn.nest_thermostat_left.jpg",
            "id":"{id}",
            "photoUrl":"https:\/\/cdn.nest_thermostat_left.jpg",
            "profileId":"{channeltemplate-id}",
            "remoteId":"{remote-id}"
         },
         "components":[
            {
               "id":"thermostat",
               "type":"thermostat"
            }
         ],
         "groups":[
            "{group-id}"
         ],
         "href":"\/v3\/legacy\/tiles\/{tile-id}",
         "id":"{tile-id}",
         "information":[
            {
               "componentType":"thermostat",
               "options":{
                  "inputPath":"data.value",
                  "mathExpression":"x * 100",
                  "prefix":"",
                  "suffix":"%"
               },
               "property":"humidity",
               "type":"text-expression"
            },
            {
               "componentType":"thermostat",
               "options":{
                  "inputPath":"data.value",
                  "inputUnit":"C"
               },
               "property":"environment_temperature",
               "type":"text-unit"
            }
         ],
         "isGroupable":false,
         "kind":"device",
         "label":"Device",
         "overlayUrl":"",
         "photoUrl":"https:\/\/cdn/nest_thermostat_left.jpg",
         "photoUrlAlt":"https:\/\/cdn/nest_thermostat_left.jpg",
         "profile":"{channeltemplate-id}",
         "user":"{user-id}"
      },
      {
         "_id":"\/v3\/legacy\/tiles\/{tile-id}",
         "_rev":"1-d1780bc8367d83cd4dbea3c97a1bfe13",
         "actions":[
            {
               "componentType":"light-bulb",
               "options":{
                  "icon":"on_off",
                  "mappings":{
                     "off":false,
                     "on":true
                  },
                  "outputPath":"data.value"
               },
               "property":"status",
               "type":"tri-state"
            }
         ],
         "channel":"{channel-id}",
         "channelInfo":{
            "backgroundPhotoUrl":"https:\/\/cdn\/allianz-hue-left.jpg",
            "id":"{id}",
            "photoUrl":"https:\/\/cdn\/allianz-hue-left.jpg",
            "profileId":"{channeltemplate-id}",
            "remoteId":"{remote-id}"
         },
         "components":[
            {
               "id":"light-bulb",
               "type":"light-bulb"
            }
         ],
         "groups":[
            "{group-id}"
         ],
         "href":"\/v3\/legacy\/tiles\/{tile-id}",
         "id":"{tile-id}",
         "information":[
            {
               "componentType":"light-bulb",
               "options":{
                  "char":"\ue600",
                  "format":"hsv"
               },
               "property":"color",
               "type":"icon-color"
            },
            {
               "componentType":"light-bulb",
               "options":{
                  "inputPath":"data.value",
                  "mathExpression":"x * 100",
                  "prefix":"",
                  "suffix":"%"
               },
               "property":"brightness",
               "type":"text-expression"
            }
         ],
         "isGroupable":true,
         "kind":"device",
         "label":"office light",
         "overlayUrl":"https:\/\/cdn.\/muzzley_label_fr.png",
         "photoUrl":"https:\/\/cdn\/allianz-hue-left.jpg",
         "photoUrlAlt":"https:\/\/cdn\/allianz-hue-left.jpg",
         "profile":"{channeltemplate-id}",
         "user":"{user-id}"
      }
   ]
}
```

### **Units Table**

The Units table is needed to determine which conversions between metric and imperial systems are needed. Some devices output their measurements in either metric or imperial system, and conversion is done on-device, according to user preferences.

#### Call GET <https://cdn.muzzley.com/units/units_table.json>

* Response 200 (application/json)

```javascript
{
   "version":"1",
   "unitSpec":{
      "celsius":{
         "name":{
            "singular":"celsius",
            "plural":"celsius"
         },
         "prefix":"",
         "suffix":" °C",
         "decimalPlaces":1,
         "unitSystem":"metric",
         "public":true
      },
      "millimeter":{
         "name":{
            "singular":"millimeter",
            "plural":"millimeters"
         },
         "prefix":"",
         "suffix":" mm",
         "decimalPlaces":2,
         "unitSystem":"metric"
      },
      "centimeter":{
         "name":{
            "singular":"centimeter",
            "plural":"centimeters"
         },
         "prefix":"",
         "suffix":" cm",
         "decimalPlaces":2,
         "unitSystem":"metric"
      },
      "meter":{
         "name":{
            "singular":"meter",
            "plural":"meters"
         },
         "prefix":"",
         "suffix":" m",
         "decimalPlaces":1,
         "unitSystem":"metric",
         "public":true
      },
      "kilometer":{
         "name":{
            "singular":"kilometer",
            "plural":"kilometers"
         },
         "prefix":"",
         "suffix":" km",
         "decimalPlaces":1,
         "unitSystem":"metric"
      },
      "milligram":{
         "name":{
            "singular":"milligram",
            "plural":"milligrams"
         },
         "prefix":"",
         "suffix":" mg",
         "decimalPlaces":2,
         "unitSystem":"metric"
      },
      "gram":{
         "name":{
            "singular":"gram",
            "plural":"grams"
         },
         "prefix":"",
         "suffix":" gr",
         "decimalPlaces":1,
         "unitSystem":"metric",
         "public":true
      },
      "kilogram":{
         "name":{
            "singular":"kilogram",
            "plural":"kilograms"
         },
         "prefix":"",
         "suffix":" kg",
         "decimalPlaces":1,
         "unitSystem":"metric"
      },
      "milliliter":{
         "name":{
            "singular":"milliliter",
            "plural":"milliliters"
         },
         "prefix":"",
         "suffix":" ml",
         "decimalPlaces":2,
         "unitSystem":"metric"
      },
      "liter":{
         "name":{
            "singular":"liter",
            "plural":"liters"
         },
         "prefix":"",
         "suffix":" l",
         "decimalPlaces":1,
         "unitSystem":"metric",
         "public":true
      },
      "lp100km":{
         "name":{
            "singular":"liters per 100 kilometers",
            "plural":""
         },
         "prefix":"",
         "suffix":" l/100km",
         "decimalPlaces":1,
         "unitSystem":"metric"
      },
      "kmpl":{
         "name":{
            "singular":"kilometers per liter",
            "plural":""
         },
         "prefix":"",
         "suffix":" km/L",
         "decimalPlaces":1,
         "unitSystem":"metric",
         "public":true
      },
      "mps":{
         "name":{
            "singular":"meters per second",
            "plural":""
         },
         "prefix":"",
         "suffix":" m/s",
         "decimalPlaces":1,
         "unitSystem":"metric",
         "public":true
      },
      "kmph":{
         "name":{
            "singular":"kilometers per hour",
            "plural":""
         },
         "prefix":"",
         "suffix":" km/h",
         "decimalPlaces":0,
         "unitSystem":"metric"
      },
      "watt":{
         "name":{
            "singular":"watt",
            "plural":"watts"
         },
         "prefix":"",
         "suffix":" W",
         "decimalPlaces":4,
         "unitSystem":"metric",
         "public":true
      },
      "kilowatt":{
         "name":{
            "singular":"kilowatt",
            "plural":"kilowatts"
         },
         "prefix":"",
         "suffix":" kW",
         "decimalPlaces":2,
         "unitSystem":"metric"
      },
      "mbar":{
         "name":{
            "singular":"millibar",
            "plural":"millibars"
         },
         "prefix":"",
         "suffix":" mbar",
         "decimalPlaces":1,
         "unitSystem":"metric",
         "public":true
      },
      "bar":{
         "name":{
            "singular":"bar",
            "plural":"bars"
         },
         "prefix":"",
         "suffix":" bar",
         "decimalPlaces":0,
         "unitSystem":"metric"
      },
      "pascal":{
         "name":{
            "singular":"pascal",
            "plural":"pascals"
         },
         "prefix":"",
         "suffix":" Pa",
         "decimalPlaces":0,
         "unitSystem":"metric"
      },
      "volt":{
         "name":{
            "singular":"volt",
            "plural":"volts"
         },
         "prefix":"",
         "suffix":" V",
         "decimalPlaces":0,
         "unitSystem":"metric"
      },
      "ampere":{
         "name":{
            "singular":"ampere",
            "plural":"amperes"
         },
         "prefix":"",
         "suffix":" A",
         "decimalPlaces":3,
         "unitSystem":"metric"
      },
      "hertz":{
         "name":{
            "singular":"hertz",
            "plural":"hertz"
         },
         "prefix":"",
         "suffix":" Hz",
         "decimalPlaces":0,
         "unitSystem":"metric"
      },
      "kph":{
         "name":{
            "singular":"kilowatt hour",
            "plural":"kilowatts hour"
         },
         "prefix":"",
         "suffix":" kWh",
         "decimalPlaces":0,
         "unitSystem":"metric"
      },
      "fahrenheit":{
         "name":{
            "singular":"fahrenheit",
            "plural":"fahrenheit"
         },
         "prefix":"",
         "suffix":" °F",
         "decimalPlaces":1,
         "unitSystem":"imperial"
      },
      "inch":{
         "name":{
            "singular":"inch",
            "plural":"inches"
         },
         "prefix":"",
         "suffix":" in",
         "decimalPlaces":2,
         "unitSystem":"imperial"
      },
      "foot":{
         "name":{
            "singular":"foot",
            "plural":"feet"
         },
         "prefix":"",
         "suffix":" ft",
         "decimalPlaces":2,
         "unitSystem":"imperial"
      },
      "yard":{
         "name":{
            "singular":"yard",
            "plural":"yards"
         },
         "prefix":"",
         "suffix":" yd",
         "decimalPlaces":2,
         "unitSystem":"imperial"
      },
      "mile":{
         "name":{
            "singular":"mile",
            "plural":"miles"
         },
         "prefix":"",
         "suffix":" mi",
         "decimalPlaces":2,
         "unitSystem":"imperial"
      },
      "grain":{
         "name":{
            "singular":"grain",
            "plural":"grains"
         },
         "prefix":"",
         "suffix":" gr",
         "decimalPlaces":2,
         "unitSystem":"imperial"
      },
      "ounce":{
         "name":{
            "singular":"ounce",
            "plural":"ounces"
         },
         "prefix":"",
         "suffix":" oz",
         "decimalPlaces":2,
         "unitSystem":"imperial"
      },
      "pound":{
         "name":{
            "singular":"pound",
            "plural":"pounds"
         },
         "prefix":"",
         "suffix":" lb",
         "decimalPlaces":1,
         "unitSystem":"imperial"
      },
      "gallon":{
         "name":{
            "singular":"gallon",
            "plural":"gallons"
         },
         "prefix":"",
         "suffix":" gal",
         "decimalPlaces":2,
         "unitSystem":"imperial"
      },
      "mpg":{
         "name":{
            "singular":"miles per gallon",
            "plural":""
         },
         "prefix":"",
         "suffix":" mpg",
         "decimalPlaces":0,
         "unitSystem":"imperial"
      },
      "mpgus":{
         "name":{
            "singular":"miles per gallon (US)",
            "plural":""
         },
         "prefix":"",
         "suffix":" mpg (US)",
         "decimalPlaces":0,
         "unitSystem":"imperial"
      },
      "fps":{
         "name":{
            "singular":"feet per second",
            "plural":""
         },
         "prefix":"",
         "suffix":" fps",
         "decimalPlaces":0,
         "unitSystem":"imperial"
      },
      "mph":{
         "name":{
            "singular":"miles per hour",
            "plural":""
         },
         "prefix":"",
         "suffix":" mph",
         "decimalPlaces":1,
         "unitSystem":"imperial"
      },
      "horsepower":{
         "name":{
            "singular":"horsepower",
            "plural":"horsepowers"
         },
         "prefix":"",
         "suffix":" hp",
         "decimalPlaces":4,
         "unitSystem":"imperial"
      },
      "psi":{
         "name":{
            "singular":"pounds per square inch",
            "plural":""
         },
         "prefix":"",
         "suffix":" psi",
         "decimalPlaces":1,
         "unitSystem":"imperial"
      },
      "inhg":{
         "name":{
            "singular":"inches of mercury",
            "plural":""
         },
         "prefix":"",
         "suffix":" inHg",
         "decimalPlaces":1,
         "unitSystem":"imperial"
      },
      "mmhg":{
         "name":{
            "singular":"blood pressure",
            "plural":""
         },
         "prefix":"",
         "suffix":" mmHg",
         "decimalPlaces":0
      },
      "kelvin":{
         "name":{
            "singular":"kelvin",
            "plural":"kelvins"
         },
         "prefix":"",
         "suffix":" °K",
         "decimalPlaces":0
      },
      "lux":{
         "name":{
            "singular":"lux",
            "plural":"lux"
         },
         "prefix":"",
         "suffix":" lx",
         "decimalPlaces":0
      },
      "millisecond":{
         "name":{
            "singular":"millisecond",
            "plural":"milliseconds"
         },
         "prefix":"",
         "suffix":" ms",
         "decimalPlaces":0
      },
      "second":{
         "name":{
            "singular":"second",
            "plural":"seconds"
         },
         "prefix":"",
         "suffix":" s",
         "decimalPlaces":0
      },
      "hour":{
         "name":{
            "singular":"hour",
            "plural":"hours"
         },
         "prefix":"",
         "suffix":" h",
         "decimalPlaces":0
      },
      "minute":{
         "name":{
            "singular":"minute",
            "plural":"minutes"
         },
         "prefix":"",
         "suffix":" min",
         "decimalPlaces":0
      },
      "lumen":{
         "name":{
            "singular":"lumen",
            "plural":"lumens"
         },
         "prefix":"",
         "suffix":" lm",
         "decimalPlaces":0
      },
      "rpm":{
         "name":{
            "singular":" revolutions per minute",
            "plural":""
         },
         "prefix":"",
         "suffix":" r/min",
         "decimalPlaces":0
      },
      "bpm":{
         "name":{
            "singular":"beats per minute",
            "plural":"beats per minute"
         },
         "prefix":"",
         "suffix":" bpm",
         "decimalPlaces":0
      },
      "spo2":{
         "name":{
            "singular":"pulse oximetry",
            "plural":""
         },
         "prefix":"",
         "suffix":" SpO2",
         "decimalPlaces":0
      },
      "ppm":{
         "name":{
            "singular":"parts per million",
            "plural":"parts per millions"
         },
         "prefix":"",
         "suffix":" ppm",
         "decimalPlaces":0
      },
      "decibel":{
         "name":{
            "singular":"decibel",
            "plural":"decibels"
         },
         "prefix":"",
         "suffix":" dB",
         "decimalPlaces":0
      },
      "mgdl":{
         "name":{
            "singular":"milligrams per deciliter",
            "plural":"milligrams per deciliters"
         },
         "prefix":"",
         "suffix":" mg/dL",
         "decimalPlaces":0
      },
      "calorie":{
         "name":{
            "singular":"calorie",
            "plural":"calories"
         },
         "prefix":"",
         "suffix":" cal",
         "decimalPlaces":0
      }
   },
   "unitCalc":{
      "from":{
         "to":"expression"
      },
      "fahrenheit":{
         "celsius":"(x - 32) / 1.8"
      },
      "inch":{
         "millimeter":"x / 0.03937",
         "centimeter":"x / 0.3937"
      },
      "feet":{
         "centimeter":"x / 30.5"
      },
      "yard":{
         "meter":"x * 0.9144",
         "kilometer":"x * 0.0009144",
         "mile":"x / 1760"
      },
      "mile":{
         "kilometer":"x / 0.6214",
         "meter":"x * 1609.34",
         "yard":"x * 1760"
      },
      "meter":{
         "kilometer":"x * 0.001",
         "yard":"x / 0.9144",
         "mile":"x / 1609.34"
      },
      "kilometer":{
         "meter":"x * 1000",
         "yard":"x * 1093.61",
         "mile":"x * 0.621371"
      },
      "grain":{
         "milligram":"x * 0.015432358"
      },
      "ounce":{
         "gram":"x / 0.03527"
      },
      "pound":{
         "kilogram":"x / 2.2046"
      },
      "gallon":{
         "liter":"x * 4.5"
      },
      "mpg":{
         "kmpl":"x * 0.354006"
      },
      "mpgus":{
         "kmpl":"x * 0.4251"
      },
      "fps":{
         "mps":"x * 0.3048"
      },
      "mph":{
         "kmph":"x * 1.609344",
         "mps":"x * 0.44704"
      },
      "horsepower":{
         "watt":"x * 745.7",
         "kilowatt":"x * 0.7457"
      },
      "kilowatt":{
         "watt":"x * 1000",
         "horsepower":"x / 0.7457"
      },
      "watt":{
         "kilowatt":"x / 1000",
         "horsepower":"x / 745.7"
      },
      "psi":{
         "bar":"x * 0.0689476",
         "mbar":"x * 68.9476"
      },
      "inhg":{
         "mbar":"x * 33.8639"
      },
      "celsius":{
         "fahrenheit":"(x * 1.8) + 32"
      },
      "millimeter":{
         "inch":"x * 0.03937"
      },
      "centimeter":{
         "inch":"x * 0.3937",
         "foot":"x / 30.5"
      },
      "milligram":{
         "grain":"x  * 0.015432358"
      },
      "gram":{
         "ounce":"x * 0.03527"
      },
      "kilogram":{
         "pound":"x * 2.2046"
      },
      "liter":{
         "gallon":"x / 4.5"
      },
      "kmpl":{
         "mpgus":"x / 0.4251",
         "mpg":"x / 0.354006"
      },
      "mps":{
         "fps":"x / 0.3048",
         "mph":"x / 0.44704"
      },
      "kmph":{
         "mph":"x / 1.609344"
      },
      "bar":{
         "psi":"x / 0.0689476"
      },
      "mbar":{
         "psi":"x / 68.9476",
         "inhg":"x / 33.8639"
      },
      "second":{
         "hour":"x/3600"
      }
   }
}
```
