Introduction
A webhook is a callback function that allows applications to communicate with each other in real-time by sending automated messages over the web.
Building Engines APIs feature REST interfaces for core functionality and webhooks for proactive notifications. Webhooks are registered on-behalf of a client by a System Administrative privileged user or by a Building Engines operations member. Webhooks will be invoked by a background worker thread in response to selective operations and follow a common pattern described below.
A webhook is invoked on an HTTP or HTTPS endpoint. HTTPS is preferred and HTTP endpoints should be relegated to initial tests. Each webhook is registered with an organization-supplied name and assigned a secret key. The secret key is a cryptographically random value assigned by the BE system at webhook creation. This is used to sign the payload of the webhook allowing the receiver to validate the authenticity of the event.
General Payload
The webhook is invoked with an HTTP POST operation. The general body of the webhook is in application/json format. The format is:
{
"event": {
"code": "Webhook Event Name (see below)",
"name": "Name of Webhook from registration",
"created_at": "ISO-8601 UTC date of Webhook creation"
},
"data": see below,
"signature": “sha256=signature of data portion"
}
The name value is simply the name supplied by the organization during registration (e.g. “low- rating-feedback-event”). The code value is the BE event subscribed to, for instance feedback.low_rating.
The signature is a Base64 encoded value of a SHA-256 HMAC value using the assigned secret- key, encoded at UTF-8, against the payload string also encoded as UTF-8. The following Python code illustrates calculating the signature:
import hmac
import hashlib
import base64
hmac_value = hmac.new(secret_key.encode('utf-8'),
data_string.encode('utf-8'), hashlib.sha256)
signature = 'sha256=' + str(base64.b64encode(hmac_value.digest()))
When posting to an HTTPS callback we will further validate the certificate as being correct before completing the operation.
Webhook Events
Service Feedback Events: feedback.low_rating:
The data body of the Low Rating webhook includes the following data:
{
"service": "Name of the Service being rated",
"building": "Building Name where rating occurred",
"user": "User Name (User Email)",
"rating": Given rating from 1-5,
"comments": "User supplied comment",
}
Work Order Events: work_orders.created Data in the webhook:
{
"work_order_id": "ID of new Work”,
"changed_by_id Order": "ID of the user creating the Work Order",
}
This event fires when a new Work Order is created.
Work Order Events: work_orders.assignee_change
Data in the webhook:
{
"work_order_id": "ID of new Work Order",
"changed_by_id": "ID of the user changing the Work Order",
“old_assignee”: “Email of the old assignee”,
“new_assignee”: “Email of the new assignee”,
}
This event fires when a new Work Order assignee changes
Work Order Events: work_orders.status_change
Data in the webhook:
{
"work_order_id": "ID of new Work Order",
"changed_by_id": "ID of the user changing the Work Order",
“old_status”: “Status changing from”,
“new_status”: “Status changing to”,
}
This event fires when a new Work Order changes status.
Steps to register a Web-hook
Your management account should have account_admin permission to register a web-hook.
After logging in,
-
To list all web-hooks:
- Go the following endpoint to list all web-hooks.
- GET /webhooks
- Go the following endpoint to list all web-hooks.
-
To create a web-hook:
- Go to the following endpoint to register a web-hook.
- POST /webhooks
- And in the POST body pass the JSON data in the following format.
-
{
"account_id":"b2101576-8216-44e5-a6e8-a51d9651a1a2",
"name": "wo-created",
"event_name": "work_orders.created",
"url": "https://webhook.site/1550c74d-c43b-4d28-84fb-77b8e7f88b41"
} -
account_id: This field should be the account id of the prism instance you would like to register to.
-
name: This field represents the name of the web-hook.
-
event_name: In this field we need to enter the name of triggering event for the web-hook.
-
url: In this field we have to add the Unique URL which we will get from the website Webhook.site - Test, transform and automate Web requests and emails.
-
After processing the request, the web-hook will be registered and will be triggered every time a work order is created or the specified event occurs.
- Go to the following endpoint to register a web-hook.
-
Details will be visible in the web-hook website:
- Whenever the web-hook will be triggered you’ll see the request in the website specified in url field in POST body.
- The request details such as payload will be visible in the website.
Walkthrough the Process:
- Open Webhook.site - Test, transform and automate Web requests and emails to get your Unique url which will be used in the url field in the post body to specify the endpoint where web-hook details will be intercepted.
- After getting the url, create the web-hook using the above post body as a template.
- The web-hook is now created and will be triggered as the mentioned event occurs, which in this case is work_orders.created and this event occurs when a work order is created.
- Now let’s create a work order and trigger the web-hook. The below image shows the work order creation using POST method and its corresponding POST body.
- Because we have a web-hook triggered by the event work_orders.created, we will receive requests at the specified URL (Unique URL) provided by webhook.site.
- The webhook.site unique URL will capture details in the request, including account_id, building_id, event object and data object containing event name, object ID, type ("work_orders" in this case), work order ID, and changed by user ID.
- The image depicts a sample web-hook payload with its contents.
In this way we can register the web-hooks and get the details whenever the triggering event occurs.
Web-Hooks available and their details:
Entity | Triggering Event | Sample Payload | Comment |
Work Order | priority_changed |
payload={ "account_id": "9e69e851-4cb5-4dc9-8bb1-1adbb92b8261", "building_id": "9fa1b5b8-ae6c-476b-a961-28fe358b82e7", "event": { "code": "work_orders.priority_change", "name": "wo_comment_added", "created_at": "2024-05-31T06:58:00.269618Z" }, "data": { "event": "priority_changed", "object_id": "02a0670f-3b1d-4323-81fd-783bcb983a4e", "type": "work_orders", "work_order_id": "02a0670f-3b1d-4323-81fd-783bcb983a4e", "changed_by_id": "0a9b453d-eec3-4ff6-896e-3a7142618ab7", "old_priority": 3, "new_priority": 2 } } |
Triggered when the priority of the work order is changed. |
new_to_open |
payload = { "account_id": "9e69e851-4cb5-4dc9-8bb1-1adbb92b8261", "building_id": "9fa1b5b8-ae6c-476b-a961-28fe358b82e7", "event": { "code": "work_orders.status_change", "name": "wo_status_change", "created_at": "2024-05-31T06:44:42.793191Z" }, "data": { "event": "new_to_open", "object_id": "02a0670f-3b1d-4323-81fd-783bcb983a4e", "type": "work_orders", "work_order_id": "02a0670f-3b1d-4323-81fd-783bcb983a4e", "changed_by_id": "0a9b453d-eec3-4ff6-896e-3a7142618ab7", "old_status": "new", "new_status": "open" } } |
Triggered when the status of work order is changed from “new” to “open”. | |
on_hold |
payload={ "account_id": "9e69e851-4cb5-4dc9-8bb1-1adbb92b8261", "building_id": "9fa1b5b8-ae6c-476b-a961-28fe358b82e7", "event": { "code": "work_orders.status_change", "name": "wo_status_change", "created_at": "2024-05-31T06:44:42.793191Z" }, "data": { "event": "on_hold", "object_id": "02a0670f-3b1d-4323-81fd-783bcb983a4e", "type": "work_orders", "work_order_id": "02a0670f-3b1d-4323-81fd-783bcb983a4e", "changed_by_id": "0a9b453d-eec3-4ff6-896e-3a7142618ab7", "old_status": "open", "new_status": "onhold" } } |
Triggered when the status of work order is put on hold. | |
off_hold |
payload={ "account_id": "9e69e851-4cb5-4dc9-8bb1-1adbb92b8261", "building_id": "9fa1b5b8-ae6c-476b-a961-28fe358b82e7", "event": { "code": "work_orders.status_change", "name": "wo_status_change", "created_at": "2024-05-31T06:44:42.793191Z" }, "data": { "event": "off_hold", "object_id": "02a0670f-3b1d-4323-81fd-783bcb983a4e", "type": "work_orders", "work_order_id": "02a0670f-3b1d-4323-81fd-783bcb983a4e", "changed_by_id": "0a9b453d-eec3-4ff6-896e-3a7142618ab7", "old_status": "onhold", "new_status": "open" } } |
Triggered when the status of work order is changed from hold to other status. | |
new |
payload={ "account_id": "9e69e851-4cb5-4dc9-8bb1-1adbb92b8261", "building_id": "9fa1b5b8-ae6c-476b-a961-28fe358b82e7", "event": { "code": "work_orders.created", "name": "wo-create", "created_at": "2024-05-31T05:05:03.474862Z" }, "data": { "event": "new", "object_id": "02a0670f-3b1d-4323-81fd-783bcb983a4e", "type": "work_orders", "work_order_id": "02a0670f-3b1d-4323-81fd-783bcb983a4e", "changed_by_id": "0a9b453d-eec3-4ff6-896e-3a7142618ab7" } } |
Triggered when the work order is new i.e. was just created. | |
cancelled |
payload={ "account_id": "9e69e851-4cb5-4dc9-8bb1-1adbb92b8261", "building_id": "9fa1b5b8-ae6c-476b-a961-28fe358b82e7", "event": { "code": "work_orders.status_change", "name": "wo_status_change", "created_at": "2024-05-31T06:44:42.793191Z" }, "data": { "event": "cancelled", "object_id": "02a0670f-3b1d-4323-81fd-783bcb983a4e", "type": "work_orders", "work_order_id": "02a0670f-3b1d-4323-81fd-783bcb983a4e", "changed_by_id": "0a9b453d-eec3-4ff6-896e-3a7142618ab7", "old_status": "open", "new_status": "cancelled" } } |
Triggered when the work order is cancelled. | |
closed |
payload={ "account_id": "9e69e851-4cb5-4dc9-8bb1-1adbb92b8261", "building_id": "9fa1b5b8-ae6c-476b-a961-28fe358b82e7", "event": { "code": "work_orders.status_change", "name": "wo_status_change", "created_at": "2024-05-31T06:44:42.793191Z" }, "data": { "event": "closed", "object_id": "02a0670f-3b1d-4323-81fd-783bcb983a4e", "type": "work_orders", "work_order_id": "02a0670f-3b1d-4323-81fd-783bcb983a4e", "changed_by_id": "0a9b453d-eec3-4ff6-896e-3a7142618ab7", "old_status": "completed", "new_status": "closed" } } |
Triggered when the status of the work order is changed to closed. | |
completed |
payload={ "account_id": "9e69e851-4cb5-4dc9-8bb1-1adbb92b8261", "building_id": "9fa1b5b8-ae6c-476b-a961-28fe358b82e7", "event": { "code": "work_orders.status_change", "name": "wo_status_change", "created_at": "2024-05-31T06:44:42.793191Z" }, "data": { "event": "completed", "object_id": "02a0670f-3b1d-4323-81fd-783bcb983a4e", "type": "work_orders", "work_order_id": "02a0670f-3b1d-4323-81fd-783bcb983a4e", "changed_by_id": "0a9b453d-eec3-4ff6-896e-3a7142618ab7", "old_status": "open", "new_status": "completed" } } |
Triggered when the status of work order is changed to completed. | |
assignee_change |
payload={ "account_id": "9e69e851-4cb5-4dc9-8bb1-1adbb92b8261", "building_id": "9fa1b5b8-ae6c-476b-a961-28fe358b82e7", "event": { "code": "work_orders.assignee_change", "name": "wo_assignee_change", "created_at": "2024-05-31T06:44:42.793191Z" }, "data": { "event": "assignee_change", "object_id":"d49e9dd5-db2f-4e80-99f5-61f5d3593b91", "type":"work_orders", "changed_by_id": "9ec57c18-d499-4ba9-9dbb-51e113052881", "old_assignee":{ "prev_assignee":"6aa8079a-2121-4308-bb68-b5166aef552c", "prev_organisation_assignee":"", "prev_team_assignee":"" }, "new_assignee":{ "new_assignee":"6a2ba644-b0ac-45d6-873f-e3280bc0aa9f", "new_organisation_assignee":"", "new_team_assignee":"" } } } |
Triggered when the assignee or organisation_assignee or team_assignee of the work order changes. | |
comments |
payload={ "account_id": "9e69e851-4cb5-4dc9-8bb1-1adbb92b8261", "building_id": "9fa1b5b8-ae6c-476b-a961-28fe358b82e7", "event": { "code": "work_orders.comment_added", "name": "wo_comment_added", "created_at": "2024-05-31T06:53:29.173488Z" }, "data": { "event": "comments", "object_id": "02a0670f-3b1d-4323-81fd-783bcb983a4e", "type": "work_orders", "work_order_id": "02a0670f-3b1d-4323-81fd-783bcb983a4e", "changed_by_id": "0a9b453d-eec3-4ff6-896e-3a7142618ab7", "comment_id": "8a867dba-7191-4ff0-b73d-9cb4ac1707cf" } } |
Triggered when a comment is added in work order. | |
Visitor | new_visitor_person |
payload= { "account_id": "9e69e851-4cb5-4dc9-8bb1-1adbb92b8261", "building_id": "9fa1b5b8-ae6c-476b-a961-28fe358b82e7", "event": { "code": "visitors.created", "name": "visitor-created", "created_at": "2024-05-31T13:44:35.940300Z" }, "data": { "event": "new_visitor_person", "object_id": "e32b9f3d-528b-4cf2-bf27-acc3193d3559", "type": "visitors", "visitor_id": "e32b9f3d-528b-4cf2-bf27-acc3193d3559", "changed_by_id": "None" } } |
Triggered when new person is added. |
new_premier_visitor_person |
payload= { "account_id": "9e69e851-4cb5-4dc9-8bb1-1adbb92b8261", "building_id": "9fa1b5b8-ae6c-476b-a961-28fe358b82e7", "event": { "code": "visitors.created", "name": "visitor-created", "created_at": "2024-05-31T13:44:35.940300Z" }, "data": { "event": "new_premier_visitor_person", "object_id": "5a789f92-942a-431d-84b2-6f089e37b7f4", "type": "visitors", "visitor_id": "5a789f92-942a-431d-84b2-6f089e37b7f4", "changed_by_id": "None" } } |
Triggered when a new premier visitor is added. | |
premier_visitor_checked_in |
payload= { "account_id": "9e69e851-4cb5-4dc9-8bb1-1adbb92b8261", "building_id": "9fa1b5b8-ae6c-476b-a961-28fe358b82e7", "event": { "code": "visitors.checked_in_change", "name": "visitor_checked_in", "created_at": "2024-05-31T14:18:36.019208Z" }, "data": { "event": "premier_visitor_checked_in", "object_id": "19765dc0-edb2-4003-9fe6-c3f50d9f1137", "type": "visitors", "visitor_id": "19765dc0-edb2-4003-9fe6-c3f50d9f1137", "changed_by_id": "None", "old_checked_in": null, "new_checked_in": "2024-05-31 14:19:50.754000+00:00" } } |
Triggered when premier visitor checks in. | |
visitor_checked_in |
payload={ "account_id": "9e69e851-4cb5-4dc9-8bb1-1adbb92b8261", "building_id": "9fa1b5b8-ae6c-476b-a961-28fe358b82e7", "event": { "code": "visitors.checked_in_change", "name": "visitor_checked_in", "created_at": "2024-05-31T14:16:42.481703Z" }, "data": { "event": "visitor_checked_in", "object_id": "6d92bb63-effe-45a8-9c15-ab9bdbf40a9d", "type": "visitors", "visitor_id": "6d92bb63-effe-45a8-9c15-ab9bdbf40a9d", "changed_by_id": "None", "old_checked_in": null, "new_checked_in": "2024-05-31 14:17:12.579000+00:00" } } |
Triggered when the visitor checks in. | |
Watch List | new_watch_list_person |
payload = { "account_id": "9e69e851-4cb5-4dc9-8bb1-1adbb92b8261", "building_id": "None", "event": { "code": "watch_list.created", "name": "new_watch_list", "created_at": "2024-05-31T14:22:55.369307Z" }, "data": { "event": "new_watch_list_person", "object_id": "1bc3fa32-5df8-4ae8-81c7-0163da2d0126", "type": "watch_list", "watch_list_id": "1bc3fa32-5df8-4ae8-81c7-0163da2d0126", "changed_by_id": "0a9b453d-eec3-4ff6-896e-3a7142618ab7" } } |
Triggered when new watch list request is created. |
watch_list_deny |
payload={ "account_id": "9e69e851-4cb5-4dc9-8bb1-1adbb92b8261", "building_id": "None", "event": { "code": "watch_list.status_change", "name": "new_watch_status_change", "created_at": "2024-05-31T14:51:14.688380Z" }, "data": { "event": "watch_list_deny", "object_id": "1bc3fa32-5df8-4ae8-81c7-0163da2d0126", "type": "watch_list", "watch_list_id": "1bc3fa32-5df8-4ae8-81c7-0163da2d0126", "changed_by_id": "0a9b453d-eec3-4ff6-896e-3a7142618ab7", "old_status": "pending", "new_status": "declined" } } |
Triggered when the status code of watch list is changed to declined. |