API Reference

This section provides a technical overview on how to interact with the API and interactive testing can be performed via our swagger documentation. 

Overview

Endpoint & Versioning

All APIs are reached on the https://client-api.culture.ai endpoint with the version prefixing the API name, for example version 1 of the test API would be /v1/test.

Changes to APIs will be made iteratively unless breaking, in which case you will be notified ahead of time and in our release notes of the upcoming changes. We will always make an effort to keep our APIs backwards compatible with changes being made to new major versions only.

Authentication

Generate an API key in your administration dashboard valid for the scopes that the APIs you want to call require, then pass it in the Authorization header of your request as Basic <API KEY>. You may also restrict the IP ranges each API key can be called from, for additional security.

You can find permissions listed along with the API endpoints below.

Requests & Responses

GET request parameters can be passed via JSON or query string, but we recommend passing them as JSON with the Content-Type of application/json to work around query string length limitations. All other requests should pass their parameters in a JSON string via the request/post body.

Responses will always be made with the Content-Type set to application/json and a JSON object being returned.

Errors

Whenever an error is encountered you will receive a < 400 status code JSON response with the key error in it, describing what exactly was wrong about the request. Here are all the status codes you can expect and some example error messages:

Status code Error message Reason
401

No authentication provided

Invalid authentication

Authentication out of bounds

The Authorization header has not been set.

The provided API key is invalid.

The provided API key is valid, but not for the given IP range.

403 Invalid authentication level The API being called requires a scope that the API key is not valid for.
400/422 Invalid <X> Part of the request body is invalid or malformed.
404 N/A The requested API does not exist.
405 N/A Incorrect HTTP verb supplied for the given API.
500 Service communication error Something has gone wrong on CultureAI's side, the error will have been flagged to us but any additional context you can provide to success@culture.ai would be useful.


Pagination & Ordering

CultureAI supports a cursor-offset hybrid pagination system, which allows you to determine the total amount of records and paginate through real time data feeds without receiving duplicates or skipping records. Ordering is not currently supported on any APIs at this early stage, but we plan to in the future.

APIs which support pagination will note the request supporting a pagination cursor, return their items inside the data key as opposed to the root of the JSON response, include a total key representing the total amount of items there is to retrieve, and (assuming there is more items to retrieve) include a nextPageCursor key which you pass as the paginationCursor on your request for the next page. You can control how many items are returned in each page with the pageSize parameter, the default is 50 and the maximum is 500.

Here is an example of a paginated request using the employee list API, we start by fetching a page of 5 employees:

GET https://client-api.culture.ai/v1/employees?pageSize=5 
Accept: application/json
Authorization: Basic <API_KEY>

Which gives us a response indicating there are 11 employees total and another page from our current position:

{
"data": [
{
"id": 11123,
"name": "Test Account 1",
"email": "test1@culture.ai"
},
{
"id": 11124,
"name": "Test Account 2",
"email": "test2@culture.ai"
},
....
],
"total": 11,
"nextPageCursor": "eyJzdGFydCI6MSwibWF4SWQiOjE4MTQ3MX0="
}

To fetch the next page we make another request, identical to the first but with the parameter paginationCursor set to the value of nextPageCursor from our previous response:

GET https://client-api.culture.ai/v1/employees?pageSize=5&paginationCursor=eyJzdGFydCI6MSwibWF4SWQiOjE4MTQ3MX0 
Accept: application/json
Authorization: Basic <API_KEY>

API Endpoints

Connection Testing 

Tests your connection and authentication with the CultureAI API, requires no scopes. Returns minimal data about who you are authenticated as and what the read API key was for your verification.

Request 

This API does not support any parameters.

GET https://client-api.culture.ai/v1/me 
Accept: application/json
Authorization: Basic <API_KEY>

Response 

{
"apiKey": "API_KEY",
"client": "Culture AI"
}

Get Employees 

Fetches the employees you have synced, imported or manually created in access management settings.

Requires the employee.read scope.

Request 

