kenso 0.1.8 → 0.1.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/kenso.js +1 -1
- package/dist/operations.json +1 -1
- package/docs/reference.md +456 -299
- package/package.json +2 -2
package/docs/reference.md
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
# Kenso CLI command reference
|
|
2
2
|
|
|
3
|
-
Generated from kenso 0.1.
|
|
3
|
+
Generated from kenso 0.1.10 (API contracts 3d429b7be4f5) by `scripts/build-reference.ts`. Do not edit it: `pnpm build` writes it again.
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
1364 commands. Beta commands work only on workspaces with their feature flag; `kenso describe` hides the ones yours cannot use. Every command also takes the global flags below. For the same data as JSON, run `kenso describe <resource> <action>`.
|
|
6
6
|
|
|
7
7
|
## Global flags
|
|
8
8
|
|
|
@@ -76,6 +76,7 @@ Exit codes: 0 ok, 1 error, 2 usage, 3 auth, 4 not found, 5 some rows failed, 6 r
|
|
|
76
76
|
- [bookings](#bookings) (5)
|
|
77
77
|
- [brand-kit](#brand-kit) (3)
|
|
78
78
|
- [brands](#brands) (1)
|
|
79
|
+
- [browser-runs](#browser-runs) (4)
|
|
79
80
|
- [bug-reports](#bug-reports) (1)
|
|
80
81
|
- [build-events](#build-events) (2)
|
|
81
82
|
- [build-files](#build-files) (6)
|
|
@@ -244,7 +245,7 @@ Exit codes: 0 ok, 1 error, 2 usage, 3 auth, 4 not found, 5 some rows failed, 6 r
|
|
|
244
245
|
- [meeting-results](#meeting-results) (7)
|
|
245
246
|
- [meeting-shares](#meeting-shares) (3)
|
|
246
247
|
- [meeting-types](#meeting-types) (6)
|
|
247
|
-
- [meetings](#meetings) (
|
|
248
|
+
- [meetings](#meetings) (26)
|
|
248
249
|
- [members](#members) (10)
|
|
249
250
|
- [microsoft-teams-admin-consent-sessions](#microsoft-teams-admin-consent-sessions) (1)
|
|
250
251
|
- [migration-connections](#migration-connections) (9)
|
|
@@ -489,7 +490,7 @@ kenso access-requests list --all
|
|
|
489
490
|
|
|
490
491
|
Add a domain to an account. Returns the account.
|
|
491
492
|
|
|
492
|
-
`domain`: a domain, website URL or work email (normalized to the registrable domain). `isPrimary` makes it the primary. A domain the account already has is a `200` no-op. One another account owns is `409 conflict` with `domain_taken` (and that `accountId`, unless account scope `own` hides that account). Requires
|
|
493
|
+
`domain`: a domain, website URL or work email (normalized to the registrable domain). `isPrimary` makes it the primary. A domain the account already has is a `200` no-op. One another account owns is `409 conflict` with `domain_taken` (and that `accountId`, unless account scope `own` hides that account). Requires Accounts edit.
|
|
493
494
|
|
|
494
495
|
- Beta: needs the `accounts` feature flag on the workspace.
|
|
495
496
|
- API: `POST /v1/accounts/{accountId}/domains`
|
|
@@ -515,7 +516,7 @@ kenso account-domains create --account-id <account-id> --data @body.json
|
|
|
515
516
|
|
|
516
517
|
Remove a domain from its account. Returns the account.
|
|
517
518
|
|
|
518
|
-
The account's last domain cannot go (`409 invalid_state`, `last_domain`). Removing the primary promotes the oldest remaining domain. Requires
|
|
519
|
+
The account's last domain cannot go (`409 invalid_state`, `last_domain`). Removing the primary promotes the oldest remaining domain. Requires Accounts edit.
|
|
519
520
|
|
|
520
521
|
- Beta: needs the `accounts` feature flag on the workspace.
|
|
521
522
|
- API: `DELETE /v1/account-domains/{accountDomainId}`
|
|
@@ -840,7 +841,7 @@ kenso account-tiers update --data @body.json
|
|
|
840
841
|
|
|
841
842
|
Save a new account view at the end of the calling member's strip.
|
|
842
843
|
|
|
843
|
-
Body: `name` (required, 1-80 characters after trim; names may repeat), `filters` (optional, the same `{ "field", "operator", "values" }` conditions as `accounts.search`; a condition with no values is dropped), `isActive` (optional; `true` makes the new view the active one and clears every view's draft). A member keeps at most 50 views, the four defaults included: the 51st is `409 conflict` with detail `view_limit`. Returns `201` with the view. Requires
|
|
844
|
+
Body: `name` (required, 1-80 characters after trim; names may repeat), `filters` (optional, the same `{ "field", "operator", "values" }` conditions as `accounts.search`; a condition with no values is dropped), `isActive` (optional; `true` makes the new view the active one and clears every view's draft). A member keeps at most 50 views, the four defaults included: the 51st is `409 conflict` with detail `view_limit`. Returns `201` with the view. Requires Accounts view.
|
|
844
845
|
|
|
845
846
|
- Beta: needs the `accounts` feature flag on the workspace.
|
|
846
847
|
- API: `POST /v1/account-views`
|
|
@@ -865,7 +866,7 @@ kenso account-views create --data @body.json
|
|
|
865
866
|
|
|
866
867
|
Delete one of the calling member's account views.
|
|
867
868
|
|
|
868
|
-
Soft delete; returns `204`. Deleting the active view makes the default view active with no draft. The default view cannot be deleted (`409 invalid_state`, detail `default_view`). Later views move up one position. Requires
|
|
869
|
+
Soft delete; returns `204`. Deleting the active view makes the default view active with no draft. The default view cannot be deleted (`409 invalid_state`, detail `default_view`). Later views move up one position. Requires Accounts view.
|
|
869
870
|
|
|
870
871
|
- Beta: needs the `accounts` feature flag on the workspace.
|
|
871
872
|
- API: `DELETE /v1/account-views/{accountViewId}`
|
|
@@ -885,7 +886,7 @@ kenso account-views delete --account-view-id <account-view-id>
|
|
|
885
886
|
|
|
886
887
|
Copy one of the calling member's account views.
|
|
887
888
|
|
|
888
|
-
Inserts `{name} copy` (a long name is cut so the copy fits in 80 characters) with the source's saved `filters` (not its draft) right after the source; later views move down one position. The copy becomes the active view, with every draft cleared, when the source was active. The default view cannot be duplicated (`409 invalid_state`, detail `default_view`); the 51st view is `409 conflict`, detail `view_limit`. Returns `201` with the copy. Requires
|
|
889
|
+
Inserts `{name} copy` (a long name is cut so the copy fits in 80 characters) with the source's saved `filters` (not its draft) right after the source; later views move down one position. The copy becomes the active view, with every draft cleared, when the source was active. The default view cannot be duplicated (`409 invalid_state`, detail `default_view`); the 51st view is `409 conflict`, detail `view_limit`. Returns `201` with the copy. Requires Accounts view.
|
|
889
890
|
|
|
890
891
|
- Beta: needs the `accounts` feature flag on the workspace.
|
|
891
892
|
- API: `POST /v1/account-views/{accountViewId}/duplicate`
|
|
@@ -905,7 +906,7 @@ kenso account-views duplicate --account-view-id <account-view-id>
|
|
|
905
906
|
|
|
906
907
|
List the calling member's saved account views.
|
|
907
908
|
|
|
908
|
-
Every view in strip order (`position`, 0-based), at most 50, in one page (`pagination.hasMore` is always false). Exactly one view is `isActive`; only that view can carry `draftFilters` (unsaved edits, omitted when there are none). `accountCount` counts live accounts that pass the view's saved `filters`, not the draft and no `q` (with account scope `own`, only accounts the caller owns); for the active tab, show `pagination.total` of your own `accounts.search` (`includeTotal: true`) instead. The first call creates the four default views. `timeZone` (optional, an IANA zone) is the zone the lastTouch, latestSignal and nextTouch day buckets count calendar days in, as on `accounts.search`; the member's app time zone wins over it. Requires
|
|
909
|
+
Every view in strip order (`position`, 0-based), at most 50, in one page (`pagination.hasMore` is always false). Exactly one view is `isActive`; only that view can carry `draftFilters` (unsaved edits, omitted when there are none). `accountCount` counts live accounts that pass the view's saved `filters`, not the draft and no `q` (with account scope `own`, only accounts the caller owns); for the active tab, show `pagination.total` of your own `accounts.search` (`includeTotal: true`) instead. The first call creates the four default views. `timeZone` (optional, an IANA zone) is the zone the lastTouch, latestSignal and nextTouch day buckets count calendar days in, as on `accounts.search`; the member's app time zone wins over it. Requires Accounts view.
|
|
909
910
|
|
|
910
911
|
- Beta: needs the `accounts` feature flag on the workspace.
|
|
911
912
|
- API: `GET /v1/account-views`
|
|
@@ -925,7 +926,7 @@ kenso account-views list
|
|
|
925
926
|
|
|
926
927
|
Update one of the calling member's account views. Absent fields stay unchanged.
|
|
927
928
|
|
|
928
|
-
<list type="bullet"> <item> `name`: 1-80 characters after trim. Cannot be null.</item> <item> `filters`: saves the view's conditions (null or `[]` = none) and clears its draft, unless `draftFilters` is in the same body ("Update view").</item> <item> `draftFilters`: unsaved conditions; null clears them ("Reset"). Only the view that is active after this request can hold a draft; a draft on any other view is `409 invalid_state` with detail `view_not_active`.</item> <item> `isActive`: only `true`, which makes this the active view and clears every other view's draft. `false` is `400`: activate another view instead.</item> </list> The default view (`isDefault`) cannot change `name` or `filters` (`409 invalid_state`, detail `default_view`); it can hold a draft ("Save as view" on All). Another member's or workspace's view is `404`. Requires
|
|
929
|
+
<list type="bullet"> <item> `name`: 1-80 characters after trim. Cannot be null.</item> <item> `filters`: saves the view's conditions (null or `[]` = none) and clears its draft, unless `draftFilters` is in the same body ("Update view").</item> <item> `draftFilters`: unsaved conditions; null clears them ("Reset"). Only the view that is active after this request can hold a draft; a draft on any other view is `409 invalid_state` with detail `view_not_active`.</item> <item> `isActive`: only `true`, which makes this the active view and clears every other view's draft. `false` is `400`: activate another view instead.</item> </list> The default view (`isDefault`) cannot change `name` or `filters` (`409 invalid_state`, detail `default_view`); it can hold a draft ("Save as view" on All). Another member's or workspace's view is `404`. Requires Accounts view.
|
|
929
930
|
|
|
930
931
|
- Beta: needs the `accounts` feature flag on the workspace.
|
|
931
932
|
- API: `PATCH /v1/account-views/{accountViewId}`
|
|
@@ -1000,7 +1001,7 @@ kenso accounts add-to-campaign --account-id <account-id> --data @body.json
|
|
|
1000
1001
|
|
|
1001
1002
|
Create up to 100 accounts in one call.
|
|
1002
1003
|
|
|
1003
|
-
`items` (1 to 100) are each a `POST /v1/accounts` body. Returns 200 with one result per item in request order: `created` (with the account and `research`: queued or waiting_credits), `domain_taken` (the `accountId` that already owns `domain`; counted in skipped), `invalid` (`field`, `code` and `error` of the item's first problem) or `failed` (retry that item). The same domain twice in one call (acme.com and www.acme.com) creates once; the repeat is domain_taken. Duplicates are by domain only: acme.com and acme.io are two accounts. Ken resolves each company from Kenso Search and, when research is on, starts research per created account, charged its model tokens at 2x model cost, and each web page or search on Kenso's Firecrawl key at 2x Firecrawl cost; research waits for credits when the balance is short. With account scope `own`, every created account is the caller's, and an item naming another member's `ownerMemberId` is `invalid` with code `permission_denied`. Requires
|
|
1004
|
+
`items` (1 to 100) are each a `POST /v1/accounts` body. Returns 200 with one result per item in request order: `created` (with the account and `research`: queued or waiting_credits), `domain_taken` (the `accountId` that already owns `domain`; counted in skipped), `invalid` (`field`, `code` and `error` of the item's first problem) or `failed` (retry that item). The same domain twice in one call (acme.com and www.acme.com) creates once; the repeat is domain_taken. Duplicates are by domain only: acme.com and acme.io are two accounts. Ken resolves each company from Kenso Search and, when research is on, starts research per created account, charged its model tokens at 2x model cost, and each web page or search on Kenso's Firecrawl key at 2x Firecrawl cost; research waits for credits when the balance is short. With account scope `own`, every created account is the caller's, and an item naming another member's `ownerMemberId` is `invalid` with code `permission_denied`. Requires Accounts edit.
|
|
1004
1005
|
|
|
1005
1006
|
- Beta: needs the `accounts` feature flag on the workspace.
|
|
1006
1007
|
- API: `POST /v1/accounts/bulk-create`
|
|
@@ -1045,7 +1046,7 @@ kenso accounts bulk-update --data @body.json
|
|
|
1045
1046
|
|
|
1046
1047
|
Create an account from its domains.
|
|
1047
1048
|
|
|
1048
|
-
`domains` (1 to 20 domains, website URLs or work emails; the first is primary) is required. A domain another account owns is `409 conflict` with detail `domain_taken` and that `accountId`: use that account instead. With account scope `own`, an account the caller cannot see is not named (the detail has no `accountId`), a missing, null or own `ownerMemberId` makes the caller the owner, and another member's is `403 permission_denied` with `scope: all`. Fields a person sets are pinned. Ken resolves the company from Kenso Search and fills the name (else from the primary domain: acme.com becomes Acme), industry, size, HQ and LinkedIn page without pinning them. When research is on, it starts research, charged its model tokens at 2x model cost, and each web page or search on Kenso's Firecrawl key at 2x Firecrawl cost. `skipResearch=true` creates the account without research or the committee run, so the create costs no credits; research can be started later with `POST /v1/accounts/{accountId}/research`. `sendsFromInboxId` and `sendsFromLinkedInAccountId` are checked like on PATCH. Requires
|
|
1049
|
+
`domains` (1 to 20 domains, website URLs or work emails; the first is primary) is required. A domain another account owns is `409 conflict` with detail `domain_taken` and that `accountId`: use that account instead. With account scope `own`, an account the caller cannot see is not named (the detail has no `accountId`), a missing, null or own `ownerMemberId` makes the caller the owner, and another member's is `403 permission_denied` with `scope: all`. Fields a person sets are pinned. Ken resolves the company from Kenso Search and fills the name (else from the primary domain: acme.com becomes Acme), industry, size, HQ and LinkedIn page without pinning them. When research is on, it starts research, charged its model tokens at 2x model cost, and each web page or search on Kenso's Firecrawl key at 2x Firecrawl cost. `skipResearch=true` creates the account without research or the committee run, so the create costs no credits; research can be started later with `POST /v1/accounts/{accountId}/research`. `sendsFromInboxId` and `sendsFromLinkedInAccountId` are checked like on PATCH. Requires Accounts edit.
|
|
1049
1050
|
|
|
1050
1051
|
- Beta: needs the `accounts` feature flag on the workspace.
|
|
1051
1052
|
- API: `POST /v1/accounts`
|
|
@@ -1105,7 +1106,7 @@ kenso accounts delete --account-id <account-id>
|
|
|
1105
1106
|
|
|
1106
1107
|
Count accounts per filter value for the filter panel.
|
|
1107
1108
|
|
|
1108
|
-
Body: `filters`, the same conditions as `accounts.search` (optional). Returns `totalCount` (accounts that pass every filter) and one facet per field, in this order: `stage`, `committee`, `lastTouch`, `industry`, `fundingRound`, `headcount`, `signal`, `latestSignal`, `hasOpenOpportunity` (only while the opportunities feature is on), `tier`, `accountType`. Each value's `count` applies every other filter but not the field's own, so it is the number of accounts the list would show after adding that value (an account with several signal kinds counts under each). There is no `q`. Fixed fields list every value, zero counts included: stage in the order meeting_booked, engaged, warming, researching, nurture, lost, paused, not_a_fit; committee, lastTouch, headcount, signal, latestSignal and accountType in the order listed on `accounts.search`; tier 1 to the workspace ladder's tierCount. The facets take `filters` only, not `where`. `industry` and `fundingRound` list the 100 values most used across every account in the workspace, zero counts included. Industry sorts by count, highest first, then name; funding round puts Pre-seed, Seed and Series A to E first, then the rest alphabetically. With account scope `own`, the counts, `totalCount` and the industry and funding round values come only from the accounts the caller owns. Requires
|
|
1109
|
+
Body: `filters`, the same conditions as `accounts.search` (optional). Returns `totalCount` (accounts that pass every filter) and one facet per field, in this order: `stage`, `committee`, `lastTouch`, `industry`, `fundingRound`, `headcount`, `signal`, `latestSignal`, `hasOpenOpportunity` (only while the opportunities feature is on), `tier`, `accountType`. Each value's `count` applies every other filter but not the field's own, so it is the number of accounts the list would show after adding that value (an account with several signal kinds counts under each). There is no `q`. Fixed fields list every value, zero counts included: stage in the order meeting_booked, engaged, warming, researching, nurture, lost, paused, not_a_fit; committee, lastTouch, headcount, signal, latestSignal and accountType in the order listed on `accounts.search`; tier 1 to the workspace ladder's tierCount. The facets take `filters` only, not `where`. `industry` and `fundingRound` list the 100 values most used across every account in the workspace, zero counts included. Industry sorts by count, highest first, then name; funding round puts Pre-seed, Seed and Series A to E first, then the rest alphabetically. With account scope `own`, the counts, `totalCount` and the industry and funding round values come only from the accounts the caller owns. Requires Accounts view.
|
|
1109
1110
|
|
|
1110
1111
|
- Beta: needs the `accounts` feature flag on the workspace.
|
|
1111
1112
|
- API: `POST /v1/accounts/facets`
|
|
@@ -1128,7 +1129,7 @@ kenso accounts facets --data @body.json
|
|
|
1128
1129
|
|
|
1129
1130
|
Return one account.
|
|
1130
1131
|
|
|
1131
|
-
`expand=stakeholders` embeds up to 200 stakeholders with their person. `expand=research` embeds the research dossier (status, trigger, errorCode, researchedAt, isStale, whyNow, angle, fitScore, tagline, description, facts, links, pains, stack, signals, sources). The status is the latest run's; the dossier fields come from the latest succeeded run, so a refresh in progress still shows the previous dossier. researchStatus (none | waiting_credits | queued | running | succeeded | failed) and researchedAt are on every account in get, list and search. `score` (0-99 from the signals of the last 90 days and the engaged people), `scoredAt`, `signalCount`, `engagedPeopleCount` and `latestSignal` (id, kind, title, occurredAt, detectedAt) are absent until the account is first scored. `handoff` is the latest hand-off to a teammate (`accounts.hand-off`), omitted when there is none. Requires
|
|
1132
|
+
`expand=stakeholders` embeds up to 200 stakeholders with their person. `expand=research` embeds the research dossier (status, trigger, errorCode, researchedAt, isStale, whyNow, angle, fitScore, tagline, description, facts, links, pains, stack, signals, sources). The status is the latest run's; the dossier fields come from the latest succeeded run, so a refresh in progress still shows the previous dossier. researchStatus (none | waiting_credits | queued | running | succeeded | failed) and researchedAt are on every account in get, list and search. `score` (0-99 from the signals of the last 90 days and the engaged people), `scoredAt`, `signalCount`, `engagedPeopleCount` and `latestSignal` (id, kind, title, occurredAt, detectedAt) are absent until the account is first scored. `handoff` is the latest hand-off to a teammate (`accounts.hand-off`), omitted when there is none. Requires Accounts view.
|
|
1132
1133
|
|
|
1133
1134
|
- Beta: needs the `accounts` feature flag on the workspace.
|
|
1134
1135
|
- API: `GET /v1/accounts/{accountId}`
|
|
@@ -1261,7 +1262,7 @@ kenso accounts links --account-id <account-id>
|
|
|
1261
1262
|
|
|
1262
1263
|
List accounts in the current workspace.
|
|
1263
1264
|
|
|
1264
|
-
Filters: `stage` (comma = OR: researching, warming, engaged, meeting_booked, nurture, lost, paused, not_a_fit), `ownerMemberId`, `domain` (any domain, URL or email; normalized), `q` (name or domain contains), `nextTouchBefore`, `latestSignalAfter` (the latest signal's event time is at or after it), `tagIds` (comma = OR: accounts carrying any of these tags; up to 100 positive ids, anything else is `400 validation_failed`), `hasOpenOpportunity` (`true`: accounts with an open opportunity, `false`: accounts without), `isCustomer` (`true`: customer accounts, `false`: the rest), `accountType` (comma = OR: prospect, client, lost, churned, partner, competitor, investor, do_not_contact), `fitsIcp` (`true`: accounts that fit the ICP, which are the accounts Today surfaces for their signals: none of the account's domains is one of the workspace's own domains (Settings > Company domains and the Primary), its stage is not `not_a_fit`, and research has not scored its fit below 20 (an account not researched yet fits); `false`: the accounts that do not). `sort`: `-createdAt` (default), `name`, `nextTouchAt`, `-score` (highest first, never scored last), `-latestSignalAt` (newest first, no signal last). Today's Heating up is `latestSignalAfter=<now - 7 days>&fitsIcp=true&sort=-score&limit=4`. Each item embeds its domains, its `tagIds` and, when it has one, its `latestSignal`, and carries `openOpportunityCount`, `openPipelineAmount` and `openOpportunityStage`, and, once handed off, its latest `handoff`. `score` (0-99), `scoredAt`, `signalCount` and `engagedPeopleCount` are absent until the account is first scored. `expand=committee` adds each account's `committee`: `stakeholderCount`, `openSeatCount`, `coverage` (covered and total, as on `GET /v1/accounts/{accountId}/committee`), `roles` (role, stakeholderCount and openSeatCount per role that has either) and `run`, the latest mapping run as the committee read returns it (omitted when Ken never mapped the account). Without `expand` there is no `committee`. Requires
|
|
1265
|
+
Filters: `stage` (comma = OR: researching, warming, engaged, meeting_booked, nurture, lost, paused, not_a_fit), `ownerMemberId`, `domain` (any domain, URL or email; normalized), `q` (name or domain contains), `nextTouchBefore`, `latestSignalAfter` (the latest signal's event time is at or after it), `tagIds` (comma = OR: accounts carrying any of these tags; up to 100 positive ids, anything else is `400 validation_failed`), `hasOpenOpportunity` (`true`: accounts with an open opportunity, `false`: accounts without), `isCustomer` (`true`: customer accounts, `false`: the rest), `accountType` (comma = OR: prospect, client, lost, churned, partner, competitor, investor, do_not_contact), `fitsIcp` (`true`: accounts that fit the ICP, which are the accounts Today surfaces for their signals: none of the account's domains is one of the workspace's own domains (Settings > Company domains and the Primary), its stage is not `not_a_fit`, and research has not scored its fit below 20 (an account not researched yet fits); `false`: the accounts that do not). `sort`: `-createdAt` (default), `name`, `nextTouchAt`, `-score` (highest first, never scored last), `-latestSignalAt` (newest first, no signal last). Today's Heating up is `latestSignalAfter=<now - 7 days>&fitsIcp=true&sort=-score&limit=4`. Each item embeds its domains, its `tagIds` and, when it has one, its `latestSignal`, and carries `openOpportunityCount`, `openPipelineAmount` and `openOpportunityStage`, and, once handed off, its latest `handoff`. `score` (0-99), `scoredAt`, `signalCount` and `engagedPeopleCount` are absent until the account is first scored. `expand=committee` adds each account's `committee`: `stakeholderCount`, `openSeatCount`, `coverage` (covered and total, as on `GET /v1/accounts/{accountId}/committee`), `roles` (role, stakeholderCount and openSeatCount per role that has either) and `run`, the latest mapping run as the committee read returns it (omitted when Ken never mapped the account). Without `expand` there is no `committee`. Requires Accounts view.
|
|
1265
1266
|
|
|
1266
1267
|
- Beta: needs the `accounts` feature flag on the workspace.
|
|
1267
1268
|
- API: `GET /v1/accounts` (a list: `--limit`, `--cursor`, `--all`)
|
|
@@ -1349,7 +1350,7 @@ kenso accounts research --account-id <account-id> --data @body.json
|
|
|
1349
1350
|
|
|
1350
1351
|
Search accounts in the current workspace with filter conditions and AND / OR groups.
|
|
1351
1352
|
|
|
1352
|
-
Body: `filters`, `where`, `q`, `sort`, `limit` (1-200, default 50), `cursor`, `includeTotal`. Every field is optional; an empty body lists every account. `filters`, `where` and `q` AND together. `filters` is a list of `{ "field", "operator", "values" }` conditions. Conditions AND together; the values of one condition OR together. `operator` is `is` or `is_not`; `is_not` also matches an account that has no value for the field. One condition per field (a second is `400 validation_failed`, detail `duplicate_field`). 1 to 50 values per condition, duplicates removed; a condition with an empty `values` list is ignored. Fields and values:<list type="bullet"><item>`stage`: researching, warming, engaged, meeting_booked, nurture, lost, paused, not_a_fit.</item><item>`committee`: n = stakeholders with coverage engaged or planned, t = all stakeholders. `none_engaged` when n = 0 (also with no stakeholders), `under_half` when n / t < 0.5, else `half_or_more`.</item><item>`lastTouch`: `past_7_days` (lastTouchAt within 7 days), `one_to_four_weeks` (7 to 28 days ago), `over_a_month` (older), `never` (no touch sent or done).</item><item>`headcount`: `under_250`, `from_250_to_999`, `from_1000` (employeeCount). An account with no employeeCount is in no bucket.</item><item>`industry`, `fundingRound`: any text, 1-200 characters, exact match. Read the values in use from `accounts.facets`.</item><item>`signal`: job_change, funding, hiring, public_post, event, asset_view, tech_change. An account matches a value when it has a signal of that kind whose event time (when it happened, else when Ken found it) is in the last 90 days; `job_change` also matches `leadership_hire`. `is_not` matches an account with none of them.</item><item>`latestSignal`: the latest signal's event time in the `lastTouch` buckets: `past_7_days`, `one_to_four_weeks`, `over_a_month`, `never` (no signal, or not scored yet).</item><item>`hasOpenOpportunity`: `true` (the account has a live opportunity in an open stage) or `false`. It is also a facet field with yes and no counts.</item><item>`isCustomer`: `true` (the account is marked a customer) or `false`. Not a facet field.</item><item>`tier`: 1 to 10, the tier the account is worked at (the hand-set tier, else the placed tier, else the tier its score falls in on the workspace's ladder). A tier past the ladder's tierCount matches no account. It is also a facet field.</item><item>`accountType`: prospect, client, lost, churned, partner, competitor, investor, do_not_contact. It is also a facet field.</item></list> `where` is a group `{ "match": "all" | "any", "conditions": [...] }`: `all` needs every entry to hold, `any` at least one. An entry is a condition `{ "field", "operator", "values" }` or a group, one level deep (a group inside a group inside `where` is `400`), with at most 50 conditions in all. A field may appear in several conditions. A condition whose operator needs values and that has none is dropped, and a group with no entries matches every account. Every `filters` field takes `is` and `is_not` with the values above, and where adds:<list type="bullet"><item>`headcount``lt` / `gte`: one whole number of employees (0 to 10,000,000). An account with no employeeCount matches neither.</item><item>`committee``lt` / `gte`: one share from 0 to 100, 100 n / t (no committee is 0).</item><item>`lastTouch`, `latestSignal``within_days` / `older_than_days`: one whole number of days from 1 to 365. Within: in the last N days. Older: more than N days ago; an account never touched (or with no signal) matches neither.</item><item>`owner`: `is` / `is_not` member ids (`is_not` also matches no owner), or `is_empty` (no owner, no values).</item><item>`tags`: tag ids. `is`: the account has any of them; `is_not`: it has none of them.</item><item>`domain`: `is` (a domain, URL or work email, normalized like a domain write; a free email provider is `400`), `contains` or `ends_with` (a lower-case piece such as `acme` or `.io`). It matches when any of the account's domains does.</item><item>`pipelineStage`: the stage key of the account's open opportunities. `is`: one of them is in one of these stages; `is_not`: none is; `is_empty`: the account has no open opportunity.</item><item>`nextTouch`: `is_planned`, `is_not_planned` (no values), or `within_days` N (planned for the next N days, 1 to 365; an overdue touch counts).</item></list> Example: <c>{"where": {"match": "any", "conditions": [{"field": "tier", "operator": "is", "values": ["1"]}, {"match": "all", "conditions": [{"field": "accountType", "operator": "is", "values": ["prospect"]}, {"field": "lastTouch", "operator": "older_than_days", "values": ["30"]}]}]}}</c>: tier 1 accounts, and prospects last touched more than 30 days ago. Every problem in `filters` or `where` is listed in one `400 validation_failed`, each with its path (`where.conditions[1].conditions[0].values[0]`). `q` (name or domain contains) and `sort` (`-createdAt` default, `name`, `nextTouchAt`, `-score`, `-latestSignalAt`) work as on `accounts.list`. `includeTotal: true` fills `pagination.total` with every account that passes the filters, where and q. Each item embeds its domains. Requires
|
|
1353
|
+
Body: `filters`, `where`, `q`, `sort`, `limit` (1-200, default 50), `cursor`, `includeTotal`. Every field is optional; an empty body lists every account. `filters`, `where` and `q` AND together. `filters` is a list of `{ "field", "operator", "values" }` conditions. Conditions AND together; the values of one condition OR together. `operator` is `is` or `is_not`; `is_not` also matches an account that has no value for the field. One condition per field (a second is `400 validation_failed`, detail `duplicate_field`). 1 to 50 values per condition, duplicates removed; a condition with an empty `values` list is ignored. Fields and values:<list type="bullet"><item>`stage`: researching, warming, engaged, meeting_booked, nurture, lost, paused, not_a_fit.</item><item>`committee`: n = stakeholders with coverage engaged or planned, t = all stakeholders. `none_engaged` when n = 0 (also with no stakeholders), `under_half` when n / t < 0.5, else `half_or_more`.</item><item>`lastTouch`: `past_7_days` (lastTouchAt within 7 days), `one_to_four_weeks` (7 to 28 days ago), `over_a_month` (older), `never` (no touch sent or done).</item><item>`headcount`: `under_250`, `from_250_to_999`, `from_1000` (employeeCount). An account with no employeeCount is in no bucket.</item><item>`industry`, `fundingRound`: any text, 1-200 characters, exact match. Read the values in use from `accounts.facets`.</item><item>`signal`: job_change, funding, hiring, public_post, event, asset_view, tech_change. An account matches a value when it has a signal of that kind whose event time (when it happened, else when Ken found it) is in the last 90 days; `job_change` also matches `leadership_hire`. `is_not` matches an account with none of them.</item><item>`latestSignal`: the latest signal's event time in the `lastTouch` buckets: `past_7_days`, `one_to_four_weeks`, `over_a_month`, `never` (no signal, or not scored yet).</item><item>`hasOpenOpportunity`: `true` (the account has a live opportunity in an open stage) or `false`. It is also a facet field with yes and no counts.</item><item>`isCustomer`: `true` (the account is marked a customer) or `false`. Not a facet field.</item><item>`tier`: 1 to 10, the tier the account is worked at (the hand-set tier, else the placed tier, else the tier its score falls in on the workspace's ladder). A tier past the ladder's tierCount matches no account. It is also a facet field.</item><item>`accountType`: prospect, client, lost, churned, partner, competitor, investor, do_not_contact. It is also a facet field.</item></list> `where` is a group `{ "match": "all" | "any", "conditions": [...] }`: `all` needs every entry to hold, `any` at least one. An entry is a condition `{ "field", "operator", "values" }` or a group, one level deep (a group inside a group inside `where` is `400`), with at most 50 conditions in all. A field may appear in several conditions. A condition whose operator needs values and that has none is dropped, and a group with no entries matches every account. Every `filters` field takes `is` and `is_not` with the values above, and where adds:<list type="bullet"><item>`headcount``lt` / `gte`: one whole number of employees (0 to 10,000,000). An account with no employeeCount matches neither.</item><item>`committee``lt` / `gte`: one share from 0 to 100, 100 n / t (no committee is 0).</item><item>`lastTouch`, `latestSignal``within_days` / `older_than_days`: one whole number of days from 1 to 365. Within: in the last N days. Older: more than N days ago; an account never touched (or with no signal) matches neither.</item><item>`owner`: `is` / `is_not` member ids (`is_not` also matches no owner), or `is_empty` (no owner, no values).</item><item>`tags`: tag ids. `is`: the account has any of them; `is_not`: it has none of them.</item><item>`domain`: `is` (a domain, URL or work email, normalized like a domain write; a free email provider is `400`), `contains` or `ends_with` (a lower-case piece such as `acme` or `.io`). It matches when any of the account's domains does.</item><item>`pipelineStage`: the stage key of the account's open opportunities. `is`: one of them is in one of these stages; `is_not`: none is; `is_empty`: the account has no open opportunity.</item><item>`nextTouch`: `is_planned`, `is_not_planned` (no values), or `within_days` N (planned for the next N days, 1 to 365; an overdue touch counts).</item></list> Example: <c>{"where": {"match": "any", "conditions": [{"field": "tier", "operator": "is", "values": ["1"]}, {"match": "all", "conditions": [{"field": "accountType", "operator": "is", "values": ["prospect"]}, {"field": "lastTouch", "operator": "older_than_days", "values": ["30"]}]}]}}</c>: tier 1 accounts, and prospects last touched more than 30 days ago. Every problem in `filters` or `where` is listed in one `400 validation_failed`, each with its path (`where.conditions[1].conditions[0].values[0]`). `q` (name or domain contains) and `sort` (`-createdAt` default, `name`, `nextTouchAt`, `-score`, `-latestSignalAt`) work as on `accounts.list`. `includeTotal: true` fills `pagination.total` with every account that passes the filters, where and q. Each item embeds its domains. Requires Accounts view. Days: with a time zone, `lastTouch`, `latestSignal` and `nextTouch` count calendar days in it, as the app shows them. The zone is the member's app time zone (Settings), else `timeZone` (an IANA zone such as `Europe/Bucharest`; an unknown one is `400`). Past 7 days is today and the 7 days before it (from the zone's midnight 7 days ago), 1-4 weeks back to the zone's midnight 28 days ago, `within_days` N from the zone's midnight N days ago (`older_than_days` is before it), and `nextTouch``within_days` N before the zone's midnight after the day N days ahead. With no zone the windows roll back from now.
|
|
1353
1354
|
|
|
1354
1355
|
- Beta: needs the `accounts` feature flag on the workspace.
|
|
1355
1356
|
- API: `POST /v1/accounts/search`
|
|
@@ -1380,7 +1381,7 @@ kenso accounts search --data @body.json
|
|
|
1380
1381
|
|
|
1381
1382
|
Update account fields. Absent fields stay unchanged; null clears.
|
|
1382
1383
|
|
|
1383
|
-
Fields: name, stage, ownerMemberId (a workspace member), fitScore (0-100), whyNow, angle, cadenceDays (1-365), industry, fundingRound (1-100 characters), employeeCount, hqLocation, linkedinUrl, kenCompanyId (the company's Kenso id), sendsFromInboxId, sendsFromLinkedInAccountId. `sendsFromInboxId` is the inbox email touches send from: a member's primary inbox (owned and on the workspace's primary domain), or a shared campaign inbox on one of the workspace's cold sending domains, whose touches the account owner approves. `sendsFromLinkedInAccountId` is the LinkedIn account LinkedIn touches send from, connected by a member. Null on either means the owner's default. Neither is pinned, so an agent may change them. A bad id is `400 validation_failed` with code `not_found`, `not_owned`, `not_member` (its member left the workspace) or `email_domain_mismatch` (the inbox is not on the workspace's email domain; the message says what fixes it). Only a changed id is checked, so a form that sends the stored ids back saves. A disconnected sender is accepted; its touches wait until it reconnects. Changing a field a person set is `409 conflict` with `pinned_by_user` unless `overwritePinned: true`; nothing is applied partially. With account scope `own`, an account the caller does not own is `404 not_found`, and an `ownerMemberId` other than the caller's own is `403 permission_denied` with `scope: all`. Requires
|
|
1384
|
+
Fields: name, stage, ownerMemberId (a workspace member), fitScore (0-100), whyNow, angle, cadenceDays (1-365), industry, fundingRound (1-100 characters), employeeCount, hqLocation, linkedinUrl, kenCompanyId (the company's Kenso id), sendsFromInboxId, sendsFromLinkedInAccountId. `sendsFromInboxId` is the inbox email touches send from: a member's primary inbox (owned and on the workspace's primary domain), or a shared campaign inbox on one of the workspace's cold sending domains, whose touches the account owner approves. `sendsFromLinkedInAccountId` is the LinkedIn account LinkedIn touches send from, connected by a member. Null on either means the owner's default. Neither is pinned, so an agent may change them. A bad id is `400 validation_failed` with code `not_found`, `not_owned`, `not_member` (its member left the workspace) or `email_domain_mismatch` (the inbox is not on the workspace's email domain; the message says what fixes it). Only a changed id is checked, so a form that sends the stored ids back saves. A disconnected sender is accepted; its touches wait until it reconnects. Changing a field a person set is `409 conflict` with `pinned_by_user` unless `overwritePinned: true`; nothing is applied partially. With account scope `own`, an account the caller does not own is `404 not_found`, and an `ownerMemberId` other than the caller's own is `403 permission_denied` with `scope: all`. Requires Accounts edit. `tierOverride` (1 to the ladder's `tierCount`; a higher tier is `400 validation_failed`) sets the account's tier by hand after the other fields are saved, and routes it to that tier's destination at once where the workspace has tier routing on (account-tiers); null is Auto: the account goes back to its auto tier (the tier the ladder placed it at, else its score's tier) without routing, and the ladder moves it from then on. Both write a tier change to the account's activity, with tier routing on or off. A tier whose move adds the account's people to a campaign, or stops the people the ladder put in one, also requires campaigns edit (`403 permission_denied`); both are checked before anything is saved. The response's `tier` is the hand-set tier, else `autoTier`. When another tier change on the account ran at the same time, the tier is not set and the response is `409 conflict`; the other fields are saved. A campaign that refuses the people (the plan's lead limit) also leaves the tier unset, with the other fields saved. `isCustomer` (true or false) marks the account a customer or clears it, after the other fields are saved. Only a workspace admin can change it (`403 forbidden` with code `customer_not_allowed`, checked before anything is saved); anyone else may send the stored value back, which leaves the flag as it is. true puts every domain of the account on the workspace blocklist with reason `customer`, so Ken sends its people nothing; false takes off only those rows, and a domain blocked for another reason stays blocked. The response carries `isCustomer`, `customerSince` and `customerSource` (manual here). `accountType` (prospect, client, lost, churned, partner, competitor, investor, do_not_contact; not null) is what the workspace calls the account, written after `isCustomer`. `client` is the customer flag: moving an account to client marks it a customer (its domains go on the blocklist) and moving a client to another type clears it, so either needs a workspace admin (`403 forbidden` with code `customer_not_allowed`, checked before anything is saved); the flag turning on or off any other way (a won opportunity, the CRM, `isCustomer`) moves the type to client or back to prospect. Any other type change is open to anyone with accounts edit. `accountType` and `isCustomer` that disagree in one body are `400 validation_failed`. Each change writes `account.type_changed` on the account's timeline. Only `client` changes sending by itself: any other type blocks the account's domains only while an enabled blocklist rule names it (`accountTypes` on `/v1/blocklist-rules`, DEV-4105), except that a client moved to lost, churned, competitor or do_not_contact keeps its domains on the blocklist. Sending the type the account already has changes nothing. To stop contacting an account, put its domains on the blocklist.
|
|
1384
1385
|
|
|
1385
1386
|
- Beta: needs the `accounts` feature flag on the workspace.
|
|
1386
1387
|
- API: `PATCH /v1/accounts/{accountId}`
|
|
@@ -1892,7 +1893,7 @@ kenso agent-team update-settings --data @body.json
|
|
|
1892
1893
|
|
|
1893
1894
|
Reserve one AI assist call for the calling member.
|
|
1894
1895
|
|
|
1895
|
-
Counts against the caller's per-user quota for the feature (`onboarding_interview`, `build_chat_suggestions`, `ai_search_filters`, or `builder_chat`): 10 to 20 a minute and 200 to 300 a rolling day. Nothing else is saved. An unknown feature is `400 validation_failed`. A spent quota is `429 quota_exceeded` with `Retry-After` and a top-level `quotaResetAt`, the same shape as `POST /v1/support/turns`. Super admins and workspaces with billing bypass are exempt. Requires `
|
|
1896
|
+
Counts against the caller's per-user quota for the feature (`onboarding_interview`, `build_chat_suggestions`, `ai_search_filters`, or `builder_chat`): 10 to 20 a minute and 200 to 300 a rolling day. Nothing else is saved. An unknown feature is `400 validation_failed`. A spent quota is `429 quota_exceeded` with `Retry-After` and a top-level `quotaResetAt`, the same shape as `POST /v1/support/turns`. Super admins and workspaces with billing bypass are exempt. Requires the `ask` permission.
|
|
1896
1897
|
|
|
1897
1898
|
- API: `POST /v1/ai-assist/reservations`
|
|
1898
1899
|
- Generated from the API contract
|
|
@@ -1916,7 +1917,7 @@ kenso ai-assist-reservations create --data @body.json
|
|
|
1916
1917
|
|
|
1917
1918
|
Estimate prompt tokens and list the models a flow can use.
|
|
1918
1919
|
|
|
1919
|
-
Internal. Replaces token analysis and supported models. `flow` is required. A campaign outside `X-Ken-Workspace-Id` is `not_found` before either read. Requires
|
|
1920
|
+
Internal. Replaces token analysis and supported models. `flow` is required. A campaign outside `X-Ken-Workspace-Id` is `not_found` before either read. Requires Campaigns view.
|
|
1920
1921
|
|
|
1921
1922
|
- API: `GET /v1/campaigns/{campaignId}/ai-cost-estimate`
|
|
1922
1923
|
- Generated from the API contract
|
|
@@ -1939,7 +1940,7 @@ kenso ai-cost-estimate get --campaign-id <campaign-id>
|
|
|
1939
1940
|
|
|
1940
1941
|
Approve a held contact's lines.
|
|
1941
1942
|
|
|
1942
|
-
The lines the hold keeps become the contact's personalization lines and the contact counts as personalized, so it can send. Not charged. A contact with no hold in the campaign (never held, already approved, or regenerated) is `not_held` (409). When the contact already has a live line for one of the held variables the approval is `conflict` (409) and nothing changes; regenerate the contact instead. A campaign or contact outside the workspace, or a contact not in this campaign, is `not_found`. Requires
|
|
1943
|
+
The lines the hold keeps become the contact's personalization lines and the contact counts as personalized, so it can send. Not charged. A contact with no hold in the campaign (never held, already approved, or regenerated) is `not_held` (409). When the contact already has a live line for one of the held variables the approval is `conflict` (409) and nothing changes; regenerate the contact instead. A campaign or contact outside the workspace, or a contact not in this campaign, is `not_found`. Requires Campaigns edit.
|
|
1943
1944
|
|
|
1944
1945
|
- API: `POST /v1/campaigns/{campaignId}/ai-line-holds/{contactId}/approve`
|
|
1945
1946
|
- Generated from the API contract
|
|
@@ -1959,7 +1960,7 @@ kenso ai-line-holds approve --campaign-id <campaign-id> --contact-id <contact-id
|
|
|
1959
1960
|
|
|
1960
1961
|
List the contacts the AI line check held in a campaign.
|
|
1961
1962
|
|
|
1962
|
-
Newest hold first, with the reasons and the lines each hold keeps. Pages with `limit` (1 to 200, default 50) and `cursor`. A contact appears until it is approved or regenerated. A campaign outside the workspace is `not_found`. Requires
|
|
1963
|
+
Newest hold first, with the reasons and the lines each hold keeps. Pages with `limit` (1 to 200, default 50) and `cursor`. A contact appears until it is approved or regenerated. A campaign outside the workspace is `not_found`. Requires Campaigns view.
|
|
1963
1964
|
|
|
1964
1965
|
- API: `GET /v1/campaigns/{campaignId}/ai-line-holds` (a list: `--limit`, `--cursor`, `--all`)
|
|
1965
1966
|
- Generated from the API contract
|
|
@@ -1984,7 +1985,7 @@ kenso ai-line-holds list --campaign-id <campaign-id> --all
|
|
|
1984
1985
|
|
|
1985
1986
|
List a contact's AI lines.
|
|
1986
1987
|
|
|
1987
|
-
One line per AI variable of the contact's campaign: the stored line its next send renders (the newest personalized line, or its rewrite when the prompt rewrites; the segment's prompt before the campaign's). Older runs and replaced lines are not listed. Ordered by variable, at most 200 lines, not paginated. A contact outside the workspace, deleted, or not in a campaign is `not_found`. Requires
|
|
1988
|
+
One line per AI variable of the contact's campaign: the stored line its next send renders (the newest personalized line, or its rewrite when the prompt rewrites; the segment's prompt before the campaign's). Older runs and replaced lines are not listed. Ordered by variable, at most 200 lines, not paginated. A contact outside the workspace, deleted, or not in a campaign is `not_found`. Requires Campaigns view.
|
|
1988
1989
|
|
|
1989
1990
|
- Beta: needs the `ai_line_edit` feature flag on the workspace.
|
|
1990
1991
|
- API: `GET /v1/contacts/{contactId}/ai-lines`
|
|
@@ -2004,7 +2005,7 @@ kenso ai-lines list --contact-id <contact-id>
|
|
|
2004
2005
|
|
|
2005
2006
|
Write a contact's AI lines again.
|
|
2006
2007
|
|
|
2007
|
-
Clears the contact's personalized lines (and the rewritten lines built on them) and queues a personalization run for that contact alone, charged as one lead. Returns `202` with the run; poll `GET /v1/ai-runs/{aiRunId}`. When the run lands, an approval draft that shows the lead is updated. A lead already sent or exported, with a send queued, or in an unfinished AI run is `409 invalid_state` and nothing changes. AI quota limits answer `429 quota_exceeded` and too few credits `402`, both before anything is cleared, so the lead keeps its lines. Only a full AI run queue (`503`) after the clear leaves the lead without lines until a retry or the next scheduled AI run. Requires `
|
|
2008
|
+
Clears the contact's personalized lines (and the rewritten lines built on them) and queues a personalization run for that contact alone, charged as one lead. Returns `202` with the run; poll `GET /v1/ai-runs/{aiRunId}`. When the run lands, an approval draft that shows the lead is updated. A lead already sent or exported, with a send queued, or in an unfinished AI run is `409 invalid_state` and nothing changes. AI quota limits answer `429 quota_exceeded` and too few credits `402`, both before anything is cleared, so the lead keeps its lines. Only a full AI run queue (`503`) after the clear leaves the lead without lines until a retry or the next scheduled AI run. Requires Campaigns edit and the `ask` permission.
|
|
2008
2009
|
|
|
2009
2010
|
- Beta: needs the `ai_line_edit` feature flag on the workspace.
|
|
2010
2011
|
- API: `POST /v1/contacts/{contactId}/ai-lines/regenerate`
|
|
@@ -2024,7 +2025,7 @@ kenso ai-lines regenerate --contact-id <contact-id>
|
|
|
2024
2025
|
|
|
2025
2026
|
Replace the text of one of a contact's AI lines.
|
|
2026
2027
|
|
|
2027
|
-
The next send of the lead renders the new text, and an approval draft that shows the lead is updated. Steps already sent keep what they sent. `text` is required, at most 4,000 characters; it gets the cleanup a generated line gets (emoji removed, dashes normalized, spaces collapsed) and must be 1 to 1,000 characters after it, else `validation_failed`. Another of the contact's lines that the send does not read (an older run, a personalized line its rewrite replaces) is `409 invalid_state` and nothing changes; list the lines again and edit the one shown. A line that is not the contact's is `not_found`. Requires
|
|
2028
|
+
The next send of the lead renders the new text, and an approval draft that shows the lead is updated. Steps already sent keep what they sent. `text` is required, at most 4,000 characters; it gets the cleanup a generated line gets (emoji removed, dashes normalized, spaces collapsed) and must be 1 to 1,000 characters after it, else `validation_failed`. Another of the contact's lines that the send does not read (an older run, a personalized line its rewrite replaces) is `409 invalid_state` and nothing changes; list the lines again and edit the one shown. A line that is not the contact's is `not_found`. Requires Campaigns edit.
|
|
2028
2029
|
|
|
2029
2030
|
- Beta: needs the `ai_line_edit` feature flag on the workspace.
|
|
2030
2031
|
- API: `PATCH /v1/contacts/{contactId}/ai-lines/{aiLineId}`
|
|
@@ -2051,7 +2052,7 @@ kenso ai-lines update --contact-id <contact-id> --ai-line-id <ai-line-id> --data
|
|
|
2051
2052
|
|
|
2052
2053
|
Queue an AI run for a campaign in the current workspace.
|
|
2053
2054
|
|
|
2054
|
-
Returns `202` with a run id. Poll `GET /v1/ai-runs/{aiRunId}`. A campaign outside `X-Ken-Workspace-Id` is `not_found` before the run is queued. With `dryRun: true` the request is validated the same way and the answer is `200` with what the run would process: `batchSize` (the requested batch, else the flow's submission limit when `processAll`, else 500), `eligibleCount` (eligible contacts now, in `segmentId` when set), `projectedContactCount` (the lower of the two, an upper bound) and the flow's `blockingGate` and `blockingReason`. Nothing is queued, no quota is reserved and no credits are spent. Requires `
|
|
2055
|
+
Returns `202` with a run id. Poll `GET /v1/ai-runs/{aiRunId}`. A campaign outside `X-Ken-Workspace-Id` is `not_found` before the run is queued. With `dryRun: true` the request is validated the same way and the answer is `200` with what the run would process: `batchSize` (the requested batch, else the flow's submission limit when `processAll`, else 500), `eligibleCount` (eligible contacts now, in `segmentId` when set), `projectedContactCount` (the lower of the two, an upper bound) and the flow's `blockingGate` and `blockingReason`. Nothing is queued, no quota is reserved and no credits are spent. Requires Campaigns edit and the `ask` permission.
|
|
2055
2056
|
|
|
2056
2057
|
- API: `POST /v1/campaigns/{campaignId}/ai-runs`
|
|
2057
2058
|
- Generated from the API contract
|
|
@@ -2063,7 +2064,7 @@ Returns `202` with a run id. Poll `GET /v1/ai-runs/{aiRunId}`. A campaign outsid
|
|
|
2063
2064
|
| `--flow` | string | no | flow (body, string) |
|
|
2064
2065
|
| `--batch-size` | integer | no | batchSize (body, integer) |
|
|
2065
2066
|
| `--process-all` | boolean | no | processAll (body, boolean) |
|
|
2066
|
-
| `--segment-id` | integer | no |
|
|
2067
|
+
| `--segment-id` | integer | no | A segment of the campaign. Omit it for every segment; `0` is `400 validation_failed`, not "no segment". |
|
|
2067
2068
|
| `--provider` | string | no | provider (body, string) |
|
|
2068
2069
|
| `--model` | string | no | model (body, string) |
|
|
2069
2070
|
| `--body-dry-run` | boolean | no | True validates the run and returns what it would process (`200`), without queueing it, reserving quota or spending credits. Default false. |
|
|
@@ -2082,7 +2083,7 @@ kenso ai-runs create --campaign-id <campaign-id> --data @body.json
|
|
|
2082
2083
|
|
|
2083
2084
|
Read one AI run.
|
|
2084
2085
|
|
|
2085
|
-
The run's campaign must belong to `X-Ken-Workspace-Id`. A missing run, or a run outside the workspace, is `not_found`. Requires
|
|
2086
|
+
The run's campaign must belong to `X-Ken-Workspace-Id`. A missing run, or a run outside the workspace, is `not_found`. Requires Campaigns view.
|
|
2086
2087
|
|
|
2087
2088
|
- API: `GET /v1/ai-runs/{aiRunId}`
|
|
2088
2089
|
- Generated from the API contract
|
|
@@ -2101,7 +2102,7 @@ kenso ai-runs get --ai-run-id <ai-run-id>
|
|
|
2101
2102
|
|
|
2102
2103
|
Read AI-run eligibility for a campaign, with an optional invalidation preview.
|
|
2103
2104
|
|
|
2104
|
-
Replaces eligible counts and the invalidation preview. Pass `flow` and `preview` (`freshness` or `reset`) to include the preview. A campaign outside the workspace is `not_found` before either read. Requires
|
|
2105
|
+
Replaces eligible counts and the invalidation preview. Pass `flow` and `preview` (`freshness` or `reset`) to include the preview. A campaign outside the workspace is `not_found` before either read. Requires Campaigns view.
|
|
2105
2106
|
|
|
2106
2107
|
- API: `GET /v1/campaigns/{campaignId}/ai-runs/eligibility`
|
|
2107
2108
|
- Generated from the API contract
|
|
@@ -2111,7 +2112,7 @@ Replaces eligible counts and the invalidation preview. Pass `flow` and `preview`
|
|
|
2111
2112
|
| `--campaign-id` | integer | yes | campaignId (path, integer) |
|
|
2112
2113
|
| `--flow` | string | no | flow (query, string) |
|
|
2113
2114
|
| `--preview` | string | no | preview (query, string) |
|
|
2114
|
-
| `--segment-id` | integer | no |
|
|
2115
|
+
| `--segment-id` | integer | no | A segment of the campaign. Omit it for every segment; `0` is `400 validation_failed`, not "no segment". |
|
|
2115
2116
|
| `--each` | string | no | Run once per row of a JSONL or CSV file (- for stdin); row keys fill params and body by name. |
|
|
2116
2117
|
| `--concurrency` | integer | no | With --each: requests in flight at once (1-16, default 4). |
|
|
2117
2118
|
|
|
@@ -2289,7 +2290,7 @@ kenso analytics get-deliverability
|
|
|
2289
2290
|
|
|
2290
2291
|
Return the bounce gates in force and each domain's and inbox's verdict for the last 24 hours.
|
|
2291
2292
|
|
|
2292
|
-
Read-only (DEV-5210). Counts accepted cold and 1:1 sends and hard bounces over the last 24 hours, as the sequencer's bounce signal does, and judges each row by the
|
|
2293
|
+
Read-only (DEV-5210). Counts accepted cold and 1:1 sends and hard bounces over the last 24 hours, as the sequencer's bounce signal does, and judges each row by the bounce gates the sequencer enforces: inbox rows by the inbox block gate, domain rows by the campaign pause gate (there is no domain bounce block). A row is `over` when its rate is strictly above `threshold` with at least `minSends` sends and `minBounces` hard bounces, `watch` when it is not over and its rate is at or above 80% of the threshold, and `ok` otherwise. `isSmallSample` marks a row with fewer sends than `minSends`, which cannot be `over`. The sequencer itself judges over `enforcedWindowHours`; `isEnforced` is false while it only records. A mailbox with no managed domain counts toward its address's domain, except on a free-mail provider (gmail.com), where it has an inbox row only. Rates are fractions from 0 to 1. Rows are worst first; `limit` caps each list (1 to 200, default 50).
|
|
2293
2294
|
|
|
2294
2295
|
- API: `GET /v1/analytics/deliverability-gates`
|
|
2295
2296
|
- Generated from the API contract
|
|
@@ -2644,7 +2645,7 @@ kenso apollo-lists list
|
|
|
2644
2645
|
|
|
2645
2646
|
Advance a draft through one AI flow.
|
|
2646
2647
|
|
|
2647
|
-
Requires
|
|
2648
|
+
Requires Campaigns edit.
|
|
2648
2649
|
|
|
2649
2650
|
- API: `POST /v1/approval-tests/{approvalTestId}/advance`
|
|
2650
2651
|
- Generated from the API contract
|
|
@@ -2669,7 +2670,7 @@ kenso approval-tests advance --approval-test-id <approval-test-id> --data @body.
|
|
|
2669
2670
|
|
|
2670
2671
|
Create an approval draft for a campaign in the current workspace.
|
|
2671
2672
|
|
|
2672
|
-
Returns `201` and `Location`. Requires `
|
|
2673
|
+
Returns `201` and `Location`. Requires Campaigns edit and the `share` permission.
|
|
2673
2674
|
|
|
2674
2675
|
- API: `POST /v1/campaigns/{campaignId}/approval-tests`
|
|
2675
2676
|
- Generated from the API contract
|
|
@@ -2699,7 +2700,7 @@ kenso approval-tests create --campaign-id <campaign-id> --data @body.json
|
|
|
2699
2700
|
|
|
2700
2701
|
Read a draft's client feedback.
|
|
2701
2702
|
|
|
2702
|
-
Feedback rows have no numeric id, so this returns the full window with no cursor and no total count. Requires
|
|
2703
|
+
Feedback rows have no numeric id, so this returns the full window with no cursor and no total count. Requires Campaigns view.
|
|
2703
2704
|
|
|
2704
2705
|
- API: `GET /v1/approval-tests/{approvalTestId}/feedback`
|
|
2705
2706
|
- Generated from the API contract
|
|
@@ -2760,7 +2761,7 @@ kenso approval-tests list --campaign-id <campaign-id> --all
|
|
|
2760
2761
|
|
|
2761
2762
|
Rotate a draft's share-link token.
|
|
2762
2763
|
|
|
2763
|
-
Requires `
|
|
2764
|
+
Requires Campaigns edit and the `share` permission.
|
|
2764
2765
|
|
|
2765
2766
|
- API: `POST /v1/approval-tests/{approvalTestId}/rotate-link`
|
|
2766
2767
|
- Generated from the API contract
|
|
@@ -4070,7 +4071,7 @@ kenso ats-pushes create --data @body.json
|
|
|
4070
4071
|
|
|
4071
4072
|
Upload a pending attachment for an email message.
|
|
4072
4073
|
|
|
4073
|
-
Multipart field `file` and form field `messageId` (`msg_`, email only). Caps stay at 5 files, 8 MiB each, and 10 MiB pending. Requires
|
|
4074
|
+
Multipart field `file` and form field `messageId` (`msg_`, email only). Caps stay at 5 files, 8 MiB each, and 10 MiB pending. Requires Inbox edit.
|
|
4074
4075
|
|
|
4075
4076
|
- API: `POST /v1/attachments`
|
|
4076
4077
|
- Generated from the API contract
|
|
@@ -4092,7 +4093,7 @@ kenso attachments create --file ./file.csv
|
|
|
4092
4093
|
|
|
4093
4094
|
Delete a pending attachment that has not been sent.
|
|
4094
4095
|
|
|
4095
|
-
Returns `204`. A malformed id is `not_found`. Requires
|
|
4096
|
+
Returns `204`. A malformed id is `not_found`. Requires Inbox edit.
|
|
4096
4097
|
|
|
4097
4098
|
- API: `DELETE /v1/attachments/{attachmentId}`
|
|
4098
4099
|
- Generated from the API contract
|
|
@@ -4111,7 +4112,7 @@ kenso attachments delete --attachment-id <attachment-id>
|
|
|
4111
4112
|
|
|
4112
4113
|
Download attachment bytes.
|
|
4113
4114
|
|
|
4114
|
-
A malformed id is `not_found`. `inline=true` is only honored for an inline image. Requires
|
|
4115
|
+
A malformed id is `not_found`. `inline=true` is only honored for an inline image. Requires Inbox view.
|
|
4115
4116
|
|
|
4116
4117
|
- API: `GET /v1/attachments/{attachmentId}/content`
|
|
4117
4118
|
- Generated from the API contract
|
|
@@ -4261,7 +4262,7 @@ kenso auto-pauses list --all
|
|
|
4261
4262
|
|
|
4262
4263
|
Return autonomous reply settings for the current workspace.
|
|
4263
4264
|
|
|
4264
|
-
|
|
4265
|
+
Open to any workspace member.
|
|
4265
4266
|
|
|
4266
4267
|
- API: `GET /v1/autonomous-reply-settings`
|
|
4267
4268
|
- Generated from the API contract
|
|
@@ -4279,7 +4280,7 @@ kenso autonomous-reply-settings get
|
|
|
4279
4280
|
|
|
4280
4281
|
Update autonomous reply settings.
|
|
4281
4282
|
|
|
4282
|
-
Absent fields stay unchanged. JSON null clears `extraInstructions`. `mode` is `draft` or `autonomous`, or `approve_risky` where the workspace has the `reply_agent_approve_risky` flag on; elsewhere `approve_risky` gets the same `400 validation_failed` on `mode` as an unknown mode. A body without `mode` keeps the stored mode. Requires `
|
|
4283
|
+
Absent fields stay unchanged. JSON null clears `extraInstructions`. `mode` is `draft` or `autonomous`, or `approve_risky` where the workspace has the `reply_agent_approve_risky` flag on; elsewhere `approve_risky` gets the same `400 validation_failed` on `mode` as an unknown mode. A body without `mode` keeps the stored mode. Requires the `workspace_settings` permission.
|
|
4283
4284
|
|
|
4284
4285
|
- API: `PATCH /v1/autonomous-reply-settings`
|
|
4285
4286
|
- Generated from the API contract
|
|
@@ -4404,7 +4405,7 @@ kenso blitz-people search --data @body.json
|
|
|
4404
4405
|
|
|
4405
4406
|
Add up to 1,000 blocklist values of one type.
|
|
4406
4407
|
|
|
4407
|
-
Send `values`, or `entries` (`[{ "value": "...", "reason": "..." }]`) for a reason per value, not both. Optional `reason` applies to every value without its own. Per-value outcomes are `succeeded` or `failed`. Duplicates stay failed with `already_exists` and keep their own reason. A domain a customer account or a blocklist rule already lists becomes `manual` under its id, with the reason sent, and is in `succeeded` with `claimed: true`, as on the single add. A shared mail provider domain (gmail.com, hotmail.co.uk, web.de) fails with `shared_mail_provider`; any other malformed value with `invalid`. To undo the add, bulk-delete only the `succeeded` ids without `claimed: true`: a claimed entry was blocked before the add, and deleting it unblocks the domain. Requires `
|
|
4408
|
+
Send `values`, or `entries` (`[{ "value": "...", "reason": "..." }]`) for a reason per value, not both. Optional `reason` applies to every value without its own. Per-value outcomes are `succeeded` or `failed`. Duplicates stay failed with `already_exists` and keep their own reason. A domain a customer account or a blocklist rule already lists becomes `manual` under its id, with the reason sent, and is in `succeeded` with `claimed: true`, as on the single add. A shared mail provider domain (gmail.com, hotmail.co.uk, web.de) fails with `shared_mail_provider`; any other malformed value with `invalid`. To undo the add, bulk-delete only the `succeeded` ids without `claimed: true`: a claimed entry was blocked before the add, and deleting it unblocks the domain. Requires the `workspace_settings` permission.
|
|
4408
4409
|
|
|
4409
4410
|
- API: `POST /v1/blocklist-entries/bulk-create`
|
|
4410
4411
|
- Generated from the API contract
|
|
@@ -4427,7 +4428,7 @@ kenso blocklist-entries bulk-create --data @body.json
|
|
|
4427
4428
|
|
|
4428
4429
|
Remove up to 1,000 blocklist entries by id.
|
|
4429
4430
|
|
|
4430
|
-
Body `{ "ids": [...] }`. Removes them in one transaction and runs the own-domain and rule reconciles once, so undoing a large upload takes one call per 1,000 entries. To undo a bulk add, send only its `succeeded` ids without `claimed: true`: a claimed entry was blocked before the add (by a customer account or a rule), and a customer entry deleted here stays off. `succeeded` lists every id that is off the blocklist after the call, in request order, including an id already gone. An own-domain entry, and a rule entry while blocklist rules are on, stay and are in `failed` with `invalid_state` and the single delete's message. Requires `
|
|
4431
|
+
Body `{ "ids": [...] }`. Removes them in one transaction and runs the own-domain and rule reconciles once, so undoing a large upload takes one call per 1,000 entries. To undo a bulk add, send only its `succeeded` ids without `claimed: true`: a claimed entry was blocked before the add (by a customer account or a rule), and a customer entry deleted here stays off. `succeeded` lists every id that is off the blocklist after the call, in request order, including an id already gone. An own-domain entry, and a rule entry while blocklist rules are on, stay and are in `failed` with `invalid_state` and the single delete's message. Requires the `workspace_settings` permission.
|
|
4431
4432
|
|
|
4432
4433
|
- API: `POST /v1/blocklist-entries/bulk-delete`
|
|
4433
4434
|
- Generated from the API contract
|
|
@@ -4448,7 +4449,7 @@ kenso blocklist-entries bulk-delete --data @body.json
|
|
|
4448
4449
|
|
|
4449
4450
|
Add one email or domain to the blocklist.
|
|
4450
4451
|
|
|
4451
|
-
Optional `reason` (at most 200 characters) says why the value is blocked. A duplicate entry is `validation_failed` and keeps its own reason. A domain a customer account or a blocklist rule already lists becomes `manual` under its id, with this reason, and comes back with `claimed: true`. A shared mail provider domain (gmail.com, hotmail.co.uk, web.de) is `validation_failed` with detail code `shared_mail_provider`: block those addresses one by one. Requires `
|
|
4452
|
+
Optional `reason` (at most 200 characters) says why the value is blocked. A duplicate entry is `validation_failed` and keeps its own reason. A domain a customer account or a blocklist rule already lists becomes `manual` under its id, with this reason, and comes back with `claimed: true`. A shared mail provider domain (gmail.com, hotmail.co.uk, web.de) is `validation_failed` with detail code `shared_mail_provider`: block those addresses one by one. Requires the `workspace_settings` permission.
|
|
4452
4453
|
|
|
4453
4454
|
- API: `POST /v1/blocklist-entries`
|
|
4454
4455
|
- Generated from the API contract
|
|
@@ -4472,7 +4473,7 @@ kenso blocklist-entries create --data @body.json
|
|
|
4472
4473
|
|
|
4473
4474
|
Remove one blocklist entry.
|
|
4474
4475
|
|
|
4475
|
-
Requires `
|
|
4476
|
+
Requires the `workspace_settings` permission. An entry outside the workspace is `not_found`.
|
|
4476
4477
|
|
|
4477
4478
|
- API: `DELETE /v1/blocklist-entries/{entryId}`
|
|
4478
4479
|
- Generated from the API contract
|
|
@@ -4491,7 +4492,7 @@ kenso blocklist-entries delete --entry-id <entry-id>
|
|
|
4491
4492
|
|
|
4492
4493
|
Import blocklist rows from a CSV file.
|
|
4493
4494
|
|
|
4494
|
-
Multipart field `file` is a `.csv` with `email` and/or `domain` columns and an optional `reason` column; a cell over 200 characters is cut, never failing the file. Optional form field `reason` (at most 200 characters) applies to every row without its own. Rows already on the blocklist keep their own reason, and a shared mail provider in the `domain` column (gmail.com) is skipped. Requires `
|
|
4495
|
+
Multipart field `file` is a `.csv` with `email` and/or `domain` columns and an optional `reason` column; a cell over 200 characters is cut, never failing the file. Optional form field `reason` (at most 200 characters) applies to every row without its own. Rows already on the blocklist keep their own reason, and a shared mail provider in the `domain` column (gmail.com) is skipped. Requires the `workspace_settings` permission.
|
|
4495
4496
|
|
|
4496
4497
|
- API: `POST /v1/blocklist-entries/imports`
|
|
4497
4498
|
- Generated from the API contract
|
|
@@ -4513,7 +4514,7 @@ kenso blocklist-entries import --file ./file.csv
|
|
|
4513
4514
|
|
|
4514
4515
|
List blocklist entries in the current workspace.
|
|
4515
4516
|
|
|
4516
|
-
Ordered by id, which follows creation: `sort=createdAt` (the default) is oldest first, `sort=-createdAt` newest first; keep the same `sort` while paging. Optional filters: `type` (`email` or `domain`), `value` (an exact match), `q` (a case-insensitive substring of the value or the reason), `source` (comma-separated `manual`, `own_domain`, `customer`, `rule`) and `hasReason`. `includeTotal=true` adds `pagination.total`, every entry the filters match. `includeCounts=true` adds `counts`: the workspace's entries in all, emails, domains, from the CRM (`customer` and `rule`) and with no reason, whatever the filters.
|
|
4517
|
+
Ordered by id, which follows creation: `sort=createdAt` (the default) is oldest first, `sort=-createdAt` newest first; keep the same `sort` while paging. Optional filters: `type` (`email` or `domain`), `value` (an exact match), `q` (a case-insensitive substring of the value or the reason), `source` (comma-separated `manual`, `own_domain`, `customer`, `rule`) and `hasReason`. `includeTotal=true` adds `pagination.total`, every entry the filters match. `includeCounts=true` adds `counts`: the workspace's entries in all, emails, domains, from the CRM (`customer` and `rule`) and with no reason, whatever the filters. Open to any workspace member.
|
|
4517
4518
|
|
|
4518
4519
|
- API: `GET /v1/blocklist-entries` (a list: `--limit`, `--cursor`, `--all`)
|
|
4519
4520
|
- Generated from the API contract
|
|
@@ -4546,7 +4547,7 @@ kenso blocklist-entries list --all
|
|
|
4546
4547
|
|
|
4547
4548
|
Set or clear why a blocklist entry is blocked.
|
|
4548
4549
|
|
|
4549
|
-
Body `{ "reason": "..." }`, at most 200 characters; `null` or blank clears it. `reason` is required. Requires `
|
|
4550
|
+
Body `{ "reason": "..." }`, at most 200 characters; `null` or blank clears it. `reason` is required. Requires the `workspace_settings` permission. An entry outside the workspace is `not_found`.
|
|
4550
4551
|
|
|
4551
4552
|
- API: `PATCH /v1/blocklist-entries/{entryId}`
|
|
4552
4553
|
- Generated from the API contract
|
|
@@ -4619,7 +4620,7 @@ kenso blocklist-rules delete --rule-id <rule-id>
|
|
|
4619
4620
|
|
|
4620
4621
|
List blocklist rules.
|
|
4621
4622
|
|
|
4622
|
-
Every rule in `position` order (at most 20), each with `stages`, `accountTypes`, `crmLifecycles`, `crmList` (with the `members` and `readAt` of its last read) and `matches`: the accounts its stages (and release window, `releaseAfterDays`) or account types match now (each once), the domains and people (emails) it blocks and the CRM records it matches, enabled or not. The first enabled rule that matches a domain or email gives its entry the reason.
|
|
4623
|
+
Every rule in `position` order (at most 20), each with `stages`, `accountTypes`, `crmLifecycles`, `crmList` (with the `members` and `readAt` of its last read) and `matches`: the accounts its stages (and release window, `releaseAfterDays`) or account types match now (each once), the domains and people (emails) it blocks and the CRM records it matches, enabled or not. The first enabled rule that matches a domain or email gives its entry the reason. Open to any workspace member.
|
|
4623
4624
|
|
|
4624
4625
|
- Beta: needs the `blocklist_rules` feature flag on the workspace.
|
|
4625
4626
|
- API: `GET /v1/blocklist-rules`
|
|
@@ -4638,7 +4639,7 @@ kenso blocklist-rules list
|
|
|
4638
4639
|
|
|
4639
4640
|
Preview what a blocklist rule would block.
|
|
4640
4641
|
|
|
4641
|
-
`stages` is a comma-separated list of up to 20 stage keys from `GET /v1/opportunity-stages`; an unknown or archived key is `400 out_of_range`. `accountTypes` is a comma-separated list of account types (`client`, `lost`, `churned`, `partner`, `competitor`, `investor`, `do_not_contact`; `prospect` or an unknown type is `400 out_of_range`). Send at least one of the two, or a CRM criterion: `crmLifecycles` is a comma-separated list of up to 5 CRM lifecycle stages (`lead`, `prospect`, `opportunity`, `customer`, `churned`) and `crmListId` a contact or company list of the connected CRM (`GET /v1/crm-connections/{connectionId}/lists`, at most 10,000 members, read live now and never stored). A CRM criterion while `blocklist_rules_crm` is off is `400 not_enabled`; with no connected CRM `400 invalid_state`; on a CRM Kenso cannot read lists or lifecycle stages from `400 unsupported`; an unknown or too large list `400 out_of_range`; a CRM that is not reachable or rate limited `503` or `429`. Returns the accounts with a live opportunity in one of the stages or of one of the types (each once), the distinct domains and people (emails) a rule would block, the CRM records it matches (`crmRecords`), how many of the domains and people a blocklist entry already lists (`alreadyBlocked`, any source), up to 10 accounts by id with one of their domains, up to 10 CRM records with the email or domain each blocks (`crmSample`), and what is left out: accounts and CRM companies with no domain, CRM contacts with neither a company domain nor an email (`skipped.noEmail`) and free email domains. Optional `releaseAfterDays` (1-3650) previews a release window: an account matched by stage counts only while one of its deals in the stages closed less than that many days ago or has no close date (a match by type or from the CRM never releases), and `skipped.released` counts the accounts it already let go. Never writes. Requires
|
|
4642
|
+
`stages` is a comma-separated list of up to 20 stage keys from `GET /v1/opportunity-stages`; an unknown or archived key is `400 out_of_range`. `accountTypes` is a comma-separated list of account types (`client`, `lost`, `churned`, `partner`, `competitor`, `investor`, `do_not_contact`; `prospect` or an unknown type is `400 out_of_range`). Send at least one of the two, or a CRM criterion: `crmLifecycles` is a comma-separated list of up to 5 CRM lifecycle stages (`lead`, `prospect`, `opportunity`, `customer`, `churned`) and `crmListId` a contact or company list of the connected CRM (`GET /v1/crm-connections/{connectionId}/lists`, at most 10,000 members, read live now and never stored). A CRM criterion while `blocklist_rules_crm` is off is `400 not_enabled`; with no connected CRM `400 invalid_state`; on a CRM Kenso cannot read lists or lifecycle stages from `400 unsupported`; an unknown or too large list `400 out_of_range`; a CRM that is not reachable or rate limited `503` or `429`. Returns the accounts with a live opportunity in one of the stages or of one of the types (each once), the distinct domains and people (emails) a rule would block, the CRM records it matches (`crmRecords`), how many of the domains and people a blocklist entry already lists (`alreadyBlocked`, any source), up to 10 accounts by id with one of their domains, up to 10 CRM records with the email or domain each blocks (`crmSample`), and what is left out: accounts and CRM companies with no domain, CRM contacts with neither a company domain nor an email (`skipped.noEmail`) and free email domains. Optional `releaseAfterDays` (1-3650) previews a release window: an account matched by stage counts only while one of its deals in the stages closed less than that many days ago or has no close date (a match by type or from the CRM never releases), and `skipped.released` counts the accounts it already let go. Never writes. Requires Accounts view, since it names accounts.
|
|
4642
4643
|
|
|
4643
4644
|
- Beta: needs the `blocklist_rules` feature flag on the workspace.
|
|
4644
4645
|
- API: `GET /v1/blocklist-rules/preview`
|
|
@@ -5153,6 +5154,101 @@ Return the brand of a verified custom host.
|
|
|
5153
5154
|
kenso brands get-by-host
|
|
5154
5155
|
```
|
|
5155
5156
|
|
|
5157
|
+
## browser-runs
|
|
5158
|
+
|
|
5159
|
+
### kenso browser-runs get
|
|
5160
|
+
|
|
5161
|
+
Return one browser run in full.
|
|
5162
|
+
|
|
5163
|
+
The run with its task, identity and inbox, the structured `result`, `quotes` with their URLs, `screenshots` (`url` is the screenshot route), the replay link while it is kept (`replayExpiresAt`), the `submission` (the form URL and the fields sent), the watched domains, the first human reply and its seconds after the submit, and the error of a failed run. A run of another workspace is 404. Requires workflows view.
|
|
5164
|
+
|
|
5165
|
+
- Beta: needs the `browser_steps` and `workflows` feature flag on the workspace.
|
|
5166
|
+
- API: `GET /v1/browser-runs/{browserRunId}`
|
|
5167
|
+
- Generated from the API contract
|
|
5168
|
+
|
|
5169
|
+
| Flag | Type | Required | Description |
|
|
5170
|
+
| --- | --- | --- | --- |
|
|
5171
|
+
| `--browser-run-id` | integer | yes | browserRunId (path, integer) |
|
|
5172
|
+
| `--each` | string | no | Run once per row of a JSONL or CSV file (- for stdin); row keys fill params and body by name. |
|
|
5173
|
+
| `--concurrency` | integer | no | With --each: requests in flight at once (1-16, default 4). |
|
|
5174
|
+
|
|
5175
|
+
```bash
|
|
5176
|
+
kenso browser-runs get --browser-run-id <browser-run-id>
|
|
5177
|
+
```
|
|
5178
|
+
|
|
5179
|
+
### kenso browser-runs list
|
|
5180
|
+
|
|
5181
|
+
List the workspace's browser runs, newest first.
|
|
5182
|
+
|
|
5183
|
+
Filters: `workflowId`, `runId` (the workflow run), `nodeId` (the browser step), `recordType` and `recordId`, `status` (one of queued, awaiting_approval, declined, running, done, confirmed, unconfirmed, blocked, out_of_browser_time, failed). Items carry no quotes, screenshots or submission: read one run for those. `limit` 1 to 200 (default 50); continue with `pagination.nextCursor`. Requires workflows view.
|
|
5184
|
+
|
|
5185
|
+
- Beta: needs the `browser_steps` and `workflows` feature flag on the workspace.
|
|
5186
|
+
- API: `GET /v1/browser-runs` (a list: `--limit`, `--cursor`, `--all`)
|
|
5187
|
+
- Generated from the API contract
|
|
5188
|
+
|
|
5189
|
+
| Flag | Type | Required | Description |
|
|
5190
|
+
| --- | --- | --- | --- |
|
|
5191
|
+
| `--cursor` | string | no | Start at this cursor (the next: hint of a previous page). |
|
|
5192
|
+
| `--limit` | integer | no | 1 to 200, default 50. |
|
|
5193
|
+
| `--node-id` | string | no | The browser step's node id in the workflow. |
|
|
5194
|
+
| `--record-id` | integer | no | recordId (query, integer) |
|
|
5195
|
+
| `--record-type` | string | no | account, person, lead, place or none. |
|
|
5196
|
+
| `--run-id` | integer | no | The workflow run the browser runs belong to. |
|
|
5197
|
+
| `--status` | string | no | One status: queued, awaiting_approval, declined, running, done, confirmed, unconfirmed, blocked, out_of_browser_time, failed. |
|
|
5198
|
+
| `--workflow-id` | integer | no | workflowId (query, integer) |
|
|
5199
|
+
| `--all` | boolean | no | Follow every page and stream all items (NDJSON when piped). |
|
|
5200
|
+
| `--each` | string | no | Run once per row of a JSONL or CSV file (- for stdin); row keys fill params and body by name. |
|
|
5201
|
+
| `--concurrency` | integer | no | With --each: requests in flight at once (1-16, default 4). |
|
|
5202
|
+
|
|
5203
|
+
```bash
|
|
5204
|
+
kenso browser-runs list
|
|
5205
|
+
kenso browser-runs list --all
|
|
5206
|
+
```
|
|
5207
|
+
|
|
5208
|
+
### kenso browser-runs screenshot
|
|
5209
|
+
|
|
5210
|
+
One screenshot of a browser run, as JPEG.
|
|
5211
|
+
|
|
5212
|
+
`n` is 1-based, up to the run's `screenshotCount`. 404 when the run, the index or the file is not there. Cached privately for an hour. Requires workflows view.
|
|
5213
|
+
|
|
5214
|
+
- Beta: needs the `browser_steps` and `workflows` feature flag on the workspace.
|
|
5215
|
+
- API: `GET /v1/browser-runs/{browserRunId}/screenshots/{n}`
|
|
5216
|
+
- Generated from the API contract
|
|
5217
|
+
|
|
5218
|
+
| Flag | Type | Required | Description |
|
|
5219
|
+
| --- | --- | --- | --- |
|
|
5220
|
+
| `--browser-run-id` | integer | yes | browserRunId (path, integer) |
|
|
5221
|
+
| `--n` | integer | yes | n (path, integer) |
|
|
5222
|
+
| `--each` | string | no | Run once per row of a JSONL or CSV file (- for stdin); row keys fill params and body by name. |
|
|
5223
|
+
| `--concurrency` | integer | no | With --each: requests in flight at once (1-16, default 4). |
|
|
5224
|
+
|
|
5225
|
+
```bash
|
|
5226
|
+
kenso browser-runs screenshot --browser-run-id <browser-run-id> --n <n>
|
|
5227
|
+
```
|
|
5228
|
+
|
|
5229
|
+
### kenso browser-runs summary
|
|
5230
|
+
|
|
5231
|
+
Runs by status and reply buckets for one workflow's browser steps.
|
|
5232
|
+
|
|
5233
|
+
Over the browser runs of `workflowId` (one step with `nodeId`) created in [`createdAfter`, `createdBefore`) (default the last 30 days, at most 400 days): `runs`, `byStatus`, `replies` (`withinHour`, `withinDay`, `afterDay` from the first human reply after the submit; `noneBeforeTimeout` submitted runs whose watch closed with no human reply; `watching` still open), credits and browser minutes. Requires workflows view.
|
|
5234
|
+
|
|
5235
|
+
- Beta: needs the `browser_steps` and `workflows` feature flag on the workspace.
|
|
5236
|
+
- API: `GET /v1/browser-runs/summary`
|
|
5237
|
+
- Generated from the API contract
|
|
5238
|
+
|
|
5239
|
+
| Flag | Type | Required | Description |
|
|
5240
|
+
| --- | --- | --- | --- |
|
|
5241
|
+
| `--created-after` | string | no | Inclusive; default 30 days before Ken.Scraper.API.Dtos.BrowserRunSummaryRequest.CreatedBefore. |
|
|
5242
|
+
| `--created-before` | string | no | Exclusive; default now. |
|
|
5243
|
+
| `--node-id` | string | no | One browser step's node id; every browser step of the workflow when absent. |
|
|
5244
|
+
| `--workflow-id` | integer | yes | Required: a request without it fails binding with the canonical 400 on `workflowId`; 0 is refused too. |
|
|
5245
|
+
| `--each` | string | no | Run once per row of a JSONL or CSV file (- for stdin); row keys fill params and body by name. |
|
|
5246
|
+
| `--concurrency` | integer | no | With --each: requests in flight at once (1-16, default 4). |
|
|
5247
|
+
|
|
5248
|
+
```bash
|
|
5249
|
+
kenso browser-runs summary --workflow-id <workflow-id>
|
|
5250
|
+
```
|
|
5251
|
+
|
|
5156
5252
|
## bug-reports
|
|
5157
5253
|
|
|
5158
5254
|
### kenso bug-reports create
|
|
@@ -5214,7 +5310,7 @@ kenso build-events append --build-session-id <build-session-id> --data @body.jso
|
|
|
5214
5310
|
|
|
5215
5311
|
List durable UI events for a build session.
|
|
5216
5312
|
|
|
5217
|
-
Ordered by `seq`. The cursor is the last returned seq. Read-only. Requires
|
|
5313
|
+
Ordered by `seq`. The cursor is the last returned seq. Read-only. Requires Campaigns view.
|
|
5218
5314
|
|
|
5219
5315
|
- API: `GET /v1/build-sessions/{buildSessionId}/events` (a list: `--limit`, `--cursor`, `--all`)
|
|
5220
5316
|
- Generated from the API contract
|
|
@@ -5370,7 +5466,7 @@ kenso build-files search --all
|
|
|
5370
5466
|
|
|
5371
5467
|
Return the workspace's active build session.
|
|
5372
5468
|
|
|
5373
|
-
Optional `campaignId` narrows the lookup. Read-only. Requires
|
|
5469
|
+
Optional `campaignId` narrows the lookup. Read-only. Requires Campaigns view.
|
|
5374
5470
|
|
|
5375
5471
|
- API: `GET /v1/build-sessions/active`
|
|
5376
5472
|
- Generated from the API contract
|
|
@@ -5389,7 +5485,7 @@ kenso build-sessions active
|
|
|
5389
5485
|
|
|
5390
5486
|
Return the latest build session for one campaign.
|
|
5391
5487
|
|
|
5392
|
-
One session, including a completed one. Read-only. Requires
|
|
5488
|
+
One session, including a completed one. Read-only. Requires Campaigns view.
|
|
5393
5489
|
|
|
5394
5490
|
- API: `GET /v1/build-sessions/by-campaign`
|
|
5395
5491
|
- Generated from the API contract
|
|
@@ -5483,7 +5579,7 @@ kenso build-sessions feedback --data @body.json
|
|
|
5483
5579
|
|
|
5484
5580
|
Return one build session.
|
|
5485
5581
|
|
|
5486
|
-
A missing or cross-workspace id is `not_found`. Read-only. Requires
|
|
5582
|
+
A missing or cross-workspace id is `not_found`. Read-only. Requires Campaigns view.
|
|
5487
5583
|
|
|
5488
5584
|
- API: `GET /v1/build-sessions/{buildSessionId}`
|
|
5489
5585
|
- Generated from the API contract
|
|
@@ -5502,7 +5598,7 @@ kenso build-sessions get --build-session-id <build-session-id>
|
|
|
5502
5598
|
|
|
5503
5599
|
List agent memory for the current workspace.
|
|
5504
5600
|
|
|
5505
|
-
Memory ids are not numeric, so this returns the matching rows in one window. Read-only. Requires
|
|
5601
|
+
Memory ids are not numeric, so this returns the matching rows in one window. Read-only. Requires Campaigns view.
|
|
5506
5602
|
|
|
5507
5603
|
- API: `GET /v1/build-sessions/memory`
|
|
5508
5604
|
- Generated from the API contract
|
|
@@ -6045,7 +6141,7 @@ kenso calendars update --calendar-id <calendar-id> --data @body.json
|
|
|
6045
6141
|
|
|
6046
6142
|
List a member's Call queue.
|
|
6047
6143
|
|
|
6048
|
-
Open call tasks that have not expired, assigned to the member, and open call touches (planned, drafted, awaiting approval or failed) on the member's accounts or on accounts with no owner. Each item carries the person or contact's `name`, `title`, `company`, `phone` (the task's, else the person's primary phone, else the contact's), `timeZoneId` and `zoneSource` (account, phone, owner or default), `callableNow` and `opensAt` (when the call can be made: once it is due, inside business hours while Contact limits keep calls to them, and under the calls per person per day limit, else `limitReached` and the next day's window, or local midnight while any time is callable; a snoozed or future call opens at its due time), `reason`, `attempts` and `briefReady`. Callable first, then by `dueAt`, then id. Filters: `assignee` (`me`, the default, or a member id for a workspace admin, else `403`), `due` (`now`, `today` before the end of the local day in the caller's app time zone, else in `timezone`, or `all`, the default). `limit` 1-200 (default 50); `pagination.hasMore` says more exist and there is no cursor. `counts`: `open` and `callableNow` over the whole queue read (at most 500). Requires
|
|
6144
|
+
Open call tasks that have not expired, assigned to the member, and open call touches (planned, drafted, awaiting approval or failed) on the member's accounts or on accounts with no owner. Each item carries the person or contact's `name`, `title`, `company`, `phone` (the task's, else the person's primary phone, else the contact's), `timeZoneId` and `zoneSource` (account, phone, owner or default), `callableNow` and `opensAt` (when the call can be made: once it is due, inside business hours while Contact limits keep calls to them, and under the calls per person per day limit, else `limitReached` and the next day's window, or local midnight while any time is callable; a snoozed or future call opens at its due time), `reason`, `attempts` and `briefReady`. Callable first, then by `dueAt`, then id. Filters: `assignee` (`me`, the default, or a member id for a workspace admin, else `403`), `due` (`now`, `today` before the end of the local day in the caller's app time zone, else in `timezone`, or `all`, the default). `limit` 1-200 (default 50); `pagination.hasMore` says more exist and there is no cursor. `counts`: `open` and `callableNow` over the whole queue read (at most 500). Requires Accounts view.
|
|
6049
6145
|
|
|
6050
6146
|
- Beta: needs the `calls` feature flag on the workspace.
|
|
6051
6147
|
- API: `GET /v1/call-queue`
|
|
@@ -6115,7 +6211,7 @@ kenso call-sequences replace --campaign-id <campaign-id> --data @body.json
|
|
|
6115
6211
|
|
|
6116
6212
|
Create a call task.
|
|
6117
6213
|
|
|
6118
|
-
Body: `personId` or `contactId` (exactly one; a contact's task is also on its person when it has one), `dueAt` (default now, at most 90 days out, else `400 out_of_range`), `title` (1-200), `instructions`, `assigneeMemberId` (default the caller; a member of this workspace, else `400 invalid_member`) and `phone` (any format, stored E.164; a bad number is `400 invalid_phone`; default the person's primary phone when the call is made). The reason is `manual`, `accountId` the person's first account, `expiresAt` a week after `dueAt` (after now for a past `dueAt`). Writes `call.task_created` on the person's timeline. Returns `201`. When the person (else contact) already has an open call task, that task comes back with `200` and `existing: true`, also when another writer wins the race; one past its `expiresAt` is expired instead and a new task created. Under account scope `own`, an open task assigned to someone else is `409 conflict` with detail `call_task_exists` and no task id, and a contact whose person is not on the caller's accounts is `404`. Requires
|
|
6214
|
+
Body: `personId` or `contactId` (exactly one; a contact's task is also on its person when it has one), `dueAt` (default now, at most 90 days out, else `400 out_of_range`), `title` (1-200), `instructions`, `assigneeMemberId` (default the caller; a member of this workspace, else `400 invalid_member`) and `phone` (any format, stored E.164; a bad number is `400 invalid_phone`; default the person's primary phone when the call is made). The reason is `manual`, `accountId` the person's first account, `expiresAt` a week after `dueAt` (after now for a past `dueAt`). Writes `call.task_created` on the person's timeline. Returns `201`. When the person (else contact) already has an open call task, that task comes back with `200` and `existing: true`, also when another writer wins the race; one past its `expiresAt` is expired instead and a new task created. Under account scope `own`, an open task assigned to someone else is `409 conflict` with detail `call_task_exists` and no task id, and a contact whose person is not on the caller's accounts is `404`. Requires Accounts edit.
|
|
6119
6215
|
|
|
6120
6216
|
- Beta: needs the `calls` feature flag on the workspace.
|
|
6121
6217
|
- API: `POST /v1/call-tasks`
|
|
@@ -6144,7 +6240,7 @@ kenso call-tasks create --data @body.json
|
|
|
6144
6240
|
|
|
6145
6241
|
Delete a call task.
|
|
6146
6242
|
|
|
6147
|
-
Soft delete: the task leaves every list and the Call queue. Returns `204`. Requires
|
|
6243
|
+
Soft delete: the task leaves every list and the Call queue. Returns `204`. Requires Accounts edit.
|
|
6148
6244
|
|
|
6149
6245
|
- Beta: needs the `calls` feature flag on the workspace.
|
|
6150
6246
|
- API: `DELETE /v1/call-tasks/{callTaskId}`
|
|
@@ -6164,7 +6260,7 @@ kenso call-tasks delete --call-task-id <call-task-id>
|
|
|
6164
6260
|
|
|
6165
6261
|
Return one call task.
|
|
6166
6262
|
|
|
6167
|
-
A task of another workspace, a deleted one, or another member's under account scope `own` is `404`. Requires
|
|
6263
|
+
A task of another workspace, a deleted one, or another member's under account scope `own` is `404`. Requires Accounts view.
|
|
6168
6264
|
|
|
6169
6265
|
- Beta: needs the `calls` feature flag on the workspace.
|
|
6170
6266
|
- API: `GET /v1/call-tasks/{callTaskId}`
|
|
@@ -6204,7 +6300,7 @@ kenso call-tasks get-brief --call-task-id <call-task-id>
|
|
|
6204
6300
|
|
|
6205
6301
|
List call tasks.
|
|
6206
6302
|
|
|
6207
|
-
Live tasks by `dueAt`, then id. Filters: `assignee` (`me` or a member id; blank is every member, and a member with account scope `own` always gets only their own, so naming another member is `403 permission_denied` with `scope: all`), `status` (open, done, skipped, expired; comma = OR), `due` (`now` due before now, `today` before the end of the local day, overdue included, `overdue` before the local day started), `timezone` (IANA, default UTC, for a caller with no app time zone; the app time zone sets the local day when set), `personId`, `accountId` and `campaignId`. `limit` 1-200 (default 50), `cursor` from `pagination.nextCursor`. Requires
|
|
6303
|
+
Live tasks by `dueAt`, then id. Filters: `assignee` (`me` or a member id; blank is every member, and a member with account scope `own` always gets only their own, so naming another member is `403 permission_denied` with `scope: all`), `status` (open, done, skipped, expired; comma = OR), `due` (`now` due before now, `today` before the end of the local day, overdue included, `overdue` before the local day started), `timezone` (IANA, default UTC, for a caller with no app time zone; the app time zone sets the local day when set), `personId`, `accountId` and `campaignId`. `limit` 1-200 (default 50), `cursor` from `pagination.nextCursor`. Requires Accounts view.
|
|
6208
6304
|
|
|
6209
6305
|
- Beta: needs the `calls` feature flag on the workspace.
|
|
6210
6306
|
- API: `GET /v1/call-tasks` (a list: `--limit`, `--cursor`, `--all`)
|
|
@@ -6234,7 +6330,7 @@ kenso call-tasks list --all
|
|
|
6234
6330
|
|
|
6235
6331
|
Skip an open call task.
|
|
6236
6332
|
|
|
6237
|
-
Body: `reason`, one of `no_phone`, `not_relevant` or `other`. The task becomes `skipped` with `skipReason` and `doneAt`, and leaves the Call queue; `call.task_skipped` goes on the person's timeline. Reopen it with `PATCH``status: open`. A task that is not open is `409 invalid_state`. A task another writer changed while the request ran is `409 conflict` with detail `call_task_changed`: read it again and retry. Requires
|
|
6333
|
+
Body: `reason`, one of `no_phone`, `not_relevant` or `other`. The task becomes `skipped` with `skipReason` and `doneAt`, and leaves the Call queue; `call.task_skipped` goes on the person's timeline. Reopen it with `PATCH``status: open`. A task that is not open is `409 invalid_state`. A task another writer changed while the request ran is `409 conflict` with detail `call_task_changed`: read it again and retry. Requires Accounts edit.
|
|
6238
6334
|
|
|
6239
6335
|
- Beta: needs the `calls` feature flag on the workspace.
|
|
6240
6336
|
- API: `POST /v1/call-tasks/{callTaskId}/skip`
|
|
@@ -6258,7 +6354,7 @@ kenso call-tasks skip --call-task-id <call-task-id> --data @body.json
|
|
|
6258
6354
|
|
|
6259
6355
|
Snooze an open call task.
|
|
6260
6356
|
|
|
6261
|
-
Body, optional: `until` (in the future, at most 90 days out). Without it the task moves to the next day's calling window in its zone (08:00 local the next weekday while Contact limits keep calls to business hours, else a day from now). `expiresAt` moves with it and `snoozeCount` goes up by one. A task that is not open is `409 invalid_state`. A task another writer changed while the request ran is `409 conflict` with detail `call_task_changed`: read it again and retry. Requires
|
|
6357
|
+
Body, optional: `until` (in the future, at most 90 days out). Without it the task moves to the next day's calling window in its zone (08:00 local the next weekday while Contact limits keep calls to business hours, else a day from now). `expiresAt` moves with it and `snoozeCount` goes up by one. A task that is not open is `409 invalid_state`. A task another writer changed while the request ran is `409 conflict` with detail `call_task_changed`: read it again and retry. Requires Accounts edit.
|
|
6262
6358
|
|
|
6263
6359
|
- Beta: needs the `calls` feature flag on the workspace.
|
|
6264
6360
|
- API: `POST /v1/call-tasks/{callTaskId}/snooze`
|
|
@@ -6282,7 +6378,7 @@ kenso call-tasks snooze --call-task-id <call-task-id> --data @body.json
|
|
|
6282
6378
|
|
|
6283
6379
|
Update a call task. Absent fields stay unchanged.
|
|
6284
6380
|
|
|
6285
|
-
Fields of an open task: `dueAt` (at most 90 days out; moves `expiresAt` with it), `title`, `instructions`, `assigneeMemberId` (a member of this workspace, not null) and `phone` (null clears; a bad number is `400 invalid_phone`). `status` can only be `open`: it reopens a skipped or expired task, clears its skip reason and done time and keeps it in the queue for another week; a done task stays done (`409 invalid_state`). When the person (else contact) already has another open task, the reopen is `409 conflict` with detail `call_task_exists` and that task's `callTaskId`; one past its `expiresAt` is expired instead. A task another writer changed while the request ran is `409 conflict` with detail `call_task_changed`: read it again and retry. Skip with `POST /v1/call-tasks/{callTaskId}/skip`. Requires
|
|
6381
|
+
Fields of an open task: `dueAt` (at most 90 days out; moves `expiresAt` with it), `title`, `instructions`, `assigneeMemberId` (a member of this workspace, not null) and `phone` (null clears; a bad number is `400 invalid_phone`). `status` can only be `open`: it reopens a skipped or expired task, clears its skip reason and done time and keeps it in the queue for another week; a done task stays done (`409 invalid_state`). When the person (else contact) already has another open task, the reopen is `409 conflict` with detail `call_task_exists` and that task's `callTaskId`; one past its `expiresAt` is expired instead. A task another writer changed while the request ran is `409 conflict` with detail `call_task_changed`: read it again and retry. Skip with `POST /v1/call-tasks/{callTaskId}/skip`. Requires Accounts edit.
|
|
6286
6382
|
|
|
6287
6383
|
- Beta: needs the `calls` feature flag on the workspace.
|
|
6288
6384
|
- API: `PATCH /v1/call-tasks/{callTaskId}`
|
|
@@ -6456,7 +6552,7 @@ kenso calling numbers-buy --data @body.json
|
|
|
6456
6552
|
|
|
6457
6553
|
List the workspace's phone numbers.
|
|
6458
6554
|
|
|
6459
|
-
Every number not released, newest first, at most five. `unpaid` is true when its monthly credits could not be charged.
|
|
6555
|
+
Every number not released, newest first, at most five. `unpaid` is true when its monthly credits could not be charged. Open to any workspace member.
|
|
6460
6556
|
|
|
6461
6557
|
- Beta: needs the `calling` feature flag on the workspace.
|
|
6462
6558
|
- API: `GET /v1/calling/numbers`
|
|
@@ -6518,7 +6614,7 @@ kenso calling numbers-update --number-id <number-id> --data @body.json
|
|
|
6518
6614
|
|
|
6519
6615
|
Return what a call to a number costs.
|
|
6520
6616
|
|
|
6521
|
-
`to` is the number to call. `millicreditsPerMinute` is the destination rate plus the rep's leg, and `recordingMillicreditsPerMinute` is added when the call is recorded. A destination Kenso has no price for yet is `priced: false` with null rates; a value that is not a phone number is 400 `invalid_phone`.
|
|
6617
|
+
`to` is the number to call. `millicreditsPerMinute` is the destination rate plus the rep's leg, and `recordingMillicreditsPerMinute` is added when the call is recorded. A destination Kenso has no price for yet is `priced: false` with null rates; a value that is not a phone number is 400 `invalid_phone`. Open to any workspace member.
|
|
6522
6618
|
|
|
6523
6619
|
- Beta: needs the `calling` feature flag on the workspace.
|
|
6524
6620
|
- API: `GET /v1/calling/rates`
|
|
@@ -6538,7 +6634,7 @@ kenso calling rates-get
|
|
|
6538
6634
|
|
|
6539
6635
|
Return the workspace's calling settings.
|
|
6540
6636
|
|
|
6541
|
-
A workspace that never saved them gets the defaults and `updatedAt` null.
|
|
6637
|
+
A workspace that never saved them gets the defaults and `updatedAt` null. Open to any workspace member.
|
|
6542
6638
|
|
|
6543
6639
|
- Beta: needs the `calling` feature flag on the workspace.
|
|
6544
6640
|
- API: `GET /v1/calling/settings`
|
|
@@ -6579,7 +6675,7 @@ kenso calling settings-update --data @body.json
|
|
|
6579
6675
|
|
|
6580
6676
|
Return the workspace's monthly calling spend limit.
|
|
6581
6677
|
|
|
6582
|
-
`monthlyLimitMillicredits` null is no limit; a workspace that never set it reads 2,000,000 (2,000 credits) with `isDefault: true`. `spentThisMonthMillicredits` is call minutes and recordings charged this UTC calendar month plus open call holds, the same spend the cap counts; number fees are not in it. Separate from `/v1/spend-limits`.
|
|
6678
|
+
`monthlyLimitMillicredits` null is no limit; a workspace that never set it reads 2,000,000 (2,000 credits) with `isDefault: true`. `spentThisMonthMillicredits` is call minutes and recordings charged this UTC calendar month plus open call holds, the same spend the cap counts; number fees are not in it. Separate from `/v1/spend-limits`. Open to any workspace member.
|
|
6583
6679
|
|
|
6584
6680
|
- Beta: needs the `calling` feature flag on the workspace.
|
|
6585
6681
|
- API: `GET /v1/calling/spend-limit`
|
|
@@ -6682,7 +6778,7 @@ kenso calling voicemails-delete --voicemail-id <voicemail-id>
|
|
|
6682
6778
|
|
|
6683
6779
|
List your voicemail greetings.
|
|
6684
6780
|
|
|
6685
|
-
Your live greetings, oldest first: the first is the one an `auto` drop plays. `audioUrl` is a 5-minute link to listen to it, absent while Kenso's audio store is not set up.
|
|
6781
|
+
Your live greetings, oldest first: the first is the one an `auto` drop plays. `audioUrl` is a 5-minute link to listen to it, absent while Kenso's audio store is not set up. Open to any workspace member.
|
|
6686
6782
|
|
|
6687
6783
|
- Beta: needs the `calling` feature flag on the workspace.
|
|
6688
6784
|
- API: `GET /v1/calling/voicemails`
|
|
@@ -6703,7 +6799,7 @@ kenso calling voicemails-list
|
|
|
6703
6799
|
|
|
6704
6800
|
Log a call.
|
|
6705
6801
|
|
|
6706
|
-
Body: `personId`, `contactId` or `phone` (a phone no person or contact holds is `400 person_not_found`), `disposition` (required), `direction`, `startedAt` (default now), `endedAt` or `durationSeconds`, `notes`, `nextStep`, `followUpAt`, `callTaskId` or `touchId`, `recordingUrl` (https), `externalId` and `askedNotToBeCalled`. An API key logs source `api`, anyone else `manual`; the caller is the call's member. `askedNotToBeCalled: true` opts the person out of calls before the call is written (a call with no person is `400`; if the opt-out fails, nothing is logged). A wrong_number disposition never opts out. The disposition closes or retries the call task, completes the touch, and moves the lead (connected: working; meeting_booked: qualified, the account to meeting_booked and the campaign stopped; not_interested: disqualified and the campaign stopped; wrong_number: the number marked invalid and a phone find queued). `followUpAt` queues a follow-up call task. Writes `call.logged` on the person's timeline. Returns `201`; the same `externalId` from the same caller updates that call and returns `200`. Requires
|
|
6802
|
+
Body: `personId`, `contactId` or `phone` (a phone no person or contact holds is `400 person_not_found`), `disposition` (required), `direction`, `startedAt` (default now), `endedAt` or `durationSeconds`, `notes`, `nextStep`, `followUpAt`, `callTaskId` or `touchId`, `recordingUrl` (https), `externalId` and `askedNotToBeCalled`. An API key logs source `api`, anyone else `manual`; the caller is the call's member. `askedNotToBeCalled: true` opts the person out of calls before the call is written (a call with no person is `400`; if the opt-out fails, nothing is logged). A wrong_number disposition never opts out. The disposition closes or retries the call task, completes the touch, and moves the lead (connected: working; meeting_booked: qualified, the account to meeting_booked and the campaign stopped; not_interested: disqualified and the campaign stopped; wrong_number: the number marked invalid and a phone find queued). `followUpAt` queues a follow-up call task. Writes `call.logged` on the person's timeline. Returns `201`; the same `externalId` from the same caller updates that call and returns `200`. Requires Accounts edit.
|
|
6707
6803
|
|
|
6708
6804
|
- Beta: needs the `calls` feature flag on the workspace.
|
|
6709
6805
|
- API: `POST /v1/calls`
|
|
@@ -6742,7 +6838,7 @@ kenso calls create --data @body.json
|
|
|
6742
6838
|
|
|
6743
6839
|
Dial a call task, a call touch, a person or a number.
|
|
6744
6840
|
|
|
6745
|
-
Body: one of `callTaskId`, `touchId` (an account touch on the call channel; its stakeholder's person is called), `personId` or `phone`, and `force`. The number is the task's, else the person's phone, else the task contact's. A person who asked not to be called is `409 opted_out`, and `force` does not override it. Outside the person's calling hours (the workspace's business hours in their zone) it is `409 outside_calling_hours` with `opensAt` in the error detail; at the workspace's calls per person per day it is `409 limit_reached` unless `force` is true. A connected dialer the caller is linked on places the call (`status: dialing`) and Kenso logs it at once: `callId`, with the task or touch it works and no disposition. `PATCH /v1/calls/{callId}` saves its outcome (closing the task or completing the touch) and the dialer's events fill it in, so one dial is one call. Otherwise `status: tel` with `telHref` and no call is written. Kenso with no number for the person is `409 no_phone`. Requires
|
|
6841
|
+
Body: one of `callTaskId`, `touchId` (an account touch on the call channel; its stakeholder's person is called), `personId` or `phone`, and `force`. The number is the task's, else the person's phone, else the task contact's. A person who asked not to be called is `409 opted_out`, and `force` does not override it. Outside the person's calling hours (the workspace's business hours in their zone) it is `409 outside_calling_hours` with `opensAt` in the error detail; at the workspace's calls per person per day it is `409 limit_reached` unless `force` is true. A connected dialer the caller is linked on places the call (`status: dialing`) and Kenso logs it at once: `callId`, with the task or touch it works and no disposition. `PATCH /v1/calls/{callId}` saves its outcome (closing the task or completing the touch) and the dialer's events fill it in, so one dial is one call. Otherwise `status: tel` with `telHref` and no call is written. Kenso with no number for the person is `409 no_phone`. Requires Accounts edit.
|
|
6746
6842
|
|
|
6747
6843
|
- Beta: needs the `calls` feature flag on the workspace.
|
|
6748
6844
|
- API: `POST /v1/calls/dial`
|
|
@@ -6770,7 +6866,7 @@ kenso calls dial --data @body.json
|
|
|
6770
6866
|
|
|
6771
6867
|
Get a call.
|
|
6772
6868
|
|
|
6773
|
-
The call with its transcript. Another workspace's or a deleted call is 404. Requires
|
|
6869
|
+
The call with its transcript. Another workspace's or a deleted call is 404. Requires Accounts view.
|
|
6774
6870
|
|
|
6775
6871
|
- Beta: needs the `calls` feature flag on the workspace.
|
|
6776
6872
|
- API: `GET /v1/calls/{callId}`
|
|
@@ -6790,7 +6886,7 @@ kenso calls get --call-id <call-id>
|
|
|
6790
6886
|
|
|
6791
6887
|
List calls.
|
|
6792
6888
|
|
|
6793
|
-
Live calls, newest first (`startedAt`, then id). Filters: `personId`, `accountId`, `memberId` (who made or took the call), `campaignId`, `from` (started at or after) and `to` (started before), `disposition` (comma = OR). `limit` 1-200 (default 50), `cursor` from `pagination.nextCursor`. The list leaves out transcripts. Requires
|
|
6889
|
+
Live calls, newest first (`startedAt`, then id). Filters: `personId`, `accountId`, `memberId` (who made or took the call), `campaignId`, `from` (started at or after) and `to` (started before), `disposition` (comma = OR). `limit` 1-200 (default 50), `cursor` from `pagination.nextCursor`. The list leaves out transcripts. Requires Accounts view.
|
|
6794
6890
|
|
|
6795
6891
|
- Beta: needs the `calls` feature flag on the workspace.
|
|
6796
6892
|
- API: `GET /v1/calls` (a list: `--limit`, `--cursor`, `--all`)
|
|
@@ -6820,7 +6916,7 @@ kenso calls list --all
|
|
|
6820
6916
|
|
|
6821
6917
|
Open a call's recording.
|
|
6822
6918
|
|
|
6823
|
-
Redirects (302) to the recording: a fresh link from the dialer that logged the call while it is still connected, else the https link the call was logged with. No recording is 404. Requires
|
|
6919
|
+
Redirects (302) to the recording: a fresh link from the dialer that logged the call while it is still connected, else the https link the call was logged with. No recording is 404. Requires Accounts view.
|
|
6824
6920
|
|
|
6825
6921
|
- Beta: needs the `calls` feature flag on the workspace.
|
|
6826
6922
|
- API: `GET /v1/calls/{callId}/recording`
|
|
@@ -6840,7 +6936,7 @@ kenso calls recording --call-id <call-id>
|
|
|
6840
6936
|
|
|
6841
6937
|
Update a call.
|
|
6842
6938
|
|
|
6843
|
-
Body: `disposition` (cannot be null), `notes`, `nextStep`, `followUpAt`; absent fields stay, null clears. The first disposition a call gets runs its effects as on create; changing it later writes `call.updated` only. A new `followUpAt` queues a follow-up call task. `askedNotToBeCalled: true` opts the call's person out of calls (a call with no person is `400`). Requires
|
|
6939
|
+
Body: `disposition` (cannot be null), `notes`, `nextStep`, `followUpAt`; absent fields stay, null clears. The first disposition a call gets runs its effects as on create; changing it later writes `call.updated` only. A new `followUpAt` queues a follow-up call task. `askedNotToBeCalled: true` opts the call's person out of calls (a call with no person is `400`). Requires Accounts edit.
|
|
6844
6940
|
|
|
6845
6941
|
- Beta: needs the `calls` feature flag on the workspace.
|
|
6846
6942
|
- API: `PATCH /v1/calls/{callId}`
|
|
@@ -7578,7 +7674,7 @@ kenso campaign-video-variables update --campaign-id <campaign-id> --variable-key
|
|
|
7578
7674
|
|
|
7579
7675
|
Archive a campaign.
|
|
7580
7676
|
|
|
7581
|
-
Idempotent for an already-archived campaign. A campaign that is still sending returns `409 invalid_state`. Requires
|
|
7677
|
+
Idempotent for an already-archived campaign. A campaign that is still sending returns `409 invalid_state`. Requires Campaigns edit.
|
|
7582
7678
|
|
|
7583
7679
|
- API: `POST /v1/campaigns/{campaignId}/archive`
|
|
7584
7680
|
- Generated from the API contract
|
|
@@ -7682,7 +7778,7 @@ kenso campaigns asset-template-put --campaign-id <campaign-id> --data @body.json
|
|
|
7682
7778
|
|
|
7683
7779
|
Create a campaign in the current workspace.
|
|
7684
7780
|
|
|
7685
|
-
Returns `201` and `Location`. Requires
|
|
7781
|
+
Returns `201` and `Location`. Requires Campaigns edit. Reserves the `campaignCreate` abuse quota. A sales campaign starts with `stopCompanyOnReply` on. Optional `kind` is `sales` (default) or `recruiting`. A recruiting campaign needs the `recruiting` flag for the workspace, else `400 validation_failed` with detail code `feature_disabled`; it starts with `stopCompanyOnReply`, `groupSameCompanySends` and same-company Cc off, and as a Draft, so its AI build can start. Optional `roleId` names a live role of the workspace (else `404 not_found`) and is only for a recruiting campaign (else `400` with detail code `not_recruiting`).
|
|
7686
7782
|
|
|
7687
7783
|
- API: `POST /v1/campaigns`
|
|
7688
7784
|
- Generated from the API contract
|
|
@@ -7707,7 +7803,7 @@ kenso campaigns create --data @body.json
|
|
|
7707
7803
|
|
|
7708
7804
|
Queue lead enrichment for a campaign.
|
|
7709
7805
|
|
|
7710
|
-
Replaces the legacy campaign enrichment trigger. The request finishes when Search accepts the batches and returns an `enrichment` job. `minConfidence` defaults to 0.5. Requires
|
|
7806
|
+
Replaces the legacy campaign enrichment trigger. The request finishes when Search accepts the batches and returns an `enrichment` job. `minConfidence` defaults to 0.5. Requires Campaigns edit. A campaign outside the workspace is `not_found` before the run.
|
|
7711
7807
|
|
|
7712
7808
|
- API: `POST /v1/campaigns/{campaignId}/enrichment-runs`
|
|
7713
7809
|
- Generated from the API contract
|
|
@@ -7730,7 +7826,7 @@ kenso campaigns create-enrichment-run --campaign-id <campaign-id> --data @body.j
|
|
|
7730
7826
|
|
|
7731
7827
|
Soft-delete a campaign.
|
|
7732
7828
|
|
|
7733
|
-
Requires
|
|
7829
|
+
Requires Campaigns edit. Returns `204`.
|
|
7734
7830
|
|
|
7735
7831
|
- API: `DELETE /v1/campaigns/{campaignId}`
|
|
7736
7832
|
- Generated from the API contract
|
|
@@ -7749,7 +7845,7 @@ kenso campaigns delete --campaign-id <campaign-id>
|
|
|
7749
7845
|
|
|
7750
7846
|
Duplicate a campaign inside the current workspace.
|
|
7751
7847
|
|
|
7752
|
-
`includeContacts` copies contacts. The copy stays in this workspace. Returns `201` and `Location`. Requires
|
|
7848
|
+
`includeContacts` copies contacts. The copy stays in this workspace. Returns `201` and `Location`. Requires Campaigns edit. Reserves the campaign-duplicate abuse quota.
|
|
7753
7849
|
|
|
7754
7850
|
- API: `POST /v1/campaigns/{campaignId}/duplicate`
|
|
7755
7851
|
- Generated from the API contract
|
|
@@ -7774,7 +7870,7 @@ kenso campaigns duplicate --campaign-id <campaign-id> --data @body.json
|
|
|
7774
7870
|
|
|
7775
7871
|
Return one campaign in the current workspace.
|
|
7776
7872
|
|
|
7777
|
-
A missing or cross-workspace id is `not_found`. Read-only. Requires
|
|
7873
|
+
A missing or cross-workspace id is `not_found`. Read-only. Requires Campaigns view.
|
|
7778
7874
|
|
|
7779
7875
|
- API: `GET /v1/campaigns/{campaignId}`
|
|
7780
7876
|
- Generated from the API contract
|
|
@@ -7833,7 +7929,7 @@ kenso campaigns get-autopilot --campaign-id <campaign-id>
|
|
|
7833
7929
|
|
|
7834
7930
|
Report whether a campaign can launch and how long sending should take.
|
|
7835
7931
|
|
|
7836
|
-
Replaces `GET /v1/campaigns/{id}/can-launch` and `GET /v1/campaigns/{id}/sending-estimate`. A campaign outside the workspace is `not_found` before either read. Requires
|
|
7932
|
+
Replaces `GET /v1/campaigns/{id}/can-launch` and `GET /v1/campaigns/{id}/sending-estimate`. A campaign outside the workspace is `not_found` before either read. Requires Campaigns view. `warnings` never change `canLaunch`; `localization_incomplete` (one per enabled language of an `auto` campaign) names the steps with no approved translation and whether those contacts get the source text or are held. `approval_required` means the client was asked and launch answers 409 `approval_required` until they approve; its `kinds` lists what waits (`copy`, `lead_list`, ...). The warning `approval_will_be_requested` names what nobody asked about yet: launch asks the client, then refuses until they approve.
|
|
7837
7933
|
|
|
7838
7934
|
- API: `GET /v1/campaigns/{campaignId}/launch-readiness`
|
|
7839
7935
|
- Generated from the API contract
|
|
@@ -7852,7 +7948,7 @@ kenso campaigns get-launch-readiness --campaign-id <campaign-id>
|
|
|
7852
7948
|
|
|
7853
7949
|
Read a campaign's LinkedIn settings.
|
|
7854
7950
|
|
|
7855
|
-
Replaces `GET /v1/campaigns/{id}/linkedin-config`. A campaign outside the workspace is `not_found`. Requires
|
|
7951
|
+
Replaces `GET /v1/campaigns/{id}/linkedin-config`. A campaign outside the workspace is `not_found`. Requires Campaigns view.
|
|
7856
7952
|
|
|
7857
7953
|
- API: `GET /v1/campaigns/{campaignId}/linkedin-settings`
|
|
7858
7954
|
- Generated from the API contract
|
|
@@ -7871,7 +7967,7 @@ kenso campaigns get-linkedin-settings --campaign-id <campaign-id>
|
|
|
7871
7967
|
|
|
7872
7968
|
Count a campaign's contacts by email security gateway and mailbox host.
|
|
7873
7969
|
|
|
7874
|
-
Each live contact is judged by its first Safe or Verified email, the one the lead list shows. `gateways` lists every active security gateway and `mailboxProviders` every active mailbox host and forwarder, 0 included, most contacts first. `pendingCount` counts contacts whose domain is not checked for a gateway yet. Counts cover at most 100,000 contacts (`isPartial`). Read-only. A campaign outside the workspace, or a workspace without the `security_gateways` feature, is `not_found`. Requires
|
|
7970
|
+
Each live contact is judged by its first Safe or Verified email, the one the lead list shows. `gateways` lists every active security gateway and `mailboxProviders` every active mailbox host and forwarder, 0 included, most contacts first. `pendingCount` counts contacts whose domain is not checked for a gateway yet. Counts cover at most 100,000 contacts (`isPartial`). Read-only. A campaign outside the workspace, or a workspace without the `security_gateways` feature, is `not_found`. Requires Campaigns view.
|
|
7875
7971
|
|
|
7876
7972
|
- Beta: needs the `security_gateways` feature flag on the workspace.
|
|
7877
7973
|
- API: `GET /v1/campaigns/{campaignId}/mail-providers`
|
|
@@ -7911,7 +8007,7 @@ kenso campaigns get-processing-status --campaign-id <campaign-id>
|
|
|
7911
8007
|
|
|
7912
8008
|
Read whether lead scoring is enabled for a campaign.
|
|
7913
8009
|
|
|
7914
|
-
Replaces `POST /v1/campaigns/{id}/scoring` for reads. A campaign outside the workspace is `not_found`. Requires
|
|
8010
|
+
Replaces `POST /v1/campaigns/{id}/scoring` for reads. A campaign outside the workspace is `not_found`. Requires Campaigns view.
|
|
7915
8011
|
|
|
7916
8012
|
- API: `GET /v1/campaigns/{campaignId}/scoring`
|
|
7917
8013
|
- Generated from the API contract
|
|
@@ -7930,7 +8026,7 @@ kenso campaigns get-scoring --campaign-id <campaign-id>
|
|
|
7930
8026
|
|
|
7931
8027
|
Return a campaign's sender routing.
|
|
7932
8028
|
|
|
7933
|
-
DEV-5225. `allInboxes` is the campaign's inbox mode. Each rule sends the first email to prospects on its mailbox provider or security gateway only from its domains and inboxes; a gateway rule wins over a mailbox provider rule, and prospects no rule matches go from the inboxes no rule claims (`everyoneElse`). Per rule and for Everyone else: the campaign's inboxes that can send now (Kenso-sendable, not paused), their summed daily limits, and the leads that can still get an email and match now (at most 100,000 leads read; a lead whose provider is still being detected is in no group). `warnings`: `rule_no_inbox`, `everyone_else_no_inbox`, `rule_slow` (over 5 days at the rule's capacity). Read-only. Needs the workspace's `sender_routing` flag, else `400 validation_failed` with detail code `feature_disabled`. Requires
|
|
8029
|
+
DEV-5225. `allInboxes` is the campaign's inbox mode. Each rule sends the first email to prospects on its mailbox provider or security gateway only from its domains and inboxes; a gateway rule wins over a mailbox provider rule, and prospects no rule matches go from the inboxes no rule claims (`everyoneElse`). Per rule and for Everyone else: the campaign's inboxes that can send now (Kenso-sendable, not paused), their summed daily limits, and the leads that can still get an email and match now (at most 100,000 leads read; a lead whose provider is still being detected is in no group). `warnings`: `rule_no_inbox`, `everyone_else_no_inbox`, `rule_slow` (over 5 days at the rule's capacity). Read-only. Needs the workspace's `sender_routing` flag, else `400 validation_failed` with detail code `feature_disabled`. Requires Campaigns view. A campaign outside the workspace is `not_found`.
|
|
7934
8030
|
|
|
7935
8031
|
- API: `GET /v1/campaigns/{campaignId}/sender-routing`
|
|
7936
8032
|
- Generated from the API contract
|
|
@@ -7949,7 +8045,7 @@ kenso campaigns get-sender-routing --campaign-id <campaign-id>
|
|
|
7949
8045
|
|
|
7950
8046
|
Return one campaign's weekly report.
|
|
7951
8047
|
|
|
7952
|
-
`weekOf` is any date (`YYYY-MM-DD`, from 2000-01-01 to one year from today) in the wanted Monday-to-Sunday week. `timeZone` is an IANA name; without it the campaign's sending time zone is used, else UTC. The week's dates are picked in that time zone; its numbers and `changed` are counted on those UTC days, like the Analytics tab. Without `weekOf` the report covers the latest week that has ended both there and in UTC. `week` and `toDate` are email counts from campaign performance. `toDate` and `segments` run from the campaign's creation (at most 366 days back) to the end of the week. `changed` and `next` are sentences built from data, not AI. `next` is as of the request, in the campaign's sending time zone, and is empty for a week older than the default week. A missing or cross-workspace campaign is `not_found`. Read-only. Requires
|
|
8048
|
+
`weekOf` is any date (`YYYY-MM-DD`, from 2000-01-01 to one year from today) in the wanted Monday-to-Sunday week. `timeZone` is an IANA name; without it the campaign's sending time zone is used, else UTC. The week's dates are picked in that time zone; its numbers and `changed` are counted on those UTC days, like the Analytics tab. Without `weekOf` the report covers the latest week that has ended both there and in UTC. `week` and `toDate` are email counts from campaign performance. `toDate` and `segments` run from the campaign's creation (at most 366 days back) to the end of the week. `changed` and `next` are sentences built from data, not AI. `next` is as of the request, in the campaign's sending time zone, and is empty for a week older than the default week. A missing or cross-workspace campaign is `not_found`. Read-only. Requires Campaigns view.
|
|
7953
8049
|
|
|
7954
8050
|
- API: `GET /v1/campaigns/{campaignId}/weekly-report`
|
|
7955
8051
|
- Generated from the API contract
|
|
@@ -7970,7 +8066,7 @@ kenso campaigns get-weekly-report --campaign-id <campaign-id>
|
|
|
7970
8066
|
|
|
7971
8067
|
Report whether a campaign's workflows can start.
|
|
7972
8068
|
|
|
7973
|
-
Replaces `startWorkflowReadiness` on the legacy `GET /v1/campaigns/{id}`. Runs the same checks that gate starting enrichment, verification, and AI workflows (imported contacts or an active signal, contact limit, name, schedule, email sequence, AI variables) and returns each one with `isPassed`. Sending launch readiness is `GET .../launch-readiness`. A campaign outside the workspace is `not_found`. Read-only. Requires
|
|
8069
|
+
Replaces `startWorkflowReadiness` on the legacy `GET /v1/campaigns/{id}`. Runs the same checks that gate starting enrichment, verification, and AI workflows (imported contacts or an active signal, contact limit, name, schedule, email sequence, AI variables) and returns each one with `isPassed`. Sending launch readiness is `GET .../launch-readiness`. A campaign outside the workspace is `not_found`. Read-only. Requires Campaigns view.
|
|
7974
8070
|
|
|
7975
8071
|
- API: `GET /v1/campaigns/{campaignId}/workflow-readiness`
|
|
7976
8072
|
- Generated from the API contract
|
|
@@ -7989,7 +8085,7 @@ kenso campaigns get-workflow-readiness --campaign-id <campaign-id>
|
|
|
7989
8085
|
|
|
7990
8086
|
Launch sending for a campaign.
|
|
7991
8087
|
|
|
7992
|
-
Requires `
|
|
8088
|
+
Requires Campaigns edit and the `launch` permission. Returns the campaign after the launch command confirms. While the workspace's data is scheduled for deletion or being deleted, returns `409 invalid_state`.
|
|
7993
8089
|
|
|
7994
8090
|
- API: `POST /v1/campaigns/{campaignId}/launch`
|
|
7995
8091
|
- Generated from the API contract
|
|
@@ -8008,7 +8104,7 @@ kenso campaigns launch --campaign-id <campaign-id>
|
|
|
8008
8104
|
|
|
8009
8105
|
List campaigns in the current workspace.
|
|
8010
8106
|
|
|
8011
|
-
Includes archived campaigns and excludes approval-test drafts. Optional `status` is a comma-separated OR filter. `q` is a case-insensitive substring of the name, or of the owner's first name, last name, full name, or email. Optional `kind` is `sales` or `recruiting`. Each item carries `leadCount`, from one cached count of the workspace. It usually lags new or removed leads by under 15 minutes; on a very large workspace the first list after a quiet period can show an older count, which the next list corrects. A campaign that count has not seen is counted live, and a single-campaign read (`GET /v1/campaigns/{campaignId}`) counts live for a current number. `leadCount` is omitted when that count does not finish in time on a very large workspace. Each item carries `linkedInOnly`, true for a LinkedIn-only campaign, read once for the page. It is only on this list: it is omitted on a single-campaign read and when the read fails. Ordered by id. Read-only. Requires
|
|
8107
|
+
Includes archived campaigns and excludes approval-test drafts. Optional `status` is a comma-separated OR filter. `q` is a case-insensitive substring of the name, or of the owner's first name, last name, full name, or email. Optional `kind` is `sales` or `recruiting`. Each item carries `leadCount`, from one cached count of the workspace. It usually lags new or removed leads by under 15 minutes; on a very large workspace the first list after a quiet period can show an older count, which the next list corrects. A campaign that count has not seen is counted live, and a single-campaign read (`GET /v1/campaigns/{campaignId}`) counts live for a current number. `leadCount` is omitted when that count does not finish in time on a very large workspace. Each item carries `linkedInOnly`, true for a LinkedIn-only campaign, read once for the page. It is only on this list: it is omitted on a single-campaign read and when the read fails. Ordered by id. Read-only. Requires Campaigns view.
|
|
8012
8108
|
|
|
8013
8109
|
- API: `GET /v1/campaigns` (a list: `--limit`, `--cursor`, `--all`)
|
|
8014
8110
|
- Generated from the API contract
|
|
@@ -8033,7 +8129,7 @@ kenso campaigns list --all
|
|
|
8033
8129
|
|
|
8034
8130
|
List the AI workflows attached to a campaign.
|
|
8035
8131
|
|
|
8036
|
-
Ids: 1 qualification, 2 personalization, 3 rewriting, 4 segmentation, 6 scoring, 8 line check. Read-only. Requires
|
|
8132
|
+
Ids: 1 qualification, 2 personalization, 3 rewriting, 4 segmentation, 6 scoring, 8 line check. Read-only. Requires Campaigns view. A campaign outside the workspace is `not_found`.
|
|
8037
8133
|
|
|
8038
8134
|
- API: `GET /v1/campaigns/{campaignId}/ai-workflows`
|
|
8039
8135
|
- Generated from the API contract
|
|
@@ -8052,7 +8148,7 @@ kenso campaigns list-ai-workflows --campaign-id <campaign-id>
|
|
|
8052
8148
|
|
|
8053
8149
|
List inboxes assigned to a campaign.
|
|
8054
8150
|
|
|
8055
|
-
Requires
|
|
8151
|
+
Requires Campaigns view. A campaign outside the workspace is `not_found`.
|
|
8056
8152
|
|
|
8057
8153
|
- API: `GET /v1/campaigns/{campaignId}/inboxes`
|
|
8058
8154
|
- Generated from the API contract
|
|
@@ -8071,7 +8167,7 @@ kenso campaigns list-inboxes --campaign-id <campaign-id>
|
|
|
8071
8167
|
|
|
8072
8168
|
List LinkedIn accounts assigned to a campaign.
|
|
8073
8169
|
|
|
8074
|
-
Requires
|
|
8170
|
+
Requires Campaigns view. A campaign outside the workspace is `not_found`.
|
|
8075
8171
|
|
|
8076
8172
|
- API: `GET /v1/campaigns/{campaignId}/linkedin-accounts`
|
|
8077
8173
|
- Generated from the API contract
|
|
@@ -8090,7 +8186,7 @@ kenso campaigns list-linkedin-accounts --campaign-id <campaign-id>
|
|
|
8090
8186
|
|
|
8091
8187
|
Count a campaign's leads by mailbox provider and security gateway.
|
|
8092
8188
|
|
|
8093
|
-
DEV-5225. Every active mailbox provider and security gateway with the campaign's leads behind it (0 included), most leads first: the leads that can still get an email, by the domain of the address they are sent to. A lead counts once under its mailbox provider and once under its security gateway. `pendingCount`: provider still being detected. `noProviderCount`: no listed provider. Counts cover at most 100,000 leads (`isPartial`). Read-only. Needs the `sender_routing` flag (`feature_disabled`). Requires
|
|
8189
|
+
DEV-5225. Every active mailbox provider and security gateway with the campaign's leads behind it (0 included), most leads first: the leads that can still get an email, by the domain of the address they are sent to. A lead counts once under its mailbox provider and once under its security gateway. `pendingCount`: provider still being detected. `noProviderCount`: no listed provider. Counts cover at most 100,000 leads (`isPartial`). Read-only. Needs the `sender_routing` flag (`feature_disabled`). Requires Campaigns view. A campaign outside the workspace is `not_found`.
|
|
8094
8190
|
|
|
8095
8191
|
- API: `GET /v1/campaigns/{campaignId}/recipient-providers`
|
|
8096
8192
|
- Generated from the API contract
|
|
@@ -8109,7 +8205,7 @@ kenso campaigns list-recipient-providers --campaign-id <campaign-id>
|
|
|
8109
8205
|
|
|
8110
8206
|
Pause sending, processing, and AI workflows together.
|
|
8111
8207
|
|
|
8112
|
-
Idempotent. A campaign that is already paused returns `200` with the unchanged resource. A subsystem that is not running is left as it is. If any subsystem fails, the action returns that error and the caller can retry. A campaign that is still launching returns `409 invalid_state`. Requires `
|
|
8208
|
+
Idempotent. A campaign that is already paused returns `200` with the unchanged resource. A subsystem that is not running is left as it is. If any subsystem fails, the action returns that error and the caller can retry. A campaign that is still launching returns `409 invalid_state`. Requires Campaigns edit and the `launch` permission.
|
|
8113
8209
|
|
|
8114
8210
|
- API: `POST /v1/campaigns/{campaignId}/pause`
|
|
8115
8211
|
- Generated from the API contract
|
|
@@ -8128,7 +8224,7 @@ kenso campaigns pause --campaign-id <campaign-id>
|
|
|
8128
8224
|
|
|
8129
8225
|
Replace the AI workflows attached to a campaign.
|
|
8130
8226
|
|
|
8131
|
-
Full replace: send every workflow id the campaign should run in `aiWorkflowIds`. Ids not listed are detached, and an empty list detaches all of them. Read the current set first to add one workflow. Ids: 1 qualification, 2 personalization, 3 rewriting, 4 segmentation, 6 scoring, 8 line check. Rewriting runs only when the campaign has rewriting prompts. Line check (8) grades personalization lines before they are saved and holds a contact whose lines fail; a campaign gets it with personalization by default, and detaching it is the opt-out. This route does not add it: keep 8 in the list to keep it on. While the campaign is scheduled, launching, or sending, 1, 2, and 4 must stay as they are and 3 may only be added; any other change to them is `invalid_state` (409) because they gate which contacts may send, so pause first. 6 and 8 can change at any time. No other campaign field changes. Requires
|
|
8227
|
+
Full replace: send every workflow id the campaign should run in `aiWorkflowIds`. Ids not listed are detached, and an empty list detaches all of them. Read the current set first to add one workflow. Ids: 1 qualification, 2 personalization, 3 rewriting, 4 segmentation, 6 scoring, 8 line check. Rewriting runs only when the campaign has rewriting prompts. Line check (8) grades personalization lines before they are saved and holds a contact whose lines fail; a campaign gets it with personalization by default, and detaching it is the opt-out. This route does not add it: keep 8 in the list to keep it on. While the campaign is scheduled, launching, or sending, 1, 2, and 4 must stay as they are and 3 may only be added; any other change to them is `invalid_state` (409) because they gate which contacts may send, so pause first. 6 and 8 can change at any time. No other campaign field changes. Requires Campaigns edit. A campaign outside the workspace is `not_found` before the write.
|
|
8132
8228
|
|
|
8133
8229
|
- API: `PUT /v1/campaigns/{campaignId}/ai-workflows`
|
|
8134
8230
|
- Generated from the API contract
|
|
@@ -8179,7 +8275,7 @@ kenso campaigns replace-autopilot --campaign-id <campaign-id> --data @body.json
|
|
|
8179
8275
|
|
|
8180
8276
|
Replace the inboxes assigned to a campaign.
|
|
8181
8277
|
|
|
8182
|
-
Full replace. Send `inboxIds`, or `assignAllActive` to assign every Kenso-sendable inbox. Either one fixes the pool to that list. `allInboxes: true` turns on live "All inboxes" instead: every inbox a launch would assign (paused inboxes the campaign lacks and blocked Migma senders left out) joins now and inboxes connected later join too; it ignores the other fields and needs the `sender_routing` flag for the workspace, else `400 validation_failed` with detail code `feature_disabled`. Requires
|
|
8278
|
+
Full replace. Send `inboxIds`, or `assignAllActive` to assign every Kenso-sendable inbox. Either one fixes the pool to that list. `allInboxes: true` turns on live "All inboxes" instead: every inbox a launch would assign (paused inboxes the campaign lacks and blocked Migma senders left out) joins now and inboxes connected later join too; it ignores the other fields and needs the `sender_routing` flag for the workspace, else `400 validation_failed` with detail code `feature_disabled`. Requires Campaigns edit. A campaign outside the workspace is `not_found` before the write.
|
|
8183
8279
|
|
|
8184
8280
|
- API: `PUT /v1/campaigns/{campaignId}/inboxes`
|
|
8185
8281
|
- Generated from the API contract
|
|
@@ -8206,7 +8302,7 @@ kenso campaigns replace-inboxes --campaign-id <campaign-id> --data @body.json
|
|
|
8206
8302
|
|
|
8207
8303
|
Replace the LinkedIn accounts assigned to a campaign.
|
|
8208
8304
|
|
|
8209
|
-
Full replace. Send `linkedinAccountIds`, or `assignAllConnected` to assign every Connected LinkedIn seat. Requires
|
|
8305
|
+
Full replace. Send `linkedinAccountIds`, or `assignAllConnected` to assign every Connected LinkedIn seat. Requires Campaigns edit. A campaign outside the workspace is `not_found` before the write.
|
|
8210
8306
|
|
|
8211
8307
|
- API: `PUT /v1/campaigns/{campaignId}/linkedin-accounts`
|
|
8212
8308
|
- Generated from the API contract
|
|
@@ -8265,7 +8361,7 @@ kenso campaigns replace-linkedin-settings --campaign-id <campaign-id> --data @bo
|
|
|
8265
8361
|
|
|
8266
8362
|
Turn lead scoring on or off for a campaign.
|
|
8267
8363
|
|
|
8268
|
-
Requires
|
|
8364
|
+
Requires Campaigns edit. A campaign outside the workspace is `not_found` before the write.
|
|
8269
8365
|
|
|
8270
8366
|
- API: `PUT /v1/campaigns/{campaignId}/scoring`
|
|
8271
8367
|
- Generated from the API contract
|
|
@@ -8289,7 +8385,7 @@ kenso campaigns replace-scoring --campaign-id <campaign-id> --data @body.json
|
|
|
8289
8385
|
|
|
8290
8386
|
Replace a campaign's sender routing rules.
|
|
8291
8387
|
|
|
8292
|
-
DEV-5225. Full replace: `rules` is every rule, `[]` clears them. Each rule names an active mailbox provider or security gateway `provider` slug (one rule per provider) and at least one whole sending domain in `domains` (lowercased when saved; inboxes added on it later join) or single `inboxIds`. Every domain must be the address domain of a workspace inbox and every inbox a workspace inbox, else `400 validation_failed` with detail codes `unknown_provider`, `unsupported_provider`, `duplicate_provider`, `empty_rule`, `unknown_domain` or `unknown_inbox`. Applies to first emails planned from now on and to queued first emails at send time; follow-ups stay on the first email's inbox. Returns the routing as `GET` does. Needs the `sender_routing` flag (`feature_disabled`). Requires
|
|
8388
|
+
DEV-5225. Full replace: `rules` is every rule, `[]` clears them. Each rule names an active mailbox provider or security gateway `provider` slug (one rule per provider) and at least one whole sending domain in `domains` (lowercased when saved; inboxes added on it later join) or single `inboxIds`. Every domain must be the address domain of a workspace inbox and every inbox a workspace inbox, else `400 validation_failed` with detail codes `unknown_provider`, `unsupported_provider`, `duplicate_provider`, `empty_rule`, `unknown_domain` or `unknown_inbox`. Applies to first emails planned from now on and to queued first emails at send time; follow-ups stay on the first email's inbox. Returns the routing as `GET` does. Needs the `sender_routing` flag (`feature_disabled`). Requires Campaigns edit. A campaign outside the workspace is `not_found` before the write.
|
|
8293
8389
|
|
|
8294
8390
|
- API: `PUT /v1/campaigns/{campaignId}/sender-routing`
|
|
8295
8391
|
- Generated from the API contract
|
|
@@ -8311,7 +8407,7 @@ kenso campaigns replace-sender-routing --campaign-id <campaign-id> --data @body.
|
|
|
8311
8407
|
|
|
8312
8408
|
Restart a campaign's processing.
|
|
8313
8409
|
|
|
8314
|
-
Re-runs the processing pipeline from the beginning, to recover a campaign that stalled or errored, or to reprocess after a configuration change. On a draft campaign it starts processing behind the same readiness checks as `resume`, and a draft trigger campaign is `400 validation_failed` (start it with `resume`). An archived campaign is `400 validation_failed`. A campaign with `autoLaunchWhenReady` launches once processing reaches ready. Returns the campaign. Requires
|
|
8410
|
+
Re-runs the processing pipeline from the beginning, to recover a campaign that stalled or errored, or to reprocess after a configuration change. On a draft campaign it starts processing behind the same readiness checks as `resume`, and a draft trigger campaign is `400 validation_failed` (start it with `resume`). An archived campaign is `400 validation_failed`. A campaign with `autoLaunchWhenReady` launches once processing reaches ready. Returns the campaign. Requires Campaigns edit and the `launch` permission. While the workspace's data is scheduled for deletion or being deleted, returns `409 invalid_state`.
|
|
8315
8411
|
|
|
8316
8412
|
- API: `POST /v1/campaigns/{campaignId}/restart`
|
|
8317
8413
|
- Generated from the API contract
|
|
@@ -8330,7 +8426,7 @@ kenso campaigns restart --campaign-id <campaign-id>
|
|
|
8330
8426
|
|
|
8331
8427
|
Resume sending, processing, and AI workflows together.
|
|
8332
8428
|
|
|
8333
|
-
Idempotent. A campaign that is already running returns `200` with the resource. A subsystem that was not paused is left as it is. If any subsystem fails, the action returns that error and the caller can retry. A campaign that is still launching returns `409 invalid_state`, and so does every campaign while the workspace's data is scheduled for deletion or being deleted. Requires `
|
|
8429
|
+
Idempotent. A campaign that is already running returns `200` with the resource. A subsystem that was not paused is left as it is. If any subsystem fails, the action returns that error and the caller can retry. A campaign that is still launching returns `409 invalid_state`, and so does every campaign while the workspace's data is scheduled for deletion or being deleted. Requires Campaigns edit and the `launch` permission.
|
|
8334
8430
|
|
|
8335
8431
|
- API: `POST /v1/campaigns/{campaignId}/resume`
|
|
8336
8432
|
- Generated from the API contract
|
|
@@ -8349,7 +8445,7 @@ kenso campaigns resume --campaign-id <campaign-id>
|
|
|
8349
8445
|
|
|
8350
8446
|
Re-queue failed enrichment without restarting the campaign.
|
|
8351
8447
|
|
|
8352
|
-
Deletes failed website and email-finder markers so existing workers pick the contacts up again. Does not restart processing, and does not change qualification, personalization, or sent state. If data or email enrichment is paused, the markers are still cleared and workers wait until resume. Idempotent: clearing nothing is still `200`. An archived campaign is `validation_failed` and is not touched. A campaign outside the workspace is `not_found` before the retry. Requires
|
|
8448
|
+
Deletes failed website and email-finder markers so existing workers pick the contacts up again. Does not restart processing, and does not change qualification, personalization, or sent state. If data or email enrichment is paused, the markers are still cleared and workers wait until resume. Idempotent: clearing nothing is still `200`. An archived campaign is `validation_failed` and is not touched. A campaign outside the workspace is `not_found` before the retry. Requires Campaigns edit.
|
|
8353
8449
|
|
|
8354
8450
|
- API: `POST /v1/campaigns/{campaignId}/retry-enrichment`
|
|
8355
8451
|
- Generated from the API contract
|
|
@@ -8368,7 +8464,7 @@ kenso campaigns retry-enrichment --campaign-id <campaign-id>
|
|
|
8368
8464
|
|
|
8369
8465
|
Score contacts in a campaign.
|
|
8370
8466
|
|
|
8371
|
-
The run finishes in the request and returns a `lead_scoring` job. Poll it with `GET /v1/jobs/{jobId}?type=lead_scoring`. Scores are `qualityScore` on each contact. Requires `
|
|
8467
|
+
The run finishes in the request and returns a `lead_scoring` job. Poll it with `GET /v1/jobs/{jobId}?type=lead_scoring`. Scores are `qualityScore` on each contact. Requires Campaigns edit and the `ask` permission. A campaign outside the workspace is `not_found` before the run.
|
|
8372
8468
|
|
|
8373
8469
|
- API: `POST /v1/campaigns/{campaignId}/scoring/run`
|
|
8374
8470
|
- Generated from the API contract
|
|
@@ -8391,7 +8487,7 @@ kenso campaigns run-scoring --campaign-id <campaign-id> --data @body.json
|
|
|
8391
8487
|
|
|
8392
8488
|
Update a campaign's name, contact limit, send schedule, ramp-up, owner, sending switches, same-company rules, account-play protection, new-leads-first order, catch-all lane, language settings, mode, or auto-launch.
|
|
8393
8489
|
|
|
8394
|
-
Absent fields stay unchanged. `status` is rejected. Unknown JSON members are a 400. A schedule or daily-cap change writes a planner request row (nothing consumes it any more, DEV-1821; gap-fill picks up the change on its next pass); `rampUpDays`, `stopCompanyOnReply` and `groupSameCompanySends` do not, as in the legacy update. `rampUpDays` is 0 (no ramp) to 30 scheduled sending days, else `400 validation_failed`. `stopCompanyOnReply` is the same stored value as `stopSequenceForCompanyOnReply` in the LinkedIn settings; it is written after the other fields. `ownerMemberId` must be an active member of the workspace, else `400 validation_failed` with detail code `not_a_member`. Changing `stopOnReply`, `trackClicks`, `trackOpens`, or `unsubscribeLink` needs the `campaign_send_settings` flag for the workspace, else `400 validation_failed` with detail code `feature_disabled` per field and nothing is written. Sending the stored value is accepted without the flag. `protectAccountPlays` turns skipping people in active account plays on or off for this campaign; people already stopped stay stopped. Requires
|
|
8490
|
+
Absent fields stay unchanged. `status` is rejected. Unknown JSON members are a 400. A schedule or daily-cap change writes a planner request row (nothing consumes it any more, DEV-1821; gap-fill picks up the change on its next pass); `rampUpDays`, `stopCompanyOnReply` and `groupSameCompanySends` do not, as in the legacy update. `rampUpDays` is 0 (no ramp) to 30 scheduled sending days, else `400 validation_failed`. `stopCompanyOnReply` is the same stored value as `stopSequenceForCompanyOnReply` in the LinkedIn settings; it is written after the other fields. `ownerMemberId` must be an active member of the workspace, else `400 validation_failed` with detail code `not_a_member`. Changing `stopOnReply`, `trackClicks`, `trackOpens`, or `unsubscribeLink` needs the `campaign_send_settings` flag for the workspace, else `400 validation_failed` with detail code `feature_disabled` per field and nothing is written. Sending the stored value is accepted without the flag. `protectAccountPlays` turns skipping people in active account plays on or off for this campaign; people already stopped stay stopped. Requires Campaigns edit. `newLeadsFirst` true gives first emails the campaign's daily capacity ahead of its follow-ups; it takes effect on the next gap-fill pass. While it is true the response carries `awaitingFirstEmailCount`. `catchAllLaneEnabled` true opts the campaign in to the catch-all lane: the sequencer may also send to unverified CatchAll addresses whose catch-all score clears a bar, capped per campaign and per inbox per day, until the lane's bounce circuit breaker pauses it. It does nothing until Kenso turns the lane on platform-wide. `catchAllLanePausedAt` is system-owned: sending it is an unknown member (`400`). `bookingMeetingTypeId` names a live, enabled round robin meeting type of this workspace that takes this campaign's bookings when the account owner and the sender can't; `null` clears it. `kind` cannot be changed: any value is `400 validation_failed` with detail code `kind_immutable`. `roleId` names a live role of this workspace for a recruiting campaign and needs the `recruiting` flag; `null` clears it. On a sales campaign it is `400` with detail code `not_recruiting`. `excludedCountries` replaces the countries this campaign never sends to: ISO 3166-1 alpha-2 codes or country names, stored as upper-case codes; `[]` clears it. An entry that names no country is `400 validation_failed` with detail code `invalid_country` and nothing is written. Imports drop a contact whose country is listed and the sequencer skips one already on the campaign, from its next pass. The language settings (`sourceLanguage`, `languageMode``source_only` or `auto`, `enabledLanguages`, `formalityOverrides` locale to `formal` or `informal`, and `languageFallback``source` or `hold`) need the `multilingual_outreach` flag for the workspace, else `400 validation_failed` with detail code `feature_disabled` per field sent, even for the stored value. A locale must be a market pack that is not a draft and `sourceLanguage` may also be a language with a primary pack (`en`), else detail code `unknown_language` or `draft_language`; any other bad value is `invalid_value`. `null`, `[]` or `{}` clears `enabledLanguages` or `formalityOverrides`. `mode` is `batch` or `trigger`, else `400 validation_failed`. Batch to trigger converts the campaign to signal-based sending; trigger to batch is `400 validation_failed` with detail code `mode_one_way` and nothing is written. `autoLaunchWhenReady` true launches the campaign once it is ready, with no further confirmation; changing it needs the launch permission (`403 forbidden`), is `400` once the campaign launched or for a trigger or approval-test campaign, and `409 conflict` once auto-launch has run. `mode``trigger` on a batch campaign is `400 validation_failed` on `autoLaunchWhenReady`, and nothing is written, when it comes with `autoLaunchWhenReady` true, or without it while the campaign is set to auto-launch: send `false` in the same request to turn that off.
|
|
8395
8491
|
|
|
8396
8492
|
- API: `PATCH /v1/campaigns/{campaignId}`
|
|
8397
8493
|
- Generated from the API contract
|
|
@@ -8485,7 +8581,7 @@ kenso checkout-sessions create --data @body.json
|
|
|
8485
8581
|
|
|
8486
8582
|
List stage checkpoints for a build session.
|
|
8487
8583
|
|
|
8488
|
-
Ordered by id. Read-only. Requires
|
|
8584
|
+
Ordered by id. Read-only. Requires Campaigns view.
|
|
8489
8585
|
|
|
8490
8586
|
- API: `GET /v1/build-sessions/{buildSessionId}/checkpoints` (a list: `--limit`, `--cursor`, `--all`)
|
|
8491
8587
|
- Generated from the API contract
|
|
@@ -8646,7 +8742,7 @@ kenso cli-logins token --data @body.json
|
|
|
8646
8742
|
|
|
8647
8743
|
Download a weekly click report CSV.
|
|
8648
8744
|
|
|
8649
|
-
Streams the clicked-leads CSV of the weekly click-report email whose link carries `reportToken`. Requires
|
|
8745
|
+
Streams the clicked-leads CSV of the weekly click-report email whose link carries `reportToken`. Requires Campaigns view and the `export` permission in the workspace and account scope all, because the CSV covers every account. An unknown token, or a token of another workspace, is `404 not_found`; an expired report is `410 gone`. The CSV holds lead PII: `Cache-Control: private, no-store`.
|
|
8650
8746
|
|
|
8651
8747
|
- API: `GET /v1/click-reports/{reportToken}/content`
|
|
8652
8748
|
- Generated from the API contract
|
|
@@ -8984,7 +9080,7 @@ kenso committee-seats delete --seat-id <seat-id>
|
|
|
8984
9080
|
|
|
8985
9081
|
Return one company in the current workspace.
|
|
8986
9082
|
|
|
8987
|
-
A missing or cross-workspace id is `not_found`. Requires
|
|
9083
|
+
A missing or cross-workspace id is `not_found`. Requires Campaigns view.
|
|
8988
9084
|
|
|
8989
9085
|
- API: `GET /v1/companies/{companyId}`
|
|
8990
9086
|
- Generated from the API contract
|
|
@@ -9003,7 +9099,7 @@ kenso companies get --company-id <company-id>
|
|
|
9003
9099
|
|
|
9004
9100
|
List companies in the current workspace.
|
|
9005
9101
|
|
|
9006
|
-
Ordered by id. `q` matches the name. `domain` is an exact match. Requires
|
|
9102
|
+
Ordered by id. `q` matches the name. `domain` is an exact match. Requires Campaigns view.
|
|
9007
9103
|
|
|
9008
9104
|
- API: `GET /v1/companies` (a list: `--limit`, `--cursor`, `--all`)
|
|
9009
9105
|
- Generated from the API contract
|
|
@@ -9051,7 +9147,7 @@ kenso company-data get
|
|
|
9051
9147
|
|
|
9052
9148
|
Return the behavior signals of the person behind a contact.
|
|
9053
9149
|
|
|
9054
|
-
`workspace` holds this workspace's own evidence: `tags` (such as `cold_responder`, `prefers_linkedin`, `best_window:weekday_morning`, `away_until:2026-11-18`), `signals` (`{key, value, rate, touches, responses}`, rate 0 to 1), `touches` and `computedAt` (rebuilt nightly). `network` has the same fields from every Kenso workspace, anonymous, plus `workspaces` (how many other workspaces touched the person); it never says which workspace, sender, campaign or reply, and it is present only with the `behavior_signals_network` feature and when at least one other workspace touched the person. `email_confirmed`, `email_dead_end` and `left_company` are tagged only for the contact's own email address or its company domain. Absent means null: no `workspace` when the workspace has no profile for the person, and an empty object when the contact has no LinkedIn URL and no email. A contact outside the workspace or deleted is `not_found`. Requires
|
|
9150
|
+
`workspace` holds this workspace's own evidence: `tags` (such as `cold_responder`, `prefers_linkedin`, `best_window:weekday_morning`, `away_until:2026-11-18`), `signals` (`{key, value, rate, touches, responses}`, rate 0 to 1), `touches` and `computedAt` (rebuilt nightly). `network` has the same fields from every Kenso workspace, anonymous, plus `workspaces` (how many other workspaces touched the person); it never says which workspace, sender, campaign or reply, and it is present only with the `behavior_signals_network` feature and when at least one other workspace touched the person. `email_confirmed`, `email_dead_end` and `left_company` are tagged only for the contact's own email address or its company domain. Absent means null: no `workspace` when the workspace has no profile for the person, and an empty object when the contact has no LinkedIn URL and no email. A contact outside the workspace or deleted is `not_found`. Requires Campaigns view and the `behavior_signals` feature.
|
|
9055
9151
|
|
|
9056
9152
|
- Beta: needs the `behavior_signals` feature flag on the workspace.
|
|
9057
9153
|
- API: `GET /v1/contacts/{contactId}/behavior`
|
|
@@ -9073,7 +9169,7 @@ kenso contact-behavior get --contact-id <contact-id>
|
|
|
9073
9169
|
|
|
9074
9170
|
Download a contact export file.
|
|
9075
9171
|
|
|
9076
|
-
Streams CSV, or a ZIP when a campaign export is one file per segment. Each download is sized from a live count and charged to the export row quota before any row is read; a file over the per-request row cap is `429 quota_exceeded`. Requires `
|
|
9172
|
+
Streams CSV, or a ZIP when a campaign export is one file per segment. Each download is sized from a live count and charged to the export row quota before any row is read; a file over the per-request row cap is `429 quota_exceeded`. Requires Campaigns view and the `export` permission. A missing or expired export is `not_found`.
|
|
9077
9173
|
|
|
9078
9174
|
- API: `GET /v1/contact-exports/{exportId}/content`
|
|
9079
9175
|
- Generated from the API contract
|
|
@@ -9092,7 +9188,7 @@ kenso contact-exports content --export-id <export-id>
|
|
|
9092
9188
|
|
|
9093
9189
|
Create a contact export and return its job.
|
|
9094
9190
|
|
|
9095
|
-
`kind` is `contacts` (workspace filters), `campaign`, `clicked`, `advanced`, or `events`. Campaign kinds require `campaignId` in the current workspace. `events` also requires `occurredAfter` and `occurredBefore`. Requires `
|
|
9191
|
+
`kind` is `contacts` (workspace filters), `campaign`, `clicked`, `advanced`, or `events`. Campaign kinds require `campaignId` in the current workspace. `events` also requires `occurredAfter` and `occurredBefore`. Requires Campaigns view and the `export` permission. Poll `GET /v1/jobs/{jobId}?type=contact_export`. The job's `downloadUrl` streams the file. Contacts from a Kenso library list are never exported. For kinds `contacts`, `campaign` and `advanced` the job's `excludedLibraryContacts` says how many were left out, including 0. Kind `contacts` also takes `campaignIds` (1 to 50 campaigns of the workspace, not with `campaignId`), `listId` (a contact's import list), `createdAfter` (inclusive) and `createdBefore` (exclusive), `maxRows` (1 to 50000) and `skipRows` (in contact id order). Other kinds refuse them. `readyOnly` still needs one `campaignId`.
|
|
9096
9192
|
|
|
9097
9193
|
- API: `POST /v1/contact-exports`
|
|
9098
9194
|
- Generated from the API contract
|
|
@@ -9140,7 +9236,7 @@ kenso contact-exports create --data @body.json
|
|
|
9140
9236
|
|
|
9141
9237
|
Write a contact export to a new Google Sheet.
|
|
9142
9238
|
|
|
9143
|
-
Builds the same rows `GET /v1/contact-exports/{exportId}/content` streams and writes them to a new spreadsheet, `Kenso export - {campaign name or Contacts} - {yyyy-MM-dd}`, in the caller's own Google Drive through their Kenso Workspace Google connection. Cells are written as text, never as formulas, and a cell that starts like a formula (`=`, `@`, a tab or line break, or `+` or `-` that is not a number or phone number) keeps a leading apostrophe, as in the CSV download. A campaign export that is one file per segment is `409 invalid_state`: export one segment at a time. Google refusing to create or write the sheet in the member's Drive is `409 invalid_state` too. No usable Google connection is `409 reconnect_required`; Google failing or rate-limiting is `503 provider_unavailable`. Counts against the same export row limits as the download. Requires `
|
|
9239
|
+
Builds the same rows `GET /v1/contact-exports/{exportId}/content` streams and writes them to a new spreadsheet, `Kenso export - {campaign name or Contacts} - {yyyy-MM-dd}`, in the caller's own Google Drive through their Kenso Workspace Google connection. Cells are written as text, never as formulas, and a cell that starts like a formula (`=`, `@`, a tab or line break, or `+` or `-` that is not a number or phone number) keeps a leading apostrophe, as in the CSV download. A campaign export that is one file per segment is `409 invalid_state`: export one segment at a time. Google refusing to create or write the sheet in the member's Drive is `409 invalid_state` too. No usable Google connection is `409 reconnect_required`; Google failing or rate-limiting is `503 provider_unavailable`. Counts against the same export row limits as the download. Requires Campaigns view, the `export` permission and the `google_sheets` feature flag (404 without it).
|
|
9144
9240
|
|
|
9145
9241
|
- Beta: needs the `google_sheets` feature flag on the workspace.
|
|
9146
9242
|
- API: `POST /v1/contact-exports/{exportId}/google-sheet`
|
|
@@ -9162,7 +9258,7 @@ kenso contact-exports google-sheet --export-id <export-id>
|
|
|
9162
9258
|
|
|
9163
9259
|
List contact fields for the column picker, CSV export, and CSV import.
|
|
9164
9260
|
|
|
9165
|
-
The catalog is static. `usages` is `list`, `export`, and/or `import`. Ordered with `qualityReasoning` beside `qualityScore`. `securityGateway` and `mailboxProvider` are listed only when the workspace has security gateways. `customImage` (an import target) is listed only when the workspace has campaign images. `customVideo` (an import target) is listed only when the workspace has campaign videos. Requires
|
|
9261
|
+
The catalog is static. `usages` is `list`, `export`, and/or `import`. Ordered with `qualityReasoning` beside `qualityScore`. `securityGateway` and `mailboxProvider` are listed only when the workspace has security gateways. `customImage` (an import target) is listed only when the workspace has campaign images. `customVideo` (an import target) is listed only when the workspace has campaign videos. Requires Campaigns view.
|
|
9166
9262
|
|
|
9167
9263
|
- API: `GET /v1/contact-fields` (a list: `--limit`, `--cursor`, `--all`)
|
|
9168
9264
|
- Generated from the API contract
|
|
@@ -9186,7 +9282,7 @@ kenso contact-fields list --all
|
|
|
9186
9282
|
|
|
9187
9283
|
Preview the buyers Ken finds at a list of companies, for a campaign's ICP.
|
|
9188
9284
|
|
|
9189
|
-
Body: `campaignId` (required; another workspace's campaign is `404`), `companies` (1 to 50, each `{ key?, name?, domain? }` with a name or a domain, else `400 validation_failed` on `companies[i]`) and `perCompany` (1 to 3, default 3). Send a longer list in parts of 50. Example: `{ "campaignId": 812, "companies": [{ "key": "row-2", "name": "Northwind", "domain": "northwind.com" }], "perCompany": 3 }`. A company with a domain is the Kenso Search company that owns it: one Kenso Search also matches by the given name at that domain, else one whose website is the domain's home page. A company with only a page under the domain (`notion.so/...`) does not count, and no name match stands in for it. A company without a domain is found by a name only one company has. Unmatched companies say why (`acme.com is not in Kenso Search`, `could not match notion.so: no company in Kenso Search has it as its own website`, `no domain, name matches 3 companies`). A matched company lists up to `perCompany` people at it in the campaign's ICP (the titles, seniority, functions and exclusions of its live segments), best first, each with a one-line `reason`, and each person once in the whole answer, by Kenso id or LinkedIn URL (Kenso Search can hold one person twice); when the ICP finds too few, Ken fills the company from a looser search and marks those people `weakMatch`. No ICP ranks people by seniority, and `icp` is empty. `signal` is the company's latest hiring, funding or leadership change from the last 90 days. A company Kenso Search does not answer for in time is `failed`; retry it. Each person's `contact` is a `POST /v1/contact-imports``source: search` contact: post the kept ones unchanged to add them (dedupe, blocklist and lead credits apply there). Nothing is stored and nothing is charged; the companies times `perCompany` count against the workspace's `searchBrowseRows` quota (`429 quota_exceeded` past it). Requires
|
|
9285
|
+
Body: `campaignId` (required; another workspace's campaign is `404`), `companies` (1 to 50, each `{ key?, name?, domain? }` with a name or a domain, else `400 validation_failed` on `companies[i]`) and `perCompany` (1 to 3, default 3). Send a longer list in parts of 50. Example: `{ "campaignId": 812, "companies": [{ "key": "row-2", "name": "Northwind", "domain": "northwind.com" }], "perCompany": 3 }`. A company with a domain is the Kenso Search company that owns it: one Kenso Search also matches by the given name at that domain, else one whose website is the domain's home page. A company with only a page under the domain (`notion.so/...`) does not count, and no name match stands in for it. A company without a domain is found by a name only one company has. Unmatched companies say why (`acme.com is not in Kenso Search`, `could not match notion.so: no company in Kenso Search has it as its own website`, `no domain, name matches 3 companies`). A matched company lists up to `perCompany` people at it in the campaign's ICP (the titles, seniority, functions and exclusions of its live segments), best first, each with a one-line `reason`, and each person once in the whole answer, by Kenso id or LinkedIn URL (Kenso Search can hold one person twice); when the ICP finds too few, Ken fills the company from a looser search and marks those people `weakMatch`. No ICP ranks people by seniority, and `icp` is empty. `signal` is the company's latest hiring, funding or leadership change from the last 90 days. A company Kenso Search does not answer for in time is `failed`; retry it. Each person's `contact` is a `POST /v1/contact-imports``source: search` contact: post the kept ones unchanged to add them (dedupe, blocklist and lead credits apply there). Nothing is stored and nothing is charged; the companies times `perCompany` count against the workspace's `searchBrowseRows` quota (`429 quota_exceeded` past it). Requires Campaigns edit and the `import` permission.
|
|
9190
9286
|
|
|
9191
9287
|
- Beta: needs the `csv_buyer_preview` feature flag on the workspace.
|
|
9192
9288
|
- API: `POST /v1/contact-imports/buyer-previews`
|
|
@@ -9210,7 +9306,7 @@ kenso contact-imports buyer-preview --data @body.json
|
|
|
9210
9306
|
|
|
9211
9307
|
Start a contact import and return its job.
|
|
9212
9308
|
|
|
9213
|
-
JSON `source` is `campaign` (copy from `sourceCampaignId`), `search` (a `contacts` array, at most 1,000), `blitz` (the same `contacts` array, at most 1,000, for people picked in the Blitz tab of Search; the run's surface is Blitz and it counts no Kenso Search work), `loopster` (`records`, 1 to 1,000 people picked in the Loopster tab of Search, as its search returned them, and that search's `searchId`: when a record has no LinkedIn URL, Kenso reads it from a temporary table in the workspace's Loopster account, then trashes the table; the run's surface is Loopster and it counts no Kenso Search work) or `people` (`personIds`, 1 to 1,000 workspace people; each becomes a contact with their name, email, title, LinkedIn URL and the company of their highest-priority account; needs the `accounts` feature and Accounts view, and with account scope `own` takes only people on the caller's accounts), `event` (`eventId`, optional `roles` and `includeAccounts`: an outbound event's attendees with an email or a LinkedIn URL, at most 5,000; rows whose company is a workspace account are left out unless `includeAccounts` is true, and then with account scope `own` only those on the caller's accounts are added; needs the `accounts` and `event_outbound` features and Accounts view) or `sales_navigator` (`linkedinAccountId`, a seat the caller connected, and `url`, a Sales Navigator lead search or lead list; its people with their name, current title, LinkedIn profile and company. One import reads at most 8 pages (about 200 to 400 people): a list it cannot read to the end imports nothing and is `400 validation_failed` with code `incomplete_read` on `url`. Behind the `sales_navigator` feature, a seat without Sales Navigator is `409 sales_navigator_required`). Where the `linkedin_network` feature is on, `linkedin_connections` (`connectionIds`, 1 to 1,000 ids from `GET /v1/linkedin-connections`; each becomes a contact with first and last name, title, headline, LinkedIn URL, seniority and Kenso Search's company name, domain, LinkedIn URL, industry and size; needs Accounts view; elsewhere it is an unknown source). Multipart `source=csv` uploads a CSV file into `campaignId`; its optional form field `columnMappings` (a JSON array of mappings, as for a Google Sheet) sets the columns, and a mapped column the header row lacks is `400 validation_failed`; omitted, the header row is mapped by the import's aliases. Behind the `csv_import_check` feature (a field sent while it is off is `400 validation_failed` on that field) the CSV create also takes the List check choices of a scan: `fixes` (a JSON array of `missingKey`, `invalidEmail`, `noMx`, `catchAll`, `personalEmail`, `roleAddress`, `companyContacted`, `companyCap`) drops the rows the List check flags for them and counts each under its key in the job's `skipped`; `includeRecentlyContacted=true` keeps the rows the campaign's recently-emailed window would skip, for this import only; `cleanup=true` cleans the name, email, title, company, domain, LinkedIn URL and phone cells as the scan's cleanup notes say. Omitted, they are off. JSON `source``google_sheets` (behind the `google_sheets` flag) reads `spreadsheetId` (an id or a Google Sheets URL) and the optional `sheet` with the caller's own Kenso Workspace Google connection; row 1 is the header and `columnMappings` work as for a CSV. No connection is `409 reconnect_required`; a sheet not picked for Kenso is `409 sheet_not_shared`. JSON `source``airtable` (behind the `airtable` flag) reads every record of `tableId` (an id or name) in `baseId`, or of its `viewId` when set, with the workspace's Airtable token: the table's field names, primary field first, are the header and each record is a row of cell text. A table or view of more than 10,000 records is `400 validation_failed` on `tableId`: import it in parts through views. No token is `409 not_connected`; a token without the read scopes or access to the base is `409 scope_required`. JSON `source``saved_list` (behind the `saved_lists` flag; elsewhere it is an unknown source) imports the members of `savedListId`: a list of this workspace (a private one only for its owner), a list shared with it, or a library list. The optional `memberFilters` (`country`, `seniority`, `title`, `industry`, `headcountBand`, `hasSendableEmail`) narrow the members. A company list with `roles` (1 to 20 titles) imports up to 5 people per company found by Kenso Search, for at most 500 companies; without `roles` each company is one company contact. `findPeople` must be absent or false. Members this list already put in the campaign are skipped, so a retry adds only the rest. A library list's cached Safe emails land Safe with no email charge on a paid plan; a Free workspace gets no emails from a library list. A member copied out of a library list follows the same rules in any list. `columnMappings` is refused: the list sets its own columns. More than 100,000 contacts is `400 validation_failed` on `memberFilters`. Every source applies the import's dedupe, blocklist and contact limits. A JSON body over 10 MB is `413`; the multipart CSV upload accepts up to 400 MB. Requires `
|
|
9309
|
+
JSON `source` is `campaign` (copy from `sourceCampaignId`), `search` (a `contacts` array, at most 1,000), `blitz` (the same `contacts` array, at most 1,000, for people picked in the Blitz tab of Search; the run's surface is Blitz and it counts no Kenso Search work), `loopster` (`records`, 1 to 1,000 people picked in the Loopster tab of Search, as its search returned them, and that search's `searchId`: when a record has no LinkedIn URL, Kenso reads it from a temporary table in the workspace's Loopster account, then trashes the table; the run's surface is Loopster and it counts no Kenso Search work) or `people` (`personIds`, 1 to 1,000 workspace people; each becomes a contact with their name, email, title, LinkedIn URL and the company of their highest-priority account; needs the `accounts` feature and Accounts view, and with account scope `own` takes only people on the caller's accounts), `event` (`eventId`, optional `roles` and `includeAccounts`: an outbound event's attendees with an email or a LinkedIn URL, at most 5,000; rows whose company is a workspace account are left out unless `includeAccounts` is true, and then with account scope `own` only those on the caller's accounts are added; needs the `accounts` and `event_outbound` features and Accounts view) or `sales_navigator` (`linkedinAccountId`, a seat the caller connected, and `url`, a Sales Navigator lead search or lead list; its people with their name, current title, LinkedIn profile and company. One import reads at most 8 pages (about 200 to 400 people): a list it cannot read to the end imports nothing and is `400 validation_failed` with code `incomplete_read` on `url`. Behind the `sales_navigator` feature, a seat without Sales Navigator is `409 sales_navigator_required`). Where the `linkedin_network` feature is on, `linkedin_connections` (`connectionIds`, 1 to 1,000 ids from `GET /v1/linkedin-connections`; each becomes a contact with first and last name, title, headline, LinkedIn URL, seniority and Kenso Search's company name, domain, LinkedIn URL, industry and size; needs Accounts view; elsewhere it is an unknown source). Multipart `source=csv` uploads a CSV file into `campaignId`; its optional form field `columnMappings` (a JSON array of mappings, as for a Google Sheet) sets the columns, and a mapped column the header row lacks is `400 validation_failed`; omitted, the header row is mapped by the import's aliases. Behind the `csv_import_check` feature (a field sent while it is off is `400 validation_failed` on that field) the CSV create also takes the List check choices of a scan: `fixes` (a JSON array of `missingKey`, `invalidEmail`, `noMx`, `catchAll`, `personalEmail`, `roleAddress`, `companyContacted`, `companyCap`) drops the rows the List check flags for them and counts each under its key in the job's `skipped`; `includeRecentlyContacted=true` keeps the rows the campaign's recently-emailed window would skip, for this import only; `cleanup=true` cleans the name, email, title, company, domain, LinkedIn URL and phone cells as the scan's cleanup notes say. Omitted, they are off. JSON `source``google_sheets` (behind the `google_sheets` flag) reads `spreadsheetId` (an id or a Google Sheets URL) and the optional `sheet` with the caller's own Kenso Workspace Google connection; row 1 is the header and `columnMappings` work as for a CSV. No connection is `409 reconnect_required`; a sheet not picked for Kenso is `409 sheet_not_shared`. JSON `source``airtable` (behind the `airtable` flag) reads every record of `tableId` (an id or name) in `baseId`, or of its `viewId` when set, with the workspace's Airtable token: the table's field names, primary field first, are the header and each record is a row of cell text. A table or view of more than 10,000 records is `400 validation_failed` on `tableId`: import it in parts through views. No token is `409 not_connected`; a token without the read scopes or access to the base is `409 scope_required`. JSON `source``saved_list` (behind the `saved_lists` flag; elsewhere it is an unknown source) imports the members of `savedListId`: a list of this workspace (a private one only for its owner), a list shared with it, or a library list. The optional `memberFilters` (`country`, `seniority`, `title`, `industry`, `headcountBand`, `hasSendableEmail`) narrow the members. A company list with `roles` (1 to 20 titles) imports up to 5 people per company found by Kenso Search, for at most 500 companies; without `roles` each company is one company contact. `findPeople` must be absent or false. Members this list already put in the campaign are skipped, so a retry adds only the rest. A library list's cached Safe emails land Safe with no email charge on a paid plan; a Free workspace gets no emails from a library list. A member copied out of a library list follows the same rules in any list. `columnMappings` is refused: the list sets its own columns. More than 100,000 contacts is `400 validation_failed` on `memberFilters`. Every source applies the import's dedupe, blocklist and contact limits. A JSON body over 10 MB is `413`; the multipart CSV upload accepts up to 400 MB. Requires Campaigns edit and the `import` permission. Poll `GET /v1/jobs/{jobId}?type=contact_import`. `linkedin_url` (`url`, optional `linkedinAccountId`, `maxLeads`, `postKinds`) queues a LinkedIn import that needs the `linkedin_url_import` flag. Options (DEV-15): `source=campaign` takes `importLimit` (above 0), `importOffset` (0 or more), `onlyImportQualifiedContacts`, `onlyImportValidContacts`, `deduplicateCampaignIds` (1 to 50 campaigns of the workspace; others are `not_found`), `deduplicationMode` (`none`, `by_email` the default, or `by_data`), `allowReimport`, `copyDataEnrichment` and `copyEmailEnrichment` (keep the source's enrichment results; default false). `source=search` (not `blitz`) takes `importLimit`, `triggerPostProcessing` (default true) and `tagIds` (1 to 50 workspace contact tags put on every imported contact). A multipart CSV takes the form fields `importLimit` and `tagIds` (a JSON array, for example `[3,4]`). An option sent with a source that does not honor it, or with `target=people`, is `400 validation_failed` on that field. `source=segment` copies one segment of the workspace (`sourceSegmentId`, from any campaign) into `campaignId` as a new segment with the source segment's name. `copyQualification`, `copyEmailEnrichment` and `copyEmailVerification` keep the source contacts' AI qualification, found emails and email verification (each default false). `segmentId` is refused (the copy makes its own segment); a segment name already in the campaign is `400`, and another import into it in progress is `409`. A campaign or segment copy Kenso cannot start right now (a full import queue, or its job could not be recorded) is `503 service_unavailable`: nothing was copied, so retry it. `target` is `campaign` (the default) or `people`. With `people` (behind the `lead_intake` feature, `404` when off, and Accounts edit) `campaignId` is optional and ignored: the rows of source `csv` (multipart, form field `target=people`), `search`, `blitz`, `event`, `linkedin_connections`, `sales_navigator`, `google_sheets` or `airtable` are queued and run through person intake as workspace people with source `import`. A row needs an email, a LinkedIn URL, or a name with a business company domain; others are skipped. The job's `personImport` reports the created, updated and skipped counts.
|
|
9214
9310
|
|
|
9215
9311
|
- API: `POST /v1/contact-imports`
|
|
9216
9312
|
- Generated from the API contract
|
|
@@ -9389,7 +9485,7 @@ kenso contact-limits update --data @body.json
|
|
|
9389
9485
|
|
|
9390
9486
|
Soft-delete up to 1,000 contacts by id.
|
|
9391
9487
|
|
|
9392
|
-
Requires
|
|
9488
|
+
Requires Campaigns edit. Ids outside the workspace are reported in `failed` and are not deleted.
|
|
9393
9489
|
|
|
9394
9490
|
- API: `POST /v1/contacts/bulk-delete`
|
|
9395
9491
|
- Generated from the API contract
|
|
@@ -9474,7 +9570,7 @@ kenso contacts bulk-resume --data @body.json
|
|
|
9474
9570
|
|
|
9475
9571
|
Update fields on up to 1,000 contacts in one call.
|
|
9476
9572
|
|
|
9477
|
-
Each item is a `contactId` plus any fields `PATCH /v1/contacts/{contactId}` accepts, with the same semantics: absent fields stay unchanged, null clears a string. Items run one at a time in request order. A contact outside the workspace is `not_found` and is not written. A field error fails only that item. `results` is in request order; `status` is `updated`, `not_found`, `validation_failed`, `video_in_use` (the lead's video is used by a sent or queued step), or `failed`. The whole request is rejected, with nothing written, when `items` is empty, has more than 1,000 entries, has an entry that is not an object or lacks a positive `contactId`, or repeats a `contactId`. An item's `customVariables` merges as on the single update. Requires
|
|
9573
|
+
Each item is a `contactId` plus any fields `PATCH /v1/contacts/{contactId}` accepts, with the same semantics: absent fields stay unchanged, null clears a string. Items run one at a time in request order. A contact outside the workspace is `not_found` and is not written. A field error fails only that item. `results` is in request order; `status` is `updated`, `not_found`, `validation_failed`, `video_in_use` (the lead's video is used by a sent or queued step), or `failed`. The whole request is rejected, with nothing written, when `items` is empty, has more than 1,000 entries, has an entry that is not an object or lacks a positive `contactId`, or repeats a `contactId`. An item's `customVariables` merges as on the single update. Requires Campaigns edit.
|
|
9478
9574
|
|
|
9479
9575
|
- API: `POST /v1/contacts/bulk-update`
|
|
9480
9576
|
- Generated from the API contract
|
|
@@ -9495,7 +9591,7 @@ kenso contacts bulk-update --data @body.json
|
|
|
9495
9591
|
|
|
9496
9592
|
Add up to 1,000 contacts to a campaign.
|
|
9497
9593
|
|
|
9498
|
-
Uses the existing campaign lead upsert, in batches of 100. Accepted and updated rows are succeeded. A later batch can fail without rolling back earlier rows; the upsert is safe to retry. `customImageUrl` sets the lead's own image (an empty string clears it): a malformed URL fails its row before anything is written, and a refused image (campaign images off for the workspace) fails its row with the contact's id, the contact itself saved. `customVideo` sets the lead's own video (a share link or embed code; an empty string clears it): a value no supported provider matches fails its row before anything is written, a refused video (campaign videos off) fails its row with the contact's id, and a video a sent or queued step uses fails its row with code `video_in_use`, the contact saved and the old video kept. `customVariables` is an object of string values merged into the contact's custom variables (a null or empty value clears that key on an existing contact); a key new to the campaign joins its catalog with AI context off. A blank, unusable or reserved key, or more than 50 keys, fails its row before anything is written; a batch that would take the campaign past 50 custom variables fails every row in it. `emailValidity` (optional, `safe` for an email you already verified) qualifies a new contact on import in a campaign without AI qualification, spending one contact allowance; omitted keeps a stored verdict on an existing email. `useKenEmail` (optional) on a row with no email takes the address from Kenso's email pool when it holds a recently verified one for the person, free, for the first 25 such rows of the request; a row still without an email is refused unless the campaign is LinkedIn-only. Requires
|
|
9594
|
+
Uses the existing campaign lead upsert, in batches of 100. Accepted and updated rows are succeeded. A later batch can fail without rolling back earlier rows; the upsert is safe to retry. `customImageUrl` sets the lead's own image (an empty string clears it): a malformed URL fails its row before anything is written, and a refused image (campaign images off for the workspace) fails its row with the contact's id, the contact itself saved. `customVideo` sets the lead's own video (a share link or embed code; an empty string clears it): a value no supported provider matches fails its row before anything is written, a refused video (campaign videos off) fails its row with the contact's id, and a video a sent or queued step uses fails its row with code `video_in_use`, the contact saved and the old video kept. `customVariables` is an object of string values merged into the contact's custom variables (a null or empty value clears that key on an existing contact); a key new to the campaign joins its catalog with AI context off. A blank, unusable or reserved key, or more than 50 keys, fails its row before anything is written; a batch that would take the campaign past 50 custom variables fails every row in it. `emailValidity` (optional, `safe` for an email you already verified) qualifies a new contact on import in a campaign without AI qualification, spending one contact allowance; omitted keeps a stored verdict on an existing email. `useKenEmail` (optional) on a row with no email takes the address from Kenso's email pool when it holds a recently verified one for the person, free, for the first 25 such rows of the request; a row still without an email is refused unless the campaign is LinkedIn-only. Requires Campaigns edit. `results` has one item per row in request order: `index`, `status` (`created`, `updated`, `skipped` or `failed`), `id` when saved, and for a skipped or failed row a `reason` (`duplicate`, `blocklisted`, `already_contacted`, `limit_reached`, `invalid_email`, `excluded`, `validation` or `other`) and a `message`. A saved row has `sendable`, false when the contact will not send (added unqualified with no contact allowance left, or do-not-contact).
|
|
9499
9595
|
|
|
9500
9596
|
- API: `POST /v1/campaigns/{campaignId}/contacts`
|
|
9501
9597
|
- Generated from the API contract
|
|
@@ -9517,7 +9613,7 @@ kenso contacts create --campaign-id <campaign-id> --data @body.json
|
|
|
9517
9613
|
|
|
9518
9614
|
Soft-delete one contact.
|
|
9519
9615
|
|
|
9520
|
-
Requires
|
|
9616
|
+
Requires Campaigns edit.
|
|
9521
9617
|
|
|
9522
9618
|
- API: `DELETE /v1/contacts/{contactId}`
|
|
9523
9619
|
- Generated from the API contract
|
|
@@ -9536,7 +9632,7 @@ kenso contacts delete --contact-id <contact-id>
|
|
|
9536
9632
|
|
|
9537
9633
|
List events for one contact.
|
|
9538
9634
|
|
|
9539
|
-
Event ids are the stored event id, which is a string. Requires
|
|
9635
|
+
Event ids are the stored event id, which is a string. Requires Campaigns view. A cursor is valid only with the same `limit` that issued it.
|
|
9540
9636
|
|
|
9541
9637
|
- API: `GET /v1/contacts/{contactId}/events` (a list: `--limit`, `--cursor`, `--all`)
|
|
9542
9638
|
- Generated from the API contract
|
|
@@ -9583,6 +9679,8 @@ kenso contacts export --campaign 812 --wait
|
|
|
9583
9679
|
|
|
9584
9680
|
Return one contact in the current workspace.
|
|
9585
9681
|
|
|
9682
|
+
Also returns `dataFlags` (flags about the contact's data, as stored) and `personalEmails` (personal addresses a data provider found, newest first, for the reader only: never sent to). The list, search and update responses do not have them.
|
|
9683
|
+
|
|
9586
9684
|
- API: `GET /v1/contacts/{contactId}`
|
|
9587
9685
|
- Generated from the API contract
|
|
9588
9686
|
|
|
@@ -9627,7 +9725,7 @@ kenso contacts import --campaign 812 --file big.csv --server-import --yes
|
|
|
9627
9725
|
|
|
9628
9726
|
List contacts in the current workspace.
|
|
9629
9727
|
|
|
9630
|
-
Ordered by id. Requires
|
|
9728
|
+
Ordered by id. Requires Campaigns view. Each contact on the page counts one row of the workspace's `apiReadRows` quota (DEV-3685); past it, 429 `quota_exceeded` with `Retry-After`.
|
|
9631
9729
|
|
|
9632
9730
|
- API: `GET /v1/contacts` (a list: `--limit`, `--cursor`, `--all`)
|
|
9633
9731
|
- Generated from the API contract
|
|
@@ -9660,7 +9758,7 @@ kenso contacts list --all
|
|
|
9660
9758
|
|
|
9661
9759
|
List every scraped website page of the contact's company.
|
|
9662
9760
|
|
|
9663
|
-
One entry per distinct page with its markdown and scrape date. `source` is `archive` for pages copied from the Common Crawl archive (then `scrapedAt` is the archive capture date), `live` for pages Kenso scraped, and `imported` for content supplied in a CSV upload (then `scrapedAt` is the upload time). Ordered home, about, pricing, products, customer pages, careers, then the rest; newest first within a type. Pages without content are left out. At most 50 pages, not paginated. Requires
|
|
9761
|
+
One entry per distinct page with its markdown and scrape date. `source` is `archive` for pages copied from the Common Crawl archive (then `scrapedAt` is the archive capture date), `live` for pages Kenso scraped, and `imported` for content supplied in a CSV upload (then `scrapedAt` is the upload time). Ordered home, about, pricing, products, customer pages, careers, then the rest; newest first within a type. Pages without content are left out. At most 50 pages, not paginated. Requires Campaigns view.
|
|
9664
9762
|
|
|
9665
9763
|
- API: `GET /v1/contacts/{contactId}/website-pages`
|
|
9666
9764
|
- Generated from the API contract
|
|
@@ -9793,7 +9891,7 @@ kenso contacts resume --where '{"campaignIds": [812], "q": "acme"}' --yes
|
|
|
9793
9891
|
|
|
9794
9892
|
Search contacts in the current workspace.
|
|
9795
9893
|
|
|
9796
|
-
Same filters as the list, plus more than one `campaignIds` value, lead `filters` groups, `readyOnly`, and `contactIds`. `q` is the free-text search. Ordered by id unless `sort` is set, in which case the cursor is an offset into that order. No total count. `readyOnly` requires exactly one campaign id. `securityGateway` and `mailboxProvider` filter on the contact's first Safe or Verified email and need security gateways on the workspace (400 otherwise). Requires
|
|
9894
|
+
Same filters as the list, plus more than one `campaignIds` value, lead `filters` groups, `readyOnly`, and `contactIds`. `q` is the free-text search. Ordered by id unless `sort` is set, in which case the cursor is an offset into that order. No total count. `readyOnly` requires exactly one campaign id. `securityGateway` and `mailboxProvider` filter on the contact's first Safe or Verified email and need security gateways on the workspace (400 otherwise). Requires Campaigns view. Pages count on `apiReadRows` like the list.
|
|
9797
9895
|
|
|
9798
9896
|
- API: `POST /v1/contacts/search`
|
|
9799
9897
|
- Generated from the API contract
|
|
@@ -10012,7 +10110,7 @@ kenso credit-model-usage create --data @body.json
|
|
|
10012
10110
|
|
|
10013
10111
|
Return the credit rate card.
|
|
10014
10112
|
|
|
10015
|
-
The price of every credit action. Static: it does not depend on the workspace and sends no `X-Ken-Workspace-Id`. `millicreditsPerUnit` is per one unit; `unitSize` is the quantity prices are usually quoted for. Domain rows apply per whole dollar of `ceil(registrarUsd x 1.03) + 1`. The `web_scrape` row (per 1,000 pages, at 2x Firecrawl cost) is listed only once Kenso's Firecrawl price is configured, and the `podcast_search` row (per 1,000 Firecrawl credits a podcast lookup uses, at 2x Firecrawl cost) with it. The two places rows (a search page of up to 200 places, and a detail, reviews or photos open past 500 free a day) are listed only while Maps Data can run (
|
|
10113
|
+
The price of every credit action. Static: it does not depend on the workspace and sends no `X-Ken-Workspace-Id`. `millicreditsPerUnit` is per one unit; `unitSize` is the quantity prices are usually quoted for. Domain rows apply per whole dollar of `ceil(registrarUsd x 1.03) + 1`. The `web_scrape` row (per 1,000 pages, at 2x Firecrawl cost) is listed only once Kenso's Firecrawl price is configured, and the `podcast_search` row (per 1,000 Firecrawl credits a podcast lookup uses, at 2x Firecrawl cost) with it. The two places rows (a search page of up to 200 places, and a detail, reviews or photos open past 500 free a day) are listed only while Maps Data can run (switched on, with an API key set). Any signed-in person.
|
|
10016
10114
|
|
|
10017
10115
|
- API: `GET /v1/credits/rate-card`
|
|
10018
10116
|
- Generated from the API contract
|
|
@@ -10601,7 +10699,7 @@ kenso crm-sync-issues retry --connection-id <connection-id> --issue-id <issue-id
|
|
|
10601
10699
|
|
|
10602
10700
|
Declare one custom variable.
|
|
10603
10701
|
|
|
10604
|
-
Returns `201` and `Location`. An existing key is updated. Requires
|
|
10702
|
+
Returns `201` and `Location`. An existing key is updated. Requires Campaigns edit.
|
|
10605
10703
|
|
|
10606
10704
|
- API: `POST /v1/campaigns/{campaignId}/custom-variables`
|
|
10607
10705
|
- Generated from the API contract
|
|
@@ -10629,7 +10727,7 @@ kenso custom-variables create --campaign-id <campaign-id> --data @body.json
|
|
|
10629
10727
|
|
|
10630
10728
|
Remove one custom variable.
|
|
10631
10729
|
|
|
10632
|
-
Requires
|
|
10730
|
+
Requires Campaigns edit. Returns `204`.
|
|
10633
10731
|
|
|
10634
10732
|
- API: `DELETE /v1/campaigns/{campaignId}/custom-variables/{variableKey}`
|
|
10635
10733
|
- Generated from the API contract
|
|
@@ -10649,7 +10747,7 @@ kenso custom-variables delete --campaign-id <campaign-id> --variable-key <variab
|
|
|
10649
10747
|
|
|
10650
10748
|
List a campaign's custom variables.
|
|
10651
10749
|
|
|
10652
|
-
Ordered by key. `q` matches the key or the name. Requires
|
|
10750
|
+
Ordered by key. `q` matches the key or the name. Requires Campaigns view.
|
|
10653
10751
|
|
|
10654
10752
|
- API: `GET /v1/campaigns/{campaignId}/custom-variables` (a list: `--limit`, `--cursor`, `--all`)
|
|
10655
10753
|
- Generated from the API contract
|
|
@@ -10673,7 +10771,7 @@ kenso custom-variables list --campaign-id <campaign-id> --all
|
|
|
10673
10771
|
|
|
10674
10772
|
Update one custom variable.
|
|
10675
10773
|
|
|
10676
|
-
Absent fields stay unchanged. Requires
|
|
10774
|
+
Absent fields stay unchanged. Requires Campaigns edit.
|
|
10677
10775
|
|
|
10678
10776
|
- API: `PATCH /v1/campaigns/{campaignId}/custom-variables/{variableKey}`
|
|
10679
10777
|
- Generated from the API contract
|
|
@@ -11097,7 +11195,7 @@ kenso doctor --profile client-a --output json
|
|
|
11097
11195
|
|
|
11098
11196
|
Start a domain health check.
|
|
11099
11197
|
|
|
11100
|
-
Returns `202` with a `domain_health` job. A check already running for the workspace is `409 conflict` and `data.id` is that running job. Requires
|
|
11198
|
+
Returns `202` with a `domain_health` job. A check already running for the workspace is `409 conflict` and `data.id` is that running job. Requires Delivery edit. Example: `{ "domainIds": [4, 9] }`.
|
|
11101
11199
|
|
|
11102
11200
|
- API: `POST /v1/domain-health-checks`
|
|
11103
11201
|
- Generated from the API contract
|
|
@@ -11336,7 +11434,7 @@ kenso domain-orders search --data @body.json
|
|
|
11336
11434
|
|
|
11337
11435
|
Apply one field update to up to 1,000 domains.
|
|
11338
11436
|
|
|
11339
|
-
Requires
|
|
11437
|
+
Requires Delivery edit. Auto-renew requires Delivery edit and the `billing` permission. `websiteMode` (`redirect` or `page`) records the person's answer to "rebuild or redirect"; it cannot be cleared. A `tagIds` entry the workspace has no tag for is `404 not_found`, and nothing is written.
|
|
11340
11438
|
|
|
11341
11439
|
- API: `POST /v1/domains/bulk-update`
|
|
11342
11440
|
- Generated from the API contract
|
|
@@ -11404,7 +11502,7 @@ kenso domains create-inbox --domain-id <domain-id> --data @body.json
|
|
|
11404
11502
|
|
|
11405
11503
|
Delete a domain.
|
|
11406
11504
|
|
|
11407
|
-
Returns `204`. Requires
|
|
11505
|
+
Returns `204`. Requires Delivery edit.
|
|
11408
11506
|
|
|
11409
11507
|
- API: `DELETE /v1/domains/{domainId}`
|
|
11410
11508
|
- Generated from the API contract
|
|
@@ -11496,7 +11594,7 @@ kenso domains list --all
|
|
|
11496
11594
|
|
|
11497
11595
|
Update a domain. Absent fields stay unchanged. Null clears text fields and tag ids.
|
|
11498
11596
|
|
|
11499
|
-
Requires
|
|
11597
|
+
Requires Delivery edit. Auto-renew requires Delivery edit and the `billing` permission. `websiteMode` (`redirect` or `page`) records the person's answer to "rebuild or redirect"; it cannot be cleared. A `tagIds` entry the workspace has no tag for is `404 not_found`, and nothing is written.
|
|
11500
11598
|
|
|
11501
11599
|
- API: `PATCH /v1/domains/{domainId}`
|
|
11502
11600
|
- Generated from the API contract
|
|
@@ -11518,7 +11616,7 @@ kenso domains update --domain-id <domain-id> --data @body.json
|
|
|
11518
11616
|
|
|
11519
11617
|
Verify Kenso tracking DNS for one domain.
|
|
11520
11618
|
|
|
11521
|
-
Requires
|
|
11619
|
+
Requires Delivery edit.
|
|
11522
11620
|
|
|
11523
11621
|
- API: `POST /v1/domains/{domainId}/verify-dns`
|
|
11524
11622
|
- Generated from the API contract
|
|
@@ -11680,7 +11778,7 @@ kenso email-sequences get --campaign-id <campaign-id>
|
|
|
11680
11778
|
|
|
11681
11779
|
Preview the campaign email sequence for one contact.
|
|
11682
11780
|
|
|
11683
|
-
Requires
|
|
11781
|
+
Requires Campaigns view. Variable types are lowercase snake_case. Each step shows the text dispatch sends the contact: a contact routed to another language gets the approved localization with its `language`, English `mirrorSubject` and `mirrorBody`, and `qaScore`. `language` previews as a contact in that language instead. Pass `contactId`, or `useRandom=true` to preview a random contact of the campaign; with neither the call is `400 validation_failed` on `contactId`. A contact outside the campaign, or a campaign with no contacts to pick, is `404 not_found`. `senderEmailId` previews from that inbox of the campaign, as the test send sends from it: its names, signature and unsubscribe host fill the steps, and `sender` names it. Without it, or with an inbox the campaign does not use, the first sender by email fills them.
|
|
11684
11782
|
|
|
11685
11783
|
- API: `GET /v1/campaigns/{campaignId}/email-sequence/preview`
|
|
11686
11784
|
- Generated from the API contract
|
|
@@ -11704,7 +11802,7 @@ kenso email-sequences preview --campaign-id <campaign-id>
|
|
|
11704
11802
|
|
|
11705
11803
|
Replace the campaign email sequence.
|
|
11706
11804
|
|
|
11707
|
-
Creates the sequence when none exists. Requires
|
|
11805
|
+
Creates the sequence when none exists. Requires Campaigns edit. A link the URL reputation check refuses is 400 `validation_failed` with one `link_reputation_blocked` detail per link: `field``steps[i].subject` or `steps[i].body`, `rule`, `stepOrder` and, for a saved step, `stepId`. Send `expectedModifiedAt` (the `modifiedAt` from your last read) so an edit made since is not overwritten.
|
|
11708
11806
|
|
|
11709
11807
|
- API: `PUT /v1/campaigns/{campaignId}/email-sequence`
|
|
11710
11808
|
- Generated from the API contract
|
|
@@ -11730,7 +11828,7 @@ kenso email-sequences replace --campaign-id <campaign-id> --data @body.json
|
|
|
11730
11828
|
|
|
11731
11829
|
Send the campaign email sequence to test recipients.
|
|
11732
11830
|
|
|
11733
|
-
`targetEmails` takes at most 5 valid addresses, none on the workspace blocklist or hard bounced. Once the campaign has inboxes, `senderEmailId` must be one of them. Each recipient x step counts against the workspace's daily test-send emails (429 when used up). Requires
|
|
11831
|
+
`targetEmails` takes at most 5 valid addresses, none on the workspace blocklist or hard bounced. Once the campaign has inboxes, `senderEmailId` must be one of them. Each recipient x step counts against the workspace's daily test-send emails (429 when used up). Requires Campaigns edit. Each step goes out as dispatch sends it to the contact, in the contact's language or in `language`; `notes` names a step sent as an approved translation.
|
|
11734
11832
|
|
|
11735
11833
|
- API: `POST /v1/campaigns/{campaignId}/email-sequence/test-send`
|
|
11736
11834
|
- Generated from the API contract
|
|
@@ -11758,7 +11856,7 @@ kenso email-sequences test-send --campaign-id <campaign-id> --data @body.json
|
|
|
11758
11856
|
|
|
11759
11857
|
Email the conversation to support.
|
|
11760
11858
|
|
|
11761
|
-
Replaces `POST /v1/support-chat/escalate`. The workspace is `X-Ken-Workspace-Id`. Requires `
|
|
11859
|
+
Replaces `POST /v1/support-chat/escalate`. The workspace is `X-Ken-Workspace-Id`. Requires the `ask` permission.
|
|
11762
11860
|
|
|
11763
11861
|
- API: `POST /v1/support/escalations`
|
|
11764
11862
|
- Generated from the API contract
|
|
@@ -13376,7 +13474,7 @@ kenso inbound-webhooks delete --inbound-webhook-id <inbound-webhook-id>
|
|
|
13376
13474
|
|
|
13377
13475
|
List recent deliveries for an inbound webhook.
|
|
13378
13476
|
|
|
13379
|
-
The delivery log has no numeric id, so this window uses `limit` (1 to 100, default 100) and omits `totalCount`. Requires `
|
|
13477
|
+
The delivery log has no numeric id, so this window uses `limit` (1 to 100, default 100) and omits `totalCount`. Requires the `integrations` permission.
|
|
13380
13478
|
|
|
13381
13479
|
- API: `GET /v1/inbound-webhooks/{inboundWebhookId}/deliveries`
|
|
13382
13480
|
- Generated from the API contract
|
|
@@ -13396,7 +13494,7 @@ kenso inbound-webhooks deliveries --inbound-webhook-id <inbound-webhook-id>
|
|
|
13396
13494
|
|
|
13397
13495
|
Return one inbound webhook in the current workspace.
|
|
13398
13496
|
|
|
13399
|
-
A missing or cross-workspace id is `not_found`. Requires `
|
|
13497
|
+
A missing or cross-workspace id is `not_found`. Requires the `integrations` permission.
|
|
13400
13498
|
|
|
13401
13499
|
- API: `GET /v1/inbound-webhooks/{inboundWebhookId}`
|
|
13402
13500
|
- Generated from the API contract
|
|
@@ -13415,7 +13513,7 @@ kenso inbound-webhooks get --inbound-webhook-id <inbound-webhook-id>
|
|
|
13415
13513
|
|
|
13416
13514
|
List a campaign's inbound webhooks in the current workspace.
|
|
13417
13515
|
|
|
13418
|
-
Ordered by id. Read-only. Requires `
|
|
13516
|
+
Ordered by id. Read-only. Requires the `integrations` permission.
|
|
13419
13517
|
|
|
13420
13518
|
- API: `GET /v1/campaigns/{campaignId}/inbound-webhooks` (a list: `--limit`, `--cursor`, `--all`)
|
|
13421
13519
|
- Generated from the API contract
|
|
@@ -13438,7 +13536,7 @@ kenso inbound-webhooks list --campaign-id <campaign-id> --all
|
|
|
13438
13536
|
|
|
13439
13537
|
List the workspace's people webhooks.
|
|
13440
13538
|
|
|
13441
|
-
A people webhook runs lead intake on every delivery: it creates or updates a person (source `form` for the form presets, `visitor` for rb2b and vector, else `webhook`). Ordered by id. A campaign's webhooks are listed under the campaign. Requires the `accounts` and `lead_intake` features. Read-only. Requires `
|
|
13539
|
+
A people webhook runs lead intake on every delivery: it creates or updates a person (source `form` for the form presets, `visitor` for rb2b and vector, else `webhook`). Ordered by id. A campaign's webhooks are listed under the campaign. Requires the `accounts` and `lead_intake` features. Read-only. Requires the `integrations` permission.
|
|
13442
13540
|
|
|
13443
13541
|
- Beta: needs the `accounts` and `lead_intake` feature flag on the workspace.
|
|
13444
13542
|
- API: `GET /v1/inbound-webhooks` (a list: `--limit`, `--cursor`, `--all`)
|
|
@@ -13626,7 +13724,7 @@ kenso inbox-stock get
|
|
|
13626
13724
|
|
|
13627
13725
|
Apply one field update to up to 1,000 inboxes.
|
|
13628
13726
|
|
|
13629
|
-
`paused` pauses or resumes every selected inbox, as on `PATCH /v1/inboxes/{inboxId}`. `profileImageUrl` sets one photo, as on the PATCH, on up to 100 inboxes and takes no other field: `updatedCount` counts the inboxes InboxKit accepted, each other one is in `failed` with the reason. A `tagIds` entry the workspace has no tag for is `404 not_found`, and nothing is written. Needs Delivery edit.
|
|
13727
|
+
`paused` pauses or resumes every selected inbox, as on `PATCH /v1/inboxes/{inboxId}`. `profileImageUrl` sets one photo, as on the PATCH, on up to 100 inboxes and takes no other field: `updatedCount` counts the inboxes InboxKit accepted, each other one is in `failed` with the reason. `forwardingDestination` is set or cleared through InboxKit on each inbox the same way: an inbox InboxKit refused, or one not linked to InboxKit, is in `failed` and left out of `updatedCount`. A destination the request cannot take (malformed, or a Kenso-hosted address), or forwarding being unavailable (InboxKit not configured), is `400`, and nothing is written. A `tagIds` entry the workspace has no tag for is `404 not_found`, and nothing is written. An inbox listed in `failed` is never counted in `updatedCount`, and an id sent twice counts once. Needs Delivery edit.
|
|
13630
13728
|
|
|
13631
13729
|
- API: `POST /v1/inboxes/bulk-update`
|
|
13632
13730
|
- Generated from the API contract
|
|
@@ -13728,7 +13826,7 @@ kenso inboxes create-connect-confirmation --data @body.json
|
|
|
13728
13826
|
|
|
13729
13827
|
Start a Gmail or Microsoft connect.
|
|
13730
13828
|
|
|
13731
|
-
`provider` is `google` or `microsoft`. `purpose` is `primary` (the caller's own mailbox, through the Kenso Workspace app; `not_found` without Kenso Accounts) or `campaign` (a shared campaign mailbox, through Kenso Mail). Open `authorizationUrl` before `expiresAt`; nothing is stored until the connect finishes. It finishes in the Kenso dashboard (DEV-2228): after consent the provider sends the browser there, and the member who created the session (for an API key, its owner) must be signed in, in this workspace. Anyone else is refused and nothing is connected, so a key that names no member cannot finish a connect. Requires delivery edit, like the legacy `authorize` routes. A client seat (Delivery view, `approve_own_sends`) connects only its own primary inbox: `purpose=campaign` is `403 forbidden` with `own_inbox_only`, and a login email off the workspace's email domain (or a workspace with none) is `409 invalid_state` with `email_domain_mismatch`, whose message says what fixes it, because that mailbox would never be its primary inbox. A grant for any mailbox but the caller's login email waits for `POST /v1/inboxes/connect-confirmations`, which needs delivery edit, so a client seat connects only its login email.
|
|
13829
|
+
`provider` is `google` or `microsoft`. `purpose` is `primary` (the caller's own mailbox, through the Kenso Workspace app; `not_found` without Kenso Accounts) or `campaign` (a shared campaign mailbox, through Kenso Mail). Open `authorizationUrl` before `expiresAt`; nothing is stored until the connect finishes. It finishes in the Kenso dashboard (DEV-2228): after consent the provider sends the browser there, and the member who created the session (for an API key, its owner) must be signed in, in this workspace. Anyone else is refused and nothing is connected, so a key that names no member cannot finish a connect. Requires delivery edit, like the legacy `authorize` routes. A client seat (Delivery view, `approve_own_sends`) connects only its own primary inbox: `purpose=campaign` is `403 forbidden` with `own_inbox_only`, and a login email off the workspace's email domain (or a workspace with none) is `409 invalid_state` with `email_domain_mismatch`, whose message says what fixes it, because that mailbox would never be its primary inbox. A grant for any mailbox but the caller's login email waits for `POST /v1/inboxes/connect-confirmations`, which needs delivery edit, so a client seat connects only its login email. Any member may call it; the action then checks delivery edit or `approve_own_sends` (DEV-1811). Optional `returnTo` (DEV-1611) is a dashboard path the finished connect lands on, on the dashboard's own origin, with the usual result query (`gmail=connected`, `microsoft=error&reason=...`); for Microsoft the admin-consent return lands there too. Anything but a relative path with one leading `/`, no `//`, backslash or control characters, at most 512 characters, is `validation_failed` on `returnTo`. Without it the connect returns to the app's default page.
|
|
13732
13830
|
|
|
13733
13831
|
- API: `POST /v1/inboxes/connect-sessions`
|
|
13734
13832
|
- Generated from the API contract
|
|
@@ -13810,7 +13908,7 @@ kenso inboxes get --inbox-id <inbox-id>
|
|
|
13810
13908
|
|
|
13811
13909
|
Return warmup state for one inbox.
|
|
13812
13910
|
|
|
13813
|
-
`status` and `enabled` come from the live warmup provider's own status, picked in the order pause and resume act on. `status` is `pending` while bought warmup waits to activate, and `paused` when it is paused. An Azure inbox with no warmup subscription is `failed`, because Kenso cannot enroll Azure. `readiness` is the cold-send warmup gate's verdict from provider warmup snapshots: `ready`, `bypassed`, `unconfirmed`, `too_young`, `provider_stale`, or `unavailable`.
|
|
13911
|
+
`status` and `enabled` come from the live warmup provider's own status, picked in the order pause and resume act on. `status` is `pending` while bought warmup waits to activate, and `paused` when it is paused. An Azure inbox with no warmup subscription is `failed`, because Kenso cannot enroll Azure. `readiness` is the cold-send warmup gate's verdict from provider warmup snapshots: `ready`, `bypassed`, `unconfirmed`, `too_young`, `provider_stale`, or `unavailable`. Needs Delivery view.
|
|
13814
13912
|
|
|
13815
13913
|
- API: `GET /v1/inboxes/{inboxId}/warmup`
|
|
13816
13914
|
- Generated from the API contract
|
|
@@ -13879,7 +13977,7 @@ kenso inboxes rename --inbox-id <inbox-id> --data @body.json
|
|
|
13879
13977
|
|
|
13880
13978
|
Update an inbox. Absent fields stay unchanged. Null clears text fields and forwarding.
|
|
13881
13979
|
|
|
13882
|
-
`trackOpens` is the owner's Track opens option and exists only on a member's own mailbox (`ownerMemberId` set); on a shared campaign inbox it is `validation_failed`, and anyone but the owner gets `forbidden`. `paused: true` pauses outreach from the inbox and sets `pausedAt` (kept when it is already paused): campaign steps, triggers and approved Accounts 1:1 email wait instead of sending, and new leads are planned on the campaign's other inboxes. `paused: false` resumes it and clears `pausedAt`; held sends go out on the next dispatch. Warmup, reply sync and replies a member sends keep running, and campaign assignments stay. Needs Delivery edit. `profileImageUrl` (https, not null) sets the sender photo: a `POST /v1/inbox-photos` URL as is, any other fetched once (image-from-URL quota), saved only after InboxKit accepts it. Needs the `inbox_photos` flag, else `400` detail code `feature_disabled`, and an inbox Kenso can set (`profilePhotoSupport``google` or `microsoft`), else `400`; either way nothing is written. InboxKit timing out or failing is `503 service_unavailable`: try again. A `tagIds` entry the workspace has no tag for is `404 not_found`, and nothing is written. The update is not atomic: `trackOpens`, then the text fields, then forwarding, then `paused`, then `profileImageUrl` are written in turn, so a failure part-way leaves the earlier ones applied. Each write is idempotent, so retrying the same PATCH is safe.
|
|
13980
|
+
`trackOpens` is the owner's Track opens option and exists only on a member's own mailbox (`ownerMemberId` set); on a shared campaign inbox it is `validation_failed`, and anyone but the owner gets `forbidden`. `paused: true` pauses outreach from the inbox and sets `pausedAt` (kept when it is already paused): campaign steps, triggers and approved Accounts 1:1 email wait instead of sending, and new leads are planned on the campaign's other inboxes. `paused: false` resumes it and clears `pausedAt`; held sends go out on the next dispatch. Warmup, reply sync and replies a member sends keep running, and campaign assignments stay. Needs Delivery edit. `profileImageUrl` (https, not null) sets the sender photo: a `POST /v1/inbox-photos` URL as is, any other fetched once (image-from-URL quota), saved only after InboxKit accepts it. Needs the `inbox_photos` flag, else `400` detail code `feature_disabled`, and an inbox Kenso can set (`profilePhotoSupport``google` or `microsoft`), else `400`; either way nothing is written. InboxKit timing out or failing is `503 service_unavailable`: try again. A `tagIds` entry the workspace has no tag for is `404 not_found`, and nothing is written. A `forwardingDestination` the request cannot take (malformed, or a Kenso-hosted address), forwarding being unavailable (InboxKit not configured), or a `forwardingDestination` (set or null) on an inbox not linked to InboxKit, is `400`, and nothing is written either. The update is not atomic: `trackOpens`, then the text fields, then forwarding, then `paused`, then `profileImageUrl` are written in turn, so a failure part-way leaves the earlier ones applied. Each write is idempotent, so retrying the same PATCH is safe.
|
|
13883
13981
|
|
|
13884
13982
|
- API: `PATCH /v1/inboxes/{inboxId}`
|
|
13885
13983
|
- Generated from the API contract
|
|
@@ -14543,7 +14641,7 @@ kenso jobs cancel --job-id <job-id>
|
|
|
14543
14641
|
|
|
14544
14642
|
Return one job.
|
|
14545
14643
|
|
|
14546
|
-
Requires `type` because the same numeric id can exist in more than one source. An `inbox_import` job carries `inboxImport` with counts and per-row results; one with no progress for 10 minutes reads `failed` with `error.code``interrupted`. A missing or cross-workspace id is `not_found`, and so is another member's `knowledge_export`. Read-only. Each type needs what its own routes need, as on the list; without it the call is `403 permission_denied`. A scraping job's status read sets `X-Ken-Web-Source` and `X-Ken-Credits-Charged`: Kenso's key charges a job as its reads report progress. A crawl or batch scrape returns one Firecrawl status page (about 10 MB at most) per read: when `
|
|
14644
|
+
Requires `type` because the same numeric id can exist in more than one source. An `inbox_import` job carries `inboxImport` with counts and per-row results; one with no progress for 10 minutes reads `failed` with `error.code``interrupted`. A missing or cross-workspace id is `not_found`, and so is another member's `knowledge_export`. Read-only. Each type needs what its own routes need, as on the list; without it the call is `403 permission_denied`. A scraping job's status read sets `X-Ken-Web-Source` and `X-Ken-Credits-Charged`: Kenso's key charges a job as its reads report progress. A crawl or batch scrape returns one Firecrawl status page (about 10 MB at most) per read: when `result.next` is not null, pass it back as `cursor` to read the following page. Other types ignore `cursor`. An `extraction` reads `running` while it runs and `failed` once it failed, with the provider's status body in `result`; only an answer that carries no status is `503 service_unavailable`. A crawl or batch scrape read draws from the Heavy rate-limit class, like the legacy status routes it replaces.
|
|
14547
14645
|
|
|
14548
14646
|
- API: `GET /v1/jobs/{jobId}` (a list: `--limit`, `--cursor`, `--all`)
|
|
14549
14647
|
- Generated from the API contract
|
|
@@ -16522,7 +16620,7 @@ kenso learnings list
|
|
|
16522
16620
|
|
|
16523
16621
|
Start a hosted connect or reconnect session.
|
|
16524
16622
|
|
|
16525
|
-
Omit the account id to connect a new seat. `linkedInAccountId` or `linkedinAccountId` reconnects that seat. A client seat (Delivery view, `approve_own_sends`) connects only its own LinkedIn: reconnecting a seat another member connected is `403 forbidden` with `not_your_linkedin`, and a new seat while it holds one is `409 conflict` with `reconnect_instead`. Requires Delivery edit, or `approve_own_sends` (
|
|
16623
|
+
Omit the account id to connect a new seat. `linkedInAccountId` or `linkedinAccountId` reconnects that seat. A client seat (Delivery view, `approve_own_sends`) connects only its own LinkedIn: reconnecting a seat another member connected is `403 forbidden` with `not_your_linkedin`, and a new seat while it holds one is `409 conflict` with `reconnect_instead`. Requires Delivery edit, or `approve_own_sends` (any member may call it; the action decides, DEV-1811). `importConnections: true` on a new seat imports its connections into Accounts once it connects, while `linkedin_connections_import` is on (ignored otherwise); a reconnect ignores it and keeps the stored setting (DEV-5778).
|
|
16526
16624
|
|
|
16527
16625
|
- API: `POST /v1/linkedin-accounts/connect-sessions`
|
|
16528
16626
|
- Generated from the API contract
|
|
@@ -16684,7 +16782,7 @@ kenso linkedin-accounts update --linkedin-account-id <linkedin-account-id> --dat
|
|
|
16684
16782
|
|
|
16685
16783
|
List the workspace's LinkedIn connections.
|
|
16686
16784
|
|
|
16687
|
-
Filters: `linkedinAccountId` (one seat), `icpStatus` (comma = OR: pending, fit, not_fit, unknown), `jobChanged` (`true`: Kenso Search reported a job change within the network's `jobChangeWindowDays`), `seniority` (comma = OR, Kenso Search levels such as entry, senior, manager, director, vp, c_level, owner, partner), `matchStatus` (comma = OR: pending, matched, not_found, failed), `importStatus` (comma = OR: pending, imported, skipped, dismissed; DEV-5778), `companyDomain` (any domain, URL or email; normalized), `q` (name, title or company name contains; at most 300 characters). `sort`: `-createdAt` (default), `-icpScore` (highest first, unscored last), `-connectedAt` (newest first). Each item carries the person (`fullName`, `headline`, `linkedinUrl`, `connectedAt`), Kenso Search's match (`title`, `seniority`, company fields, `jobChangedAt`, `isJobChanged`, previous company and title), the ICP score (`icpStatus`, `icpScore` 0-100, fit at 70, up to 3 `icpReasons`) and `accountId` when a live account the caller can see owns the company domain, and the connections import (`importStatus`, `personId`, `importedAt`, `importSkipCode`, `importAccountId`). `limit` 1-200 (default 50); a cursor is valid only with the same filters and sort. Requires
|
|
16785
|
+
Filters: `linkedinAccountId` (one seat), `icpStatus` (comma = OR: pending, fit, not_fit, unknown), `jobChanged` (`true`: Kenso Search reported a job change within the network's `jobChangeWindowDays`), `seniority` (comma = OR, Kenso Search levels such as entry, senior, manager, director, vp, c_level, owner, partner), `matchStatus` (comma = OR: pending, matched, not_found, failed), `importStatus` (comma = OR: pending, imported, skipped, dismissed; DEV-5778), `companyDomain` (any domain, URL or email; normalized), `q` (name, title or company name contains; at most 300 characters). `sort`: `-createdAt` (default), `-icpScore` (highest first, unscored last), `-connectedAt` (newest first). Each item carries the person (`fullName`, `headline`, `linkedinUrl`, `connectedAt`), Kenso Search's match (`title`, `seniority`, company fields, `jobChangedAt`, `isJobChanged`, previous company and title), the ICP score (`icpStatus`, `icpScore` 0-100, fit at 70, up to 3 `icpReasons`) and `accountId` when a live account the caller can see owns the company domain, and the connections import (`importStatus`, `personId`, `importedAt`, `importSkipCode`, `importAccountId`). `limit` 1-200 (default 50); a cursor is valid only with the same filters and sort. Requires Accounts view.
|
|
16688
16786
|
|
|
16689
16787
|
- Beta: needs the one of `linkedin_connections_import`, `linkedin_network` feature flag on the workspace.
|
|
16690
16788
|
- API: `GET /v1/linkedin-connections` (a list: `--limit`, `--cursor`, `--all`)
|
|
@@ -16717,7 +16815,7 @@ kenso linkedin-connections list --all
|
|
|
16717
16815
|
|
|
16718
16816
|
Promote LinkedIn connections to Accounts.
|
|
16719
16817
|
|
|
16720
|
-
1 to 100 `connectionIds`. Each matched connection's current company (Kenso Search's company domain) becomes an account, or joins the live account that already owns that domain; connections at one company share one account, and each person becomes a stakeholder (role unknown, source search). A new account starts at `stage` (researching, warming or engaged; default researching) with the caller as owner and queues research; an existing account keeps its stage. `accounts` lists each account with `accountId`, `name`, `domain`, `created`, `research` and `people` (`connectionId`, `personId`, `stakeholderId`, `result` added or already_stakeholder). Connections that were not placed are in `skipped` with a `code`: not_found, not_matched (no Kenso Search match yet), no_company_domain, generic_email_domain, domain_taken (another member's account owns the domain and the caller works only its own accounts), previously_removed (a person removed them from the account; agents and API keys do not re-add them), failed (retry). When none can be placed the answer is `400 validation_failed` with one detail per connection, or 500 when one failed on Kenso's side. Campaign sequences are not touched. Requires
|
|
16818
|
+
1 to 100 `connectionIds`. Each matched connection's current company (Kenso Search's company domain) becomes an account, or joins the live account that already owns that domain; connections at one company share one account, and each person becomes a stakeholder (role unknown, source search). A new account starts at `stage` (researching, warming or engaged; default researching) with the caller as owner and queues research; an existing account keeps its stage. `accounts` lists each account with `accountId`, `name`, `domain`, `created`, `research` and `people` (`connectionId`, `personId`, `stakeholderId`, `result` added or already_stakeholder). Connections that were not placed are in `skipped` with a `code`: not_found, not_matched (no Kenso Search match yet), no_company_domain, generic_email_domain, domain_taken (another member's account owns the domain and the caller works only its own accounts), previously_removed (a person removed them from the account; agents and API keys do not re-add them), failed (retry). When none can be placed the answer is `400 validation_failed` with one detail per connection, or 500 when one failed on Kenso's side. Campaign sequences are not touched. Requires Accounts edit and the `accounts` feature.
|
|
16721
16819
|
|
|
16722
16820
|
- Beta: needs the `accounts` and `linkedin_network` feature flag on the workspace.
|
|
16723
16821
|
- API: `POST /v1/linkedin-connections/promote`
|
|
@@ -16742,7 +16840,7 @@ kenso linkedin-connections promote --data @body.json
|
|
|
16742
16840
|
|
|
16743
16841
|
Get the inbound connection request settings of the caller's LinkedIn seats.
|
|
16744
16842
|
|
|
16745
|
-
`seats` lists the live LinkedIn accounts the caller connected, any mode, oldest first; for a workspace admin also the colleagues' seats that are not off, with `isOwnSeat` false (an admin may only switch those off). Each seat has `linkedinAccountId`, `displayName`, `connectedByMemberId`, `seatStatus` (connecting, connected, credentials_error, restricted, disconnected, deleted, connect_failed), its settings (`mode` off, manual or autonomous; `acceptThreshold` 0-100, default 80; `lane` accounts or campaign; `campaignId`; `sendFirstMessage`; `autonomousEnabledByMemberId`, `autonomousEnabledAt` and `autonomousEnabledVia`: app, the client label of the owner's agent such as Claude Code, or api), its scan (`scanStatus` pending, scanning, idle, paused or blocked; `nextScanAt`, `firstScanCompletedAt`, `lastSuccessAt`, `backoffUntil`, `lastError`) and `counts`: one entry per lane (spam, strong, unclear; omitted before triage) and status (pending_triage, awaiting_decision, accept_queued, accepted, ignored, gone, failed) with a nonzero `count`. A seat never configured shows the defaults (mode off). Requires
|
|
16843
|
+
`seats` lists the live LinkedIn accounts the caller connected, any mode, oldest first; for a workspace admin also the colleagues' seats that are not off, with `isOwnSeat` false (an admin may only switch those off). Each seat has `linkedinAccountId`, `displayName`, `connectedByMemberId`, `seatStatus` (connecting, connected, credentials_error, restricted, disconnected, deleted, connect_failed), its settings (`mode` off, manual or autonomous; `acceptThreshold` 0-100, default 80; `lane` accounts or campaign; `campaignId`; `sendFirstMessage`; `autonomousEnabledByMemberId`, `autonomousEnabledAt` and `autonomousEnabledVia`: app, the client label of the owner's agent such as Claude Code, or api), its scan (`scanStatus` pending, scanning, idle, paused or blocked; `nextScanAt`, `firstScanCompletedAt`, `lastSuccessAt`, `backoffUntil`, `lastError`) and `counts`: one entry per lane (spam, strong, unclear; omitted before triage) and status (pending_triage, awaiting_decision, accept_queued, accepted, ignored, gone, failed) with a nonzero `count`. A seat never configured shows the defaults (mode off). Requires Accounts view.
|
|
16746
16844
|
|
|
16747
16845
|
- Beta: needs the `linkedin_inbound` feature flag on the workspace.
|
|
16748
16846
|
- API: `GET /v1/linkedin-inbound`
|
|
@@ -16763,7 +16861,7 @@ kenso linkedin-inbound get
|
|
|
16763
16861
|
|
|
16764
16862
|
Change one seat's inbound connection request settings.
|
|
16765
16863
|
|
|
16766
|
-
Body (absent fields stay as they are): `mode` (off, manual or autonomous), `acceptThreshold` (0-100, the score at or above which autonomous mode accepts a request by itself), `lane` (accounts or campaign: where accepted leads go), `campaignId` (null clears it) and `sendFirstMessage` (the delayed AI first message, accounts lane only). Lane campaign needs a scheduled or sending campaign of the workspace that sends from this seat (a campaign with no seat list sends from every seat); otherwise `400 validation_failed` with `seat_not_in_campaign` on `campaignId`. Moving to lane accounts does not check the stored campaign, so a seat whose campaign stopped being live can always leave the campaign lane. Only the member who connected the seat may change it; a workspace admin may send exactly `{ "mode": "off" }` for a colleague's seat. Anything else on a colleague's seat is `404 not_found`, so an API key with no user, which connected no seat, changes none. The owner's agent or API key changes the seat as the owner, autonomous mode included (DEV-5878); an agent turns autonomous mode on only when its person asked it to. Its change counts as the owner's: on an autonomous seat Ken then accepts strong fits and sends their AI first messages with no one approving. Turning autonomous mode on, or changing an autonomous seat's other settings, also needs the approve permission, as deciding one request does: without it the answer is `403 permission_denied`. Turning autonomous on stamps `autonomousEnabledVia` (app, the `X-Ken-Client` label, or api), and every save writes a Security audit line naming the caller and its client (DEV-5147). Kenso calls no LinkedIn API here; the background scan reads a seat once it is on. Answers the seat as `linkedin-inbound.get` lists it. Requires
|
|
16864
|
+
Body (absent fields stay as they are): `mode` (off, manual or autonomous), `acceptThreshold` (0-100, the score at or above which autonomous mode accepts a request by itself), `lane` (accounts or campaign: where accepted leads go), `campaignId` (null clears it) and `sendFirstMessage` (the delayed AI first message, accounts lane only). Lane campaign needs a scheduled or sending campaign of the workspace that sends from this seat (a campaign with no seat list sends from every seat); otherwise `400 validation_failed` with `seat_not_in_campaign` on `campaignId`. Moving to lane accounts does not check the stored campaign, so a seat whose campaign stopped being live can always leave the campaign lane. Only the member who connected the seat may change it; a workspace admin may send exactly `{ "mode": "off" }` for a colleague's seat. Anything else on a colleague's seat is `404 not_found`, so an API key with no user, which connected no seat, changes none. The owner's agent or API key changes the seat as the owner, autonomous mode included (DEV-5878); an agent turns autonomous mode on only when its person asked it to. Its change counts as the owner's: on an autonomous seat Ken then accepts strong fits and sends their AI first messages with no one approving. Turning autonomous mode on, or changing an autonomous seat's other settings, also needs the approve permission, as deciding one request does: without it the answer is `403 permission_denied`. Turning autonomous on stamps `autonomousEnabledVia` (app, the `X-Ken-Client` label, or api), and every save writes a Security audit line naming the caller and its client (DEV-5147). Kenso calls no LinkedIn API here; the background scan reads a seat once it is on. Answers the seat as `linkedin-inbound.get` lists it. Requires Accounts edit.
|
|
16767
16865
|
|
|
16768
16866
|
- Beta: needs the `linkedin_inbound` feature flag on the workspace.
|
|
16769
16867
|
- API: `PATCH /v1/linkedin-inbound/seats/{linkedinAccountId}`
|
|
@@ -16794,7 +16892,7 @@ kenso linkedin-inbound-seats update --linkedin-account-id <linkedin-account-id>
|
|
|
16794
16892
|
|
|
16795
16893
|
Withdraw pending invitations on one of the caller's LinkedIn seats.
|
|
16796
16894
|
|
|
16797
|
-
Body: `linkedinAccountId` and exactly one of `invitationIds` (1-100 ids from `linkedin-invitations.list`) and `olderThanDays` (1-365: every pending invitation sent more than that many days ago, except those a campaign lane on the seat still waits on, which follow their campaign's own withdraw rule). Nothing reaches LinkedIn now: the withdraws are queued, and the background withdraw sends them paced with the seat's other LinkedIn actions, inside its working hours, at most 25 a day per seat. LinkedIn blocks inviting a withdrawn person again for about three weeks. With ids the answer is `queued` (how many this request queued), `alreadyQueued` (ids already queued, withdrawn or gone, left as they were) and `notFound` (ids never listed on this seat). With days it starts a sweep that reads the seat's whole sent list first (the seat's withdraws wait while it runs) and answers `sweepId`, `olderThanDays` and `status`; a seat's running sweep is answered as it is. Both or neither field is `400 validation_failed`. A seat that is not connected is `409 invalid_state` with `seat_unavailable`. Requires
|
|
16895
|
+
Body: `linkedinAccountId` and exactly one of `invitationIds` (1-100 ids from `linkedin-invitations.list`) and `olderThanDays` (1-365: every pending invitation sent more than that many days ago, except those a campaign lane on the seat still waits on, which follow their campaign's own withdraw rule). Nothing reaches LinkedIn now: the withdraws are queued, and the background withdraw sends them paced with the seat's other LinkedIn actions, inside its working hours, at most 25 a day per seat. LinkedIn blocks inviting a withdrawn person again for about three weeks. With ids the answer is `queued` (how many this request queued), `alreadyQueued` (ids already queued, withdrawn or gone, left as they were) and `notFound` (ids never listed on this seat). With days it starts a sweep that reads the seat's whole sent list first (the seat's withdraws wait while it runs) and answers `sweepId`, `olderThanDays` and `status`; a seat's running sweep is answered as it is. Both or neither field is `400 validation_failed`. A seat that is not connected is `409 invalid_state` with `seat_unavailable`. Requires Accounts edit and the `approve` permission.
|
|
16798
16896
|
|
|
16799
16897
|
- Beta: needs the `linkedin_inbound` feature flag on the workspace.
|
|
16800
16898
|
- API: `POST /v1/linkedin-invitations/withdrawals`
|
|
@@ -16818,7 +16916,7 @@ kenso linkedin-invitation-withdrawals create --data @body.json
|
|
|
16818
16916
|
|
|
16819
16917
|
List the withdraws asked for on one of the caller's LinkedIn seats.
|
|
16820
16918
|
|
|
16821
|
-
Latest request first. `linkedinAccountId` is required; `status` filters by withdraw status (comma separated: queued, withdrawn, gone, failed). `data.items` are invitations with their `withdrawal` (`status`, `requestedAt`, `requestedVia`, `requestedByMemberId`, `sweepId`, `withdrawnAt`, `error`). `gone` means the invitation was no longer pending on LinkedIn, most likely accepted. `data.sweeps` are the seat's latest 10 sweeps (`status` running, done or failed, `queued`, `scannedPages`, `error`; a done sweep with `page_cap_reached` stopped before the oldest invitations). `data.pagination` pages the items; `limit` 1-200 (default 50), and a cursor is valid only with the same filters. Read from Kenso, so a disconnected seat still shows its history. Requires
|
|
16919
|
+
Latest request first. `linkedinAccountId` is required; `status` filters by withdraw status (comma separated: queued, withdrawn, gone, failed). `data.items` are invitations with their `withdrawal` (`status`, `requestedAt`, `requestedVia`, `requestedByMemberId`, `sweepId`, `withdrawnAt`, `error`). `gone` means the invitation was no longer pending on LinkedIn, most likely accepted. `data.sweeps` are the seat's latest 10 sweeps (`status` running, done or failed, `queued`, `scannedPages`, `error`; a done sweep with `page_cap_reached` stopped before the oldest invitations). `data.pagination` pages the items; `limit` 1-200 (default 50), and a cursor is valid only with the same filters. Read from Kenso, so a disconnected seat still shows its history. Requires Accounts view.
|
|
16822
16920
|
|
|
16823
16921
|
- Beta: needs the `linkedin_inbound` feature flag on the workspace.
|
|
16824
16922
|
- API: `GET /v1/linkedin-invitations/withdrawals` (a list: `--limit`, `--cursor`, `--all`)
|
|
@@ -16845,7 +16943,7 @@ kenso linkedin-invitation-withdrawals list --all
|
|
|
16845
16943
|
|
|
16846
16944
|
List the pending invitations one of the caller's LinkedIn seats sent.
|
|
16847
16945
|
|
|
16848
|
-
Read live from LinkedIn, newest first. `linkedinAccountId` is required. Each item carries `invitationId` (what a withdraw takes), the invitee (`providerId`, `name`, and `publicIdentifier` and `profileUrl` when LinkedIn sends them, which is rare), `sentAt`, the campaign lane on the seat that invited the same person (`campaignId`, `contactId`; omitted for an invitation sent outside Kenso) and `withdrawal` once someone asked to withdraw it. `limit` 1-100 (default 50). A seat that is not connected is `409 invalid_state` with `seat_unavailable`. When LinkedIn limits the seat's reads the answer is `429 rate_limited` with a `Retry-After` header in seconds. Requires
|
|
16946
|
+
Read live from LinkedIn, newest first. `linkedinAccountId` is required. Each item carries `invitationId` (what a withdraw takes), the invitee (`providerId`, `name`, and `publicIdentifier` and `profileUrl` when LinkedIn sends them, which is rare), `sentAt`, the campaign lane on the seat that invited the same person (`campaignId`, `contactId`; omitted for an invitation sent outside Kenso) and `withdrawal` once someone asked to withdraw it. `limit` 1-100 (default 50). A seat that is not connected is `409 invalid_state` with `seat_unavailable`. When LinkedIn limits the seat's reads the answer is `429 rate_limited` with a `Retry-After` header in seconds. Requires Accounts view.
|
|
16849
16947
|
|
|
16850
16948
|
- Beta: needs the `linkedin_inbound` feature flag on the workspace.
|
|
16851
16949
|
- API: `GET /v1/linkedin-invitations` (a list: `--limit`, `--cursor`, `--all`)
|
|
@@ -16871,7 +16969,7 @@ kenso linkedin-invitations list --all
|
|
|
16871
16969
|
|
|
16872
16970
|
List companies where ICP-fit connections work that are not accounts yet.
|
|
16873
16971
|
|
|
16874
|
-
One item per company domain with at least one connection scored fit and no live account owning the domain: `companyDomain`, `companyName`, `kenCompanyId`, `industry`, `employeeCount`, `fitConnectionCount`, `connectionCount`, `topScore` and up to 5 fit `connections`, best score first. Ordered by fit connections, then top score. Promote a company with `linkedin-connections.promote`. `limit` 1-200 (default 50) and `cursor` page by offset. Requires
|
|
16972
|
+
One item per company domain with at least one connection scored fit and no live account owning the domain: `companyDomain`, `companyName`, `kenCompanyId`, `industry`, `employeeCount`, `fitConnectionCount`, `connectionCount`, `topScore` and up to 5 fit `connections`, best score first. Ordered by fit connections, then top score. Promote a company with `linkedin-connections.promote`. `limit` 1-200 (default 50) and `cursor` page by offset. Requires Accounts view.
|
|
16875
16973
|
|
|
16876
16974
|
- Beta: needs the `linkedin_network` feature flag on the workspace.
|
|
16877
16975
|
- API: `GET /v1/linkedin-network/account-suggestions` (a list: `--limit`, `--cursor`, `--all`)
|
|
@@ -16894,7 +16992,7 @@ kenso linkedin-network account-suggestions --all
|
|
|
16894
16992
|
|
|
16895
16993
|
Get the workspace's LinkedIn network: each seat's sync state and the network counts.
|
|
16896
16994
|
|
|
16897
|
-
`seats` lists every live LinkedIn account of the workspace, any status, oldest first. Each seat has `linkedinAccountId`, `displayName`, `connectedByMemberId`, `seatStatus` (connecting, connected, credentials_error, restricted, disconnected, deleted, connect_failed), `pausedAt`, and its connections sync: `status` (not_started, pending, syncing, synced, paused, blocked), `connectionCount`, `totalCount`, `initialSyncCompletedAt`, `lastSuccessAt`, `nextRunAt`, `backoffUntil` and `lastError` (rate_limited, timeout, http_403 and similar). Workspace counts over live connections: `connectionCount`, `matchedCount`, `pendingCount` (match or score still pending), `icpFitCount` (score 70 or more), `jobChangedCount` (Kenso Search job change within `jobChangeWindowDays`), `jobChangedIcpFitCount` and `seniorJobChangedIcpFitCount` (also vp, c_level, owner or partner). `hasIcp` is false while the workspace has no ICP text; connections are then scored unknown. Requires
|
|
16995
|
+
`seats` lists every live LinkedIn account of the workspace, any status, oldest first. Each seat has `linkedinAccountId`, `displayName`, `connectedByMemberId`, `seatStatus` (connecting, connected, credentials_error, restricted, disconnected, deleted, connect_failed), `pausedAt`, and its connections sync: `status` (not_started, pending, syncing, synced, paused, blocked), `connectionCount`, `totalCount`, `initialSyncCompletedAt`, `lastSuccessAt`, `nextRunAt`, `backoffUntil` and `lastError` (rate_limited, timeout, http_403 and similar). Workspace counts over live connections: `connectionCount`, `matchedCount`, `pendingCount` (match or score still pending), `icpFitCount` (score 70 or more), `jobChangedCount` (Kenso Search job change within `jobChangeWindowDays`), `jobChangedIcpFitCount` and `seniorJobChangedIcpFitCount` (also vp, c_level, owner or partner). `hasIcp` is false while the workspace has no ICP text; connections are then scored unknown. Requires Accounts view.
|
|
16898
16996
|
|
|
16899
16997
|
- Beta: needs the one of `linkedin_connections_import`, `linkedin_network` feature flag on the workspace.
|
|
16900
16998
|
- API: `GET /v1/linkedin-network`
|
|
@@ -16913,7 +17011,7 @@ kenso linkedin-network get
|
|
|
16913
17011
|
|
|
16914
17012
|
Ask for a LinkedIn network sync now.
|
|
16915
17013
|
|
|
16916
|
-
Body (optional): `linkedinAccountId`, one live LinkedIn account of the workspace (404 `not_found` otherwise). Without it, every connected, unpaused seat. Each seat becomes due for the background sync now, never sooner than its `backoffUntil`; a `blocked` seat stays blocked until it is reconnected. Connections whose Kenso Search match failed are queued to match again, and when the workspace has ICP text, matched connections scored unknown are queued to score again. Kenso does not call LinkedIn in this request: the sync runs in the background, so poll `linkedin-network.get`. Answers 202 with the same model as `linkedin-network.get`. Requires
|
|
17014
|
+
Body (optional): `linkedinAccountId`, one live LinkedIn account of the workspace (404 `not_found` otherwise). Without it, every connected, unpaused seat. Each seat becomes due for the background sync now, never sooner than its `backoffUntil`; a `blocked` seat stays blocked until it is reconnected. Connections whose Kenso Search match failed are queued to match again, and when the workspace has ICP text, matched connections scored unknown are queued to score again. Kenso does not call LinkedIn in this request: the sync runs in the background, so poll `linkedin-network.get`. Answers 202 with the same model as `linkedin-network.get`. Requires Accounts edit.
|
|
16917
17015
|
|
|
16918
17016
|
- Beta: needs the `linkedin_network` feature flag on the workspace.
|
|
16919
17017
|
- API: `POST /v1/linkedin-network/sync`
|
|
@@ -16938,7 +17036,7 @@ kenso linkedin-network sync --data @body.json
|
|
|
16938
17036
|
|
|
16939
17037
|
Accept or skip a connection request.
|
|
16940
17038
|
|
|
16941
|
-
Body: `action` (`accept_as_lead`: accept, then hand the person to Accounts or the seat's campaign; `accept_only`: accept and add to the network, nothing else; `skip`: hide it, still pending on LinkedIn) and `updatedAt` from the version the person reviewed (optional; a newer version is `409 conflict` with `concurrent_change`). The same decision as the request's item in Approvals. Only a request on a seat the caller connected can be decided; any other id is `404 not_found`. The seat owner's agent or API key decides as the owner (DEV-5878); an agent decides only when its person asked it to. A key with no user connected no seat, so every id is `404` for it. The decision is recorded as the owner's (`decidedBy` person), with `decidedVia` the `X-Ken-Client` label, or api (DEV-5147): on an autonomous seat its accept's AI first message then goes out with no one approving, as the owner's would; a request with a note still waits for approval. An accept works from awaiting_decision or ignored (a rescued spam item), a skip only from awaiting_decision; anything else is `409 invalid_state` with `invalid_transition`. Accepting on a seat that is not connected is `409 invalid_state` with `seat_unavailable`, and on a seat whose inbound mode is off it is `409 invalid_state` with `seat_off`. An accept queues the request: the paced background accept sends it to LinkedIn later. Unknown actions are `400 validation_failed` with `unknown_action`. Answers the request in its new state. Requires
|
|
17039
|
+
Body: `action` (`accept_as_lead`: accept, then hand the person to Accounts or the seat's campaign; `accept_only`: accept and add to the network, nothing else; `skip`: hide it, still pending on LinkedIn) and `updatedAt` from the version the person reviewed (optional; a newer version is `409 conflict` with `concurrent_change`). The same decision as the request's item in Approvals. Only a request on a seat the caller connected can be decided; any other id is `404 not_found`. The seat owner's agent or API key decides as the owner (DEV-5878); an agent decides only when its person asked it to. A key with no user connected no seat, so every id is `404` for it. The decision is recorded as the owner's (`decidedBy` person), with `decidedVia` the `X-Ken-Client` label, or api (DEV-5147): on an autonomous seat its accept's AI first message then goes out with no one approving, as the owner's would; a request with a note still waits for approval. An accept works from awaiting_decision or ignored (a rescued spam item), a skip only from awaiting_decision; anything else is `409 invalid_state` with `invalid_transition`. Accepting on a seat that is not connected is `409 invalid_state` with `seat_unavailable`, and on a seat whose inbound mode is off it is `409 invalid_state` with `seat_off`. An accept queues the request: the paced background accept sends it to LinkedIn later. Unknown actions are `400 validation_failed` with `unknown_action`. Answers the request in its new state. Requires Accounts edit and the `approve` permission.
|
|
16942
17040
|
|
|
16943
17041
|
- Beta: needs the `linkedin_inbound` feature flag on the workspace.
|
|
16944
17042
|
- API: `POST /v1/linkedin-requests/{linkedinRequestId}/decisions`
|
|
@@ -16963,7 +17061,7 @@ kenso linkedin-requests decide --linkedin-request-id <linkedin-request-id> --dat
|
|
|
16963
17061
|
|
|
16964
17062
|
List the connection requests on the caller's LinkedIn seats.
|
|
16965
17063
|
|
|
16966
|
-
Newest first. Filters: `linkedinAccountId` (one of the caller's seats; a colleague's seat lists nothing), `lane` (spam, strong or unclear) and `status` (pending_triage, awaiting_decision, accept_queued, accepted, ignored, gone or failed); `lane=spam&status=ignored` lists the requests Ken hid as spam, which a person can still accept with `linkedin-requests.decide`. Each item carries the person (`fullName`, `headline`, `note`, `linkedinUrl`, `receivedAt`), Kenso Search's match (`matchStatus`, `title`, `seniority`, company fields), the triage (`lane`, `spamCategory` sellers, recruiters_job_seekers, empty_profile or none; `icpScore` 0-100; up to 3 `icpReasons`), the decision (`decision`, `decidedBy` person or autonomous, `decidedByMemberId`, `decidedVia` app, the client label of the owner's agent or api, `decidedAt`), the accept (`acceptedAt`) and the hand-off (`handoffStatus`, `accountId`, `personId`, `contactId`, `campaignId`). `updatedAt` is the decision version. `limit` 1-200 (default 50); a cursor is valid only with the same filters. Requires
|
|
17064
|
+
Newest first. Filters: `linkedinAccountId` (one of the caller's seats; a colleague's seat lists nothing), `lane` (spam, strong or unclear) and `status` (pending_triage, awaiting_decision, accept_queued, accepted, ignored, gone or failed); `lane=spam&status=ignored` lists the requests Ken hid as spam, which a person can still accept with `linkedin-requests.decide`. Each item carries the person (`fullName`, `headline`, `note`, `linkedinUrl`, `receivedAt`), Kenso Search's match (`matchStatus`, `title`, `seniority`, company fields), the triage (`lane`, `spamCategory` sellers, recruiters_job_seekers, empty_profile or none; `icpScore` 0-100; up to 3 `icpReasons`), the decision (`decision`, `decidedBy` person or autonomous, `decidedByMemberId`, `decidedVia` app, the client label of the owner's agent or api, `decidedAt`), the accept (`acceptedAt`) and the hand-off (`handoffStatus`, `accountId`, `personId`, `contactId`, `campaignId`). `updatedAt` is the decision version. `limit` 1-200 (default 50); a cursor is valid only with the same filters. Requires Accounts view.
|
|
16967
17065
|
|
|
16968
17066
|
- Beta: needs the `linkedin_inbound` feature flag on the workspace.
|
|
16969
17067
|
- API: `GET /v1/linkedin-requests` (a list: `--limit`, `--cursor`, `--all`)
|
|
@@ -17114,7 +17212,7 @@ kenso linkedin-sequences save-version --campaign-id <campaign-id> --data @body.j
|
|
|
17114
17212
|
|
|
17115
17213
|
Soft-delete a campaign list that no contact references.
|
|
17116
17214
|
|
|
17117
|
-
A list that still has contacts, including soft-deleted contacts, is `validation_failed`. Requires
|
|
17215
|
+
A list that still has contacts, including soft-deleted contacts, is `validation_failed`. Requires Campaigns edit.
|
|
17118
17216
|
|
|
17119
17217
|
- API: `DELETE /v1/lists/{listId}`
|
|
17120
17218
|
- Generated from the API contract
|
|
@@ -17133,7 +17231,7 @@ kenso lists delete --list-id <list-id>
|
|
|
17133
17231
|
|
|
17134
17232
|
Return one campaign list in the current workspace.
|
|
17135
17233
|
|
|
17136
|
-
A missing or cross-workspace id is `not_found`. Requires
|
|
17234
|
+
A missing or cross-workspace id is `not_found`. Requires Campaigns view.
|
|
17137
17235
|
|
|
17138
17236
|
- API: `GET /v1/lists/{listId}`
|
|
17139
17237
|
- Generated from the API contract
|
|
@@ -17152,7 +17250,7 @@ kenso lists get --list-id <list-id>
|
|
|
17152
17250
|
|
|
17153
17251
|
List a campaign's import lists in the current workspace.
|
|
17154
17252
|
|
|
17155
|
-
Newest first. `limit` and `cursor` page the set. Read-only. Requires
|
|
17253
|
+
Newest first. `limit` and `cursor` page the set. Read-only. Requires Campaigns view.
|
|
17156
17254
|
|
|
17157
17255
|
- API: `GET /v1/campaigns/{campaignId}/lists` (a list: `--limit`, `--cursor`, `--all`)
|
|
17158
17256
|
- Generated from the API contract
|
|
@@ -17715,7 +17813,7 @@ kenso me delete-avatar
|
|
|
17715
17813
|
|
|
17716
17814
|
Return the authenticated caller.
|
|
17717
17815
|
|
|
17718
|
-
Replaces `GET /v1/me/context`, `GET /v1/users/me`, and `GET /v1/workspaces/me`. Read-only.
|
|
17816
|
+
Replaces `GET /v1/me/context`, `GET /v1/users/me`, and `GET /v1/workspaces/me`. Read-only. Open to any signed-in caller. When `X-Ken-Workspace-Id` is present, `role` is the caller's role in that workspace. A Kenso staff caller keeps its own staff role. `features` is always present: the sorted feature flag keys on for the caller, e.g. `["accounts", "studio"]`. The workspace is `X-Ken-Workspace-Id` when the caller may act in it, else the caller's only workspace, else none. Gate UI on it; never on flag rows. `permissions` is always present: the caller's effective permissions in that same workspace (template, pages, features, account scope, monthly credit limit, credits used this month), narrowed by an API key's template. It is null for Kenso staff, when there is no workspace, while the `permissions` feature flag is off for the workspace (the default), or when permissions could not be evaluated (including an API key that no longer resolves). `hasPaidPlan` is always present: whether that same workspace is on a paid plan, null for Kenso staff, when there is no workspace, or when the plan could not be read. `role` is deprecated.
|
|
17719
17817
|
|
|
17720
17818
|
- API: `GET /v1/me`
|
|
17721
17819
|
- Generated from the API contract
|
|
@@ -17771,7 +17869,7 @@ kenso me get-calendar-preferences
|
|
|
17771
17869
|
|
|
17772
17870
|
Return the caller's notification preferences.
|
|
17773
17871
|
|
|
17774
|
-
One row per event: `isEnabled` is the Email toggle as before, `channels` holds the In app, Email, Slack and Teams choices (a saved choice, else the event's default) and `surface` is `classic` or `accounts`. Accounts events are listed when the `notifications` feature is on for the workspace or for any other workspace the caller is a member of, since those workspaces email the caller; their In app, Slack and Teams toggles change only where the feature is on. Always-on system events (billing, onboarding, domain import, access requests) are listed only for a super admin, with `isLocked` true; everyone else gets them on their defaults. `dailyBrief` is the brief time and time zone, and `destinations` the caller's email and Slack channel in the workspace. The workspace is `X-Ken-Workspace-Id` when the caller is a member, else the caller's only workspace, else none. Read-only.
|
|
17872
|
+
One row per event: `isEnabled` is the Email toggle as before, `channels` holds the In app, Email, Slack and Teams choices (a saved choice, else the event's default) and `surface` is `classic` or `accounts`. Accounts events are listed when the `notifications` feature is on for the workspace or for any other workspace the caller is a member of, since those workspaces email the caller; their In app, Slack and Teams toggles change only where the feature is on. Always-on system events (billing, onboarding, domain import, access requests) are listed only for a super admin, with `isLocked` true; everyone else gets them on their defaults. `dailyBrief` is the brief time and time zone, and `destinations` the caller's email and Slack channel in the workspace. The workspace is `X-Ken-Workspace-Id` when the caller is a member, else the caller's only workspace, else none. Read-only. Open to any workspace member.
|
|
17775
17873
|
|
|
17776
17874
|
- API: `GET /v1/me/notification-preferences`
|
|
17777
17875
|
- Generated from the API contract
|
|
@@ -17807,7 +17905,7 @@ kenso me get-preferences
|
|
|
17807
17905
|
|
|
17808
17906
|
Return how the caller signs in.
|
|
17809
17907
|
|
|
17810
|
-
`emailSwitchAvailable` is true when the app may offer to move the caller's Google, Microsoft or LinkedIn sign-in onto an email login (`POST /v1/me/sign-in/switch`): `Auth0:SignInEmailSwitch:Enabled` is on, the caller is a person signed in to the Kenso app (not an API key or an agent), and the account is not a Kenso team or staff one. `409 conflict` when the account no longer signs in with the caller's sign-in: a switch moved it, and the API has not refused that token yet (up to 30 s). Read-only.
|
|
17908
|
+
`emailSwitchAvailable` is true when the app may offer to move the caller's Google, Microsoft or LinkedIn sign-in onto an email login (`POST /v1/me/sign-in/switch`): `Auth0:SignInEmailSwitch:Enabled` is on, the caller is a person signed in to the Kenso app (not an API key or an agent), and the account is not a Kenso team or staff one. `409 conflict` when the account no longer signs in with the caller's sign-in: a switch moved it, and the API has not refused that token yet (up to 30 s). Read-only. Open to any workspace member.
|
|
17811
17909
|
|
|
17812
17910
|
- API: `GET /v1/me/sign-in`
|
|
17813
17911
|
- Generated from the API contract
|
|
@@ -17843,7 +17941,7 @@ kenso me get-signature
|
|
|
17843
17941
|
|
|
17844
17942
|
Connect another Google, LinkedIn or Microsoft work login to the caller's sign-in.
|
|
17845
17943
|
|
|
17846
|
-
The Kenso app calls it after the member signed in to the other login in its link round-trip, with that login's ID token. Only a person signed in to the Kenso app may link: an API key, an MCP client or an agent gets `403 forbidden`. `403 feature_off` unless the `security_actions` feature is on for the workspace. The token must be one Auth0 issued the Kenso app (signature, issuer, audience), at most ten minutes old (`400 login_expired`), else `400 invalid_login`; the provider must have verified its email (`400 unverified_email`), which may differ from the account's; and the login must be Google, LinkedIn or Microsoft work (`400 provider_not_allowed`). Auth0 never marks an Entra email verified, so a Microsoft work login answers `400 unverified_email` unless `Auth0:SignInEmailSwitch:MicrosoftConnectEnabled` is on (DEV-5799): then it links with an unverified email, which is only a label and finds, binds, grants or accepts nothing; the round-trip's fresh sign-in is the proof. `409 already_linked` when it is the caller's own sign-in, or a retry of the caller's own link that Auth0 made (the account below is closed then). `409 login_in_use` when another Kenso account signs in with that login or holds its address, read before any Auth0 change. The one exception is the account Auth0's signup made for this login during the round-trip: made in the last 30 minutes, after the Auth0 login, with no workspace. Auth0 then folds the login into the caller's, so it signs in to this account, and that account is closed (`previousAccount`). `503` when Auth0 cannot be reached or another switch or link runs; when Auth0 did not answer the link, reload the logins before retrying. Records `sign_in.login_linked` in each of the caller's workspaces.
|
|
17944
|
+
The Kenso app calls it after the member signed in to the other login in its link round-trip, with that login's ID token. Only a person signed in to the Kenso app may link: an API key, an MCP client or an agent gets `403 forbidden`. `403 feature_off` unless the `security_actions` feature is on for the workspace. The token must be one Auth0 issued the Kenso app (signature, issuer, audience), at most ten minutes old (`400 login_expired`), else `400 invalid_login`; the provider must have verified its email (`400 unverified_email`), which may differ from the account's; and the login must be Google, LinkedIn or Microsoft work (`400 provider_not_allowed`). Auth0 never marks an Entra email verified, so a Microsoft work login answers `400 unverified_email` unless `Auth0:SignInEmailSwitch:MicrosoftConnectEnabled` is on (DEV-5799): then it links with an unverified email, which is only a label and finds, binds, grants or accepts nothing; the round-trip's fresh sign-in is the proof. `409 already_linked` when it is the caller's own sign-in, or a retry of the caller's own link that Auth0 made (the account below is closed then). `409 login_in_use` when another Kenso account signs in with that login or holds its address, read before any Auth0 change. The one exception is the account Auth0's signup made for this login during the round-trip: made in the last 30 minutes, after the Auth0 login, with no workspace. Auth0 then folds the login into the caller's, so it signs in to this account, and that account is closed (`previousAccount`). `503` when Auth0 cannot be reached or another switch or link runs; when Auth0 did not answer the link, reload the logins before retrying. Records `sign_in.login_linked` in each of the caller's workspaces. Open to any workspace member.
|
|
17847
17945
|
|
|
17848
17946
|
- API: `POST /v1/me/sign-in/link`
|
|
17849
17947
|
- Generated from the API contract
|
|
@@ -17996,7 +18094,7 @@ kenso me register-session --data @body.json
|
|
|
17996
18094
|
|
|
17997
18095
|
Replace the caller's avatar.
|
|
17998
18096
|
|
|
17999
|
-
Multipart field `file` must be a non-empty PNG, JPEG, or WebP under 10 MB.
|
|
18097
|
+
Multipart field `file` must be a non-empty PNG, JPEG, or WebP under 10 MB. Open to any workspace member.
|
|
18000
18098
|
|
|
18001
18099
|
- API: `PUT /v1/me/avatar`
|
|
18002
18100
|
- Generated from the API contract
|
|
@@ -18017,7 +18115,7 @@ kenso me replace-avatar --file ./file.csv
|
|
|
18017
18115
|
|
|
18018
18116
|
Schedule deletion of the caller's account in 14 days.
|
|
18019
18117
|
|
|
18020
|
-
Idempotent while a deletion is already pending. Refused when the caller is the last admin of a workspace.
|
|
18118
|
+
Idempotent while a deletion is already pending. Refused when the caller is the last admin of a workspace. Open to any workspace member.
|
|
18021
18119
|
|
|
18022
18120
|
- API: `POST /v1/me/deletion-request`
|
|
18023
18121
|
- Generated from the API contract
|
|
@@ -18095,7 +18193,7 @@ kenso me revoke-session --session-id <session-id>
|
|
|
18095
18193
|
|
|
18096
18194
|
Move the caller's Google, Microsoft or LinkedIn sign-in onto an email login.
|
|
18097
18195
|
|
|
18098
|
-
The Kenso app calls it once the confirmation link it sent to the new address is opened, with the Auth0 database login it created for that address. Only a person signed in to the Kenso app may switch: an API key, an MCP client or an agent gets `403 forbidden`. `403 feature_off` unless `Auth0:SignInEmailSwitch:Enabled`. The login must be a verified database login for `email`, made for this account and this sign-in, and the address must not be a Kenso team one; it may be the address the old sign-in uses. Its Auth0 organizations are copied first; then the account moves onto it (same user id, workspaces and roles), and the old sign-in is linked into it when Auth0 verified the old sign-in's address, so it still signs in to this account (`linked`), else blocked, then deleted. A failure before the move leaves the account as it was. `409 email_taken` when another Kenso account uses the address, `409 conflict` when the account changed meanwhile, `503` when Auth0 cannot be reached or another switch runs. The caller's token belongs to the retired sign-in: sign the session out afterwards.
|
|
18196
|
+
The Kenso app calls it once the confirmation link it sent to the new address is opened, with the Auth0 database login it created for that address. Only a person signed in to the Kenso app may switch: an API key, an MCP client or an agent gets `403 forbidden`. `403 feature_off` unless `Auth0:SignInEmailSwitch:Enabled`. The login must be a verified database login for `email`, made for this account and this sign-in, and the address must not be a Kenso team one; it may be the address the old sign-in uses. Its Auth0 organizations are copied first; then the account moves onto it (same user id, workspaces and roles), and the old sign-in is linked into it when Auth0 verified the old sign-in's address, so it still signs in to this account (`linked`), else blocked, then deleted. A failure before the move leaves the account as it was. `409 email_taken` when another Kenso account uses the address, `409 conflict` when the account changed meanwhile, `503` when Auth0 cannot be reached or another switch runs. The caller's token belongs to the retired sign-in: sign the session out afterwards. Open to any workspace member. Cleanup contract (DEV-4247). The new login: the Kenso app never deletes it, and a retry reuses its marked login while Auth0 still has it. Before this endpoint has read the login as made for this account and the caller's sign-in, with no account on it, it deletes nothing: `403 feature_off`, a `400` for a malformed request or a login Auth0 does not have, `403` for a login made for another account or sign-in, `409` for a login an account holds, a `503` when another switch runs or Auth0 cannot be read, and `404`. After that, every refusal deletes it (`409 conflict` when the account left the caller's sign-in included), unless the switch's lease ran short: then the refusal keeps the login, whatever it answers, since another submit may be moving the account onto it, and a lease found short before the move answers `503`. The old sign-in: when Auth0 does not answer the link, or refuses the block or the delete, it stays marked retired (until Auth0 confirms the link or the block, then `Auth0:SignInEmailSwitch:RetiredFor`), so its tokens reach no account, and `SignInEmailSwitchCleanupJob` on clickevent.processor retries. The `moved_at` stamp (DEV-4247). Once the account is on the new login, and before the old sign-in is linked or retired, the switch writes `app_metadata.ken_sign_in_switch.moved_at` (ISO-8601 UTC) on that login, in one write with its `ken_user_id` and `from_user_id`. It never writes it before the move commits. The Kenso app finishes a switch whose answer it lost only on that stamp. When Auth0 refuses it, the switch still answers `200`, and `SignInEmailSwitchCleanupJob` writes it. A retry for an account already on that login answers `409 conflict` and writes a missing stamp first.
|
|
18099
18197
|
|
|
18100
18198
|
- API: `POST /v1/me/sign-in/switch`
|
|
18101
18199
|
- Generated from the API contract
|
|
@@ -18118,7 +18216,7 @@ kenso me switch-sign-in --data @body.json
|
|
|
18118
18216
|
|
|
18119
18217
|
Update the caller's profile.
|
|
18120
18218
|
|
|
18121
|
-
`linkedinUrl`, `firstName`, `lastName`, `jobTitle`, `timeZone` and `language`: absent is unchanged, null or blank clears it. Values are trimmed. `firstName` and `lastName` are at most 100 characters, `jobTitle` at most 200, `timeZone` must be an IANA id such as `America/New_York`, and `language` a BCP 47 tag such as `fr` or `fr-FR` (stored cased, so `fr-fr` is `fr-FR`; null means en); otherwise `validation_failed` with one detail per field. The time zone is stored and returned only. A name saved here is kept on later sign-ins. Saving a URL may enqueue a best-effort avatar derivation when no photo exists.
|
|
18219
|
+
`linkedinUrl`, `firstName`, `lastName`, `jobTitle`, `timeZone` and `language`: absent is unchanged, null or blank clears it. Values are trimmed. `firstName` and `lastName` are at most 100 characters, `jobTitle` at most 200, `timeZone` must be an IANA id such as `America/New_York`, and `language` a BCP 47 tag such as `fr` or `fr-FR` (stored cased, so `fr-fr` is `fr-FR`; null means en); otherwise `validation_failed` with one detail per field. The time zone is stored and returned only. A name saved here is kept on later sign-ins. Saving a URL may enqueue a best-effort avatar derivation when no photo exists. Open to any workspace member, since everyone can edit their own profile.
|
|
18122
18220
|
|
|
18123
18221
|
- API: `PATCH /v1/me`
|
|
18124
18222
|
- Generated from the API contract
|
|
@@ -18235,7 +18333,7 @@ kenso me update-notification --notification-id <notification-id> --data @body.js
|
|
|
18235
18333
|
|
|
18236
18334
|
Update the caller's notification preferences.
|
|
18237
18335
|
|
|
18238
|
-
Send only the changed events. Each item sets `isEnabled` (the Email toggle), `channels` (any of `inApp`, `email`, `slack`, `teams`, `push`), or both; `isEnabled` and `channels.email` must agree. Unknown event keys reject the whole request, and so does an `isLocked` event unless the caller is a super admin (detail code `locked`). In app, Slack, Teams and Push on an Accounts event need the `notifications` feature. `dailyBrief.time` is HH:mm and `dailyBrief.timeZone` an IANA time zone. Returns the updated preferences.
|
|
18336
|
+
Send only the changed events. Each item sets `isEnabled` (the Email toggle), `channels` (any of `inApp`, `email`, `slack`, `teams`, `push`), or both; `isEnabled` and `channels.email` must agree. Unknown event keys reject the whole request, and so does an `isLocked` event unless the caller is a super admin (detail code `locked`). In app, Slack, Teams and Push on an Accounts event need the `notifications` feature. `dailyBrief.time` is HH:mm and `dailyBrief.timeZone` an IANA time zone. Returns the updated preferences. Open to any workspace member.
|
|
18239
18337
|
|
|
18240
18338
|
- API: `PATCH /v1/me/notification-preferences`
|
|
18241
18339
|
- Generated from the API contract
|
|
@@ -18952,7 +19050,7 @@ kenso meetings create --data @body.json
|
|
|
18952
19050
|
|
|
18953
19051
|
Plan the meeting's follow-up now ("Draft follow-up").
|
|
18954
19052
|
|
|
18955
|
-
No body. For a meeting that got no automatic follow-up: it plans the touch, and Ken's writer drafts it on its next pass as the meeting's owner (poll GET until `status` leaves planned). It skips the held check and the owner's "Draft a follow-up after each call" setting, and keeps every other rule. `201` with the touch when it planned one; `200` with the existing one when the meeting already has it (one per meeting, never redrafted: rewrite it with POST /v1/touches/{touchId}/rewrite). `409 invalid_state` when the meeting gets none, with the reason as `error.details[0].code`: `no_account`, `private`, `no_touch_stage`, `no_notes`, `no_recipient`, `flag_off` (Ken's writer is off for the workspace) or `follow_up_deleted`. Nothing is sent without an approval. Flags `meetings` and `meeting_follow_up`; meetings edit, and never a client seat.
|
|
19053
|
+
No body. For a meeting that got no automatic follow-up: it plans the touch, and Ken's writer drafts it on its next pass as the meeting's owner (poll GET until `status` leaves planned). It skips the held check and the owner's "Draft a follow-up after each call" setting, and keeps every other rule. `201` with the touch when it planned one; `200` with the existing one when the meeting already has it (one per meeting, never redrafted: rewrite it with POST /v1/touches/{touchId}/rewrite). `409 invalid_state` when the meeting gets none, with the reason as `error.details[0].code`: `no_account`, `private`, `no_touch_stage`, `no_notes`, `no_recipient`, `recipient_suppressed` (the guest unsubscribed, bounced or is on the blocklist), `flag_off` (Ken's writer is off for the workspace) or `follow_up_deleted`. When you already have an email thread with the guest, the follow-up replies in it from the inbox it lives in (`inReplyToMessageId` and `senderInboxId` on the touch); a member's own mailbox only when it is the meeting owner's. Nothing is sent without an approval. Flags `meetings` and `meeting_follow_up`; meetings edit, and never a client seat.
|
|
18956
19054
|
|
|
18957
19055
|
- Beta: needs the `meeting_follow_up` and `meetings` feature flag on the workspace.
|
|
18958
19056
|
- API: `POST /v1/meetings/{meetingId}/follow-up`
|
|
@@ -19238,6 +19336,29 @@ List the meeting's notes sources, the facts they produced and the new people on
|
|
|
19238
19336
|
kenso meetings list-sources --meeting-id <meeting-id>
|
|
19239
19337
|
```
|
|
19240
19338
|
|
|
19339
|
+
### kenso meetings next-step-tasks
|
|
19340
|
+
|
|
19341
|
+
Add a meeting's next steps as tasks.
|
|
19342
|
+
|
|
19343
|
+
Body `{ "lines": [ { "text": "Send the pilot pricing to Maya", "dueAt": "2026-11-05T09:00:00Z" } ] }`: 1 to 20 lines, each `text` trimmed with whitespace runs made one space, then 1 to 500 characters, `dueAt` optional (without it the task is due now). Each line becomes one touch on the meeting's account: `channel` task, `reason` manual, `meetingId` the meeting, `title` the line (a line over 200 characters is cut at a word with "…" for the title and kept whole as the `body`), created by the caller. Returns `{ "items": [...], "created": 1 }`, each item the touch as GET /v1/touches/{touchId} returns it, in line order, and `created`, the number of tasks this request wrote (always present, `0` included). Safe to retry: a line that already has its task (the same text, ignoring case and spacing) returns it and writes nothing, so a repeated line is one task. A line whose task was deleted stays deleted: it is left out of `items` and listed in `skipped` as `{ "text", "reason": "deleted" }` (`not_visible` for a task on an account you cannot see). `201` when it created a task, `200` when every line already had one. `400 validation_failed` for no lines, more than 20, or a blank or too long line (nothing written); `404` for a meeting you cannot see; `409 invalid_state` with `error.details[0].code``no_account` when the meeting has no account (or one outside your account scope). Nothing is sent. Flags `meetings` and `accounts`; meetings edit and accounts edit, and never a client seat.
|
|
19344
|
+
|
|
19345
|
+
- Beta: needs the `accounts` and `meetings` feature flag on the workspace.
|
|
19346
|
+
- API: `POST /v1/meetings/{meetingId}/next-step-tasks`
|
|
19347
|
+
- Generated from the API contract
|
|
19348
|
+
- Request body: json (`kenso describe meetings next-step-tasks` prints its schema)
|
|
19349
|
+
|
|
19350
|
+
| Flag | Type | Required | Description |
|
|
19351
|
+
| --- | --- | --- | --- |
|
|
19352
|
+
| `--meeting-id` | string | yes | meetingId (path, string) |
|
|
19353
|
+
| `--data` | json | no | Request body as JSON: inline, @file or - for stdin. Flags win over its keys. |
|
|
19354
|
+
| `--each` | string | no | Run once per row of a JSONL or CSV file (- for stdin); row keys fill params and body by name. |
|
|
19355
|
+
| `--concurrency` | integer | no | With --each: requests in flight at once (1-16, default 4). |
|
|
19356
|
+
|
|
19357
|
+
```bash
|
|
19358
|
+
kenso meetings next-step-tasks --meeting-id <meeting-id>
|
|
19359
|
+
kenso meetings next-step-tasks --meeting-id <meeting-id> --data @body.json
|
|
19360
|
+
```
|
|
19361
|
+
|
|
19241
19362
|
### kenso meetings regenerate-notes
|
|
19242
19363
|
|
|
19243
19364
|
Rewrite the meeting's notes in another template.
|
|
@@ -19283,6 +19404,33 @@ An attached source loses its transcript and the Knowledge rows it produced; a di
|
|
|
19283
19404
|
kenso meetings remove-source --meeting-id <meeting-id> --source-id <source-id>
|
|
19284
19405
|
```
|
|
19285
19406
|
|
|
19407
|
+
### kenso meetings rename-speaker
|
|
19408
|
+
|
|
19409
|
+
Rename a transcript speaker: name them as one of the meeting's participants, or type a name.
|
|
19410
|
+
|
|
19411
|
+
Body `{ "speaker": "Speaker 2", "participantId": 502 }` or `{ "speaker": "Speaker 2", "name": "Jane Doe" }`. `speaker` is the name the transcript shows now (or the label it had before any rename). `participantId` is one of this meeting's participants (`participants[].id` on `GET /v1/meetings/{meetingId}`): their name and email are kept, and the turns match them by email from then on. Otherwise `name` is a typed name, 1 to 120 characters. Neither clears the rename. Every turn of that speaker changes. `source` picks the transcript (`notetaker` or an import's provider such as `fireflies`); without it, the stored transcript the GET returns. The rename reaches every later read (this route, the live view, the MCP, follow-up drafts, call scoring) but is not retroactive: notes already written keep the old names until they are regenerated. While Kenso is still recording, a rename applies to the stored transcript: the answer is that transcript, not the live lines, and a speaker only the live lines have is 422. The meeting's owner or a workspace admin only (403 `forbidden` otherwise); an agent or an API key renames as its member. Returns the transcript as the GET does, with the new names. 400 `validation_failed` for a missing speaker or a bad name; 404 for a meeting you cannot see or a source with no transcript you may read; 422 `validation_error` for a participant not in this meeting or a speaker no turn has; 409 `conflict` when the transcript kept changing (read it again and retry). Flag `meetings`; meetings edit.
|
|
19412
|
+
|
|
19413
|
+
- Beta: needs the `meetings` feature flag on the workspace.
|
|
19414
|
+
- API: `PATCH /v1/meetings/{meetingId}/transcript/speakers`
|
|
19415
|
+
- Generated from the API contract
|
|
19416
|
+
- Request body: json (`kenso describe meetings rename-speaker` prints its schema)
|
|
19417
|
+
|
|
19418
|
+
| Flag | Type | Required | Description |
|
|
19419
|
+
| --- | --- | --- | --- |
|
|
19420
|
+
| `--meeting-id` | string | yes | meetingId (path, string) |
|
|
19421
|
+
| `--speaker` | string | no | speaker (body, string) |
|
|
19422
|
+
| `--name` | string | no | name (body, string) |
|
|
19423
|
+
| `--participant-id` | integer | no | participantId (body, integer) |
|
|
19424
|
+
| `--source` | string | no | source (body, string) |
|
|
19425
|
+
| `--data` | json | no | Request body as JSON: inline, @file or - for stdin. Flags win over its keys. |
|
|
19426
|
+
| `--each` | string | no | Run once per row of a JSONL or CSV file (- for stdin); row keys fill params and body by name. |
|
|
19427
|
+
| `--concurrency` | integer | no | With --each: requests in flight at once (1-16, default 4). |
|
|
19428
|
+
|
|
19429
|
+
```bash
|
|
19430
|
+
kenso meetings rename-speaker --meeting-id <meeting-id>
|
|
19431
|
+
kenso meetings rename-speaker --meeting-id <meeting-id> --data @body.json
|
|
19432
|
+
```
|
|
19433
|
+
|
|
19286
19434
|
### kenso meetings replace-brief
|
|
19287
19435
|
|
|
19288
19436
|
Save a brief you wrote as the meeting's new version.
|
|
@@ -19353,9 +19501,9 @@ kenso meetings score-call --meeting-id <meeting-id>
|
|
|
19353
19501
|
|
|
19354
19502
|
### kenso meetings update
|
|
19355
19503
|
|
|
19356
|
-
Move a meeting to another account, clear its account,
|
|
19504
|
+
Move a meeting to another account, clear its account, make it private or shared, or choose whether the Kenso Notetaker bot joins.
|
|
19357
19505
|
|
|
19358
|
-
Body: `accountId` (an account you can see, or null to clear it; else `400`; a meeting with no account gets one only from its owner, else `403`)
|
|
19506
|
+
Body: `accountId` (an account you can see, or null to clear it; else `400`; a meeting with no account gets one only from its owner, else `403`), `isPrivate` (true or false; only the meeting's owner and workspace admins, else `403`) and `botMode` (auto, send or skip, else `400`; only the meeting's owner and workspace admins, else `403`; `403` with detail `feature_disabled` while the workspace does not have the Kenso Notetaker bot; skip takes back a bot waiting to join). Absent fields stay unchanged, and an unknown field is `400`. Changing the account moves no stage and stops nothing. Making a meeting private writes one `meeting.made_private` timeline row. `409 conflict` when the meeting kept changing while it was saved: read it again and retry. Returns the meeting with its capture and bot.
|
|
19359
19507
|
|
|
19360
19508
|
- Beta: needs the `meetings` feature flag on the workspace.
|
|
19361
19509
|
- API: `PATCH /v1/meetings/{meetingId}`
|
|
@@ -19367,6 +19515,7 @@ Body: `accountId` (an account you can see, or null to clear it; else `400`; a me
|
|
|
19367
19515
|
| `--meeting-id` | string | yes | meetingId (path, string) |
|
|
19368
19516
|
| `--account-id` | integer | no | accountId (body, integer) |
|
|
19369
19517
|
| `--is-private` | boolean | no | isPrivate (body, boolean) |
|
|
19518
|
+
| `--bot-mode` | string | no | botMode (body, string) |
|
|
19370
19519
|
| `--no-is-private` | boolean | no | Send isPrivate as false. |
|
|
19371
19520
|
| `--data` | json | no | Request body as JSON: inline, @file or - for stdin. Flags win over its keys. |
|
|
19372
19521
|
| `--each` | string | no | Run once per row of a JSONL or CSV file (- for stdin); row keys fill params and body by name. |
|
|
@@ -19635,7 +19784,7 @@ kenso members update --member-id <member-id> --data @body.json
|
|
|
19635
19784
|
|
|
19636
19785
|
Start Microsoft's admin consent for Teams transcripts.
|
|
19637
19786
|
|
|
19638
|
-
Returns Microsoft's admin-consent page for the Ken Workspace app with the two Teams transcript permissions (`OnlineMeetings.Read` and `OnlineMeetingTranscript.Read.All`), and when the link expires (7 days, since it is often forwarded to the tenant's Microsoft admin). Open it in the browser; a Microsoft admin of the members' tenant approves. Microsoft then sends the browser back to Ken, which lands on `returnTo` with `teams_consent=granted` (members waiting on the approval are searched again), `teams_consent=denied` (declined, or Microsoft failed) or `teams_consent=invalid` (an expired or altered link). Nothing is stored until then. `returnTo` is a dashboard path (at most 512 characters, a single leading `/`); omitted, `/
|
|
19787
|
+
Returns Microsoft's admin-consent page for the Ken Workspace app with the two Teams transcript permissions (`OnlineMeetings.Read` and `OnlineMeetingTranscript.Read.All`), and when the link expires (7 days, since it is often forwarded to the tenant's Microsoft admin). Open it in the browser; a Microsoft admin of the members' tenant approves. Microsoft then sends the browser back to Ken, which lands on `returnTo` with `teams_consent=granted` (members waiting on the approval are searched again), `teams_consent=denied` (declined, or Microsoft failed) or `teams_consent=invalid` (an expired or altered link). Nothing is stored until then. `returnTo` is a dashboard path (at most 512 characters, a single leading `/`); omitted, `/settings/integrations/teams`. `400 validation_failed` for any other `returnTo`, `503 service_unavailable` while Ken's Microsoft app is not configured. Workspace admins only, as a person in Ken: an agent or an API key gets `403`.
|
|
19639
19788
|
|
|
19640
19789
|
- Beta: needs the `meetings` and `native_transcripts` feature flag on the workspace.
|
|
19641
19790
|
- API: `POST /v1/integrations/microsoft-teams/admin-consent-sessions`
|
|
@@ -19644,7 +19793,7 @@ Returns Microsoft's admin-consent page for the Ken Workspace app with the two Te
|
|
|
19644
19793
|
|
|
19645
19794
|
| Flag | Type | Required | Description |
|
|
19646
19795
|
| --- | --- | --- | --- |
|
|
19647
|
-
| `--return-to` | string | no | The dashboard path Microsoft's admin-consent page returns to, at most 512 characters, starting with a single `/`. Omitted: `/
|
|
19796
|
+
| `--return-to` | string | no | The dashboard path Microsoft's admin-consent page returns to, at most 512 characters, starting with a single `/`. Omitted: `/settings/integrations/teams`. |
|
|
19648
19797
|
| `--data` | json | no | Request body as JSON: inline, @file or - for stdin. Flags win over its keys. |
|
|
19649
19798
|
| `--each` | string | no | Run once per row of a JSONL or CSV file (- for stdin); row keys fill params and body by name. |
|
|
19650
19799
|
| `--concurrency` | integer | no | With --each: requests in flight at once (1-16, default 4). |
|
|
@@ -19686,7 +19835,7 @@ kenso migration-connections create --data @body.json
|
|
|
19686
19835
|
|
|
19687
19836
|
Finish connecting Outreach.
|
|
19688
19837
|
|
|
19689
|
-
Send the `code`, `state` and `error` Outreach returned, with `provider``outreach`, signed in to the dashboard as the member who started the connect, in the workspace it was started in. `data.returnUrl` is the Kenso app path to land on, `/{workspaceId}/
|
|
19838
|
+
Send the `code`, `state` and `error` Outreach returned, with `provider``outreach`, signed in to the dashboard as the member who started the connect, in the workspace it was started in. `data.returnUrl` is the Kenso app path to land on, `/{workspaceId}/settings/import` with `outreach=connected&connectionId={id}`, or `outreach=error&reason=...` with `provider_error` (declined, or Outreach failed), `exchange_failed`, `scope_required` (a permission was not granted), `key_rejected`, `vendor_error`, `vendor_unavailable`, `not_found`, `run_already_active`, `account_mismatch` (a reconnect of a connection that discovered or ran, with another Outreach organization or one Kenso cannot confirm: add it as a new connection), `discovery_changed` or `save_failed`. A state that is expired, unreadable, or was started by another member or in another workspace is `validation_failed` with `invalid_state` in `error.details[0].code`, and nothing is exchanged. An API key, MCP or agent call is `forbidden`.
|
|
19690
19839
|
|
|
19691
19840
|
- Beta: needs the `migrations` feature flag on the workspace.
|
|
19692
19841
|
- API: `POST /v1/migration-connections/connect-completions`
|
|
@@ -20052,7 +20201,7 @@ kenso migration-vendors list
|
|
|
20052
20201
|
|
|
20053
20202
|
Create a model configuration for a campaign in the current workspace.
|
|
20054
20203
|
|
|
20055
|
-
Returns `201` and `Location`. A campaign outside the workspace is `not_found` before the write. Requires
|
|
20204
|
+
Returns `201` and `Location`. A campaign outside the workspace is `not_found` before the write. Requires Campaigns edit.
|
|
20056
20205
|
|
|
20057
20206
|
- API: `POST /v1/model-configurations`
|
|
20058
20207
|
- Generated from the API contract
|
|
@@ -20080,7 +20229,7 @@ kenso model-configurations create --data @body.json
|
|
|
20080
20229
|
|
|
20081
20230
|
Delete a model configuration in the current workspace.
|
|
20082
20231
|
|
|
20083
|
-
Returns `204`. A configuration outside the workspace is `not_found` before the delete. Requires
|
|
20232
|
+
Returns `204`. A configuration outside the workspace is `not_found` before the delete. Requires Campaigns edit.
|
|
20084
20233
|
|
|
20085
20234
|
- API: `DELETE /v1/model-configurations/{modelConfigurationId}`
|
|
20086
20235
|
- Generated from the API contract
|
|
@@ -20099,7 +20248,7 @@ kenso model-configurations delete --model-configuration-id <model-configuration-
|
|
|
20099
20248
|
|
|
20100
20249
|
Return one model configuration in the current workspace.
|
|
20101
20250
|
|
|
20102
|
-
A missing id, or one whose campaign is outside the workspace, is `not_found`. Requires
|
|
20251
|
+
A missing id, or one whose campaign is outside the workspace, is `not_found`. Requires Campaigns view.
|
|
20103
20252
|
|
|
20104
20253
|
- API: `GET /v1/model-configurations/{modelConfigurationId}`
|
|
20105
20254
|
- Generated from the API contract
|
|
@@ -20118,7 +20267,7 @@ kenso model-configurations get --model-configuration-id <model-configuration-id>
|
|
|
20118
20267
|
|
|
20119
20268
|
List model configurations for a campaign in the current workspace.
|
|
20120
20269
|
|
|
20121
|
-
`campaignId` is required. A campaign outside `X-Ken-Workspace-Id` is `not_found` before the list is read. Optional `flow` narrows the page. Requires
|
|
20270
|
+
`campaignId` is required. A campaign outside `X-Ken-Workspace-Id` is `not_found` before the list is read. Optional `flow` narrows the page. Requires Campaigns view.
|
|
20122
20271
|
|
|
20123
20272
|
- API: `GET /v1/model-configurations` (a list: `--limit`, `--cursor`, `--all`)
|
|
20124
20273
|
- Generated from the API contract
|
|
@@ -20142,7 +20291,7 @@ kenso model-configurations list --all
|
|
|
20142
20291
|
|
|
20143
20292
|
Update a model configuration in the current workspace.
|
|
20144
20293
|
|
|
20145
|
-
Absent fields stay unchanged. A configuration outside the workspace is `not_found` before the write. Requires
|
|
20294
|
+
Absent fields stay unchanged. A configuration outside the workspace is `not_found` before the write. Requires Campaigns edit.
|
|
20146
20295
|
|
|
20147
20296
|
- API: `PATCH /v1/model-configurations/{modelConfigurationId}`
|
|
20148
20297
|
- Generated from the API contract
|
|
@@ -20388,7 +20537,7 @@ kenso onboarding get
|
|
|
20388
20537
|
|
|
20389
20538
|
Update the signed-in user's onboarding progress.
|
|
20390
20539
|
|
|
20391
|
-
Replaces `PATCH /v1/onboarding/progress`. Null fields are left unchanged. `segment` is `new_to_outbound`, `experienced`, or `expert_ai`. `lane` is `before_launch` or `after_launch`. `answers` is a JSON object that replaces the stored one, at most 262,144 bytes as compact JSON; anything else is `400 validation_failed`. Setting `completedAt` no
|
|
20540
|
+
Replaces `PATCH /v1/onboarding/progress`. Null fields are left unchanged. `segment` is `new_to_outbound`, `experienced`, or `expert_ai`. `lane` is `before_launch` or `after_launch`. `answers` is a JSON object that replaces the stored one, at most 262,144 bytes as compact JSON; anything else is `400 validation_failed`. Setting `completedAt` turns no feature flag on. Saved answers with `mode: recruiting` turn `recruiting` on for the resolved workspace (DEV-1274). Works before the caller has a workspace. Requires a signed-in user.
|
|
20392
20541
|
|
|
20393
20542
|
- API: `PATCH /v1/onboarding`
|
|
20394
20543
|
- Generated from the API contract
|
|
@@ -20899,7 +21048,7 @@ kenso optiverse-connection get
|
|
|
20899
21048
|
|
|
20900
21049
|
Add up to 500 attendees, exhibitors, speakers or sponsors to an outbound event.
|
|
20901
21050
|
|
|
20902
|
-
Body: `source` (required: csv, url, manual, api, paste, xlsx, pdf or image, or a Find with Ken source: company_people, prospectus, profile_mention, inbox_mention or last_year), `sourceUrl` (http or https, up to 2048 characters) and `items` (1 to 500). Each item has `role` (required: attendee, exhibitor, speaker or sponsor) and any of `fullName`, `firstName`, `lastName`, `title`, `email`, `linkedinUrl`, `companyName` and `companyDomain` (a domain, website URL or work email; without it, a work email's domain is used), and must name a person (a full name, first and last name, email or LinkedIn URL) or a company. Example: `{ "source": "url", "sourceUrl": "https://example.com/speakers", "items": [ { "role": "speaker", "fullName": "Maya Chen", "title": "VP Sales", "companyName": "Northwind", "companyDomain": "northwind.com" } ] }`. Returns 200 with `succeeded`, `failed` and one result per item in request order: `created` (with `id`), `duplicate` (with the `id` of the row already on the event with the same role and the same email, else LinkedIn URL, else name and company, else company; counted in succeeded) or `validation_failed` (with `error`; counted in failed). A duplicate fills the stored row's blank `title` and `companyDomain` from the item, and a filled domain marks the row matched (source `input`), so resending a row with its domain corrects an unmatched one. Rows with no company domain are looked up in Kenso Search during this call: the company by name, the person by first name, last name and company. A failed lookup marks the row `failed` and never fails the request; sending the row again retries it. Another workspace's event is `404`. Requires
|
|
21051
|
+
Body: `source` (required: csv, url, manual, api, paste, xlsx, pdf or image, or a Find with Ken source: company_people, prospectus, profile_mention, inbox_mention or last_year), `sourceUrl` (http or https, up to 2048 characters) and `items` (1 to 500). Each item has `role` (required: attendee, exhibitor, speaker or sponsor) and any of `fullName`, `firstName`, `lastName`, `title`, `email`, `linkedinUrl`, `companyName` and `companyDomain` (a domain, website URL or work email; without it, a work email's domain is used), and must name a person (a full name, first and last name, email or LinkedIn URL) or a company. Example: `{ "source": "url", "sourceUrl": "https://example.com/speakers", "items": [ { "role": "speaker", "fullName": "Maya Chen", "title": "VP Sales", "companyName": "Northwind", "companyDomain": "northwind.com" } ] }`. Returns 200 with `succeeded`, `failed` and one result per item in request order: `created` (with `id`), `duplicate` (with the `id` of the row already on the event with the same role and the same email, else LinkedIn URL, else name and company, else company; counted in succeeded) or `validation_failed` (with `error`; counted in failed). A duplicate fills the stored row's blank `title` and `companyDomain` from the item, and a filled domain marks the row matched (source `input`), so resending a row with its domain corrects an unmatched one. Rows with no company domain are looked up in Kenso Search during this call: the company by name, the person by first name, last name and company. A failed lookup marks the row `failed` and never fails the request; sending the row again retries it. Another workspace's event is `404`. Requires Accounts edit.
|
|
20903
21052
|
|
|
20904
21053
|
- Beta: needs the `accounts` and `event_outbound` feature flag on the workspace.
|
|
20905
21054
|
- API: `POST /v1/outbound-events/{eventId}/attendees/bulk-create`
|
|
@@ -20924,7 +21073,7 @@ kenso outbound-event-attendees bulk-create --event-id <event-id> --data @body.js
|
|
|
20924
21073
|
|
|
20925
21074
|
Remove one attendee, exhibitor, speaker or sponsor from its event.
|
|
20926
21075
|
|
|
20927
|
-
Soft delete; returns `204`. The same person or company can be added again afterwards. A row of another workspace, or of a deleted event, is `404 not_found`. Requires
|
|
21076
|
+
Soft delete; returns `204`. The same person or company can be added again afterwards. A row of another workspace, or of a deleted event, is `404 not_found`. Requires Accounts edit.
|
|
20928
21077
|
|
|
20929
21078
|
- Beta: needs the `accounts` and `event_outbound` feature flag on the workspace.
|
|
20930
21079
|
- API: `DELETE /v1/outbound-event-attendees/{attendeeId}`
|
|
@@ -20944,7 +21093,7 @@ kenso outbound-event-attendees delete --attendee-id <attendee-id>
|
|
|
20944
21093
|
|
|
20945
21094
|
List an outbound event's attendees, exhibitors, speakers and sponsors.
|
|
20946
21095
|
|
|
20947
|
-
Filters: `role` (comma = OR: attendee, exhibitor, speaker, sponsor) and `account` (`matched`: the row's company domain belongs to a live account; `unmatched`: every other row). `limit` 1-500 (default 100) and `cursor` page by id, oldest first. Each row carries `account` (the matched account with its stage and this event's Event touch, else null), `personId` (a person in the workspace with the row's email, else its LinkedIn URL) and `stakeholderId` (that person on that account). With account scope `own`, only accounts the caller owns and their people match. Another workspace's event is `404`. Requires
|
|
21096
|
+
Filters: `role` (comma = OR: attendee, exhibitor, speaker, sponsor) and `account` (`matched`: the row's company domain belongs to a live account; `unmatched`: every other row). `limit` 1-500 (default 100) and `cursor` page by id, oldest first. Each row carries `account` (the matched account with its stage and this event's Event touch, else null), `personId` (a person in the workspace with the row's email, else its LinkedIn URL) and `stakeholderId` (that person on that account). With account scope `own`, only accounts the caller owns and their people match. Another workspace's event is `404`. Requires Accounts view.
|
|
20948
21097
|
|
|
20949
21098
|
- Beta: needs the `accounts` and `event_outbound` feature flag on the workspace.
|
|
20950
21099
|
- API: `GET /v1/outbound-events/{eventId}/attendees` (a list: `--limit`, `--cursor`, `--all`)
|
|
@@ -20972,7 +21121,7 @@ kenso outbound-event-attendees list --event-id <event-id> --all
|
|
|
20972
21121
|
|
|
20973
21122
|
Add a suggested event as an outbound event.
|
|
20974
21123
|
|
|
20975
|
-
Creates a normal outbound event from the suggestion (name, dates, timezone, format, city, venue and url), ready for an attendee list (`POST /v1/outbound-events/{eventId}/extract-attendees` reads its page), and marks the suggestion `added` with that `eventId`. The body is optional: `{ "attendance": "going" }` (or `not_going`) sets the new event's `attendance`; without it the event is not decided (`null`). Any other attendance is `400 validation_failed`. Returns `200` with `{ suggestion, event }`. A suggestion that is not `suggested` (already added or dismissed) is `409 invalid_state`; another workspace's is `404`. Requires
|
|
21124
|
+
Creates a normal outbound event from the suggestion (name, dates, timezone, format, city, venue and url), ready for an attendee list (`POST /v1/outbound-events/{eventId}/extract-attendees` reads its page), and marks the suggestion `added` with that `eventId`. The body is optional: `{ "attendance": "going" }` (or `not_going`) sets the new event's `attendance`; without it the event is not decided (`null`). Any other attendance is `400 validation_failed`. Returns `200` with `{ suggestion, event }`. A suggestion that is not `suggested` (already added or dismissed) is `409 invalid_state`; another workspace's is `404`. Requires Accounts edit.
|
|
20976
21125
|
|
|
20977
21126
|
- Beta: needs the `accounts` and `event_outbound` feature flag on the workspace.
|
|
20978
21127
|
- API: `POST /v1/outbound-event-suggestions/{suggestionId}/accept`
|
|
@@ -20996,7 +21145,7 @@ kenso outbound-event-suggestions accept --suggestion-id <suggestion-id> --data @
|
|
|
20996
21145
|
|
|
20997
21146
|
Dismiss a suggested event, so Ken never suggests it again.
|
|
20998
21147
|
|
|
20999
|
-
Marks the suggestion `dismissed` and returns it. Kenso keeps its page and its name and start date, so weekly discovery skips the event on every source. A suggestion that is not `suggested` is `409 invalid_state`; another workspace's is `404`. Requires
|
|
21148
|
+
Marks the suggestion `dismissed` and returns it. Kenso keeps its page and its name and start date, so weekly discovery skips the event on every source. A suggestion that is not `suggested` is `409 invalid_state`; another workspace's is `404`. Requires Accounts edit.
|
|
21000
21149
|
|
|
21001
21150
|
- Beta: needs the `accounts` and `event_outbound` feature flag on the workspace.
|
|
21002
21151
|
- API: `POST /v1/outbound-event-suggestions/{suggestionId}/dismiss`
|
|
@@ -21016,7 +21165,7 @@ kenso outbound-event-suggestions dismiss --suggestion-id <suggestion-id>
|
|
|
21016
21165
|
|
|
21017
21166
|
List suggested events in the current workspace, most relevant first.
|
|
21018
21167
|
|
|
21019
|
-
`status`: `suggested` (default: waiting for a decision; an event that has ended, by today's date in its own `timezone`, else UTC, is left out), `added` or `dismissed`. `limit` 1-200 (default 50) and `cursor` page by `relevance`, then id, both descending. Each suggestion carries `name`, `startsOn`, `endsOn`, `timezone`, `format` (`in_person`, `virtual` or `hybrid`), `city`, `venue`, `url` (the event page), `source` (where Ken found it: `luma`, `dev_events`, `allevents` or `meetup`; `eventbrite`, `tentimes` or `conferenceindex` where Kenso reads them through Firecrawl for the workspace; or `eventbrite` or `linkedin` from a workflow's Apify actor), `sourceUrl` (the listing it was found on; null for an Apify actor's events), `relevance` (0-100), `reason` (one line on why it fits), `accounts` (the workspace's accounts the page names, each `{ accountId, name, role }`), `status`, `eventId` (the event adding it created), `createdAt` and `decidedAt`. Requires
|
|
21168
|
+
`status`: `suggested` (default: waiting for a decision; an event that has ended, by today's date in its own `timezone`, else UTC, is left out), `added` or `dismissed`. `limit` 1-200 (default 50) and `cursor` page by `relevance`, then id, both descending. Each suggestion carries `name`, `startsOn`, `endsOn`, `timezone`, `format` (`in_person`, `virtual` or `hybrid`), `city`, `venue`, `url` (the event page), `source` (where Ken found it: `luma`, `dev_events`, `allevents` or `meetup`; `eventbrite`, `tentimes` or `conferenceindex` where Kenso reads them through Firecrawl for the workspace; or `eventbrite` or `linkedin` from a workflow's Apify actor), `sourceUrl` (the listing it was found on; null for an Apify actor's events), `relevance` (0-100), `reason` (one line on why it fits), `accounts` (the workspace's accounts the page names, each `{ accountId, name, role }`), `status`, `eventId` (the event adding it created), `createdAt` and `decidedAt`. Requires Accounts view.
|
|
21020
21169
|
|
|
21021
21170
|
- Beta: needs the `accounts` and `event_outbound` feature flag on the workspace.
|
|
21022
21171
|
- API: `GET /v1/outbound-event-suggestions` (a list: `--limit`, `--cursor`, `--all`)
|
|
@@ -21042,7 +21191,7 @@ kenso outbound-event-suggestions list --all
|
|
|
21042
21191
|
|
|
21043
21192
|
Create an outbound event.
|
|
21044
21193
|
|
|
21045
|
-
Body: `name` (required, 1-200 characters after trim), `startsOn` (required, YYYY-MM-DD), `endsOn` (YYYY-MM-DD, default `startsOn`, not before it), `timezone` (IANA, such as `America/Chicago`), `format` (`in_person`, the default, `virtual` or `hybrid`), `attendance` (`going` or `not_going`, default null), `city` and `venue` (up to 200 characters) and `url` (http or https, up to 2048 characters). Example: `{ "name": "SaaStr Annual", "startsOn": "2026-09-09", "endsOn": "2026-09-11", "timezone": "America/Los_Angeles", "city": "San Mateo", "url": "https://www.saastrannual.com" }`. Returns `201` with the event. Requires
|
|
21194
|
+
Body: `name` (required, 1-200 characters after trim), `startsOn` (required, YYYY-MM-DD), `endsOn` (YYYY-MM-DD, default `startsOn`, not before it), `timezone` (IANA, such as `America/Chicago`), `format` (`in_person`, the default, `virtual` or `hybrid`), `attendance` (`going` or `not_going`, default null), `city` and `venue` (up to 200 characters) and `url` (http or https, up to 2048 characters). Example: `{ "name": "SaaStr Annual", "startsOn": "2026-09-09", "endsOn": "2026-09-11", "timezone": "America/Los_Angeles", "city": "San Mateo", "url": "https://www.saastrannual.com" }`. Returns `201` with the event. Requires Accounts edit.
|
|
21046
21195
|
|
|
21047
21196
|
- Beta: needs the `accounts` and `event_outbound` feature flag on the workspace.
|
|
21048
21197
|
- API: `POST /v1/outbound-events`
|
|
@@ -21073,7 +21222,7 @@ kenso outbound-events create --data @body.json
|
|
|
21073
21222
|
|
|
21074
21223
|
Delete an outbound event.
|
|
21075
21224
|
|
|
21076
|
-
Soft delete; returns `204`. Its rows stop showing in every list. Another workspace's event is `404`. Requires
|
|
21225
|
+
Soft delete; returns `204`. Its rows stop showing in every list. Another workspace's event is `404`. Requires Accounts edit.
|
|
21077
21226
|
|
|
21078
21227
|
- Beta: needs the `accounts` and `event_outbound` feature flag on the workspace.
|
|
21079
21228
|
- API: `DELETE /v1/outbound-events/{eventId}`
|
|
@@ -21093,7 +21242,7 @@ kenso outbound-events delete --event-id <event-id>
|
|
|
21093
21242
|
|
|
21094
21243
|
Read an event page or a pasted list and preview the people or companies it lists.
|
|
21095
21244
|
|
|
21096
|
-
Body: `url` (the exhibitor, speaker, sponsor or attendee page, an absolute http(s) URL up to 2048 characters) or `text` (a pasted list instead: names, emails, LinkedIn URLs, an email or a page's text, up to 120,000 characters; not both), and `role` (required: attendee, exhibitor, speaker or sponsor, given to every row). Example: `{ "url": "https://example.com/exhibitors", "role": "exhibitor" }` or `{ "text": "Jordan Lee - VP Sales, Acme Robotics", "role": "attendee" }`. A page comes from Kenso's web archive first (`source``archive`), else a live read when the workspace can run one (`live`); otherwise `source` is `none` with no rows. Pasted text is `source``text` with no `url`; a row read from text may also carry an `email`. The model reads the rows, long content in parts of 20,000 characters at once; each row comes back normalized like bulk-create (repeats and rows that fail validation are left out), in order, ready to send to `POST /v1/outbound-events/{eventId}/attendees/bulk-create`. `truncated` is true when the page was too long to read whole, an answer reached the model's output cap (the rows read before it are kept), a part failed while others answered, or the rows reached the cap of 300. Nothing is stored. The model calls are not charged; a live read is charged like any web read of the workspace (an archive read is free). A model failure answers 200 with no rows. Files go to the multipart form of this route (`outbound-events.extract-attendees-from-files`). `mode``prospectus` (DEV-4351; default `attendees`) reads a sponsorship prospectus or a who-attends page for the companies it names (company-only rows, sent to bulk-create with `source``prospectus`), `titleMix` (the job titles it says attendees hold, each with `share` as a fraction or null, largest first, at most 20: send them as `find-company-people`'s `titles`) and `attendeeCount`; a page in this mode is read from the site or Kenso's archive only, never live. Another workspace's event is `404`. Requires
|
|
21245
|
+
Body: `url` (the exhibitor, speaker, sponsor or attendee page, an absolute http(s) URL up to 2048 characters) or `text` (a pasted list instead: names, emails, LinkedIn URLs, an email or a page's text, up to 120,000 characters; not both), and `role` (required: attendee, exhibitor, speaker or sponsor, given to every row). Example: `{ "url": "https://example.com/exhibitors", "role": "exhibitor" }` or `{ "text": "Jordan Lee - VP Sales, Acme Robotics", "role": "attendee" }`. A page comes from Kenso's web archive first (`source``archive`), else a live read when the workspace can run one (`live`); otherwise `source` is `none` with no rows. Pasted text is `source``text` with no `url`; a row read from text may also carry an `email`. The model reads the rows, long content in parts of 20,000 characters at once; each row comes back normalized like bulk-create (repeats and rows that fail validation are left out), in order, ready to send to `POST /v1/outbound-events/{eventId}/attendees/bulk-create`. `truncated` is true when the page was too long to read whole, an answer reached the model's output cap (the rows read before it are kept), a part failed while others answered, or the rows reached the cap of 300. Nothing is stored. The model calls are not charged; a live read is charged like any web read of the workspace (an archive read is free). A model failure answers 200 with no rows. Files go to the multipart form of this route (`outbound-events.extract-attendees-from-files`). `mode``prospectus` (DEV-4351; default `attendees`) reads a sponsorship prospectus or a who-attends page for the companies it names (company-only rows, sent to bulk-create with `source``prospectus`), `titleMix` (the job titles it says attendees hold, each with `share` as a fraction or null, largest first, at most 20: send them as `find-company-people`'s `titles`) and `attendeeCount`; a page in this mode is read from the site or Kenso's archive only, never live. Another workspace's event is `404`. Requires Accounts edit.
|
|
21097
21246
|
|
|
21098
21247
|
- Beta: needs the `accounts` and `event_outbound` feature flag on the workspace.
|
|
21099
21248
|
- API: `POST /v1/outbound-events/{eventId}/extract-attendees`
|
|
@@ -21120,7 +21269,7 @@ kenso outbound-events extract-attendees --event-id <event-id> --data @body.json
|
|
|
21120
21269
|
|
|
21121
21270
|
Read uploaded files (a spreadsheet, PDFs, badge or card photos) and preview the people they list.
|
|
21122
21271
|
|
|
21123
|
-
Multipart form on the same path as `outbound-events.extract-attendees`: `files` (1 to 10 files) and `role` (required: attendee, exhibitor, speaker or sponsor, given to every row). One entry per file comes back in upload order, each with `kind` (`spreadsheet`, `pdf`, `image` or `other`), `status` (`read`, `skipped` or `failed`) and, unless read, a `reason`. An .xlsx (at most 10 MB, one per request; a second is `extra_spreadsheet`) comes back as `table`: its first visible sheet with a value, the first row as `columns` (at most 50) and up to 5,000 `rows`, each with one cell per column, for column mapping; no model reads it. Hidden rows are left out; hidden columns are kept, in place. A PDF (at most 10 MB, the first 40 pages; at most 120,000 characters across the request's PDFs, a later one is `text_limit`) has its text read by the model like a page; one with no text layer, such as a scan, is `no_text`: send photos of its pages instead. Each JPEG, PNG or WebP image (at most 3.75 MB and 8,000 px on a side; a badge, a business card or a list) is one Claude vision call, at most 3 at a time. A PDF's or image's `rows` are normalized like bulk-create, may carry an `email` (never a phone number), and are ready to send to `POST /v1/outbound-events/{eventId}/attendees/bulk-create` with `source``pdf` or `image` (`xlsx` for a mapped table). Other reasons: `unsupported_type` (HEIC included: send it as JPEG), `too_large`, `too_many_files` (past the tenth), `oversized_image` (over 8,000 px on one side: crop it into parts), `unreadable` (a damaged file or image header) and `extraction_failed` (the model did not answer; try again). `truncated` is true when Kenso read only part of a file. `mode``prospectus` (default `attendees`) reads each PDF or image as a sponsorship prospectus or who-attends page: company-only `rows` (bulk-create `source``prospectus`), `titleMix` and `attendeeCount`, as on `outbound-events.extract-attendees`. Nothing is stored. The model calls are not charged. A request over 52 MB is `413`. Another workspace's event is `404`. Requires
|
|
21272
|
+
Multipart form on the same path as `outbound-events.extract-attendees`: `files` (1 to 10 files) and `role` (required: attendee, exhibitor, speaker or sponsor, given to every row). One entry per file comes back in upload order, each with `kind` (`spreadsheet`, `pdf`, `image` or `other`), `status` (`read`, `skipped` or `failed`) and, unless read, a `reason`. An .xlsx (at most 10 MB, one per request; a second is `extra_spreadsheet`) comes back as `table`: its first visible sheet with a value, the first row as `columns` (at most 50) and up to 5,000 `rows`, each with one cell per column, for column mapping; no model reads it. Hidden rows are left out; hidden columns are kept, in place. A PDF (at most 10 MB, the first 40 pages; at most 120,000 characters across the request's PDFs, a later one is `text_limit`) has its text read by the model like a page; one with no text layer, such as a scan, is `no_text`: send photos of its pages instead. Each JPEG, PNG or WebP image (at most 3.75 MB and 8,000 px on a side; a badge, a business card or a list) is one Claude vision call, at most 3 at a time. A PDF's or image's `rows` are normalized like bulk-create, may carry an `email` (never a phone number), and are ready to send to `POST /v1/outbound-events/{eventId}/attendees/bulk-create` with `source``pdf` or `image` (`xlsx` for a mapped table). Other reasons: `unsupported_type` (HEIC included: send it as JPEG), `too_large`, `too_many_files` (past the tenth), `oversized_image` (over 8,000 px on one side: crop it into parts), `unreadable` (a damaged file or image header) and `extraction_failed` (the model did not answer; try again). `truncated` is true when Kenso read only part of a file. `mode``prospectus` (default `attendees`) reads each PDF or image as a sponsorship prospectus or who-attends page: company-only `rows` (bulk-create `source``prospectus`), `titleMix` and `attendeeCount`, as on `outbound-events.extract-attendees`. Nothing is stored. The model calls are not charged. A request over 52 MB is `413`. Another workspace's event is `404`. Requires Accounts edit.
|
|
21124
21273
|
|
|
21125
21274
|
- Beta: needs the `accounts` and `event_outbound` feature flag on the workspace.
|
|
21126
21275
|
- API: `POST /v1/outbound-events/{eventId}/extract-attendees`
|
|
@@ -21145,7 +21294,7 @@ kenso outbound-events extract-attendees-from-files --event-id <event-id> --file
|
|
|
21145
21294
|
|
|
21146
21295
|
Find people at the event's exhibitor, sponsor and listed companies with Kenso Search.
|
|
21147
21296
|
|
|
21148
|
-
Body (optional): `titles` (1 to 20 job titles of up to 100 characters, such as a prospectus's `titleMix`; default the roles that staff a booth: sales, marketing, partnerships, business development, account executives, events and founders; Kenso Search matches a current title that holds every word of one), `nearEventCity` (true: only people whose profile city is the event's city; ignored when the event has none), `perCompany` (3 to 10, default 5) and `limit` (1 to 200, default 200). Example: `{ "titles": ["CFO", "Partner"], "perCompany": 3 }`. The companies are the event's exhibitor and sponsor rows and its rows with no person (the companies a prospectus named), sponsors first, at most 100 per call; each is found in Kenso Search by its domain, else by a name only one company has. People already on the event are left out. Each comes back with `source``company_people`, `isLikely` true (they work there and may not go: label them likely and write "your team is exhibiting", never "saw you're attending"), a `reason` and a `row` with the company's role, ready for `POST /v1/outbound-events/{eventId}/attendees/bulk-create` with that source. `companyCount` is how many companies Kenso Search looked at; `truncated` is true when the limit or the 100-company cap cut the list. A Kenso Search failure leaves its companies out with a `note`. Nothing is stored and nothing is charged; each profile returned counts against the workspace's `searchBrowseRows` quota (`429``quota_exceeded` past it). Another workspace's event is `404`. Requires
|
|
21297
|
+
Body (optional): `titles` (1 to 20 job titles of up to 100 characters, such as a prospectus's `titleMix`; default the roles that staff a booth: sales, marketing, partnerships, business development, account executives, events and founders; Kenso Search matches a current title that holds every word of one), `nearEventCity` (true: only people whose profile city is the event's city; ignored when the event has none), `perCompany` (3 to 10, default 5) and `limit` (1 to 200, default 200). Example: `{ "titles": ["CFO", "Partner"], "perCompany": 3 }`. The companies are the event's exhibitor and sponsor rows and its rows with no person (the companies a prospectus named), sponsors first, at most 100 per call; each is found in Kenso Search by its domain, else by a name only one company has. People already on the event are left out. Each comes back with `source``company_people`, `isLikely` true (they work there and may not go: label them likely and write "your team is exhibiting", never "saw you're attending"), a `reason` and a `row` with the company's role, ready for `POST /v1/outbound-events/{eventId}/attendees/bulk-create` with that source. `companyCount` is how many companies Kenso Search looked at; `truncated` is true when the limit or the 100-company cap cut the list. A Kenso Search failure leaves its companies out with a `note`. Nothing is stored and nothing is charged; each profile returned counts against the workspace's `searchBrowseRows` quota (`429``quota_exceeded` past it). Another workspace's event is `404`. Requires Accounts edit.
|
|
21149
21298
|
|
|
21150
21299
|
- Beta: needs the `accounts` and `event_outbound` feature flag on the workspace.
|
|
21151
21300
|
- API: `POST /v1/outbound-events/{eventId}/find-company-people`
|
|
@@ -21172,7 +21321,7 @@ kenso outbound-events find-company-people --event-id <event-id> --data @body.jso
|
|
|
21172
21321
|
|
|
21173
21322
|
Find the previous edition's speaker, sponsor and exhibitor lists and preview their rows, labeled last year.
|
|
21174
21323
|
|
|
21175
|
-
Body (optional): `url` (the event's site: its home page or a speaker, sponsor or exhibitor page, this year's or last year's, an absolute http(s) URL up to 2048 characters; default the event's `url`, and one of them is required) and `limit` (1 to 500 rows, default 500). Example: `{ "url": "https://kccncna2026.sched.com" }`. Last year is the year before the event's start date (`year`). Ken looks, for free and with no key: first at the link with the year moved back (`kccncna2026.sched.com` is `kccncna2025.sched.com`, an a2z show's `FABTECH2026` is `FABTECH2025`), a past-year page that is often still live; then at the list pages last year's version of the link names, each read live when its address carries last year, else from its latest Wayback Machine copy of last year; with none found, at one Wayback lookup across the site. Common Crawl is not read: its robots.txt closes it to crawlers. At most 4 pages are read (`truncated` when more were found), each with the extract-attendees readers: a platform's own list (Sched, Sessionize, Map Your Show, a2z, ExpoFP, Luma) with no model call, any other page's text by the model. `lists` has each page read: `url` (as published), `archiveUrl` and `capturedAt` (the Wayback copy, null when live), `role`, `reader`, `count` (rows it gave), `truncated` and `note`. Each of `people` has `source``last_year`, `lastYear` true, `isLikely` true, a `reason` (<c>Speaker in 2025 on kccncna2025.sched.com</c>), `pageUrl`, `capturedAt` and a `row` with its role on last year's list, ready for `POST /v1/outbound-events/{eventId}/attendees/bulk-create` with source `last_year`, which labels the row "last year" on the event. Rows already on the event in the same role are left out. Last year's list is a proxy: companies usually come back (63% of FABTECH 2026's exhibitors were there in 2025), people less often (31% of KubeCon NA 2025's speakers spoke in 2024), so write "spoke last year", never "see you there". `truncated` is true when the limit, the page cap or a list's own cap cut the answer. `note` says why nothing came back. Nothing is stored and nothing is charged. Another workspace's event is `404`. Requires
|
|
21324
|
+
Body (optional): `url` (the event's site: its home page or a speaker, sponsor or exhibitor page, this year's or last year's, an absolute http(s) URL up to 2048 characters; default the event's `url`, and one of them is required) and `limit` (1 to 500 rows, default 500). Example: `{ "url": "https://kccncna2026.sched.com" }`. Last year is the year before the event's start date (`year`). Ken looks, for free and with no key: first at the link with the year moved back (`kccncna2026.sched.com` is `kccncna2025.sched.com`, an a2z show's `FABTECH2026` is `FABTECH2025`), a past-year page that is often still live; then at the list pages last year's version of the link names, each read live when its address carries last year, else from its latest Wayback Machine copy of last year; with none found, at one Wayback lookup across the site. Common Crawl is not read: its robots.txt closes it to crawlers. At most 4 pages are read (`truncated` when more were found), each with the extract-attendees readers: a platform's own list (Sched, Sessionize, Map Your Show, a2z, ExpoFP, Luma) with no model call, any other page's text by the model. `lists` has each page read: `url` (as published), `archiveUrl` and `capturedAt` (the Wayback copy, null when live), `role`, `reader`, `count` (rows it gave), `truncated` and `note`. Each of `people` has `source``last_year`, `lastYear` true, `isLikely` true, a `reason` (<c>Speaker in 2025 on kccncna2025.sched.com</c>), `pageUrl`, `capturedAt` and a `row` with its role on last year's list, ready for `POST /v1/outbound-events/{eventId}/attendees/bulk-create` with source `last_year`, which labels the row "last year" on the event. Rows already on the event in the same role are left out. Last year's list is a proxy: companies usually come back (63% of FABTECH 2026's exhibitors were there in 2025), people less often (31% of KubeCon NA 2025's speakers spoke in 2024), so write "spoke last year", never "see you there". `truncated` is true when the limit, the page cap or a list's own cap cut the answer. `note` says why nothing came back. Nothing is stored and nothing is charged. Another workspace's event is `404`. Requires Accounts edit.
|
|
21176
21325
|
|
|
21177
21326
|
- Beta: needs the `accounts` and `event_outbound` feature flag on the workspace.
|
|
21178
21327
|
- API: `POST /v1/outbound-events/{eventId}/find-last-year`
|
|
@@ -21197,7 +21346,7 @@ kenso outbound-events find-last-year --event-id <event-id> --data @body.json
|
|
|
21197
21346
|
|
|
21198
21347
|
Find people who say they are going: inbox replies and Kenso Search profiles that name the event.
|
|
21199
21348
|
|
|
21200
|
-
Body (optional): `name` (the event name to look for, up to 100 characters; default the event's name without its year, its city or a part in brackets: `Web Summit Lisbon 2026` is `Web Summit`) and `limit` (1 to 100, default 50). First come inbound campaign replies in this workspace's inbox (not bounces or automated replies) from the year before the event until it ends whose own words (the quoted email cut off) name it as somewhere the writer goes ("see you at Slush", or the name before the event's year) and do not decline it ("I won't be at Slush"), with `source``inbox_mention`, the reply's `contactId`, `threadId` and `repliedAt`. Then Kenso Search profiles whose headline, summary or current title name it (`source``profile_mention`; not the organizer's staff, nor a profile naming only a past edition such as "Speaker at Slush 2019"): those naming it with the event's year first, then those naming it alone, unless the name alone is on more than 2,000 profiles (common words), when only the year matches count (`phrase` says what was looked for). LinkedIn posts are not in Kenso Search. `isLikely` is false: they named the event themselves. Every `row` is an attendee, ready for `POST /v1/outbound-events/{eventId}/attendees/bulk-create` with its source; people already on the event are left out. Nothing is stored and nothing is charged; each profile returned counts against the workspace's `searchBrowseRows` quota. Another workspace's event is `404`. Requires
|
|
21349
|
+
Body (optional): `name` (the event name to look for, up to 100 characters; default the event's name without its year, its city or a part in brackets: `Web Summit Lisbon 2026` is `Web Summit`) and `limit` (1 to 100, default 50). First come inbound campaign replies in this workspace's inbox (not bounces or automated replies) from the year before the event until it ends whose own words (the quoted email cut off) name it as somewhere the writer goes ("see you at Slush", or the name before the event's year) and do not decline it ("I won't be at Slush"), with `source``inbox_mention`, the reply's `contactId`, `threadId` and `repliedAt`. Then Kenso Search profiles whose headline, summary or current title name it (`source``profile_mention`; not the organizer's staff, nor a profile naming only a past edition such as "Speaker at Slush 2019"): those naming it with the event's year first, then those naming it alone, unless the name alone is on more than 2,000 profiles (common words), when only the year matches count (`phrase` says what was looked for). LinkedIn posts are not in Kenso Search. `isLikely` is false: they named the event themselves. Every `row` is an attendee, ready for `POST /v1/outbound-events/{eventId}/attendees/bulk-create` with its source; people already on the event are left out. Nothing is stored and nothing is charged; each profile returned counts against the workspace's `searchBrowseRows` quota. Another workspace's event is `404`. Requires Accounts edit.
|
|
21201
21350
|
|
|
21202
21351
|
- Beta: needs the `accounts` and `event_outbound` feature flag on the workspace.
|
|
21203
21352
|
- API: `POST /v1/outbound-events/{eventId}/find-people-going`
|
|
@@ -21222,7 +21371,7 @@ kenso outbound-events find-people-going --event-id <event-id> --data @body.json
|
|
|
21222
21371
|
|
|
21223
21372
|
Return one outbound event with its counts.
|
|
21224
21373
|
|
|
21225
|
-
Another workspace's event, or a deleted one, is `404 not_found`. Requires
|
|
21374
|
+
Another workspace's event, or a deleted one, is `404 not_found`. Requires Accounts view.
|
|
21226
21375
|
|
|
21227
21376
|
- Beta: needs the `accounts` and `event_outbound` feature flag on the workspace.
|
|
21228
21377
|
- API: `GET /v1/outbound-events/{eventId}`
|
|
@@ -21242,7 +21391,7 @@ kenso outbound-events get --event-id <event-id>
|
|
|
21242
21391
|
|
|
21243
21392
|
Show the LinkedIn attendee reads of an outbound event: the warning, the limits, your seats and the latest reads.
|
|
21244
21393
|
|
|
21245
|
-
Returns `enabled` (false while reads are switched off: the warning and limits still show, and no read can start), `warning` (to show before every read), `note` (what a read can and cannot do), `limits`, `event` (attendees counted against the event's limit, attendees left, and `nextReadAt` while the gap between reads runs), `seats` (the LinkedIn seats the caller connected here, each with `canRead`, `allowance`, and when it cannot read, `refusal`: seat_unavailable, seat_paused, event_cooldown, event_limit, seat_reads_today or seat_limit, with `message` and `availableAt`) and `reads` (the latest 5, newest first, each with `status` queued, reading, done or failed, `stopReason`, `message` and its preview `rows`, normalized like bulk-create). Another workspace's event is `404`. Requires
|
|
21394
|
+
Returns `enabled` (false while reads are switched off: the warning and limits still show, and no read can start), `warning` (to show before every read), `note` (what a read can and cannot do), `limits`, `event` (attendees counted against the event's limit, attendees left, and `nextReadAt` while the gap between reads runs), `seats` (the LinkedIn seats the caller connected here, each with `canRead`, `allowance`, and when it cannot read, `refusal`: seat_unavailable, seat_paused, event_cooldown, event_limit, seat_reads_today or seat_limit, with `message` and `availableAt`) and `reads` (the latest 5, newest first, each with `status` queued, reading, done or failed, `stopReason`, `message` and its preview `rows`, normalized like bulk-create). Another workspace's event is `404`. Requires Accounts view.
|
|
21246
21395
|
|
|
21247
21396
|
- Beta: needs the `accounts` and `event_outbound` feature flag on the workspace.
|
|
21248
21397
|
- API: `GET /v1/outbound-events/{eventId}/linkedin-attendees`
|
|
@@ -21262,7 +21411,7 @@ kenso outbound-events linkedin-attendees --event-id <event-id>
|
|
|
21262
21411
|
|
|
21263
21412
|
List outbound events in the current workspace, newest first.
|
|
21264
21413
|
|
|
21265
|
-
`status`: `upcoming` (the event ends today or later, today being the date in the event's own `timezone`, else UTC), `past` (it ended before today) or `all` (default). `limit` 1-200 (default 50) and `cursor` page by id, newest first. Each event carries its `format`, `attendance` (`going`, `not_going` or null), its `status` (`upcoming`, `live` or `past`, from its dates in its own `timezone`, else UTC) and `counts`: live rows, rows per role, distinct companies and distinct live accounts whose domain a row carries (with account scope `own`, only accounts the caller owns). Requires
|
|
21414
|
+
`status`: `upcoming` (the event ends today or later, today being the date in the event's own `timezone`, else UTC), `past` (it ended before today) or `all` (default). `limit` 1-200 (default 50) and `cursor` page by id, newest first. Each event carries its `format`, `attendance` (`going`, `not_going` or null), its `status` (`upcoming`, `live` or `past`, from its dates in its own `timezone`, else UTC) and `counts`: live rows, rows per role, distinct companies and distinct live accounts whose domain a row carries (with account scope `own`, only accounts the caller owns). Requires Accounts view.
|
|
21266
21415
|
|
|
21267
21416
|
- Beta: needs the `accounts` and `event_outbound` feature flag on the workspace.
|
|
21268
21417
|
- API: `GET /v1/outbound-events` (a list: `--limit`, `--cursor`, `--all`)
|
|
@@ -21286,7 +21435,7 @@ kenso outbound-events list --all
|
|
|
21286
21435
|
|
|
21287
21436
|
Plan an Event touch for every target account attending the event.
|
|
21288
21437
|
|
|
21289
|
-
Body (optional): `dueAt` (ISO 8601; default 09:00 UTC fourteen days before the event starts, or now when that has passed). Example: `{ "dueAt": "2026-10-21T09:00:00Z" }`. Every live account an attendee matches by company domain gets one touch on the `event` channel titled `Meet at {event name}`, with a body naming the event and the account's people on the list, on the stakeholder of its first listed person (speakers first). The touches wait for a person to approve them in Today; approving one marks it done and sends nothing. Accounts in stage `paused`, `not_a_fit` or `lost`, and touches a Contact limits guardrail refuses, are skipped with the reason. A second call finds the touches it made (`touchesExisting`). Then the event's speakers at those accounts become `event` account signals (`signalsCreated`, new ones only). An event that ended before today in its `timezone` (UTC when it has none), so its status is `past`, is `409 invalid_state`. Another workspace's event is `404`. Requires
|
|
21438
|
+
Body (optional): `dueAt` (ISO 8601; default 09:00 UTC fourteen days before the event starts, or now when that has passed). Example: `{ "dueAt": "2026-10-21T09:00:00Z" }`. Every live account an attendee matches by company domain gets one touch on the `event` channel titled `Meet at {event name}`, with a body naming the event and the account's people on the list, on the stakeholder of its first listed person (speakers first). The touches wait for a person to approve them in Today; approving one marks it done and sends nothing. Accounts in stage `paused`, `not_a_fit` or `lost`, and touches a Contact limits guardrail refuses, are skipped with the reason. A second call finds the touches it made (`touchesExisting`). Then the event's speakers at those accounts become `event` account signals (`signalsCreated`, new ones only). An event that ended before today in its `timezone` (UTC when it has none), so its status is `past`, is `409 invalid_state`. Another workspace's event is `404`. Requires Accounts edit.
|
|
21290
21439
|
|
|
21291
21440
|
- Beta: needs the `accounts` and `event_outbound` feature flag on the workspace.
|
|
21292
21441
|
- API: `POST /v1/outbound-events/{eventId}/plan-touches`
|
|
@@ -21310,7 +21459,7 @@ kenso outbound-events plan-touches --event-id <event-id> --data @body.json
|
|
|
21310
21459
|
|
|
21311
21460
|
Read an event's page and preview the event fields it states, to fill the New event form.
|
|
21312
21461
|
|
|
21313
|
-
Body: `url` (required: the event's page, an absolute http(s) URL up to 2048 characters, such as a Luma, Eventbrite or Sched link or the conference's own site). Example: `{ "url": "https://lu.ma/revops-mixer" }`. The page is read straight from the site (robots.txt obeyed, never Firecrawl). Each field comes from the first source that states it: the page's schema.org Event (`json_ld`), then Luma's or Eventbrite's own page data (`luma`, `eventbrite`, which add the IANA `timezone`); only when neither names an event does one Claude Haiku call read the page's text (`model`; not charged). Returns 200 with `url` (the page that answered), `platform` (`luma`, `eventbrite`, `sched` or null), `event` (`name`, `startsOn`, `endsOn`, `timezone`, `format`, `city`, `venue` and `url`, the body `outbound-events.create` takes; a field the page does not state is absent), `sources` (per field, where it came from), `missing` (the fields to fill in by hand; no city or venue for a virtual event), `pages` (the site's speaker, sponsor, exhibitor and attendee pages, each with `url`, `role` and `label`, to read with `outbound-events.extract-attendees` once the event exists; a Luma event offers its hosts and featured guests) and `note` (why the page could not be read or named no event, else absent). A page that cannot be read answers 200 with only `event.url` and the note. Nothing is stored. Each call counts on the workspace's `outboundEventLinkPreviews` quota (30 an hour, 200 a day; past it, `429 quota_exceeded` with `Retry-After`). Requires
|
|
21462
|
+
Body: `url` (required: the event's page, an absolute http(s) URL up to 2048 characters, such as a Luma, Eventbrite or Sched link or the conference's own site). Example: `{ "url": "https://lu.ma/revops-mixer" }`. The page is read straight from the site (robots.txt obeyed, never Firecrawl). Each field comes from the first source that states it: the page's schema.org Event (`json_ld`), then Luma's or Eventbrite's own page data (`luma`, `eventbrite`, which add the IANA `timezone`); only when neither names an event does one Claude Haiku call read the page's text (`model`; not charged). Returns 200 with `url` (the page that answered), `platform` (`luma`, `eventbrite`, `sched` or null), `event` (`name`, `startsOn`, `endsOn`, `timezone`, `format`, `city`, `venue` and `url`, the body `outbound-events.create` takes; a field the page does not state is absent), `sources` (per field, where it came from), `missing` (the fields to fill in by hand; no city or venue for a virtual event), `pages` (the site's speaker, sponsor, exhibitor and attendee pages, each with `url`, `role` and `label`, to read with `outbound-events.extract-attendees` once the event exists; a Luma event offers its hosts and featured guests) and `note` (why the page could not be read or named no event, else absent). A page that cannot be read answers 200 with only `event.url` and the note. Nothing is stored. Each call counts on the workspace's `outboundEventLinkPreviews` quota (30 an hour, 200 a day; past it, `429 quota_exceeded` with `Retry-After`). Requires Accounts edit.
|
|
21314
21463
|
|
|
21315
21464
|
- Beta: needs the `accounts` and `event_outbound` feature flag on the workspace.
|
|
21316
21465
|
- API: `POST /v1/outbound-events/preview-from-link`
|
|
@@ -21333,7 +21482,7 @@ kenso outbound-events preview-from-link --data @body.json
|
|
|
21333
21482
|
|
|
21334
21483
|
Start reading a LinkedIn event's attendees through one of your seats.
|
|
21335
21484
|
|
|
21336
|
-
Body: `url` (required: the event's page, `https://www.linkedin.com/events/...`, or its attendee search link), `linkedInAccountId` (required: a LinkedIn seat the caller connected in this workspace, connected and not paused) and `acceptWarning` (required, true: the caller read the warning from `GET /v1/outbound-events/{eventId}/linkedin-attendees`). Example: `{ "url": "https://www.linkedin.com/events/7212345678901234567/", "linkedInAccountId": 6, "acceptWarning": true }`. Automated reads break LinkedIn's User Agreement (section 8.2) and can get the seat restricted. The seat must already attend the event on LinkedIn; Ken never clicks Attend. Returns `202` with the queued read. Ken.EventProcesor reads the seat's classic people search filtered by the event, 10 people a page, at least 30 seconds apart, within the seat's search budget, and keeps the people as the read's preview: nothing is added to the event until you send the rows you keep to bulk-create. Hard limits: 100 attendees a read; one read of an event every 24 hours and 300 attendees per event; 2 reads and 200 attendees per seat per UTC day. The first rate limit or restriction sign stops the read and pauses event reads on the seat for 72 hours. An empty first page ends the read with `no_attendees`: the seat is not attending, or LinkedIn does not list attendees to it. Errors: `400 validation_failed` for a missing or non-event `url` (`invalid_linkedin_event_url`), a missing seat, a seat that is not yours or not usable (`linkedin_account_unavailable`) or `acceptWarning` not true (`warning_not_accepted`); `409 invalid_state` when reads are switched off (`switched_off`) or a limit refuses the read (the detail code is the limit, with a message saying when it lifts). Another workspace's event is `404`. Requires
|
|
21485
|
+
Body: `url` (required: the event's page, `https://www.linkedin.com/events/...`, or its attendee search link), `linkedInAccountId` (required: a LinkedIn seat the caller connected in this workspace, connected and not paused) and `acceptWarning` (required, true: the caller read the warning from `GET /v1/outbound-events/{eventId}/linkedin-attendees`). Example: `{ "url": "https://www.linkedin.com/events/7212345678901234567/", "linkedInAccountId": 6, "acceptWarning": true }`. Automated reads break LinkedIn's User Agreement (section 8.2) and can get the seat restricted. The seat must already attend the event on LinkedIn; Ken never clicks Attend. Returns `202` with the queued read. Ken.EventProcesor reads the seat's classic people search filtered by the event, 10 people a page, at least 30 seconds apart, within the seat's search budget, and keeps the people as the read's preview: nothing is added to the event until you send the rows you keep to bulk-create. Hard limits: 100 attendees a read; one read of an event every 24 hours and 300 attendees per event; 2 reads and 200 attendees per seat per UTC day. The first rate limit or restriction sign stops the read and pauses event reads on the seat for 72 hours. An empty first page ends the read with `no_attendees`: the seat is not attending, or LinkedIn does not list attendees to it. Errors: `400 validation_failed` for a missing or non-event `url` (`invalid_linkedin_event_url`), a missing seat, a seat that is not yours or not usable (`linkedin_account_unavailable`) or `acceptWarning` not true (`warning_not_accepted`); `409 invalid_state` when reads are switched off (`switched_off`) or a limit refuses the read (the detail code is the limit, with a message saying when it lifts). Another workspace's event is `404`. Requires Accounts edit.
|
|
21337
21486
|
|
|
21338
21487
|
- Beta: needs the `accounts` and `event_outbound` feature flag on the workspace.
|
|
21339
21488
|
- API: `POST /v1/outbound-events/{eventId}/read-linkedin-attendees`
|
|
@@ -21360,7 +21509,7 @@ kenso outbound-events read-linkedin-attendees --event-id <event-id> --data @body
|
|
|
21360
21509
|
|
|
21361
21510
|
Update an outbound event. Absent fields stay unchanged.
|
|
21362
21511
|
|
|
21363
|
-
`name`, `startsOn` and `format` cannot be null. `endsOn` null resets it to `startsOn`; the end cannot be before the start. `attendance`, `timezone`, `city`, `venue` and `url` accept null to clear. Same limits as create. Example: `{ "endsOn": "2026-09-12", "venue": null }`. Another workspace's event is `404`. Requires
|
|
21512
|
+
`name`, `startsOn` and `format` cannot be null. `endsOn` null resets it to `startsOn`; the end cannot be before the start. `attendance`, `timezone`, `city`, `venue` and `url` accept null to clear. Same limits as create. Example: `{ "endsOn": "2026-09-12", "venue": null }`. Another workspace's event is `404`. Requires Accounts edit.
|
|
21364
21513
|
|
|
21365
21514
|
- Beta: needs the `accounts` and `event_outbound` feature flag on the workspace.
|
|
21366
21515
|
- API: `PATCH /v1/outbound-events/{eventId}`
|
|
@@ -21394,7 +21543,7 @@ kenso outbound-events update --event-id <event-id> --data @body.json
|
|
|
21394
21543
|
|
|
21395
21544
|
Return what people see on one domain: its website mode and each hostname's page status.
|
|
21396
21545
|
|
|
21397
|
-
`mode` is `unset` (nobody answered: the domain keeps its redirect), `redirect` or `page`. `currentVersionId` is the workspace's live page version, null until the first publish. `hostnames` lists the apex first, then `www`, each with `attachPath` (`worker_route`, `custom_hostname` or null when unsupported), `dnsWriter`, `status` (`detached`, `attaching`, `active`, `detaching` or `failed`), `sslStatus`, `unsupportedReason` and `checkedAt`; empty until Kenso has checked the domain. Requires
|
|
21546
|
+
`mode` is `unset` (nobody answered: the domain keeps its redirect), `redirect` or `page`. `currentVersionId` is the workspace's live page version, null until the first publish. `hostnames` lists the apex first, then `www`, each with `attachPath` (`worker_route`, `custom_hostname` or null when unsupported), `dnsWriter`, `status` (`detached`, `attaching`, `active`, `detaching` or `failed`), `sslStatus`, `unsupportedReason` and `checkedAt`; empty until Kenso has checked the domain. Requires Delivery view and the `domain_pages` feature.
|
|
21398
21547
|
|
|
21399
21548
|
- Beta: needs the `domain_pages` feature flag on the workspace.
|
|
21400
21549
|
- API: `GET /v1/domains/{domainId}/website`
|
|
@@ -21546,7 +21695,7 @@ kenso outbound-site versions-restore --version-id <version-id>
|
|
|
21546
21695
|
|
|
21547
21696
|
Return a person's activity timeline: what is planned next and what already happened.
|
|
21548
21697
|
|
|
21549
|
-
The same rows, parameters and shape as `accounts.activity`, for one person: their touches on the accounts the caller can see, the activity events naming them, and every email and LinkedIn message to or from them (`message_sent` and `message_received` rows with `message`). An account's timeline is the union of its people's. As there, message text comes only to a caller who may view the Inbox. `category` (comma = OR) and `limit` (1-500, default 100) work as there. An unknown or deleted person, another workspace's, or with account scope `own` a person on none of the caller's accounts, is `404 not_found`. A merged person is `404` with detail `person_merged` and `mergedIntoId`. Requires
|
|
21698
|
+
The same rows, parameters and shape as `accounts.activity`, for one person: their touches on the accounts the caller can see, the activity events naming them, and every email and LinkedIn message to or from them (`message_sent` and `message_received` rows with `message`). An account's timeline is the union of its people's. As there, message text comes only to a caller who may view the Inbox. `category` (comma = OR) and `limit` (1-500, default 100) work as there. An unknown or deleted person, another workspace's, or with account scope `own` a person on none of the caller's accounts, is `404 not_found`. A merged person is `404` with detail `person_merged` and `mergedIntoId`. Requires Accounts view.
|
|
21550
21699
|
|
|
21551
21700
|
- Beta: needs the `accounts` feature flag on the workspace.
|
|
21552
21701
|
- API: `GET /v1/people/{personId}/activity`
|
|
@@ -21568,7 +21717,7 @@ kenso people activity --person-id <person-id>
|
|
|
21568
21717
|
|
|
21569
21718
|
Create or match up to 200 people, each optionally onto an account.
|
|
21570
21719
|
|
|
21571
|
-
Body: `rows` (1-200) of `{ person | personId, accountId | accountDomain, role, priority }`, and `findEmails`. Each row runs in its own transaction: an invalid row writes nothing and comes back `invalid` with an `error`; the rest go on. A role address (support@, info@, no-reply@) is not the person's own email: it matches the person who holds it and never fills onto one. A new person with a LinkedIn URL or Kenso person id is created without it; one with a real first and last name (as on `people.create`) matches the same full name on the row's account, else is created there without it, and without an account is `invalid`, because only the name would find them again. Those rows carry `emailDropped: role_address`. A row with only the address is `invalid`; both invalid cases carry `reason: role_address`. A person with the same email, else LinkedIn URL, else Kenso person id, is `matched` and only their blank fields fill; a row with none of them matches the same full name on the same account; else the person is `created`. A row with only a name needs a live account, else it is `invalid`. `accountDomain` resolves to the live account with that registrable domain (unknown: `account_not_found`; a person with an email, LinkedIn URL or Kenso person id is still written). A batch never creates accounts. Places are user writes (`source: csv`), so role and priority pin; a place a person removed is reported `previously_removed`, never forced. Re-sending the same rows creates nothing. `findEmails: true` queues a find for each created or matched person without an email, and `paused` is true when they wait for credits; if queueing fails, the rows still come back with `emailFind: not_requested`. With account scope `own`, every row must name one of the caller's accounts, and a `personId` must be a person they can see; other rows are `invalid`. A match on none of their accounts that comes back `previously_removed` is left untouched and has no `personId`, and finds go only to people on one of their accounts. Requires
|
|
21720
|
+
Body: `rows` (1-200) of `{ person | personId, accountId | accountDomain, role, priority }`, and `findEmails`. Each row runs in its own transaction: an invalid row writes nothing and comes back `invalid` with an `error`; the rest go on. A role address (support@, info@, no-reply@) is not the person's own email: it matches the person who holds it and never fills onto one. A new person with a LinkedIn URL or Kenso person id is created without it; one with a real first and last name (as on `people.create`) matches the same full name on the row's account, else is created there without it, and without an account is `invalid`, because only the name would find them again. Those rows carry `emailDropped: role_address`. A row with only the address is `invalid`; both invalid cases carry `reason: role_address`. A person with the same email, else LinkedIn URL, else Kenso person id, is `matched` and only their blank fields fill; a row with none of them matches the same full name on the same account; else the person is `created`. A row with only a name needs a live account, else it is `invalid`. `accountDomain` resolves to the live account with that registrable domain (unknown: `account_not_found`; a person with an email, LinkedIn URL or Kenso person id is still written). A batch never creates accounts. Places are user writes (`source: csv`), so role and priority pin; a place a person removed is reported `previously_removed`, never forced. Re-sending the same rows creates nothing. `findEmails: true` queues a find for each created or matched person without an email, and `paused` is true when they wait for credits; if queueing fails, the rows still come back with `emailFind: not_requested`. With account scope `own`, every row must name one of the caller's accounts, and a `personId` must be a person they can see; other rows are `invalid`. A match on none of their accounts that comes back `previously_removed` is left untouched and has no `personId`, and finds go only to people on one of their accounts. Requires Accounts edit.
|
|
21572
21721
|
|
|
21573
21722
|
- Beta: needs the `accounts` feature flag on the workspace.
|
|
21574
21723
|
- API: `POST /v1/people/batch`
|
|
@@ -21592,7 +21741,7 @@ kenso people batch --data @body.json
|
|
|
21592
21741
|
|
|
21593
21742
|
Create one person on no account.
|
|
21594
21743
|
|
|
21595
|
-
Body: `fullName` (required), `firstName`, `lastName`, `title`, `email`, `linkedinUrl`, `kenPersonId`, `ownerMemberId`, `leadStatus`, `phones` (as on `people.update`). The first and latest source are `manual` for a person and `api` for an API key or agent. Email is trimmed and lower-cased; the LinkedIn URL is normalized like the `linkedinUrl` filter. A live person with the same email or LinkedIn URL is `409 conflict` with detail `person_exists` and their `personId`: use them instead of creating a twin. A name-only match is not a duplicate. A role address (a shared mailbox such as support@, info@, no-reply@) is not a person: a person who already holds it is still `409 person_exists`. Else with a `linkedinUrl`, a `kenPersonId` or a real first and last name (both parts, from `firstName` and `lastName` or `fullName`, neither a role word such as support or team, the address's local part or a label of its domain, nor an initial only; intake also checks the company name it is sent) the person is created without it and the answer carries `emailDropped: role_address`; with none of them it is `422 role_address`. No email find starts. Returns `201` with `accounts: []`. With account scope `own` it is `403``permission_denied` with `scope: all`: add the person to one of your accounts instead. Requires
|
|
21744
|
+
Body: `fullName` (required), `firstName`, `lastName`, `title`, `email`, `linkedinUrl`, `kenPersonId`, `ownerMemberId`, `leadStatus`, `phones` (as on `people.update`). The first and latest source are `manual` for a person and `api` for an API key or agent. Email is trimmed and lower-cased; the LinkedIn URL is normalized like the `linkedinUrl` filter. A live person with the same email or LinkedIn URL is `409 conflict` with detail `person_exists` and their `personId`: use them instead of creating a twin. A name-only match is not a duplicate. A role address (a shared mailbox such as support@, info@, no-reply@) is not a person: a person who already holds it is still `409 person_exists`. Else with a `linkedinUrl`, a `kenPersonId` or a real first and last name (both parts, from `firstName` and `lastName` or `fullName`, neither a role word such as support or team, the address's local part or a label of its domain, nor an initial only; intake also checks the company name it is sent) the person is created without it and the answer carries `emailDropped: role_address`; with none of them it is `422 role_address`. No email find starts. Returns `201` with `accounts: []`. With account scope `own` it is `403``permission_denied` with `scope: all`: add the person to one of your accounts instead. Requires Accounts edit.
|
|
21596
21745
|
|
|
21597
21746
|
- Beta: needs the `accounts` feature flag on the workspace.
|
|
21598
21747
|
- API: `POST /v1/people`
|
|
@@ -21623,7 +21772,7 @@ kenso people create --data @body.json
|
|
|
21623
21772
|
|
|
21624
21773
|
Delete a person who is on no live account.
|
|
21625
21774
|
|
|
21626
|
-
Soft delete: the person leaves every list, search and find-or-create match, so the same email can be added again as a new person, and Kenso never re-adds them. A person still on an account is `409 conflict` with detail `person_on_accounts` and `accounts` (`accountId`, `name`, `stakeholderId`): remove them from each first. Cancels their active email find. Returns `204`. With account scope `own` it is `403``permission_denied` with `scope: all`. Requires
|
|
21775
|
+
Soft delete: the person leaves every list, search and find-or-create match, so the same email can be added again as a new person, and Kenso never re-adds them. A person still on an account is `409 conflict` with detail `person_on_accounts` and `accounts` (`accountId`, `name`, `stakeholderId`): remove them from each first. Cancels their active email find. Returns `204`. With account scope `own` it is `403``permission_denied` with `scope: all`. Requires Accounts edit.
|
|
21627
21776
|
|
|
21628
21777
|
- Beta: needs the `accounts` feature flag on the workspace.
|
|
21629
21778
|
- API: `DELETE /v1/people/{personId}`
|
|
@@ -21643,7 +21792,7 @@ kenso people delete --person-id <person-id>
|
|
|
21643
21792
|
|
|
21644
21793
|
Remove the photo uploaded for a person.
|
|
21645
21794
|
|
|
21646
|
-
The person shows their LinkedIn photo again (`photoSource: linkedin`) when Kenso has one, else no photo. Removing a photo the person does not have changes nothing. A merged person is `404``person_merged`. Returns the person. Requires
|
|
21795
|
+
The person shows their LinkedIn photo again (`photoSource: linkedin`) when Kenso has one, else no photo. Removing a photo the person does not have changes nothing. A merged person is `404``person_merged`. Returns the person. Requires Accounts edit.
|
|
21647
21796
|
|
|
21648
21797
|
- Beta: needs the `accounts` feature flag on the workspace.
|
|
21649
21798
|
- API: `DELETE /v1/people/{personId}/photo`
|
|
@@ -21663,7 +21812,7 @@ kenso people delete-photo --person-id <person-id>
|
|
|
21663
21812
|
|
|
21664
21813
|
List the open merge suggestions for this person.
|
|
21665
21814
|
|
|
21666
|
-
Ken suggests that two people may be one human when lead intake creates a person with the same name on the email domain of a person who has another email, or when the nightly sweep finds the same email apart from dots and plus tags, the same phone, the same name on the same account, or the same name and email domain. Each item carries `id`, `todayItemId` (`merge_suggestion_{id}`), `personId`, `otherPersonId`, `reasons` (`email_local_part`, `phone`, `name_account`, `name_domain`), `foundBy` (`intake` or `sweep`), `createdAt` and `otherPerson` (the person summary), newest first. Merge with `people.merge`, which closes the suggestion; "Not a duplicate" is <c>PATCH /v1/today/items/{todayItemId}</c> with `state: done`, and Ken never suggests that pair again. A merged person is `404``person_merged`. With account scope `own`, suggestions whose other person is on none of the caller's accounts are left out. Behind the `lead_intake` feature (404 when off). Requires
|
|
21815
|
+
Ken suggests that two people may be one human when lead intake creates a person with the same name on the email domain of a person who has another email, or when the nightly sweep finds the same email apart from dots and plus tags, the same phone, the same name on the same account, or the same name and email domain. Each item carries `id`, `todayItemId` (`merge_suggestion_{id}`), `personId`, `otherPersonId`, `reasons` (`email_local_part`, `phone`, `name_account`, `name_domain`), `foundBy` (`intake` or `sweep`), `createdAt` and `otherPerson` (the person summary), newest first. Merge with `people.merge`, which closes the suggestion; "Not a duplicate" is <c>PATCH /v1/today/items/{todayItemId}</c> with `state: done`, and Ken never suggests that pair again. A merged person is `404``person_merged`. With account scope `own`, suggestions whose other person is on none of the caller's accounts are left out. Behind the `lead_intake` feature (404 when off). Requires Accounts view.
|
|
21667
21816
|
|
|
21668
21817
|
- Beta: needs the `accounts` and `lead_intake` feature flag on the workspace.
|
|
21669
21818
|
- API: `GET /v1/people/{personId}/duplicates`
|
|
@@ -21683,7 +21832,7 @@ kenso people duplicates --person-id <person-id>
|
|
|
21683
21832
|
|
|
21684
21833
|
Export the people the filters match as CSV.
|
|
21685
21834
|
|
|
21686
|
-
Body: the `people.search` filters and `sort`, no paging. Answers a streamed `text/csv` with the header `full_name,first_name,last_name,title,email,linkedin_url,accounts,added_by,added_at`. `accounts` reads `Acme (evaluator, P2); Globex (user)`; `added_by` is Ken, User, API key or Workflow; `added_at` is the UTC date. Cells that start like a formula are neutralized. More than 50,000 rows is `400 validation_failed` with detail `too_many_rows`: narrow the filters. Each export writes an audit-log entry with the filters and the row count. People made from Kenso library list contacts are never exported; the response header `X-Ken-Excluded-Library-People` says how many the filters matched, including 0. With account scope `own`, only people on the caller's accounts, each with only those accounts. Requires `
|
|
21835
|
+
Body: the `people.search` filters and `sort`, no paging. Answers a streamed `text/csv` with the header `full_name,first_name,last_name,title,email,linkedin_url,accounts,added_by,added_at`. `accounts` reads `Acme (evaluator, P2); Globex (user)`; `added_by` is Ken, User, API key or Workflow; `added_at` is the UTC date. Cells that start like a formula are neutralized. More than 50,000 rows is `400 validation_failed` with detail `too_many_rows`: narrow the filters. Each export writes an audit-log entry with the filters and the row count. People made from Kenso library list contacts are never exported; the response header `X-Ken-Excluded-Library-People` says how many the filters matched, including 0. With account scope `own`, only people on the caller's accounts, each with only those accounts. Requires Accounts view and the `export` permission.
|
|
21687
21836
|
|
|
21688
21837
|
- Beta: needs the `accounts` feature flag on the workspace.
|
|
21689
21838
|
- API: `POST /v1/people/export`
|
|
@@ -21714,7 +21863,7 @@ kenso people export --data @body.json
|
|
|
21714
21863
|
|
|
21715
21864
|
Queue a find for the email of each person without one.
|
|
21716
21865
|
|
|
21717
|
-
Body: `personIds` (1-500) and `accountId` (optional: the account whose domain to search). Skips people not in the workspace (`not_found`), with an email (`has_email`) or with a find already running (`active_find`). `estimate.maxCredits` is the most this can cost, 1 credit per queued find, charged only when an email is found. Out of credits, the finds wait as paused and `paused` is true. Returns `202`; the person's `emailFind` shows progress. With account scope `own`, people on none of the caller's accounts are skipped as `not_found`. Requires
|
|
21866
|
+
Body: `personIds` (1-500) and `accountId` (optional: the account whose domain to search). Skips people not in the workspace (`not_found`), with an email (`has_email`) or with a find already running (`active_find`). `estimate.maxCredits` is the most this can cost, 1 credit per queued find, charged only when an email is found. Out of credits, the finds wait as paused and `paused` is true. Returns `202`; the person's `emailFind` shows progress. With account scope `own`, people on none of the caller's accounts are skipped as `not_found`. Requires Accounts edit.
|
|
21718
21867
|
|
|
21719
21868
|
- Beta: needs the `accounts` feature flag on the workspace.
|
|
21720
21869
|
- API: `POST /v1/people/email-finds`
|
|
@@ -21737,7 +21886,7 @@ kenso people find-emails --data @body.json
|
|
|
21737
21886
|
|
|
21738
21887
|
Queue a find for the phone of each person without one.
|
|
21739
21888
|
|
|
21740
|
-
Body: `personIds` (1-500). Returns `202` with how many people were `queued`, `alreadyHavePhone` (a valid phone, nothing queued), `alreadyQueued` (a find already queued, running or paused) and `skipped` (not in the workspace), and `personIds` naming the people of each. A find is charged only when a number is found, at the provider's cost; out of credits, the finds wait as paused. The person's `phoneFind` shows progress, and a found number joins `phones`. With account scope `own`, people on none of the caller's accounts are skipped. Behind the `calls` feature (404 when off). Requires
|
|
21889
|
+
Body: `personIds` (1-500). Returns `202` with how many people were `queued`, `alreadyHavePhone` (a valid phone, nothing queued), `alreadyQueued` (a find already queued, running or paused) and `skipped` (not in the workspace), and `personIds` naming the people of each. A find is charged only when a number is found, at the provider's cost; out of credits, the finds wait as paused. The person's `phoneFind` shows progress, and a found number joins `phones`. With account scope `own`, people on none of the caller's accounts are skipped. Behind the `calls` feature (404 when off). Requires Accounts edit.
|
|
21741
21890
|
|
|
21742
21891
|
- Beta: needs the `accounts` and `calls` feature flag on the workspace.
|
|
21743
21892
|
- API: `POST /v1/people/phone-finds`
|
|
@@ -21759,7 +21908,7 @@ kenso people find-phones --data @body.json
|
|
|
21759
21908
|
|
|
21760
21909
|
Return one person with the accounts they are a stakeholder on.
|
|
21761
21910
|
|
|
21762
|
-
Each account carries the person's `stakeholderId`, `role`, `priority` and `coverage` there, highest priority first. `emailFind` is the newest find of their email. `tagIds` are the tags they carry; a champion carries the Champion tag. A merged person is `404` with detail `person_merged` and `mergedIntoId`, the person to read instead. Requires
|
|
21911
|
+
Each account carries the person's `stakeholderId`, `role`, `priority` and `coverage` there, highest priority first. `emailFind` is the newest find of their email. `tagIds` are the tags they carry; a champion carries the Champion tag. A merged person is `404` with detail `person_merged` and `mergedIntoId`, the person to read instead. Requires Accounts view.
|
|
21763
21912
|
|
|
21764
21913
|
- Beta: needs the `accounts` feature flag on the workspace.
|
|
21765
21914
|
- API: `GET /v1/people/{personId}`
|
|
@@ -21779,7 +21928,7 @@ kenso people get --person-id <person-id>
|
|
|
21779
21928
|
|
|
21780
21929
|
Return a person's research: the latest run's status and the latest finished research.
|
|
21781
21930
|
|
|
21782
|
-
Query (optional): `mode`, `light` or `heavy`, to read only that mode's runs (a newer Light run otherwise shows instead of the Heavy research); without it, runs of either mode. `status` is the latest run's: `none` (never researched), `queued`, `running`, `succeeded`, `no_data` (Ken found no data on the person, so nothing was written) or `failed` with `errorCode` (`person_deleted`, `source_unavailable`, `model_failed`, `invalid_output`, `timeout`). `mode` is the latest run's (`light` or `heavy`), `requestedAt` when it was opened. The rest comes from the latest succeeded run, so research stays visible while a new run is in progress or after one found nothing: `researchedMode`, `researchedAt`, `summary`, `worthKnowing` (points worth knowing before outreach, each `{text, sourceIds}`), `careerMoves` (newest first, `{text, date, companyName, title, sourceIds}`, date `YYYY`, `YYYY-MM` or `YYYY-MM-DD`) and `sources` (`{id, kind, title, url, date}`, kind `linkedin_profile`, `work_history`, `campaign_contact` or `linkedin_post`, and on Heavy `web`, `x`, `instagram`, `facebook`, `news` or `podcast`). Heavy research adds `webFindings` (`{text, kind, url, sourceIds}`, kind and url of the first source), `firecrawlCredits` and, when the web part is missing, `webNote` (for example "Web research unavailable: Firecrawl ..."). Every finding cites the ids of the sources it came from. An unknown or deleted person, another workspace's, or with account scope `own` a person on none of the caller's accounts, is `404 not_found`. A merged person is `404` with detail `person_merged` and `mergedIntoId`. Requires
|
|
21931
|
+
Query (optional): `mode`, `light` or `heavy`, to read only that mode's runs (a newer Light run otherwise shows instead of the Heavy research); without it, runs of either mode. `status` is the latest run's: `none` (never researched), `queued`, `running`, `succeeded`, `no_data` (Ken found no data on the person, so nothing was written) or `failed` with `errorCode` (`person_deleted`, `source_unavailable`, `model_failed`, `invalid_output`, `timeout`). `mode` is the latest run's (`light` or `heavy`), `requestedAt` when it was opened. The rest comes from the latest succeeded run, so research stays visible while a new run is in progress or after one found nothing: `researchedMode`, `researchedAt`, `summary`, `worthKnowing` (points worth knowing before outreach, each `{text, sourceIds}`), `careerMoves` (newest first, `{text, date, companyName, title, sourceIds}`, date `YYYY`, `YYYY-MM` or `YYYY-MM-DD`) and `sources` (`{id, kind, title, url, date}`, kind `linkedin_profile`, `work_history`, `campaign_contact` or `linkedin_post`, and on Heavy `web`, `x`, `instagram`, `facebook`, `news` or `podcast`). Heavy research adds `webFindings` (`{text, kind, url, sourceIds}`, kind and url of the first source), `firecrawlCredits` and, when the web part is missing, `webNote` (for example "Web research unavailable: Firecrawl ..."). Every finding cites the ids of the sources it came from. An unknown or deleted person, another workspace's, or with account scope `own` a person on none of the caller's accounts, is `404 not_found`. A merged person is `404` with detail `person_merged` and `mergedIntoId`. Requires Accounts view and the `accounts_research` feature.
|
|
21783
21932
|
|
|
21784
21933
|
- Beta: needs the `accounts` and `accounts_research` feature flag on the workspace.
|
|
21785
21934
|
- API: `GET /v1/people/{personId}/research`
|
|
@@ -21823,7 +21972,7 @@ kenso people import --file people.jsonl --dry-run
|
|
|
21823
21972
|
|
|
21824
21973
|
Take in one person from your own source: match, place on their company's account, assign an owner.
|
|
21825
21974
|
|
|
21826
|
-
Body: `email`, `linkedinUrl`, or a name (`fullName`, or `firstName` and `lastName`) with a business `companyDomain` (else `400``identity_required`); `title`, `companyName`, `phone` (a bad number is `400``invalid_phone`), `source` (`api` default, `workflow` or `manual`; any other is `400``invalid_source`), `sourceDetail`, `ownerMemberId` (a member, else `400``invalid_member`), `leadStatus` (default `new`), `customFields` (person custom field keys; unknown keys are ignored) and `createAccount`. A person with the same email, else LinkedIn URL, else the same name on the domain and no email, is matched: only their blank fields fill, pinned fields never change, the phone is added and the latest source updates. Else the person is created with lead status new and a score. A business domain with no account gets one (stage researching, source inbound, no research credits) unless `createAccount` is false or the workspace's intake settings say no; the person joins that account. Owner: the person's, else the account's, the CRM contact's, `ownerMemberId`, the workspace default, then the round robin. A new person adds a new_lead row to the owner's Today and notifies them. Returns `person`, `created`, `matchedBy` (email, linkedin_url, name_domain or none), `accountId`, `accountCreated` and `suggestedDuplicateOfPersonId` (same name on the domain with another email). A role address (support@, info@, no-reply@) matches the person who holds it but never fills onto one. With a LinkedIn URL or a real first and last name (as on `people.create`) the person comes in without it, matched later by that name on the address's domain, and the answer carries `emailDropped: role_address`; with neither and no match it is `422 role_address` and nothing is written. 600 calls an hour per workspace; the next is `429` with `Retry-After`. With account scope `own` it is `403``permission_denied` with `scope: all`. Behind the `lead_intake` feature (404 when off). Requires
|
|
21975
|
+
Body: `email`, `linkedinUrl`, or a name (`fullName`, or `firstName` and `lastName`) with a business `companyDomain` (else `400``identity_required`); `title`, `companyName`, `phone` (a bad number is `400``invalid_phone`), `source` (`api` default, `workflow` or `manual`; any other is `400``invalid_source`), `sourceDetail`, `ownerMemberId` (a member, else `400``invalid_member`), `leadStatus` (default `new`), `customFields` (person custom field keys; unknown keys are ignored) and `createAccount`. A person with the same email, else LinkedIn URL, else the same name on the domain and no email, is matched: only their blank fields fill, pinned fields never change, the phone is added and the latest source updates. Else the person is created with lead status new and a score. A business domain with no account gets one (stage researching, source inbound, no research credits) unless `createAccount` is false or the workspace's intake settings say no; the person joins that account. Owner: the person's, else the account's, the CRM contact's, `ownerMemberId`, the workspace default, then the round robin. A new person adds a new_lead row to the owner's Today and notifies them. Returns `person`, `created`, `matchedBy` (email, linkedin_url, name_domain or none), `accountId`, `accountCreated` and `suggestedDuplicateOfPersonId` (same name on the domain with another email). A role address (support@, info@, no-reply@) matches the person who holds it but never fills onto one. With a LinkedIn URL or a real first and last name (as on `people.create`) the person comes in without it, matched later by that name on the address's domain, and the answer carries `emailDropped: role_address`; with neither and no match it is `422 role_address` and nothing is written. 600 calls an hour per workspace; the next is `429` with `Retry-After`. With account scope `own` it is `403``permission_denied` with `scope: all`. Behind the `lead_intake` feature (404 when off). Requires Accounts edit.
|
|
21827
21976
|
|
|
21828
21977
|
- Beta: needs the `accounts` and `lead_intake` feature flag on the workspace.
|
|
21829
21978
|
- API: `POST /v1/people/intake`
|
|
@@ -21862,7 +22011,7 @@ kenso people intake --data @body.json
|
|
|
21862
22011
|
|
|
21863
22012
|
List people in the current workspace.
|
|
21864
22013
|
|
|
21865
|
-
Filters: `email`, `linkedinUrl` (any profile URL shape; normalized), `q` (name or email contains), `ownerMemberId`, `leadStatus` (comma list: new, working, qualified, disqualified, nurture), `source` (comma list on the latest source), `tagIds` (comma list of tag ids: people carrying any of them; `GET /v1/tags?systemKey=champion` gives the Champion tag), `behaviorTags` (repeatable: people whose behavior tags include any, for example `behaviorTags=cold_responder&behaviorTags=prefers_linkedin`; needs the `behavior_signals` feature; `email_confirmed`, `email_dead_end` and `left_company` cannot be filtered). `sort`: `-createdAt` (default), `name` (A-Z, unnamed last), `-score` (highest first, unscored last), `-latestSourceAt` (newest first, none last). Each person carries `ownerMemberId`, `leadStatus`, `score`, `phones`, `phone` (the first valid one), `firstSource`, `latestSource` and `tagIds`. Requires
|
|
22014
|
+
Filters: `email`, `linkedinUrl` (any profile URL shape; normalized), `q` (name or email contains), `ownerMemberId`, `leadStatus` (comma list: new, working, qualified, disqualified, nurture), `source` (comma list on the latest source), `tagIds` (comma list of tag ids: people carrying any of them; `GET /v1/tags?systemKey=champion` gives the Champion tag), `behaviorTags` (repeatable: people whose behavior tags include any, for example `behaviorTags=cold_responder&behaviorTags=prefers_linkedin`; needs the `behavior_signals` feature; `email_confirmed`, `email_dead_end` and `left_company` cannot be filtered). `sort`: `-createdAt` (default), `name` (A-Z, unnamed last), `-score` (highest first, unscored last), `-latestSourceAt` (newest first, none last). Each person carries `ownerMemberId`, `leadStatus`, `score`, `phones`, `phone` (the first valid one), `firstSource`, `latestSource` and `tagIds`. Requires Accounts view.
|
|
21866
22015
|
|
|
21867
22016
|
- Beta: needs the `accounts` feature flag on the workspace.
|
|
21868
22017
|
- API: `GET /v1/people` (a list: `--limit`, `--cursor`, `--all`)
|
|
@@ -21894,7 +22043,7 @@ kenso people list --all
|
|
|
21894
22043
|
|
|
21895
22044
|
Merge this person into another person.
|
|
21896
22045
|
|
|
21897
|
-
Body: `intoPersonId`, the person to keep. In one transaction the kept person keeps every value it has and takes this person's values for its blank fields; this person's account places move to it (on a shared account the two places combine, with touches, reports and seats re-pointed); removal history moves too; this person's active email find is cancelled. This person then reads as `404``person_merged` with `mergedIntoId`. Merging into the same, a deleted or a merged person is `400 validation_failed`. Returns the kept person. With account scope `own` it is `403``permission_denied` with `scope: all`. Requires
|
|
22046
|
+
Body: `intoPersonId`, the person to keep. In one transaction the kept person keeps every value it has and takes this person's values for its blank fields; this person's account places move to it (on a shared account the two places combine, with touches, reports and seats re-pointed); removal history moves too; this person's active email find is cancelled. This person then reads as `404``person_merged` with `mergedIntoId`. Merging into the same, a deleted or a merged person is `400 validation_failed`. Returns the kept person. With account scope `own` it is `403``permission_denied` with `scope: all`. Requires Accounts edit.
|
|
21898
22047
|
|
|
21899
22048
|
- Beta: needs the `accounts` feature flag on the workspace.
|
|
21900
22049
|
- API: `POST /v1/people/{personId}/merge`
|
|
@@ -21918,7 +22067,7 @@ kenso people merge --person-id <person-id> --data @body.json
|
|
|
21918
22067
|
|
|
21919
22068
|
Upload or replace a person's photo.
|
|
21920
22069
|
|
|
21921
|
-
Multipart field `file`: a non-empty PNG, JPEG or WebP under 10 MB, checked by type, extension and content (else `400``validation_failed`). Kenso stores it and serves it from `/media`; it shows as `photoUrl` with `photoSource: upload`, ahead of the person's LinkedIn photo, and replaces an earlier upload. A merged person is `404``person_merged`. Returns the person. Requires
|
|
22070
|
+
Multipart field `file`: a non-empty PNG, JPEG or WebP under 10 MB, checked by type, extension and content (else `400``validation_failed`). Kenso stores it and serves it from `/media`; it shows as `photoUrl` with `photoSource: upload`, ahead of the person's LinkedIn photo, and replaces an earlier upload. A merged person is `404``person_merged`. Returns the person. Requires Accounts edit.
|
|
21922
22071
|
|
|
21923
22072
|
- Beta: needs the `accounts` feature flag on the workspace.
|
|
21924
22073
|
- API: `PUT /v1/people/{personId}/photo`
|
|
@@ -21965,7 +22114,7 @@ kenso people research --person-id <person-id> --data @body.json
|
|
|
21965
22114
|
|
|
21966
22115
|
Search people in the current workspace with filters.
|
|
21967
22116
|
|
|
21968
|
-
Body, every field optional: `q` (full name, email or title contains), `accountIds` (on any of these accounts, up to 100), `onAccount` (`any` default, `none` on no live account, `some` on at least one), `roles` (holds one of these roles on some live account), `hasEmail`, `addedBy` (who created the person: user, agent, api_key, system, workflow), `ownerMemberId`, `leadStatus` (list), `source` (list, on the latest source), `tagIds` (carries any of these tags, up to 100), `sort` (`-createdAt` default, `name` A-Z with unnamed people last, `-score` highest first with unscored last, or `-latestSourceAt` newest first with none last), `limit` (1-200, default 50), `cursor`, `includeTotal`. Lists OR within themselves; filters AND together. Each row embeds its live accounts (with `stakeholderId`, `role`, `priority`, `coverage`), `emailFind` and `tagIds`. Deleted and merged people never appear. With account scope `own`, only people on the caller's accounts, each with only those accounts. Requires
|
|
22117
|
+
Body, every field optional: `q` (full name, email or title contains), `accountIds` (on any of these accounts, up to 100), `onAccount` (`any` default, `none` on no live account, `some` on at least one), `roles` (holds one of these roles on some live account), `hasEmail`, `addedBy` (who created the person: user, agent, api_key, system, workflow), `ownerMemberId`, `leadStatus` (list), `source` (list, on the latest source), `tagIds` (carries any of these tags, up to 100), `sort` (`-createdAt` default, `name` A-Z with unnamed people last, `-score` highest first with unscored last, or `-latestSourceAt` newest first with none last), `limit` (1-200, default 50), `cursor`, `includeTotal`. Lists OR within themselves; filters AND together. Each row embeds its live accounts (with `stakeholderId`, `role`, `priority`, `coverage`), `emailFind` and `tagIds`. Deleted and merged people never appear. With account scope `own`, only people on the caller's accounts, each with only those accounts. Requires Accounts view.
|
|
21969
22118
|
|
|
21970
22119
|
- Beta: needs the `accounts` feature flag on the workspace.
|
|
21971
22120
|
- API: `POST /v1/people/search`
|
|
@@ -22000,7 +22149,7 @@ kenso people search --data @body.json
|
|
|
22000
22149
|
|
|
22001
22150
|
Update person fields. Absent fields stay unchanged; null clears.
|
|
22002
22151
|
|
|
22003
|
-
Fields: fullName, firstName, lastName, title, email, linkedinUrl, kenPersonId, `ownerMemberId` (a workspace member, else `400``invalid_member`), `leadStatus` (new, working, qualified, disqualified, nurture), `phones` (`[{ number, kind }]`, up to 20; replaces the list, so send every number to keep; a number the person has keeps when it was added; a number marked invalid (a wrong number) stays even when left out, after the numbers sent; a bad number is `400``invalid_phone`; to add or remove one number use `PATCH /v1/people/{personId}/phones`), `phoneOptOut` (true: the person asked not to be called; it records now and the caller as `phoneOptOutAt`, keeping an earlier opt-out's time; false clears it; Kenso's dialer never calls an opted-out person). `score` and the sources are read-only. An owner or status change writes `person.owner_changed` or `person.lead_status_changed` with before and after; each new number writes `person.phone_added`. An email or LinkedIn URL another person holds is `409 conflict` (`email_taken`, `linkedin_url_taken`) with that `personId`, which is left out when account scope `own` hides that person. A person keeps at least one of fullName, email, linkedinUrl. Pinned fields need `overwritePinned: true`. A merged person is `404``person_merged`. Requires
|
|
22152
|
+
Fields: fullName, firstName, lastName, title, email, linkedinUrl, kenPersonId, `ownerMemberId` (a workspace member, else `400``invalid_member`), `leadStatus` (new, working, qualified, disqualified, nurture), `phones` (`[{ number, kind }]`, up to 20; replaces the list, so send every number to keep; a number the person has keeps when it was added; a number marked invalid (a wrong number) stays even when left out, after the numbers sent; a bad number is `400``invalid_phone`; to add or remove one number use `PATCH /v1/people/{personId}/phones`), `phoneOptOut` (true: the person asked not to be called; it records now and the caller as `phoneOptOutAt`, keeping an earlier opt-out's time; false clears it; Kenso's dialer never calls an opted-out person). `score` and the sources are read-only. An owner or status change writes `person.owner_changed` or `person.lead_status_changed` with before and after; each new number writes `person.phone_added`. An email or LinkedIn URL another person holds is `409 conflict` (`email_taken`, `linkedin_url_taken`) with that `personId`, which is left out when account scope `own` hides that person. A person keeps at least one of fullName, email, linkedinUrl. Pinned fields need `overwritePinned: true`. A merged person is `404``person_merged`. Requires Accounts edit.
|
|
22004
22153
|
|
|
22005
22154
|
- Beta: needs the `accounts` feature flag on the workspace.
|
|
22006
22155
|
- API: `PATCH /v1/people/{personId}`
|
|
@@ -22040,7 +22189,7 @@ kenso people update --person-id <person-id> --data @body.json
|
|
|
22040
22189
|
|
|
22041
22190
|
Add, remove or reorder a person's phones without resending the list.
|
|
22042
22191
|
|
|
22043
|
-
Body, at least one of: `add` (`[{ number, kind }]`, up to 20; a new number goes after the person's phones, recorded as added now by `manual` for a person or `api` for an API key or agent, and writes `person.phone_added`; a number the person has keeps its entry and takes the `kind` sent, and a number marked invalid (a wrong number) stays marked; `400``out_of_range` when the person would end up with more than 20 phones, wrong numbers included), `remove` (up to 20 numbers; a valid number is removed; a number marked invalid stays, so a known wrong number is never added back; a number the person does not have is ignored), `primary` (a valid number the person has after `add` and `remove`; it moves first and becomes `phone`, else `400``unknown_phone`). Applied as remove, then add, then primary, to the phones stored when the write runs, so two edits at once both land. Numbers are normalized like `people.update` phones; a bad one is `400``invalid_phone` naming it. Phones a person set need `overwritePinned: true` from an API key or agent. A merged person is `404``person_merged`. Returns the person, like `people.update`. Requires
|
|
22192
|
+
Body, at least one of: `add` (`[{ number, kind }]`, up to 20; a new number goes after the person's phones, recorded as added now by `manual` for a person or `api` for an API key or agent, and writes `person.phone_added`; a number the person has keeps its entry and takes the `kind` sent, and a number marked invalid (a wrong number) stays marked; `400``out_of_range` when the person would end up with more than 20 phones, wrong numbers included), `remove` (up to 20 numbers; a valid number is removed; a number marked invalid stays, so a known wrong number is never added back; a number the person does not have is ignored), `primary` (a valid number the person has after `add` and `remove`; it moves first and becomes `phone`, else `400``unknown_phone`). Applied as remove, then add, then primary, to the phones stored when the write runs, so two edits at once both land. Numbers are normalized like `people.update` phones; a bad one is `400``invalid_phone` naming it. Phones a person set need `overwritePinned: true` from an API key or agent. A merged person is `404``person_merged`. Returns the person, like `people.update`. Requires Accounts edit.
|
|
22044
22193
|
|
|
22045
22194
|
- Beta: needs the `accounts` feature flag on the workspace.
|
|
22046
22195
|
- API: `PATCH /v1/people/{personId}/phones`
|
|
@@ -22359,7 +22508,7 @@ kenso permission-templates update --template-id <template-id> --data @body.json
|
|
|
22359
22508
|
|
|
22360
22509
|
Return a person's behavior signals.
|
|
22361
22510
|
|
|
22362
|
-
The same body as `contact-behavior.get` for the person's LinkedIn profile (else their email): `workspace` and, with the `behavior_signals_network` feature, `network` with `workspaces` (other workspaces only). Address tags (`email_confirmed`, `email_dead_end`, `left_company`) are never on a person: read them on a contact. Absent means null. An unknown or deleted person, another workspace's, or with account scope `own` a person on none of the caller's accounts, is `404 not_found`; a merged person is `404` with detail `person_merged` and `mergedIntoId`. Requires
|
|
22511
|
+
The same body as `contact-behavior.get` for the person's LinkedIn profile (else their email): `workspace` and, with the `behavior_signals_network` feature, `network` with `workspaces` (other workspaces only). Address tags (`email_confirmed`, `email_dead_end`, `left_company`) are never on a person: read them on a contact. Absent means null. An unknown or deleted person, another workspace's, or with account scope `own` a person on none of the caller's accounts, is `404 not_found`; a merged person is `404` with detail `person_merged` and `mergedIntoId`. Requires Accounts view and the `accounts` and `behavior_signals` features.
|
|
22363
22512
|
|
|
22364
22513
|
- Beta: needs the `accounts` and `behavior_signals` feature flag on the workspace.
|
|
22365
22514
|
- API: `GET /v1/people/{personId}/behavior`
|
|
@@ -22381,7 +22530,7 @@ kenso person-behavior get --person-id <person-id>
|
|
|
22381
22530
|
|
|
22382
22531
|
Start an inbox placement test for a campaign.
|
|
22383
22532
|
|
|
22384
|
-
Requires Delivery edit. Exactly one of `domainId` or `inboxId` is required unless `randomScope` is true. Example: `{ "campaignId": 812, "inboxId": 44 }`. Kenso pays for each test, so each call counts against a per-workspace budget: `placementTestCreates` (5 a minute, 20 a day, 50 in 30 days; a Free plan gets 1, 2 and 5), over it `429 rate_limited` with `Retry-After`. Where `placement_tests_public` is on, the budget is `placementTestCreatesPublic` (2 a day, 8 in 30 days, on every plan), over it `429 quota_exceeded` naming the limit, with `Retry-After`.
|
|
22533
|
+
Requires Delivery edit. Exactly one of `domainId` or `inboxId` is required unless `randomScope` is true. Example: `{ "campaignId": 812, "inboxId": 44 }`. Kenso pays for each test, so each call counts against a per-workspace budget: `placementTestCreates` (5 a minute, 20 a day, 50 in 30 days; a Free plan gets 1, 2 and 5), over it `429 rate_limited` with `Retry-After`. Where `placement_tests_public` is on, the budget is `placementTestCreatesPublic` (2 a day, 8 in 30 days, on every plan), over it `429 quota_exceeded` naming the limit, with `Retry-After`. Kenso staff are exempt. `openPixel: true` sends the copy with the campaign open pixel on `link.` or `unsub.` of the test's sending domain, whichever serves it; `openPixelHost` names the host used. No serving host, plain-text copy, or a test with the other pixel setting already running for the campaign and domain is `409 invalid_state`.
|
|
22385
22534
|
|
|
22386
22535
|
- API: `POST /v1/placement-tests`
|
|
22387
22536
|
- Generated from the API contract
|
|
@@ -22418,7 +22567,7 @@ kenso placement-tests create --data @body.json
|
|
|
22418
22567
|
|
|
22419
22568
|
Return one placement test with its full results.
|
|
22420
22569
|
|
|
22421
|
-
Adds what the list leaves out: `type`, `startedAt`, `sentCount`, `senderInboxIds`, the `subject` and `body` sent, `counts`, per `providers`, per `senders`, per `seeds` (masked addresses), InboxKit `errors`, and up to 10 `earlierTests` of the test's own campaign and domain (whichever are set) for a trend; a shared weekly test trends with the campaign that owns it, and an inbox test without a domain has none. Result fields are omitted until the test completes. Rates are fractions from 0 to 1. Requires
|
|
22570
|
+
Adds what the list leaves out: `type`, `startedAt`, `sentCount`, `senderInboxIds`, the `subject` and `body` sent, `counts`, per `providers`, per `senders`, per `seeds` (masked addresses), InboxKit `errors`, and up to 10 `earlierTests` of the test's own campaign and domain (whichever are set) for a trend; a shared weekly test trends with the campaign that owns it, and an inbox test without a domain has none. Result fields are omitted until the test completes. Rates are fractions from 0 to 1. Requires Delivery view. A test outside the workspace is `not_found`.
|
|
22422
22571
|
|
|
22423
22572
|
- API: `GET /v1/placement-tests/{placementTestId}`
|
|
22424
22573
|
- Generated from the API contract
|
|
@@ -22437,7 +22586,7 @@ kenso placement-tests get --placement-test-id <placement-test-id>
|
|
|
22437
22586
|
|
|
22438
22587
|
List placement tests for a campaign, newest first.
|
|
22439
22588
|
|
|
22440
|
-
Requires `campaignId`. Default sort is `-createdAt`. Rates are fractions from 0 to 1. Requires
|
|
22589
|
+
Requires `campaignId`. Default sort is `-createdAt`. Rates are fractions from 0 to 1. Requires Delivery view. A campaign outside the workspace is `not_found`.
|
|
22441
22590
|
|
|
22442
22591
|
- API: `GET /v1/placement-tests` (a list: `--limit`, `--cursor`, `--all`)
|
|
22443
22592
|
- Generated from the API contract
|
|
@@ -22480,7 +22629,7 @@ kenso portal-sessions create
|
|
|
22480
22629
|
|
|
22481
22630
|
Create a prompt template in the current workspace.
|
|
22482
22631
|
|
|
22483
|
-
Returns `201` and `Location`. `scope=workspace` is owned by the workspace header. Qualification prompts keep `IQualificationWorkflowSyncService` in sync. A campaign or model configuration outside the workspace is `not_found` before the write. Requires
|
|
22632
|
+
Returns `201` and `Location`. `scope=workspace` is owned by the workspace header. Qualification prompts keep `IQualificationWorkflowSyncService` in sync. A campaign or model configuration outside the workspace is `not_found` before the write. Requires Campaigns edit.
|
|
22484
22633
|
|
|
22485
22634
|
- API: `POST /v1/prompt-templates`
|
|
22486
22635
|
- Generated from the API contract
|
|
@@ -22507,7 +22656,7 @@ kenso prompt-templates create --data @body.json
|
|
|
22507
22656
|
|
|
22508
22657
|
Delete a prompt template in the current workspace.
|
|
22509
22658
|
|
|
22510
|
-
Returns `204`. A template outside the workspace is `not_found` and is not deleted. Requires
|
|
22659
|
+
Returns `204`. A template outside the workspace is `not_found` and is not deleted. Requires Campaigns edit.
|
|
22511
22660
|
|
|
22512
22661
|
- API: `DELETE /v1/prompt-templates/{templateId}`
|
|
22513
22662
|
- Generated from the API contract
|
|
@@ -22526,7 +22675,7 @@ kenso prompt-templates delete --template-id <template-id>
|
|
|
22526
22675
|
|
|
22527
22676
|
Return one prompt template visible in the current workspace.
|
|
22528
22677
|
|
|
22529
|
-
A missing or cross-workspace id is `not_found`. Requires
|
|
22678
|
+
A missing or cross-workspace id is `not_found`. Requires Campaigns view.
|
|
22530
22679
|
|
|
22531
22680
|
- API: `GET /v1/prompt-templates/{templateId}`
|
|
22532
22681
|
- Generated from the API contract
|
|
@@ -22545,7 +22694,7 @@ kenso prompt-templates get --template-id <template-id>
|
|
|
22545
22694
|
|
|
22546
22695
|
List prompt templates visible in the current workspace.
|
|
22547
22696
|
|
|
22548
|
-
Ordered by id. Optional `flow` and `scope` narrow the page. `q` matches the name. Workspace-scoped rows are limited to `X-Ken-Workspace-Id`. Requires
|
|
22697
|
+
Ordered by id. Optional `flow` and `scope` narrow the page. `q` matches the name. Workspace-scoped rows are limited to `X-Ken-Workspace-Id`. Requires Campaigns view.
|
|
22549
22698
|
|
|
22550
22699
|
- API: `GET /v1/prompt-templates` (a list: `--limit`, `--cursor`, `--all`)
|
|
22551
22700
|
- Generated from the API contract
|
|
@@ -22570,7 +22719,7 @@ kenso prompt-templates list --all
|
|
|
22570
22719
|
|
|
22571
22720
|
Update a prompt template in the current workspace.
|
|
22572
22721
|
|
|
22573
|
-
Absent fields stay unchanged. `null` clears `description` and `modelConfigurationId`. A template outside the workspace is `not_found` before the write. Qualification prompt edits keep `IQualificationWorkflowSyncService` in sync. Requires
|
|
22722
|
+
Absent fields stay unchanged. `null` clears `description` and `modelConfigurationId`. A template outside the workspace is `not_found` before the write. Qualification prompt edits keep `IQualificationWorkflowSyncService` in sync. Requires Campaigns edit.
|
|
22574
22723
|
|
|
22575
22724
|
- API: `PATCH /v1/prompt-templates/{templateId}`
|
|
22576
22725
|
- Generated from the API contract
|
|
@@ -22594,7 +22743,7 @@ kenso prompt-templates update --template-id <template-id> --data @body.json
|
|
|
22594
22743
|
|
|
22595
22744
|
Return one prompt version for a segment in the current workspace.
|
|
22596
22745
|
|
|
22597
|
-
A missing segment or version is `not_found`. Requires
|
|
22746
|
+
A missing segment or version is `not_found`. Requires Campaigns view.
|
|
22598
22747
|
|
|
22599
22748
|
- API: `GET /v1/segments/{segmentId}/prompt-versions/{versionId}`
|
|
22600
22749
|
- Generated from the API contract
|
|
@@ -22614,7 +22763,7 @@ kenso prompt-versions get --segment-id <segment-id> --version-id <version-id>
|
|
|
22614
22763
|
|
|
22615
22764
|
List prompt versions for a segment in the current workspace.
|
|
22616
22765
|
|
|
22617
|
-
A segment outside `X-Ken-Workspace-Id` is `not_found` before versions are read. Requires
|
|
22766
|
+
A segment outside `X-Ken-Workspace-Id` is `not_found` before versions are read. Requires Campaigns view.
|
|
22618
22767
|
|
|
22619
22768
|
- API: `GET /v1/segments/{segmentId}/prompt-versions` (a list: `--limit`, `--cursor`, `--all`)
|
|
22620
22769
|
- Generated from the API contract
|
|
@@ -22637,7 +22786,7 @@ kenso prompt-versions list --segment-id <segment-id> --all
|
|
|
22637
22786
|
|
|
22638
22787
|
Restore a prompt version for a segment in the current workspace.
|
|
22639
22788
|
|
|
22640
|
-
Qualification and scoring workflow sync stay inside the existing revert command. A segment outside the workspace is `not_found` before the write. `dryRun` returns what the restore would clear and does not write. A restore that would clear campaign AI output returns `409 conflict` with `error.impact` until `confirm` is true. The body is optional. Requires
|
|
22789
|
+
Qualification and scoring workflow sync stay inside the existing revert command. A segment outside the workspace is `not_found` before the write. `dryRun` returns what the restore would clear and does not write. A restore that would clear campaign AI output returns `409 conflict` with `error.impact` until `confirm` is true. The body is optional. Requires Campaigns edit.
|
|
22641
22790
|
|
|
22642
22791
|
- API: `POST /v1/segments/{segmentId}/prompt-versions/{versionId}/restore`
|
|
22643
22792
|
- Generated from the API contract
|
|
@@ -22666,7 +22815,7 @@ kenso prompt-versions restore --segment-id <segment-id> --version-id <version-id
|
|
|
22666
22815
|
|
|
22667
22816
|
Create a prompt in the current workspace.
|
|
22668
22817
|
|
|
22669
|
-
Returns `201` and `Location`. `campaignId` or `segmentId` is required so the prompt stays in the workspace. `confirm=true` is required when the write would refresh cached AI results. Requires
|
|
22818
|
+
Returns `201` and `Location`. `campaignId` or `segmentId` is required so the prompt stays in the workspace. `confirm=true` is required when the write would refresh cached AI results. Requires Campaigns edit.
|
|
22670
22819
|
|
|
22671
22820
|
- API: `POST /v1/prompts`
|
|
22672
22821
|
- Generated from the API contract
|
|
@@ -22707,7 +22856,7 @@ kenso prompts create --confirm --data @body.json
|
|
|
22707
22856
|
|
|
22708
22857
|
Delete a prompt.
|
|
22709
22858
|
|
|
22710
|
-
Returns `204`. `confirm=true` is required when deletion would refresh cached AI results. Requires
|
|
22859
|
+
Returns `204`. `confirm=true` is required when deletion would refresh cached AI results. Requires Campaigns edit.
|
|
22711
22860
|
|
|
22712
22861
|
- API: `DELETE /v1/prompts/{promptId}`
|
|
22713
22862
|
- Generated from the API contract
|
|
@@ -22728,7 +22877,7 @@ kenso prompts delete --prompt-id <prompt-id> --confirm
|
|
|
22728
22877
|
|
|
22729
22878
|
Return one prompt in the current workspace.
|
|
22730
22879
|
|
|
22731
|
-
A missing or cross-workspace id is `not_found`. Requires
|
|
22880
|
+
A missing or cross-workspace id is `not_found`. Requires Campaigns view.
|
|
22732
22881
|
|
|
22733
22882
|
- API: `GET /v1/prompts/{promptId}`
|
|
22734
22883
|
- Generated from the API contract
|
|
@@ -22771,7 +22920,7 @@ kenso prompts link-knowledge-prompt --prompt-id <prompt-id> --data @body.json
|
|
|
22771
22920
|
|
|
22772
22921
|
List prompts in the current workspace.
|
|
22773
22922
|
|
|
22774
|
-
Ordered by id. Optional `campaignId`, `segmentId`, and `flow` narrow the page. `q` matches the name. Requires
|
|
22923
|
+
Ordered by id. Optional `campaignId`, `segmentId`, and `flow` narrow the page. `q` matches the name. Requires Campaigns view.
|
|
22775
22924
|
|
|
22776
22925
|
- API: `GET /v1/prompts` (a list: `--limit`, `--cursor`, `--all`)
|
|
22777
22926
|
- Generated from the API contract
|
|
@@ -22797,7 +22946,7 @@ kenso prompts list --all
|
|
|
22797
22946
|
|
|
22798
22947
|
Run a prompt test against live model calls.
|
|
22799
22948
|
|
|
22800
|
-
Samples contacts in the campaign and runs the requested flow. This spends model usage. A missing campaign is `not_found`. Requires `
|
|
22949
|
+
Samples contacts in the campaign and runs the requested flow. This spends model usage. A missing campaign is `not_found`. Requires Campaigns edit and the `ask` permission.
|
|
22801
22950
|
|
|
22802
22951
|
- API: `POST /v1/prompts/test`
|
|
22803
22952
|
- Generated from the API contract
|
|
@@ -22842,7 +22991,7 @@ kenso prompts unlink-knowledge-prompt --prompt-id <prompt-id>
|
|
|
22842
22991
|
|
|
22843
22992
|
Update a prompt.
|
|
22844
22993
|
|
|
22845
|
-
Absent fields stay unchanged. JSON null clears a text field or `promptTemplateId`. `segmentId` cannot change on this route, and `campaignId` cannot be cleared on a prompt without a segment (`400`: it would belong to no workspace). `confirm=true` is required when the write would refresh cached AI results. Requires
|
|
22994
|
+
Absent fields stay unchanged. JSON null clears a text field or `promptTemplateId`. `segmentId` cannot change on this route, and `campaignId` cannot be cleared on a prompt without a segment (`400`: it would belong to no workspace). `confirm=true` is required when the write would refresh cached AI results. Requires Campaigns edit.
|
|
22846
22995
|
|
|
22847
22996
|
- API: `PATCH /v1/prompts/{promptId}`
|
|
22848
22997
|
- Generated from the API contract
|
|
@@ -22907,7 +23056,7 @@ kenso provider-keys delete --provider <provider>
|
|
|
22907
23056
|
|
|
22908
23057
|
List every provider and the workspace's key status.
|
|
22909
23058
|
|
|
22910
|
-
Returns every catalogue provider, live and coming soon, in one list. This is a catalogue, not a cursor API: `pagination.nextCursor` is null and `pagination.hasMore` is false. Never returns a key or any prefix of one; `keySuffix` is the last four characters. AI providers also carry `inFlightAiBatchCount`, the workspace's AI batches still running on that key, and a `blitz` or `moltsets` key carries `quota`. `openai` is left out while `sign_in_with_chatgpt` is off for the caller, unless the workspace already saved an OpenAI key. That saved key can be changed, verified and deleted, but not replaced: `PUT openai` answers 409 even though the entry may read `live`.
|
|
23059
|
+
Returns every catalogue provider, live and coming soon, in one list. This is a catalogue, not a cursor API: `pagination.nextCursor` is null and `pagination.hasMore` is false. Never returns a key or any prefix of one; `keySuffix` is the last four characters. AI providers also carry `inFlightAiBatchCount`, the workspace's AI batches still running on that key, and a `blitz` or `moltsets` key carries `quota`. `openai` is left out while `sign_in_with_chatgpt` is off for the caller, unless the workspace already saved an OpenAI key. That saved key can be changed, verified and deleted, but not replaced: `PUT openai` answers 409 even though the entry may read `live`. Requires the `integrations` permission.
|
|
22911
23060
|
|
|
22912
23061
|
- API: `GET /v1/provider-keys`
|
|
22913
23062
|
- Generated from the API contract
|
|
@@ -23256,7 +23405,7 @@ kenso public-shares submit --token <token> --data @body.json
|
|
|
23256
23405
|
|
|
23257
23406
|
Create a reply template.
|
|
23258
23407
|
|
|
23259
|
-
The author is the caller: `user` for a person in the dashboard, `agent` for an agent, an MCP token or an API key. `authorSource``agent` only lowers a person to `agent`. Requires Inbox edit
|
|
23408
|
+
The author is the caller: `user` for a person in the dashboard, `agent` for an agent, an MCP token or an API key. `authorSource``agent` only lowers a person to `agent`. Requires Inbox edit and the `workspace_settings` permission (owners, admins and editors by default).
|
|
23260
23409
|
|
|
23261
23410
|
- API: `POST /v1/reply-templates`
|
|
23262
23411
|
- Generated from the API contract
|
|
@@ -23281,7 +23430,7 @@ kenso reply-templates create --data @body.json
|
|
|
23281
23430
|
|
|
23282
23431
|
Delete a reply template.
|
|
23283
23432
|
|
|
23284
|
-
Returns `204`. The author is the caller, as on create. An agent, an MCP token or an API key cannot delete a human-written template. Requires Inbox edit
|
|
23433
|
+
Returns `204`. The author is the caller, as on create. An agent, an MCP token or an API key cannot delete a human-written template. Requires Inbox edit and the `workspace_settings` permission (owners, admins and editors by default).
|
|
23285
23434
|
|
|
23286
23435
|
- API: `DELETE /v1/reply-templates/{replyTemplateId}`
|
|
23287
23436
|
- Generated from the API contract
|
|
@@ -23301,7 +23450,7 @@ kenso reply-templates delete --reply-template-id <reply-template-id>
|
|
|
23301
23450
|
|
|
23302
23451
|
Return one reply template in the current workspace.
|
|
23303
23452
|
|
|
23304
|
-
A missing or cross-workspace id is `not_found`. Requires
|
|
23453
|
+
A missing or cross-workspace id is `not_found`. Requires Inbox view.
|
|
23305
23454
|
|
|
23306
23455
|
- API: `GET /v1/reply-templates/{replyTemplateId}`
|
|
23307
23456
|
- Generated from the API contract
|
|
@@ -23320,7 +23469,7 @@ kenso reply-templates get --reply-template-id <reply-template-id>
|
|
|
23320
23469
|
|
|
23321
23470
|
List reply templates in the current workspace.
|
|
23322
23471
|
|
|
23323
|
-
Ordered by id. Requires
|
|
23472
|
+
Ordered by id. Requires Inbox view.
|
|
23324
23473
|
|
|
23325
23474
|
- API: `GET /v1/reply-templates` (a list: `--limit`, `--cursor`, `--all`)
|
|
23326
23475
|
- Generated from the API contract
|
|
@@ -23342,7 +23491,7 @@ kenso reply-templates list --all
|
|
|
23342
23491
|
|
|
23343
23492
|
Update a reply template.
|
|
23344
23493
|
|
|
23345
|
-
Only the fields sent are written; absent fields keep their stored value. JSON null clears `description`. The author is the caller, as on create, and a person's write records `user`. An agent, an MCP token or an API key cannot edit a human-written template. Requires Inbox edit
|
|
23494
|
+
Only the fields sent are written; absent fields keep their stored value. JSON null clears `description`. The author is the caller, as on create, and a person's write records `user`. An agent, an MCP token or an API key cannot edit a human-written template. Requires Inbox edit and the `workspace_settings` permission (owners, admins and editors by default).
|
|
23346
23495
|
|
|
23347
23496
|
- API: `PATCH /v1/reply-templates/{replyTemplateId}`
|
|
23348
23497
|
- Generated from the API contract
|
|
@@ -23985,7 +24134,7 @@ kenso saved-lists create-source --saved-list-id <saved-list-id> --data @body.jso
|
|
|
23985
24134
|
|
|
23986
24135
|
Add a CSV's rows to a saved list.
|
|
23987
24136
|
|
|
23988
|
-
Multipart: the CSV in field `file` (at most 400 MB and 100,000 rows) and, optionally, `columnMappings`: the JSON array the contact-import upload takes, for example `[{"csvColumn":"Email","targetField":"email"},{"csvColumn":"Deal size","targetField":"custom_variable","customVariableName":"deal_size"}]`. Without it the columns map by their headers, as on the campaign upload. Optional List check fields, behind the `csv_import_check` feature (a field sent while it is off is `400 validation_failed` on that field): `fixes`, a JSON array of the fixes left on in a `POST /v1/contact-imports/scans` with target `saved_list` (`blocklist`, `invalidEmail`, `noMx`, `catchAll`, `personalEmail`, `roleAddress`; `missingKey` is accepted and changes nothing), for example `["blocklist","invalidEmail","noMx"]`: the rows the check flags for them are skipped; and `cleanup` (`true` runs every cell of a field with its own cleaner through the import cleaner first). A row already on the list, or a repeat of a row that was kept, still merges into its member with all its addresses: the fixes skip rows, they never strip one address from a merging row. Kenso checks the file and answers 202 with a `csv` source in `pending`, then adds the rows in the background: read the source until it is `done` or `failed`; its `parameters` then carry `rowCount`, `inserted`, `merged` and `rejected` (rows with no LinkedIn URL, email or name and company domain; for a company list, no domain or company page; and the rows a chosen fix skipped, which `skips` counts by fix key), plus the `fixes` and `cleanup` sent. Uploaded emails enter unverified, every phone is kept, and personal columns (birth date, gender, age, personal email and the like) are never stored. Only the workspace's own lists: a shared or library list is 404. Requires Search edit and the
|
|
24137
|
+
Multipart: the CSV in field `file` (at most 400 MB and 100,000 rows) and, optionally, `columnMappings`: the JSON array the contact-import upload takes, for example `[{"csvColumn":"Email","targetField":"email"},{"csvColumn":"Deal size","targetField":"custom_variable","customVariableName":"deal_size"}]`. Without it the columns map by their headers, as on the campaign upload. Optional List check fields, behind the `csv_import_check` feature (a field sent while it is off is `400 validation_failed` on that field): `fixes`, a JSON array of the fixes left on in a `POST /v1/contact-imports/scans` with target `saved_list` (`blocklist`, `invalidEmail`, `noMx`, `catchAll`, `personalEmail`, `roleAddress`; `missingKey` is accepted and changes nothing), for example `["blocklist","invalidEmail","noMx"]`: the rows the check flags for them are skipped; and `cleanup` (`true` runs every cell of a field with its own cleaner through the import cleaner first). A row already on the list, or a repeat of a row that was kept, still merges into its member with all its addresses: the fixes skip rows, they never strip one address from a merging row. Kenso checks the file and answers 202 with a `csv` source in `pending`, then adds the rows in the background: read the source until it is `done` or `failed`; its `parameters` then carry `rowCount`, `inserted`, `merged` and `rejected` (rows with no LinkedIn URL, email or name and company domain; for a company list, no domain or company page; and the rows a chosen fix skipped, which `skips` counts by fix key), plus the `fixes` and `cleanup` sent. Uploaded emails enter unverified, every phone is kept, and personal columns (birth date, gender, age, personal email and the like) are never stored. Only the workspace's own lists: a shared or library list is 404. Requires Search edit and the `import` permission.
|
|
23989
24138
|
|
|
23990
24139
|
- Beta: needs the `saved_lists` feature flag on the workspace.
|
|
23991
24140
|
- API: `POST /v1/saved-lists/{savedListId}/uploads`
|
|
@@ -24416,7 +24565,7 @@ kenso saved-searches update --saved-search-id <saved-search-id>
|
|
|
24416
24565
|
|
|
24417
24566
|
Cancel a scheduled message that has not started sending.
|
|
24418
24567
|
|
|
24419
|
-
Requires `
|
|
24568
|
+
Requires Inbox edit and the `reply` permission. A missing id is `not_found`. A row that is already sending, sent, cancelled, or failed is `invalid_state`. Cancel still returns the scheduled message when restoring the composer draft fails, with `draft.saved` false so the caller saves the draft again.
|
|
24420
24569
|
|
|
24421
24570
|
- API: `POST /v1/scheduled-messages/{scheduledMessageId}/cancel`
|
|
24422
24571
|
- Generated from the API contract
|
|
@@ -24437,7 +24586,7 @@ kenso scheduled-messages cancel --scheduled-message-id <scheduled-message-id>
|
|
|
24437
24586
|
|
|
24438
24587
|
Start a batch scrape and return a job.
|
|
24439
24588
|
|
|
24440
|
-
Requires
|
|
24589
|
+
Requires Search edit. The response is `202` with a `batch_scrape` job. Poll `GET /v1/jobs/{jobId}?type=batch_scrape`. Cancel with `POST /v1/jobs/{jobId}/cancel?type=batch_scrape`.
|
|
24441
24590
|
|
|
24442
24591
|
- API: `POST /v1/scraping/batch-scrapes`
|
|
24443
24592
|
- Generated from the API contract
|
|
@@ -24458,7 +24607,7 @@ kenso scraping create-batch-scrape --data @body.json
|
|
|
24458
24607
|
|
|
24459
24608
|
Start a crawl and return a job.
|
|
24460
24609
|
|
|
24461
|
-
Requires
|
|
24610
|
+
Requires Search edit. The response is `202` with a `crawl` job. Poll `GET /v1/jobs/{jobId}?type=crawl`. Cancel with `POST /v1/jobs/{jobId}/cancel?type=crawl`. SSRF rejection stays in the Firecrawl service. The body needs a `limit` of 1 to 1,000 pages. When the job cannot be recorded, the started crawl is stopped and the answer is `503 service_unavailable`.
|
|
24462
24611
|
|
|
24463
24612
|
- API: `POST /v1/scraping/crawls`
|
|
24464
24613
|
- Generated from the API contract
|
|
@@ -24479,7 +24628,7 @@ kenso scraping create-crawl --data @body.json
|
|
|
24479
24628
|
|
|
24480
24629
|
Start an extraction and return a job.
|
|
24481
24630
|
|
|
24482
|
-
Requires
|
|
24631
|
+
Requires Search edit. The response is `202` with an `extraction` job. Poll `GET /v1/jobs/{jobId}?type=extraction`. Extraction cannot be canceled.
|
|
24483
24632
|
|
|
24484
24633
|
- API: `POST /v1/scraping/extractions`
|
|
24485
24634
|
- Generated from the API contract
|
|
@@ -25199,7 +25348,7 @@ kenso segment-email-sequences get-version --segment-id <segment-id> --version-id
|
|
|
25199
25348
|
|
|
25200
25349
|
List saved versions of a segment email sequence, newest first.
|
|
25201
25350
|
|
|
25202
|
-
`limit` is 1 to 100 and defaults to 20. Requires
|
|
25351
|
+
`limit` is 1 to 100 and defaults to 20. Requires Campaigns view.
|
|
25203
25352
|
|
|
25204
25353
|
- API: `GET /v1/segments/{segmentId}/email-sequence/versions` (a list: `--limit`, `--cursor`, `--all`)
|
|
25205
25354
|
- Generated from the API contract
|
|
@@ -25272,7 +25421,7 @@ kenso segment-email-sequences replace --segment-id <segment-id> --data @body.jso
|
|
|
25272
25421
|
|
|
25273
25422
|
Restore a segment email sequence to a saved version.
|
|
25274
25423
|
|
|
25275
|
-
A link the URL reputation check refuses is 400 `validation_failed` with one `link_reputation_blocked` detail per link; its `field` is `steps.subject` or `steps.body` and `stepId` is the live step the restore would overwrite. Requires
|
|
25424
|
+
A link the URL reputation check refuses is 400 `validation_failed` with one `link_reputation_blocked` detail per link; its `field` is `steps.subject` or `steps.body` and `stepId` is the live step the restore would overwrite. Requires Campaigns edit.
|
|
25276
25425
|
|
|
25277
25426
|
- API: `POST /v1/segments/{segmentId}/email-sequence/versions/{versionId}/restore`
|
|
25278
25427
|
- Generated from the API contract
|
|
@@ -25292,7 +25441,7 @@ kenso segment-email-sequences restore-version --segment-id <segment-id> --versio
|
|
|
25292
25441
|
|
|
25293
25442
|
Save a new segment email sequence version.
|
|
25294
25443
|
|
|
25295
|
-
Omit `steps` to snapshot the live sequence. With `sourceVersionId`, omitted or empty `steps` keep that version's steps, and a non-empty list overlays them. A link the URL reputation check refuses is 400 `validation_failed` with one `link_reputation_blocked` detail per link (`field`, `stepId`, `stepOrder`, `rule`, `url`), as on the sequence replace. Requires
|
|
25444
|
+
Omit `steps` to snapshot the live sequence. With `sourceVersionId`, omitted or empty `steps` keep that version's steps, and a non-empty list overlays them. A link the URL reputation check refuses is 400 `validation_failed` with one `link_reputation_blocked` detail per link (`field`, `stepId`, `stepOrder`, `rule`, `url`), as on the sequence replace. Requires Campaigns edit.
|
|
25296
25445
|
|
|
25297
25446
|
- API: `POST /v1/segments/{segmentId}/email-sequence/versions`
|
|
25298
25447
|
- Generated from the API contract
|
|
@@ -25467,7 +25616,7 @@ kenso segment-linkedin-sequences save-version --segment-id <segment-id> --data @
|
|
|
25467
25616
|
|
|
25468
25617
|
Activate a segment.
|
|
25469
25618
|
|
|
25470
|
-
Idempotent when the segment is already active. Requires
|
|
25619
|
+
Idempotent when the segment is already active. Requires Campaigns edit.
|
|
25471
25620
|
|
|
25472
25621
|
- API: `POST /v1/segments/{segmentId}/activate`
|
|
25473
25622
|
- Generated from the API contract
|
|
@@ -25486,7 +25635,7 @@ kenso segments activate --segment-id <segment-id>
|
|
|
25486
25635
|
|
|
25487
25636
|
Create a segment on a campaign in the current workspace.
|
|
25488
25637
|
|
|
25489
|
-
Returns `201` and `Location`. Requires
|
|
25638
|
+
Returns `201` and `Location`. Requires Campaigns edit.
|
|
25490
25639
|
|
|
25491
25640
|
- API: `POST /v1/campaigns/{campaignId}/segments`
|
|
25492
25641
|
- Generated from the API contract
|
|
@@ -25513,7 +25662,7 @@ kenso segments create --campaign-id <campaign-id> --data @body.json
|
|
|
25513
25662
|
|
|
25514
25663
|
Deactivate a segment.
|
|
25515
25664
|
|
|
25516
|
-
Idempotent when the segment is already inactive. Requires
|
|
25665
|
+
Idempotent when the segment is already inactive. Requires Campaigns edit.
|
|
25517
25666
|
|
|
25518
25667
|
- API: `POST /v1/segments/{segmentId}/deactivate`
|
|
25519
25668
|
- Generated from the API contract
|
|
@@ -25551,7 +25700,7 @@ kenso segments delete --segment-id <segment-id>
|
|
|
25551
25700
|
|
|
25552
25701
|
Return one segment in the current workspace.
|
|
25553
25702
|
|
|
25554
|
-
A missing or cross-workspace id is `not_found`. Requires
|
|
25703
|
+
A missing or cross-workspace id is `not_found`. Requires Campaigns view.
|
|
25555
25704
|
|
|
25556
25705
|
- API: `GET /v1/segments/{segmentId}`
|
|
25557
25706
|
- Generated from the API contract
|
|
@@ -25570,7 +25719,7 @@ kenso segments get --segment-id <segment-id>
|
|
|
25570
25719
|
|
|
25571
25720
|
Return the segment filter catalog.
|
|
25572
25721
|
|
|
25573
|
-
The values a segment filter accepts: seniority levels, functions, industries, company types, employment types, funding rounds, technologies, email validity, email providers and languages, each as `value`, `label` and an optional `category`. The catalog is the same for every workspace and is the `filterOptions` object `POST /v1/campaigns/{campaignId}/segments/preview` returns; this read needs no campaign. It replaces `GET /v1/campaigns/segments/filter-metadata`. Read-only. Requires
|
|
25722
|
+
The values a segment filter accepts: seniority levels, functions, industries, company types, employment types, funding rounds, technologies, email validity, email providers and languages, each as `value`, `label` and an optional `category`. The catalog is the same for every workspace and is the `filterOptions` object `POST /v1/campaigns/{campaignId}/segments/preview` returns; this read needs no campaign. It replaces `GET /v1/campaigns/segments/filter-metadata`. Read-only. Requires Campaigns view.
|
|
25574
25723
|
|
|
25575
25724
|
- API: `GET /v1/segments/filter-options`
|
|
25576
25725
|
- Generated from the API contract
|
|
@@ -25588,7 +25737,7 @@ kenso segments get-filter-options
|
|
|
25588
25737
|
|
|
25589
25738
|
Return one segment version and its snapshot.
|
|
25590
25739
|
|
|
25591
|
-
`segmentationType` and `status` on the snapshot are lowercase snake_case. Requires
|
|
25740
|
+
`segmentationType` and `status` on the snapshot are lowercase snake_case. Requires Campaigns view.
|
|
25592
25741
|
|
|
25593
25742
|
- API: `GET /v1/segments/{segmentId}/versions/{versionId}`
|
|
25594
25743
|
- Generated from the API contract
|
|
@@ -25608,7 +25757,7 @@ kenso segments get-version --segment-id <segment-id> --version-id <version-id>
|
|
|
25608
25757
|
|
|
25609
25758
|
List segments of a campaign in the current workspace.
|
|
25610
25759
|
|
|
25611
|
-
Ordered by id. `q` matches the name. `isActive` filters that flag. `includeMetrics=false` skips the contact counts and omits `contactCount`, `rawContactCount` and `readyContactCount`: use it when only ids and names are needed. Read-only. Requires
|
|
25760
|
+
Ordered by id. `q` matches the name. `isActive` filters that flag. `includeMetrics=false` skips the contact counts and omits `contactCount`, `rawContactCount` and `readyContactCount`: use it when only ids and names are needed. Read-only. Requires Campaigns view.
|
|
25612
25761
|
|
|
25613
25762
|
- API: `GET /v1/campaigns/{campaignId}/segments` (a list: `--limit`, `--cursor`, `--all`)
|
|
25614
25763
|
- Generated from the API contract
|
|
@@ -25636,7 +25785,7 @@ kenso segments list --campaign-id <campaign-id> --all
|
|
|
25636
25785
|
|
|
25637
25786
|
List saved versions of a segment, newest first.
|
|
25638
25787
|
|
|
25639
|
-
`limit` is 1 to 100 and defaults to 20. `cursor` is the opaque cursor from the previous page. Requires
|
|
25788
|
+
`limit` is 1 to 100 and defaults to 20. `cursor` is the opaque cursor from the previous page. Requires Campaigns view.
|
|
25640
25789
|
|
|
25641
25790
|
- API: `GET /v1/segments/{segmentId}/versions` (a list: `--limit`, `--cursor`, `--all`)
|
|
25642
25791
|
- Generated from the API contract
|
|
@@ -25659,7 +25808,7 @@ kenso segments list-versions --segment-id <segment-id> --all
|
|
|
25659
25808
|
|
|
25660
25809
|
Preview a segment filter against the campaign.
|
|
25661
25810
|
|
|
25662
|
-
Returns the match count, a contact sample, and the filter catalog (`filterOptions`). Omit the body to read the catalog only, or read it without a campaign at `GET /v1/segments/filter-options`. A body, including an empty object, runs the match preview. `segmentId` scopes a match preview to an existing segment. Read-only. Requires
|
|
25811
|
+
Returns the match count, a contact sample, and the filter catalog (`filterOptions`). Omit the body to read the catalog only, or read it without a campaign at `GET /v1/segments/filter-options`. A body, including an empty object, runs the match preview. A body whose keys name no filter field is `400 validation_failed` naming those keys, as on create and update. `segmentId` scopes a match preview to an existing segment. Read-only. Requires Campaigns view.
|
|
25663
25812
|
|
|
25664
25813
|
- API: `POST /v1/campaigns/{campaignId}/segments/preview`
|
|
25665
25814
|
- Generated from the API contract
|
|
@@ -25706,7 +25855,7 @@ kenso segments preview --campaign-id <campaign-id> --data @body.json
|
|
|
25706
25855
|
|
|
25707
25856
|
Restore a segment to a saved version.
|
|
25708
25857
|
|
|
25709
|
-
`dryRun` returns the cascade preview and does not write. Each child includes the resolved `snapshot` the revert dialog renders. An applying restore that would clear campaign AI output returns `409 conflict` with `error.impact` until `confirm` is true. Cascade `kind` and `status` are lowercase snake_case. Requires
|
|
25858
|
+
`dryRun` returns the cascade preview and does not write. Each child includes the resolved `snapshot` the revert dialog renders. An applying restore that would clear campaign AI output returns `409 conflict` with `error.impact` until `confirm` is true. Cascade `kind` and `status` are lowercase snake_case. Requires Campaigns edit.
|
|
25710
25859
|
|
|
25711
25860
|
- API: `POST /v1/segments/{segmentId}/versions/{versionId}/restore`
|
|
25712
25861
|
- Generated from the API contract
|
|
@@ -25733,7 +25882,7 @@ kenso segments restore-version --segment-id <segment-id> --version-id <version-i
|
|
|
25733
25882
|
|
|
25734
25883
|
Save a segment as a new version.
|
|
25735
25884
|
|
|
25736
|
-
Applies the body to the segment and writes one version row. The body takes the `PATCH /v1/segments/{segmentId}` fields plus `sourceVersionId`. Absent fields keep the live segment's value, or the `sourceVersionId` version's value when one is given, so a save with no body saves the current state. JSON null clears `description` and `abTestPercentage`. A `sourceVersionId` of another segment is `not_found`, and another save in progress for the segment is `409 conflict`. When the save lands but version history is not captured, `version` is null and `versionWarning` says so. Requires
|
|
25885
|
+
Applies the body to the segment and writes one version row. The body takes the `PATCH /v1/segments/{segmentId}` fields plus `sourceVersionId`. Absent fields keep the live segment's value, or the `sourceVersionId` version's value when one is given, so a save with no body saves the current state. JSON null clears `description` and `abTestPercentage`. A `sourceVersionId` of another segment is `not_found`, and another save in progress for the segment is `409 conflict`. When the save lands but version history is not captured, `version` is null and `versionWarning` says so. Requires Campaigns edit.
|
|
25737
25886
|
|
|
25738
25887
|
- API: `POST /v1/segments/{segmentId}/versions`
|
|
25739
25888
|
- Generated from the API contract
|
|
@@ -25761,7 +25910,7 @@ kenso segments save-version --segment-id <segment-id> --data @body.json
|
|
|
25761
25910
|
|
|
25762
25911
|
Update a segment.
|
|
25763
25912
|
|
|
25764
|
-
Absent fields stay unchanged. JSON null clears `description` and `abTestPercentage`. `filterCriteria` field names are camelCase (matched case-insensitively); an object that names no filter field is `400 validation_failed` and nothing is saved. Requires
|
|
25913
|
+
Absent fields stay unchanged. JSON null clears `description` and `abTestPercentage`. `filterCriteria` field names are camelCase (matched case-insensitively); an object that names no filter field is `400 validation_failed` and nothing is saved. Requires Campaigns edit.
|
|
25765
25914
|
|
|
25766
25915
|
- API: `PATCH /v1/segments/{segmentId}`
|
|
25767
25916
|
- Generated from the API contract
|
|
@@ -25828,7 +25977,7 @@ kenso sending-capacity get
|
|
|
25828
25977
|
|
|
25829
25978
|
### kenso sending-capacity get-forecast
|
|
25830
25979
|
|
|
25831
|
-
Forecast the current workspace's email sends for UTC today and the next two days: what its healthy inboxes can send per day (capacity), what is already queued or planned (planned), and what is left (remaining).
|
|
25980
|
+
Forecast the current workspace's email sends for UTC today and the next two days: what its healthy inboxes can send per day (capacity), what is already queued or planned (planned), and what is left (remaining). Read-only. Requires Delivery view. Takes no what-if inputs.
|
|
25832
25981
|
|
|
25833
25982
|
- API: `GET /v1/sending-capacity/forecast`
|
|
25834
25983
|
- Generated from the API contract
|
|
@@ -26037,7 +26186,7 @@ kenso sending-providers list
|
|
|
26037
26186
|
|
|
26038
26187
|
Return the sequence variable catalog.
|
|
26039
26188
|
|
|
26040
|
-
Pass `campaignId` to include that campaign's custom variables. Requires
|
|
26189
|
+
Pass `campaignId` to include that campaign's custom variables. Requires Campaigns view.
|
|
26041
26190
|
|
|
26042
26191
|
- API: `GET /v1/sequence-variables`
|
|
26043
26192
|
- Generated from the API contract
|
|
@@ -26058,7 +26207,7 @@ kenso sequence-variables get
|
|
|
26058
26207
|
|
|
26059
26208
|
Read the meeting notes shared with you.
|
|
26060
26209
|
|
|
26061
|
-
The token is the last path segment of the emailed link `/meeting-share/{token}`. No `X-Ken-Workspace-Id` needed. Returns the meeting's title and times, who shared it, when the link expires and Ken's notes (`notes` is null until there are notes to read); never a rep's typed lines or the transcript.
|
|
26210
|
+
The token is the last path segment of the emailed link `/meeting-share/{token}`. No `X-Ken-Workspace-Id` needed. Returns the meeting's title and times, who shared it, when the link expires and Ken's notes (`notes` is null until there are notes to read); never a rep's typed lines or the transcript. An unknown or altered token is `404`. Then the address is checked before anything else about the share: the signed-in email must be the shared address (`403 email_mismatch`, whatever state the share is in) and verified, by the session's `email_verified` claim or the user's stored verified email (`403 email_unverified`). Only then the share's state: a deleted meeting is `404`, a revoked share is `410 share_revoked`, an expired one `410 share_expired`, and Kenso Notetaker off for the sharer in that workspace `410 share_inactive`. So a `410` or `200` means the caller holds the shared address. An agent or an API key gets `403`: only a person signed in with the address opens it. Each open is audited, once per person and share per 2 minutes.
|
|
26062
26211
|
|
|
26063
26212
|
- API: `GET /v1/shared-meetings/{token}`
|
|
26064
26213
|
- Generated from the API contract
|
|
@@ -26341,7 +26490,7 @@ kenso signal-vendor-connections get --integration-key <integration-key>
|
|
|
26341
26490
|
|
|
26342
26491
|
Queue signals for the current workspace.
|
|
26343
26492
|
|
|
26344
|
-
Requires Search edit access (owners, admins and editors by default). `type` and `source` are lowercase snake_case.
|
|
26493
|
+
Requires Search edit access (owners, admins and editors by default). `type` and `source` are lowercase snake_case. Every signal is stored as synthetic. A call sends at most 100 signals, each counted against the workspace's signal quota. A contact, campaign, or segment outside the workspace is rejected before publish. `duplicateCount` counts signals skipped because their `dedupKey` was queued in the last 24 hours.
|
|
26345
26494
|
|
|
26346
26495
|
- API: `POST /v1/signals`
|
|
26347
26496
|
- Generated from the API contract
|
|
@@ -26566,7 +26715,7 @@ kenso spend-limits update --data @body.json
|
|
|
26566
26715
|
|
|
26567
26716
|
Add a person to an account as a stakeholder.
|
|
26568
26717
|
|
|
26569
|
-
Send `personId` (an existing person) or `person` (found by email, then LinkedIn URL, then kenPersonId, else created; a match only fills its blank fields), plus `role` (champion, economic_buyer, approver, evaluator, user, executive_sponsor, blocker, unknown), `priority` (1-3), `coverage` (engaged, planned, gap, not_targeted), `note`, `kenNote` (up to 1,000 characters), `reportsToStakeholderId` (a stakeholder on the same account, no cycles) and `fillsSeatId` (an open seat on this account, closed in the same write). Conflicts: `already_stakeholder`; `previously_removed` when a person removed them and the caller is not a person (resend with `force: true` only when the user asked). Requires
|
|
26718
|
+
Send `personId` (an existing person) or `person` (found by email, then LinkedIn URL, then kenPersonId, else created; a match only fills its blank fields), plus `role` (champion, economic_buyer, approver, evaluator, user, executive_sponsor, blocker, unknown), `priority` (1-3), `coverage` (engaged, planned, gap, not_targeted), `note`, `kenNote` (up to 1,000 characters), `reportsToStakeholderId` (a stakeholder on the same account, no cycles) and `fillsSeatId` (an open seat on this account, closed in the same write). Conflicts: `already_stakeholder`; `previously_removed` when a person removed them and the caller is not a person (resend with `force: true` only when the user asked). Requires Accounts edit.
|
|
26570
26719
|
|
|
26571
26720
|
- Beta: needs the `accounts` feature flag on the workspace.
|
|
26572
26721
|
- API: `POST /v1/accounts/{accountId}/stakeholders`
|
|
@@ -26600,7 +26749,7 @@ kenso stakeholders create --account-id <account-id> --data @body.json
|
|
|
26600
26749
|
|
|
26601
26750
|
Remove a stakeholder from its account.
|
|
26602
26751
|
|
|
26603
|
-
Skips their open touches; the person stays. Returns `204`. Requires
|
|
26752
|
+
Skips their open touches; the person stays. Returns `204`. Requires Accounts edit.
|
|
26604
26753
|
|
|
26605
26754
|
- Beta: needs the `accounts` feature flag on the workspace.
|
|
26606
26755
|
- API: `DELETE /v1/stakeholders/{stakeholderId}`
|
|
@@ -26620,7 +26769,7 @@ kenso stakeholders delete --stakeholder-id <stakeholder-id>
|
|
|
26620
26769
|
|
|
26621
26770
|
List an account's stakeholders, each with its person.
|
|
26622
26771
|
|
|
26623
|
-
Oldest first. Requires
|
|
26772
|
+
Oldest first. Requires Accounts view.
|
|
26624
26773
|
|
|
26625
26774
|
- Beta: needs the `accounts` feature flag on the workspace.
|
|
26626
26775
|
- API: `GET /v1/accounts/{accountId}/stakeholders` (a list: `--limit`, `--cursor`, `--all`)
|
|
@@ -26644,7 +26793,7 @@ kenso stakeholders list --account-id <account-id> --all
|
|
|
26644
26793
|
|
|
26645
26794
|
Update a stakeholder. Absent fields stay unchanged; null clears.
|
|
26646
26795
|
|
|
26647
|
-
Fields: role, priority, coverage, note, kenNote, reportsToStakeholderId. Pinned fields need `overwritePinned: true`. Requires
|
|
26796
|
+
Fields: role, priority, coverage, note, kenNote, reportsToStakeholderId. Pinned fields need `overwritePinned: true`. Requires Accounts edit.
|
|
26648
26797
|
|
|
26649
26798
|
- Beta: needs the `accounts` feature flag on the workspace.
|
|
26650
26799
|
- API: `PATCH /v1/stakeholders/{stakeholderId}`
|
|
@@ -26967,7 +27116,7 @@ kenso subscription update --data @body.json
|
|
|
26967
27116
|
|
|
26968
27117
|
Stream the stored attachment bytes for the calling user.
|
|
26969
27118
|
|
|
26970
|
-
Replaces `GET /v1/support-chat/attachments/{id}/content`. Requires `
|
|
27119
|
+
Replaces `GET /v1/support-chat/attachments/{id}/content`. Requires the `ask` permission.
|
|
26971
27120
|
|
|
26972
27121
|
- API: `GET /v1/support/attachments/{attachmentId}/content`
|
|
26973
27122
|
- Generated from the API contract
|
|
@@ -26986,7 +27135,7 @@ kenso support-attachments content --attachment-id <attachment-id>
|
|
|
26986
27135
|
|
|
26987
27136
|
Upload a file for the support agent to read: PDF, Word, Markdown, text, CSV or image.
|
|
26988
27137
|
|
|
26989
|
-
Replaces `POST /v1/support-chat/attachments`. Multipart field `file`, at most 20 MB. Takes .pdf, .docx, .md, .markdown, .txt, .csv, .png, .jpg, .jpeg, .webp and .gif, checked against the file's bytes; `kind` is `pdf`, `docx`, `text` or `image`. Each upload draws on per-user and per-workspace daily quotas; a refusal is `429`. A PDF without a text layer comes back with `textStatus``pending` while OCR reads it in the background, under the workspace's OCR page budget. Requires `
|
|
27138
|
+
Replaces `POST /v1/support-chat/attachments`. Multipart field `file`, at most 20 MB. Takes .pdf, .docx, .md, .markdown, .txt, .csv, .png, .jpg, .jpeg, .webp and .gif, checked against the file's bytes; `kind` is `pdf`, `docx`, `text` or `image`. Each upload draws on per-user and per-workspace daily quotas; a refusal is `429`. A PDF without a text layer comes back with `textStatus``pending` while OCR reads it in the background, under the workspace's OCR page budget. Requires the `ask` permission.
|
|
26990
27139
|
|
|
26991
27140
|
- API: `POST /v1/support/attachments`
|
|
26992
27141
|
- Generated from the API contract
|
|
@@ -27007,7 +27156,7 @@ kenso support-attachments create --file ./file.csv
|
|
|
27007
27156
|
|
|
27008
27157
|
Read attachment metadata and extracted text for the calling user.
|
|
27009
27158
|
|
|
27010
|
-
Replaces `GET /v1/support-chat/attachments/{id}`. Requires `
|
|
27159
|
+
Replaces `GET /v1/support-chat/attachments/{id}`. Requires the `ask` permission.
|
|
27011
27160
|
|
|
27012
27161
|
- API: `GET /v1/support/attachments/{attachmentId}`
|
|
27013
27162
|
- Generated from the API contract
|
|
@@ -27076,7 +27225,7 @@ kenso tags bulk-assign --tag-id <tag-id> --data @body.json
|
|
|
27076
27225
|
|
|
27077
27226
|
Remove a tag from up to 1,000 entities in one call.
|
|
27078
27227
|
|
|
27079
|
-
Same body, validation, and per-item behavior as `bulk-create`, through the same path as `DELETE /v1/tags/{tagId}/assignments`. A successful item is `removed`. The route needs workspace membership; each item's entity type adds its page edit access, as on assign.
|
|
27228
|
+
Same body, validation, and per-item behavior as `bulk-create`, through the same path as `DELETE /v1/tags/{tagId}/assignments`. A successful item is `removed`. A deleted tag of the workspace can still be removed from `reply` and `linkedin_conversation` items; every other item is then `not_found`. The route needs workspace membership; each item's entity type adds its page edit access, as on assign.
|
|
27080
27229
|
|
|
27081
27230
|
- API: `POST /v1/tags/{tagId}/assignments/bulk-delete`
|
|
27082
27231
|
- Generated from the API contract
|
|
@@ -27187,7 +27336,7 @@ kenso tags list --all
|
|
|
27187
27336
|
|
|
27188
27337
|
Remove a tag assignment.
|
|
27189
27338
|
|
|
27190
|
-
Query parameters, not a body: `entityType` plus `entityId`, `messageId`, or `conversationId` (the same ids as on assign). A missing `entityType` is `validation_failed`, and a tag outside the workspace is `404 not_found`. The route needs workspace membership; the entity type adds its page edit access, as on assign.
|
|
27339
|
+
Query parameters, not a body: `entityType` plus `entityId`, `messageId`, or `conversationId` (the same ids as on assign). A missing `entityType` is `validation_failed`, and a tag outside the workspace is `404 not_found`. A deleted tag of the workspace can still be removed from a `reply` or a `linkedin_conversation`. The route needs workspace membership; the entity type adds its page edit access, as on assign.
|
|
27191
27340
|
|
|
27192
27341
|
- API: `DELETE /v1/tags/{tagId}/assignments`
|
|
27193
27342
|
- Generated from the API contract
|
|
@@ -27343,7 +27492,7 @@ kenso teams-connection update --data @body.json
|
|
|
27343
27492
|
|
|
27344
27493
|
Apply the same field update to up to 1,000 threads.
|
|
27345
27494
|
|
|
27346
|
-
Returns per-id outcomes. Requires
|
|
27495
|
+
Returns per-id outcomes. Requires Inbox edit.
|
|
27347
27496
|
|
|
27348
27497
|
- API: `POST /v1/threads/bulk-update`
|
|
27349
27498
|
- Generated from the API contract
|
|
@@ -27364,7 +27513,7 @@ kenso threads bulk-update --data @body.json
|
|
|
27364
27513
|
|
|
27365
27514
|
Count inbox threads by tab and source.
|
|
27366
27515
|
|
|
27367
|
-
Requires Inbox view. Email and LinkedIn together. `status`, `folder`, `isArchived` and `isSaved` name the tab the way `GET /v1/threads` takes them, and `allCount` is the number of distinct threads that list returns for the tab. The list's `pagination.total` counts email messages, so it is higher when a thread has several messages in the tab. `accountsCount` and `campaignsCount` split the tab by account-linked and campaign threads, and `campaigns` lists every campaign with a thread in the inbox. `toReplyCount`, `unreadCount`, `latestMessageAt` and `inboxChangedAt` ignore the tab filters. `inboxChangedAt` moves when a reply arrives (a late-synced one included) or changes tab, for example when the classifier files it; poll it and refetch the list when it changes. An email thread is counted once however many messages it has; a LinkedIn conversation is one thread.
|
|
27516
|
+
Requires Inbox view. Email and LinkedIn together. `status`, `folder`, `isArchived` and `isSaved` name the tab the way `GET /v1/threads` takes them, and `allCount` is the number of distinct threads that list returns for the tab. The list's `pagination.total` counts email messages, so it is higher when a thread has several messages in the tab. `accountsCount` and `campaignsCount` split the tab by account-linked and campaign threads, and `campaigns` lists every campaign with a thread in the inbox. `toReplyCount`, `unreadCount`, `latestMessageAt` and `inboxChangedAt` ignore the tab filters. `inboxChangedAt` moves when a reply arrives (a late-synced one included) or changes tab, for example when the classifier files it; poll it and refetch the list when it changes. An email thread is counted once however many messages it has; a LinkedIn conversation is one thread. With `groupBy=person` the counts count distinct people instead (`allCount`, `accountsCount`, `campaignsCount`, `toReplyCount`, `unreadCount`, `campaigns[].threadCount`), each the number of rows `GET /v1/threads?groupBy=person` lists for that tab. A person counts under a campaign or an account by the campaign or account of their thread in the tab. A tab that lists our own sends (`folder=sent` or `folder=all`) keeps its thread counts in `allCount`, `accountsCount`, `campaignsCount` and `campaigns[].threadCount` under `groupBy=person`, since its grouped list's total may be capped; when `pagination.isTotalCapped` is true, show that total as N+. `toReplyCount` and `unreadCount` still count people (DEV-7255).
|
|
27368
27517
|
|
|
27369
27518
|
- API: `GET /v1/threads/counts`
|
|
27370
27519
|
- Generated from the API contract
|
|
@@ -27372,6 +27521,7 @@ Requires Inbox view. Email and LinkedIn together. `status`, `folder`, `isArchive
|
|
|
27372
27521
|
| Flag | Type | Required | Description |
|
|
27373
27522
|
| --- | --- | --- | --- |
|
|
27374
27523
|
| `--folder` | string | no | Inbox folder: inbox, sent, or all. Omitted means inbound. |
|
|
27524
|
+
| `--group-by` | string | no | `person`: every count counts distinct people (a row of `GET /v1/threads?groupBy=person`) instead of threads (DEV-7255). Omitted counts threads. Any other value is 400. |
|
|
27375
27525
|
| `--is-archived` | boolean | no | isArchived (query, boolean) |
|
|
27376
27526
|
| `--is-saved` | boolean | no | isSaved (query, boolean) |
|
|
27377
27527
|
| `--status` | string | no | Inbox tab token: to_reply, other, automated_reply, not_interested, human_reply. |
|
|
@@ -27413,7 +27563,7 @@ kenso threads create --data @body.json
|
|
|
27413
27563
|
|
|
27414
27564
|
Send a message on a thread.
|
|
27415
27565
|
|
|
27416
|
-
Email requires `senderEmailId`. An email reply goes to the thread's sender unless it names `to`, or `replyAll: true` (the sender, To and Cc, less the sending inbox); `cc` and `bcc` add recipients, each one bare email address. `attachmentIds` are `att_` ids uploaded against this thread (its newest message), and `contentType` is `html` (default) or `text`. Those six fields are email only: a LinkedIn reply that names any of them is `400 validation_failed` on that field and sends nothing (DEV-2537). LinkedIn sends plain text through the conversation seat
|
|
27566
|
+
Email requires `senderEmailId`. An email reply goes to the thread's sender unless it names `to`, or `replyAll: true` (the sender, To and Cc, less the sending inbox); `cc` and `bcc` add recipients, each one bare email address. `attachmentIds` are `att_` ids uploaded against this thread (its newest message), and `contentType` is `html` (default) or `text`. Those six fields are email only: a LinkedIn reply that names any of them is `400 validation_failed` on that field and sends nothing (DEV-2537). An email reply is queued for an undo window: `delaySeconds` is 60 (the default) or 300, as on a forward, and the `201` carries the queued reply's `scheduledMessageId`, which `POST /v1/scheduled-messages/{id}/cancel` takes until the window ends. A retry under the same `Idempotency-Key` returns the first reply whatever its delay (DEV-7673). `subject` is for drafts: a reply goes out on the thread's subject. LinkedIn sends plain text through the conversation seat at once, and ignores `delaySeconds`. A LinkedIn `Idempotency-Key` is bound to its thread and message: reusing it on another thread, or with another body once decided, returns `409 idempotency_key_reused` and sends nothing. Without a key, the same text repeated in a thread more than 5 minutes later is sent again. An email `Idempotency-Key` (optional, at most 200 characters, unique in the workspace) is bound to its thread, inbox and body, and to its `to`, `cc`, `bcc`, `replyAll`, `contentType` and `attachmentIds` when it names any: a retry returns the reply it scheduled, or the `202` with the client approval item it was held as, and queues nothing; another request under it is `409 idempotency_key_reused`; one still being queued is `409 in_progress` with `nextAllowedAt` and `Retry-After`; one Kenso cannot tell was queued is `409 outcome_unknown` and never queues again. A refused reply frees its key (DEV-3672). Requires Inbox edit and the `reply` permission. The send is recorded only after the provider accepts it. An email reply to a do-not-contact, blocklisted or unsubscribed contact returns `409 invalid_state` with a `confirmSuppressed` detail whose code is the reason, and is sent only when the request repeats with `confirmSuppressed: true`. LinkedIn replies to a suppressed contact are always refused. An email reply is recorded with its caller: a person, an API key, or an agent (any credential sent with `X-Ken-Actor: agent`). An API key or agent reply from its own member's mailbox is not sent: it returns `202` with the scheduled message in `status: awaiting_approval` and `approverMemberId`, and waits in that member's `GET /v1/approvals` until they approve it in person (DEV-6060); with `accounts` off, or from another member's own mailbox, it is `403 forbidden`. Its reply from an inbox a member paused or Ken blocked from sending is a `409 invalid_state` whose detail code is `inbox_paused` or `inbox_send_blocked`, with a `fix` (DEV-3672). A block carries `nextAllowedAt` (its end) and `Retry-After`; a pause has no known end and carries neither. A pause or block that starts during the undo window refuses the queued reply at send time: the scheduled message ends `failed`. When the workspace requires external approval for replies, an email reply is not sent: the response is `202` with `status``held_for_client_approval` and the `clientApprovalItemId` that holds it (DEV-1526). An email reply a teammate writes in person from a client seat's own inbox, with `accounts_send` on, is not sent either: it returns `202` with the scheduled message (`ScheduledMessageModel`) in `status: awaiting_approval` and `approverMemberId`, and waits in that client's `GET /v1/approvals` (DEV-2043). Email `archiveAfterSend: true` archives the thread once the reply sends; a waiting reply archives only when the approved reply sends, never while it waits. An API key or agent LinkedIn reply through a seat another member connected is not sent (DEV-6464): it returns `202` with `status: awaiting_approval`, `channel: linkedin`, the `approvalId` (type `reply.linkedin`) and `approverMemberId` (the seat owner), and waits in that member's `GET /v1/approvals` until they approve it in person, when it sends once. A retry with the same `Idempotency-Key` (or the same text without one) returns the same waiting reply. With `accounts` off for the owner, or a seat no member connected, it is `403 forbidden`. A person's own reply from the dashboard, and the seat owner's own agent or API key, send as before.
|
|
27417
27567
|
|
|
27418
27568
|
- API: `POST /v1/threads/{threadId}/messages`
|
|
27419
27569
|
- Generated from the API contract
|
|
@@ -27423,8 +27573,9 @@ Email requires `senderEmailId`. An email reply goes to the thread's sender unles
|
|
|
27423
27573
|
| --- | --- | --- | --- |
|
|
27424
27574
|
| `--thread-id` | string | yes | threadId (path, string) |
|
|
27425
27575
|
| `--body` | string | no | body (body, string) |
|
|
27426
|
-
| `--subject` | string | no | subject (
|
|
27576
|
+
| `--subject` | string | no | Drafts only: a reply goes out on the thread's own subject, so a send ignores this field. Set a draft's subject with `PUT /v1/threads/{threadId}/draft` (DEV-7673). |
|
|
27427
27577
|
| `--sender-email-id` | integer | no | senderEmailId (body, integer) |
|
|
27578
|
+
| `--delay-seconds` | integer | no | Email only: the undo window in seconds before the reply sends, 60 or 300, as on a forward. Omitted, it is 60. An agent sends 300. Cancel the queued reply with `POST /v1/scheduled-messages/{id}/cancel` and the response's `scheduledMessageId`. A LinkedIn reply sends at once and ignores it (DEV-7673). |
|
|
27428
27579
|
| `--confirm-suppressed` | boolean | no | Email only: send even though the contact is do-not-contact, blocklisted or unsubscribed. Set only after the user confirmed a `409 invalid_state` for a suppressed contact. |
|
|
27429
27580
|
| `--archive-after-send` | boolean | no | Email only: archive the thread once the reply sends. A reply waiting on a client seat's approval archives when the approved reply sends, never while it waits, and a skipped one leaves the thread as it was (DEV-2043). |
|
|
27430
27581
|
| `--reply-all` | boolean | no | Email only: without Ken.Scraper.API.Dtos.CreateThreadMessageRequest.To, reply to the thread's sender, To and Cc, less the sending inbox. A LinkedIn thread refuses it (DEV-2537). |
|
|
@@ -27462,7 +27613,7 @@ kenso threads delete-draft --thread-id <thread-id>
|
|
|
27462
27613
|
|
|
27463
27614
|
Forward an email thread to new recipients.
|
|
27464
27615
|
|
|
27465
|
-
Requires `
|
|
27616
|
+
Requires Inbox edit and the `reply` and `export` permissions (the built-in Client template has no `export`, so a Client seat replies but does not forward). Email only. The forward is queued and the provider confirms delivery later. `to` is required unless `replyAll` is true. `delaySeconds` is 60 or 300. `attachmentIds` are `att_` ids for this thread. Every recipient is one bare email address. A forward that reaches the thread (`replyAll` without `to`, or the contact or another participant as a recipient) returns `409 invalid_state` when the contact is suppressed (detail code is the reason; there is no confirm override, send a reply instead) or when the workspace holds replies for external approval (detail code `client_approval_required`). A queued forward returns `200` with the scheduled message. An API key or agent forward from its own member's mailbox is not sent: it returns `202` with the scheduled message in `status: awaiting_approval` and `approverMemberId`, and waits in that member's `GET /v1/approvals` until they approve it in person (DEV-6060); with `accounts` off, or from another member's own mailbox, it is `403 forbidden`.
|
|
27466
27617
|
|
|
27467
27618
|
- API: `POST /v1/threads/{threadId}/forward`
|
|
27468
27619
|
- Generated from the API contract
|
|
@@ -27497,7 +27648,7 @@ kenso threads forward --thread-id <thread-id> --data @body.json
|
|
|
27497
27648
|
|
|
27498
27649
|
Return one thread.
|
|
27499
27650
|
|
|
27500
|
-
A malformed id, unknown channel, or cross-workspace thread is `not_found`. `accountId` and `accountName` are the account whose touch the thread is, else the account on which the thread's contact is a stakeholder, when there is one. An email thread that is an account touch's thread also carries `replyTouchId`: that account's open reply touch answering the thread, which sends the reply when approved (DEV-2537). `hasDraft` says a reply draft is saved on the thread and `draftAuthor` who wrote it. Requires
|
|
27651
|
+
A malformed id, unknown channel, or cross-workspace thread is `not_found`. `accountId` and `accountName` are the account whose touch the thread is, else the account on which the thread's contact is a stakeholder, when there is one. An email thread that is an account touch's thread also carries `replyTouchId`: that account's open reply touch answering the thread, which sends the reply when approved (DEV-2537). `hasDraft` says a reply draft is saved on the thread and `draftAuthor` who wrote it. Requires Inbox view. An email thread carries `scheduledMessages`: replies and forwards queued on it that have not sent yet, including a teammate's reply waiting on a client seat (`awaiting_approval`, DEV-2043), which the writer can withdraw with `POST /v1/scheduled-messages/{id}/cancel`.
|
|
27501
27652
|
|
|
27502
27653
|
- API: `GET /v1/threads/{threadId}`
|
|
27503
27654
|
- Generated from the API contract
|
|
@@ -27535,7 +27686,7 @@ kenso threads get-draft --thread-id <thread-id>
|
|
|
27535
27686
|
|
|
27536
27687
|
List threads in the current workspace.
|
|
27537
27688
|
|
|
27538
|
-
Requires
|
|
27689
|
+
Requires Inbox view. `channel` is `email`, `linkedin`, or `all`. `limit` defaults to 50 and maxes at 100, matching the inbox list. `status` and `folder` are the inbox tab filters (to_reply, other, automated_reply, not_interested, sent) and are applied before paging. `contactId`, `inboxId`, `hasReminder` and `interest` are applied before paging too, to each thread's row, so `hasMore` and `pagination.total` count the matching threads (DEV-7640). `inboxId` is the row's `inboxId`: a LinkedIn thread's account, or the workspace inbox an email row's message was sent to (an address in its `to`) or from (DEV-7673). `interest=not_interested` matches both not-interested classifications: the one this API writes, which reads back as `negative`, and the older one, which reads back as `not_interested`. Each thread is one row, its newest message in the tab, and `pagination.total` counts threads, as `GET /v1/threads/counts` does (DEV-4083). Under `folder=all` that is the newest message in either direction, and a message we sent carries no label and no reminder, so filter `interest` and `hasReminder` with `folder=inbox` to match each thread's newest reply. Email inbox ids and LinkedIn account ids are separate id spaces: on `channel=all` an `inboxId` matches either, so pass `channel` with it to stay on one (DEV-7693). With `q`, `pagination.total` counts at most 1,000 threads: past 1,000 it is 1,000 and `pagination.isTotalCapped` is true, and paging goes on while `hasMore` is true. Without `q`, or at 1,000 matches or fewer, the total is exact and `isTotalCapped` is omitted (DEV-4517). To Reply is attributed Interested, Objection, and Wrong Contact, plus due reminders. A thread leaves it once our reply is its newest message, as a LinkedIn conversation does, and comes back with the lead's next reply. `source` is the lane on top of the tab: `accounts` (account touch threads) or `campaigns` (campaign threads), with the predicates of `accountsCount` and `campaignsCount` on `GET /v1/threads/counts`. Omitted lists every thread of the tab. A row of an account touch's thread carries `accountId` and `accountName` while the accounts feature is on for the caller, and an email one `replyTouchId`, the account's open reply touch answering the thread, when there is one (DEV-2537). Every row carries `hasDraft`, and `draftAuthor` (`user` or `agent`) when a reply draft is saved on it. `sort=oldest_waiting` lists the thread that has waited longest first, across pages: by `waitingSince`, else by the newest message; omitted keeps the inbox order, newest first. Each row whose newest message is the contact's carries `waitingSince`, when that message arrived, on any tab; it is a wait on a reply only on `to_reply`. A thread we answered whose reminder came due waits since that reminder (DEV-5202).
|
|
27539
27690
|
|
|
27540
27691
|
- API: `GET /v1/threads` (a list: `--limit`, `--cursor`, `--all`)
|
|
27541
27692
|
- Generated from the API contract
|
|
@@ -27544,16 +27695,18 @@ Requires `ReadAccess`. `channel` is `email`, `linkedin`, or `all`. `limit` defau
|
|
|
27544
27695
|
| --- | --- | --- | --- |
|
|
27545
27696
|
| `--campaign-id` | integer | no | campaignId (query, integer) |
|
|
27546
27697
|
| `--channel` | string | no | channel (query, string) |
|
|
27547
|
-
| `--contact-id` | integer | no | contactId
|
|
27698
|
+
| `--contact-id` | integer | no | Threads with this `contactId`, as each row carries it: the stored contact, or for a LinkedIn conversation stored with none, the contact its attendee is matched to (DEV-7673). |
|
|
27548
27699
|
| `--cursor` | string | no | Start at this cursor (the next: hint of a previous page). |
|
|
27549
27700
|
| `--folder` | string | no | Inbox folder: inbox, sent, or all. Omitted means inbound, matching the legacy list. |
|
|
27550
|
-
| `--
|
|
27551
|
-
| `--
|
|
27552
|
-
| `--
|
|
27701
|
+
| `--group-by` | string | no | `person`: one row per person, the person's newest thread in the tab (DEV-7255). Each row adds `personKey` (`per_`, else `con_`, else the row's `thr_` id), `personId` and `personName` (null unless `per_`), and over the person's threads on any tab `channels` (`{ email, linkedin }`), `waitingCount` (threads To Reply lists) and `threadIds` (newest first, at most 200). `pagination.total` then counts people. On a tab that lists our own sends (`folder=sent` or `folder=all`) in the default order and without `q`, the total may be capped, counting only the people among the newest messages read for the page; when `pagination.isTotalCapped` is true, show the total as N+ and page while `hasMore` is true. With `q` the total is capped at 1000 people as a plain search's is at 1000 threads. With `sort=oldest_waiting` a person sorts by their longest wait in the tab, and the row stays their newest thread. Omitted lists one row per thread. Any other value is 400. |
|
|
27702
|
+
| `--has-reminder` | boolean | no | true lists threads whose row carries a reminder, false those whose row carries none. Under `folder=all` a thread's row is its newest message in either direction, and a message we sent carries no reminder, so a thread we answered after setting a reminder on the reply does not match true. To filter threads by their newest reply, list with `folder=inbox` (DEV-7693). |
|
|
27703
|
+
| `--inbox-id` | integer | no | Threads whose `inboxId` is this inbox: a LinkedIn thread's account, or the workspace inbox an email row's message was sent to or from (DEV-7673). Email inbox ids and LinkedIn account ids are separate id spaces, so on `channel=all` (the default) the id matches an email inbox or a LinkedIn account with that id; pass `channel` to stay on one (DEV-7693). |
|
|
27704
|
+
| `--interest` | string | no | Threads whose row carries this label: interested, not_interested, negative, automated, unclassified, unsubscribe, objection, wrong_contact, out_of_office or referral; not_interested also matches negative. Under `folder=all` a thread's row is its newest message in either direction, and a message we sent carries no label (it reads as unclassified), so a thread we already answered matches only unclassified. To filter threads by their newest reply, list with `folder=inbox` (DEV-7693). |
|
|
27553
27705
|
| `--is-archived` | boolean | no | isArchived (query, boolean) |
|
|
27554
27706
|
| `--is-read` | boolean | no | isRead (query, boolean) |
|
|
27555
27707
|
| `--is-saved` | boolean | no | isSaved (query, boolean) |
|
|
27556
27708
|
| `--limit` | integer | no | Page size. |
|
|
27709
|
+
| `--person-key` | string | no | A row's `personKey` (`per_`, `con_` or `thr_`): every thread of that person, archived or not, newest first, each with the `groupBy=person` fields (DEV-7255). Every folder unless a `folder` or `status` is given; other filters still narrow it. Malformed is 400. |
|
|
27557
27710
|
| `--q` | string | no | q (query, string) |
|
|
27558
27711
|
| `--sort` | string | no | `oldest_waiting`: the thread that has waited longest first, across pages, by each row's `waitingSince`, else its newest message (DEV-5202). Omitted keeps the inbox order, newest first. Any other value is 400. |
|
|
27559
27712
|
| `--source` | string | no | The inbox lane on top of the tab: accounts or campaigns, matching accountsCount and campaignsCount of GET /v1/threads/counts. Omitted means every thread of the tab. Any other value is 400. |
|
|
@@ -27576,12 +27729,16 @@ kenso threads list --all
|
|
|
27576
27729
|
|
|
27577
27730
|
List messages in a thread, oldest first.
|
|
27578
27731
|
|
|
27732
|
+
Every item carries `kind`: `message` for a chat or email message. `includeEvents=true` on a LinkedIn thread also lists the connection note Ken sent with the invitation (`connection_note`, outbound) and the moment the person accepted (`connection_accepted`, inbound, empty body) in time order, an event before a message sent at the same instant. An email thread ignores it, and a failed read of the events returns the messages alone.
|
|
27733
|
+
|
|
27579
27734
|
- API: `GET /v1/threads/{threadId}/messages`
|
|
27580
27735
|
- Generated from the API contract
|
|
27581
27736
|
|
|
27582
27737
|
| Flag | Type | Required | Description |
|
|
27583
27738
|
| --- | --- | --- | --- |
|
|
27584
27739
|
| `--thread-id` | string | yes | threadId (path, string) |
|
|
27740
|
+
| `--include-events` | boolean | no | includeEvents (query, boolean) |
|
|
27741
|
+
| `--no-include-events` | boolean | no | Send includeEvents as false. |
|
|
27585
27742
|
| `--each` | string | no | Run once per row of a JSONL or CSV file (- for stdin); row keys fill params and body by name. |
|
|
27586
27743
|
| `--concurrency` | integer | no | With --each: requests in flight at once (1-16, default 4). |
|
|
27587
27744
|
|
|
@@ -27686,7 +27843,7 @@ kenso threads suggest --thread-id <thread-id> --data @body.json
|
|
|
27686
27843
|
|
|
27687
27844
|
Update thread fields. Absent fields stay unchanged. Null `reminderAt` clears a reminder.
|
|
27688
27845
|
|
|
27689
|
-
Requires
|
|
27846
|
+
Requires Inbox edit. The thread comes back with `hasDraft` and `draftAuthor`, as threads.get serves them; `accountId`, `replyTouchId` and `scheduledMessages` are left out (DEV-2537). `personId` (a positive integer) links the thread's contact to that person, replacing any link; a merged person links as its survivor. It needs the `unified_inbox` feature for the workspace (off is `404 not_found`) and Accounts edit (without it, `403 permission_denied`). No contact is `422 unprocessable` and a person not in the workspace (or deleted) is `404 not_found`. Each of these answers before any field is written; the link is written after the other fields, so a refused field leaves no link (DEV-7255). Bulk update refuses `personId`.
|
|
27690
27847
|
|
|
27691
27848
|
- API: `PATCH /v1/threads/{threadId}`
|
|
27692
27849
|
- Generated from the API contract
|
|
@@ -28137,7 +28294,7 @@ kenso touches update --touch-id <touch-id> --data @body.json
|
|
|
28137
28294
|
|
|
28138
28295
|
Create a tracking link on a campaign in the current workspace.
|
|
28139
28296
|
|
|
28140
|
-
Returns `201` and `Location`. Requires
|
|
28297
|
+
Returns `201` and `Location`. Requires Delivery edit.
|
|
28141
28298
|
|
|
28142
28299
|
- API: `POST /v1/campaigns/{campaignId}/tracking-links`
|
|
28143
28300
|
- Generated from the API contract
|
|
@@ -28181,7 +28338,7 @@ kenso tracking-links delete --tracking-link-id <tracking-link-id>
|
|
|
28181
28338
|
|
|
28182
28339
|
Return one tracking link in the current workspace.
|
|
28183
28340
|
|
|
28184
|
-
A missing or cross-workspace id is `not_found`. Requires
|
|
28341
|
+
A missing or cross-workspace id is `not_found`. Requires Delivery view.
|
|
28185
28342
|
|
|
28186
28343
|
- API: `GET /v1/tracking-links/{trackingLinkId}`
|
|
28187
28344
|
- Generated from the API contract
|
|
@@ -28200,7 +28357,7 @@ kenso tracking-links get --tracking-link-id <tracking-link-id>
|
|
|
28200
28357
|
|
|
28201
28358
|
List a campaign's tracking links in the current workspace.
|
|
28202
28359
|
|
|
28203
|
-
Ordered by id. Read-only. Requires
|
|
28360
|
+
Ordered by id. Read-only. Requires Delivery view.
|
|
28204
28361
|
|
|
28205
28362
|
- API: `GET /v1/campaigns/{campaignId}/tracking-links` (a list: `--limit`, `--cursor`, `--all`)
|
|
28206
28363
|
- Generated from the API contract
|
|
@@ -28223,7 +28380,7 @@ kenso tracking-links list --campaign-id <campaign-id> --all
|
|
|
28223
28380
|
|
|
28224
28381
|
Update a tracking link.
|
|
28225
28382
|
|
|
28226
|
-
Absent fields stay unchanged. JSON null clears `textValue`. Requires
|
|
28383
|
+
Absent fields stay unchanged. JSON null clears `textValue`. Requires Delivery edit. A new `domainName` goes through the URL reputation check, and changing it after mail with the link went out counts against a daily cap (`429 rate_limited` with `Retry-After` while Kenso enforces the URL reputation check). A new `domainName` on a link served from a Kenso shared tracking host is `409 shared_host_link_frozen`, and off a paid plan `402 plan_limit_reached` (`refusal.code``link_edit_requires_paid_plan`), while Kenso enforces its link edit rules (DEV-3690).
|
|
28227
28384
|
|
|
28228
28385
|
- API: `PATCH /v1/tracking-links/{trackingLinkId}`
|
|
28229
28386
|
- Generated from the API contract
|
|
@@ -28564,7 +28721,7 @@ kenso triggers update --trigger-id <trigger-id> --data @body.json
|
|
|
28564
28721
|
|
|
28565
28722
|
Reserve one support-agent turn against the per-user and per-workspace monthly quotas.
|
|
28566
28723
|
|
|
28567
|
-
Replaces `POST /v1/support-chat/turns`. A quota refusal is `429` and includes the legacy `quotaResetAt`. Requires `
|
|
28724
|
+
Replaces `POST /v1/support-chat/turns`. A quota refusal is `429` and includes the legacy `quotaResetAt`. Requires the `ask` permission.
|
|
28568
28725
|
|
|
28569
28726
|
- API: `POST /v1/support/turns`
|
|
28570
28727
|
- Generated from the API contract
|
|
@@ -28883,7 +29040,7 @@ kenso video-provider-connections verify --connection-id <connection-id>
|
|
|
28883
29040
|
|
|
28884
29041
|
Upgrade to a WebSocket and relay PCM16 audio to Deepgram Nova 3.
|
|
28885
29042
|
|
|
28886
|
-
Replaces `GET /v1/support-chat/voice`. Browser sockets cannot set headers, so they pass a `ticket` from `POST /v1/support/voice/tickets`. Until the browser moves to tickets, `access_token`, `ken_version=1.1`, and `workspace_id` still work. Requires `
|
|
29043
|
+
Replaces `GET /v1/support-chat/voice`. Browser sockets cannot set headers, so they pass a `ticket` from `POST /v1/support/voice/tickets`. Until the browser moves to tickets, `access_token`, `ken_version=1.1`, and `workspace_id` still work. Requires the `ask` permission.
|
|
28887
29044
|
|
|
28888
29045
|
- API: `GET /v1/support/voice`
|
|
28889
29046
|
- Generated from the API contract
|
|
@@ -28951,7 +29108,7 @@ kenso voice-notes audio --voice-note-id <voice-note-id>
|
|
|
28951
29108
|
|
|
28952
29109
|
Mint a single-use ticket that opens the voice WebSocket.
|
|
28953
29110
|
|
|
28954
|
-
A browser socket cannot send headers, so it opens `GET /v1/support/voice?ticket=` instead of putting the dashboard token in the URL. The ticket carries this request's `Authorization`, workspace and version, opens one socket and expires after 60 seconds. No MCP tool: only a browser socket uses it. Requires `
|
|
29111
|
+
A browser socket cannot send headers, so it opens `GET /v1/support/voice?ticket=` instead of putting the dashboard token in the URL. The ticket carries this request's `Authorization`, workspace and version, opens one socket and expires after 60 seconds. No MCP tool: only a browser socket uses it. Requires the `ask` permission.
|
|
28955
29112
|
|
|
28956
29113
|
- API: `POST /v1/support/voice/tickets`
|
|
28957
29114
|
- Generated from the API contract
|
|
@@ -31380,7 +31537,7 @@ kenso workspaces clear-reply-to --workspace-id <workspace-id>
|
|
|
31380
31537
|
|
|
31381
31538
|
Create a workspace for the caller.
|
|
31382
31539
|
|
|
31383
|
-
Replaces `POST /v1/workspaces/setup`. Idempotent: an existing workspace is returned with 200. A new workspace is 201.
|
|
31540
|
+
Replaces `POST /v1/workspaces/setup`. Idempotent: an existing workspace is returned with 200. A new workspace is 201. Open to any signed-in caller because first-workspace setup is not limited to existing admins. An API key with the staff-issued scope `workspaces:provision` (a service key, DEV-1555) gets a new workspace on every call instead, with Free billing and the Kenso team as admins, and the key's owner becomes its admin. Not idempotent for such a key. The key reaches only the workspaces it is a member of. A caller who holds no workspace and signed in with a personal, relay, agent or disposable address gets 403 `work_email_required` (DEV-7602), unless the caller is staff, signed in with LinkedIn or AgentID, or through an Auth0 organization (an accepted invitation). The rule does not apply to an API key.
|
|
31384
31541
|
|
|
31385
31542
|
- API: `POST /v1/workspaces`
|
|
31386
31543
|
- Generated from the API contract
|
|
@@ -31480,7 +31637,7 @@ kenso workspaces delete-wordmark --workspace-id <workspace-id>
|
|
|
31480
31637
|
|
|
31481
31638
|
Return one workspace.
|
|
31482
31639
|
|
|
31483
|
-
Replaces `GET /v1/clients/{id}` and `GET /v1/workspaces/{id}/company`. Non-members receive 403.
|
|
31640
|
+
Replaces `GET /v1/clients/{id}` and `GET /v1/workspaces/{id}/company`. Non-members receive 403. Open to any workspace member.
|
|
31484
31641
|
|
|
31485
31642
|
- API: `GET /v1/workspaces/{workspaceId}`
|
|
31486
31643
|
- Generated from the API contract
|
|
@@ -31516,7 +31673,7 @@ kenso workspaces get-tracking --workspace-id <workspace-id>
|
|
|
31516
31673
|
|
|
31517
31674
|
List the caller's workspaces.
|
|
31518
31675
|
|
|
31519
|
-
Replaces `GET /v1/workspaces/me`, `GET /v1/workspaces/search`, and `GET /v1/clients` for the caller's own memberships. Ordered by id. `q` matches the workspace name.
|
|
31676
|
+
Replaces `GET /v1/workspaces/me`, `GET /v1/workspaces/search`, and `GET /v1/clients` for the caller's own memberships. Ordered by id. `q` matches the workspace name. Open to any signed-in caller.
|
|
31520
31677
|
|
|
31521
31678
|
- API: `GET /v1/workspaces` (a list: `--limit`, `--cursor`, `--all`)
|
|
31522
31679
|
- Generated from the API contract
|