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

# People Search DB

> Search Datamagnet's own database of previously enriched LinkedIn profiles by keyword, location, company, job title, and more — with include/exclude support for company LinkedIn URLs.

# People Search DB

**Cost:** `10` credits/search.

Search Datamagnet's internal database of already-enriched LinkedIn profiles. Unlike [ICP People Search](/api-reference/endpoints/icp-people-search), which queries LinkedIn live, this endpoint searches previously collected profile records — so it returns instantly and doesn't consume LinkedIn scraping capacity. Each page returns up to `50` results. For companies rather than people, see [Company Search DB](/api-reference/endpoints/company-db-search).

## People search DB endpoint

Most filter fields accept multiple values. Values within the same field are OR'd together (e.g. `["San Francisco", "New York"]` matches either city); different fields are AND'd together. Booleans such as `open_to_work` take a single value.

Filters that use a fixed vocabulary — `seniority`, `ownership`, `functions`, `degree_levels`, `fields_of_study`, `employment_types` — reject a value they don't recognise with a `422` that lists what is accepted. They never quietly return zero results for a word we couldn't read.

### Free text

<ParamField body="keyword" type="string">
  Keyword search across name and headline. Also accepted as `q`; if both are sent, `keyword` wins.

  Words shorter than three characters are dropped, and the remaining words are OR'd — `"operations manufacturing quality"` matches a profile containing **any** of those words, not all three. Adding words broadens the search; use the structured filters below to narrow it.

  Example: `software engineer`
</ParamField>

### Location

<ParamField body="countries" type="string[]">
  Filter by country, matched exactly (case-insensitive) against the stored country name. For a substring match, include a `%` wildcard in the value — e.g. `["United %"]`.

  Example: `["United States", "Canada"]`
</ParamField>

<ParamField body="locations" type="string[]">
  Filter by full location string. Partial match. Example: `["Greater New York City Area"]`
</ParamField>

<ParamField body="cities" type="string[]">
  Filter by city. Partial match, against both the parsed city and the full location string. Example: `["San Francisco", "Austin"]`
</ParamField>

<ParamField body="states" type="string[]">
  Filter by state/region. Partial match, against both the parsed state and the full location string. Example: `["California"]`
</ParamField>

### Current company

A "current" position is one the profile still holds — the company filters, `employment_types` and `employer_industries` all read it the same way.

<ParamField body="companies" type="string[]">
  Filter by current company name. Partial match. Example: `["Stripe", "Plaid"]`
</ParamField>

<ParamField body="company_linkedin_urls" type="string[]">
  Filter by current company using its LinkedIn URL. Accepts a full URL, universal name, or numeric LinkedIn company ID.

  Example: `["https://www.linkedin.com/company/stripe/"]`
</ParamField>

<ParamField body="exclude_company_linkedin_urls" type="string[]">
  Exclude profiles whose **current** company matches any of these LinkedIn URLs. Accepts the same formats as `company_linkedin_urls` (full URL, universal name, or numeric ID). Useful for filtering out a competitor or your own company from results.

  Example: `["https://www.linkedin.com/company/competitor-co/"]`
</ParamField>

<ParamField body="employer_industries" type="string[]">
  Filter by the current employer's industry, matched exactly (case-insensitive). Resolved from the employer's company page where the profile itself doesn't carry an industry, which answers for roughly three quarters of people.

  Example: `["Financial Services", "Software Development"]`
</ParamField>

### Past company

<ParamField body="past_companies" type="string[]">
  Filter by a company the person has **left** (the position has an end date). Partial match. Example: `["Google"]`
</ParamField>

<ParamField body="past_company_linkedin_urls" type="string[]">
  Same as `past_companies`, by LinkedIn URL, universal name, or numeric ID.

  Example: `["https://www.linkedin.com/company/google/"]`
</ParamField>

### Role

<ParamField body="job_titles" type="string[]">
  Filter by job title. Partial match, against **any** position on the profile — current or past. Use `seniority` or `functions` when you want the role the person holds now.

  Example: `["CTO", "VP of Engineering"]`
</ParamField>

<ParamField body="seniority" type="string[]">
  Filter by the seniority of the current role, derived from the job title.

  Accepts our own labels — `Intern`, `Entry`, `Individual`, `Senior`, `Lead`, `Manager`, `Director`, `VP`, `C-suite` — or the LinkedIn Sales Navigator words the [ICP People Search](/api-reference/endpoints/icp-people-search) endpoint uses (`cxo`, `c-level`, `vice president`, `vp`, `director`, `manager`, `experienced manager`, `entry level manager`, `strategic`, `senior`, `entry level`, `in training`, `intern`). Spelling is forgiving about case, spaces, hyphens and underscores.

  `owner`, `founder` and `partner` are accepted here too and resolve to the ownership axis below, so `["VP", "founder"]` returns both groups.

  Example: `["VP", "C-suite"]`
