Webhooks
Subscribe to incoming events with webhooks.
Last updated
Subscribe to incoming events with webhooks.
Last updated
A webhook is an API concept that allows manufacturer's Web APIs to send realtime updates using regular HTTP requests.
Because Homey connects to the internet through a router, your app is not publicly accessible from the internet. We provide a webhook-forwarding service to route all incoming webhooks to the right Homey.
Let's say there is a Web API that sends a webhook when the user has turned on a light bulb. The webhook HTTP request might look like this:
First, you need a unique Webhook URL to provide to the manufacturer's Web API. Sometimes this can be configured in a manufacturer-owned developer portal, other times this URL can be registered by making an API call.
Go to https://tools.developer.homey.app/webhooks and select New Webhook
. Copy the ID & Secret to your app's /env.json
file as WEBHOOK_ID
and WEBHOOK_SECRET
.
Secondly, in your app you you need to register a webhook listener that subscribes to this webhook.
But how does the webhook service know that only this Homey may receive the webhook? There are three options, this is depending on how you register webhooks with the manufacturer's Web API.
If the manufacturer's Web API allows you to dynamically register a webhook, for example by posting your webhook URL to an endpoint (POST https://myapi.com/webhook
), you can attach Homey ID as query parameter homey
to the webhook.
Homey's webhook forwarding service understands that webhooks with a homey
query parameter should be forwarded to that Homey.
When using query parameters, the data
property is not required when registering your webhook using the this.homey.cloud.createWebhook()
function.
If the manufacturer's Web API requires you to specify the webhook URL beforehand, for example in their developer portal, then you can use the key path option when creating your webhook.
The key path describes which property from the webhook request contains the value that uniquely identifies a Homey. For example: headers['X-Device-Id']
, note that these properties are case-sensitive. You can use body
, headers
and query
in your Webhook key path filter.
A key path is an ECMAScript expression consisting only of identifiers (myVal
), member accesses (foo.bar
) and key lookup with literal values (arr[0]
obj['str-value'].bar.baz
).
Your key path has to match an incoming webhook against the data
object provided in this.homey.cloud.createWebhook(id, secret, data)
. For example, an object with { $key: "aaabbbccc" }
has to match the value aaabbbccc
in the data
object.
It is also possible to define the keypath as an array, for example: { $keys: ["aaa", "bbb"] }
then the value in the key path either has to match value aaa
or bbb
.
The key path will be checked for each Homey that is registered to this webhook. All Homeys with matching data will receive the webhook in the webhook.on('message', ...)
listener.
Let's use headers['X-Device-Id']
from the example above, and define $key
as an array in the data
object, as follows:
The webhook HTTP request might look like this:
Homey's webhook service will match your webhook based on headers['X-Device-Id']
with value aaa
(or bbb
) and forward this to that Homey. If the webhook service received value ccc
it will not be forwarded.
Using the same data
object provided in this.homey.cloud.createWebhook(id, secret, data)
as example 1, you can also define your key path in the body of your webhook HTTP request.
The webhook HTTP request might look like this:
Cloud Functions are now considered legacy and have been made "read-only", consider changing to Query Parameter or Key Path based webhooks.
If you had previously defined a custom cloud function on https://tools.developer.homey.app/webhooks, it is possible to view this function in the developer portal.
Your function has to match an incoming webhook against the data
object provided in this.homey.cloud.createWebhook(id, secret, data)
. For example an object with{ deviceId: "aaabbbccc" }
.
The webhook sends the Device's ID in the webhook's body as device_id
. Our cloud function therefore becomes:
This function will execute for each Homey that is registered to this webhook. All Homeys that returned true
will receive the webhook in the webhook.on('message', ...)
listener.