Sales Navigator company search

The same, against an account search. Ceiling 1,000 rows.

POSThttps://api.easydata.win/v1/sales/search/companies
50  per requesta request brings 100 stubs, and a stub is worth half a record

The 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 #

FieldTypeNotes
targetsrequiredarrayOne or more pasted Sales Navigator search URLs, as { "searchUrl": "..." } or a bare string. Each is paginated independently.
max_resultsrequiredintegerHow 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.
enrichbooleanFold 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_idstringYour 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_urlstringWhere 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_tagstringRoute 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
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 #

JSON
{
  "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.

JSON
{
  "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 #

StatusTypeWhen
400invalid_requestThe 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.
401invalid_api_keyMissing, malformed, revoked or expired key. Never metered.
403quota_exhaustedThis month's allowance cannot cover the submission. Nothing is reserved and nothing is charged.
403email_unverifiedNobody 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.
429rate_limitedToo 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.
422capacity_unavailableNo Sales Navigator capacity was free. The item is not charged.
400invalid_requestmax_results above 1,000.

Every failure uses the same envelope, and none of them is metered - see Errors.