---
title: "Sales Navigator Search — leads (people) & accounts (companies)"
method: POST
path: "/search/linkedin/sales-nav"
tags: ["salesNav"]
---

# Sales Navigator Search — leads (people) & accounts (companies)

`POST /search/linkedin/sales-nav`

# Sales Navigator Search

Search LinkedIn Sales Navigator for leads (people) or accounts (companies). Requires a LinkedIn account with an active Sales Navigator subscription.

## Two ways to search
1. **Structured**: pass `category` + optional `keywords` + filters
2. **URL-based**: pass a Sales Navigator search `url` from your browser — filters are extracted automatically

### Accepted `url` shapes
Sales Navigator is a SPA and writes its filter state into the **hash fragment** (`#query=...`), not the search string. The parser accepts both, plus several common paste artefacts:
- `https://www.linkedin.com/sales/search/people#query=(...)&sessionId=...` — what the browser address bar shows (most common)
- `https://www.linkedin.com/sales/search/people?query=(...)` — older / shared-link form
- `/sales/search/lead` and `/sales/search/account` path aliases (LinkedIn uses both)
- Protocol-less paste (`www.linkedin.com/sales/search/people#query=...`)
- Surrounding whitespace, quotes/backticks, `&amp;` from rich-text paste

**Rejected with a clear 400** so you don't get unfiltered results:
- Saved-list URLs (`/sales/lists/people/...`) — these aren't searches; open the list and click "Search" to get a `/sales/search/...` URL
- URLs with no query (`?sessionId=...` only) — copy the URL again **after** filters finish loading
- URLs whose query has no keywords and no filters (`#query=(spellCorrectionEnabled:true)`) — same fix

## Sales Navigator vs Classic search
Sales Navigator returns richer data than classic LinkedIn search:
- **People**: tenure at company/role, premium status, open profile flag, pending invitation status, detailed positions
- **Companies**: headcount (employee count)
- More advanced filters: seniority, function, tenure, include/exclude for company & industry

## Resolving filter IDs
Filters like location, industry, company, and school require LinkedIn numeric IDs. Use `GET /search/linkedin/parameters` to convert text (e.g. "San Francisco") into IDs.

## Pagination
Default page size: 25, max: 25. Use `start` (offset) and `count` to paginate. Check `hasMore` and `paging.total` in the response. When passing `url`, a `?page=N` (or `#…&page=N`) in the URL is honored — explicit `start` still wins if both are provided.

## Credits


## Profile URLs returned
Each item carries `profileUrl` (public `/in/...`) and `salesNavUrl` (`/sales/...`).
Sales Navigator does not return canonical vanity slugs (e.g. `/in/john-doe`) — it returns LinkedIn's encrypted profile id, so `profileUrl` is `https://www.linkedin.com/in/<encrypted-id>` (e.g. `/in/ACwAAA0-26UB...`). These URLs are clickable and redirect to the canonical vanity URL when opened in a browser, and they are accepted anywhere our API takes a profile URL (visit, connect, message, etc.).

### Upgrading to canonical vanity URLs (optional)
To resolve `/in/<encrypted-id>` → `/in/<vanity-slug>` (e.g. `/in/john-doe`), call `POST /resolve/linkedin/profiles` with the URLs, URNs, or raw encrypted ids. The endpoint returns `publicIdentifier` + a canonical `profileUrl`, and returns `publicIdentifier` + a canonical `profileUrl`.

```json
POST /resolve/linkedin/profiles
{
  "inputs": [
    "https://www.linkedin.com/in/ACwAAA0-26UBSvneYv1dZ1sfAT_NZHjmOb5qk2s",
    "urn:li:fsd_profile:ACwAAAaK0QIBxcI7cceYW8eas-3uVGwgOTW8s_k"
  ]
}
```

## Request body

