LinkedIn job searches
The LinkedIn job searches endpoints of the Kenso API.
Search LinkedIn jobs
/v1/linkedin-job-searcheslinkedin-job-searches.createNeeds the linkedin_job_search feature on your workspace. Until it is on, calls answer 404.
Runs one search. With your own connected LinkedIn seat it reads LinkedIn there, free (via: seat), and pages with nextCursor. Without a seat that can read now (none, paused, LinkedIn throttling it or reporting it unavailable) it uses LinkedIn data Kenso collects in the same call (via: social_data), charged about 0.225 credits a delivered row (about 6 credits per 25 rows), with no next cursor; with that collection off it answers ken-jobs rows only (via: ken_jobs_only). ken-jobs rows are merged after the LinkedIn rows on a first page. Answers 201 when done, or 202 with status: running while Kenso is still collecting: read it with linkedin-job-searches.get. The same search within 24 hours answers from the cache, with no read and creditsCharged 0. While the first is still running, a repeat waits on that search instead of starting another, and the rows are charged once. Errors: 400 validation_failed (also a location LinkedIn does not know), 402 insufficient_credits (collected LinkedIn data path only), 409 linkedin_seat_required (a seat cursor, or companies that are all LinkedIn company ids, when no seat can read), 429 rate_limited (your seat is pacing its reads: wait Retry-After, never a paid fallback) or quota_exceeded (25 searches a day per workspace), 503 when LinkedIn did not answer. Needs Search edit.
Parameters
YYYY-MM-DD form. 1.1 is another name for the first dated version. Leave it out to use your API key's pinned version. Keys created in the Kenso app are pinned to the newest version; keys minted by the CLI login are not. A key with no pinned version and no header gets the legacy shape where the path has one, and 404 where the path exists only in this version. A date that is not a version answers 400 unsupported_version; any other value that is not a version is treated as legacy.400 workspace_required. A workspace you are not a member of answers 404 not_found.Request body
application/json, optional.
sdr, account executive.Germany, Berlin, San Francisco Bay Area.past_day, past_week or past_month.on_site, remote, hybrid.internship, entry_level, associate, mid_senior_level, director, executive.nextCursor of an earlier seat search with the same filters.Response 201
Also answers 202. data is a LinkedInJobSearch.
ljs_ and 32 hex digits. Kept for 24 hours.completed, running (Kenso is still collecting the LinkedIn data: read it again with get) or failed (the collection failed; rows hold the ken-jobs rows and nothing was charged).seat (your own LinkedIn seat, free), social_data (LinkedIn data Kenso collects, charged per delivered row) or ken_jobs_only.cursor with the same filters.curl -X POST "https://api.ken.so/v1/linkedin-job-searches" \
-H "Authorization: Bearer $KEN_API_KEY" \
-H "Ken-Version: 1.1" \
-H "X-Ken-Workspace-Id: $KEN_WORKSPACE_ID" \
-H "Content-Type: application/json" \
-d '{
"keywords": "string",
"location": "string",
"companies": [
"string"
],
"datePosted": "string",
"workplaceType": [
"string"
],
"seniority": [
"string"
],
"limit": 1,
"cursor": "eyJpZCI6ODE1fQ"
}'{
"success": true,
"data": {
"id": "string",
"status": "string",
"via": "string",
"rows": [
{
"source": "string",
"id": "string",
"title": "string",
"company": {
"name": "string",
"linkedinUrl": "https://example.com",
"domain": "example.com"
},
"location": "string",
"postedAt": "2026-09-23T15:02:11Z",
"url": "https://example.com",
"easyApply": true,
"fewApplicants": true,
"applicants": 1,
"description": "string"
}
],
"nextCursor": "eyJpZCI6ODE1fQ",
"creditsCharged": 0.5,
"createdAt": "2026-09-23T15:02:11Z"
}
}Get a LinkedIn job search
/v1/linkedin-job-searches/{linkedInJobSearchId}linkedin-job-searches.getNeeds the linkedin_job_search feature on your workspace. Until it is on, calls answer 404.
One search of this workspace, kept 24 hours. While status is running each read checks the collection once and answers 202; when it is ready the rows are merged in, charged once, and it answers 200 completed. Another workspace's id, or an expired one, is 404 not_found.
Parameters
YYYY-MM-DD form. 1.1 is another name for the first dated version. Leave it out to use your API key's pinned version. Keys created in the Kenso app are pinned to the newest version; keys minted by the CLI login are not. A key with no pinned version and no header gets the legacy shape where the path has one, and 404 where the path exists only in this version. A date that is not a version answers 400 unsupported_version; any other value that is not a version is treated as legacy.400 workspace_required. A workspace you are not a member of answers 404 not_found.Response 200
Also answers 202. data is a LinkedInJobSearch.
ljs_ and 32 hex digits. Kept for 24 hours.completed, running (Kenso is still collecting the LinkedIn data: read it again with get) or failed (the collection failed; rows hold the ken-jobs rows and nothing was charged).seat (your own LinkedIn seat, free), social_data (LinkedIn data Kenso collects, charged per delivered row) or ken_jobs_only.cursor with the same filters.curl -X GET "https://api.ken.so/v1/linkedin-job-searches/string" \ -H "Authorization: Bearer $KEN_API_KEY" \ -H "Ken-Version: 1.1" \ -H "X-Ken-Workspace-Id: $KEN_WORKSPACE_ID"
{
"success": true,
"data": {
"id": "string",
"status": "string",
"via": "string",
"rows": [
{
"source": "string",
"id": "string",
"title": "string",
"company": {
"name": "string",
"linkedinUrl": "https://example.com",
"domain": "example.com"
},
"location": "string",
"postedAt": "2026-09-23T15:02:11Z",
"url": "https://example.com",
"easyApply": true,
"fewApplicants": true,
"applicants": 1,
"description": "string"
}
],
"nextCursor": "eyJpZCI6ODE1fQ",
"creditsCharged": 0.5,
"createdAt": "2026-09-23T15:02:11Z"
}
}