Sales Navigator company search
The same, against an account search. Ceiling 1,000 rows.
https://api.easydata.win/v1/sales/search/companiesThe people search, against a Sales Navigator account-search URL. One entry per page of 100, 50 credits a request, ceiling 1,000 rows.
enrich: true adds 1 per ROW on top of the request: the surcharge is exactly what /companies/enrich charges, which is one credit per company. The base counts requests and the surcharge counts rows, because that is what each of them causes.
A company row carries no location: the account card does not have one, and inventing a headquarters from an industry string would be a guess presented as a fact. Run /companies/enrich on the rows you keep.
Need it in the response?POST https://api.easydata.win/v1/sales/search/companies/sync runs the same operation inside your request and hands back the record, for 100per request - twice the price above, because it outranks every queued batch for a worker and holds one open while you wait. It takes target, one entity, never a targets array. See Synchronous requests.
Request #
| Field | Type | Notes |
|---|---|---|
targetsrequired | array | One or more pasted Sales Navigator search URLs, as { "searchUrl": "..." } or a bare string. Each is paginated independently. |
max_resultsrequired | integer | How many rows you want FROM EACH search URL, and the number you are billed for as they arrive. Every entry in targets is paginated independently, so two search URLs with max_results 500 is up to 1,000 rows and a quote of 500 credits - not 500 rows shared between them. Above the ceiling this is refused at submit time - that ceiling is LinkedIn's own, not ours, and it applies per search URL for the same reason. |
enrich | boolean | Fold the full record into every row, under profile for people and company for companies. Adds exactly what that enrich endpoint costs, +1 per ROW either way, charged only on the rows that actually resolved. A row whose record could not be fetched arrives as a plain stub and adds nothing to the request its page already cost, and the absent field is how you tell. |
external_id | string | Your own correlation handle. It comes back on the batch, on the completion webhook and in the usage rollup, so spend can be attributed to your pipeline rather than only to ours. |
callback_url | string | Where to deliver batch.completed. Optional - polling is a first-class path, not a fallback. Validated when you send it and again when we dial it. Mutually exclusive with webhook_tag. |
webhook_tag | string | Route the completion to the endpoints carrying this tag instead of to the untagged ones, so you can name a destination without knowing its URL. A tag matching no enabled endpoint is refused here rather than discovered as a webhook that never fired. |
Call it #
curl -X POST "https://api.easydata.win/v1/sales/search/companies" \
-H "X-API-Key: $API_KEY" \
-H "Content-Type: application/json" \
-d '{"targets":[{"searchUrl":"https://www.linkedin.com/sales/search/company?query=(filters:List())"}],"max_results":250}'Response #
{
"data": {
"batch_id": "afec9131-080b-4b96-b3bb-726249e4bbf8",
"operation": "sales.search.companies",
"status": "queued",
"total": 2,
"succeeded": 0,
"failed": 0,
"pending": 2,
"results_available": 0,
"credits_used": 0,
"external_id": "crm-sync-2026-09-01",
"created_at": "2026-09-01T10:00:00Z",
"completed_at": null,
"recommended_poll_ms": 2000
},
"meta": { "requestId": "req_8f2ka91x", "recommendedPollMs": 2000 }
}A result entry #
Once the batch has drained, this is what reading its results gives you.
{
"item_index": 0,
"page": 1,
"input": { "searchUrl": "https://www.linkedin.com/sales/search/company?query=(filters:List())" },
"status": "succeeded",
"credits_used": 50,
"data": {
"results": [
{
"linkedin_id": 1042569,
"urn": "urn:li:fs_salesCompany:1042569",
"url": "https://www.linkedin.com/company/1042569",
"name": "Supercell",
"industry": "Computer Games",
"employee_count_range": "201-500 employees",
"employee_count": 342,
"scraped_at": "2026-09-01T10:00:12Z"
}
],
"pagination": { "page": 1, "returned": 100, "has_more": true, "total": 812, "display_total": "812" }
},
"created_at": "2026-09-01T10:00:12Z"
}Errors #
| Status | Type | When |
|---|---|---|
| 400 | invalid_request | The body could not be accepted as sent. `error.field` names what was wrong. A field this reference does not list is one of these: an unknown key is refused rather than accepted and ignored, because a typo that is silently dropped is indistinguishable from one that worked. |
| 401 | invalid_api_key | Missing, malformed, revoked or expired key. Never metered. |
| 403 | quota_exhausted | This month's allowance cannot cover the submission. Nothing is reserved and nothing is charged. |
| 403 | email_unverified | Nobody on the account has confirmed their email address, and the account is on the default allowance rather than an agreed one. Open the link sent when the account was created, or request a new one from the console. |
| 429 | rate_limited | Too fast: the request budget for your key, too many batches in flight, too many synchronous requests (per minute or at once), or an agreed hourly spend already met. `message` says which. Carries `Retry-After`. Never metered. |
| 422 | capacity_unavailable | No Sales Navigator capacity was free. The item is not charged. |
| 400 | invalid_request | max_results above 1,000. |
Every failure uses the same envelope, and none of them is metered - see Errors.