For the complete documentation index, see llms.txt. This page is also available as Markdown.

Pull phishing campaign user behaviors

As a Company Admin you can list your organization’s phishing, smishing, or quishing campaigns and pull per-user behaviors for a campaign job: who opened, clicked, or submitted data, with timestamps. Use a credential with Client Role = Company Admin. Company context is automatic. Do not send X-KEEPNET-Company-Id. The same pattern applies to phishing, smishing, and quishing simulators — only the base path changes.

Request a Bearer token before any call: Quickstart → Request an access token.

Reseller

If your credential has Client Role = Reseller, send X-KEEPNET-Company-Id: <companyResourceId> on every request below (from POST /api/companies/search). See View customer's campaign list and report → and Scope API requests to a customer →.


POST /api/phishing-simulator/phishing-campaign/search

Returns a paginated list of phishing campaigns for your company.

Returns a list of the phishing campaigns. Test it: Authorize with Client ID/Secret, then Send — request body is pre-filled.

Returns a list of the phishing campaigns

post
Required scopes
This endpoint requires the following scopes:
  • : API
Authorizations
OAuth2clientCredentialsRequired

Client ID and Client Secret from Company → Company Settings → REST API. Enter credentials to auto-fetch token.

Token URL:
Body
pageNumberintegerRequiredExample: 1
pageSizeintegerRequiredExample: 20
orderBystringRequiredExample: CreateTime
ascendingbooleanRequiredExample: false
Responses
200

OK

application/json
statusstringOptional
messagestring · nullableOptional
validationMessagesstring[] · nullableOptional
post/api/phishing-simulator/phishing-campaign/search
POST /api/phishing-simulator/phishing-campaign/search HTTP/1.1
Host: api.keepnetlabs.com
Authorization: Bearer YOUR_OAUTH2_TOKEN
Content-Type: application/json
Accept: */*
Content-Length: 126

{
  "pageNumber": 1,
  "pageSize": 20,
  "orderBy": "CreateTime",
  "ascending": false,
  "filter": {
    "Condition": "AND",
    "SearchInputTextValue": ""
  }
}
200

OK

{
  "data": {
    "pageNumber": 1,
    "pageSize": 1,
    "totalNumberOfPages": 1,
    "totalNumberOfRecords": 1,
    "results": [
      {
        "resourceId": "text",
        "name": "text",
        "method": "text",
        "methodDetail": "text",
        "scenarioCount": "text",
        "instanceCount": "text",
        "targetUsers": "text",
        "status": "text",
        "instanceGroup": 1,
        "hasTraining": true,
        "jobResultMessage": "text",
        "createdBy": "text",
        "createTime": "2026-01-01T00:00:00.000Z",
        "lastLaunch": "2026-01-01T00:00:00.000Z",
        "emailDelivery": "text",
        "frequency": 1,
        "categoryDistributionType": "text"
      }
    ]
  },
  "status": "text",
  "message": "text",
  "validationMessages": [
    "text"
  ]
}

Campaigns with Mark as Test (excludeFromReports: true) are excluded from dashboard and report statistics in the UI; they may still appear in API list responses. When aggregating metrics, filter or ignore items where excludeFromReports is true.

Smishing and quishing

Same flow with a different base path:

  • Smishing: POST /api/smishing-simulator/smishing-campaign/search

  • Quishing: POST /api/quishing-simulator/quishing-campaign/search


POST /api/phishing-simulator/phishing-campaign-job-report/search

Campaign jobs are run instances of a campaign. This endpoint returns jobs for reporting. From each result row, note phishingCampaignResourceId and instanceGroup for the summary and per-user searches below. For this endpoint, use orderBy: "Name" in the request body ("CreateTime" can return 400 Invalid request).

Retrieves campaign job's list. Test it: Authorize with Client ID/Secret, then Send — request body is pre-filled.

Retrieves campaign job's list.

post
Required scopes
This endpoint requires the following scopes:
  • : API
Authorizations
OAuth2clientCredentialsRequired

Client ID and Client Secret from Company → Company Settings → REST API. Enter credentials to auto-fetch token.

Token URL:
Body
pageNumberintegerRequiredExample: 1
pageSizeintegerRequiredExample: 20
orderBystringRequiredExample: Name
ascendingbooleanRequiredExample: false
Responses
200

OK

application/json
statusstringOptional
messagestring · nullableOptional
validationMessagesstring[] · nullableOptional
post/api/phishing-simulator/phishing-campaign-job-report/search
POST /api/phishing-simulator/phishing-campaign-job-report/search HTTP/1.1
Host: api.keepnetlabs.com
Authorization: Bearer YOUR_OAUTH2_TOKEN
Content-Type: application/json
Accept: */*
Content-Length: 120

