Webhook notifications allow Sign In App to send an alert to external applications when a visitor or staff member signs in or out. Webhooks are configured within notifications, so different rules can be set by site or visitor group. Advanced filters allow you to build your own workflow, sending different webhook notifications based on the data your visitors provide.
Caveat
Webhook events are not issued for the automatic sign out functionality. For example if the system is set to sign all visitors out at midnight, a webhook event won't be issued for each individual. If webhooks are being used in a data sync scenario, the best option is to use the history endpoint.
> curl -d '{...}' -X POST https://your.url/
Creating a notification is done through the Portal via Manage > Notifications. Add a new notification and select webhook as the channel. The requirements for a webhook are the URL endpoint and a secret key for the webhook signature.
More information about the setup of Notifications can be found in the Group notifications.
Supported events
Events currently supported by webhooks are visitor.signin
, visitor.signout
.
Key | Type | Description |
---|---|---|
event | String | Event Name |
event_at | String | Date of event (ISO8601 format) |
pushed_at | String | Date the event was pushed (ISO8601 format) |
idempotency_key | String | Unique key for the event |
site | Object | The site for the visitor the event happened on |
visitor | Object | The visitor the event happened for |
Key | Type | Description |
---|---|---|
id | Integer | Unique site identifier |
type | String | The site type, this can be standard or remote |
name | String | The name of the site |
timezone | String | The sites timezone |
Key | Type | Description |
---|---|---|
id | Integer | Unique visitor identifier |
returning_visitor_id | Integer | Unique returning visitor identifier, if set |
name | String | The name of the visitor |
photo_url | String | A URL to an image of the visitor photo (optional) |
badge_url | String | A URL to an image of the visitor badge (optional) |
additional | Object | Additional data recorded about the visitor |
personal_fields | Object | Personal fields associated with the (returning) visitor |
is_returning | Boolean | Whether the visitor is a known returning visitor |
is_pre_registered | Boolean | Whether the visitor was pre-registered |
is_remote | Boolean | Whether the visitor was considered remote |
Additional and personal fields are key value Objects
.
{
"field1": "value1",
"field2": 789,
"field3": true
}
The following is a formatted example of the data. A typical request body would not contain newlines and additional spaces.
{
"event": "visitor.signin",
"event_at": "2020-01-01T12:00:01Z",
"pushed_at": "2020-01-01T12:00:01Z",
"idempotency_key": "4EPAoqR4N8jZktby",
"site": {
"id": 4567,
"type": "standard",
"name": "Acme Co",
"timezone": "Europe/London"
},
"visitor": {
"id": 1234,
"name": "John Smith",
"photo_url": null,
"badge_url": null,
"additional": {
"Company": "Acme Ltd",
"Email Address": "john@smith.com"
},
"personal_fields": {
"role": "Director",
"Car Reg": "ABC 123"
},
"is_returning": false,
"is_pre_registered": false,
"is_remote": false
},
"visiting": {
"id": 8,
"name": "Adele Vance",
"role": "Retail Manager",
"email": "AdeleV@2064mx.onmicrosoft.com",
"mobile": ""
}
}
Sign In App expects a 2xx HTTP response code to acknowledge the request succeeded.
When your end point responds with a HTTP status code that isn't considered a success, Sign In App will continue to retry for a maximum of 3 times before giving up.
Signature verification provides a mechanism to authenticate the request has been sent by Sign In App. We do this by having a shared secret, filled in when setting up the webhook. While this is optional, it is recommended.
When a webhook request is made to the webhook url, it will also include a HTTP header with the name x-signinapp-webhook-signature
.
The header is made up of two parts separated by a comma. e.g. x-signinapp-webhook-signature: t=1644316744,s1=462fa402e927893dee0bfec09379718a507c883919442de3dcb1504142ceaa5d
The t
value is a timestamp used to confirm when the webhook was sent.
The s1
value is a sha256 hmac
of the timestamp from t
concatenated with the http body.
hmac.new("MySharedSecret", "timestamp.body", hashlib.sha256).hexdigest()
Substitute the shared secret, timestamp and http body. Note there is a fullstop seperating the timestamp and the http body.
You should be checking the outcome of this call matches s1
in the webhook request header.
Javascript:
const crypto = require('crypto');
crypto
.createHmac('sha256', secret)
.update(timestamp + '.' + payload, 'utf8')
.digest('hex');
PHP:
$header = $request->getHeader('X-SignInApp-Webhook-Signature');
[$timestamp, $signature] = getSignatureParts($header);
hash_equals($signature, hash_hmac("sha256", "{$timestamp}.{$jsonEncodedPayload}", $secret));
Java:
String signedPayload = String.format("%d.%s", timestamp, payload);
String expectedSignature = Util.computeHmacSha256(secret, signedPayload);
Util.secureCompare(expectedSignature, signature)