Kenso

Triggers

Rules that act when a signal happens: create, preview, edit, archive and read their stats.

Webhooks and events9 endpointsKen-Version: 2026-11-02AuthenticationWorkspacesErrors

Runs the definition's parameters against live data without saving anything: nothing fires and nothing is charged. signalType is fundraising, open_roles or company_headcount_growth; any other signal returns 400 validation_failed with details[0].codepreview_not_supported. parameters is a JSON object with the same keys a trigger stores. limit 1 to 25 companies (default 25), cursor pagination through pagination.nextCursor. Every page has companies (sample rows), total (the source's count across pages, null for open_roles), steps (name, count and description of each gate step on this page, in order, ending with max_contacts_per_company, the most people the page can import) and estimatedCredits (isEstimate true, leads, credits, totalMillicredits, lines, and basis, which says how it was computed: those people at the leads rate of credit-estimates.create). Free: never uses the export allowance.

Parameters

Name
In
Type
Required
Description
Ken-Version
In: header
string, one of: 2026-11-02, 1.1
required
The API version: a dated version (YYYY-MM-DD), or 1.1, another name for the first dated version. Without it the request uses your API key's pinned version; an unpinned key reaches the legacy shape of the same path. 1.0 selects the legacy shape explicitly.
X-Ken-Workspace-Id
In: header
integer (int64)
optional
Workspace to act in. Required when your credential can reach more than one workspace (otherwise 400 workspace_required).

Request body

application/json, optional.

Field
Type
Required
Description
signalType
string
optional
The signal to preview, snake_case: fundraising, open_roles or company_headcount_growth.
parameters
object
optional
The definition parameters as a JSON object, the same keys a trigger stores.
limit
integer (int32)
optional
Companies per page, 1 to 25. Default 25.
cursor
string
optional
Opaque cursor from pagination.nextCursor of the previous page.

Response 200

data is a object.

Request
curl -X POST "https://api.ken.so/v1/triggers/preview" \
  -H "Authorization: Bearer $KEN_API_KEY" \
  -H "Ken-Version: 2026-11-02" \
  -H "X-Ken-Workspace-Id: $KEN_WORKSPACE_ID" \
  -H "Content-Type: application/json" \
  -d '{
  "signalType": "string",
  "parameters": null,
  "limit": 1,
  "cursor": "eyJpZCI6ODE1fQ"
}'
Response 200
{
  "success": true,
  "data": null
}

Test-fire a saved trigger against a sample signal

POST/v1/triggers/{triggerId}/test-firetriggers.test-fire

Try it on developer.ken.so

Evaluates one sample signal of the trigger's own type, the way an arriving signal is evaluated, and says whether it would fire and why. Read-only: no signal is queued, no cooldown is taken, no firing is written, no window counter changes, and nothing is sent or charged. Recent signals are not replayed; the sample is the only input. contactId is required, campaignId feeds the audience filter, payload is the signal's JSON object (for example clickedUrl for link_clicked, classification for reply_received), occurredAt defaults to now. checks run in pipeline order (status, audience_filter, parameters, cooldown), every one runs, and rejectedBy names the first that failed; status fails for a paused or archived trigger and for one whose campaign is deleted. A firing can still be suppressed later (do not contact, blocklist, frequency cap). A contact or campaign outside the workspace is 400; signals that only a scheduled sweep produces return 400 with details[0].codetest_fire_not_supported.

Parameters

Name
In
Type
Required
Description
triggerId
In: path
integer (int64)
required
Ken-Version
In: header
string, one of: 2026-11-02, 1.1
required
The API version: a dated version (YYYY-MM-DD), or 1.1, another name for the first dated version. Without it the request uses your API key's pinned version; an unpinned key reaches the legacy shape of the same path. 1.0 selects the legacy shape explicitly.
X-Ken-Workspace-Id
In: header
integer (int64)
optional
Workspace to act in. Required when your credential can reach more than one workspace (otherwise 400 workspace_required).

Request body

application/json, optional.

Field
Type
Required
Description
contactId
integer (int64)
optional
The contact the sample signal is about. Required; must be in the workspace.
campaignId
integer (int64)
optional
The campaign the sample came from, for the trigger's audience filter. Optional; must be in the workspace.
payload
object
optional
The signal payload, a JSON object of at most 16 KB, e.g. {"clickedUrl":"https://..."}.
occurredAt
string (date-time)
optional
When the sample happened (ISO 8601, within the last 365 days). Omitted means now.

