What are Webhooks and how do I use them to receive notifications when Workflows are completed?
Webhooks allow you to set up your own integrations to Malcolm! Workflow.
Webhooks are endpoints on web servers you own. Whenever a Workflow is completed the configured Webhooks will be notified. The Payload will contain the completed Workflow Session, related Workflow and (optionally) the submitted Workflow Values.
Configuration
Webhooks are are configured in "Workflows > Edit > Configure > Webhooks" section of MyMalcolm.
Webhook URL
The only requirement is to provide the URL of your Webhook. This is the URL Malcolm! will send the Payload to.
The URL should be a secure endpoint which means it should start with https://, although we do support http:// too. The endpoint should also be accessible which means hosted on a remote machine, not behind a firewall and not requiring Authentication.
Include the Workflow Values
There is an additional option to include the submitted Workflow Values in the Payload. This option is disabled by default for security reasons but available to use should you wish to enable it. By enabling the option you agree to the following terms -
(a) I would like the Workflow Values included in the Webhook Payload (b) the recieving web server is private and properly secured (c) I am aware the use of Webhooks can facilitate the transfer of end-user personal data to third party Data Processors and my use of Webhooks adheres to my responsibilities as Data Controller under applicable Data Protection Laws.
Secure your Webhook with a secret token
Webhook URLs can be called by anyone and are therefore insecure.
To ensure a request to your Webhook URL comes from Malcolm! a secret token known only by yourself and Malcolm! can be used to generate a Signature.
Malcolm! will take the Payload and the secret and create a Signature. This will be passed to your App as the request header X-Signature
. Your App will use the same secret and the received Payload to generate a second Signature. If the Signatures match you know the request came from Malcolm! and not another source.
The secret token can be any string you like, but Malcolm! recommends using a random string of at least 36 characters. For example in a Terminal window run -
ruby -rsecurerandom -e 'puts SecureRandom.hex(18)'
To validate the Payload from Malcolm! use the HMAC SHA-256 algorithm to create a hash using the Payload as the data and your secret as the key.
For example in PHP use the hash_hmac function to generate a binary hash.
$key = 'Your secret token';
$data = file_get_contents('php://input');
$hash = hash_hmac('sha256', $data, $key, true); // true = output raw binary data
Next encode the binary hash using a Base 64 encoder, in PHP this is the base64_encode function.
$encoded_hash = base64_encode($hash);
Finally prefix the encoded hash with "sha256=" and compare with the value of X-Signature
. In PHP you can use the $_SERVER variable to access the headers.
$signature = 'sha256=' . $encoded_hash;
if ($_SERVER['HTTP_X_SIGNATURE'] === $signature) {
// Request is valid
}
Conditional settings
There are conditional controls available too. If you have a condition configured the Webhook will only be notified if the conditions at the end of the Workflow are satisfied.
Headers
The HTTP POST will contain the following Headers.
Header | Description |
---|---|
Host | The Host of your Webhook URL. |
Content-Type | With value "application/json" |
X-Instance-Id | The ID of the Instance. |
X-Signature | The request Signature, if using a secret token. |
Payload
The Payload will be a JSON Body containing the Workflow Session.
Attribute | Type | Description |
---|---|---|
id | string | The ID of the Workflow Session. |
label | string | A descriptive label, which will include the name of the person who completed the Workflow if your Workflow contains name attributes. |
description | string | An extended version of the label which also includes the Workflow name. |
text | string | The same as the description but often a attribute named "text" is automatically picked up by some services. |
locale | string | The locale used during the Workflow Session. |
started-at | string | The date and time the Workflow Session was started, in ISO 8601 format. |
completed-at | string | The date and time the Workflow Session was completed, in ISO 8601 format. |
workflow | object[Workflow] | The related Workflow. |
values | array[Value] | The submitted Workflow Values (if included). |
Workflows are defined as -
Attribute | Type | Description |
---|---|---|
id | string | The ID of the Workflow. |
name | string | The name of the Workflow. |
published-at | string | The date and time the Workflow was published, in ISO 8601 format. |
version | string | The name of the Workflow version. |
Workflow Values are defined as -
Attribute | Type | Description |
---|---|---|
id | string | The ID of the Workflow Value. |
field | object[Field] | The related Workflow Field. |
value | mixed | The submitted value. |
Workflow Fields are defined as -
Attribute | Type | Description |
---|---|---|
id | string | The ID of the Workflow Field. |
name | string | The name of the Workflow Field. |
query-name | string | The URL query name for the Workflow Field if defined. |
Example
POST /webhook HTTP/1.1
Host: yourdomain.com
Content-Type: application/json
X-Instance-Id: xxxxxxxxxx
X-Signature: xxxxxxxxxx
{
"id": "xxxxxxxxxx",
"label": "Completed by Tom Jordan",
"description": "Workflow \"Open Support Ticket\" was completed by Tom Jordan.",
"text": "Workflow \"Open Support Ticket\" was completed by Tom Jordan.",
"locale": "en-GB",
"started-at": "2020-04-01T12:00:00+00:00",
"completed-at": "2020-04-01T12:05:00+00:00",
"workflow": {
"id": "xxxxxxxxxx",
"name": "Open Support Ticket",
"published-at": "2020-04-01T09:00:00+00:00",
"version": "Version 1"
},
"values": [
{
"id": "xxxxxxxxxx",
"field": {
"id": "xxxxxxxxxx",
"name": "Your name",
"query-name": "name"
},
"value": "Tom Jordan"
},
{
"id": "xxxxxxxxxx",
"field": {
"id": "xxxxxxxxxx",
"name": "Your email address",
"query-name": "email"
},
"value": "[email protected]"
}
]
}