Hive Home's Rest API

Hive Home's Rest API
Since this article was published, the Hive API has changed to enforce 2FA
This means the below process unfortunately no longer works

When my girlfriend and I purchased our first house together, we decided to go with British Gas' Hive Home products to help us with some level of automation. There are many similar alternatives out there, but Hive suited us the best so we went ahead and purchased an Outdoor Camera to cover the drive, an Indoor Camera to keep an eye on our puppy, and a few Smart Plugs to automate switching lights on.

One thing I presumed they had was a Public Facing Rest API, however, I was bitterly disappointed to find that one didn't exist, and customers have been asking on their forums for a while now, with no developments to date. This lead me down a bit of a rabbit hole, and is the basis of this post. Here's how I went about unearthing how to connect programmatically.

Capturing

I knew that Hive has an iPhone app, which allows you to control all of your devices, however, with a little bit of help from Google, I came across their web-app, which lives at my.hivehome.com. This pretty much replicates the iPhone app, however, some features of it are disabled, like the cameras - more on this later.

The interesting part of the web-app shows its real colours when your using Google Chrome, and their Web Inspector. Clicking on the "Network" tab, ensuring it's Recording the Network Log, and the "Preserve Log" option is enabled, will allow us to see what's happening.

Whilst performing a login attempt using your credentials, you can see the requests the web-app is making, and more importantly, the endpoints, headers and data sent. The below is what we see:

Hive App Login Request

Authentication

Now we know that the web-app utilises an "undiscovered" API, I decided to pull out my favourite app for investigating things like this, Postman. Postman allows us to easily replicate any kind of request, i.e. GET, POST, etc, and see their responses.

One of the first things we need to do is to be able to authenticate ourselves in order to obtain a token which will be used throughout all other requests.

Postman Authentication Request

From the above, you can see that the POST endpoint we've hit for authentication is https://beekeeper.hivehome.com/1.0/global/login, and we've added some JSON raw body to the request which replicates exactly what was seen within the web-app login request, shown in the image within the Capturing section above.

If successful, what this returns is a JSON object which contains all the data we need, specifically the token field. We need to take a copy of this token to be used in further requests. At this stage I'm unsure of how long the token lives for, so, logging in each time you want to make a request ensures the token won't have expired.

The other data in the response is also important, as it lists all the available devices attached to your account, and with that, their id's, which are required within subsequent device-based requests. You'll probably want to make a copy of the response so you're able to target the correct devices in the next section.

Requests

Now we've got the token, we need to remember to add a header parameter named Authorization, with the token as the value to every subsequent request that isn't authentication.

Replication

For this example, I'm going to simply use the "API" to switch on and off a light I have placed in my lounge. For the sake of this, let's say the id of this device is abc-123.

Firstly, I did exactly what I wanted using the web-app and was able to learn the endpoints required (Using the Capturing method above) for handling the change of the lights state. This showed that I needed to hit the endpoint https://beekeeper.hivehome.com/1.0/nodes/activeplug/abc-123, (Ensuring the endpoint is appended with the device id) but with varying JSON body content depending on the state required.

For switching the light on we had to include {"status":"ON"}, and for switching off it was {"status":"OFF"}. Let's see what switching the light on looks like, and the response we get.

Postman Light Off Request

You can see that the request returns a 200-status code, which means it was successful. Here's a little video of it in action:

 

You can use this method to replicate all the functions the web-app has; however, the camera required some further investigation.

MITM

I knew that the iPhone app has the ability to change the status of the camera, so, I decided to MITM (Man in the Middle) attack myself, in order to see the requests, and body, the iPhone was making to the endpoint.

To do this, I used a bit of software called mitmproxy. I started an instance of this using Docker on my laptop, specifically using this command docker run --rm -it -p 8080:8080 -p 127.0.0.1:8081:8081 mitmproxy/mitmproxy mitmweb --web-iface 0.0.0.0, then followed the documentation on their website and setup my iPhone to utilise this as a proxy, thus sending all my data via the application. Note; there were some specific steps involve to allow SSL traffic to be tracked, which is covered within their documentation.

Once this was setup, I opened my laptop browser to http://0.0.0.0:8081 so I'm able to see all incoming requests, then used my iPhone to open the Hive app and click through until the camera was activated. The below is the result I got.

Man-in-the-middle Camera Enable Request

What you can see from the above is the request that was made, the endpoint that was hit https://beekeeper-uk.hivehome.com/1.0/nodes/hivecamera/abc-123 and the JSON body content that was needed to turn on the camera {"mode":"ARMED"}. Turning off the camera requires you to use the following content {"mode":"PRIVACY"}.

We can use the same method above to find out all the endpoints that are used within the app.

PHP

Now we've managed to compile a list of the endpoints, headers and parameters we need in order to perform the required requests, it was time to convert these from Postman, to PHP.

We're going to utilise Guzzle in this as it's a market leader in making requests via PHP, and I'm also going to assume that the package (guzzlehttp/guzzle) has been loaded using Composer.

This example will show what's needed from a PHP point of view for Authentication, which will return the token and other account specific information:

use GuzzleHttp\Client;
use GuzzleHttp\RequestOptions

$client = new Client([
    'headers' => [
        'Accept'       => '*/*',
        'Content-Type' => 'application/json',
        'Origin'       => 'https://my.hivehome.com',
    ]
]);

$response = $client->post(
    'https://beekeeper.hivehome.com/1.0/global/login',
    [
        RequestOptions::JSON => [
            'username' => '[email protected]',
            'password' => 'password',
            'devices'  => true,
            'products' => true,
            'actions'  => true,
            'homes'    => true,
        ],
    ]
);

$data = json_decode(
    (string) $response->getBody()
);

$token = $data->token; // Example: eyJraWQiOiI4Wjgza2EwZE9lSk9p

With the above token, we're now able to make subsequent requests, so, like the example further up the page, this snippet will switch a light on, but using PHP:

use GuzzleHttp\Client;
use GuzzleHttp\RequestOptions

$client = new Client([
    'headers' => [
        'Accept'        => '*/*',
        'Content-Type'  => 'application/json',
        'Origin'        => 'https://my.hivehome.com',
        'Authorization' => 'eyJraWQiOiI4Wjgza2EwZE9lSk9p', // Token, as returned above.
    ]
]);

$response = $client->post(
    'https://beekeeper.hivehome.com/1.0/nodes/activeplug/abc-123',
    [
        RequestOptions::JSON => [
            'status' => 'ON',
        ],
    ]
);

$code = $response->getStatusCode(); // 200

And voila, it did what it was designed to do.

Conclusion

While this is not a public facing, official API, it's not using it in any other way different to how the Hive web-app uses it, however, please bear in mind that as this is not official, Hive control how it works and could shut it down at any time.

It's very useful for us programmers especially, to be able to integrate with things like this, so, hopefully they will eventually release a public facing Rest API.

Feel free to Tweet Me if you have any questions or need any help.

Package

I've since created a PHP composer package which allows you to do all the above, but in a nice easy way, included in your application using Composer. You're able to see this using the following link: https://packagist.org/packages/kan-agency/hive-php-api.