Web API local auth error

What am I missing to get my Shelly script to work?

I have created a API key with the “Devices” and “Flows” permissions using this guide, https://support.homey.app/hc/en-us/articles/8178797067292-Getting-started-with-API-Keys

I have gotten the device ID of the device I want to fetch the status of (Homey Developer Tools).

When I run my script using the API key I generated I get a 401, HomeyErrorUnauthorized

If I make a request towards http://MY_HOMEY_IP I get an object with the homeyId and homeyVersion back, so the IP is correct.
But when I make a request towards http://MY_HOMEY_IP/api/manager/devices/device/DEVICE_ID/capability/CAPABILITY_ID and sending in the ‘Authorization’: 'Bearer ’ + HOMEY_API_KEY I get the auth error.

const HOMEY = {
  apiKey: "xxx-xxx-xxx",
  ipAddress: "X.X.X.X"
}
const DEVICE_ID = "xxx-xxx-xxx"
const BASE_URL = 'http://' + HOMEY.ipAddress + '/api/manager/devices/device/';

function getHomeyData() {
    let url = 'http://' + HOMEY.ipAddress;

    Shelly.call(
        "http.get",
        {
            url: url
        },
        function (response, error_code, error_message) {
            if (response.code === 200 && response.body) {
                let homeyData = JSON.parse(response.body);
                print('Homey Data:', JSON.stringify(homeyData))
            } else {
                print("Error Code:", error_code);
                print("Message:", error_message);
                print("Body:", JSON.parse(response.body));
                if (response.code === 401) {
                    print('Unauthorized: Please check your API token and permissions.');
                }
            }
        }
    );
}

function getLockState(deviceId, capability) {
    let url = BASE_URL + deviceId + '/capability/' + capability
    print('URL:', url);
    Shelly.call(
        "http.get",
        {
            url: url,
            headers: {
                'Authorization': 'Bearer ' + HOMEY.apiKey
            }
        },
        function (response, error_code, error_message) {
            if (response.code === 200 && response.body) {
                let capabilityValue = JSON.parse(response.body);
                print('Capability Value:', capabilityValue);
            } else {
                print("Error Code:", error_code);
                print("Message:", error_message);
                print("Body:", JSON.parse(response.body));
                if (response.code === 401) {
                    print('Unauthorized: Please check your API token and permissions.');
                }
            }
        }
    );
}

getHomeyData();
getLockState(DEVICE_ID, 'locked');

I don’t have a Shelly to run this code on, but converted to a plain Node.js script it works just fine.

Are you sure that the API key was created with the correct scopes?

I have also tried to create an API key with all boxes ticked, same result…
Is there some feature I need to activate for this to work?

No, it should work.

Any special encoding I need to use? Currently it just a string which I have copy/pasted from the Homey portal and feed directly to the Authentication header.

This is the code I tested with:

const HOMEY = {
  apiKey: "...",
  ipAddress: "aa.bb.cc.dd"
}
const DEVICE_ID = "...";
const BASE_URL = 'http://' + HOMEY.ipAddress + '/api/manager/devices/device/';

async function getLockState(deviceId, capability) {
  let url = BASE_URL + deviceId + '/capability/' + capability
  console.log('URL:', url);

  const r = await fetch(url, {
    headers: {
      'Authorization': 'Bearer ' + HOMEY.apiKey
    }
  });
  console.log('R', r.status);
  const data = await r.json();
  console.log(data);
}

getLockState(DEVICE_ID, 'dim');

So looks very much like yours, but using fetch() instead of the Shelly-specific functions. You can run this code in HomeyScript to see if your issue is related to the API key somehow, or if it’s something specific to Shelly.

Ok, thanks, will try that and see if my token somehow is the problem. Or if the Shelly script might have some issues with the auth header I send in.

It was the Shelly script itself I managed to mess up, if I changed to the http.request call it worked.

const BASE_URL = 'http://' + HOMEY.ipAddress + '/api/manager/devices/device/';
const HEADERS = {
  "Authorization": "Bearer " + HOMEY.apiKey
}

Shelly.call("http.request", {
   method: "GET",
   url: url,
   headers: HEADERS
}, ...

So it seems like the http.get does not handle the headers.

Thanks for the help, the verification from your end was helpful to point me in the right direction and try something else.

1 Like