Fiber AI
Search & discovery

Getting accurate results from search

Write people and company searches that return exactly the people you mean — the rules that matter, what's available today, and worked examples of common mistakes with their fixes.

Getting accurate results from search

Most "missing results" in a search aren't missing — the request asked for something narrower than intended. A seniority that doesn't cover owners, one industry name where five apply, a revenue filter on companies that don't publish revenue. This page shows how each filter actually matches, what's available today, and the request patterns that return what you mean, with worked examples you can copy.

Running a large analysis or comparing Fiber with another data provider? Read the checklist and comparing providers first. Most gaps in side-by-side tests come from how the requests were translated, and each one has a fix below.

Checklist

  1. Read warnings on every response. Unknown filters inside searchParams are rejected with 400; unknown top-level fields are dropped and reported in warnings. See validation.
  2. Send owner, partner and intern levels as title words, not c-suite. See levels.
  3. Express a department as a keyword list in a functional block. See departments.
  4. Use every industry name that applies, spelled exactly as the industries list (GET /v1/enums/industries) returns it. See industries.
  5. Put the industry on the company side with combined search when you mean "people at companies in X": employer filters combine with the rest of your company conditions. See industries.
  6. Use employee count, not revenue, to size small companies.
  7. Choose exact or non-exact titles on purpose.
  8. Set sort when you page through results.
  9. Pass getFastEstimate: false when you need an exact combined count.
  10. Compare the people, not just the counts, when you benchmark.

What's available today

The table is the quick reference; each row links to the details.

You want to filter onHow to express it todayStatus
A job titlejobTitleV3 with plain terms, exact or non-exactAvailable
A seniority leveljobSeniority — six levels, or a functional blockAvailable
Owner, partner, intern, entry levelTitle words in jobTitleV3Workaround
A department (finance, legal, …)jobFunction — 44 values, or a keyword list in a functional blockAvailable
Past or any job, not just the current onejobStatusAvailable
Words anywhere on a profile, or only in titleskeywordsV2 with options.fieldsToSearchOverAvailable
The person's own industryindustry (people search)Available
The employer's industrylinkedinIndustries or industriesV2 (combined search)Available
Employer sizeemployeeCountV2 — any rangeAvailable
Employer revenuerevenueRangeUSD — one rangeAvailable, limited for small companies
Companies in a cityheadquartersLocation free-form-city + radiusAvailable
Attributes of a past employerCombined search + jobStatus: previously-employedAvailable, read the caveat
Employer domain and industry on each resultgetDetailedWorkExperience: trueAvailable
A person from an email or phone numberReverse lookupAvailable
Stable pagessort + cursorAvailable
Exact countsCount endpoints; getFastEstimate: false for combinedAvailable
Several size or revenue ranges, size/revenue excludes—Not yet
Gender and other protected characteristics—Not offered
Email, phone or social profile as a search filterUse reverse lookup insteadNot offered as a filter

Job titles

Job title filters match the person's current job by default (see current, past or any job). Each plain term matches one of two ways:

SettingMatchesExample: term customer success manager
exact: trueThe whole title equals the term (case ignored)"Customer Success Manager" — not "Senior Customer Success Manager"
exact: false (default)Every word of the term appears in the title, in any order, including common synonyms"Customer Success Manager", "Senior Customer Success Manager", "Manager, Customer Success"
  • Use exact: true for like-for-like comparisons with a system that matches normalized titles exactly, or when a word order matters.
  • Use exact: false for reach. In our tests, the non-exact version of a common title returned about twice as many people, all holding that role.
  • Add abbreviations and alternate spellings as extra terms ("O&M manager", "CSM") when you rely on them: it's the reliable way to cover every form.

Seniority and levels

People search also has a direct seniority filter, jobSeniority — six values: Entry level, Associate, Mid-Senior level, Director, Executive and Internship. For owner, partner and intern audiences it's not enough on its own; the functional block below covers what the filter can't.

A functional block generates the common title forms for a seniority and an optional list of keywords: ["vp"] with ["sales"] covers "VP of Sales", "Vice President, Sales", "VP Sales" and similar.

Seniority valueCovers titles like
c-suiteChief … Officer, CEO, CTO, CFO, Founder, Co-Founder
svp, vpSenior Vice President …, Vice President …, VP …
headHead of …
directorDirector of …, … Director
manager… Manager, Manager of …
lead, principal, staff, seniorLead …, Principal …, Staff …, Senior …