Response 200

data is a TriggerTestFireModel.

Field
Type
Description
object
string
Always trigger_test_fire.
triggerId
integer (int64)
signalType
string
status
string
The trigger's status: active, paused or archived.
shouldFire
boolean
True only when every check passed: the trigger would create a firing for this sample now.
rejectedBy
string
The first check that failed, or null.
checks
array of TriggerTestFireCheckModel
In pipeline order: status, audience_filter, parameters, cooldown. Every check runs.
evidence
object
What the firing would carry as evidence, when the sample met the parameters; else null.
scheduledFor
string (date-time)
When the evaluator delays the firing, the time it would be scheduled for; else null.
Request
curl -X POST "https://api.ken.so/v1/triggers/812/test-fire" \
  -H "Authorization: Bearer $KEN_API_KEY" \
  -H "Ken-Version: 2026-11-02" \
  -H "X-Ken-Workspace-Id: $KEN_WORKSPACE_ID" \
  -H "Content-Type: application/json" \
  -d '{
  "contactId": 812,
  "campaignId": 812,
  "payload": null,
  "occurredAt": "2026-09-23T15:02:11Z"
}'
Response 200
{
  "success": true,
  "data": {
    "object": "string",
    "triggerId": 812,
    "signalType": "string",
    "status": "string",
    "shouldFire": true,
    "rejectedBy": "string",
    "checks": [
      {
        "name": "string",
        "passed": true,
        "message": "string"
      }
    ],
    "evidence": null,
    "scheduledFor": "2026-09-23T15:02:11Z"
  }
}

Parameters

Name
In
Type
Required
Description
Limit
In: query
integer (int32)
optional
Cursor
In: query
string
optional
CampaignId
In: query
integer (int64)
optional
Status
In: query
string
optional
Ken-Version
In: header
string, one of: 2026-11-02, 1.1
required
The API version: a dated version (YYYY-MM-DD), or 1.1, another name for the first dated version. Without it the request uses your API key's pinned version; an unpinned key reaches the legacy shape of the same path. 1.0 selects the legacy shape explicitly.
X-Ken-Workspace-Id
In: header
integer (int64)
optional
Workspace to act in. Required when your credential can reach more than one workspace (otherwise 400 workspace_required).

Response 200

data is a list of TriggerModel. Each item has these fields. The response also carries pagination.

Field
Type
Description
id
integer (int64)
campaignId
integer (int64)
stagingCampaignId
integer (int64)
signalType
string
tier
string
parameters
string
audienceFilter
string
cooldownMinutes
integer (int32)
maxAgeMinutes
integer (int32)
priority
integer (int32)
stopSourceSequence
boolean
status
string
createdAt
string (date-time)
updatedAt
string (date-time)
Request
curl -X GET "https://api.ken.so/v1/triggers" \
  -H "Authorization: Bearer $KEN_API_KEY" \
  -H "Ken-Version: 2026-11-02" \
  -H "X-Ken-Workspace-Id: $KEN_WORKSPACE_ID"
Response 200
{
  "success": true,
  "data": [
    {
      "id": 812,
      "campaignId": 812,
      "stagingCampaignId": 812,
      "signalType": "string",
      "tier": "string",
      "parameters": "string",
      "audienceFilter": "string",
      "cooldownMinutes": 1,
      "maxAgeMinutes": 1,
      "priority": 1,
      "stopSourceSequence": true,
      "status": "string",
      "createdAt": "2026-09-23T15:02:11Z",
      "updatedAt": "2026-09-23T15:02:11Z"
    }
  ],
  "pagination": {
    "nextCursor": "eyJpZCI6ODE1fQ",
    "hasMore": true,
    "total": 1,
    "isTotalCapped": true
  }
}

Requires Campaigns edit access (owners, admins and editors by default). The campaign must belong to the workspace and be in trigger mode, or be a Batch campaign when switchCampaignToTrigger is true (the switch and the create are one transaction); the LinkedIn signal types (linkedin_post_engagement, linkedin_profile_view) take a regular campaign instead and need the workspace's linkedin_signals flag.

Parameters

