# Getting a bearer token

The following guide, describes a setup that automatically fetches an updated bearer token for usage with your homey API. It consists of two main parts:

* A homeyscript that returns an updated bearer token as a return tag value
* An example flow that runs the homeyscript regularly and stores an updated bearer token in a logic variable

### The homeyscript

First you need to update the configuration section to your homey.

* The `email` and `password` is your Homey account.
* A `client_id` and `client_secret` can be found at <http://developer.athom.com/api/projects>
* The `redirect_url` can stay untouched
* Your `cloudid` can be found here: <http://developer.athom.com/tools/system>

```javascript
// -------- o - Configure these parameters -------- o -------- o 
let email = 'xxxxx@gmail.com'
let password = 'skdjhf987s8d76fsd'
let client_id = 's8d67chdg36d8d6f6d'
let client_secret = 'dsdfghjkdfjghkdfjhgkdfjhgkdfjhgkdfjhgkfd'
let redirect_url = 'http://localhost'
let cloudid = '8sd76f87sd6f876sd8f76sd'
// -------- o -------- o -------- o -------- o -------- o 

const between = function(str, strf, strt) {
    return str.split(strf).pop().split(strt)[0].trim();
}

const authurl = 'https://accounts.athom.com/login'
console.log("POST authentication " + authurl)
const response2 = await fetch(authurl, {
  "headers": {
    "accept": "application/json, text/javascript, */*; q=0.01",
    "content-type": "application/x-www-form-urlencoded; charset=UTF-8",
  },
  "referrerPolicy": "no-referrer-when-downgrade",
  "body": 'email=' +encodeURIComponent(email) + '&password=' + encodeURIComponent(password) + '&otptoken=',
  "method": "POST",
  "mode": "cors",
  "credentials": "omit"
})
const body2 = await response2.text()
const token = JSON.parse(body2)

const authorizeurl = 'https://accounts.athom.com/oauth2/authorise?client_id=' + client_id + 
    '&redirect_uri=' + encodeURIComponent(redirect_url) + '&response_type=code&user_token=' + token.token


console.log(" Response from accounts.athom.com/login ", body2)
console.log("GET Authorization " + authorizeurl)

const response3 = await fetch(authorizeurl, {
  "headers": {
  },
  "method": "GET",
  "mode": "cors",
  "credentials": "include"
})
const body3 = await response3.text()
let csrf = between(body3, 'name="_csrf" value="', '">')



let raw = response3.headers.raw()['set-cookie']
//let rawd = raw[0].split(';')
let cookiecsrf = null
raw.forEach(el => {
    let dc = el.split('=')
    if (dc[0] === '_csrf') {
        cookiecsrf = dc[1]
    }
})

let cookie4 = '_csrf=' + cookiecsrf
// console.log("Cookie4", cookie4)
console.log(" CSRF input parameter", csrf)
console.log(" CSRF cookie", cookiecsrf)

let authorizeurl2 = 'https://accounts.athom.com/authorise?client_id=' + client_id +   '&redirect_uri=' + encodeURIComponent(redirect_url) + '&response_type=code&user_token=' + token.token
console.log("GET Authorization", authorizeurl2)
const response4 = await fetch(authorizeurl2, {
  "headers": {
    "content-type": "application/x-www-form-urlencoded",
    "cookie": cookie4
  },
  "redirect": "manual",
  "body": "resource=resource.homey." + cloudid + "&_csrf=" + csrf + "&allow=Allow",
  "method": "POST",
  "mode": "cors",
  "credentials": "include"
});

const body4 = await response4.text()
let code = response4.headers['_headers'].location[0].split('=')[1]

console.log(" Response from authorization. Redirect to ", response4.headers['_headers'].location[0])
console.log(" Response content ", body4)
console.log(" Parsed the following code ", code)



let tokenendpoint = 'https://api.athom.com/oauth2/token'
console.log("POST token (resolve code to token) " + tokenendpoint)
const response5 = await fetch(tokenendpoint, {
  "headers": {
    "content-type": "application/x-www-form-urlencoded",
  },
  "body": 'client_id=' + encodeURIComponent(client_id) +  '&client_secret=' + encodeURIComponent(client_secret) + 
    '&grant_type=authorization_code&code=' + encodeURIComponent(code),
  "method": "POST",
  "mode": "cors",
  "credentials": "include"
});


//console.log("Response5", response5)
const body5 = await response5.text()
let accesstoken = JSON.parse(body5)





let delegationEndpoint = 'https://api.athom.com/delegation/token?audience=homey'
const response6 = await fetch(delegationEndpoint, {
  "headers": {
    "content-type": "application/x-www-form-urlencoded",
    "authorization": "Bearer " + accesstoken.access_token
  },
  "referrerPolicy": "no-referrer-when-downgrade",
  "body": "client_id=" + client_id + " &client_secret=" + client_secret + "&grant_type=refresh_token&refresh_token=" + accesstoken.refresh_token,
  "method": "POST",
  "mode": "cors",
  "credentials": "include"
});



const body6 = await response6.json()
console.log(" JWT token is " + body6)

let endpoint7 = 'https://' + cloudid + '.connect.athom.com/api/manager/users/login'
console.log("POST login endpoint " + endpoint7)
const response7 = await fetch(endpoint7, {
  "headers": {
    "content-type": "application/json",
    //"authorization": "Bearer " + accesstoken.access_token
  },
  "body": JSON.stringify({"token": body6}),
  "method": "POST"
});

const body7 = await response7.json()
console.log(" Response status " + response7.status)
console.log(" Response: " + body7)

await setTagValue("accesstoken", {type: 'string', title:'Access token'}, body7)
return true
```

