Web API

Exposing and consuming a custom REST API for your Homey App with support for real-time events.

A Homey app can add its own endpoints to Homey's Web API (REST + Realtime), to allow for external access. As an example, you could use this API to enable a Raspberry PI to reports its status to Homey.

Apps on Homey Cloud are not allowed to expose a Web API. Read more about this in the Homey Cloud guide.

Your app's API endpoints are available under the following url: /api/app/com.yourapp.id/. All endpoints are protected by default, and the requesting user needs permission to your app (which is granted by default after installation). You can override this by setting "public": true.

To add API endpoints to an app, start by defining the routes in the App Manifest. The key of each route corresponds to the name of a function defined in api.js. The following route options can be configured in the App Manifest:

key

type

value

method

String, Array

"GET", "POST", "PUT" or "DELETE", or an array of these values.

path

String

for example "/", "/:foo", "/bar/:foo"

public

Boolean

Default: false, set to true to make this endpoint accessible without a token.

Only use public endpoints when no alternatives are possible. A good usecase for a public endpoint is sending a pin-code from another device to Homey.

In the following example we define four routes named getSomething, addSomething, updateSomething and deleteSomething:

/.homeycompose/app.json
  "api": {
    "getSomething": {
      "method": "GET",
      "path": "/"
    },
    "addSomething": {
      "method": "POST",
      "path": "/"
    },
    "updateSomething": {
      "method": "PUT",
      "path": "/:id"
    },
    "deleteSomething": {
      "method": "DELETE",
      "path": "/:id"
    }
  }

The implementation of each route is defined in the api.js file, this file should export async functions with names that correspond to the names defined in the App Manifest. For example:

/api.js
module.exports = {
  async getSomething({ homey, query }) {
    // you can access query parameters like "/?foo=bar" through `query.foo`

    // you can access the App instance through homey.app
    const result = await homey.app.getSomething();

    // perform other logic like mapping result data

    return result;
  },

  async addSomething({ homey, body }) {
    // access the post body and perform some action on it.
    return homey.app.addSomething(body);
  },

  async updateSomething({ homey, params, body }) {
    return homey.app.updateSomething(params.id, body);
  },

  async deleteSomething({ homey, params }) {
    return homey.app.deleteSomething(params.id);
  },
};

Api functions receive an object as their argument, this object has four properties: homey, params, query and body.

  • homey is the Homey instance. Using this instance you can, for example, access the App instance.

  • body is an object with the request body, when your request has method POST or PUT. JSON is automatically parsed.

  • params is a set of strings defined in your path.

  • query is a set of strings that are provided as query parameters, for example ?foo=bar will result in { "foo": "bar" }.

Realtime events

Your app can emit 'realtime' events, which are one-way events to a subscribing client, for example a browser showing a settings view page.

/app.js
const Homey = require('homey');

class App extends Homey.App {
  async onInit() {
    await this.homey.api.realtime("my_event", "my_json_stringifyable_value");
  }
}

module.exports = App;

Accessing the Web API of another app

Apps can also talk to each other through their API's, however you need to define the correct permissions first. Permissions for app to app communication look like this homey:app:<appId>, for example homey:app:com.athom.example or homey:app:com.yahoo.weather.

In order to communicate with another app you first need to create a ApiApp client:

/app.js
const Homey = require('homey');

class App extends Homey.App {
  async onInit() {
    this.otherAppApi = this.homey.api.getApiApp('com.athom.otherApp');
  }
}

module.exports = App;

The Homey Apps SDK provides some information about the app you are connecting to. For example whether it is installed on the Homey your app is installed on and what version of the app is installed. You can even subscribe to events that get emitted when an app is installed or uninstalled.

/app.js
const Homey = require('homey');

class App extends Homey.App {
  async onInit() {
    const isInstalled = await this.otherAppApi.getInstalled();
    const version = await this.otherAppApi.getVersion();

    this.otherAppApi.on('install', () => {
      console.log('otherApp is installed');
    });

    this.otherAppApi.on('uninstall', () => {
      console.log('otherApp is uninstalled');
    });
  }
}

module.exports = App;

Always check whether the target app is installed and has a compatible version before trying to send requests. Failing to do so may cause your app to break unexpectedly when the target app is updated.

You can interact with the Web API of the target app by making requests and listening to realtime events. Which APIs and events you can expect is up to the target app, so make sure to check the source code, read the documentation or ask the app's developer.

/app.js
const Homey = require('homey');

class App extends Homey.App {
  async onInit() {
    // Make a get request to "otherApp"s API
    const getResponse = await this.otherAppApi.get('/');

    // Post some data to "otherApp", the second argument is the request body
    const postResponse = await this.otherAppApi.post('/play', { sound: 'bell' });

    // Listen to app realtime events
    this.otherAppApi.on('realtime', (event) => {
      console.log('otherApp.onRealtime', event);
    });
  }
}

module.exports = App;

Last updated