Name
In
Type
Required
Description
Ken-Version
In: header
string, one of: 2026-11-02, 1.1
required
The API version: a dated version (YYYY-MM-DD), or 1.1, another name for the first dated version. Without it the request uses your API key's pinned version; an unpinned key reaches the legacy shape of the same path. 1.0 selects the legacy shape explicitly.
X-Ken-Workspace-Id
In: header
integer (int64)
optional
Workspace to act in. Required when your credential can reach more than one workspace (otherwise 400 workspace_required).

Request body

application/json, optional.

Field
Type
Required
Description
campaignId
integer (int64)
optional
signalType
string
optional
tier
string
optional
parameters
string
optional
audienceFilter
string
optional
cooldownMinutes
integer (int32)
optional
maxAgeMinutes
integer (int32)
optional
priority
integer (int32)
optional
stopSourceSequence
boolean
optional
switchCampaignToTrigger
boolean
optional
Opt-in, default false. A Batch campaign is switched to Trigger mode in the same transaction as the definition insert, so a failed create leaves it in Batch. Ignored for LinkedIn signals.

Response 201

data is a TriggerModel.

Field
Type
Description
id
integer (int64)
campaignId
integer (int64)
stagingCampaignId
integer (int64)
signalType
string
tier
string
parameters
string
audienceFilter
string
cooldownMinutes
integer (int32)
maxAgeMinutes
integer (int32)
priority
integer (int32)
stopSourceSequence
boolean
status
string
createdAt
string (date-time)
updatedAt
string (date-time)
Request
curl -X POST "https://api.ken.so/v1/triggers" \
  -H "Authorization: Bearer $KEN_API_KEY" \
  -H "Ken-Version: 2026-11-02" \
  -H "X-Ken-Workspace-Id: $KEN_WORKSPACE_ID" \
  -H "Content-Type: application/json" \
  -d '{
  "campaignId": 812,
  "signalType": "string",
  "tier": "string",
  "parameters": "string",
  "audienceFilter": "string",
  "cooldownMinutes": 1,
  "maxAgeMinutes": 1,
  "priority": 1,
  "stopSourceSequence": true,
  "switchCampaignToTrigger": true
}'
Response 201
{
  "success": true,
  "data": {
    "id": 812,
    "campaignId": 812,
    "stagingCampaignId": 812,
    "signalType": "string",
    "tier": "string",
    "parameters": "string",
    "audienceFilter": "string",
    "cooldownMinutes": 1,
    "maxAgeMinutes": 1,
    "priority": 1,
    "stopSourceSequence": true,
    "status": "string",
    "createdAt": "2026-09-23T15:02:11Z",
    "updatedAt": "2026-09-23T15:02:11Z"
  }
}

Get one trigger definition

GET/v1/triggers/{triggerId}triggers.get

Try it on developer.ken.so

Parameters

Name
In
Type
Required
Description
triggerId
In: path
integer (int64)
required
Ken-Version
In: header
string, one of: 2026-11-02, 1.1
required
The API version: a dated version (YYYY-MM-DD), or 1.1, another name for the first dated version. Without it the request uses your API key's pinned version; an unpinned key reaches the legacy shape of the same path. 1.0 selects the legacy shape explicitly.
X-Ken-Workspace-Id
In: header
integer (int64)
optional
Workspace to act in. Required when your credential can reach more than one workspace (otherwise 400 workspace_required).

Response 200

data is a TriggerModel.

Field
Type
Description
id
integer (int64)
campaignId
integer (int64)
stagingCampaignId
integer (int64)
signalType
string
tier
string
parameters
string
audienceFilter
string
cooldownMinutes
integer (int32)
maxAgeMinutes
integer (int32)
priority
integer (int32)
stopSourceSequence
boolean
status
string
createdAt
string (date-time)
updatedAt
string (date-time)
Request
curl -X GET "https://api.ken.so/v1/triggers/812" \
  -H "Authorization: Bearer $KEN_API_KEY" \
  -H "Ken-Version: 2026-11-02" \
  -H "X-Ken-Workspace-Id: $KEN_WORKSPACE_ID"
Response 200
{
  "success": true,
  "data": {
    "id": 812,
    "campaignId": 812,
    "stagingCampaignId": 812,
    "signalType": "string",
    "tier": "string",
    "parameters": "string",
    "audienceFilter": "string",
    "cooldownMinutes": 1,
    "maxAgeMinutes": 1,
    "priority": 1,
    "stopSourceSequence": true,
    "status": "string",
    "createdAt": "2026-09-23T15:02:11Z",
    "updatedAt": "2026-09-23T15:02:11Z"
  }
}