</ParamField>

<ParamField body="ownership" type="string[]">
  Filter by ownership of the business, which is a separate axis from seniority — an owner is not a rung above a VP. Accepted values: `owner_founder` (also spelled `owner`, `founder`, `co-founder`, `self employed`) and `partner`.

  Example: `["owner_founder"]`
</ParamField>

<ParamField body="functions" type="string[]">
  Filter by department/function of the current role, from Datamagnet's 40-function taxonomy. Accepts the name or its numeric id.

  `Software Engineering`, `Data & Analytics`, `IT & Systems`, `Information Security`, `Infrastructure & DevOps`, `Quality Assurance`, `Product Management`, `Design & UX`, `Sales`, `Business Development`, `Marketing`, `Revenue Operations`, `Customer Success`, `Customer Support`, `Finance`, `Accounting`, `Legal & Compliance`, `Human Resources`, `Recruiting & Talent`, `Administrative`, `Business Operations`, `Supply Chain & Logistics`, `Manufacturing & Production`, `Procurement`, `Engineering (non-software)`, `Construction & Skilled Trades`, `Facilities & Real Estate`, `Transportation & Drivers`, `Consulting`, `Healthcare & Clinical`, `Education & Teaching`, `Research & Science`, `Media & Communications`, `Arts & Entertainment`, `Hospitality & Food Service`, `Retail`, `Public Sector`, `Protective Services`, `Social & Community Services`, `Agriculture & Environment`.

  Titles that name no department (a bare "Founder", for example) hold no function and are excluded rather than guessed at.

  Example: `["Sales", "Marketing"]`
</ParamField>

<ParamField body="employment_types" type="string[]">
  Filter by the employment type of the **current** role. Accepted values: `full_time`, `part_time`, `contract`, `freelance`, `self_employed`, `internship`, `apprenticeship`, `seasonal`.

  Each value covers the spellings LinkedIn uses for it — `contract` also matches `Temporary`, `internship` also matches `Co-op`, and so on. A profile whose employment type was never recorded matches none of them.

  Example: `["contract", "freelance"]`
</ParamField>

### Tenure

These read the start date of the current role. That date is as fresh as the profile's last refresh, so a very recent job change may not be reflected yet — the filter can miss a change, never invent one.

<ParamField body="changed_jobs_within_days" type="integer">
  Started their current role within the last N days. Example: `90`
</ParamField>

<ParamField body="min_months_in_role" type="integer">
  At least N months in the current role. Example: `12`
</ParamField>

<ParamField body="max_months_in_role" type="integer">
  At most N months in the current role. Example: `6`
</ParamField>

### Education

The education filters must all be satisfied by the **same** degree — `degree_levels: ["bachelor"]` with `fields_of_study: ["Computer and Information Sciences"]` means one bachelor's in computing, not a bachelor's in history plus a doctorate in computing.

<ParamField body="schools" type="string[]">
  Filter by school name. Partial match. Example: `["Stanford"]`
</ParamField>

<ParamField body="degree_levels" type="string[]">
  Accepted values: `secondary`, `associate`, `bachelor`, `master`, `doctorate`. Common spellings resolve to these — `bachelors`, `masters`, `phd`, `high school`.

  Example: `["bachelor", "master"]`
</ParamField>

<ParamField body="fields_of_study" type="string[]">
  Filter by field of study, grouped into 47 CIP families. Accepts the family name or its numeric id — e.g. `Computer and Information Sciences`, `Engineering`, `Business, Management, Marketing and Related Support Services`, `Health Professions and Related Programs`, `Social Sciences`. A `422` lists all of them.

  Example: `["Computer and Information Sciences"]`
</ParamField>

<ParamField body="graduation_year_min" type="integer">
  Degree ended in or after this year. Example: `2015`
</ParamField>

<ParamField body="graduation_year_max" type="integer">
  Degree ended in or before this year. Example: `2020`
</ParamField>

### Credentials and skills

<ParamField body="skills" type="string[]">
  Filter by listed skill, matched exactly (case-insensitive) against the skill name. Example: `["Kubernetes", "Terraform"]`
</ParamField>

<ParamField body="certifications" type="string[]">
  Filter by certification name. Partial match. Must hold on the same certification as `certification_issuers`. Example: `["AWS Certified Solutions Architect"]`
</ParamField>

<ParamField body="certification_issuers" type="string[]">
  Filter by issuing organization. Partial match. Example: `["Amazon Web Services"]`
