A rep needs three things: a sized territory, a ranked list of people, and one enriched contact before each call. You can get all three from four API requests, and sizing costs nothing.
Clay pitches this as waterfall enrichment across many providers, a Chrome extension partner (Exportly) and pushes to a CRM or sequencer (Clay rep prospecting page, October 2026). LeadOcean has none of those tools. It is the data layer, so this guide is for the rep or RevOps engineer who wants the list as JSON or CSV.
TL;DR
- Total time: about 20 minutes. The example territory is IT directors and VPs at German companies with 201-500 employees.
- Records spent: about 101. The count is free, one search page of 100 is 100 records, and one enrichment is 1 record.
- The Free plan (1,000 records for life, no card) covers it with 899 records to spare.
Prerequisites
- A LeadOcean API key from app.leadocean.io/register, exported as
$LEADOCEAN_API_KEY. curlandjq.- A territory written as filters: country, job level, job function, company size.
Step 1: Size the territory (free)
Send count=true as a query parameter with limit=1. The call returns a total and spends no records. The body is flat JSON and every filter is an array.
curl -s -X POST "https://api.leadocean.io/v1/people/search?count=true&limit=1" \
-H "x-api-key: $LEADOCEAN_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"country": ["DE"],
"jobLevel": ["VP", "Director"],
"jobFunction": ["Information Technology"],
"employeeRange": ["201-500"]
}' | jq '.meta'meta.total is capped at 100,000. If the number is too big for one rep, add a filter. If it is zero, check the enum spelling (see Troubleshooting).
You can run the same count from an AI client with the leadocean_count_leads MCP tool. For the account side, leadocean_count_companies sizes the company list for free.
Step 2: Pull the first page of people
Now spend records. limit runs 1 to 100, so one page of 100 costs 100 records.
curl -s -X POST "https://api.leadocean.io/v1/people/search" \
-H "x-api-key: $LEADOCEAN_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"country": ["DE"],
"jobLevel": ["VP", "Director"],
"jobFunction": ["Information Technology"],
"employeeRange": ["201-500"],
"limit": 100
}' > page1.json
jq '.meta, (.data | length)' page1.json
jq -r '.data[].meta.source_ids.person_id' page1.json > ids.txtCheck the length before you read rows. Only people you receive count. This body has no email condition, so it returns people with and without a mailable address. Add "emailStatus": ["verified", "catch_all_valid", "catch_all"] to pull only the mailable ones.
Step 3: Page through with a cursor
Take the cursor from the last response and send it back with the same filters.
CURSOR=$(jq -r '.meta.nextCursor // empty' page1.json)
curl -s -X POST "https://api.leadocean.io/v1/people/search" \
-H "x-api-key: $LEADOCEAN_API_KEY" \
-H "Content-Type: application/json" \
-d "{
\"country\": [\"DE\"],
\"jobLevel\": [\"VP\", \"Director\"],
\"jobFunction\": [\"Information Technology\"],
\"employeeRange\": [\"201-500\"],
\"limit\": 100,
\"cursor\": \"$CURSOR\"
}" > page2.jsonOne search pages to 10,000 rows. The last page sets meta.depthCapped to true and has no cursor. Narrow the filters instead of walking the index. For a CSV of the whole list, use the Exports page in app.leadocean.io (filter builder, column picker, price preview, download). Bulk CSV export is not on Free.
Step 4: Enrich one contact before the call
Enrich takes exactly one of linkedin_url, email, phone or person_id. Take a person_id from ids.txt (each search row carries it at meta.source_ids.person_id). Set reveal_email to get the address back.
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": "PERSON_ID_FROM_STEP_2", "reveal_email": true}' \
| jq '{role: .data.contact_data.contact_current_experiences, history: .data.resume_data, status: .data.contact_data.email_status}'Since 2026-10-17 the response includes career history: past roles, education, certifications and awards. Past employers carry no company_id yet. An enrichment that finds nobody is a 404 and costs nothing. A phone number is a separate call to GET /v2/people/phone, and v2 contact calls cost one record each, including a miss.
What you get
The territory count, run with the free leadocean_count_leads MCP tool on 2026-10-21 (mailable people only, the tool default of verified, catch_all_valid and catch_all):
{
"filters": "country DE, jobLevel VP or Director, jobFunction Information Technology, employeeRange 201-500",
"total": 208,
"totalIsExact": true,
"totalAll": 679,
"distinctCompanies": 189
}So 208 people with a mailable address across 189 employers. totalAll (679) is the same filters with no email condition.
The company side, from the free leadocean_count_companies tool on 2026-10-21: companies headquartered in Germany with 201-500 employees and at least one person with a mailable address number 3,221. The top industry is IT Services and IT Consulting at 193, then Software Development at 115.
A search response has this shape (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_current_experiences": [{ "company_name": "Acme" }]
},
"resume_data": {},
"meta": { "source_ids": { "person_id": "1234567890" } }
}
],
"meta": { "count": 1, "limit": 100, "nextCursor": "...", "depthCapped": false }
}Troubleshooting
| Error | Cause | Fix |
|---|---|---|
| 401 | Missing or wrong x-api-key header | Check $LEADOCEAN_API_KEY is exported and sent in the x-api-key header |
| 429 | Above the plan's rate limit (5 requests a second on Free, 200 on Agency) | Honor the Retry-After header and slow the loop |
| 402 | Out of records (Free is 1,000 for life) | Move to Solo ($97 a month) or Agency ($497 a month). A 402 costs nothing |
| Empty results | Enum value spelled wrong, such as "vp" instead of "VP" | Check exact values with leadocean_list_enum_values or GET /v1/enums |
meta.depthCapped is true | One search reached 10,000 rows | Add filters and split the territory |
| Export refused | Over 50,000 rows a request or 500,000 a day, or on Free | Split the export; bulk CSV is not on Free |
FAQ
How many records does a rep list cost?
One record per person you receive. The example filters match 679 people, 208 of them mailable. Pulling only the mailable ones costs about 208 records. Counts, breakdowns and empty pages are free.
Can a rep use this without writing code?
Yes, partly. The Exports page in app.leadocean.io builds the filter, shows the record price first, and downloads a CSV. The CSV then goes to your own tools.
How is this different from Clay's rep workflow?
Clay chains multiple providers and pushes to a CRM or sequencer from one workspace. LeadOcean is one data source behind one API with flat pricing. If you already have a sending tool and want the list, the API is shorter. See integrations and customization.
How do I find more accounts like my best customers?
Start from the filters your best accounts share and widen one at a time. The lookalike prospecting guide covers it.
Size your territory free, then pull the list
Free to start. No credit card. 1,000 records to spend whenever you like.
Get your free API key →