There is no owner, partner, entry or intern seniority. c-suite covers "Chief … Officer" and founder titles only, so owners of small businesses and partners at firms are missed. Add them as title words next to the functional block.

"jobTitleV3": {
  "anyOf": [
    { "type": "functional", "seniority": ["c-suite"] },
    { "type": "plain", "term": "owner", "exact": false },
    { "type": "plain", "term": "co-owner", "exact": false },
    { "type": "plain", "term": "partner", "exact": false },
    { "type": "plain", "term": "managing partner", "exact": false },
    { "type": "plain", "term": "principal", "exact": false }
  ]
}

For entry-level roles use terms such as intern, trainee, junior, graduate and apprentice.

Departments

Departments have a dedicated filter on people search, jobFunction: 44 values from Accounting to Writing / Editing. The mapping from another provider's department values is in migrating from another data provider.

The keyword-list method below still earns its keep when a department's roles are titled inconsistently: one keyword covers only titles containing that word; a list covers the ways that department's roles are actually titled.

DepartmentKeywords
Financefinance, financial, accounting, controlling, controller, treasury, tax, audit
Legallegal, legal affairs, compliance, counsel, contracts, regulatory affairs
Supportsupport, customer support, customer service, customer care, customer success, technical support, help desk
Creativecreative, design, art, art director, content, video, graphic design, ux, copywriting
Human resourceshuman resources, hr, people, talent, talent acquisition, recruiting, recruit, personnel
Operationsoperations, supply chain, logistics, production, manufacturing, procurement, plant, facilities
Salessales, business development, commercial, account management, account executive
Marketingmarketing, brand, growth, communications, digital marketing, product marketing
Engineeringengineer, engineering, software, developer, technology
  • Add local-language words for non-English markets (for example "Leiter", "Directeur", "Gerente").
  • A broader list trades a little precision for reach: check a page of results before you run a large pull.

Current, past or any job

Titles and company filters apply to the current job unless you set jobStatus:

jobStatusMatches
omitted, or { "status": "currently-employed" }The person's current job
{ "status": "previously-employed" }A past job (optionally with leftAt)
{ "status": "ever-employed" }Any job, current or past

A title search over any job typically returns two to three times as many people as the current-job default.

Keywords

keywordsV2 matches phrases: the words of each term, in order, case ignored. By default it searches most of a profile: headline, summary, current and past titles, skills, education and more. That's right for "mentions X anywhere"; for "works as X", limit it to titles:

"keywordsV2": {
  "clauses": [{ "terms": ["machine learning"], "operator": "OR" }],
  "options": { "fieldsToSearchOver": { "currentJobTitles": true, "summary": false, "headline": false, "pastJobTitles": false, "pastJobSummaries": false, "pastCompanyNames": false, "currentJobSummaries": false, "currentCompanyNames": false, "interests": false, "skills": false, "industry": false, "education": false, "publications": false, "certifications": false, "articles": false, "courses": false, "projects": false, "patents": false, "volunteering": false, "languages": false } }
}

Terms in one clause combine with operator (OR by default); clauses combine with AND; negate: true excludes a clause. Keywords don't match inside words — "eng" won't match "engineer".

Industries

Two different filters are called "industry":

FilterWhat it isWhere
industryThe industry on the person's own profilePeople search
linkedinIndustriesThe employer's industry, using current LinkedIn industry namesCompany search, combined search (companyParams)
industriesV2The employer's industry in Fiber's broader standard categoriesCompany search, combined search (companyParams)
  • For "people at companies in an industry", use combined search with linkedinIndustries or industriesV2: the industry then applies to the employer and combines with the rest of your company conditions in one query.
  • One broad industry often spans several current names. Retail, for example, includes Retail, Retail Groceries, Online and Mail Order Retail, Retail Apparel and Fashion and more. Send all of them.
  • Get names from the industries list (GET /v1/enums/industries, free). It returns every valid name with its company count, so you can drop names that match no companies.
  • industriesV2 is the quick way to a broad category; linkedinIndustries is precise.

The full picture, including how to pick values that actually match companies, is in industry filtering.

linkedinIndustries values must match exactly. A misspelled or retired name (for example the older "Computer Software" instead of "Software Development") returns zero people with no error or warning. Build your lists from the industries list.

