> ## Documentation Index
> Fetch the complete documentation index at: https://docs.peoplecontext.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Person Search API

> Search for people in the LinkedIn index using Elasticsearch Query DSL

## Endpoint

```http theme={null}
POST /v1/person/search
```

This endpoint allows you to search for LinkedIn profiles using the full power of Elasticsearch Query DSL. Use it to find people by name, company, location, skills, and more.

***

## Authentication

<ParamField header="Authorization" type="string" required>
  Bearer token with your API key: `Bearer YOUR_API_KEY`
</ParamField>

See the [Authentication Guide](/guides/authentication) for detailed setup instructions.

***

## Billing

<Note>
  **Per-Result Billing**: This endpoint charges **1 credit per result returned**, not per request. If you request 10 results and get 10 back, you're charged 10 credits. If only 3 match, you're charged 3 credits.
</Note>

The response includes `credits_charged` to show exactly how many credits were used, and response headers provide quota information:

```
X-Quota-Used: 110
X-Quota-Limit: 1000
X-Quota-Remaining: 890
X-Credits-Charged: 10
```

***

## Pagination

This endpoint uses **cursor-based pagination** for efficient deep pagination through large result sets.

1. **First request**: Omit the `cursor` parameter
2. **Subsequent requests**: Use the `next_cursor` value from the previous response
3. **Last page**: When `next_cursor` is `null`, there are no more results

***

## Request Parameters

### Request Body (JSON)

<ParamField body="query" type="object" required>
  Elasticsearch Query DSL object. Supports all standard Elasticsearch queries including `match`, `term`, `bool`, `range`, and more.

  **Example:**

  ```json theme={null}
  {"match": {"profile.full_name": "John Doe"}}
  ```
</ParamField>

<ParamField body="size" type="integer" default="10">
  Number of results to return per page. Maximum 100.

  **Example:** `20`
</ParamField>

<ParamField body="cursor" type="string">
  Pagination cursor from a previous response's `next_cursor` field. Omit for the first page.

  **Example:** `"eyJ2IjoxLCJzb3J0IjpbMS4wLCJqb2huZG9lIl19"`
</ParamField>

<ParamField body="sort" type="array">
  Sort criteria as an array of sort objects. If omitted, results are sorted by relevance (`_score` descending).

  **Example:**

  ```json theme={null}
  [{"profile.connections": "desc"}, {"profile.full_name.keyword": "asc"}]
  ```
</ParamField>

<ParamField body="_source" type="array | boolean">
  Fields to include or exclude from the response. Use an array of field names to include only those fields, or `false` to exclude `_source` entirely.

  **Example:** `["profile.full_name", "profile.headline", "linkedin_url"]`
</ParamField>

***

## Response

### Success Response (200 OK)

<ResponseField name="total" type="integer">
  Total number of matching documents in the index.
</ResponseField>

<ResponseField name="results" type="array">
  Array of LinkedIn person profiles matching the query.

  <ResponseField name="linkedin_url" type="string">
    Full LinkedIn profile URL
  </ResponseField>

  <ResponseField name="linkedin_username" type="string">
    LinkedIn username (profile slug)
  </ResponseField>

  <ResponseField name="profile_id" type="string">
    LinkedIn internal profile ID
  </ResponseField>

  <ResponseField name="updated_at" type="string">
    When the profile was last updated
  </ResponseField>

  <ResponseField name="profile" type="object">
    Core profile information including `first_name`, `last_name`, `full_name`, `headline`, `summary`, `image_url`, `connections`, `followers`, `location`, and `personal_email`
  </ResponseField>

  <ResponseField name="experience" type="array">
    Array of work experience entries with `title`, `company_name`, `company_id`, `company_url`, `location`, `description`, `start_date`, `end_date`, and `is_current`
  </ResponseField>

  <ResponseField name="education" type="array">
    Array of education entries with `school_name`, `school_id`, `school_url`, `degree`, `field_of_study`, `start_date`, and `end_date`
  </ResponseField>

  <ResponseField name="certifications" type="array">
    Array of certifications with `name`, `issuer`, and `issue_date`
  </ResponseField>

  <ResponseField name="languages" type="array">
    Array of languages with `language` and `proficiency`
  </ResponseField>