This API only supports the standard pagination parameters.

GET https://client-api.culture.ai/v1/employees 
Accept: application/json
Authorization: Basic <API KEY>

Response 

This API follows the standard pagination response structure, with each employee in the data array containing the following values:

Key Type Description
id Integer The unique id of the employee, used in related APIs such as fetching risk scores.
name String The full name of the employee, space concatenated.
email String The email address of the employee, used for non-SSO login, email notifications and relating things such as Slack logins, mailbox reports, etc. to the employee.

Here is an example response:

{
"data": [
{
"id": 523163,
"name": "Test Account",
"email": "test@culture.ai"
}
....
],
"total": 52,
"nextPageCursor": "eyJzdGFydCI6NSwibWF4SWQiOjE4MTQ3MX0="
}

Employee's Risks 

List employee's associated security decision, livelihood, impact and organisation risk scores from the People & Teams Dashboard.

Requires the risk.read scope.

Request 

This API supports the standard pagination parameters, in addition to:

Parameter Type Purpose
ids Array of employee id integers Only fetch associated scores & risks for the given employee IDs.

Get all users/risks:

GET https://client-api.culture.ai/v1/risks
Accept: application/json
Authorization: Basic <API_KEY>

Get risks for a subset of employees:

GET https://client-api.culture.ai/v1/risks?ids[]=12345&ids[]=678910
Accept: application/json
Authorization: Basic <API_KEY>

Response 

This API follows the standard pagination response structure, with each object in the data array representing a single employee's score & risk data following the below structure:

Key Type Description
employeeId Integer The unique ID of the employee this is for.
securityDecisionScore Integer An integer from 0-100 aggregating an employee's positive & negative security decisions, higher is better.
securityDecisionScoreThreshold String Enum
(LOW/MED/HIGH)
A string value representing what band CultureAI consider the employee's security decision score to be in. Low is good.
overallRiskScore Integer An integer from 0-100 representing how much risk CultureAI estimates an employee poses to your organisation, considering security decisions, likelihood of being attacked and impact if breached. Lower is better.
overallRiskScoreThreshold String Enum
(LOW/MED/HIGH)
A string value representing what band of risk CultureAI consider the employee to be in. Low is good.
likelihoodRiskScore Integer An integer from 0-100 representing how likely CultureAI think it is that a given employee will be attacked. Lower is better.
likelihoodRiskScoreThreshold String Enum
(LOW/MED/HIGH)
A string value representing what band of likelihood of attack CultureAI consider the employee to be in. Low is good.
impactRiskScore Integer An integer from 0-100 representing the impact CultureAI think compromising a given employee would have on your organisation. Lower is better.
impactRiskScoreThreshold String Enum
(LOW/MED/HIGH)
A string value representing what band of impact on you organisation CultureAI consider the employee to be in. Low is good.

Here is an example response:

{
"data": [
{
"employeeId": 523163,
"securityDecisionScore": 100,
"securityDecisionScoreThreshold": "LOW",
"overallRiskScore": 50,
"overallRiskScoreThreshold": "MED",
"liklihoodRiskScore": 77,
"liklihoodRiskScoreThreshold": "HIGH",
"impactRiskScore": 0,
"impactRiskScoreThreshold": "LOW"
}
...
],
"total": 52,
"nextPageCursor": "eyJzdGFydCI6NSwibWF4SWQiOjE4MTQ3MX0="
}

Behavioural Event Creation 

Creates an event for a new or existing behaviour (Security decision) against a given employee, if you're creating an event for a new behaviour it must be set-up by an admin within Custom Behaviour settings before the CultureAI Platform will process the event.

Requires the behaviour.event.create scope.

Please note that behavioural event creation is a paid upgrade to your CultureAI account. If you'd be interested in trailing this, please get in touch with your account manager.

Request 

A dot implies the following key is in a sub object of the previous. So foo.bar would have bar in the object foo