{
  "pageNumber": 1,
  "pageSize": 20,
  "orderBy": "Name",
  "ascending": false,
  "filter": {
    "Condition": "AND",
    "SearchInputTextValue": ""
  }
}
200

OK

{
  "data": {
    "pageNumber": 1,
    "pageSize": 1,
    "totalNumberOfPages": 1,
    "totalNumberOfRecords": 1,
    "results": [
      {
        "phishingCampaignResourceId": "text",
        "instanceGroup": 1,
        "name": "text",
        "startDate": "2026-01-01T00:00:00.000Z",
        "totalOpenedCount": 1,
        "totalClickedCount": 1,
        "totalSubmittedCount": 1,
        "totalAttachmentOpenedCount": 1,
        "totalNoResponseCount": 1,
        "totalTargetUserCount": 1,
        "emailDeliveredUserCount": 1,
        "method": "text",
        "methodDetail": "text",
        "status": "text",
        "jobResultMessage": "text",
        "createdBy": "text",
        "createdDate": "2026-01-01T00:00:00.000Z",
        "emailDelivery": "text",
        "totalSubmittedMFACount": 1
      }
    ]
  },
  "status": "text",
  "message": "text",
  "validationMessages": [
    "text"
  ]
}

From the response, pick a job and note phishingCampaignResourceId and instanceGroup. Example: "phishingCampaignResourceId": "xHJe83nmj0W7", "instanceGroup": 1 (use values from your response; dummy IDs in examples — H8d).


GET /api/phishing-simulator/phishing-campaign-job-report/summary/{resourceId}/{instanceGroup}

Returns aggregate metrics for one campaign job (sent, opened, clicked, submitted counts, and related summary fields). Path resourceId is the job row’s phishingCampaignResourceId (not a target-user ID).

Returns campaign job summary. Test it: Set path resourceId and instanceGroup from the job search response.

Retrieves phishing campaign job's summary details.

get
Required scopes
This endpoint requires the following scopes:
  • : API
Authorizations
OAuth2clientCredentialsRequired

Client ID and Client Secret from Company → Company Settings → REST API. Enter credentials to auto-fetch token.

Token URL:
Path parameters
resourceIdstringRequired
instanceGroupinteger · int32Required
Responses
200

OK

