---
title: "Search people using filters and sorting"
method: POST
path: "/person/search"
tags: ["Person APIs", "Search APIs"]
---

# Search people using filters and sorting

`POST /person/search`

Search the Crustdata person database using flexible filter conditions, sorting, and cursor-based pagination.
Supports filtering on hundreds of fields including job title, company, location, seniority, industry, education, and more.
Use compound conditions with AND/OR logic to build complex queries. Results can be sorted and paginated using cursors.

<Note>
    Default `rate-limit` is 30 requests per minute. Send an email to [gtm@crustdata.co](mailto:gtm@crustdata.co) to discuss higher limits if needed for your use case.
</Note>

## Headers

- `x-api-version` '2025-11-01', required

## Request body

- PersonSearchRequest — Request body for /person/search. Use filters (optionally grouped with and/or), sorts, limit, and cursor pagination.
  - `filters` union, required — Filter criteria — a single `PersonSearchCondition` or a `PersonSearchConditionGroup` combining conditions with `and`, `or`, or `all_of` (cross-element matching on nested-array fields).
    - PersonSearchCondition — A single filter condition used to match people in /person/search.
      - `field` string, required — Field name to filter on. Valid fields include: crustdata_person_id, basic_profile.name, basic_profile.headline, basic_profile.summary, basic_profile.languages, basic_profile.last_updated, basic_profile.location, basic_profile.location.full_location, basic_profile.location.city, basic_profile.location.state, basic_profile.location.country, basic_profile.location.continent, basic_profile.normalized_title.matched_title, basic_profile.normalized_title.department, basic_profile.normalized_title.sub_department, professional_network.connections, professional_network.followers, professional_network.open_to_cards, professional_network.location, professional_network.location.raw, skills.professional_network_skills, experience.employment_details.company_name, experience.employment_details.company_id, experience.employment_details.title, experience.employment_details.description, experience.employment_details.location, experience.employment_details.start_date, experience.employment_details.end_date, experience.employment_details.seniority_level, experience.employment_details.function_category, experience.employment_details.company_website_domain, experience.employment_details.company_headcount_latest, experience.employment_details.company_headcount_range, experience.employment_details.company_industries, experience.employment_details.company_professional_network_industry, experience.employment_details.company_type, experience.employment_details.company_headquarters_country, experience.employment_details.company_hq_location, experience.employment_details.years_at_company_raw, experience.employment_details.current.name, experience.employment_details.current.company_name, experience.employment_details.current.title, experience.employment_details.current.description, experience.employment_details.current.company_id, experience.employment_details.current.position_id, experience.employment_details.current.seniority_level, experience.employment_details.current.start_date, experience.employment_details.current.company_website_domain, experience.employment_details.current.company_professional_network_industry, experience.employment_details.current.company_linkedin_profile_url, experience.employment_details.current.company_headcount_range, experience.employment_details.current.company_headcount_latest, experience.employment_details.current.company_industries, experience.employment_details.current.company_type, experience.employment_details.current.company_headquarters_country, experience.employment_details.current.company_hq_location, experience.employment_details.current.function_category, experience.employment_details.current.years_at_company_raw, experience.employment_details.past.name, experience.employment_details.past.company_name, experience.employment_details.past.title, experience.employment_details.past.description, experience.employment_details.past.company_id, experience.employment_details.past.position_id, experience.employment_details.past.seniority_level, experience.employment_details.past.start_date, experience.employment_details.past.company_website_domain, experience.employment_details.past.company_professional_network_industry, experience.employment_details.past.company_linkedin_profile_url, experience.employment_details.past.company_headcount_range, experience.employment_details.past.company_headcount_latest, experience.employment_details.past.company_industries, experience.employment_details.past.company_type, experience.employment_details.past.company_headquarters_country, experience.employment_details.past.company_hq_location, experience.employment_details.past.function_category, experience.employment_details.past.years_at_company_raw, education.schools.school, education.schools.degree, education.schools.field_of_study, education.schools.location, education.schools.location.city, education.schools.location.state, education.schools.location.country, education.schools.location.continent, education.schools.location.full_location, education.schools.location.raw, certifications.name, certifications.issue_date, certifications.expiration_date, certifications.credential_url, certifications.issuing_organization, certifications.credential_id, honors.title, social_handles.twitter_handle, basic_profile.first_name, basic_profile.last_name, recently_changed_jobs, years_of_experience_raw, experience.employment_details.current.business_email_verified, experience.employment_details.past.business_email_verified, experience.employment_details.business_email_verified, metadata.last_scraped_source, metadata.updated_at, professional_network.location.city, professional_network.location.state, professional_network.location.country, professional_network.location.continent, professional_network.metadata.last_scraped_source, experience.employment_details.employment_type, experience.employment_details.company_website, experience.employment_details.current.company_professional_network_profile_url, experience.employment_details.current.employment_type, experience.employment_details.past.company_professional_network_profile_url, experience.employment_details.past.employment_type, years_of_experience
      - `type` '=' | '!=' | '<' | '=<' | '>' | '=>' | 'in' | 'not_in' | 'has_all' | '(.)' | '(!)' | '[.]' | 'geo_distance' | 'geo_exclude', required — Filter operator. Use '=' for exact match, '!=' for not equal, '<' and '>' for exclusive numeric/date comparisons, '=<' for less-than-or-equal, '=>' for greater-than-or-equal, 'in'/'not_in' for set membership (value must be an array), 'has_all' for cross-element matching on a nested-array field (value must be a non-empty array; each listed value must be matched by some array element, possibly different elements — shorthand for an `all_of` group of one equality condition per value), '(.)' for case-insensitive all-words match (every query word must appear, in any order; a piped value is split into separate words that must ALL match (AND), not OR), '(!)' for case-insensitive fuzzy negation (excludes substring matches of `value`), '[.]' for case-insensitive exact-phrase match (words must be contiguous and in order), 'geo_distance' for geographic radius inclusion, and 'geo_exclude' for geographic radius exclusion ('geo_distance' keeps profiles inside the radius, 'geo_exclude' removes them; both take an object with `location` or `lat_lng`, plus `distance` and optional `unit`). Use '=<' and '=>' instead of '<=' and '>='. For cross-element logic beyond a single value list, use an `all_of` group (see PersonSearchConditionGroup).
      - `value` union, required — Filter value. Type depends on operator: For '=', '!=', '<', '>', '=<', '=>': string or number. For 'in', 'not_in': array of strings or numbers. For 'has_all': non-empty array of strings or numbers (nested-array fields only). For '(.)': string, supports | for OR (e.g., "VP|Director|Head of"). For '(!)': string; rows whose value contains this substring (case-insensitive) are excluded. Unlike '(.)' / '[.]', multi-word values are matched as a literal phrase (not word-split): `(!) "New York"` excludes only rows that literally contain "New York", not "New Yorker"; send separate `(!)` conditions inside an `and` group to exclude on each word independently. For '[.]': string substring to match. For 'geo_distance'/'geo_exclude': object with one of {location: string} or {lat_lng: [lat, lng]}, plus {distance: number, unit: "km"|"mi"|"miles"|"m"|"ft"}. When both `location` and `lat_lng` are supplied, `lat_lng` is used and geocoding is skipped.
        - string
        - number
        - integer
        - boolean
        - union[]
          - union
            - string
            - number
            - integer
        - object — Object value used by `geo_distance` and `geo_exclude`. Supply either `location` (geocoded server-side) or `lat_lng` (explicit `[lat, lng]`; bypasses geocoding). If both are provided, `lat_lng` wins.
          - `location` string — Reference location (e.g., "San Francisco, CA"). Ignored when `lat_lng` is also provided.
          - `lat_lng` number[] — Explicit coordinates as `[lat, lng]`. Latitude must be between -90 and 90; longitude must be between -180 and 180. When provided, geocoding is skipped.
          - `distance` number, required — Radius around the reference point.
          - `unit` 'km' | 'mi' | 'miles' | 'm' | 'meters' | 'ft' | 'feet' — Distance unit. Defaults to `km`.
    - PersonSearchConditionGroup — A group of filter conditions combined with an and/or/all_of operator.
      - `op` 'and' | 'or' | 'all_of', required — 'and'/'or' combine conditions at the document level. 'all_of' is cross-element AND over a nested-array field: each condition must be matched by at least one array element, each evaluated independently (possibly different elements). A condition inside 'all_of' may itself be an 'and'/'or' group, which is then matched within a single element. The operator is case-sensitive: send exactly 'all_of'.
      - `conditions` union[], required
        - union
          - PersonSearchCondition — A single filter condition used to match people in /person/search.
            - `field` string, required — Field name to filter on. Valid fields include: crustdata_person_id, basic_profile.name, basic_profile.headline, basic_profile.summary, basic_profile.languages, basic_profile.last_updated, basic_profile.location, basic_profile.location.full_location, basic_profile.location.city, basic_profile.location.state, basic_profile.location.country, basic_profile.location.continent, basic_profile.normalized_title.matched_title, basic_profile.normalized_title.department, basic_profile.normalized_title.sub_department, professional_network.connections, professional_network.followers, professional_network.open_to_cards, professional_network.location, professional_network.location.raw, skills.professional_network_skills, experience.employment_details.company_name, experience.employment_details.company_id, experience.employment_details.title, experience.employment_details.description, experience.employment_details.location, experience.employment_details.start_date, experience.employment_details.end_date, experience.employment_details.seniority_level, experience.employment_details.function_category, experience.employment_details.company_website_domain, experience.employment_details.company_headcount_latest, experience.employment_details.company_headcount_range, experience.employment_details.company_industries, experience.employment_details.company_professional_network_industry, experience.employment_details.company_type, experience.employment_details.company_headquarters_country, experience.employment_details.company_hq_location, experience.employment_details.years_at_company_raw, experience.employment_details.current.name, experience.employment_details.current.company_name, experience.employment_details.current.title, experience.employment_details.current.description, experience.employment_details.current.company_id, experience.employment_details.current.position_id, experience.employment_details.current.seniority_level, experience.employment_details.current.start_date, experience.employment_details.current.company_website_domain, experience.employment_details.current.company_professional_network_industry, experience.employment_details.current.company_linkedin_profile_url, experience.employment_details.current.company_headcount_range, experience.employment_details.current.company_headcount_latest, experience.employment_details.current.company_industries, experience.employment_details.current.company_type, experience.employment_details.current.company_headquarters_country, experience.employment_details.current.company_hq_location, experience.employment_details.current.function_category, experience.employment_details.current.years_at_company_raw, experience.employment_details.past.name, experience.employment_details.past.company_name, experience.employment_details.past.title, experience.employment_details.past.description, experience.employment_details.past.company_id, experience.employment_details.past.position_id, experience.employment_details.past.seniority_level, experience.employment_details.past.start_date, experience.employment_details.past.company_website_domain, experience.employment_details.past.company_professional_network_industry, experience.employment_details.past.company_linkedin_profile_url, experience.employment_details.past.company_headcount_range, experience.employment_details.past.company_headcount_latest, experience.employment_details.past.company_industries, experience.employment_details.past.company_type, experience.employment_details.past.company_headquarters_country, experience.employment_details.past.company_hq_location, experience.employment_details.past.function_category, experience.employment_details.past.years_at_company_raw, education.schools.school, education.schools.degree, education.schools.field_of_study, education.schools.location, education.schools.location.city, education.schools.location.state, education.schools.location.country, education.schools.location.continent, education.schools.location.full_location, education.schools.location.raw, certifications.name, certifications.issue_date, certifications.expiration_date, certifications.credential_url, certifications.issuing_organization, certifications.credential_id, honors.title, social_handles.twitter_handle, basic_profile.first_name, basic_profile.last_name, recently_changed_jobs, years_of_experience_raw, experience.employment_details.current.business_email_verified, experience.employment_details.past.business_email_verified, experience.employment_details.business_email_verified, metadata.last_scraped_source, metadata.updated_at, professional_network.location.city, professional_network.location.state, professional_network.location.country, professional_network.location.continent, professional_network.metadata.last_scraped_source, experience.employment_details.employment_type, experience.employment_details.company_website, experience.employment_details.current.company_professional_network_profile_url, experience.employment_details.current.employment_type, experience.employment_details.past.company_professional_network_profile_url, experience.employment_details.past.employment_type, years_of_experience
            - `type` '=' | '!=' | '<' | '=<' | '>' | '=>' | 'in' | 'not_in' | 'has_all' | '(.)' | '(!)' | '[.]' | 'geo_distance' | 'geo_exclude', required — Filter operator. Use '=' for exact match, '!=' for not equal, '<' and '>' for exclusive numeric/date comparisons, '=<' for less-than-or-equal, '=>' for greater-than-or-equal, 'in'/'not_in' for set membership (value must be an array), 'has_all' for cross-element matching on a nested-array field (value must be a non-empty array; each listed value must be matched by some array element, possibly different elements — shorthand for an `all_of` group of one equality condition per value), '(.)' for case-insensitive all-words match (every query word must appear, in any order; a piped value is split into separate words that must ALL match (AND), not OR), '(!)' for case-insensitive fuzzy negation (excludes substring matches of `value`), '[.]' for case-insensitive exact-phrase match (words must be contiguous and in order), 'geo_distance' for geographic radius inclusion, and 'geo_exclude' for geographic radius exclusion ('geo_distance' keeps profiles inside the radius, 'geo_exclude' removes them; both take an object with `location` or `lat_lng`, plus `distance` and optional `unit`). Use '=<' and '=>' instead of '<=' and '>='. For cross-element logic beyond a single value list, use an `all_of` group (see PersonSearchConditionGroup).
            - `value` union, required — Filter value. Type depends on operator: For '=', '!=', '<', '>', '=<', '=>': string or number. For 'in', 'not_in': array of strings or numbers. For 'has_all': non-empty array of strings or numbers (nested-array fields only). For '(.)': string, supports | for OR (e.g., "VP|Director|Head of"). For '(!)': string; rows whose value contains this substring (case-insensitive) are excluded. Unlike '(.)' / '[.]', multi-word values are matched as a literal phrase (not word-split): `(!) "New York"` excludes only rows that literally contain "New York", not "New Yorker"; send separate `(!)` conditions inside an `and` group to exclude on each word independently. For '[.]': string substring to match. For 'geo_distance'/'geo_exclude': object with one of {location: string} or {lat_lng: [lat, lng]}, plus {distance: number, unit: "km"|"mi"|"miles"|"m"|"ft"}. When both `location` and `lat_lng` are supplied, `lat_lng` is used and geocoding is skipped.
              - …
          - PersonSearchConditionGroup — recursive
  - `sorts` Sort[] — Sort directives applied to matched people in order.
    - `field` string, required — Field name to sort on. Valid sortable fields: crustdata_person_id, basic_profile.name, basic_profile.location, basic_profile.location.full_location, basic_profile.location.city, basic_profile.location.state, basic_profile.location.country, professional_network.connections, professional_network.followers, experience.employment_details.start_date, experience.employment_details.company_id, metadata.updated_at
    - `order` 'asc' | 'desc', required
  - `limit` integer
  - `count` integer — Alias for limit.
  - `cursor` string, nullable — Pagination cursor from a previous response's `next_cursor`. Omit on the first page.
  - `post_processing` PostProcessing — Post-processing options applied to search results (e.g., exclusions).
    - `exclude_profiles` string[] — Professional-network profile URLs to exclude from results
    - `exclude_names` string[] — Names to exclude from results
  - `return_query` boolean — Debug flag - include search query in response
  - `preview` boolean — Preview mode - return only basic fields for faster response
  - `fields` string[] — Optional list of field paths to include in each returned profile. When omitted, a default set of profile fields is returned. Use dot notation for a nested field (for example `experience.employment_details.current.title`) or a top-level family name (for example `basic_profile`) to include the whole family. An unsupported value returns a `400` whose `metadata.available_fields` lists every selectable field.

