Kenso

Client approvals

Items your clients approve before they go out.

Workspace and credits4 endpointsKen-Version: 2026-11-02AuthenticationWorkspacesErrors

Return the workspace's external approval settings

GET/v1/client-approvals/settingsclient-approvals.get-settings

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

Try it on developer.ken.so

Rules per kind (require or auto), reminder emails, the reminder time zone, the portal URL, when the link was last rotated, the effective "External approval links" switch of the white-label master, and the pending count. The first read creates the settings and the portal link. Requires the workspace_settings feature, because the portal URL lets its holder approve.

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).

Response 200

data is a ClientApprovalSettingsModel.

Field
Type
Description
rules
ClientApprovalRulesModel
Per-kind rule: require or auto.
reminderEmails
array of string
timeZone
string
portalUrl
string
portalTokenRotatedAt
string (date-time)
approvalLinksEnabled
boolean
pendingCount
integer (int32)
Request
curl -X GET "https://api.ken.so/v1/client-approvals/settings" \
  -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": {
    "rules": {
      "copy": "string",
      "leadList": "string",
      "reply": "string",
      "order": "string"
    },
    "reminderEmails": [
      "[email protected]"
    ],
    "timeZone": "string",
    "portalUrl": "https://example.com",
    "portalTokenRotatedAt": "2026-09-23T15:02:11Z",
    "approvalLinksEnabled": true,
    "pendingCount": 1
  }
}

List external approval items, newest first

GET/v1/client-approvals/itemsclient-approvals.list-items

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

Try it on developer.ken.so

Filters: status (pending, approved, changes_requested, superseded, cancelled), kind (copy, lead_list, reply, order), campaignId. limit 1-200, default 50. Requires workspace membership. Lists only the kinds the caller's pages cover, each at view: replies need Inbox, copy and lead lists Campaigns, orders Delivery. A kind the caller cannot read lists nothing.

Parameters

Name
In
Type
Required
Description
Status
In: query
string
optional
Kind
In: query
string
optional
CampaignId
In: query
integer (int64)
optional
Limit
In: query
integer (int32)
optional
Cursor
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 ClientApprovalItemModel. Each item has these fields. The response also carries pagination.

Field
Type
Description
id
integer (int64)
kind
string
status
string
title
string
campaignId
integer (int64)
campaignName
string
subjectId
integer (int64)
subjectKey
string
fingerprint
string
pausedCampaign
boolean
createdByUserId
integer (int64)
createdAt
string (date-time)
decidedAt
string (date-time)
decidedByName
string
decisionComment
string
Request
curl -X GET "https://api.ken.so/v1/client-approvals/items" \
  -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",
      "status": "string",
      "title": "string",
      "campaignId": 812,
      "campaignName": "string",
      "subjectId": 812,
      "subjectKey": "string",
      "fingerprint": "string",
      "pausedCampaign": true,
      "createdByUserId": 812,
      "createdAt": "2026-09-23T15:02:11Z",
      "decidedAt": "2026-09-23T15:02:11Z",
      "decidedByName": "string",
      "decisionComment": "string"
    }
  ],
  "pagination": {
    "nextCursor": "eyJpZCI6ODE1fQ",
    "hasMore": true,
    "total": 1,
    "isTotalCapped": true
  }
}

Return one external approval item with its snapshot, comments and log

GET/v1/client-approvals/items/{itemId}client-approvals.get-item

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

Try it on developer.ken.so

snapshot is what the client reviews, frozen when the item was created (lead removals update it), without a reply's internal send block. A missing or cross-workspace id is not_found, and so is an item the caller's pages do not cover (replies need Inbox, copy and lead lists Campaigns, orders Delivery, share items Share, each at view). Requires workspace membership.

Parameters

Name
In
Type
Required
Description
itemId
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 ClientApprovalItemDetailModel.

Field
Type
Description
id
integer (int64)
kind
string
status
string
title
string
campaignId
integer (int64)
campaignName
string
subjectId
integer (int64)
subjectKey
string
fingerprint
string
pausedCampaign
boolean
createdByUserId
integer (int64)
createdAt
string (date-time)
decidedAt
string (date-time)
decidedByName
string
decisionComment
string
snapshot
object
comments
array of ClientApprovalCommentModel
events
array of ClientApprovalEventModel
Request
curl -X GET "https://api.ken.so/v1/client-approvals/items/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,
    "kind": "string",
    "status": "string",
    "title": "string",
    "campaignId": 812,
    "campaignName": "string",
    "subjectId": 812,
    "subjectKey": "string",
    "fingerprint": "string",
    "pausedCampaign": true,
    "createdByUserId": 812,
    "createdAt": "2026-09-23T15:02:11Z",
    "decidedAt": "2026-09-23T15:02:11Z",
    "decidedByName": "string",
    "decisionComment": "string",
    "snapshot": null,
    "comments": [
      {
        "id": 812,
        "anchor": "string",
        "body": "string",
        "authorName": "string",
        "createdAt": "2026-09-23T15:02:11Z"
      }
    ],
    "events": [
      {
        "id": 812,
        "itemId": 812,
        "eventType": "string",
        "actorKind": "string",
        "actorName": "string",
        "actorUserId": 812,
        "data": null,
        "createdAt": "2026-09-23T15:02:11Z"
      }
    ]
  }
}

List the approval log, newest first

GET/v1/client-approvals/eventsclient-approvals.list-events

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

Try it on developer.ken.so

Every item created, decision, comment, lead removal or restore, reminder, link rotation, rules change, campaign pause or resume and submitted Classic review. itemId filters to one item. before is an ISO-8601 upper bound (exclusive). limit 1-200, default 50. Requires workspace membership. Leaves out the events of items the caller's pages do not cover, as the item list does, share link events without the Share page and classic reviews without Campaigns.

Parameters

Name
In
Type
Required
Description
ItemId
In: query
integer (int64)
optional
Before
In: query
string (date-time)
optional
Limit
In: query
integer (int32)
optional
Cursor
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 ClientApprovalEventModel. Each item has these fields. The response also carries pagination.

Field
Type
Description
id
integer (int64)
itemId
integer (int64)
eventType
string
actorKind
string
actorName
string
actorUserId
integer (int64)
data
object
createdAt
string (date-time)
Request
curl -X GET "https://api.ken.so/v1/client-approvals/events" \
  -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,
      "itemId": 812,
      "eventType": "string",
      "actorKind": "string",
      "actorName": "string",
      "actorUserId": 812,
      "data": null,
      "createdAt": "2026-09-23T15:02:11Z"
    }
  ],
  "pagination": {
    "nextCursor": "eyJpZCI6ODE1fQ",
    "hasMore": true,
    "total": 1,
    "isTotalCapped": true
  }
}