</ParamField>

<ParamField body="languages" type="string[]">
  Filter by a language listed on the profile, matched exactly (case-insensitive) as LinkedIn spells it. Example: `["German", "Spanish"]`
</ParamField>

### Profile attributes

<ParamField body="open_to_work" type="boolean">
  Filter by the LinkedIn open-to-work badge.

  This filter is tri-state rather than a plain on/off switch. `true` returns profiles where the badge was seen. `false` returns profiles that were checked by a provider that reads the badge and did not have it. Profiles nobody has checked yet hold no badge information at all and are excluded from both sides, so `false` is **not** the complement of `true`, and leaving the field out is not the same as sending `false`.

  Example: `true`
</ParamField>

<ParamField body="is_premium" type="boolean">
  Filter by LinkedIn Premium. Example: `true`
</ParamField>

<ParamField body="is_creator" type="boolean">
  Filter by LinkedIn creator mode. Example: `true`
</ParamField>

<ParamField body="min_followers" type="integer">
  Minimum follower count. Example: `1000`
</ParamField>

### Contactability

<ParamField body="has_email" type="boolean">
  `true` returns only profiles Datamagnet currently holds an email address for; `false` returns only those it holds none for. Like `open_to_work`, this describes our records, not the person — `false` is not a claim that they have no email.

  Example: `true`
</ParamField>

<ParamField body="has_phone" type="boolean">
  As `has_email`, for phone numbers. Example: `true`
</ParamField>

### Response shape and paging

<ParamField body="raw_data" default={true} type="boolean">
  Whether to include the full `raw_data` payload on each result. Send `false` to omit it — the response is much smaller and the search is faster, and every other field is unaffected.
</ParamField>

<ParamField body="limit" default={50} type="integer">
  Maximum number of results to return per page, from `1` to `50`. A value outside that range is rejected rather than quietly reduced — page through larger result sets with `offset`.
</ParamField>

<ParamField body="offset" default={0} type="integer">
  Number of results to skip, for pagination.
</ParamField>

### Unrecognised fields

A field name this endpoint doesn't know is not applied. The search still runs, and the response carries an `ignored_filters` array naming what was dropped — so a mistyped `job_title` (for `job_titles`) shows up as a named mistake instead of a page of results that looks filtered but isn't.

If **every** filter in the request was unrecognised, the search is refused with a `422` and no credits are charged, rather than run as an unfiltered scan of the whole database.

***

## Response

<RequestExample>
  ```json Request theme={null}
  {
    "keyword": "software engineer",
    "cities": ["San Francisco"],
    "company_linkedin_urls": ["https://www.linkedin.com/company/stripe/"],
    "exclude_company_linkedin_urls": ["https://www.linkedin.com/company/competitor-co/"],
    "job_titles": ["Backend Engineer"],
    "seniority": ["Senior", "Lead"],
    "functions": ["Software Engineering"],
    "degree_levels": ["bachelor"],
    "min_months_in_role": 12,
    "has_email": true,
    "open_to_work": true,
    "raw_data": false,
    "limit": 50,
    "offset": 0
  }
  ```
</RequestExample>

<ResponseExample>
  ```json Response theme={null}
  {
    "message": [
      {
        "id": 10432,
        "entity_urn": "ACoAAC8Np1kB17Ro_b3eo8YZWUZFudbt9lrg1Tw",
        "username": "jane-doe-1234",
        "full_name": "Jane Doe",
        "display_name": "Jane Doe",
        "profile_headline": "Backend Engineer at Stripe",
        "description": "Building payments infrastructure.",
        "profile_link": "https://linkedin.com/in/jane-doe-1234",
        "location": "San Francisco, California, United States",
        "location_city": "San Francisco",
        "location_state": "California",
        "country": "United States",
        "followers": 1240,
        "connections": 500,
        "is_premium": true,
        "is_creator": false,
        "is_influencer": false,
        "is_job_seeker": false,
        "is_openlink": false,
        "is_retired": false,
        "open_to_work": true,
        "avatar_url": "https://media.licdn.com/dms/image/...",
        "profile_picture": "https://media.licdn.com/dms/image/...",
        "email": null,
        "linkedin_url": "https://linkedin.com/in/jane-doe-1234",
        "current_job_title": "Backend Engineer",
        "current_company": "Stripe",
        "current_job_location": "San Francisco, CA",
        "current_employment_type": "Full-time"
      }
    ],
    "credit_used": 10,
    "total": 1
  }
  ```
</ResponseExample>

## The response model

### Properties