Update a trigger definition

PATCH/v1/triggers/{triggerId}triggers.update

Try it on developer.ken.so

Requires Campaigns edit access (owners, admins and editors by default). Omitted fields stay unchanged. audienceFilter: null clears the filter.

Parameters

Name
In
Type
Required
Description
triggerId
In: path
integer (int64)
required
Ken-Version
In: header
string, one of: 2026-11-02, 1.1
required
The API version: a dated version (YYYY-MM-DD), or 1.1, another name for the first dated version. Without it the request uses your API key's pinned version; an unpinned key reaches the legacy shape of the same path. 1.0 selects the legacy shape explicitly.
X-Ken-Workspace-Id
In: header
integer (int64)
optional
Workspace to act in. Required when your credential can reach more than one workspace (otherwise 400 workspace_required).

Request body

application/json, optional: object.

Response 200

data is a TriggerModel.

Field
Type
Description
id
integer (int64)
campaignId
integer (int64)
stagingCampaignId
integer (int64)
signalType
string
tier
string
parameters
string
audienceFilter
string
cooldownMinutes
integer (int32)
maxAgeMinutes
integer (int32)
priority
integer (int32)
stopSourceSequence
boolean
status
string
createdAt
string (date-time)
updatedAt
string (date-time)
Request
curl -X PATCH "https://api.ken.so/v1/triggers/812" \
  -H "Authorization: Bearer $KEN_API_KEY" \
  -H "Ken-Version: 2026-11-02" \
  -H "X-Ken-Workspace-Id: $KEN_WORKSPACE_ID" \
  -H "Content-Type: application/json" \
  -d '{}'
Response 200
{
  "success": true,
  "data": {
    "id": 812,
    "campaignId": 812,
    "stagingCampaignId": 812,
    "signalType": "string",
    "tier": "string",
    "parameters": "string",
    "audienceFilter": "string",
    "cooldownMinutes": 1,
    "maxAgeMinutes": 1,
    "priority": 1,
    "stopSourceSequence": true,
    "status": "string",
    "createdAt": "2026-09-23T15:02:11Z",
    "updatedAt": "2026-09-23T15:02:11Z"
  }
}

Archive a trigger definition

DELETE/v1/triggers/{triggerId}triggers.delete

Try it on developer.ken.so

Parameters

Name
In
Type
Required
Description
triggerId
In: path
integer (int64)
required
Ken-Version
In: header
string, one of: 2026-11-02, 1.1
required
The API version: a dated version (YYYY-MM-DD), or 1.1, another name for the first dated version. Without it the request uses your API key's pinned version; an unpinned key reaches the legacy shape of the same path. 1.0 selects the legacy shape explicitly.
X-Ken-Workspace-Id
In: header
integer (int64)
optional
Workspace to act in. Required when your credential can reach more than one workspace (otherwise 400 workspace_required).

Response 204

Request
curl -X DELETE "https://api.ken.so/v1/triggers/812" \
  -H "Authorization: Bearer $KEN_API_KEY" \
  -H "Ken-Version: 2026-11-02" \
  -H "X-Ken-Workspace-Id: $KEN_WORKSPACE_ID"
Response 204
HTTP/1.1 204 No Content

Firing stats for one trigger

GET/v1/triggers/{triggerId}/statstriggers.get-stats

Try it on developer.ken.so

Parameters

Name
In
Type
Required
Description
triggerId
In: path
integer (int64)
required
Days
In: query
integer (int32)
optional
Ken-Version
In: header
string, one of: 2026-11-02, 1.1
required
The API version: a dated version (YYYY-MM-DD), or 1.1, another name for the first dated version. Without it the request uses your API key's pinned version; an unpinned key reaches the legacy shape of the same path. 1.0 selects the legacy shape explicitly.
X-Ken-Workspace-Id
In: header
integer (int64)
optional
Workspace to act in. Required when your credential can reach more than one workspace (otherwise 400 workspace_required).

Response 200

data is a TriggerStatsModel.

