Skip to content
English
  • There are no suggestions because the search field is empty.

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

List Simulated Phishing History

Returns a paginated list of simulated phishing attempts sent to employees.
 

Requires the `behaviour.email-phishing.simulated` scope.

Request

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

Example Request

curl -X GET "https://client-api.culture.ai/v1/email-phishing/simulated?pageSize=10&monthView=3&loadMetaData=true" \

-H "Authorization: Basic YOUR_API_KEY"

 

Request Parameters

Parameter Type Required Description
pageSize
Integer No
Items per page (default: 50, max: 500)
paginationCursor
String No
Cursor for fetching next page
filterMode
String No
Scope filter (default: 'ORG')
monthView
String No
Time filter - 'ALL' or number of months
loadMetaData
Boolean No
Include employee metadata in response
campaignIds
Array No
Filter by specific campaign IDs
sortColumn
String No
Column to sort by
sortDir
String No
Sort direction ('asc' or 'desc')
includeDeletedEmployees
Boolean No
Include deleted employees (default: true)

 

Response 

Field Type Description
data Array List of phishing attempts
data[].phishId Integer Unique phishing attempt identifier
data[].organisationEmployeeId Integer Employee ID
data[].userName String Employee full name
data[].userForename String Employee first name
data[].userSurname String Employee surname
data[].userEmail String Employee email address
data[].scenarioName String Name of the phishing scenario
data[].campaignName String Name of the campaign
data[].sent_time Timestamp When the phishing email was sent
data[].clicked_time Timestamp When the phishing link was clicked (null if not clicked)
data[].ipAddress String IP address of click (“N/A” if not clicked)
data[].trainingAssignedTime Timestamp When JIT training was assigned
data[].trainingCompletedTime Timestamp When JIT training was completed
data[].trainingDuration String Duration of training completion
data[].employeeMetadata Object Employee metadata (if loadMetaData = true)
total Integer Total number of records
nextPageCursor String Cursor for next page (if more results exist)

 

Here is an example response:

{
  "data": [
    {
      "phishId": 12345,
      "organisationEmployeeId": 5678,
      "userName": "John Smith",
      "userForename": "John",
      "userSurname": "Smith",
      "userEmail": "john.smith@example.com",
      "scenarioName": "Password Reset Request",
      "campaignName": "Q4 Security Assessment",
      "sent_time": "2024-10-15 09:30:00",
      "clicked_time": "2024-10-15 09:45:23",
      "ipAddress": "192.168.1.100",
      "trainingAssignedTime": "2024-10-15 09:45:30",
      "trainingCompletedTime": "2024-10-15 10:15:45",
      "trainingDuration": "30 minutes",
      "employeeMetadata": {
        "department": "Marketing",
        "location": "London"
      }
    },
    {
      "phishId": 12346,
      "organisationEmployeeId": 5679,
      "userName": "Jane Doe",
      "userForename": "Jane",
      "userSurname": "Doe",
      "userEmail": "jane.doe@example.com",
      "scenarioName": "Invoice Attachment",
      "campaignName": "Q4 Security Assessment",
      "sent_time": "2024-10-15 09:30:00",
      "clicked_time": null,
      "ipAddress": "N/A",
      "trainingAssignedTime": null,
      "trainingCompletedTime": null,
      "trainingDuration": "N/A",
      "employeeMetadata": {
        "department": "Engineering",
        "location": "Manchester"
      }
    }
  ],
  "total": 156,
  "nextPageCursor": "eyJzdGFydCI6MTAsIm1heElkIjoxMjM0Nn0="
}

List Effective Scenarios

Returns scenario effectiveness data showing how well each phishing scenario performs.
 

Requires the `behaviour.email-phishing.effective-scenarios`
 scope.

Request

GET https://client-api.culture.ai/v1/email-phishing/effective-scenarios
Accept: application/json
Authorization: Basic <API_KEY>

Example Request

curl -X GET "https://client-api.culture.ai/v1/email-phishing/effective-scenarios?monthView=6" \
  -H "Authorization: Basic YOUR_API_KEY"

 

Request Parameters

Parameter Type Required Description
filterMode
String No
Scope filter (default: 'ORG')
monthView
String No
Time filter - 'ALL' or number of months

 

Response 