Company size and revenue

  • employeeCountV2 takes one range: { "lowerBoundExclusive": 10, "upperBoundInclusive": 200 }: arbitrary bounds, not just preset bands. Watch the boundary rule: the lower bound is exclusive, except 0, which is inclusive. Details and examples: sizing and locating companies.
  • revenueRangeUSD takes one range: { "lowerBound": 1000000, "upperBound": 10000000 }. It matches companies whose revenue figure falls in the range.

A revenue filter only returns companies that have a revenue figure. Many small and private companies don't publish one, so revenue filters on small companies return a small share of them. To target small businesses, filter on employee count instead.

Company filters in combined search reach people whose current employer Fiber has identified. For broad sizing, compare a combined count with the same people search without company filters.

Past employers

To find people by what a past employer looked like (its industry, size, location), use combined search with profileParams.jobStatus set to previously-employed. The title and company conditions then apply to the same past job.

This matches a past job entry, not "has left". Someone who held the role earlier at the same company, and still works there, also matches. If you need people who have left, check the current job in the results.

Employer details on each person

Set getDetailedWorkExperience: true in people search to get detailed_work_experiences, where each job carries company_details: the employer's domains, LinkedIn org ID and industries. No extra charge, and no separate company lookup per employer.

Validation, errors and warnings

You sendYou get
An unknown field inside searchParams, profileParams or companyParams (for example gender, or a typo)400 — Unrecognized key(s) in object: 'gender'
An invalid value for a fixed list (a person industry, a country code)400 listing the valid values
An unknown top-level field (for example includeCounts instead of includeCount)200 — the field is ignored and reported in warnings
A misspelled free-text value (linkedinIndustries names)200 with zero results, no warning

A top-level typo still returns results, so it's easy to miss:

{
  "output": { "data": ["…"], "nextCursor": "…" },
  "warnings": [
    {
      "field": "includeCounts",
      "message": "You passed an extraneous field 'includeCounts'. Did you mean to pass this field somewhere else? …"
    }
  ]
}

Fail loudly on warnings in your integration:

const res = await fetch("https://api.fiber.ai/v1/people-search", { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify(body) });
const json = await res.json();
if (!res.ok) throw new Error(json.message);
if (json.warnings?.length) throw new Error(`Search warnings: ${JSON.stringify(json.warnings)}`);
res = requests.post("https://api.fiber.ai/v1/people-search", json=body)
res.raise_for_status()
if res.json().get("warnings"):
    raise RuntimeError(f"Search warnings: {res.json()['warnings']}")

Prefer the current fields: jobs instead of pastJobs/currentJobs, jobTitleV3 instead of jobTitle/jobTitleV2, keywordsV2 instead of keywords.

What search doesn't filter on

  • Gender and other protected characteristics are not available as search filters.
  • Email, phone and social profiles aren't search filters. To go from an email or phone number to a person, use reverse lookup (the reverse email and reverse phone operations, linked from the operations index).
  • Several size or revenue ranges, or size/revenue excludes, aren't supported yet. Run one search per range, or use a single wider range. Industry and country filters do support excludes (noneOf).
  • Natural-language search reports anything it can't express in unsupportedFilters.

Counting

  • includeCount: true on a search and the matching count endpoints return the same number. Counts cover all matches — they aren't capped.
  • The combined count operation estimates the people count by default. Pass getFastEstimate: false for an exact number when you report or compare results; it takes a little longer. The response's isEstimate flag tells you which mode produced the number.
  • Exclusion lists apply to results, not to counts.

Caching, what counts skip, and the fair-benchmark recipe are in search counts.

Paging

Set sort whenever you page. Without it, results have no guaranteed order, and the same person can appear on two pages. With sort, page order is stable.

{
  "searchParams": {
    "country3LetterCode": { "anyOf": ["USA"] },
    "jobTitleV3": { "anyOf": [{ "type": "functional", "seniority": ["vp"], "keywords": ["sales"] }] },
    "sort": [{ "field": "followerCount", "direction": "desc" }]
  },
  "pageSize": 100
}

Pass nextCursor from each response as cursor in the next request, with the same searchParams. See pagination.

Comparing Fiber with another provider

  1. Translate vocabularies deliberately. Levels (owner/partner as title words), departments (keyword lists), industries (every current name, on the employer). The translation tables are in migrating from another data provider.
  2. Match semantics. Exact vs non-exact titles; current job vs any job; country vs radius vs state.
  3. Use exact counts (getFastEstimate: false) and read warnings on every call.
  4. Sample the people. Pull 25 or more profiles from each side for the same search and check they're the people you meant. A bigger number isn't automatically better — and a smaller one isn't automatically missing data.
  5. Report per filter type, not one blended number.
  6. Send us your request bodies if a result looks off — we'll help you write them.