Field
Type
Description
fired
integer (int32)
exported
integer (int32)
suppressed
integer (int32)
suppressionBreakdown
map of integer (int32)
lastFiredAt
string (date-time)
Request
curl -X GET "https://api.ken.so/v1/triggers/812/stats" \
  -H "Authorization: Bearer $KEN_API_KEY" \
  -H "Ken-Version: 2026-11-02" \
  -H "X-Ken-Workspace-Id: $KEN_WORKSPACE_ID"
Response 200
{
  "success": true,
  "data": {
    "fired": 1,
    "exported": 1,
    "suppressed": 1,
    "suppressionBreakdown": {
      "key": 1
    },
    "lastFiredAt": "2026-09-23T15:02:11Z"
  }
}

LinkedIn engagements a LinkedIn signal trigger stored

GET/v1/triggers/{triggerId}/linkedin-engagementstriggers.list-linkedin-engagements

Needs the linkedin_signals feature on your workspace. Until it is on, calls answer 404.

Try it on developer.ken.so

Newest first. status filters to new, imported, offered or skipped. Each item names the engager (actor), the post and comment when there is one, and for imported the person's contact in the campaign; skipReason says why an item was skipped. Items also carry the reaction type, the comment and parent comment ids, the post text, Jev's intent and reason, and ownPost. A trigger of another signal type returns an empty list. 404 while the workspace's linkedin_signals flag is off.

Parameters

Name
In
Type
Required
Description
triggerId
In: path
integer (int64)
required
Limit
In: query
integer (int32)
optional
Page size, 1 to 200 (default 50).
Cursor
In: query
string
optional
Opaque cursor from pagination.nextCursor.
Status
In: query
string
optional
new, imported, offered or skipped.
Ken-Version
In: header
string, one of: 2026-11-02, 1.1
required
The API version: a dated version (YYYY-MM-DD), or 1.1, another name for the first dated version. Without it the request uses your API key's pinned version; an unpinned key reaches the legacy shape of the same path. 1.0 selects the legacy shape explicitly.
X-Ken-Workspace-Id
In: header
integer (int64)
optional
Workspace to act in. Required when your credential can reach more than one workspace (otherwise 400 workspace_required).

Response 200

data is a list of LinkedInEngagementModel. Each item has these fields. The response also carries pagination.

Field
Type
Description
id
integer (int64)
kind
string
post_reaction, post_comment, post_reply or profile_view.
postUrl
string
actor
LinkedInEngagementActorModel
commentText
string
reactionType
string
like, celebrate, support, love, insightful or funny; reactions only.
commentId
string
LinkedIn's id of the comment or reply.
parentCommentId
string
The comment a reply answers; set on post_reply only.
postText
string
The text of the post that was engaged with, cut at 2,000 characters.
intent
string
positive, requesting, question, neutral or negative: Jev's label of a comment or reply; null until classified and on reactions.
intentReason
string
Jev's one-line reason for the intent label.
ownPost
boolean
False when the post is a pasted third-party post (its author is not a seat or company page of the workspace).
occurredAt
string (date-time)
firstSeenAt
string (date-time)
status
string
new, imported, offered (a workflow run took it; no contact) or skipped.
skipReason
string
When skipped: own_seat, kind_filtered, reaction_type_filtered, keyword_mismatch, intent_filtered, or not_imported (the intake created no contact).
contactId
integer (int64)
Request
curl -X GET "https://api.ken.so/v1/triggers/812/linkedin-engagements" \
  -H "Authorization: Bearer $KEN_API_KEY" \
  -H "Ken-Version: 2026-11-02" \
  -H "X-Ken-Workspace-Id: $KEN_WORKSPACE_ID"
Response 200
{
  "success": true,
  "data": [
    {
      "id": 812,
      "kind": "string",
      "postUrl": "https://example.com",
      "actor": {
        "name": "string",
        "headline": "string",
        "profileUrl": "https://example.com"
      },
      "commentText": "string",
      "reactionType": "string",
      "commentId": "string",
      "parentCommentId": "string",
      "postText": "string",
      "intent": "string",
      "intentReason": "string",
      "ownPost": true,
      "occurredAt": "2026-09-23T15:02:11Z",
      "firstSeenAt": "2026-09-23T15:02:11Z",
      "status": "string",
      "skipReason": "string",
      "contactId": 812
    }
  ],
  "pagination": {
    "nextCursor": "eyJpZCI6ODE1fQ",
    "hasMore": true,
    "total": 1,
    "isTotalCapped": true
  }
}