Filtering & Search
The API supports five ways to find data, from broad to precise.
How do I filter companies by employee count?
Filter companies by employee count with the named employee_bands filter or a numeric cf[total_number_of_employees] range. Use Filter Options to discover valid employee-band values before requesting rows.
Text search
Substring match on the entity's name field. Single-token, not multi-token fuzzy:
GET /v1/companies?search=acmesearch=MERCER%20SAN%20FRANCISCO typically return [] — the implementation is closer to LIKE '%MERCER SAN FRANCISCO%' against the name column. Use the most distinctive token and combine with states= or other narrowing filters; for post-token disambiguation, filter the response client-side on company_city /broker_city.Named filters
Structured filters with known values. Most accept comma-separated lists:
GET /v1/companies?states=CA,NY&industries=Hospitals,Software+Publishers&employee_bands=Mid-market+AccountsCombination logic: AND across parameters, OR within a comma-separated list. states=CA,NY&industries=Hospitals returns rows in (CA OR NY) AND Hospitals.
Unknown query parameters are rejected with 400 VALIDATION_ERROR. This catches typos early.
Column filters
Filter on any column using cf[column_name]:
Exact match:
GET /v1/companies?cf[company_state]=CA,NY
# Reverse-lookup a single person by a unique field (no /personnel/lookup exists)
GET /v1/personnel?lead_type=company&cf[email_address]=jennifer.smith%40example.com
GET /v1/personnel?lead_type=company&cf[person_linkedin_url]=https%3A%2F%2Flinkedin.com%2Fin%2FjsmithNumeric range:
GET /v1/companies?cf[total_premiums]=gte:1000000,lte:5000000
GET /v1/companies?cf[participants]=gte:100
GET /v1/companies?cf[broker_tenure_years]=lte:2Range operators: gte: (>=), lte: (<=). Combine both for a range.
Percentage columns such as participant_growth, commission_growth, and broker_commission_growth_pct interpret numeric thresholds as percent values. For example, cf[participant_growth]=gte:1 means at least 1%, and gte:1.001 is a slightly stricter threshold than gte:1.
cf[] filters are applied server-side for the columns listed below. Always sanity-check a new numeric filter with &count_only=true first so you can confirm the row count before spending credits on a full response or export.Available numeric columns:
| Entity | Columns |
|---|---|
| Companies | participants, total_premiums, medical_premiums, total_number_of_employees, broker_commission, broker_tenure_years, broker_commission_growth_pct, assets_401k, primary_broker_compensation, participant_growth |
| Brokers | total_offices, total_clients, total_commissions, total_premiums |
| Personnel | total_number_of_employees |
Named filters vs column filters — when to use which
Both syntaxes work. Pick by intent: named filters when one exists (states=, industries=, employee_bands=); reach for cf[col]= when there is no named filter, when you need a numeric range, or when you want exclude-blanks (eb[col]=true) on the same column.
| Named filters | Column filters | |
|---|---|---|
| Examples | states= | cf[company_state]= |
| Validates against enums? | Yes | Yes (when column is enum-typed) |
| Numeric ranges? | No | Yes (gte:, lte:) |
| Match response keys 1:1? | Sometimes | Always — useful for round-tripping a key |
| Supports eb[]? | No | Yes |
Don't mix a named filter and a cf[] filter on the same column in the same request — behavior is the AND of both, but it's easy to confuse yourself.
Signal vs column name — same name, different parameter
Three signals share names with numeric columns. They are scoped by parameter and mean different things.
| Name | As signals= (signal) | As cf[col]= (numeric column) |
|---|---|---|
participant_growth | Filter rows where YoY participant growth ≥ 20% | Numeric range filter on the participant_growth field (% change) |
commission_growth | Filter rows where YoY commission growth ≥ 15% | (Phase 2 — not yet a cf[] column) |
self_funded | Filter rows flagged self-funded by the proprietary algorithm | Use funding_status=Self-Funded instead |
Exclude blanks
Only return rows where a column has a value:
GET /v1/companies?eb[website]=true&eb[linkedin]=trueeb[column] only accepts true. Sending false returns a structured 400 VALIDATION_ERROR instead of acting as a no-op.
+ decodes to a space. The enum value Fifty+ relationships must be sent as Fifty%2B%20relationships. Sending it raw will be parsed as Fifty relationships (extra space) and won't match. Bracket params and values with spaces also need encoding — cf[company_state]=CA,NY becomes cf%5Bcompany_state%5D=CA%2CNY.Lookup (exact match, single result)
For CRM enrichment — returns one entity, 404 on no match, or 400 with suggestions on multi-match.
| Resource | Endpoint | Match parameters |
|---|---|---|
| Company | GET /v1/companies/lookup | ?domain=, ?name=, or ?ein= (provide exactly one) |
| Broker | GET /v1/brokers/lookup | ?name= |
GET /v1/companies/lookup?domain=stripe.com
GET /v1/companies/lookup?name=Stripe+Inc
GET /v1/companies/lookup?ein=123456789
GET /v1/brokers/lookup?name=Marsh+%26+McLennanDomains are normalized (protocol, www., trailing slash removed). For bulk lookup, use POST /v1/companies/batch (up to 100 domains/EINs) or POST /v1/personnel/batch (up to 50 company EINs).
Lookup vs cf[name]= — when to use which
lookup does three things cf[] doesn't: (1) normalizes domains, (2) returns 404 (not an empty list) when nothing matches, (3) returns 400 with suggestions when multiple entities match. Use lookup for record-matching workflows where "exact, single result" is the goal. Use cf[company_name]=...when you want a list response shape (even if it's a list of one).
Personnel is cf[]-only. There's no /personnel/lookup endpoint, so reverse-lookup by email or LinkedIn URL goes through cf[email_address]= / cf[person_linkedin_url]= on the list endpoint. See Personnel → Reverse lookup for the full recipe.
Relationship filters match history, not current
broker=, carrier=, and broker_office= match against any historical relationship the record has held — not just the primary/current. For "current Mercer clients only," filter the response client-side on primary_broker after the query. The same applies to primary_carrier and primary_broker_office.
Entity-specific filters
See each entity's reference page for its full filter list: