Skip to main content
POST /people/search accepts every company filter that POST /companies/search accepts. You no longer need to pre-fetch companies, collect their IDs, and feed them into a second people query — one request does both layers.

Two parameter families, one body

A /people/search request body is split conceptually into two filter families. They live at the same level in the JSON, and you mix them freely.
Filter on attributes of the person:
The company_ prefix exists only on the location/place filters because the bare places / locations names are already used for the person’s address. Everything else uses the bare company name (technologies, not company_technologies).

Build a query in four steps

1

Decide the people predicate

Who, exactly? Title, seniority, department, country. Keep this layer at the top level of the body — the company predicate usually does the precision work.
2

Decide the company predicate

Which companies do they need to work at? Industry, size, founded year, HQ country, technology stack. Group these under a company_filters: {...} object so it’s obvious which layer each key belongs to.
3

Pick AND/OR per filter via filter_conditions

For any multi-value filter that needs precision (e.g., “uses all of these techs”), add an entry to filter_conditions inside company_filters. Defaults are OR.
4

Send the request

POST /people/search. Both styles are accepted, but company_filters: {...} reads cleaner and matches the Monitors payload shape.

Complete example

The query: VPs of Engineering or CTOs at US-based mid-market companies founded between 2015 and 2023, employing 100-5,000 people, that use both Kubernetes and Docker, but excluding companies HQ’d in San Francisco.

Key remap reference

When /people/search hands company filters to the shared engine, the location/place keys are renamed to their bare forms. The bare names are what the engine — and filter_conditions[].key — actually see: This is why filter_conditions[].key for company-level locations uses the bare names:
{ "key": "company_places", "operator": "and" } is silently ignored — the engine doesn’t recognise the prefixed name. Always reference the engine name in filter_conditions.

Joins behind the scenes

Adding any company-level filter switches the people-to-company join from LEFT JOIN to INNER JOIN. People without a recognised company on file are excluded from the result, even when they match every people-level filter.
If your search drops to zero rows the moment you add company_locations or technologies, check whether your dataset has companies linked to the people you expect. The engine prefers correctness over recall here — it never invents companies to satisfy the filter.
You’ll see this same join behaviour reflected in the response: every returned person includes a populated company object whenever any company filter was applied.

Common patterns

Target a fixed list of companies (companies or domains), then layer on people-level filters to find the right buyers inside each one.
Describe the company shape, not specific accounts. Use ranges and verticals — the engine returns the people that fit.
Find buyers at companies running a specific stack. AND on technologies is the typical override.
Find decision-makers at companies that use a competitor’s product (one tech) but not yours (excluded via categories or a separate filter pass).
Then re-run with technologies: [114] (your product’s tag ID) and diff client-side.

Next steps

filter_conditions

Full reference — every key, every default, copyable AND/OR recipes.

Filters Overview

The mental model behind the unified filter engine.

People Search reference

Full request/response schema for /people/search.

Company Search reference

Full request/response schema for /companies/search.