Worked examples

Each example shows a request that looks right, what goes wrong, and the fix.

Partners at small accounting firms

Looks right: combined search, linkedinIndustries: ["Accounting"], employees ≤ 50, seniority c-suite.

What goes wrong: partners and owners aren't a seniority, so the search returns only "Chief …" and founder titles.

Fix: keep c-suite and add owner/partner title words — the corrected request returned nearly three times as many people.

{
  "companyParams": {
    "linkedinIndustries": { "anyOf": ["Accounting"] },
    "employeeCountV2": { "lowerBoundExclusive": 0, "upperBoundInclusive": 50 }
  },
  "profileParams": {
    "country3LetterCode": { "anyOf": ["USA"] },
    "jobTitleV3": {
      "anyOf": [
        { "type": "functional", "seniority": ["c-suite"] },
        { "type": "plain", "term": "owner", "exact": false },
        { "type": "plain", "term": "partner", "exact": false },
        { "type": "plain", "term": "managing partner", "exact": false },
        { "type": "plain", "term": "principal", "exact": false }
      ]
    }
  }
}

Looks right: functional with seniority head, director, vp and keywords ["legal"].

What goes wrong: only titles containing "legal" match; "VP, Compliance" and "Director of Regulatory Affairs" don't.

Fix: a department keyword list — about five times as many people, all legal and regulatory leaders.

"jobTitleV3": {
  "anyOf": [{
    "type": "functional",
    "seniority": ["head", "director", "vp"],
    "keywords": ["legal", "legal affairs", "compliance", "counsel", "contracts", "regulatory affairs"]
  }]
}

Product leaders at software companies

Looks right: linkedinIndustries: ["Computer Software"].

What goes wrong: that name is retired, so the search returns zero — with no error.

Fix: current names from the industries list (GET /v1/enums/industries): ["Software Development", "Desktop Computing Software Products", "Mobile Computing Software Products", "Embedded Software Products"].

Managers at banks

Looks right: people search with industry: { "anyOf": ["Banking"] }.

What goes wrong: that's the industry on the person's own profile. It answers "people who describe themselves as banking", not "people who work at companies in banking" — and only the employer's industry combines with company conditions like size or location.

Fix: combined search with the employer's industry:

{
  "companyParams": { "linkedinIndustries": { "anyOf": ["Banking"] } },
  "profileParams": {
    "country3LetterCode": { "anyOf": ["FRA"] },
    "jobTitleV3": { "anyOf": [{ "type": "functional", "seniority": ["manager", "director"] }] }
  }
}

Founders of small companies

Looks right: revenueRangeUSD: { "lowerBound": 0, "upperBound": 5000000 }.

What goes wrong: most small companies have no revenue figure, so they're left out.

Fix: size by headcount — employeeCountV2: { "lowerBoundExclusive": 0, "upperBoundInclusive": 20 } returned dozens of times more founders.

Customer success managers

Looks right: { "type": "plain", "term": "customer success manager", "exact": true }.

What goes wrong: exact matching skips "Senior Customer Success Manager" and "Manager, Customer Success".

Fix: "exact": false — about twice as many people, all in the role.

"Machine learning" people

Looks right: keywordsV2 with ["machine learning"].

What goes wrong: keywords search the whole profile, so founders, speakers and managers who mention machine learning match too.

Fix: limit to currentJobTitles when you mean "works as" — the results become machine learning engineers. Keep all fields when you mean "has experience with".

Anyone who has been a product designer

Looks right: plain term "product designer".

What goes wrong: titles match the current job only.

Fix: add "jobStatus": { "status": "ever-employed" } — about two and a half times as many people.

A typo that fails silently

Looks right: "includeCounts": true next to searchParams.

What goes wrong: the response is 200 with results but no count; the field is listed in warnings.

Fix: "includeCount": true — and treat any warnings as an error.

Cost and rate limits

OperationRate limit (per minute)
peopleSearch, peopleSearchCount180
companySearch, companyCount180
combinedSearchCount120
paginatedCombinedSearch30
Typeaheads240
getIndustries and other lists120 (free)

Searches are billed per result returned; see Billing and search cost. Every response's chargeInfo is the authoritative record of what a call cost.

On this page