application/json
statusstringOptional
messagestring · nullableOptional
validationMessagesstring[] · nullableOptional
get/api/phishing-simulator/phishing-campaign-job-report/summary/{resourceId}/{instanceGroup}
GET /api/phishing-simulator/phishing-campaign-job-report/summary/{resourceId}/{instanceGroup} HTTP/1.1
Host: api.keepnetlabs.com
Authorization: Bearer YOUR_OAUTH2_TOKEN
Accept: */*
200

OK

{
  "data": {
    "phishingCampaignResourceId": "text",
    "phishingCampaignName": "text",
    "campaignInfo": {
      "startDate": "2026-01-01T00:00:00.000Z",
      "endDate": "2026-01-01T00:00:00.000Z",
      "scheduledDate": "2026-01-01T00:00:00.000Z",
      "totalTargetUserCount": 1,
      "emailDeliveredUserCount": 1,
      "emailNotDeliveredUserCount": 1,
      "emailDeliveryStartDate": "2026-01-01T00:00:00.000Z",
      "emailDeliveryEndDate": "2026-01-01T00:00:00.000Z",
      "frequency": 1,
      "emailDeliveryDuration": "text",
      "scheduleTypeId": 1,
      "categoryDistributionType": "text",
      "trackingReplyInfo": "text",
      "sendUserPreferredLanguage": 1
    },
    "settings": {
      "excludeFromReports": true,
      "duration": 1,
      "smtpName": "text",
      "directEmailSettingName": "text"
    },
    "targetUsers": {
      "randomlyUsersCount": 1,
      "targetGroupsCount": 1,
      "sendRandomlyUsers": true,
      "sendOnlyActiveUsers": true
    },
    "scenarioStats": {
      "openedEmail": 1,
      "clickedEmail": 1,
      "submittedEmail": 1,
      "attachmentOpenedEmail": 1,
      "reportedEmail": 1,
      "noResponseEmail": 1,
      "notDelivered": 1,
      "failedToSend": 1,
      "mfa": 1
    },
    "scenarios": [
      {
        "scenarioInfo": {
          "name": "text",
          "category": "text",
          "methodTypeId": 1,
          "difficultyTypeId": 1,
          "languageShortCode": "text"
        },
        "trainingInfo": {
          "trainingId": "text",
          "trainingDescription": "text",
          "name": "text",
          "categoryName": "text",
          "companyName": "text",
          "languageList": [
            {
              "languageId": "text",
              "languageShortCode": "text"
            }
          ]
        },
        "enrollmentInfo": {
          "enrollmentId": "text"
        },
        "emailTemplateInfo": {
          "resourceId": "text",
          "name": "text",
          "categoryResourceId": "text",
          "difficultyResourceId": "text",
          "fromName": "text",
          "fromAddress": "text",
          "languageShortCode": "text",
          "phishingFileName": "text",
          "phishingFileType": "text",
          "phishingFileUrl": "text",
          "subject": "text",
          "template": "text"
        },
        "emailTemplateInfos": [
          {
            "resourceId": "text",
            "name": "text",
            "categoryResourceId": "text",
            "difficultyResourceId": "text",
            "fromName": "text",
            "fromAddress": "text",
            "languageShortCode": "text",
            "phishingFileName": "text",
            "phishingFileType": "text",
            "phishingFileUrl": "text",
            "subject": "text",
            "template": "text"
          }
        ],
        "landingPageTemplateInfo": {
          "resourceId": "text",
          "name": "text",
          "methodTypeId": 1,
          "difficultyTypeId": 1,
          "urlTemplate": "text",
          "languageShortCode": "text"
        }
      }
    ],
    "scenariosGeneralInfo": {
      "categories": [
        "text"
      ],
      "methodTypeId": 1,
      "difficultyTypeIds": [
        1
      ],
      "languageShortCodes": [
        "text"
      ]
    },
    "landingPageTemplateInfo": {
      "resourceId": "text",
      "name": "text",
      "methodTypeId": 1,
      "difficultyTypeId": 1,
      "urlTemplate": "text",
      "languageShortCode": "text"
    },
    "trainingInfoForCategory": {
      "trainingId": "text",
      "trainingDescription": "text",
      "name": "text",
      "categoryName": "text",
      "companyName": "text",
      "languageList": [
        {
          "languageId": "text",
          "languageShortCode": "text"
        }
      ]
    },
    "enrollmentInfoForCategory": {
      "enrollmentId": "text"
    },
    "smartGroupInfo": {
      "resourceId": "text",
      "name": "text"
    },
    "campaignDurationExpired": true
  },
  "status": "text",
  "message": "text",
  "validationMessages": [
    "text"
  ]
}

Example: GET /api/phishing-simulator/phishing-campaign-job-report/summary/xHJe83nmj0W7/1


POST /api/phishing-simulator/phishing-campaign-job-report/{searchType}/search/{resourceId}/{instanceGroup}

Returns a paginated list of target users for the campaign job filtered by behavior. Path resourceId = phishingCampaignResourceId from the job search row; instanceGroup = instanceGroup from the same row.

Common searchType values: Opened, Clicked, All, NoResponse, Reported, AttachmentOpened, Replied. For submitted users, use All and read submittedCount / lastSubmittedTime; Submitted is not valid as searchType (400). Per-user field names are in Endpoints → PhishingCampaignJobReport.

Search Phishing Campaign Users. Test it: Set path parameters from the job search response; request body is pre-filled.

Search Phishing Campaign Users

post
Required scopes
This endpoint requires the following scopes:
  • : API
Authorizations
OAuth2clientCredentialsRequired

Client ID and Client Secret from Company → Company Settings → REST API. Enter credentials to auto-fetch token.

Token URL:
Path parameters
searchTypestringRequired
resourceIdstringRequired
instanceGroupinteger · int32Required
Body
pageNumberintegerRequiredExample: 1
pageSizeintegerRequiredExample: 100
orderBystringRequiredExample: Email
ascendingbooleanRequiredExample: false
Responses
200

OK

application/json
statusstringOptional
messagestring · nullableOptional
validationMessagesstring[] · nullableOptional
post/api/phishing-simulator/phishing-campaign-job-report/{searchType}/search/{resourceId}/{instanceGroup}
POST /api/phishing-simulator/phishing-campaign-job-report/{searchType}/search/{resourceId}/{instanceGroup} HTTP/1.1
Host: api.keepnetlabs.com
Authorization: Bearer YOUR_OAUTH2_TOKEN
Content-Type: application/json
Accept: */*
Content-Length: 122

