Search
Search Kenso's people and company index, look up profiles, read facets and filters, and import people into a campaign.
Returns ken-search's people page. Each person also carries hasKenEmail: true when Kenso already holds a verified email for the person's LinkedIn profile, so importing them costs no email find on a paid plan. kenEmailStatus labels the best address Kenso holds: none, risky, catch_all or verified. It labels only: no filter, no sort, and no address in the answer. Lookalikes (needs the workspace's lookalikes feature, else 403 feature_disabled): companyLookalike finds people at companies like the seeds ({seeds: [{companyId} | {domain} | {linkedInUrl} | {text}], negatives, mode: precise | broad, minGrade: 1-5, excludeDomains, includeNonB2b}, 1-100 seeds); lookalike finds people like seed people ({seeds: [{personId} | {linkedInUrl}], negatives, mode, minGrade, includeSeedCompanies}, 1-50 seeds). Not both (400 lookalike_conflict). Kenso adds the workspace's do-not-contact and customer domains to excludeDomains. minGrade is a whole number from 1 to 5 (default 2): precise mode drops rows graded below it, broad mode keeps every row. Rows then sort by similarity, each carries lookalike: {score, grade} (score 0-100, grade 1-5 with 5 best), and the page carries lookalikeSeeds: {resolved, unresolved}. Errors: 400 lookalikes_unavailable, too_many_seeds, invalid_lookalike (also a minGrade that is not 1-5, such as a letter); 422 no_usable_seeds with lookalikeSeeds. A lookalike search is a snapshot: stored searches refuse it (400 lookalike_not_storable). view: full (the default) returns each person's whole profile; summary keeps only the fields a list row needs (names, headline, LinkedIn URL, photo, current title, company and its size and funding, location, seniority, function, the job-change signals, hasKenEmail, kenEmailStatus, lookalike), 1-2 KB a person instead of 17-28 KB. Get the full record with get-person. Any other value is 400 validation_failed.
Parameters
400 workspace_required).Response 200
data is a object.
curl -X POST "https://api.ken.so/v1/search/people" \ -H "Authorization: Bearer $KEN_API_KEY" \ -H "Ken-Version: 2026-11-02" \ -H "X-Ken-Workspace-Id: $KEN_WORKSPACE_ID"
{
"success": true,
"data": null
}Get one person by index id
/v1/search/people/{personId}search.get-personThe person carries hasKenEmail and kenEmailStatus, as in people search.
Parameters
400 workspace_required).Response 200
data is a object.
curl -X GET "https://api.ken.so/v1/search/people/812" \ -H "Authorization: Bearer $KEN_API_KEY" \ -H "Ken-Version: 2026-11-02" \ -H "X-Ken-Workspace-Id: $KEN_WORKSPACE_ID"
{
"success": true,
"data": null
}Look up a person by LinkedIn profile URL
/v1/search/people/lookupsearch.lookup-personThe person carries hasKenEmail and kenEmailStatus, as in people search.
Parameters
400 workspace_required).Response 200
data is a object.
curl -X GET "https://api.ken.so/v1/search/people/lookup" \ -H "Authorization: Bearer $KEN_API_KEY" \ -H "Ken-Version: 2026-11-02" \ -H "X-Ken-Workspace-Id: $KEN_WORKSPACE_ID"
{
"success": true,
"data": null
}Get facet counts for a people search
/v1/search/people/facetssearch.get-people-facetsParameters
400 workspace_required).Response 200
data is a object.
curl -X POST "https://api.ken.so/v1/search/people/facets" \ -H "Authorization: Bearer $KEN_API_KEY" \ -H "Ken-Version: 2026-11-02" \ -H "X-Ken-Workspace-Id: $KEN_WORKSPACE_ID"
{
"success": true,
"data": null
}The upstream path remains accounts.
Lookalikes (needs the workspace's lookalikes feature, else 403 feature_disabled): send lookalike: {seeds: [{companyId} | {domain} | {linkedInUrl} | {text}], negatives: [{companyId} | {domain} | {linkedInUrl}], mode: precise | broad, minGrade: 1-5, excludeDomains: [...], includeNonB2b}, 1-100 seeds and 0-100 negatives, a text seed up to 4,000 characters. Kenso adds the workspace's do-not-contact and customer domains to excludeDomains (10,000 at most, yours first). Rows then sort by similarity (sortBy is ignored, at most 2,000 results through the usual paging), each carries lookalike: {score, grade} (score 0-100, grade 1-5 with 5 best), and the page carries lookalikeSeeds: {resolved, unresolved}. minGrade is a whole number from 1 to 5 (default 2): precise mode drops rows graded below it, broad mode keeps every row. Errors: 400 lookalikes_unavailable, too_many_seeds, invalid_lookalike (also a minGrade that is not 1-5); 422 no_usable_seeds with lookalikeSeeds. A lookalike search is a snapshot: stored searches refuse it (400 lookalike_not_storable), so save or import its results as a selection of ids.
Parameters
400 workspace_required).Response 200
data is a object.
curl -X POST "https://api.ken.so/v1/search/companies" \ -H "Authorization: Bearer $KEN_API_KEY" \ -H "Ken-Version: 2026-11-02" \ -H "X-Ken-Workspace-Id: $KEN_WORKSPACE_ID"
{
"success": true,
"data": null
}Get one company by index id
/v1/search/companies/{companyId}search.get-companyParameters
400 workspace_required).Response 200
data is a object.
curl -X GET "https://api.ken.so/v1/search/companies/812" \ -H "Authorization: Bearer $KEN_API_KEY" \ -H "Ken-Version: 2026-11-02" \ -H "X-Ken-Workspace-Id: $KEN_WORKSPACE_ID"
{
"success": true,
"data": null
}Look up a company by LinkedIn company URL
/v1/search/companies/lookupsearch.lookup-companyParameters
400 workspace_required).Response 200
data is a object.
curl -X GET "https://api.ken.so/v1/search/companies/lookup" \ -H "Authorization: Bearer $KEN_API_KEY" \ -H "Ken-Version: 2026-11-02" \ -H "X-Ken-Workspace-Id: $KEN_WORKSPACE_ID"
{
"success": true,
"data": null
}Get facet counts for a company search
/v1/search/companies/facetssearch.get-company-facetsParameters
400 workspace_required).Response 200
data is a object.
curl -X POST "https://api.ken.so/v1/search/companies/facets" \ -H "Authorization: Bearer $KEN_API_KEY" \ -H "Ken-Version: 2026-11-02" \ -H "X-Ken-Workspace-Id: $KEN_WORKSPACE_ID"
{
"success": true,
"data": null
}Parameters
400 workspace_required).Response 200
data is a object.
curl -X GET "https://api.ken.so/v1/search/filters" \ -H "Authorization: Bearer $KEN_API_KEY" \ -H "Ken-Version: 2026-11-02" \ -H "X-Ken-Workspace-Id: $KEN_WORKSPACE_ID"
{
"success": true,
"data": null
}Get the filter metadata catalog, or one category's values
/v1/search/metadatasearch.get-metadataWithout category this returns the whole catalog as one resource. With category it returns a list of that category's values: q filters them, limit (1-100, default 50) and cursor page them, and includeTotal=true adds pagination.totalCount. A cursor that did not come from pagination.nextCursor is 400 validation_failed.
Parameters
industries. Without it the whole catalog is returned.category.category.pagination.nextCursor of the previous page.pagination.totalCount, the number of values in the category that match q.400 workspace_required).Response 200
data is a object.
curl -X GET "https://api.ken.so/v1/search/metadata" \ -H "Authorization: Bearer $KEN_API_KEY" \ -H "Ken-Version: 2026-11-02" \ -H "X-Ken-Workspace-Id: $KEN_WORKSPACE_ID"
{
"success": true,
"data": null
}Search people who work at the given companies
/v1/search/companies/peoplesearch.search-company-peopleBody: a people search plus companyIds, the company index ids to search in. Returns ken-search's people page; each person carries hasKenEmail and kenEmailStatus, as in people search. Takes companyLookalike and lookalike exactly as people search does, behind the same lookalikes feature.
Parameters
400 workspace_required).Response 200
data is a object.
curl -X POST "https://api.ken.so/v1/search/companies/people" \ -H "Authorization: Bearer $KEN_API_KEY" \ -H "Ken-Version: 2026-11-02" \ -H "X-Ken-Workspace-Id: $KEN_WORKSPACE_ID"
{
"success": true,
"data": null
}List companies whose headcount grew
/v1/search/headcount-changessearch.list-headcount-changesFilters: month (yyyy-MM, detection month; all months, newest first, without it) and minGrowthPct. limit (1-100, default 50) and cursor page the list.
Parameters
yyyy-MM. Without it every month is returned, most recent first.20 for 20%.pagination.nextCursor of the previous page.400 workspace_required).Response 200
data is a list of object. Each item has these fields. The response also carries pagination.
curl -X GET "https://api.ken.so/v1/search/headcount-changes" \ -H "Authorization: Bearer $KEN_API_KEY" \ -H "Ken-Version: 2026-11-02" \ -H "X-Ken-Workspace-Id: $KEN_WORKSPACE_ID"
{
"success": true,
"data": [],
"pagination": {
"nextCursor": "eyJpZCI6ODE1fQ",
"hasMore": true,
"totalCount": 1
}
}Expand job titles into related titles
/v1/search/people/expand-titlessearch.expand-titlesThe body is ken-search's title expansion request and is forwarded as is. Each expansion is a model call: the same body in the same workspace is answered from the last hour's result, and anything else takes one unit of the workspace's aiSearchExpand quota (20 a minute, 500 a day, shared with industry expansion, every caller kind). Past it, 429 quota_exceeded with Retry-After.
Parameters
400 workspace_required).Response 200
data is a object.
curl -X POST "https://api.ken.so/v1/search/people/expand-titles" \ -H "Authorization: Bearer $KEN_API_KEY" \ -H "Ken-Version: 2026-11-02" \ -H "X-Ken-Workspace-Id: $KEN_WORKSPACE_ID"
{
"success": true,
"data": null
}Expand industries into related industries
/v1/search/metadata/expand-industriessearch.expand-industriesThe body is ken-search's industry expansion request (up to 50 industries) and is forwarded as is. Cached and metered like title expansion, on the same aiSearchExpand quota.
Parameters
400 workspace_required).Response 200
data is a object.
curl -X POST "https://api.ken.so/v1/search/metadata/expand-industries" \ -H "Authorization: Bearer $KEN_API_KEY" \ -H "Ken-Version: 2026-11-02" \ -H "X-Ken-Workspace-Id: $KEN_WORKSPACE_ID"
{
"success": true,
"data": null
}List seed suggestions for a lookalike search
/v1/search/lookalike-seedssearch.list-lookalike-seedsNeeds the lookalikes feature on your workspace. Until it is on, calls answer 404.
source (required): customers (the workspace's customer accounts, count 1 per account), crm (companies on CRM deals: opportunities and synced CRM deals, count is deals), interested (companies whose people replied Interested, count is distinct contacts), replies (companies whose people sent any real reply: every class but Automated, HardBounce, SoftBounce, OutOfOffice and NDR, count is distinct contacts), campaign (companies of one campaign's live leads, count is contacts) or website_visitors (companies behind human visits to the workspace's tracked website, count is visits). crm_won is still accepted as crm with stage=won. stage (crm only): won (default), open (neither won nor lost) or any. campaignId: required with campaign, an optional filter with interested and replies; it also needs Campaigns view (403 permission_denied without it), and a campaign outside the workspace, or deleted, is 404 not_found. since (interested, replies, website_visitors): a YYYY-MM-DD day (UTC); only replies or visits on or after it count. A parameter the source does not take is 400 validation_failed. Replies, campaign leads and visits are read newest first, at most 20,000, then grouped by company domain (the contact's company domain, else the address's domain); a free mail domain never becomes a seed. Each row is {domain, name, count}. Up to 200 rows, ordered by count descending then domain, in one page. An empty list is normal. Free. Needs the workspace's lookalikes feature (404 while it is off), and Accounts view on top of the controller's Search view: the rows are the workspace's customers, deals, replies, leads and visitors, which the accounts, opportunities and CRM routes keep behind Accounts view.
Parameters
customers, crm, interested, replies, campaign or website_visitors. crm_won is still accepted, as crm with stage=won.crm only: won (default), open (neither won nor lost) or any.campaign; an optional filter with interested and replies.interested, replies and website_visitors: a day as YYYY-MM-DD (UTC); only replies or visits on or after it count.400 workspace_required).Response 200
data is a list of LookalikeSeedModel. Each item has these fields. The response also carries pagination.
acme.com. Send it as a {"domain": ...} seed.crm, crm_won), distinct Interested contacts (interested), distinct replying contacts (replies), the campaign's contacts at the company (campaign), visits (website_visitors), or customer accounts with the domain, normally 1 (customers).curl -X GET "https://api.ken.so/v1/search/lookalike-seeds" \ -H "Authorization: Bearer $KEN_API_KEY" \ -H "Ken-Version: 2026-11-02" \ -H "X-Ken-Workspace-Id: $KEN_WORKSPACE_ID"
{
"success": true,
"data": [
{
"domain": "example.com",
"name": "string",
"count": 1
}
],
"pagination": {
"nextCursor": "eyJpZCI6ODE1fQ",
"hasMore": true,
"totalCount": 1
}
}List a campaign's most recent import
/v1/search/importssearch.list-importscampaignId is required. Returns the campaign's latest import as a list of zero or one item; there is never a next page. A campaign outside the workspace is 404 not_found.
Parameters
400 workspace_required).Response 200
data is a list of object. Each item has these fields. The response also carries pagination.
curl -X GET "https://api.ken.so/v1/search/imports" \ -H "Authorization: Bearer $KEN_API_KEY" \ -H "Ken-Version: 2026-11-02" \ -H "X-Ken-Workspace-Id: $KEN_WORKSPACE_ID"
{
"success": true,
"data": [],
"pagination": {
"nextCursor": "eyJpZCI6ODE1fQ",
"hasMore": true,
"totalCount": 1
}
}Import Search people into a campaign
/v1/search/importssearch.create-importBody: campaignId plus exactly one of personIds (the people to import) or searchFilters (a people search; every match is imported, up to limit). Returns 202 with the import job, { jobId, status }; poll GET /v1/search/imports/{importId}. A campaign outside the workspace is 404 not_found. Needs a member role or higher, and the Search page (the import runs a Search query); reading an import's status needs only Campaigns view.
Parameters
400 workspace_required).Request body
application/json, optional.
POST /v1/search/people. Imports every match, up to limit.searchFilters import adds.Response 202
data is a object.
curl -X POST "https://api.ken.so/v1/search/imports" \
-H "Authorization: Bearer $KEN_API_KEY" \
-H "Ken-Version: 2026-11-02" \
-H "X-Ken-Workspace-Id: $KEN_WORKSPACE_ID" \
-H "Content-Type: application/json" \
-d '{
"campaignId": 812,
"personIds": [
812
],
"searchFilters": null,
"limit": 1
}'{
"success": true,
"data": null
}Preview a Search import: how many of its people Kenso already holds an email for
/v1/search/imports/previewsearch.preview-importBody: the selection a create would send, without campaignId: exactly one of personIds or searchFilters (with limit, 5,000 when absent). Returns { personCount, checkedCount, kenEmailCount }: the people the import would take, the people checked (the first 500 Search returns, in import order) and how many of those Kenso already holds a verified email for. On a paid plan an address Kenso already holds costs no email find. Imports nothing and counts no Search quota. Needs Campaigns view and the Search page.
Parameters
400 workspace_required).Request body
application/json, optional.
POST /v1/search/imports. Previews its matches up to limit.searchFilters import would add (5,000 when absent).Response 200
data is a SearchImportPreview.
personIds (at most 5,000, the import's cap for picks), or the filter's matches up to limit (5,000 when absent).curl -X POST "https://api.ken.so/v1/search/imports/preview" \
-H "Authorization: Bearer $KEN_API_KEY" \
-H "Ken-Version: 2026-11-02" \
-H "X-Ken-Workspace-Id: $KEN_WORKSPACE_ID" \
-H "Content-Type: application/json" \
-d '{
"personIds": [
812
],
"searchFilters": null,
"limit": 1
}'{
"success": true,
"data": {
"personCount": 1,
"checkedCount": 1,
"kenEmailCount": 1
}
}Returns ken-search's import status. ken-search is always asked for the resolved workspace and answers 404 not_found for an import from another workspace.
Parameters
400 workspace_required).Response 200
data is a object.
curl -X GET "https://api.ken.so/v1/search/imports/812" \ -H "Authorization: Bearer $KEN_API_KEY" \ -H "Ken-Version: 2026-11-02" \ -H "X-Ken-Workspace-Id: $KEN_WORKSPACE_ID"
{
"success": true,
"data": null
}Answers at once and never waits for a build. status: ready (the sample; refreshing true while a rebuild runs because the ICP changed or the sample expired), pending (nothing cached yet and a build is queued or running; poll again in about 5 seconds), unavailable (no ICP context yet, or the last build for this ICP failed: retried after 10 minutes when the model or a search was down, after 6 hours when it found nothing; also when the workspace ran its 6 builds of the day with no sample to serve) or off (the search_sample flag is off; nothing runs). A ready sample holds query (the filters it searched) and the tabs profiles and companies ({ request, page }, page as POST /v1/search/people and /companies answer), jobs ({ request: { jobFilters, peopleFilters }, companies, people }, as /v1/job-post-searches answers) and funding ({ request: { signalType, parameters }, page }, as POST /v1/triggers/preview answers). A tab is absent when its search failed or found nothing. The sample is cached for 7 days (10 minutes when a tab failed on an outage) and rebuilt, at most 6 times a day, when the website, the company context or the ICP Knowledge file changes. Requires Search view.
Parameters
400 workspace_required).Response 200
data is a SearchSampleResource.
curl -X GET "https://api.ken.so/v1/search/sample" \ -H "Authorization: Bearer $KEN_API_KEY" \ -H "Ken-Version: 2026-11-02" \ -H "X-Ken-Workspace-Id: $KEN_WORKSPACE_ID"
{
"success": true,
"data": {
"status": "string",
"refreshing": true,
"generatedAt": "2026-09-23T15:02:11Z",
"expiresAt": "2026-09-23T15:02:11Z",
"query": {
"titles": [
"string"
],
"seniorityLevels": [
"string"
],
"industries": [
"string"
],
"headcountMin": 1,
"headcountMax": 1,
"countries": [
"string"
],
"hiringTitles": [
"string"
],
"fundingMinRaisedUsd": 1,
"fundingRaisedWithinDays": 1,
"fundingIndustryGroups": [
"string"
]
},
"profiles": {
"request": null,
"page": null
},
"companies": {
"request": null,
"page": null
},
"jobs": {
"request": null,
"companies": null,
"people": null
},
"funding": {
"request": null,
"page": null
}
}
}