</ResponseField>

<ResponseField name="next_cursor" type="string | null">
  Cursor for the next page of results. `null` if there are no more results.
</ResponseField>

<ResponseField name="credits_charged" type="integer">
  Number of credits charged for this request (1 per result returned).
</ResponseField>

### Error Responses

**Error Status Codes:**

* **400 Bad Request** - Invalid query syntax or invalid cursor
* **401 Unauthorized** - Missing or invalid API key
* **403 Forbidden** - Organization is inactive
* **429 Too Many Requests** - Rate limit exceeded or insufficient credits

```json theme={null}
{
  "detail": "Insufficient credits. Have 5, need up to 10. Reduce 'size' parameter or upgrade your plan."
}
```

***

## Examples

<CodeGroup>
  ```bash cURL theme={null}
  # Simple name search
  curl -X POST "https://api.peoplecontext.com/v1/person/search" \
    -H "Authorization: Bearer YOUR_API_KEY" \
    -H "Content-Type: application/json" \
    -d '{
      "query": {"match": {"profile.full_name": "John Doe"}},
      "size": 10
    }'

  # Search with filters
  curl -X POST "https://api.peoplecontext.com/v1/person/search" \
    -H "Authorization: Bearer YOUR_API_KEY" \
    -H "Content-Type: application/json" \
    -d '{
      "query": {
        "bool": {
          "must": [{"match": {"profile.headline": "software engineer"}}],
          "filter": [{"term": {"profile.location.country.keyword": "united states"}}]
        }
      },
      "size": 20
    }'

  # Paginate with cursor
  curl -X POST "https://api.peoplecontext.com/v1/person/search" \
    -H "Authorization: Bearer YOUR_API_KEY" \
    -H "Content-Type: application/json" \
    -d '{
      "query": {"match": {"profile.headline": "software engineer"}},
      "size": 10,
      "cursor": "eyJ2IjoxLCJzb3J0IjpbMS4wLCJqb2huZG9lIl19"
    }'
  ```

  ```python Python theme={null}
  import requests

  url = "https://api.peoplecontext.com/v1/person/search"
  headers = {
      "Authorization": "Bearer YOUR_API_KEY",
      "Content-Type": "application/json"
  }

  # Search for software engineers in the US
  payload = {
      "query": {
          "bool": {
              "must": [{"match": {"profile.headline": "software engineer"}}],
              "filter": [{"term": {"profile.location.country.keyword": "united states"}}]
          }
      },
      "size": 20
  }

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

  print(f"Total matches: {data['total']}")
  print(f"Credits charged: {data['credits_charged']}")

  for person in data["results"]:
      profile = person.get("profile", {})
      print(f"- {profile.get('full_name')} | {profile.get('headline')}")

  # Paginate through all results
  while data.get("next_cursor"):
      payload["cursor"] = data["next_cursor"]
      response = requests.post(url, headers=headers, json=payload)
      data = response.json()

      for person in data["results"]:
          profile = person.get("profile", {})
          print(f"- {profile.get('full_name')} | {profile.get('headline')}")
  ```

  ```javascript JavaScript theme={null}
  const url = 'https://api.peoplecontext.com/v1/person/search';
  const headers = {
    'Authorization': 'Bearer YOUR_API_KEY',
    'Content-Type': 'application/json'
  };

  // Search for software engineers
  const payload = {
    query: {
      bool: {
        must: [{ match: { 'profile.headline': 'software engineer' } }],
        filter: [{ term: { 'profile.location.country.keyword': 'united states' } }]
      }
    },
    size: 20
  };

  const response = await fetch(url, {
    method: 'POST',
    headers,
    body: JSON.stringify(payload)
  });

  const data = await response.json();

  console.log(`Total matches: ${data.total}`);
  console.log(`Credits charged: ${data.credits_charged}`);

  data.results.forEach(person => {
    const { full_name, headline } = person.profile || {};
    console.log(`- ${full_name} | ${headline}`);
  });

  // Paginate with cursor
  if (data.next_cursor) {
    payload.cursor = data.next_cursor;
    const nextResponse = await fetch(url, {
      method: 'POST',
      headers,
      body: JSON.stringify(payload)
    });
    const nextData = await nextResponse.json();
    // Process next page...
  }
  ```
