Filter operator reference
Person Search accepts the followingfilters.type operators.
Operator sets differ per endpoint.
contains is not supported on
/person/search (use (.) for substring/word matching) — it is accepted
by Company Search and by the autocomplete endpoints’ filters. has_all
works only on nested array fields (for example
experience.employment_details.*); non-array fields return 400.(!) — fuzzy negation
(!) excludes profiles whose value contains the given substring,
case-insensitive. It is the opposite of (.). Multi-word values are matched
as a literal phrase — they are not word-split:
-
{ "type": "(!)", "value": "New York" }excludes only profiles that literally contain the phrase"New York". A profile whose location is"New Yorker"is not excluded by this filter;"New York City"is excluded because it contains the full phrase. -
To exclude on each word independently, wrap multiple
(!)conditions in anandgroup:
geo_distance — radius around a point
Supply the centre of the radius using one of:
location— a string that is geocoded server-side (e.g."San Francisco, CA").lat_lng— explicit coordinates as[lat, lng]. Skips geocoding.
lat_lng wins. distance is required; unit defaults
to km.
See
geo_distance examples
for end-to-end requests using both location and lat_lng.
geo_exclude — exclude a radius
geo_exclude is the inverse of geo_distance: it removes profiles inside
the radius and keeps everyone else. It takes the same value object —
location or lat_lng, a required distance, and an optional unit
(defaults to km) — and works on the same location fields. Use it to carve
out a metro you already cover, or to target candidates outside a region.
geo_exclude examples
for an end-to-end request.
Nested-array matching: all_of and has_all
Some fields are arrays of nested objects — for example a person’s
employment history (experience.employment_details.*), where each entry has
its own title, company_id, company_name, and dates. When you put several
conditions on one such field, there are two distinct things you might mean:
- Same element — one array entry satisfies all the conditions (was an Engineer at company X — one job).
- Cross element — different entries each satisfy a condition (was an Engineer at A and a Manager at B — two separate jobs).
and group over one nested field means same element: all
conditions must match within a single entry. To express cross element, use
an all_of group.
all_of — each condition matched by some element
all_of is a group operator (like and/or). Each condition inside it must be
satisfied by at least one array element, and each condition is evaluated
independently — so different conditions can be matched by different
elements. A condition can be a single filter or an and/or group; a group is
matched within one element.
Existential — some job is both Engineer and at company 629097:
Engineer at one company and Manager at another, in
different jobs:
all_of groups nest freely inside and/or groups, so you can combine
cross-element requirements with document-level filters (like location).
Conditions inside all_of accept any positive operator
(=, (.), [.], in, <, >, =<, =>).
has_all — every value matched by some element
has_all is shorthand for the common cross-element case: a value list where
each value is matched by some element of the array.
Worked at both company 629097 and 632500 (two separate roles):
all_of with one equality condition per value:
{ "op": "all_of", "conditions": [company_id = 629097, company_id = 632500] }.
Rules and validation
- Send the operator in lowercase:
all_of(likeand/or;allOfand other casings are rejected). - All fields inside one
all_ofcondition (or itsand/orgroup) must resolve to a single nested-array path. Mixing paths (for example an employment field and an education field in the same group) is rejected — split them into separateall_ofconditions. all_ofandhas_allare valid only on nested-array fields (employment, education, certifications, honors). Using them on a scalar field (such as a name) is rejected.- Conditions inside
all_ofallow positive predicates only. Negation operators (!=,not_in,(!),geo_exclude) are not allowed — apply negation at the document level instead. - Do not put a
has_allcondition (or anotherall_of) inside anall_ofgroup — expand it into=conditions instead. has_allrequires a non-empty list value.
Searchable fields
- Some returned fields use a different filter path. For example, the returned
basic_profile.current_titleis searched withexperience.employment_details.current.title. - Contact availability flags such as
contact.has_business_emailare response-only convenience fields. For search filters, useexperience.employment_details.current.business_email_verified,experience.employment_details.past.business_email_verified, orexperience.employment_details.business_email_verified. social_handles.professional_network_identifier.profile_urlis returned in search results but is rejected as a search filter. Use Person Enrich for direct profile URL lookups.- Some searchable fields, such as
certifications.*andhonors.title, may not appear in the response summary below.
Country filters do not all use the same value format. Use full country names
for person location fields, and use ISO 3166-1 alpha-3 codes for employer
headquarters country fields.
Country and region value formats
For headquarters country filters, use ISO-3 codes such as
USA, IND, and
GBR. For the full code list, see the
ISO 3166-1 alpha-3 country code list.
For basic_profile.location.country, use Autocomplete
to discover indexed full-country labels before filtering.
Website value formats
Filter websites with the
company_website_domain fields — a bare domain, no
scheme. The all-roles company_website filter matches the stored URL
exactly, including scheme and any query string (stored values can look like
https://example.com?utm_source=profile), so prefer the domain fields unless
you need an exact URL match. In search responses the website comes back as a
full URL under experience.employment_details.current.company_website /
past.company_website; the company_website_domain paths are filter-side
names and never appear in the search response.
Person Enrich is the reverse: it
returns the bare domain under company_website_domain.
Identity & metadata
Basic profile
Professional network
Skills
Experience — all employers
Experience — current employer
Experience — past employer
Education
Certifications & honors
Social handles
Other
Open-to signal values
professional_network.open_to_cards is a closed enum of exactly three code strings. Filter with the in operator using one or more of these values:
Filter example
Response fields
Each profile in the response can include these sections, depending onfields. This table summarizes returned sections only. It is not a complete filter reference.
skills and dev_platform_profiles are not returned by Person Search.
Search returns a lightweight subset, so these sections are absent from the
response for every account regardless of fields — they are not gated, just
not part of search. Fetch skills with
Person Enrich. skills.professional_network_skills
still works as a filter (see Filterable but not returned).Filterable but not returned
Some fields can be used infilters to narrow results but are not returned
in the search response — search is lightweight discovery, not full enrichment.
Filter on them, then fetch their values with
Person Enrich.
skills.professional_network_skills is the most common example — filterable here,
but only returned by Enrich.
The reverse also holds for a few fields: the person’s profile URL
(
social_handles.professional_network_identifier.profile_url) is returned
but not filterable. To find people at a company, filter on the employer’s
company URL
(experience.employment_details.current.company_professional_network_profile_url)
instead.Request parameter reference
Preview mode
Preview mode
Preview search is a premium feature. Book a demo to enable it for your
account.
preview: true to get lightweight results before running a full search. Preview responses keep the same top-level shape but may return fewer profile fields.
If preview is not enabled for your account,
the API returns
400 invalid_request with the message error: PersonDB preview feature is not available for your account.Errors
No results
When no people match the filters, the API returns200 with an empty profiles array:
Filter sizing. To match many values of a field, put them all in a single
in condition rather than many separate conditions — in compiles to one
efficient query. A single in list of up to ~5,000–10,000 values returns in a
few seconds; larger lists get progressively slower, and very large lists
(roughly 50,000+) are rejected. For bigger sets, split the values into
~5,000–10,000 chunks across multiple requests and merge. The request body is
hard-capped at 10 MB (larger bodies return 413 request_too_large),
though with typical payloads you reach the query-size limit first.API reference summary
Paginate through results
When your search matches more profiles than yourlimit, use cursor-based pagination to walk through all pages.
First page: send your normal search request.
next_cursor value from the response and pass it in your next request. Keep the same filters and limit.
next_cursor is null, which means you have reached the last page.
Sort results
Use thesorts parameter to order results by a specific field. This is important for stable pagination.
crustdata_person_id, metadata.updated_at, basic_profile.name, basic_profile.location, basic_profile.location.city, basic_profile.location.state, basic_profile.location.country, basic_profile.location.full_location, professional_network.connections, professional_network.followers, experience.employment_details.start_date, experience.employment_details.company_id, experience.employment_details.company_headcount_latest, experience.employment_details.years_at_company_raw, recently_changed_jobs, and years_of_experience_raw. Sorting on any other field returns 400.
The Sortable column in Searchable fields marks these per
field, alongside whether each field is Filterable.
See the full API reference for the complete OpenAPI schema
