Webhook endpoints
Endpoints Kenso posts events to: register them, read their signing secret, send a test and resend failed deliveries.
List webhook endpoints in the current workspace
/v1/webhook-endpointswebhook-endpoints.listEach endpoint's health, lastDelivery and failedAttempts come from its latest 10 attempts.
Parameters
400 workspace_required).Response 200
data is a list of WebhookEndpointModel. Each item has these fields. The response also carries pagination.
zapier, make or n8n when the endpoint belongs to that app; null otherwise.active, failing (the newest attempt failed) or disabled. Omitted, with lastDelivery and failedAttempts, when the delivery log could not be read.reply.classified labels): the endpoint receives only events whose reply has one of them. Empty: every event. A filtered endpoint never receives an event without a reply classification. With Ken.Scraper.API.Canonical.WebhookEndpointModel.CampaignIds, both must match.<type>.batch deliveries of up to 100 events ({eventType, eventId, timestamp, clientId, count, events}), never one by one.curl -X GET "https://api.ken.so/v1/webhook-endpoints" \ -H "Authorization: Bearer $KEN_API_KEY" \ -H "Ken-Version: 2026-11-02" \ -H "X-Ken-Workspace-Id: $KEN_WORKSPACE_ID"
{
"success": true,
"data": [
{
"id": "ep_2bKq8yZ0aB3cD4eF5gH6iJ7kL8m",
"url": "https://hooks.example.com/kenso/replies",
"events": [
"reply.classified"
],
"description": "Interested replies into our CRM",
"isDisabled": false,
"createdAt": "2026-09-23T15:02:11Z",
"health": "active",
"lastDelivery": {
"occurredAt": "2026-10-13T16:22:41Z",
"status": "success",
"responseStatusCode": 200,
"eventType": "reply.classified"
},
"failedAttempts": 0,
"campaignIds": [
4821
],
"classifications": [
"interested"
],
"isBatched": false
}
],
"pagination": {
"nextCursor": "eyJpZCI6ODE1fQ",
"hasMore": true,
"total": 1,
"isTotalCapped": true
}
}Register a webhook endpoint
/v1/webhook-endpointswebhook-endpoints.createRequires the integrations permission (admins by default). url must be https outside Development. events is a non-empty set of supported event types. app (zapier, make or n8n) tags the endpoint; omitted, it is taken from the URL host. campaignIds (workspace campaigns; another workspace's id is not_found) and classifications (snake_case labels) filter deliveries; both together must both match. A filter holds at most 10 campaigns, 10 classifications, or campaigns times classifications up to 10. isBatched delivers the high-volume types as batches; it needs an events list and is refused while batching is off.
Parameters
400 workspace_required).Request body
application/json, optional.
zapier, make or n8n. Omitted: taken from the URL host when it is a known catch-hook host.reply.classified). Omitted or empty: every one.Response 201
data is a WebhookEndpointModel.
zapier, make or n8n when the endpoint belongs to that app; null otherwise.active, failing (the newest attempt failed) or disabled. Omitted, with lastDelivery and failedAttempts, when the delivery log could not be read.reply.classified labels): the endpoint receives only events whose reply has one of them. Empty: every event. A filtered endpoint never receives an event without a reply classification. With Ken.Scraper.API.Canonical.WebhookEndpointModel.CampaignIds, both must match.<type>.batch deliveries of up to 100 events ({eventType, eventId, timestamp, clientId, count, events}), never one by one.curl -X POST "https://api.ken.so/v1/webhook-endpoints" \
-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 '{
"url": "https://hooks.example.com/kenso/replies",
"events": [
"reply.classified"
],
"description": "Interested replies into our CRM",
"campaignIds": [
4821
],
"classifications": [
"interested"
],
"isBatched": false
}'{
"success": true,
"data": {
"id": "ep_2bKq8yZ0aB3cD4eF5gH6iJ7kL8m",
"url": "https://hooks.example.com/kenso/replies",
"events": [
"reply.classified"
],
"description": "Interested replies into our CRM",
"isDisabled": false,
"createdAt": "2026-09-23T15:02:11Z",
"health": "active",
"lastDelivery": {
"occurredAt": "2026-10-13T16:22:41Z",
"status": "success",
"responseStatusCode": 200,
"eventType": "reply.classified"
},
"failedAttempts": 0,
"campaignIds": [
4821
],
"classifications": [
"interested"
],
"isBatched": false
}
}Get one webhook endpoint
/v1/webhook-endpoints/{webhookEndpointId}webhook-endpoints.gethealth, lastDelivery and failedAttempts come from the endpoint's latest 10 attempts.
Parameters
400 workspace_required).Response 200
data is a WebhookEndpointModel.
zapier, make or n8n when the endpoint belongs to that app; null otherwise.active, failing (the newest attempt failed) or disabled. Omitted, with lastDelivery and failedAttempts, when the delivery log could not be read.reply.classified labels): the endpoint receives only events whose reply has one of them. Empty: every event. A filtered endpoint never receives an event without a reply classification. With Ken.Scraper.API.Canonical.WebhookEndpointModel.CampaignIds, both must match.<type>.batch deliveries of up to 100 events ({eventType, eventId, timestamp, clientId, count, events}), never one by one.curl -X GET "https://api.ken.so/v1/webhook-endpoints/string" \ -H "Authorization: Bearer $KEN_API_KEY" \ -H "Ken-Version: 2026-11-02" \ -H "X-Ken-Workspace-Id: $KEN_WORKSPACE_ID"
{
"success": true,
"data": {
"id": "ep_2bKq8yZ0aB3cD4eF5gH6iJ7kL8m",
"url": "https://hooks.example.com/kenso/replies",
"events": [
"reply.classified"
],
"description": "Interested replies into our CRM",
"isDisabled": false,
"createdAt": "2026-09-23T15:02:11Z",
"health": "active",
"lastDelivery": {
"occurredAt": "2026-10-13T16:22:41Z",
"status": "success",
"responseStatusCode": 200,
"eventType": "reply.classified"
},
"failedAttempts": 0,
"campaignIds": [
4821
],
"classifications": [
"interested"
],
"isBatched": false
}
}Update a webhook endpoint
/v1/webhook-endpoints/{webhookEndpointId}webhook-endpoints.updateRequires the integrations permission (admins by default). Omitted fields stay unchanged. isDisabled pauses or resumes delivery. app sets the app tag; an empty string clears it. campaignIds and classifications replace that filter (empty clears it); the one omitted keeps its value. isBatched turns batch delivery on or off.
Parameters
400 workspace_required).Request body
application/json, optional.
zapier, make or n8n. Omitted: unchanged. An empty string clears the tag.Response 200
data is a WebhookEndpointModel.
zapier, make or n8n when the endpoint belongs to that app; null otherwise.active, failing (the newest attempt failed) or disabled. Omitted, with lastDelivery and failedAttempts, when the delivery log could not be read.reply.classified labels): the endpoint receives only events whose reply has one of them. Empty: every event. A filtered endpoint never receives an event without a reply classification. With Ken.Scraper.API.Canonical.WebhookEndpointModel.CampaignIds, both must match.<type>.batch deliveries of up to 100 events ({eventType, eventId, timestamp, clientId, count, events}), never one by one.curl -X PATCH "https://api.ken.so/v1/webhook-endpoints/string" \
-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 '{
"url": "https://example.com",
"events": [
"string"
],
"description": "string",
"isDisabled": true,
"app": "string",
"campaignIds": [
812
],
"classifications": [
"string"
],
"isBatched": true
}'{
"success": true,
"data": {
"id": "ep_2bKq8yZ0aB3cD4eF5gH6iJ7kL8m",
"url": "https://hooks.example.com/kenso/replies",
"events": [
"reply.classified"
],
"description": "Interested replies into our CRM",
"isDisabled": false,
"createdAt": "2026-09-23T15:02:11Z",
"health": "active",
"lastDelivery": {
"occurredAt": "2026-10-13T16:22:41Z",
"status": "success",
"responseStatusCode": 200,
"eventType": "reply.classified"
},
"failedAttempts": 0,
"campaignIds": [
4821
],
"classifications": [
"interested"
],
"isBatched": false
}
}Delete a webhook endpoint
/v1/webhook-endpoints/{webhookEndpointId}webhook-endpoints.deleteParameters
400 workspace_required).Response 204
curl -X DELETE "https://api.ken.so/v1/webhook-endpoints/string" \ -H "Authorization: Bearer $KEN_API_KEY" \ -H "Ken-Version: 2026-11-02" \ -H "X-Ken-Workspace-Id: $KEN_WORKSPACE_ID"
HTTP/1.1 204 No Content
Get the endpoint signing secret
/v1/webhook-endpoints/{webhookEndpointId}/signing-secretwebhook-endpoints.get-signing-secretRequires the integrations permission (admins by default). Treat secret as a credential.
Parameters
400 workspace_required).Response 200
data is a WebhookSigningSecretModel.
curl -X GET "https://api.ken.so/v1/webhook-endpoints/string/signing-secret" \ -H "Authorization: Bearer $KEN_API_KEY" \ -H "Ken-Version: 2026-11-02" \ -H "X-Ken-Workspace-Id: $KEN_WORKSPACE_ID"
{
"success": true,
"data": {
"secret": "string"
}
}Resend failed deliveries since a time
/v1/webhook-endpoints/{webhookEndpointId}/recoverwebhook-endpoints.recoverResends every delivery to this endpoint that failed in the window and never succeeded. since is required and at most 14 days ago; until defaults to now. Svix runs the resends in the background, so the response is 202 with the window. Counts as 10 resends against the workspace's resend limit.
Parameters
400 workspace_required).Request body
application/json, optional.
Response 202
data is a WebhookRecoverModel.
curl -X POST "https://api.ken.so/v1/webhook-endpoints/string/recover" \
-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 '{
"since": "2026-09-23T15:02:11Z",
"until": "2026-09-23T15:02:11Z"
}'{
"success": true,
"data": {
"since": "2026-09-23T15:02:11Z",
"until": "2026-09-23T15:02:11Z"
}
}Send a test event to one endpoint
/v1/webhook-endpoints/{webhookEndpointId}/testwebhook-endpoints.testRequires the integrations feature. Sends the example payload of eventType to this endpoint only and waits up to 5 seconds for the first attempt. eventType is any event type available to the workspace, whether or not the endpoint receives it or filters by campaign or classification; it defaults to the first event the endpoint receives (reply.received when it receives every event). A batched endpoint gets a high-volume type's <type>.batch example, and eventType in the response says so. A type the workspace cannot use is validation_failed. A disabled endpoint is invalid_state.
Parameters
400 workspace_required).Request body
application/json, optional.
Response 200
data is a WebhookEndpointTestModel.
msg_) of the test delivery.curl -X POST "https://api.ken.so/v1/webhook-endpoints/string/test" \
-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 '{
"eventType": "string"
}'{
"success": true,
"data": {
"messageId": "msg_ZW1haWw6NDAyMjg0LjJAZXhhbXBsZS5jb20",
"eventType": "string",
"attempt": {
"status": "string",
"responseStatusCode": 1,
"occurredAt": "2026-09-23T15:02:11Z"
}
}
}