Pushing risk events to Webhooks

Setup and configure RESTful endpoints to recieve data from CultureAI's automation platform

Event subscriptions

You can subscribe to events by configuring RESTful webhooks for them en-masse or individually within React on Platform.

Request & event payload

Currently all webhooks are called via a POST request to the URL you configure in React, in the future this may expand out to other HTTP verbs, so any integration should be built with that in mind.

Requests to webhooks are made with the Content-Type header set to application/json and payload passed via POST body as a JSON encoded object. The event payload is standardised and versioned, meaning you will always get the same format and no changes will be made to it until the payload version reaches EOL, which you will be notified far in advance of.

The payload version your webhook is called with will be the latest at the time of configuring it in React, but you can always change this to other supported versions by contacting us on success@culture.ai. To check which version a webhook is using, simply refer to the X-WEBHOOK-VERSION header it is called with.

Payload v1.0

The standard event data in version 1.0 is as such:

Data Type Value
event Object Object containing details about the event being pushed.
event.id Integer Unique id of the event its self, when an event is affects multiple employees this may be shared across them.
event.occurrenceId Integer Unique id of the event happening to the specific employee.
event.pushId Integer Unique id of the webhook call attempt, we recommend you store this for future reference as CultureAI can give you additional context on what was sent and went wrong using it.
event.type String String representing the type of event e.g. EmailPhishing\Clicking.
common.title String String briefly describing the event, e.g. An employee clicked on a phishing email.
common.subtext String String giving additional context on the event, e.g. Details of a data breach.
common.dataSource String String representing the source of the event, e.g. Microsoft integration, Email Phishing, etc.
common.date ISO_8601 Date ISO_8601 formatted date-only string for when the event happened.
common.timestamp Nullable Unix Timestamp

Unix Time representing the date and

time when the event happened, some events do not have a specific time (e.g. Data breaches) in which case this will be null.

common.behaviourIndicator Enum String POSITIVE, NEUTRAL or NEGATIVE depending on what the event represents, e.g. Clicking a phishing email is NEGATIVE, reporting a phishing email is POSITIVE.
common.employee Nullable Object Object containing details about the employee, some events are not employee specific in which case this will be null.
common.employee.id Integer Unique id of the employee affected by the event.
common.employee.forename Nullable String String containing the employee's first name, can be null if its not been set.
common.employee.surname Nullable String String containing the employee's last name, can be null its not been set.
common.employee.email String String containing the employee's email.
common.employee.jobTitle Nullable String String containing the employee's job title, can be null its not been set.
common.employee.platformUser Boolean Whether the employee has access to the CultureAI Platform, and thus can view reporting data.
common.employee.platformAdmin Boolean Whether the employee has admin access to the CultureAI Platform, and thus can configure settings.
common.employee.creationDate Unix Timestamp Unix Time representing the date and time when the employee was first created, if they were deleted and restored it's still the date of first creation.
common.employee.metadata Object Object containing all metadata from employee syncing, e.g. Department from GSuite or Microsoft Azure.
specific Object Object containing data specific to the event which has happened, e.g. The from address and subject of a reported phishing email. Particulars can be found here.

Here is an example JSON payload for an Email Phishing link being clicked by a Microsoft Azure synced employee:

{
"event": {
"id": 129505,
"occurrenceId": 32768,
"pushId": 61,
"type": "EmailPhishing\\Clicking"
},
"common": {
"title": "Employee clicked a phishing link",
"subtext": "COVID-19 Vaccine BUPA",
"dataSource": "Email Phishing",
"date": "2021-08-16",
"timestamp": 1629127113,
"employee": {
"id": 690321,
"forename": "Foo",
"surname": "Bar",
"metadata": {
"ad_object_id": "aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa",
"accountEnabled": "True",
"createdDateTime": "2020-09-17T10:50:31Z",
"companyName": "CultureAI",
"displayName": "Foo Bar",
"mailNickname": "foo.bar",
"refreshTokensValidFromDateTime": "2021-09-17T17:29:05Z",
"signInSessionsValidFromDateTime": "2021-09-17T17:29:05Z",
"usageLocation": "GB",
"userPrincipalName": "foo.bar@culture.ai",
"userType": "Member",
"managerId": "bbbbbbbb-bbbb-bbbb-bbbb-bbbbbbbbbbbb",
"manager": "foo.manager@culture.ai",
"managerFirst": "Foo",
"managerLast": "Manager",
"imAddresses": "foo.bar@culture.ai",
"preferredLanguage": "en-GB",
"department": "foo.manager@culture.ai"
},
"email": "foo.bar@culture.ai",
"jobTitle": "Developer",
"platformUser": true,
"platformAdmin": true,
"creationDate": 1600340103
},
"behaviourIndicator": "NEGATIVE"
},
"specific": {
"sendTime": 1629127097,
"clickTime": 1629127113,
"credentialDiscloseTime": null,
"reportTime": null,
"scenario": {
"id": 62,
"name": "COVID-19 Vaccine BUPA",
"from": {
"name": "Bupa",
"address": "covid@bupvaccines.com"
}
}
}
}

Webhook security

You should not assume any call to your webhook has come from CultureAI, but rather validate the X-WEBHOOK-SIGNATURE header it is called with. This is a SHA-256 hash signed of the request its self with your webhook secret which can be retrieved and regenerated on the general settings page.

To generate this signature, concatenate the request timestamp passed via X-WEBHOOK-TIMESTAMP, the payload version passed via X-WEBHOOK-VERSION and the request body with ::: in-between, then sign with your webhook secret and make sure the result exactly matches the value passed in the X-WEBHOOK-SIGNATURE header.

Here's an example implemented in PHP:

<?php

$secret = '...';

//Generate signature
$signingData = implode(':::', [$_SERVER['HTTP_X_WEBHOOK_TIMESTAMP'], $_SERVER['HTTP_X_WEBHOOK_VERSION'], file_get_contents('php://input')]);
$signature = hash_hmac('sha256', $signingData, $secret);

//Validate signature
if(!hash_equals($signature, $_SERVER['HTTP_X_WEBHOOK_SIGNATURE'])) {
exit;
}

//We're secure!

Re-attempt policy

When a webhook is called and fails to respond with a success-indicating HTTP Status code it will be re-tried up to a maximum of 3 times with a day in-between, after which you must contact success@culture.ai for assistance in having failures re-attempted again.

Here is how we determine success indicating HTTP status codes:

Response Retry?
2xx
3xx
4xx
410
5xx
Timed out

Event specific data

Below is the event specific data provided in the specific object of a RESTful webhook payload, if an event is not listed here then no data will be included in the specific object.

Simulated email phishing (all events)

Data Type Value
sendTime Unix Timestamp Unix Time representing the date and time when the phishing email was original sent.
clickTime Nullable Unix Timestamp Unix Time representing the date and time when the phishing email was first clicked, can be null if the email has not been clicked.
credentialDiscloseTime Nullable Unix Timestamp Unix Time representing the date and time when the phishing email first had credentials disclosed to its associated phishing site, can be null if credentials have not been disclosed.
reportTime Nullable Unix Timestamp Unix Time representing the date and time when the phishing email was first reported by the receiving user, can be null if the email has not been reported.
scenario Object Object containing data about the email phishing scenario sent.
scenario.id Integer Unique identifier for the simulated email phishing scenario.
scenario.name String Name of the simulated email phishing scenario (e.g.Bupa care voucher).
scenario.from Object Object containing data about the sender of a given email phishing scenario.
scenario.from.name String Name that the email phishing scenario sends its email with.
scenario.from.address String Email address that the email phishing scenario is sent from.