### Updating a logic variable

Run the homeyscript above regularly to update an logic variable using the flow below.

![](https://1587494504-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-Ltn3vQOSB-YGC6qLZu_%2F-MIEAz7qY8mqr0-B5bRs%2F-MIEDA8OpDvefv1phG7U%2FSkjermbilde%202020-09-27%20kl.%2013.00.14.png?alt=media\&token=c1eb7ece-4a2e-4849-8cff-c0f2a4b4e44a)

### Using the bearer token with the API

Here is an example using the Homey API with the bearer token:

```javascript
// -------- o - Configure these parameters -------- o -------- o 
let cloudid = 'sd87f68ds76f87sd6f8sd76f'
// -------- o -------- o -------- o -------- o -------- o 

let variables = await Homey.logic.getVariables()
let getVar = (name) => {
    let x = _.find(variables, (val, key) => {return (val.name === name) })
    if (typeof x === 'undefined') throw new Error("Could not find variable [" + name + "]")
    return x
}
let accesstoken = getVar('accesstoken').value
console.log("Access token is " + accesstoken)
let baseapi = 'https://' + cloudid + '.connect.athom.com/api/'
let apiendpoint = baseapi + 'manager/devices/device/'
console.log("GET " + apiendpoint)
const response = await fetch(apiendpoint, {
  "headers": {
    "accept": "application/json",
    "Authorization": "Bearer " + accesstoken
  },
  "method": "GET"
});
console.log(" Response status " + response.status + " " + response.statusText)
const responseBody = await response.text()
const data = JSON.parse(responseBody)
console.log(" Result ", data)

```

### Homey API reference

Thanks to Johan Bendz for providing a list of API endpoints: <https://github.com/JohanBendz/Homey-Endpoints/blob/master/Homey-REST-endpoints>

The base URL is:&#x20;

```javascript
https://<cloudid>.connect.athom.com/api/
```

[https://apps.developer.athom.com/tutorial-Web Api.html](https://apps.developer.athom.com/tutorial-Web%20Api.html)

Use the bearer token to make an authorized call:

```javascript
GET /api/manager/sessions/session/ HTTP/1.1
Host: <cloudid>.connect.athom.com
Authorization: Bearer <ACCESS TOKEN>
```

```javascript
# Alarms
GET /api/manager/alarms/alarm/

# Apps
GET /api/manager/apps/app/
GET /api/manager/apps/app/<APP_ID>/ (eg. com.fibaro)

# Cloud state
GET /api/manager/cloud/state/

# Devices
GET /api/manager/devices/device/
GET /api/manager/devices/device/<DEVICE_ID>/

# Drivers
GET /api/manager/devices/drivers/
GET /api/manager/drivers/pairsession/

# Experiments
GET /api/manager/experiments/experiment/

# Flow
GET /api/manager/flow/flow/
GET /api/manager/flow/flow/<FLOW_ID>/

# Flow folders
GET /api/manager/flow/flowfolder/

# Flow tokens
GET /api/manager/flowtoken/flowtoken/

# Images
GET /api/manager/images/image/

# Insights
GET /api/manager/insights/log/

# Language and unit settings
GET /api/manager/i18n/

# LED ring
GET /api/manager/ledring/screensaver/
GET /api/manager/ledring/state/

# Location
GET /api/manager/geolocation/

# Logic
GET /api/logic/variable/
GET /api/logic/variable/<VARIABLE_ID>/
PUT { "value": value } TO /api/manager/logic/variable/<VARIABLE_ID>/ 

# Mobile
GET /api/manager/mobile/

# Notifications
GET /api/manager/notifications/notification/
GET /api/manager/notifications/owner/

# Presence
GET /api/manager/presence/

# Reminders
GET /api/manager/reminder/reminder/

# Sessions
GET /api/manager/sessions/session/

# Switch on:
PUT { "value": true } TO /api/manager/devices/device/<DEVICE_ID>/capability/onoff/

# Switch off:
PUT { "value": false } TO /api/manager/devices/device/<DEVICE_ID>/capability/onoff/

# System
GET https://<HOMEY_IP>/api/manager/system/

# System Reboot // Use with caution!
POST https://<HOMEY_IP>/api/manager/system/reboot/

# Users
GET /api/manager/users/user/
GET /api/manager/users/user/<USER_ID>/
GET /api/manager/users/state/

# Weather
GET /api/manager/weather/weather/

# Zigbee
GET /api/manager/zigbee/state/

# Z-Wave
GET /api/manager/zwave/state/
GET /api/manager/zwave/log/
POST /api/manager/zwave/command/
- heal: payload {command: "heal", opts: {nodeId: <NODE_ID>}}
- test: payload {command: "sendData", opts: "<NODE_ID>,0x20,0x00"} 

# Zones
GET /api/manager/zones/
GET /api/manager/zones/<ZONE_ID>/
```
