Back to blog
6 min read

People Search API: Exact Match vs Text Search

By Kooperativa Engineering

The most common integration mistake we see with people search filters is not a malformed request, it is a request that returns zero results with no error, because one field is being treated as a text search when it is actually an exact match.

first_name and last_name filters are exact matches. Send "Rob" against a profile whose first name is stored as "Robert" and you get nothing back, not a partial match, not a fuzzy match, nothing. full_name, by contrast, is a genuine text search, and it behaves differently in a specific way worth knowing.

How the text-search fields actually match

For full_name and title, the last word in the query is treated as a prefix rather than a whole word. That means "engin" matches both "engineer" and "engineering", which is useful, but it also means multi-word queries require every word to be present somewhere in the field. "chief marketing officer" will not match a profile whose title is just "marketing manager", because "chief" and "officer" are both missing.

A filtered search request

Combining several filters at once looks like this. Location has to be an ISO 2-letter country code, not a full country name, which is the second most common source of an empty result set:

POST /api/v1/people/search with combined filtersbash
curl -X POST "https://kooperativa.io/api/v1/people/search" \
  -H "Authorization: Bearer ik_live_..." \
  -H "Content-Type: application/json" \
  -d '{
    "title": "engineer",
    "location": ["US", "GB"],
    "seniority": "manager",
    "industry": "Computer Software",
    "skills": ["Leadership"],
    "per_page": 50
  }'

Filters that are exact even though they look like free text

skills, past_company, and education all match a whole stored value rather than a substring. A profile whose only listed skill is "Leadership Development" will not match a filter for "Leadership", because those are two different stored strings, not one string containing the other.

This is a deliberate tradeoff, not an oversight: exact matching on these fields keeps a search for a specific skill from accidentally pulling in every tangentially related one. The cost is that it requires knowing the exact value as stored, which is rarely obvious in advance for fields like skills or education.

The practical fix

When a filter has an ID variant available, company_id instead of company, education_id instead of education, prefer it. Names drift across profiles ("NYU" versus "New York University" for the same school), IDs do not. company_id comes back on every enrich response, so the pattern that avoids this whole class of bug is: enrich once, cache the ID, filter by ID from then on.

Get started

Try Kooperativa

One API key. Person and company enrichment, structured search, and monitors under one flat license.

Keep reading