- object
  - `category` 'people' | 'companies' — Type of Sales Navigator search: 'people' (leads) or 'companies' (accounts). Required unless url is provided.
  - `url` string — Sales Navigator search URL — paste directly from your browser. Category and filters are extracted automatically. Explicit params override URL-derived values. Example: https://www.linkedin.com/sales/search/people?query=...
  - `keywords` string — Search keywords. Supports LinkedIn Boolean syntax: use double quotes for exact phrases, AND/OR/NOT operators (UPPERCASE), and parentheses for grouping.
  - `title` string — Job title keywords (people only). Supports Boolean OR: 'CEO OR CTO OR Founder'.
  - `company` object — Current-employer filter (people only). Accepts company names ('Stripe', 'Datadog') OR LinkedIn numeric ids. Server resolves names via typeahead.
    - `include` string[] — Labels OR numeric IDs to include. Labels are resolved server-side (no need to call /parameters first).
    - `exclude` string[] — Labels OR numeric IDs to exclude. Labels are resolved server-side (no need to call /parameters first).
  - `industry` object — Industry filter. Accepts industry names ('Software Development', 'Hospitals and Health Care') OR LinkedIn numeric ids. Server resolves.
    - `include` string[] — Labels OR numeric IDs to include. Labels are resolved server-side (no need to call /parameters first).
    - `exclude` string[] — Labels OR numeric IDs to exclude. Labels are resolved server-side (no need to call /parameters first).
  - `location` string[] — Geography filter (people & companies). Accepts location names ('France', 'San Francisco Bay Area', 'EMEA') OR LinkedIn geo ids. Server resolves via typeahead.
  - `locationExclude` string[] — Geography filter to EXCLUDE. Same accepted shapes as `location`. Useful for 'all of Europe except Switzerland' patterns.
  - `seniority` string[] — Seniority levels (people only). Accepts labels ('CXO', 'VP', 'Director', 'Owner / Partner', 'Senior', 'Entry Level', etc.) OR LinkedIn numeric ids. Server resolves labels to LinkedIn's 3-digit ids (CXO=310, etc.) — do NOT guess the ids.
  - `function` string[] — Job function (people only). Accepts function names ('Sales', 'Engineering', 'Marketing', 'Finance', etc. — 26 canonical) OR LinkedIn numeric ids.
  - `tenure` object[] — Years at current company (people only). Array of ranges, e.g. [{min:3}, {max:10}].
    - `min` integer — Minimum years
    - `max` integer — Maximum years
  - `profileLanguage` string[] — Profile language (people only). Accepts ISO 639-1 codes (e.g. 'en') or full language names; the server resolves either.
  - `connectionDegree` string[] — Network distance: 'F' (1st-degree), 'S' (2nd-degree), 'O' (3rd-degree and beyond), or 'GROUP'. The labels '1st degree', '2nd degree', '3rd degree' are also accepted.
  - `school` string[] — School filter (people only). Accepts school names ('Stanford', 'HEC Paris') OR LinkedIn numeric ids. Server resolves via typeahead.
  - `yearsOfExperience` string[] — Overall years of experience (people only). Accepts labels ('Less than 1 year', '1 to 2 years', '3 to 5 years', '6 to 10 years', 'More than 10 years') OR LinkedIn numeric ids 1-5.
  - `persona` string[] — Buyer Persona IDs the user has configured on sales.linkedin.com home (combos of function+seniority+title+geo). Match the IDs from the URL filter ((type:PERSONA,values:List((id:<id>,…)))).
  - `recentlyChangedJobs` boolean — Filter to leads who changed jobs in the last 90 days (LinkedIn buying-intent flag). True = include only job-changers; omit/false = no constraint.
  - `postedOnLinkedin` boolean — Filter to leads who recently posted on LinkedIn (engagement signal — active posters reply more often). True = include only recent posters; omit/false = no constraint.
  - `sharedExperiences` boolean — Filter to leads with shared experience with the searcher (same school / past employer / group). True = include only shared-experience matches; omit/false = no constraint.
  - `viewedYourProfile` boolean — Filter to leads who recently viewed YOUR profile (LinkedIn flag VYP). Highest-intent engagement signal — they already showed interest. Requires Sales Nav seat that captures profile views.
  - `followsYourCompany` boolean — Filter to leads who follow YOUR company page (LinkedIn flag CF). Warm-touch signal — they opted into your brand.
  - `connectionOf` string[] — Filter to leads connected to a specific person. Values are LinkedIn ENCRYPTED member URN ids (e.g. 'ACwAAAim9ZcB…'), not numeric ids. Useful for 'find people connected to my champion at X' warm-intro patterns.
  - `pastCompany` object — Past-employer filter (people only). Accepts company names ('Stripe') OR LinkedIn numeric ids. The server wraps numeric ids as 'urn:li:organization:<id>' (the wire shape Sales Nav requires) — callers can pass the bare id or the URN.
    - `include` string[] — Labels OR numeric IDs to include. Labels are resolved server-side (no need to call /parameters first).
    - `exclude` string[] — Labels OR numeric IDs to exclude. Labels are resolved server-side (no need to call /parameters first).
  - `companyHeadquarters` object — Where the lead's CURRENT employer is HQ'd (people only). Accepts location names ('France', 'United States') OR LinkedIn geo ids. Distinct from `location` which is the lead's own location — useful for 'sell to UK-headquartered companies regardless of where the buyer lives'.
    - `include` string[] — Labels OR numeric IDs to include. Labels are resolved server-side (no need to call /parameters first).
    - `exclude` string[] — Labels OR numeric IDs to exclude. Labels are resolved server-side (no need to call /parameters first).
  - `yearsInCurrentPosition` string[] — Years in current ROLE/POSITION (people only). Same accepted labels as `yearsOfExperience` ('Less than 1 year', '1 to 2 years', etc.). Distinct from `tenure` which counts years at current COMPANY.
  - `pastTitle` string — Past job title keywords (people only). Free-text, supports Boolean OR. Finds leads who previously held a matching title.
  - `firstName` string — First name (people only). Exact name filter.
  - `lastName` string — Last name (people only). Exact name filter.
  - `groups` string[] — LinkedIn Groups membership (people only). Accepts group names ('Digital Marketing') OR numeric group ids. Server resolves names via typeahead.
  - `pastColleague` boolean — Filter to leads who are past colleagues of the searcher (worked at the same company, overlapping dates). True = include only past colleagues; omit/false = no constraint. Warm-intro signal.
  - `leadInteractions` string[] — Filter by your past interaction with the lead (people only). Accepts labels ('Messaged') OR LinkedIn codes.
  - `savedLeadsAndAccounts` string[] — Filter to your saved leads / accounts (people only). Accepts 'All my saved leads' / 'All my saved accounts' OR codes SL/SA.
  - `companyHeadcount` string[] — Employee count (companies only). Accepts labels ('1-10', '11-50', '51-200', '201-500', '501-1,000', '1,001-5,000', '5,001-10,000', '10,001+', 'Self-employed') OR LinkedIn letter codes A-I.
  - `companyType` string[] — Company type (companies only). Accepts labels ('Public Company', 'Privately Held', 'Non Profit', 'Educational Institution', 'Government Agency', 'Self-Employed', 'Self-Owned', 'Partnership') OR LinkedIn letter codes.
  - `numOfFollowers` string[] — Company follower-count buckets (companies only). Accepts labels ('1-50', '51-100', '101-1,000', '1,001-5,000', '5,001+') OR ids 1-5.
  - `fortune` string[] — Fortune-list membership (companies only). Accepts 'Fortune 50' / 'Fortune 100' / 'Fortune 250' / 'Fortune 500' OR codes FORTUNE_50/100/250/500.
  - `accountActivities` string[] — Account buying-intent signals (companies only). Accepts labels ('Senior leadership changes in last 3 months', 'Funding events in past 12 months') OR codes SLC/RFE.
  - `jobOpportunities` string[] — Account hiring signals (companies only). Accepts the LinkedIn hiring-signal labels OR codes.
  - `start` integer — Pagination offset (default 0).
  - `count` integer — Results per page (default 25, max 25).
  - `campaignSlug` string — Campaign ID. Auto-adds discovered contacts to this campaign in background. Mandatory whenever a campaign is active.

