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. |