Field Type Description
data Array List of scenarios
data[].scenario String Name of the phishing scenario
data[].totalTested Integer Total number of employees tested with this scenario
data[].percentTested Float Percentage of employees tested
data[].totalClicked Integer Total number of clicks
data[].percentClicked Float Percentage who clicked the phishing link
data[].displayPercentTested String Formatted percentage tested (e.g., "27%", "< 1%")
data[].displayPercentClicked String Formatted percentage clicked (e.g., "7%", "0%")

 

Here is an example response:

{
  "data": [
    {
      "scenario": "Ebay",
      "totalTested": 1481,
      "percentTested": 27.89,
      "totalClicked": 15,
      "percentClicked": 1.01,
      "displayPercentTested": "28%",
      "displayPercentClicked": "1%"
    },
    {
      "scenario": "Google Authenticator",
      "totalTested": 1,
      "percentTested": 0.02,
      "totalClicked": 0,
      "percentClicked": 0,
      "displayPercentTested": "< 1%",
      "displayPercentClicked": "0%"
    },
    {
      "scenario": "Nike - Discount Code",
      "totalTested": 1453,
      "percentTested": 27.36,
      "totalClicked": 33,
      "percentClicked": 2.27,
      "displayPercentTested": "27%",
      "displayPercentClicked": "2%"
    },
    {
      "scenario": "Asos Black Friday",
      "totalTested": 1404,
      "percentTested": 26.44,
      "totalClicked": 93,
      "percentClicked": 6.62,
      "displayPercentTested": "26%",
      "displayPercentClicked": "7%"
    },
    {
      "scenario": "John Lewis Black Friday",
      "totalTested": 1437,
      "percentTested": 27.06,
      "totalClicked": 81,
      "percentClicked": 5.64,
      "displayPercentTested": "27%",
      "displayPercentClicked": "6%"
    }
  ]
}

List Susceptible Users

Returns a paginated list of users who are susceptible to phishing attacks.
 

Requires the `behaviour.email-phishing.susceptible` scope.

Request

GET https://client-api.culture.ai/v1/email-phishing/susceptible-users
Accept: application/json
Authorization: Basic <API_KEY>

Example Request

curl -X GET "https://client-api.culture.ai/v1/email-phishing/susceptible-users?pageSize=20&sortColumn=clickRate&sortDir=desc" \
  -H "Authorization: Basic YOUR_API_KEY"

 

Request Parameters

Parameter Type Required Description
pageSize Integer No Items per page (default: 50, max: 500)
paginationCursor String No Cursor for fetching next page
filterMode String No Scope filter (default: ORG)
monthView String No Time filter — ALL or number of months
metadataName String No Filter by metadata field name
sortColumn String No Column to sort by
sortDir String No Sort direction (asc or desc)

 

Response 

Field Type Description
data Array List of susceptible users
data[].id Integer Employee ID
data[].email String Employee email address
data[].currentlySusceptible String “Yes” or “No”
data[].clickStreak Integer Current consecutive click streak
data[].totalAssessments Integer Total number of phishing assessments
data[].totalOccurrences Integer Total phishing occurrences
data[].scenarioLevels Array Difficulty levels of scenarios clicked (e.g., “high”, “low”)
data[].clickCount String Number of clicks
data[].clickRate String Formatted click rate (e.g., “100%”, “< 1%”)
data[].credsCount String Number of credentials submissions
data[].credsRate String Formatted credentials submission rate
data[].overallClicks Integer Total overall clicks
data[].reportCount String Number of phishing reports
data[].reportRate String Formatted report rate
data[].jitStatus String Just-in-time training status (Not Enabled, Not started, In progress, Completed)
data[].recentAssessments Object / Array Recent phishing assessments with scenario details
data[].recentAssessmentList String Formatted summary of recent assessments
data[].nudges String Nudge email stats as reported/total or N/A
total Integer Total number of records
nextPageCursor String Cursor for next page (if more results exist)

 

Here is an example response:

{
  "data": [
    {
      "id": 269079,
      "currentlySusceptible": "Yes",
      "clickStreak": 1,
      "totalAssessments": 1,
      "totalOccurrences": 1,
      "scenarioLevels": ["high"],
      "clickCount": "1",
      "clickRate": "100%",
      "credsCount": "0",
      "credsRate": "0%",
      "overallClicks": 1,
      "reportCount": "0",
      "reportRate": "0%",
      "jitStatus": "Not Enabled",
      "recentAssessments": {
        "1": {
          "scenarioName": "Asos Black Friday",
          "created_at": "2025-12-01 16:11:34",
          "badAction": true
        }
      },
      "email": "john.smith@example.com",
      "recentAssessmentList": "Bad: Scenario 'Asos Black Friday' sent on 01/12/2025 at 4:11pm; ",
      "nudges": "N/A"
    },
    {
      "id": 269132,
      "currentlySusceptible": "Yes",
      "clickStreak": 1,
      "totalAssessments": 1,
      "totalOccurrences": 1,
      "scenarioLevels": ["high"],
      "clickCount": "1",
      "clickRate": "100%",
      "credsCount": "0",
      "credsRate": "0%",
      "overallClicks": 1,
      "reportCount": "0",
      "reportRate": "0%",
      "jitStatus": "Completed",
      "recentAssessments": {
        "2": {
          "scenarioName": "Asos Black Friday",
          "created_at": "2025-11-27 12:50:25",
          "badAction": true
        }
      },
      "email": "jane.doe@example.com",
      "recentAssessmentList": "Bad: Scenario 'Asos Black Friday' sent on 27/11/2025 at 12:50pm; ",
      "nudges": "N/A"
    },
    {
      "id": 269159,
      "currentlySusceptible": "Yes",
      "clickStreak": 1,
      "totalAssessments": 1,
      "totalOccurrences": 1,
      "scenarioLevels": ["low"],
      "clickCount": "1",
      "clickRate": "100%",
      "credsCount": "0",
      "credsRate": "0%",
      "overallClicks": 1,
      "reportCount": "0",
      "reportRate": "0%",
      "jitStatus": "Not Enabled",
      "recentAssessments": [
        {
          "scenarioName": "Ebay",
          "created_at": "2025-12-04 12:40:34",
          "badAction": true
        }
      ],
      "email": "bob.wilson@example.com",
      "recentAssessmentList": "Bad: Scenario 'Ebay' sent on 04/12/2025 at 12:40pm; ",
      "nudges": "N/A"
    }
  ],
  "total": 5311,
  "nextPageCursor": "eyJzdGFydCI6MywibWF4SWQiOjI2OTE1OX0="
}

List Behaviour Change Over Time

Returns phishing behaviour change data over time for charting purposes.
 

Requires the `behaviour.email-phishing.change-over-time` scope.

Request

GET https://client-api.culture.ai`/v1/email-phishing/change-over-time`
Accept: application/json
Authorization: Basic <API_KEY>

Request Parameters

Parameter Type Required Description
viewMode String Yes Either simple or detailed
filterMode String No Scope filter (default: ORG)
includeNoData Boolean No Include months with no data (default: false)

 

Response (Simple View)

Field Type Description
structuredData Object Monthly data keyed by month identifier (MM-YYYY)
structuredData[month].month String Month identifier
structuredData[month].totalClickedOnly Integer Total users who clicked only
structuredData[month].totalClickedAndCreds Integer Total users who clicked and submitted credentials
structuredData[month].totalReported Integer Total users who reported the phishing email
structuredData[month].percentClickedOnly Integer Percentage who clicked only
structuredData[month].percentReported Integer Percentage who reported
structuredData[month].percentClickedAndCreds Integer Percentage who submitted credentials
structuredData[month].percentNoAction Integer Percentage who took no action
flattenedData Object Data flattened for chart rendering
flattenedData.month Array List of formatted months (e.g., “Jan 25”)
flattenedData.[metric] Array Array of values for each metric

Response (Detailed View)

Field Type Description
structuredData Array Array of monthly data objects
structuredData[].month String Month identifier (MM-YYYY)
structuredData[].fastestClickTime Integer Fastest click time in seconds
structuredData[].fastestReportTime Integer Fastest report time in seconds
structuredData[].totalEvents Integer Total phishing events for the month
structuredData[].totalClickedOnly String Total users who clicked only
structuredData[].totalClickedAndCreds String Total users who submitted credentials
structuredData[].totalDownloaded String Total users who downloaded attachments
structuredData[].totalReported String Total users who reported
structuredData[].totalNoAction String Total users who took no action
structuredData[].percentClickedOnly Float Percentage who clicked only
structuredData[].percentClickedAndCreds Float Percentage who submitted credentials
structuredData[].percentDownloaded Float Percentage who downloaded
structuredData[].percentReported Float Percentage who reported
structuredData[].percentNoAction Float Percentage who took no action
flattenedData Object Data flattened for chart rendering