Parameter Type Purpose
behaviour Array Provides details about the behaviour the event will be linked to
behaviour.reference String Unique reference for the behaviour, used to link multiple created events to the same behaviour
event Array Provides details about the event being created
event.employee Array Provides linking data for the employee the event happened to, either id ot email must be provided
event.employee.id Optional Integer ID of the employee the event happened to, if fetched from another API
event.employee.email Optional String Case insensitive string of the employee's email address as configured in Users & Access
event.description Nullable String Text giving further detail on the event, displayed under the event title within supporting event logs
event.reference Integer Unique reference for the event happening within the behaviour, used to ensure event uniqueness
event.date String Y-m-d formatted date string (EG: 2024-07-28) for the date the event happened
event.time Nullable String H:i:s formatted time string (EG: 17:32:16) for the time on the date the event happened. The event will be displayed as date-only if this is not specified. Events with & without times can be used within the same behaviour
event.metadata Optional Array Provides additional data for displaying within "Details" on supporting event logs, and for use as "Personalisation Tokens" within messages
event.metadata.* Array Array of a single metadata value relating to the event
event.metadata.*.key String Short name for the metadata being recorded, will be automatically converted to Title Case when displayed
event.metadata.*.value String Value of the metadata being recorded, will be stored securely so PII containing values may be provided
event.metadata.*.important Boolean Whether the metadata is important to describing the event, true will display the metadata key & value in the "Details" column of supporting event logs
POST https://client-api.culture.ai/v1/risks
Accept: application/json
Authorization: Basic <API_KEY>

{
    "behaviour": {
        "reference": "LEAVING_DESKTOP_UNLOCKED"
    },
    "event": {
        "employee": {
            "email": "robby.rogers@culture.ai"
        },
        "reference": 5000,
        "date": "2024-02-22",
        "time": "09:58:32",
        "description": "Laptop was left unlocked on longue table",
        "metadata": [
            {
                "key": "area",
                "value": "Social Lounge 1",
                "important": true
            },
            {
                "key": "spottedBy",
                "value": "IT Support",
                "important": false
            },
            {
                "key": "operatingSystem",
                "value": "Windows",
                "important": false
            }
        ]
    }
}

Response 

Key Type Description
id Nullable Integer The unique id of the processed behaviroual event, null when the event has not been processed
ingestionId Integer The unique id of the ingestion log, identifies this ingestion of an event even when the event has not been processed yet
status Enum The processing status of the ingested event
PENDING_BEHAVIOUR_SETUP if the ingested event has not been processed
INGESTED if the ingested event has been processed into a behavioural event

Here is an example response when ingesting an event for a new behaviour, note how the id is null because the event has not been processed and the status is PENDING_BEHAVIOUR_SETUP to indicate the event was ingested to a behaviour which has not been set-up within Custom Behaviour settings:

{
    "id": null,
    "ingestionId": 16,
    "status": "PENDING_BEHAVIOUR_SETUP"
}

Here is an example response when ingesting an event for a behaviour which has already been set-up, the event will appear immediately in the UI with triggered processes such as Interventions & Just-in-time-education processing within a few minutes of ingestion, usually within a minute.

{
    "id": 5313640,
    "ingestionId": 17,
    "status": "INGESTED"
}

List Email Reports 

Fetches email reports from users submitted by the CultureAI reporting plugin or synchronized via integration.

Requires the triage.reports.emails.read scope.

This API supports the standard pagination parameters, in addition to:

Parameter Type Purpose
fromDate Date time string (Y-m-d H:i:s) Restrict the returned results based on the reportedAt
GET https://client-api.culture.ai/v1/triage/reports/emails
Accept: application/json
Authorization: Basic <API_KEY>

Response 