## Response `200`

Search results from Sales Navigator

- union
  - object
    - `success` true, required
    - `category` 'people', required
    - `items` object[], required
      - `type` 'PEOPLE', required
      - `id` string, required — Sales Navigator lead ID
      - `name` string, required
      - `firstName` string, nullable, required
      - `lastName` string, nullable, required
      - `memberUrn` string, nullable, required — LinkedIn member URN (e.g. urn:li:member:12345)
      - `profileUrn` string, nullable, required — Canonical profile URN (urn:li:fsd_profile:ACo...) derived from any ACoA id found in the payload. Null only when LinkedIn returns a bare numeric memberUrn with no ACoA trace.
      - `publicIdentifier` string, nullable, required — LinkedIn vanity URL slug
      - `profileUrl` string, nullable, required — Profile URL. 3-tier fallback: (1) real /in/<slug>, (2) synthesized /in/<encrypted-id> when only a URN is known — LinkedIn accepts both ACoA… and ACwA… encrypted ids as the slug (case-sensitive), (3) /sales/lead/<id> as last resort when neither is available. Tier 3 URLs are not persistable in Bereach — call POST /resolve/linkedin/profiles to upgrade them.
      - `salesNavUrl` string, nullable, required — Sales Navigator lead URL
      - `profilePicture` string, nullable, required
      - `headline` string, nullable, required
      - `location` string, nullable, required
      - `networkDistance` 'DISTANCE_1' | 'DISTANCE_2' | 'DISTANCE_3' | 'OUT_OF_NETWORK', nullable, required — LinkedIn network distance: DISTANCE_1=connected, DISTANCE_2=2nd degree, DISTANCE_3=3rd degree, OUT_OF_NETWORK=not connected.
      - `premium` boolean, nullable, required — True if the person has a LinkedIn Premium account.
      - `openProfile` boolean, nullable, required — True if the person has Open Profile — can be messaged without a connection.
      - `pendingInvitation` boolean, nullable, required — True if you have an outstanding connection invitation to this person.
      - `currentPositions` object[], required — Current work positions for this profile.
        - `company` string, nullable, required
        - `companyId` string, nullable, required
        - `role` string, nullable, required
        - `description` string, nullable, required
        - `location` string, nullable, required
        - `tenureAtCompany` object, nullable, required
          - `years` integer
          - `months` integer
        - `tenureAtRole` object, nullable, required
          - `years` integer
          - `months` integer
    - `paging` object, required
      - `start` integer, required
      - `count` integer, required
      - `total` integer, required
    - `hasMore` boolean, required
    - `warnings` object[] — Caveats about this result set. Absent or empty means the search ran exactly as asked.
      - `field` string, required — Which part of the request this is about, or `search` when it is about the whole result set.
      - `value` string, required — The value involved: what was dropped, or a code naming the condition.
      - `type` string, required — What kind of caveat this is. SEARCH_QUOTA: LinkedIn capped this account for the month, so the set is TRUNCATED and not the whole market. PARSE_EMPTY: the page answered and no rows could be read, and LinkedIn did not say the market is empty, so treat it as unread rather than as nobody matching. URL_FACET: a pasted search URL carried a filter this search cannot apply, so it ran wider than the one on screen. ENUM: a value was not recognised and that filter was dropped. LANE_FALLBACK: some or all rows came from the public lane, which fills fewer fields. AND_BLOB / OR_OVERFLOW: the keyword shape over-constrained and was retried or flagged. SEARCH_PLAN: the ask was spread across a search budget rather than paged.
      - `hint` string — One sentence a caller can show a person.
    - `creditsUsed` integer, required — Credits consumed by this call. 0 for free endpoints, cached results, duplicates, and for every query that does not touch LinkedIn.
    - `retryAfter` integer, required — Seconds to wait before another call of the same type. 0 means no wait is needed.
    - `_meta` object — Credit balance carried on every response so a caller never has to ask for it separately. Absent when the caller has no connected account.
      - `credits` object, required
        - `current` number, required — Credits spent this period.
        - `limit` number, nullable, required — Period allowance, or null when unlimited.
        - `remaining` number, nullable, required — Allowance left, or null when unlimited.
        - `percentage` number, required — Share of the allowance spent, 0 to 100.
        - `isUnlimited` boolean, required
        - `accountPlan` string, required — The credential's plan.
  - object
    - `success` true, required
    - `category` 'companies', required
    - `items` object[], required
      - `type` 'COMPANY', required
      - `name` string, required
      - `profileUrl` string, nullable, required
      - `summary` string, nullable, required
      - `industry` string, nullable, required
      - `location` string, nullable, required
      - `logoUrl` string, nullable — Company logo URL when LinkedIn surfaces it on the result entity. Display this in the company card.
      - `id` string, required — Sales Navigator company ID
      - `headcount` string, nullable, required — Employee count or range
    - `paging` object, required
      - `start` integer, required
      - `count` integer, required
      - `total` integer, required
    - `hasMore` boolean, required
    - `warnings` object[] — Caveats about this result set. Absent or empty means the search ran exactly as asked.
      - `field` string, required — Which part of the request this is about, or `search` when it is about the whole result set.
      - `value` string, required — The value involved: what was dropped, or a code naming the condition.
      - `type` string, required — What kind of caveat this is. SEARCH_QUOTA: LinkedIn capped this account for the month, so the set is TRUNCATED and not the whole market. PARSE_EMPTY: the page answered and no rows could be read, and LinkedIn did not say the market is empty, so treat it as unread rather than as nobody matching. URL_FACET: a pasted search URL carried a filter this search cannot apply, so it ran wider than the one on screen. ENUM: a value was not recognised and that filter was dropped. LANE_FALLBACK: some or all rows came from the public lane, which fills fewer fields. AND_BLOB / OR_OVERFLOW: the keyword shape over-constrained and was retried or flagged. SEARCH_PLAN: the ask was spread across a search budget rather than paged.
      - `hint` string — One sentence a caller can show a person.
    - `creditsUsed` integer, required — Credits consumed by this call. 0 for free endpoints, cached results, duplicates, and for every query that does not touch LinkedIn.
    - `retryAfter` integer, required — Seconds to wait before another call of the same type. 0 means no wait is needed.
    - `_meta` object — Credit balance carried on every response so a caller never has to ask for it separately. Absent when the caller has no connected account.
      - `credits` object, required
        - `current` number, required — Credits spent this period.
        - `limit` number, nullable, required — Period allowance, or null when unlimited.
        - `remaining` number, nullable, required — Allowance left, or null when unlimited.
        - `percentage` number, required — Share of the allowance spent, 0 to 100.
        - `isUnlimited` boolean, required
        - `accountPlan` string, required — The credential's plan.

## Other responses

- `400` — The server cannot or will not process the request due to something that is perceived to be a client error.
- `401` — Although HTTP specifies "unauthorized", this response means "unauthenticated". Authenticate to continue. NOTE: 401 is also returned with code "linkedin_not_connected" when the caller IS authenticated but has no connected LinkedIn account — connect LinkedIn (not re-authenticate) to continue.
- `403` — The client does not have access rights to the content.
- `404` — The server cannot find the requested resource.
- `409` — The request conflicts with the current state of the server.
- `410` — The requested content has been permanently deleted from the server.
- `422` — The request was well-formed but was unable to be followed due to semantic errors.
- `429` — Rate limit exceeded. Read error.retryAfter for the wait time in seconds.
- `500` — The server encountered a situation it does not know how to handle.
- `502` — LinkedIn returned a server error or the proxy connection failed. Retry after a few seconds.
- `503` — Proxy capacity temporarily exceeded. Retry after a few seconds.

---

[API](https://skmtc.net/berea/apis/bereach-api.md) · [All operations](https://skmtc.net/berea/apis/bereach-api/llms.txt) · [OpenAPI document](https://skmtc-service-staging.skmtc.workers.dev/v1/apis/berea/bereach-api/revisions/a1e86af2406d/schema)