Example Request (Simple View)

curl -X GET "https://client-api.culture.ai/v1/email-phishing/change-over-time?viewMode=simple" \
  -H "Authorization: Basic YOUR_API_KEY"

Here is an example response: (Simple View)

{
  "structuredData": {
    "01-2025": {
      "month": "01-2025",
      "totalClickedOnly": 79,
      "totalClickedAndCreds": 0,
      "totalReported": 612,
      "percentClickedOnly": 2,
      "percentReported": 15,
      "percentClickedAndCreds": 0,
      "percentNoAction": 83
    },
    "02-2025": {
      "month": "02-2025",
      "totalClickedOnly": 156,
      "totalClickedAndCreds": 10,
      "totalReported": 570,
      "percentClickedOnly": 4,
      "percentReported": 14,
      "percentClickedAndCreds": 0,
      "percentNoAction": 82
    },
    "03-2025": {
      "month": "03-2025",
      "totalClickedOnly": 156,
      "totalClickedAndCreds": 10,
      "totalReported": 570,
      "percentClickedOnly": 4,
      "percentReported": 14,
      "percentClickedAndCreds": 0,
      "percentNoAction": 82
    }
  },
  "flattenedData": {
    "month": ["Jan 25", "Feb 25", "Mar 25"],
    "totalClickedOnly": [79, 156, 156],
    "totalClickedAndCreds": [0, 10, 10],
    "totalReported": [612, 570, 570],
    "percentClickedOnly": [2, 4, 4],
    "percentReported": [15, 14, 14],
    "percentClickedAndCreds": [0, 0, 0],
    "percentNoAction": [83, 82, 82]
  }
}

Example Request (Detailed View)

curl -X GET "https://client-api.culture.ai/v1/email-phishing/change-over-time?viewMode=detailed&includeNoData=true" \
  -H "Authorization: Basic YOUR_API_KEY"

Here is an example response: (Simple View)

{
  "structuredData": [
    {
      "month": "02-2025",
      "fastestClickTime": 22,
      "fastestReportTime": 27,
      "totalEvents": 3995,
      "totalClickedOnly": "156",
      "totalClickedAndCreds": "10",
      "totalDownloaded": "0",
      "totalReported": "601",
      "totalNoAction": "3105",
      "percentClickedOnly": 3.90,
      "percentClickedAndCreds": 0.25,
      "percentDownloaded": 0,
      "percentReported": 15.04,
      "percentNoAction": 77.72
    },
    {
      "month": "05-2025",
      "fastestClickTime": 14,
      "fastestReportTime": 38,
      "totalEvents": 4219,
      "totalClickedOnly": "167",
      "totalClickedAndCreds": "10",
      "totalDownloaded": "0",
      "totalReported": "773",
      "totalNoAction": "3191",
      "percentClickedOnly": 3.96,
      "percentClickedAndCreds": 0.24,
      "percentDownloaded": 0,
      "percentReported": 18.32,
      "percentNoAction": 75.63
    },
    {
      "month": "07-2025",
      "fastestClickTime": 12,
      "fastestReportTime": 36,
      "totalEvents": 4609,
      "totalClickedOnly": "227",
      "totalClickedAndCreds": "14",
      "totalDownloaded": "0",
      "totalReported": "835",
      "totalNoAction": "3464",
      "percentClickedOnly": 4.93,
      "percentClickedAndCreds": 0.30,
      "percentDownloaded": 0,
      "percentReported": 18.12,
      "percentNoAction": 75.16
    }
  ],
  "flattenedData": {
    "month": ["Feb 25", "May 25", "Jul 25"],
    "fastestClickTime": [22, 14, 12],
    "fastestReportTime": [27, 38, 36],
    "totalEvents": [3995, 4219, 4609],
    "totalClickedOnly": ["156", "167", "227"],
    "totalClickedAndCreds": ["10", "10", "14"],
    "totalDownloaded": ["0", "0", "0"],
    "totalReported": ["601", "773", "835"],
    "totalNoAction": ["3105", "3191", "3464"],
    "percentClickedOnly": [3.90, 3.96, 4.93],
    "percentClickedAndCreds": [0.25, 0.24, 0.30],
    "percentDownloaded": [0, 0, 0],
    "percentReported": [15.04, 18.32, 18.12],
    "percentNoAction": [77.72, 75.63, 75.16]
  }
}