<ResponseField name="message" type="array">
  List of matching profiles.

  <Expandable title="Profile object">
    <ResponseField name="id" type="integer">
      Internal Datamagnet profile ID.
    </ResponseField>

    <ResponseField name="entity_urn" type="string">
      LinkedIn entity URN.
    </ResponseField>

    <ResponseField name="username" type="string">
      LinkedIn username/vanity URL.
    </ResponseField>

    <ResponseField name="full_name" type="string">
      Full name of the person.
    </ResponseField>

    <ResponseField name="display_name" type="string">
      Display name as shown on LinkedIn.
    </ResponseField>

    <ResponseField name="profile_headline" type="string">
      LinkedIn profile headline.
    </ResponseField>

    <ResponseField name="description" type="string">
      Profile description/about section.
    </ResponseField>

    <ResponseField name="profile_link" type="string">
      LinkedIn profile URL.
    </ResponseField>

    <ResponseField name="location" type="string">
      Full location string.
    </ResponseField>

    <ResponseField name="location_city" type="string">
      City of the profile's location.
    </ResponseField>

    <ResponseField name="location_state" type="string">
      State/region of the profile's location.
    </ResponseField>

    <ResponseField name="country" type="string">
      Country of the profile's location.
    </ResponseField>

    <ResponseField name="followers" type="integer">
      Number of LinkedIn followers.
    </ResponseField>

    <ResponseField name="connections" type="integer">
      Number of LinkedIn connections.
    </ResponseField>

    <ResponseField name="is_premium" type="boolean">
      Whether the person has LinkedIn Premium.
    </ResponseField>

    <ResponseField name="is_creator" type="boolean">
      Whether the person is a LinkedIn creator.
    </ResponseField>

    <ResponseField name="is_influencer" type="boolean">
      Whether the person is a LinkedIn influencer.
    </ResponseField>

    <ResponseField name="is_job_seeker" type="boolean">
      Whether the person is marked as a job seeker.
    </ResponseField>

    <ResponseField name="is_openlink" type="boolean">
      Whether the person uses OpenLink.
    </ResponseField>

    <ResponseField name="is_retired" type="boolean">
      Whether the person is marked as retired.
    </ResponseField>

    <ResponseField name="open_to_work" type="boolean">
      Whether the person carries the LinkedIn open-to-work badge. `null` when no provider that reads the badge has checked this profile, which is true of most of the database — it is not the same as `false`.
    </ResponseField>

    <ResponseField name="avatar_url" type="string">
      Profile picture URL.
    </ResponseField>

    <ResponseField name="profile_picture" type="string">
      Profile picture URL (alternate source).
    </ResponseField>

    <ResponseField name="email" type="string">
      Email address, when available. May be `null`.
    </ResponseField>

    <ResponseField name="linkedin_url" type="string">
      Computed LinkedIn profile URL, built from `username`.
    </ResponseField>

    <ResponseField name="current_job_title" type="string">
      Job title of the profile's current position, when available.
    </ResponseField>

    <ResponseField name="current_company" type="string">
      Name of the profile's current company, when available.
    </ResponseField>

    <ResponseField name="current_job_location" type="string">
      Location of the profile's current position, when available.
    </ResponseField>

    <ResponseField name="current_employment_type" type="string">
      Employment type of the current position (e.g. `Full-time`), when available.
    </ResponseField>

    <ResponseField name="raw_data" type="object">
      The full stored payload this profile was built from. Included by default; send `raw_data: false` in the request to omit it.
    </ResponseField>
  </Expandable>
</ResponseField>

<ResponseField name="credit_used" type="integer">
  Number of credits used for this request. Example: `10`
</ResponseField>

<ResponseField name="total" type="integer">
  Number of results returned in this response.
</ResponseField>

<ResponseField name="ignored_filters" type="string[]">
  Present only when the request contained field names this endpoint doesn't recognise. Names them, so a typo shows up as a typo rather than as results that look filtered but aren't. The rest of the search ran normally.
</ResponseField>

## Errors

| Status | Meaning                                                                                                                                                                                                                                                              | What to do                                                                                                                                  |
| ------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------- |
| `400`  | The body was not a JSON object, or `limit` was outside `1`–`50`, or `offset` was negative. `message` names the problem.                                                                                                                                              | Fix the request.                                                                                                                            |
| `422`  | Either every filter in the request was an unrecognised field name, or a fixed-vocabulary filter was given a value that doesn't exist — an unknown function, a degree level that isn't one of the five. `message` names what was rejected and lists what is accepted. | Correct the name or the value.                                                                                                              |
| `504`  | The search ran too long to answer.                                                                                                                                                                                                                                   | Narrow it and retry — fewer countries, a more specific job title. A broad `keyword` with no structured filter beside it is the usual cause. |

Nothing is charged on any error.
