The subscriptions resource on the API can be used to directly push new events to an external HTTP server in addition to just temporarily saving them on the Brain. This concept is called a "webhook".
The Brain webhooks implementation is modeled after the RESTHooks specification.
Creating a webhook subscription
A new subscription can be created with a POST request to /api/subscriptions
. It is also possible to turn an existing subscription into a webhook subscription by modifying it with a PUT request. A subscription will function as a webhook when it has a non-empty target_url
string. Other properties with "target" in their name influence how the webhook will behave. See the subscription resource documentation for more information.
The following example cURL command would create a webhook subscription for all item events, with retry-on-failure enabled (up to a maximum of 48 hours):
curl --request POST --data '{"topic_filter":
"items/#", "database_hold_time_h": 48, "target_url": "https://<application-host>/webhook-handler", "target_retry": true}' --header
"Content-Type: application/json" --header "X-Api-Key:
xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
https://<brain-host>/api/subscriptions
The topic filter format is detailed in Event filtering.
A webhook testing utility like webhook.site can be useful to check the webhook's output before implementing the receiving side.
For security purposes, it is recommended to:
- Always use HTTPS with a valid certificate. If the URL is a HTTPS URL, the certificate will be verified by the Brain unless
verify_target_certificate
is changed to false. Certificate verification should never be disabled outside of a test environment. - Include a (randomly generated) token in the URL and refuse requests without the correct token.
Processing webhooks
When an event matching a webhook subscription occurs, the Brain will perform an HTTP POST request to the endpoint specified in target_url
. The content type is application/json
and the body will contain a JSON array of event objects (as found on the events resource). This array may contain multiple events, for example if they occurred in rapid succession.
The snippet below shows an example of a body with a JSON array and event objects. Event content (action, arguments and payload) may be different depending on the type of event or subscription settings. Refer to events resource for more info.
[ { "id": "634003a4be7b6515d96cfd9f", "topic": { "resource_type": "items", "resource_id": "5e9d987831546c0353e668c3", "action": "moved-to", "arguments": { "location": "5e7cee7cbc4423033c25f6e3", "prev_location": "5e7cef3380785403d93dcbed" } }, "payload": {
...
}, "time_event": "2022-10-07T10:47:00.639Z", "time_created": "2022-10-07T10:47:00.641Z", "time_expire": "2022-10-08T10:47:00.641Z" }, { "id": "634003a4be7b6515d96cfda0", "topic": { "resource_type": "items", "resource_id": "6051deef89f1d306aeb06ad5", "action": "moved-to", "arguments": { "location": "5e7cee7cbc4423033c25f6e3", "prev_location": "5e7cef3380785403d93dcbed" } }, "payload": {
... }, "time_event": "2022-10-07T10:47:00.641Z", "time_created": "2022-10-07T10:47:00.643Z", "time_expire": "2022-10-08T10:47:00.643Z" },
..... ]
The subscription ID that triggered the webhook is provided through the X-Subscription-ID
header. Note that if there are webhook subscriptions with overlapping topic filters (e.g. items/#
and items/+/moved-to/#
), events matching multiple of these subscriptions will be delivered to each matching webhook target.
HTTP response
If your application has successfully received the events sent by the Brain through a webhook HTTP request, it should return a "200 OK" HTTP status code (no response body is expected). Redirect status codes (3xx) will be followed up to a maximum depth of 3, but should be avoided to avoid request overhead. Any 4xx or 5xx status code is considered a failure and will trigger a redelivery attempt if the target_retry
setting is enabled on the subscription. Some 4xx status codes will be treated in a special way:
- 410 Gone indicates that the webhook endpoint is no longer in use. This will cause the
target_url
of the subscription to be cleared immediately, changing it from a webhook subscription to a regular subscription. - 429 Too Many Requests indicates that the server is overloaded. This will delay the next event delivery with one minute.
Pseudocode example
The following pseudocode illustrates a possible implementation outline for processing webhook requests as explained in this article.
def webhookRequestHandler(httpRequest) { events = jsonDecode(httpRequest.body) for (event in events) { processEvent(event) } httpRequest.return(200) } httpServer.registerPathHandler("/webhook-handler", webhookRequestHandler)
Troubleshooting delivery errors
Webhook subscriptions on /api/subscriptions
have a "delivery status", which indicates whether the last delivery attempt succeeded or failed. It also indicates information about the last failure, if there ever was one. For example, this information shows that the subscription failed to deliver two events because it cannot connect to the target server:
"target_delivery_status": { "since": "2018-05-31T10:31:17.427Z", "ok": false }, "target_delivery_last_failure": { "time": "2018-05-31T10:31:17.426Z", "error": { "code": "ECONNREFUSED" }, "events": { "until_id": "5b0fcef4acdba442945e9758", "from_id": "5b0fcef4acdba442945e9746", "count": 2 } }
The error
object will contain information about the failure reason; the exact contents will depend on the type of failure (e.g. network error, HTTP status). The events
object contains the range of events that was being delivered; this can be useful to determine whether or not the problem is being caused by the contents of the events. The contents of these events can be retrieved by querying /api/subscriptions/<subscription-id>/events?from_id=<from-id>&until_id=<until-id>
.
Comments
0 comments
Article is closed for comments.