</CodeGroup>

***

## Sample Response

```json theme={null}
{
  "total": 15234,
  "results": [
    {
      "linkedin_url": "https://www.linkedin.com/in/johndoe",
      "linkedin_username": "johndoe",
      "profile_id": "ABC123",
      "updated_at": "2025-01-15T10:30:00Z",
      "profile": {
        "first_name": "John",
        "last_name": "Doe",
        "full_name": "John Doe",
        "headline": "Senior Software Engineer at TechCorp",
        "summary": "Passionate about building scalable systems...",
        "image_url": "https://media.licdn.com/...",
        "connections": 500,
        "followers": 1200,
        "location": {
          "raw_address": "San Francisco Bay Area",
          "country": "United States",
          "country_code": "US"
        }
      },
      "experience": [
        {
          "title": "Senior Software Engineer",
          "company_name": "TechCorp",
          "company_url": "https://www.linkedin.com/company/techcorp",
          "location": "San Francisco, CA",
          "start_date": "2022-01",
          "end_date": null,
          "is_current": true
        }
      ],
      "education": [
        {
          "school_name": "Stanford University",
          "degree": "Bachelor of Science",
          "field_of_study": "Computer Science",
          "start_date": "2014",
          "end_date": "2018"
        }
      ],
      "certifications": [],
      "languages": [
        {"language": "English", "proficiency": "Native"},
        {"language": "Spanish", "proficiency": "Professional"}
      ]
    }
  ],
  "next_cursor": "eyJ2IjoxLCJzb3J0IjpbOC41LCJqb2huZG9lIl19",
  "credits_charged": 1
}
```

***

## Query Examples

### Search by Name

```json theme={null}
{
  "query": {"match": {"profile.full_name": "John Doe"}}
}
```

### Search by Company

```json theme={null}
{
  "query": {"match": {"experience.company_name": "Google"}}
}
```

### Search by Job Title (Current Only)

```json theme={null}
{
  "query": {
    "nested": {
      "path": "experience",
      "query": {
        "bool": {
          "must": [
            {"match": {"experience.title": "Software Engineer"}},
            {"term": {"experience.is_current": true}}
          ]
        }
      }
    }
  }
}
```

### Search by Location

```json theme={null}
{
  "query": {
    "term": {"profile.location.country.keyword": "united states"}
  }
}
```

### Combined Search with Filters

```json theme={null}
{
  "query": {
    "bool": {
      "must": [
        {"match": {"profile.headline": "software engineer"}}
      ],
      "filter": [
        {"term": {"profile.location.country.keyword": "united states"}},
        {"range": {"profile.connections": {"gte": 500}}}
      ]
    }
  },
  "sort": [{"profile.connections": "desc"}],
  "size": 50
}
```

***

## Best Practices

<Tip>
  **Use Filters for Exact Matches**: Use `term` queries in a `filter` context for exact matches (like country codes). Filters are cached and faster than `match` queries.
</Tip>

<Tip>
  **Limit Fields with \_source**: If you only need specific fields, use the `_source` parameter to reduce response size and improve performance.
</Tip>

<Warning>
  **Mind Your Credits**: With per-result billing, requesting `size: 100` could charge up to 100 credits per request. Start with smaller page sizes and paginate as needed.
</Warning>

<Note>
  **Keyword Fields**: For exact matching on text fields, use the `.keyword` suffix (e.g., `profile.location.country.keyword`). Without it, text is analyzed and may not match exactly.
</Note>

***

## Related

* [LinkedIn Webset Guide](/guides/linkedin-webset) - Overview of LinkedIn data
* [Person Enrichment API](/api-reference/person/enrich) - Enrich profiles by identifier
* [Authentication Guide](/guides/authentication) - API key setup
