TL;DR
- Smart lead generation means filtering by who fits and who is reachable first, then spending on the people left. It is a sizing step, a narrowing step and a verification step, not a bigger list.
- It takes about 20 minutes with a free API key. Sizing and counting cost 0 records.
- A full run on a 25-person sample spends about 50 LeadOcean records: 25 from search, 25 from enrich. The Free plan has 1,000 records for life.
Most "smart" lead generation tools add a score on top of a list. The part that saves money happens earlier: you decide who is worth a record before you pull anyone. That is what this guide does.
Related: best lead generation tools that actually work, lead generation tactics and predictive lead generation.
Prerequisites
- A LeadOcean account. Start free: no card, 1,000 records for life, 5 requests a second.
- An API key from the app, exported as
$LEADOCEAN_API_KEY. curlandjq. Or an MCP client: LeadOcean runs a hosted MCP server athttps://api.leadocean.io/mcpwith 13 tools, and the sizing tools are free.
export LEADOCEAN_API_KEY="paste-your-key-here"Step 1: Write the buyer as filters
Start with a filter set, not a keyword. A smart list is one you can describe in five fields.
Here is the example used in this guide: VPs and Directors in sales, at US companies with 51-200 employees, that run a CRM on their website.
| Field | Filter | Value |
|---|---|---|
| Seniority | jobLevel | VP, Director |
| Function | jobFunction | Sales & Business Development |
| Where | country | US |
| Size | employeeRange | 51-200 |
| Signal | technologyCategories | CRM |
The technology filter is the "smart" part. LeadOcean reads detected website technology for about 7.8M crawled sites, so a CRM on the site is a usable buying signal and costs nothing to add.
Enum values are exact strings. Check them before you guess:
curl -s "https://api.leadocean.io/v1/enums/job_function" \
-H "x-api-key: $LEADOCEAN_API_KEY" | jq '.data'Or ask the MCP tool leadocean_list_enum_values with name: "job_function". Both are free.
Step 2: Size the list before you pull it
Send the search with count=true as a query parameter and limit=1. It returns the total and spends nothing.
curl -s -X POST "https://api.leadocean.io/v1/people/search?count=true" \
-H "x-api-key: $LEADOCEAN_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"jobLevel": ["VP", "Director"],
"jobFunction": ["Sales & Business Development"],
"country": ["US"],
"employeeRange": ["51-200"],
"technologyCategories": ["CRM"],
"limit": 1
}' | jq '.meta'meta.total is capped at 100,000, which is fine for a list you want to narrow. meta.countOnly is true and data comes back empty.
Read the number as a decision. Too big to work, so add a filter. Too small to matter, so drop one. Zero, so check an enum value. This is where bad lead generation gets fixed, because it is free.
Step 3: Search the mailable slice
Now pull a page. Ask only for people whose email is worth sending to by setting emailStatus. Keep the first page at 25.
curl -s -X POST "https://api.leadocean.io/v1/people/search" \
-H "x-api-key: $LEADOCEAN_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"jobLevel": ["VP", "Director"],
"jobFunction": ["Sales & Business Development"],
"country": ["US"],
"employeeRange": ["51-200"],
"technologyCategories": ["CRM"],
"emailStatus": ["verified", "catch_all_valid"],
"limit": 25
}' > page1.json
jq '.meta' page1.jsonThe body is flat JSON and every filter is an array. limit runs 1 to 100. Paginate with the cursor from the previous response. One search pages to 10,000 rows, then meta.depthCapped is true and there is no nextCursor. Narrow the filters instead of walking the index.
A search page of 25 spends 25 records. An empty page spends none.
Step 4: Enrich and check the status
Search gives you the person. Enrich adds the detail you personalize with: current role, and since 2026-10-17 career history (past roles, education, certifications).
Enrich takes exactly one of linkedin_url, email, phone or person_id. There is no name plus domain lookup, so you search first, then enrich by the person_id each search row carries at meta.source_ids.person_id.
ID=$(jq -r '.data[0].meta.source_ids.person_id' page1.json)
curl -s -X POST "https://api.leadocean.io/v1/people/enrich" \
-H "x-api-key: $LEADOCEAN_API_KEY" \
-H "Content-Type: application/json" \
-d "{\"person_id\": \"$ID\", \"reveal_email\": true}"Past employers carry no company_id yet, so match them on company name. A person we hold nothing for is a 404 and costs nothing.
Then read email_status before you send. Bounces are not refunded or credited back, so the check is yours. Treat verified as send, catch_all_valid as send at lower volume, and everything else as a hold.
Step 5: Export the winners
Once the filter set returns people you would email, move off pages and export. Exports take up to 50,000 rows a request and 500,000 a day. Bulk CSV export is not on Free.
curl -s -X POST "https://api.leadocean.io/v1/exports" \
-H "x-api-key: $LEADOCEAN_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"name": "us-sales-leaders-crm",
"limit": 127,
"preset": "full",
"filters": {
"jobLevel": ["VP", "Director"],
"jobFunction": ["Sales & Business Development"],
"country": ["US"],
"employeeRange": ["51-200"],
"technologyCategories": ["CRM"],
"emailStatus": ["verified"]
}
}'The export body nests the search filters under filters and needs a limit. Each row costs one record, so set limit from your count.
Prefer clicks? The Exports page in the app has the same filter builder, a column picker, the record price before you start and a CSV download. Check the pricing page for what each plan includes.
What you get
The sizing step, run through the free leadocean_count_leads MCP tool on 2026-10-21 with the filters from Step 1:
{
"total": 127,
"totalIsExact": true,
"totalAll": 404,
"distinctCompanies": 70,
"credits": 0
}Read it this way. 127 people match and have a verified, catch-all-valid or catch-all email (the tool's default mailable slice). 404 match the same filters with no email condition. They sit at 70 companies. The run cost 0 records.
The enrich response shape, from the API reference (placeholder values):
{
"success": true,
"data": {
"profile_data": { "profile_full_name": "Jane Doe" },
"contact_data": {
"has_email": true,
"email_status": "verified",
"contact_emails": [{ "email": "jane.doe@acme.com", "type": "work", "status": "verified" }],
"contact_current_experiences": [{ "company_name": "Acme" }]
},
"resume_data": { "experiences": [], "educations": [] },
"meta": { "source_ids": { "person_id": "1234567890" } }
}
}The top-level blocks are the ones in api.leadocean.io/openapi.json. Values here are placeholders, not a real record. The reference does not list the keys inside resume_data, so print one response before you parse it.
Troubleshooting
| Error | Cause | Fix |
|---|---|---|
| 401 | Missing or wrong x-api-key header | Re-copy the key from the app and check $LEADOCEAN_API_KEY is exported in this shell |
| 429 | Above the plan's rate limit: 5 requests a second on Free, 200 on Agency | Wait the Retry-After seconds, then slow the loop |
| 402 | Out of records (Free has 1,000 for life) | Check GET /v1/usage, narrow the filters, or move to a paid plan |
Empty data with a total of 0 | A bad enum value, such as Sales instead of Sales & Business Development | Look up the exact string with GET /v1/enums or leadocean_list_enum_values |
meta.depthCapped is true | One search reached its 10,000-row page limit | Add a filter and search again, or export |
| Export refused | Over 50,000 rows a request or 500,000 a day, or on the Free plan | Split the filters into smaller exports, or use a paid plan |
FAQ
What is smart lead generation?
It is lead generation that decides who is worth contacting before it pulls any data. You filter by role, company size, location and a signal, check the list size for free, and spend records only on mailable people.
Do I need AI to do it?
No. The savings come from filters and verification. If you use an AI agent, LeadOcean's MCP server lets it run the same free counts and then the paid search, with OAuth sign-in and no key to paste.
How many records does a test run cost?
About 50 for the 25-person sample in this guide: 25 for the search page and 25 for the enrichments. Counts, enums, empty pages and enrichments that find nothing cost nothing.
Which plan do I need?
Free covers the guide with 1,000 records for life. Solo at $97 a month suits one person who exports CSVs. Agency at $497 a month suits teams, with 200 requests a second and 5 keys. See pricing.
Can I score leads?
LeadOcean returns the filters and the status fields. Scoring sits in your own code or CRM. LeadOcean does not score leads. A common version is a weighted sum of seniority, headcount band and the technology signal.
Size your next list free, then spend records only on people who fit
Free to start. No credit card. 1,000 records to spend whenever you like.
Get your free API key →