docs sourcing
Raw search
One page of the person index for filters you choose.
Raw search is for builders who want their own sourcing logic: you choose the filters, you get one page of 25 people, and nothing is planned, ranked, or deduplicated for you.
curl -s -X POST "$RECRUITMCP_BASE/v1/people/search" \
-H "Authorization: Bearer $RECRUITMCP_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: $(uuidgen)" \
-d '{"filters": {"current_job_titles": ["Data Engineer"], "geo_ids": ["90009596"], "past_companies": ["Showpad"]}, "page": 1}'
Filters
Each filter maps one to one to a filter the person index applies. Anything else is refused with 400 unsupported_filter and details.field; nothing is silently ignored.
| Filter | Values |
|---|---|
current_job_titles, past_job_titles (+ exclude_…) | Titles, up to 70 |
geo_ids, exclude_geo_ids | Location ids from lookups, up to 70 |
current_companies, past_companies (+ exclude_…) | Company URLs, ids, or names, up to 50 |
schools, exclude_schools | School names, up to 50 |
industry_ids, function_ids, seniority_level_ids (+ exclude_…) | Ids from the value lists |
years_of_experience_ids, years_at_current_company_ids | Year buckets 1–5 |
company_headcount | Size ranges A–I |
profile_languages | Language codes the profile is written in |
first_names, last_names | Up to 50 |
recently_changed_jobs | Changed jobs in the last 90 days |
search | Keywords. Quote phrases; combine with OR, AND, NOT |
Unknown top-level fields are refused the same way, as 400 invalid_request with details.field and details.allowed, so a typo such as pgae never runs a different search than you meant. There is no raw flag: every layer returns the normalized profile, and raw: true is refused. The reasons are in API layers.
Refused on purpose, with a reason in the error: time in the current title (years_in_current_position_ids; filter run candidates on tenure_months), skills (put the skill in search), and emails (use POST /v1/people:match).
Response
| Field | Meaning |
|---|---|
data[] | People: profile_id, name, location, profile URL, current positions, and already_seen |
query_key | Stable id of this filter set. Ask for the next page with the same filters |
done, total_elements | Whether more pages exist, and the index's total when it reports one |
applied_filters | Every filter as sent, plus suppression and exclude_seen |
ignored_fields | Always empty here; raw search refuses instead of ignoring |
omitted.unpaid | Leads on this page that were not returned because the balance ran out. They were not charged |
resume | { page, query_key } when unpaid is greater than zero. Repeat the same filters and that page after you add credits. Leads already billed come back free |
People already in your seen register are returned with already_seen: true. Pass exclude_seen: true to drop them. Suppressed people are always removed, in every layer, and counted.
Fetch the full profiles of the people you want with POST /v1/people:fetch.
What it costs
1 credit per lead actually returned. Suppressed people and people left out with exclude_seen are not charged, an empty page is free, and a lead is charged once per workspace. There is no per-page fee. ?dry_run=true is free and returns an estimate from 0 up to 25 credits.
MCP: search_people_raw in the advanced toolset. Without confirm it is the estimate.
Reference: searchPeople and PeopleFilters in the API reference.