{
  "pageNumber": 1,
  "pageSize": 100,
  "orderBy": "Email",
  "ascending": false,
  "filter": {
    "Condition": "AND",
    "SearchInputTextValue": ""
  }
}
200

OK

{
  "data": {
    "totalSandBoxActivityCount": 1,
    "pageNumber": 1,
    "pageSize": 1,
    "totalNumberOfPages": 1,
    "totalNumberOfRecords": 1,
    "results": [
      {
        "resourceId": "text",
        "firstName": "text",
        "lastName": "text",
        "email": "text",
        "department": "text",
        "phishingScenarioName": "text",
        "phishingScenarioLanguage": "text",
        "emailTemplateLanguage": "text",
        "lastOpenedTime": "2026-01-01T00:00:00.000Z",
        "lastOpenedTimeToLocalUser": "text",
        "openedCount": 1,
        "lastClickedTime": "2026-01-01T00:00:00.000Z",
        "lastClickedTimeToLocalUser": "text",
        "clickedCount": 1,
        "lastSubmittedTime": "2026-01-01T00:00:00.000Z",
        "lastSubmittedTimeToLocalUser": "text",
        "submittedCount": 1,
        "lastAttachmentOpenedTime": "2026-01-01T00:00:00.000Z",
        "lastAttachmentOpenedTimeToLocalUser": "text",
        "attachmentOpenedCount": 1,
        "minPasswordComplexity": "text",
        "status": "text",
        "jobResultMessage": "text",
        "lastSendingTime": "2026-01-01T00:00:00.000Z",
        "lastSendingTimeToLocalUser": "text",
        "reportedCount": 1,
        "lastReportedTime": "2026-01-01T00:00:00.000Z",
        "lastReportedTimeToLocalUser": "text",
        "emailDelivery": "text",
        "mfaSubmittedCount": 1,
        "activityType": "text",
        "systemActivityType": "text",
        "mfaLastSubmittedTime": "2026-01-01T00:00:00.000Z",
        "mfaLastSubmittedTimeToLocalUser": "text",
        "replyType": "text",
        "replySent": "2026-01-01T00:00:00.000Z",
        "replySentToLocalUser": "text",
        "isTrackingReplyContentEnabled": true,
        "isTrackingReplyOutOfOfficeEnabled": true,
        "preferredLanguage": "text",
        "targetGroups": "text",
        "targetUserId": 1,
        "customFieldValues": [
          {
            "resourceId": "text",
            "name": "text",
            "dataType": "text",
            "value": "text",
            "timestampValue": "2026-01-01T00:00:00.000Z"
          }
        ]
      }
    ]
  },
  "status": "text",
  "message": "text",
  "validationMessages": [
    "text"
  ]
}

