Filter on hasPhone to keep only people we hold a number for, then size the list. Sizing is free.
hasPhone is a search filter, so it costs nothing to apply. The numbers themselves come from the phone lookup or an export, which cost records.
The filter
| Filter | Type | Example values | Note |
|---|---|---|---|
hasPhone | boolean | true, false | true keeps people with a known number. false keeps people without one. |
reachable | enum | any, strict | Holding an email or a phone. strict also needs the email to be verified, catch_all_valid or catch_all. |
hasPhone says a number exists. It does not return it. To read the numbers, call find phone number per person or export with the phone columns.
Pair it with jobLevel, jobFunction and country to shape the list. The enum strings are exact: VP, Sales & Business Development, US.
How many you can reach
Three live counts from leadocean_count_leads, run on 2026-10-01. Each spent no records.
| Filters | People with a phone |
|---|---|
hasPhone true, jobLevel VP, jobFunction Sales & Business Development, country US | 252,990 |
hasPhone true, jobLevel C-Team, employeeRange 11-50, country GB | 50,190 |
hasPhone true, jobLevel Director, jobFunction Information Technology, continent Europe | 13,799 |
One caution on method. The same first query without hasPhone returned 115,336, and that run applied the tool's default mailable email filter. With hasPhone, the count was 252,990, and it did not change when we passed every email status. So treat these counts as people with a number, not as people with a number and a mailable email. Add reachable set to strict when you need both.
Run it from an AI agent
Connect the MCP server at https://api.leadocean.io/mcp (OAuth sign-in, no key pasted), then ask in plain words.
Find VP-level sales leaders in the US that we hold a phone number for. Size it first, then show me 25.
The agent counts first with the free tool, then calls leadocean_search_leads with this:
{
"hasPhone": true,
"jobLevel": ["VP"],
"jobFunction": ["Sales & Business Development"],
"country": ["US"],
"limit": 25
}The search costs 1 record per person returned. For one named person, use leadocean_find_phone. That costs 1 record.
Run it with the API
One flat JSON body to POST /v1/people/search. Filters are arrays of strings, and hasPhone is a boolean.
curl -X POST "https://api.leadocean.io/v1/people/search" \
-H "x-api-key: $LEADOCEAN_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"hasPhone": true,
"jobLevel": ["VP"],
"jobFunction": ["Sales & Business Development"],
"country": ["US"],
"limit": 25
}'For the free sizing call, put count=true in the URL (not the body) and set limit to 1.
curl -X POST "https://api.leadocean.io/v1/people/search?count=true" \
-H "x-api-key: $LEADOCEAN_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"hasPhone": true,
"jobLevel": ["VP"],
"jobFunction": ["Sales & Business Development"],
"country": ["US"],
"limit": 1
}'data comes back empty and meta.countOnly is true. meta.total stops at 100,000 on the REST API, so the first count above reads as a floor there. The MCP count tool returned the exact figure.
Export the list
POST /v1/exports takes the same filters inside a filters object. One export is up to 50,000 rows, and an account can export 500,000 rows a day.
curl -X POST "https://api.leadocean.io/v1/exports" \
-H "x-api-key: $LEADOCEAN_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"name": "us-vp-sales-with-phone",
"filters": {
"hasPhone": true,
"jobLevel": ["VP"],
"jobFunction": ["Sales & Business Development"],
"country": ["US"]
},
"limit": 5000,
"columns": ["profile_full_name", "current_job_title", "current_company_name", "phone_N_number", "phone_N_type"],
"caps": {"phones": 2}
}'Phone columns need the enrich scope. The CSV headers come back as phone_1_number, phone_2_number. The phone_N_dnc column exists but is not populated yet, so null means unknown, never safe to call.
Poll GET /v1/exports/{id}, then download. Prefer clicking? The Exports page in the app at app.leadocean.io has the filter builder, a column picker, the record price before you start, and a CSV download.
Combine it
- Add
jobLevelandjobFunctionto reach one buyer. See how to find a VP of Sales phone number. - Add
countryorcontinentto stay inside the regions you are allowed to call. The second and third counts above do this. - Add
employeeRange(for example["11-50"]) to pick a company size, as in the GB count above.
More ways to build a people list are on the find people hub. To run the lookup from Claude, use the find phone number skill.
FAQ
Does hasPhone return the phone numbers?
No. It filters to people we hold a number for. Read the numbers with GET /v2/people/phone, leadocean_find_phone or an export with the phone columns.
How many phone numbers does each person have?
Up to 2 in an export by default, set with caps. The lookup returns every number we hold, best first, each with a type.
Can I trust the do-not-call flag?
Not yet. dnc is published on every number but is not populated. Null means unknown. Check your own suppression lists before you dial.
What does it cost?
Counting is free, as are list_filters and list_enum_values. A search or export row costs 1 record per person. The free plan has 1,000 records, one-off, no card. Pro is $499 a month. See pricing.
Size your phone-number list for free, then pull it
Free to start. No credit card. 1,000 records to spend whenever you like.
Get your free API key →