# Search people (Sales Navigator) (BETA)

Search people with structured filters or a pasted Sales Navigator URL.

**POST** `https://api.up2data.ai/v1/search/people/sales-nav`

**Credits:** 1 credit per page (up to 25 results) - **Mode:** synchronous

Two ways to search: pass structured `filters`, or paste a full Sales Navigator lead-search URL as `sales_nav_url`. Geo, industry, company, and school filters take LinkedIn IDs, not free text. Empty pages are free. A single call returns at most 100 results (`pagination.has_more` is true when more exist); for a bigger pull, send it as a search item in [`POST /v1/batch`](https://up2data.ai/docs/v1/api/batch-create/) instead of looping sync calls.

> **Warning:** Provide `filters` or `sales_nav_url`, never both, never neither.

> **Info:** Counts as 1 request against the 5,000/min per-key limit and 1 search against the 5,000/hour per-organization search quota. See [Rate limits](https://up2data.ai/docs/v1/guides/rate-limits/).

> **Info:** Send many as batch operation items (operation search.people.sales_nav); up to 2,500 results per item, reserved at submission and refunded for any shortfall once the search runs. See the [batch endpoint](https://up2data.ai/docs/v1/api/batch-create/).

## Request

| Field | Type | Notes |
|---|---|---|
| `filters` | `object` | Structured filter object; see the fields below. Provide filters or sales_nav_url, never both, never neither. |
| `filters.keywords` | `string` |  |
| `filters.titles` | `string[]` |  |
| `filters.past_titles` | `string[]` |  |
| `filters.seniorities` | `string[]` | Enum per item: owner, partner, cxo, vp, director, manager, senior, entry, training, strategic. |
| `filters.function_ids` | `string[]` | LinkedIn FUNCTION ids, e.g. "25" for Sales. |
| `filters.company_ids` | `FacetId[]` | Bare id string, or { id, text } for a display label. |
| `filters.past_company_ids` | `FacetId[]` |  |
| `filters.company_sizes` | `string[]` | Enum per item: self-employed, 1-10, 11-50, 51-200, 201-500, 501-1000, 1001-5000, 5001-10000, 10001+. |
| `filters.industry_ids` | `FacetId[]` |  |
| `filters.location_ids` | `FacetId[]` | LinkedIn geo / REGION ids. |
| `filters.school_ids` | `FacetId[]` |  |
| `filters.years_of_experience` | `string[]` | Enum per item: "1" through "5". |
| `filters.years_at_current_company` | `string[]` | Enum per item: "1" through "5". |
| `filters.years_in_current_position` | `string[]` | Enum per item: "1" through "5". |
| `filters.first_name` | `string` |  |
| `filters.last_name` | `string` |  |
| `filters.posted_on_linkedin` | `boolean` |  |
| `filters.recently_changed_jobs` | `boolean` |  |
| `sales_nav_url` | `string` | Full Sales Navigator lead-search URL pasted from the browser. Mutually exclusive with filters. |
| `max_results` | `integer` | Default 100. 1 to 2,500; a sync call returns at most 100 results (`pagination.has_more` is true when more exist). For a bigger pull, send it as a search item in POST /v1/batch, which allows up to 2,500. |

## Call it

**cURL**

```bash
curl -X POST "https://api.up2data.ai/v1/search/people/sales-nav" \
  -H "X-API-Key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
  "filters": {
    "titles": [
      "VP Sales"
    ],
    "seniorities": [
      "vp",
      "director"
    ],
    "location_ids": [
      {
        "id": "102095887",
        "text": "California"
      }
    ],
    "company_sizes": [
      "51-200",
      "201-500"
    ]
  },
  "max_results": 50
}'
```

**Python**

```python
import requests

url = "https://api.up2data.ai/v1/search/people/sales-nav"
headers = {
    "X-API-Key": "YOUR_API_KEY",
    "Content-Type": "application/json",
}
payload = {
    "filters": {
        "titles": [
            "VP Sales"
        ],
        "seniorities": [
            "vp",
            "director"
        ],
        "location_ids": [
            {
                "id": "102095887",
                "text": "California"
            }
        ],
        "company_sizes": [
            "51-200",
            "201-500"
        ]
    },
    "max_results": 50
}

response = requests.post(url, headers=headers, json=payload)
print(response.json())
```

**Node**

```javascript
const url = "https://api.up2data.ai/v1/search/people/sales-nav";
const headers = {
  "X-API-Key": "YOUR_API_KEY",
  "Content-Type": "application/json",
};
const body = {
  "filters": {
    "titles": [
      "VP Sales"
    ],
    "seniorities": [
      "vp",
      "director"
    ],
    "location_ids": [
      {
        "id": "102095887",
        "text": "California"
      }
    ],
    "company_sizes": [
      "51-200",
      "201-500"
    ]
  },
  "max_results": 50
};

const response = await fetch(url, {
  method: "POST",
  headers,
  body: JSON.stringify(body),
});
const data = await response.json();
console.log(data);
```

**Go**

```go
package main

import (
	"bytes"
	"fmt"
	"io"
	"net/http"
)

func main() {
	url := "https://api.up2data.ai/v1/search/people/sales-nav"
	body := bytes.NewBufferString(`{
  "filters": {
    "titles": [
      "VP Sales"
    ],
    "seniorities": [
      "vp",
      "director"
    ],
    "location_ids": [
      {
        "id": "102095887",
        "text": "California"
      }
    ],
    "company_sizes": [
      "51-200",
      "201-500"
    ]
  },
  "max_results": 50
}`)
	req, err := http.NewRequest("POST", url, body)
	if err != nil {
		panic(err)
	}
	req.Header.Set("X-API-Key", "YOUR_API_KEY")
	req.Header.Set("Content-Type", "application/json")

	client := &http.Client{}
	resp, err := client.Do(req)
	if err != nil {
		panic(err)
	}
	defer resp.Body.Close()

	respBody, _ := io.ReadAll(resp.Body)
	fmt.Println(string(respBody))
}
```

## Response

**200**

```json
{
  "data": {
    "results": [{
      "url": "https://www.linkedin.com/in/ACwAAAtrDxoBpU0UuxqsRapB-BUxVWrU38-8c0g",
      "full_name": "Tong Zhi",
      "location": { "city": "London", "region": "England", "country": "United Kingdom" },
      "positions": [{ "title": "Co-Founder & CTO", "company": "HireHarbour", "company_url": "https://www.linkedin.com/company/100124585", "linkedin_id": "100124585", "started_at": "2023-10", "ended_at": null, "description": "Helping businesses by finding experienced, high quality remote staff." }],
      "current_company": { "name": "HireHarbour", "url": "https://www.linkedin.com/company/100124585", "linkedin_id": "100124585", "title": "Co-Founder & CTO", "started_at": "2023-10" },
      "is_premium": true
    }],
    "pagination": { "returned": 10, "max_results": 10, "pages_scraped": 1, "has_more": true }
  },
  "meta": { "creditsUsed": 1, "creditsRemaining": 98418, "billed": true, "reason": "success", "requestId": "req_example", "latencyMs": 2800, "resolved_search_url": "https://www.linkedin.com/sales/search/people?query=(spellCorrectionEnabled:true,filters:List((type:CURRENT_TITLE,values:List((text:CTO,selectionType:INCLUDED)))),keywords:kubernetes)" }
}
```

## Errors

| Status | Type | When | Billed |
|---|---|---|---|
| 400 | `invalid_request` | Malformed body, unknown filter, bad enum value, or both/neither of filters and sales_nav_url provided. | No |
| 401 | `invalid_api_key` | Missing, malformed, or revoked key. | No |
| 402 | `insufficient_credits` | Balance can't cover the page(s) requested. | No |
| 429 | `rate_limited` | Over the 5,000 requests/min limit, or the 5,000 searches/hour per-organization quota. Honor Retry-After. | No |
| 500 | `internal_error` | Something broke on the server side. | No |
| 504 | `upstream_timeout` | The live scrape didn't complete in time. | No |

See the [Errors guide](https://up2data.ai/docs/v1/guides/errors/) for every error type this version can return.