Example: POST /api/phishing-simulator/phishing-campaign-job-report/Opened/search/xHJe83nmj0W7/1. Paginate until pageNumber reaches totalNumberOfPages or results is empty. From a user row, note resourceId for the email detail endpoints below.


POST /api/phishing-simulator/phishing-campaign-job-report/search-email-opened/{resourceId}

Event-level opened detail for one target user. Path resourceId is the user’s resourceId from a user list row (Opened / Clicked / All search), not phishingCampaignResourceId.

Search Phishing Campaign User Email Opened. Test it: Set path resourceId from the user list; request body is pre-filled.

Search Phishing Campaign User Email Opened

post
Required scopes
This endpoint requires the following scopes:
  • : API
Authorizations
OAuth2clientCredentialsRequired

Client ID and Client Secret from Company → Company Settings → REST API. Enter credentials to auto-fetch token.

Token URL:
Path parameters
resourceIdstringRequired
Body
pageNumberintegerRequiredExample: 1
pageSizeintegerRequiredExample: 100
orderBystringRequiredExample: Email
ascendingbooleanRequiredExample: false
Responses
200

OK

application/json
statusstringOptional
messagestring · nullableOptional
validationMessagesstring[] · nullableOptional
post/api/phishing-simulator/phishing-campaign-job-report/search-email-opened/{resourceId}
POST /api/phishing-simulator/phishing-campaign-job-report/search-email-opened/{resourceId} HTTP/1.1
Host: api.keepnetlabs.com
Authorization: Bearer YOUR_OAUTH2_TOKEN
Content-Type: application/json
Accept: */*
Content-Length: 122

{
  "pageNumber": 1,
  "pageSize": 100,
  "orderBy": "Email",
  "ascending": false,
  "filter": {
    "Condition": "AND",
    "SearchInputTextValue": ""
  }
}
200

OK

{
  "data": {
    "resourceId": "text",
    "openedTime": "2026-01-01T00:00:00.000Z",
    "sandBoxType": 1,
    "systemSandBoxType": 1,
    "activityType": "text",
    "systemActivityType": "text",
    "isChangedActivity": true,
    "openedTimeToLocalUser": "text",
    "browserName": "text",
    "userAgent": "text",
    "userGeolocation": "text",
    "userIpAddressList": "text",
    "isExcluded": true
  },
  "status": "text",
  "message": "text",
  "validationMessages": [
    "text"
  ]
}

POST /api/phishing-simulator/phishing-campaign-job-report/search-email-clicked/{resourceId}

Event-level clicked detail for the same user. Same path resourceId as the opened endpoint.

Search Phishing Campaign User Email Clicked. Test it: Set path resourceId from the user list; request body is pre-filled.

Search Phishing Campaign User Email Clicked

post
Required scopes
This endpoint requires the following scopes:
  • : API
Authorizations
OAuth2clientCredentialsRequired

Client ID and Client Secret from Company → Company Settings → REST API. Enter credentials to auto-fetch token.

Token URL:
Path parameters
resourceIdstringRequired
Body
pageNumberintegerRequiredExample: 1
pageSizeintegerRequiredExample: 100
orderBystringRequiredExample: Email
ascendingbooleanRequiredExample: false
Responses
200

OK

application/json
statusstringOptional
messagestring · nullableOptional
validationMessagesstring[] · nullableOptional
post/api/phishing-simulator/phishing-campaign-job-report/search-email-clicked/{resourceId}
POST /api/phishing-simulator/phishing-campaign-job-report/search-email-clicked/{resourceId} HTTP/1.1
Host: api.keepnetlabs.com
Authorization: Bearer YOUR_OAUTH2_TOKEN
Content-Type: application/json
Accept: */*
Content-Length: 122

{
  "pageNumber": 1,
  "pageSize": 100,
  "orderBy": "Email",
  "ascending": false,
  "filter": {
    "Condition": "AND",
    "SearchInputTextValue": ""
  }
}
200