List Campaigns

Returns a paginated list of email phishing campaigns.
 

Requires the `behaviour.email-phishing.campaigns` scope.

Request

GET https://client-api.culture.ai/v1/email-phishing/campaigns`
Accept: application/json
Authorization: Basic <API_KEY>

Example Request

curl -X GET "https://client-api.culture.ai/v1/email-phishing/campaigns?pageSize=10&search.value=Q4" \
  -H "Authorization: Basic YOUR_API_KEY"

 

Request Parameters

Parameter Type Required Description
pageSize Integer No Items per page (default: 50, max: 500)
paginationCursor String No Cursor for fetching next page
filterMode String No Scope filter (default: ORG)
monthView String No Time filter — ALL or number of months
search.value String No Search term to filter campaigns
filterOptions.organisationGroupId Integer No Filter by organisation group

 

Response 

Field Type Description
data Array List of campaigns
data[].id Integer Campaign ID
data[].name String Campaign name
data[].schedule_from Date Campaign start date (YYYY-MM-DD)
data[].schedule_to Date Campaign end date (YYYY-MM-DD)
data[].schedule_at_override String Override schedule time (null if not set)
data[].language String Campaign language (e.g., ENGLISH, null)
data[].exclude_clicks_from_occurrence Boolean Whether to exclude clicks from occurrence tracking
data[].status String Campaign status (PAUSED, COMPLETED, ACTIVE, SCHEDULED)
data[].totalSent Integer Total phishing emails sent
data[].percentageOfUsersThatClicked String Formatted click rate (e.g., “5%”)
data[].percentageOfUsersThatGaveCreds String Formatted credentials submission rate
data[].percentageOfUsersThatReported String Formatted report rate
data[].averageClickTime String Average time to click (human-readable format)
data[].averageReportTime String Average time to report (human-readable format)
total Integer Total number of records
nextPageCursor String Cursor for next page (if more results exist)

 

Here is an example response:

{
  "data": [
    {
      "id": 1903,
      "name": "November Black Friday Campaign 2025",
      "schedule_from": "2025-11-19",
      "schedule_to": "2025-12-03",
      "schedule_at_override": null,
      "language": "ENGLISH",
      "exclude_clicks_from_occurrence": false,
      "status": "PAUSED",
      "totalSent": 547,
      "percentageOfUsersThatClicked": "3%",
      "percentageOfUsersThatGaveCreds": "0%",
      "percentageOfUsersThatReported": "14%",
      "averageClickTime": "1 day 51 minutes 36 seconds",
      "averageReportTime": "1 day 3 hours 47 minutes 57 seconds"
    },
    {
      "id": 116,
      "name": "January campaign",
      "schedule_from": "2024-01-25",
      "schedule_to": "2024-02-08",
      "schedule_at_override": null,
      "language": null,
      "exclude_clicks_from_occurrence": false,
      "status": "COMPLETED",
      "totalSent": 3500,
      "percentageOfUsersThatClicked": "5%",
      "percentageOfUsersThatGaveCreds": "0%",
      "percentageOfUsersThatReported": "7%",
      "averageClickTime": "1 day 15 hours 34 minutes 24 seconds",
      "averageReportTime": "2 days 5 hours 32 minutes 29 seconds"
    },
    {
      "id": 352,
      "name": "April campaign 24",
      "schedule_from": "2024-04-15",
      "schedule_to": "2024-04-26",
      "schedule_at_override": null,
      "language": null,
      "exclude_clicks_from_occurrence": false,
      "status": "COMPLETED",
      "totalSent": 3828,
      "percentageOfUsersThatClicked": "5%",
      "percentageOfUsersThatGaveCreds": "0%",
      "percentageOfUsersThatReported": "5%",
      "averageClickTime": "1 day 21 hours 30 minutes",
      "averageReportTime": "22 hours 16 minutes 56 seconds"
    }
  ],
  "total": 14,
  "nextPageCursor": "eyJzdGFydCI6MywibWF4SWQiOjE5MDN9"
}

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.