## Response `200`

People matching the search criteria

- PersonSearchResponse — Paginated response from the person search endpoint containing matched profiles and pagination metadata.
  - `profiles` PersonSearch[], required — Array of person profiles matching the search criteria
    - `crustdata_person_id` integer
    - `basic_profile` object
      - `name` string
      - `headline` string
      - `current_title` string
      - `professional_network_name` string, nullable — Display name on the person's professional-network profile.
      - `profile_picture_permalink` string, nullable
      - `location` object, nullable
        - `city` string, nullable
        - `state` string, nullable
        - `country` string, nullable
        - `continent` string, nullable
        - `raw` string, nullable
      - `normalized_title` object, nullable — Job Title Normalization (JTN, beta) — structured representation of the person's current title mapped to Crustdata's proprietary taxonomy (20 departments, 226 sub-departments). See https://docs.crustdata.com/guides/job-title-normalization.
        - `matched_title` string, nullable — Canonical normalized title matched to the person's current title.
        - `department` string, nullable — High-level department the normalized title maps to.
        - `sub_department` string, nullable — More granular classification within the department.
        - `similarity` number, nullable — Similarity score between the raw title and the matched normalized title, from 0 to 1.
        - `confident` boolean, nullable — Whether the normalized-title match is considered confident.
    - `contact` PersonSearchContact — Contact-availability flags for a person — indicates whether email or phone data is present.
      - `has_business_email` boolean — Whether person has a verified business email
      - `has_personal_email` boolean — Whether person has a personal email on file
      - `has_phone_number` boolean — Whether person has a phone number on file
    - `social_handles` object
      - `professional_network_identifier` object
        - `profile_url` string
      - `dev_platform_identifier` object
        - `profile_url` string, nullable
      - `twitter_identifier` object, nullable — The person's handle on X (formerly Twitter), when available.
        - `slug` string, nullable — The X/Twitter handle slug (the portion after the profile URL host). May be an empty string when no handle is on file.
    - `experience` object
      - `employment_details` object
        - `current` PersonEmploymentDetails[]
          - `name` string, nullable
          - `professional_network_id` string, nullable
          - `title` string, nullable
          - `description` string, nullable
          - `location` object, nullable
            - `raw` string, nullable
          - `employment_type` string, nullable
          - `start_date` string, nullable
          - `end_date` string, nullable
          - `is_default` boolean, nullable
          - `crustdata_company_id` integer, nullable
          - `company_website_domain` string, nullable
          - `company_profile_picture_permalink` string, nullable — Stable Crustdata-hosted permalink to the company logo, suitable for rendering in your own interface.
          - `company_professional_network_profile_url` string, nullable
          - `seniority_level` string, nullable
          - `function_category` string, nullable
          - `years_at_company` string, nullable
          - `years_at_company_raw` number, nullable
          - `company_headcount_latest` integer, nullable
          - `company_headcount_range` string, nullable
          - `company_industries` string[], nullable
          - `company_professional_network_industry` string, nullable
          - `company_type` string, nullable
          - `company_website` string, nullable
          - `company_headquarters_country` string, nullable
          - `company_hq_location` string, nullable
          - `company_hq_location_address_components` string[], nullable
          - `position_id` integer, nullable
          - `business_email_verified` boolean, nullable
        - `past` PersonEmploymentDetails[]
          - `name` string, nullable
          - `professional_network_id` string, nullable
          - `title` string, nullable
          - `description` string, nullable
          - `location` object, nullable
            - `raw` string, nullable
          - `employment_type` string, nullable
          - `start_date` string, nullable
          - `end_date` string, nullable
          - `is_default` boolean, nullable
          - `crustdata_company_id` integer, nullable
          - `company_website_domain` string, nullable
          - `company_profile_picture_permalink` string, nullable — Stable Crustdata-hosted permalink to the company logo, suitable for rendering in your own interface.
          - `company_professional_network_profile_url` string, nullable
          - `seniority_level` string, nullable
          - `function_category` string, nullable
          - `years_at_company` string, nullable
          - `years_at_company_raw` number, nullable
          - `company_headcount_latest` integer, nullable
          - `company_headcount_range` string, nullable
          - `company_industries` string[], nullable
          - `company_professional_network_industry` string, nullable
          - `company_type` string, nullable
          - `company_website` string, nullable
          - `company_headquarters_country` string, nullable
          - `company_hq_location` string, nullable
          - `company_hq_location_address_components` string[], nullable
          - `position_id` integer, nullable
          - `business_email_verified` boolean, nullable
    - `education` object
      - `schools` PersonEducation[]
        - `school` string — Name of the educational institution.
        - `degree` string, nullable — Degree earned at the institution.
        - `field_of_study` string, nullable — Primary field of study.
        - `description` string, nullable — Free-text description of the education entry as it appears on the profile. May be an empty string when no description is provided.
        - `location` object, nullable — Geographic location of the institution, resolved into structured components.
          - `raw` string, nullable — Location string as it appears on the profile.
          - `city` string, nullable — City component of the institution location.
          - `state` string, nullable — State or region component of the institution location.
          - `country` string, nullable — Country component of the institution location.
          - `continent` string, nullable — Continent component of the institution location.
        - `start_year` integer, nullable — Year the person started at the institution.
        - `end_year` integer, nullable — Year the person finished at the institution.
        - `activities_and_societies` string, nullable — Activities and societies the person participated in.
        - `institute_logo_permalink` string, nullable — Stable Crustdata-hosted permalink to the institution logo, suitable for rendering in your own interface.
        - `institute_logo_url` string, nullable — Source URL of the institution logo, when available.
        - `professional_network_id` string, nullable — Identifier of the institution on the professional network.
    - `metadata` object — Profile-level metadata for this person record.
      - `updated_at` string, date-time, nullable — When this person's profile data was last updated.
  - `next_cursor` string, nullable — Opaque cursor string for fetching the next page of results. Pass this value as the cursor parameter in subsequent requests. Null when no more results are available.
  - `total_count` integer, nullable — Total number of profiles matching the search criteria across all pages
  - `total_count_relation` string, nullable — Qualifier for `total_count`, indicating whether it is exact or a lower bound (for example `eq` for an exact count or `gte` when the true total is at least `total_count`). Currently returned as `null`.

## Other responses

- `400` — Invalid search request
- `401` — Unauthorized - invalid or missing API key
- `403` — Forbidden - search access not available for this account
- `500` — Internal server error

---

[API](https://skmtc.dev/crustdata/apis/batch-api.md) · [All operations](https://skmtc.dev/crustdata/apis/batch-api/llms.txt) · [OpenAPI document](https://skmtc-service-production.skmtc.workers.dev/v1/apis/crustdata/batch-api/revisions/581689e66ae7/schema)