OK

{
  "data": {
    "resourceId": "text",
    "clickedTime": "2026-01-01T00:00:00.000Z",
    "sandBoxType": 1,
    "systemSandBoxType": 1,
    "activityType": "text",
    "systemActivityType": "text",
    "isChangedActivity": true,
    "clickedTimeToLocalUser": "text",
    "browserName": "text",
    "userAgent": "text",
    "userGeolocation": "text",
    "userIpAddressList": "text",
    "isExcluded": true
  },
  "status": "text",
  "message": "text",
  "validationMessages": [
    "text"
  ]
}

POST /api/phishing-simulator/phishing-campaign-job-report/search-email-submitted/{resourceId}

Event-level submitted detail for the same user. Same path resourceId as above. Using the campaign job ID here returns 404 (Phishing campaign instance user not found).

Search Phishing Campaign User Email Submitted. Test it: Set path resourceId from the user list; request body is pre-filled.

Search Phishing Campaign User Email Submitted

post
Required scopes
This endpoint requires the following scopes:
  • : API
Authorizations
OAuth2clientCredentialsRequired

Client ID and Client Secret from Company → Company Settings → REST API. Enter credentials to auto-fetch token.

Token URL:
Path parameters
resourceIdstringRequired
Body
pageNumberintegerRequiredExample: 1
pageSizeintegerRequiredExample: 100
orderBystringRequiredExample: Email
ascendingbooleanRequiredExample: false
Responses
200

OK

application/json
statusstringOptional
messagestring · nullableOptional
validationMessagesstring[] · nullableOptional
post/api/phishing-simulator/phishing-campaign-job-report/search-email-submitted/{resourceId}
POST /api/phishing-simulator/phishing-campaign-job-report/search-email-submitted/{resourceId} HTTP/1.1
Host: api.keepnetlabs.com
Authorization: Bearer YOUR_OAUTH2_TOKEN
Content-Type: application/json
Accept: */*
Content-Length: 122

{
  "pageNumber": 1,
  "pageSize": 100,
  "orderBy": "Email",
  "ascending": false,
  "filter": {
    "Condition": "AND",
    "SearchInputTextValue": ""
  }
}
200

OK

{
  "data": {
    "submittedTime": "2026-01-01T00:00:00.000Z",
    "submittedData": "text",
    "submittedTimeToLocalUser": "text",
    "browserName": "text",
    "userAgent": "text",
    "userGeolocation": "text",
    "userIpAddressList": "text",
    "isExcluded": true
  },
  "status": "text",
  "message": "text",
  "validationMessages": [
    "text"
  ]
}

Export

  • Export job report list: POST /api/phishing-simulator/phishing-campaign-job-report/search/export — same body shape as job search (see Endpoints → PhishingCampaignJobReport). Response is CSV (binary), not JSON.

  • Export per behavior list: POST /api/phishing-simulator/phishing-campaign-job-report/{searchType}/search/export/{resourceId}/{instanceGroup} (for example Opened with the same phishingCampaignResourceId and instanceGroup).

Smishing and quishing have equivalent paths under smishing-simulator and quishing-simulator.


Common errors

  • 403 Forbidden — Wrong Client Role or missing permission. Set Client Role = Company Admin in Company → Company Settings → REST API. Roles and permissions →

  • 401 Unauthorized — Missing or invalid token. Request a new token via POST /connect/token.

  • 400 Bad Request — Invalid search body. For phishing-campaign-job-report/search, use orderBy: "Name" and a non-null filter (Condition, SearchInputTextValue: ""). Do not send filter: null. Do not use searchType=Submitted for user behavior search.

  • 404 Not Found — Wrong path ID. Use phishingCampaignResourceId + instanceGroup for summary and {searchType}/search; use the user’s resourceId for search-email-* endpoints.

Related: Quickstart →. Reseller: View customer's campaign list and report →. Endpoint details: Endpoints → PhishingCampaign, PhishingCampaignJobReport.

Last updated