Key Type Description
caseId Integer The caseID associated with the reported email, this is a logical aggregation and shared between reports where they appear to be the same
reportType String The source of the report event, this will be CULTUREAI for reports submitted via the CultureAI Outlook or Gmail plugin, or the integration such as 'MICROSOFT'
reportTypeId Integer A unique reference linked to the reportType and used for retrieving further information such as the original email
externalReference String Used for integration synced reports, represents the id/reference of the report in the integration (EG Microsoft Defender)
reportedAt String The timestamp from when the email was reported (YYYY-mm-dd hh:mm:ss)
isSimulated Integer Specifies whether the email was sent by CultureAI as part of a simulated phishing assessment. 1 if simulated, 0 if not.
isSharedMailbox Integer Specifies whether the email was reported by a user from a shared mailbox (currently supported only for Microsoft 365 using the CultureAI plugin)
recipients Array An array containing 'name' (string) and 'email' (string) keys for each recipient, may contain the reporter's details where no recipients are visible (e.g. if all users BCC'd)
sender Array An array containing 'name' (string) and 'email' (string) keys for the sender
subject String Subject of the email
riskScore Integer Indicative score on risk out of 100 (higher number suggests higher risk) based on high level automated analysis
attachments Integer Number of attachments in the email
reportedBy Array An array containing 'id' (integer), 'name' (string), 'email' (string) for the reporting user. Id is a unique employee reference used within the CultureAI platform.
reportReason String Has the reason the user reported the email (where provided), current options are 'PHISHING', 'SPAM', 'OTHER'
interactions Array Array containing any interactions specified by the user, currently supports 'CLICKED'.

Note, some fields may be returned as 'null' where the source does not provide sufficient metadata (e.g. 3rd party integration).

Here is an example response:

[
{
"caseId": 10,
"reportType": "CULTUREAI",
"reportTypeId": 406,
"externalReference": null,
"reportedAt": "2021-11-30 22:11:19",
"isSimulated": 0,
"isSharedMailbox": 0,
"recipients": [
{
"name": "Bob Smith",
"email": "bob.smith@culture.ai"
},
{
"name": "Another User",
"email": "another.user@culture.ai"
}
],
"sender": {
"name": "payroll",
"email": "urgent@thirdparty.culture.ai"
},
"subject": "Urgent: Payroll details need updating",
"riskScore": 97,
"attachments": 1,
"reportedBy": {
"id": 46,
"name": "Targeted User",
"email": "targeted.user@culture.ai"
},
"reportReason": "PHISHING",
"interactions": ['CLICKED']
}
]

Fetch Reported Email Contents 

Fetches a reported email and associated metadata, only supported for the 'CULTUREAI' report source.

Requires the triage.reports.emails.detail scope.

Request

GET https://client-api.culture.ai/v1/triage/reports/emails/detail
Accept: application/json
Authorization: Basic <API_KEY>
Content-Type: application/json

{
"reportType": "CULTUREAI",
"reportTypeId": 406
}

Response 

Key Type Description
headers String The headers extracted from the email
links Array Returns an array of links found in the body of the main email
body String The body of the email
attachments Array Returns an array of attachment details 'filename' (string), 'contentType' (string), 'sha512' (string)
raw String Base64 encoded version of the raw email content

Here is an example response:

{
"headers": "Received: from ...",
"links": [
"https:\/\/app.domain.eu\/account\/profile\/u-tQ0u6I-g11j9",
"https:\/\/app.domain.eu\/monitors\/686069?to_ts=1638299909000",
"https:\/\/app.domain.eu\/monitors#686069\/edit",
"https:\/\/app.domain.eu\/event\/event?id=6275296781375450081",
"https:\/\/app.domain.eu\/account\/login\/mobile?dd_referrer=subscription_email&amp;dd_m=1&amp;",
"https:\/\/app.domain.eu\/account\/preferences"
],
"body": "<html><head>\r\n<meta http-equiv=\"Co...",
"attachments": [],
"raw": "UmVjZWl2ZWQ6IGZyb20gQ1dMUDEyM01CMzc3OS5HQlJ..."
}

Bug Reports & Feature Requests

If you spot anything wrong with our APIs (We're only human!) or have new features you'd like to see, or data you'd like to pull out, don't hesitate to contact us on success@culture.ai.