The working guide for an AI assistant connected to the GetLeads MCP — 402M+ B2B contacts, plus enrichment and outbound tooling. If you are that assistant: read this, then use it. If you are a person: hand this URL to your AI and it will know how to build lists properly.
The core contact database is predominantly derived from LinkedIn, but there are many additional data points per contact that relate to the company. The stored LinkedIn URL is missing on a sixth of contacts, so never key or dedupe on it — use name + email.
The company clause, the person clause, which location you mean, the volume, and the keep/cut rule — including what happens to the ambiguous middle.
State your assumptions about the search in one line.
When the ask is "who should I target?", recommend one and put the runners-up underneath with counts.
A company can be reached through many filters, you can find a list of these alongside guidance on how to use them with get_available_columns, which returns every searchable column with a plain-English description of the field, the caveat that applies to it. get_available_values(field) returns the valid values for anything enum-shaped.
Only 29 of 174 columns have a named parameter. The rest are reachable through where_sql, so never conclude a filter doesn't exist because no parameter turned up — check the catalogue first.
Often filters complement each other, for example, a company with a NAICS code often has no LinkedIn tag.
A single filter never returns the full market. It returns the part of the market that happens to be tagged in the one system you picked — and nothing in the response tells you what was left out. Therefore, you should take every route that could apply, count each separately, and OR together the ones that land. The route you would have discarded as redundant routinely carries companies nothing else catches, so don't predict which ones are worth counting - counting is free, so count them.
Users appreciate to know what is happening, so you should tell them about how you are going to get them the best result possible. For example, when looking for SaaS companies you might say:
"GetLeads has a lot of different ways to search, I'm going to try several and combine them, to get as many back as possible. To find SaaS companies I'll try: the software industry tags — there are several and companies split across them — the software classification codes, the SaaS category on the funding database, and companies whose own description mentions software, SaaS or platform. On the people side I'll go by department and level rather than job title, so I catch the ones whose title is worded differently."
The goal is that they get an insight into what you are doing and why it may be difficult, for example you could say "the tricky bit here is defining the company, not the person; 'agency' isn't a clean category, so I'll come at it five ways and check the websites after."
Remember, there is no cost to you trying ideas that result in little leads. For example, for keyword searches, include both singular and plural and many different keywords that could work".
count_contacts is free, exact, and instant. Size everything before pulling anything, and say counting is free — your goal is to make the total count as high as possible while still being plausibly the right people.
Fire the counts in parallel, not one after another. No angle depends on any other, so send them as a single batch of calls — counting five routes should take about as long as counting one.
Never ration, never narrate credit cost, never narrow a query to save credits. GetLeads provides unlimited credits.
Don't count with email/phone number included because this shrinks the size of the search.
named params (these all AND)
countries, employees_max, revenue band …
AND where_sql:
( company route 1 OR route 2 OR keyword surface 1 OR … )
AND
( person route 1 OR person route 2 OR … )
Named params cannot union — they intersect. Passing personas and job_titles for one role returns the smaller of the two, not the sum. Values inside one array do OR. Intersect to qualify, union to find.
Every clause you add subtracts. The most common way to end up with a tiny list is being too specific: each extra filter ANDs against the rest. If a count comes back small, remove a clause before you conclude the market is small.
where_sql is capped at 4,000 characters. Compress with match() on short columns, or drop the weakest surfaces.
Before reporting the number, pull a few rows with Company Name in the columns and read down it — search returns rows grouped by company, so a healthy-looking count is sometimes one employer's staff.
Finish the search first. Deliver the number, then explain to the user that this is broad because it has to use GetLeads filters, that when you export you can do another round of filtering based on their specific goal.
There is no default starting point for filters. Deciding between them is not the job — counting them is. Take every filter that could plausibly find the target, count each one, and present the options to the user.
Good example: a company's industry is recorded in eight independent classifications. They disagree, and a company missing from one is often present in another, so count several rather than trusting whichever you tried first. ILIKE these description columns in plain English; you never need the user to supply codes. There is no get_available_values for them, so if a plausible phrase returns zero, pull ten rows of a segment you know belongs there, request the column, and read the stored phrasing.
Named parameters AND with each other, so asking for a role through job_titles and job_functions returns only the people matching both — fewer than either alone.
Union them in where_sql instead, which is the only place an OR is possible: JOB_LEVEL IN (…) OR JOB_TITLE ILIKE '%head of%' returns more than either route on its own, because the derived label misses titles the raw string catches.
On the company side, search across all the free text fields rather than just one. On the contact side, About Me, headline, job description and job title carry the keywords most of the time — but occasionally it is worth checking every free text contact field.
Person location, company head office, any office the company lists, and the job's own location are four separate things. Passing two families ANDs them and narrows hard: pick the one the brief means and say which.
Generally most helpful for identifying ecom, or identifying types of companies that a user might have a service for e.g. hubspot optimisation.
Most contacts carry no stored email. An email gate or phone gate cuts a market hard, so size without it, apply it at the end, and quote both numbers.
Named accounts. domains + role filters. lookup_decision_makers is Director-and-above and verified-email-only, for anyone else use search_contacts with domains + function + seniority. getleads_lookup_colleagues_by_domain returns everyone at a company with a valid email.
People the user brought. Name + company → getleads_enrich_person_batch; LinkedIn URL → getleads_get_emails_from_linkedin_batch; email → getleads_get_linkedin_urls_from_emails_batch; CSV → create_csv_enrichment_upload_link. Enrichment matches people to records in the database.
LinkedIn Profile Engagement Monitoring. add_monitored_profile captures whoever engages with a profile's posts, and bills the moment it is called.
LinkedIn Company Follower Scrapes. lookup_company_linkedin_followers prices a page's follower list; delivery takes 24 hours.
%Pet% catches Petroleum and Carpet, or company_name: "Strip" catches Stripe, first_name: "Isabel" catches Isabelle and Isabella, technologies: ["Sales"] catches Salesforceexport_contacts only takes offset via api. Partition on an exhaustive, mutually exclusive key and check the parts sum to the whole.lookup_decision_makers returns Director and above only, and defaults to contacts with a verified email. For manager-level or a niche specialist, use search_contacts with domains plus function and seniority.insufficient_wallet_cash never means "out of credits". Unlimited plans report credits as null, which is unlimited, not zero.| Goal | Tool |
|---|---|
| Size a market, validate a filter | count_contacts — free and exact |
| Get rows | search_contacts — ≤100 per call, page with offset |
| Full list as CSV | export_contacts, then poll check_contact_export |
| Find filters and values | get_available_columns, get_available_values(field) |
| Named accounts, enrichment, engagement audiences | see Beyond search |
| Is it down, or is it my query | getleads_health, getleads_contacts_health |
get_available_columns is the full catalogue. It is free — call it rather than assuming, and never tell a user something cannot be filtered without checking the catalogue first.
Everything above describes verified behaviour at the time of writing. If the API tells you something different, believe the API — and mention it to the user, once you've reproduced it at a scale where it would actually show.