TL;DR
- GTM teams need four things from a data source: a free size check, a small test pull, verified emails for the best rows and a bulk export. Each is one request below.
- It takes about 30 minutes. The example spends about 35 of your 1,000 free records: 25 for the pull, 10 for email reveals.
- Counts, filter lookups and enum lookups cost nothing. Only people you receive count as records.
Prerequisites
- A LeadOcean account. The free plan has 1,000 records for life, no card and 5 requests a second.
- An API key from app.leadocean.io, exported as
$LEADOCEAN_API_KEY. curlandjq. Python 3 is optional for the loop in step 3.- A written ICP: job level, function, country and company size.
- A paid plan only for step 4. Bulk CSV export is not on Free. It is included on Solo ($97 a month) and Agency ($497 a month).
export LEADOCEAN_API_KEY="paste-from-app-leadocean-io"
curl -s https://api.leadocean.io/v1/account -H "x-api-key: $LEADOCEAN_API_KEY"The account call is free. It shows your plan and the records you have left.
Step 1: Size the list before you spend anything
A people search with count=true and limit=1 returns a total and no rows. It costs nothing. Send count as a query parameter, not in a JSON body.
curl -s -G https://api.leadocean.io/v1/people/search \
-H "x-api-key: $LEADOCEAN_API_KEY" \
--data-urlencode "jobLevel=VP" \
--data-urlencode "jobFunction=Sales & Business Development" \
--data-urlencode "country=US" \
--data-urlencode "emailStatus=verified,catch_all_valid,catch_all" \
--data-urlencode "count=true" \
--data-urlencode "limit=1" | jq '.meta | {total, totalIsExact, countOnly, distinctCompanies}'meta.total stops at 100,000. If totalIsExact is false, treat the number as a floor. The same filters in the MCP tool leadocean_count_leads return an uncapped count with breakdowns.
Sizing companies works the same way. GET /v1/companies/count takes the company-search filters and returns an exact total with breakdowns by industry, headcount band, HQ country, HQ state and NAICS.
curl -s -G https://api.leadocean.io/v1/companies/count \
-H "x-api-key: $LEADOCEAN_API_KEY" \
--data-urlencode "industry=Software Development" | jq '.data | {total, facets}'Enum filters are exact strings. Look them up first with GET /v1/enums/job_function or the leadocean_list_enum_values tool.
Step 2: Pull a small batch of people
Pull 25 rows to check fit before you commit volume. The search body is flat JSON, filters are arrays, limit runs 1 to 100 and paging uses a cursor.
curl -s https://api.leadocean.io/v1/people/search \
-H "x-api-key: $LEADOCEAN_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"jobLevel": ["VP"],
"jobFunction": ["Sales & Business Development"],
"country": ["US"],
"emailStatus": ["verified", "catch_all_valid", "catch_all"],
"limit": 25
}' > people.json
jq '{rows: (.data | length), nextCursor: .meta.nextCursor}' people.jsonSearch rows are thin: profile, current role and email flags. Each row carries a person_id at meta.source_ids.person_id. Step 3 uses it.
To start from a target account instead, call GET /v1/companies/acme.com/people. It lists people at one domain and stops at 10,000 rows.
Step 3: Reveal work emails for the best rows
Enrich takes exactly one of linkedin_url, email, phone or person_id. There is no name plus domain lookup, so search first and enrich by person_id. Set reveal_email to true to get the address. It costs no extra record.
import json, os, requests
H = {"x-api-key": os.environ["LEADOCEAN_API_KEY"]}
rows = json.load(open("people.json"))["data"][:10]
with open("enriched.jsonl", "a") as out:
for r in rows:
pid = r["meta"]["source_ids"]["person_id"]
res = requests.post("https://api.leadocean.io/v1/people/enrich",
headers=H, json={"person_id": pid, "reveal_email": True})
if res.status_code == 404: # nobody matched, costs nothing
continue
res.raise_for_status()
out.write(json.dumps(res.json()) + "\n")Ten reveals spend 10 records. An enrichment that finds nothing is a 404 and costs nothing. Since October 2026 the response also carries career history: past roles, education and certifications. Past employers have no company_id yet.
Read email_status before you send. LeadOcean does not refund or credit back bounced emails.
Step 4: Export the full list for your sequencer or CRM
Once the 25-row sample looks right, export. POST /v1/exports takes the same filters as search. It takes up to 50,000 rows a request and 500,000 a day. This needs Solo or Agency.
curl -s https://api.leadocean.io/v1/exports \
-H "x-api-key: $LEADOCEAN_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"name": "US sales VPs, mailable",
"filters": {
"jobLevel": ["VP"],
"jobFunction": ["Sales & Business Development"],
"country": ["US"],
"emailStatus": ["verified", "catch_all_valid", "catch_all"]
},
"limit": 5000
}'You can also run the same export in the app at app.leadocean.io. The Exports page has a filter builder, a column picker, the record price before you start and a CSV download. Load the file into your own sequencer or CRM. LeadOcean supplies the data. It has no sequencer, dialer, CRM or Chrome extension.
Step 5: Let the team ask in plain language
Ops and sales people who do not write curl can use the hosted MCP server. It uses OAuth sign-in, so no key is pasted. Add it in Claude Code with one command (Claude Code MCP docs).
claude mcp add --transport http leadocean https://api.leadocean.io/mcpThen ask for a count first. This prompt spends no records.
Use leadocean_count_leads for VPs in Sales & Business Development in the US.
Do not search or look up any person. Return the total and the top 5 industries.leadocean_count_leads, leadocean_list_filters and leadocean_list_enum_values are free. leadocean_search_leads, leadocean_get_lead and leadocean_export_leads spend records, so tell the agent to stop and ask before it calls them.
Choosing the route
Use the API when a script or an enrichment job calls the data. Use the app Exports page when a RevOps person needs a CSV today and wants the record price shown first. Use MCP when the question is "how big is this segment" and a person is typing it.
Keep one rule across all three: size first, sample 25, then scale. A bad enum value or a wrong country filter costs you 25 records at the sample stage, not 5,000 at the export stage.
What you get
This is a live free count run on 2026-10-21 with leadocean_count_leads (jobLevel VP, jobFunction Sales & Business Development, country US). It filters on mailable addresses (emailStatus verified, catch_all_valid or catch_all) and spent 0 records.
{
"total": 129494,
"totalIsExact": true,
"totalAll": 350517,
"distinctCompanies": 58121,
"credits": 0
}totalAll is the same filters with no email filter. Pulling 25 of those rows plus 10 reveals is 35 records, 3.5% of the free allowance.
A search row has this shape (response shape from the API reference, placeholder values):
{
"success": true,
"data": [
{
"profile_data": {
"profile_full_name": "Jane Doe",
"profile_headline": "VP of Sales at Acme"
},
"contact_data": {
"has_email": true,
"email_status": "verified",
"email_type": "work",
"contact_current_experiences": [
{ "company_name": "Acme", "company_domain": "acme.com", "job_title": "VP of Sales" }
]
},
"meta": { "source_ids": { "person_id": "1234567890" } }
}
],
"meta": { "count": 25, "credits": 25, "nextCursor": "eyJ..." }
}Troubleshooting
| Error | Cause | Fix |
|---|---|---|
| 401 | Missing or wrong x-api-key header | Check $LEADOCEAN_API_KEY is set in the shell that runs the call |
| 429 | Above the plan's rate limit (5 a second on Free, 200 on Agency) | Wait for Retry-After, then slow the loop |
| 402 | Out of records on the free plan | Check GET /v1/account, then move to a paid plan |
Empty data | Enum value spelled wrong, such as vp for jobLevel | Look up exact values with GET /v1/enums |
| 404 on enrich | Nobody matched the input | Nothing is charged. Skip the row |
| Export refused | Over 50,000 rows a request or 500,000 a day, or you are on Free | Split the export or use a paid plan |
FAQ
How many records does a GTM team need?
Start with the free 1,000 to test fit. Paid plans have a fair-use pace instead of credits, so there is no per-record price or overage invoice. Solo is $97 a month for one person. Agency is $497 a month for teams, with 5 keys.
Can I use this without writing code?
Yes. The app at app.leadocean.io has an Exports page with a filter builder and CSV download. The MCP server at https://api.leadocean.io/mcp also exposes 13 tools to Claude and other MCP clients.
Does LeadOcean replace our sequencer or CRM?
No. It is a data source. Export a CSV or call the API from your own tools.
How fresh is the data?
The dataset is refreshed monthly. Each record also carries its own fetched_at date.
Where do I go next?
For tool picks by team type, see data providers for GTM engineers, for RevOps teams and for enterprise teams. Plans are on the pricing page.
Size your GTM list before you pay for it
Free to start. No credit card. 1,000 records to spend whenever you like.
Get your free API key →