Moving to account-based marketing means swapping a list of leads for a list of accounts, each with a named buying committee. This recipe builds both with four API calls. You end with 50 accounts and about 150 contacts. Hand them to a sequencer, an ad platform or a direct mail tool.
Guides like Clay's ABM guide cover the strategy. This page is the data step: queries you can run today.
TL;DR
- Size the market for free, pick 50 accounts, then find three roles at each one.
- It takes about 20 minutes and spends about 350 records. The Free plan holds 1,000 records for life, so you can run it twice.
- Output is a CSV of accounts and contacts. LeadOcean has no sequencer or CRM, so you send it to your own tools.
Prerequisites
- A LeadOcean API key from app.leadocean.io. The Free plan needs no card. Export it as
$LEADOCEAN_API_KEY. curlandjq, or any HTTP client.- An ideal customer profile in one line. Ours for this recipe: US software companies with 201-500 employees.
- Optional: Claude connected to the hosted MCP server at
https://api.leadocean.io/mcp, which gives you the free count tools in chat.
Step 1: Size the account market (free)
Count before you pull. A count call costs nothing, so tune the filters until the list is the size you can actually work.
The MCP tool leadocean_count_companies wraps GET /v1/companies/count. It takes the company-search filters and returns an exact total with breakdowns.
curl -s "https://api.leadocean.io/v1/companies/count?industry=Software%20Development&employeeRange=201-500&hqCountry=US" \
-H "x-api-key: $LEADOCEAN_API_KEY"Check the enum values first. They are exact strings, and a typo returns zero rows.
curl -s "https://api.leadocean.io/v1/enums" -H "x-api-key: $LEADOCEAN_API_KEY"Step 2: Pull the 50 best-fit accounts
A real ABM list is small. Fifty accounts is a number one team can run with a personal touch.
POST /v1/companies/search takes a flat JSON body. Filters are arrays, limit runs 1 to 100, and you page with cursor. Add hasMailableContacts so you do not pick accounts you cannot reach.
curl -s https://api.leadocean.io/v1/companies/search \
-H "x-api-key: $LEADOCEAN_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"industry": ["Software Development"],
"employeeRange": ["201-500"],
"hqCountry": ["US"],
"hasMailableContacts": true,
"limit": 50
}' | tee accounts.json | jq '.meta | {count, total, nextCursor}'This spends 50 records. Rank the 50 against your own signals (technology, funding, hiring) before you commit. Narrow with technologies or keywords rather than paging deeper.
Save the domains for the next step:
jq -r '.data[].company_data.company_domain // empty' accounts.json > domains.txt
wc -l domains.txtThe domain sits at company_data.company_domain, per the company lookup docs.
Step 3: Find the buying committee at each account
A buying committee is the three to six people who sign off. For a marketing tool, start with three roles: the budget owner, the champion and the technical gate.
POST /v1/people/search accepts a domain array alongside title and level filters. Send one account per call and ask for three people.
DOMAIN=acme.com
curl -s https://api.leadocean.io/v1/people/search \
-H "x-api-key: $LEADOCEAN_API_KEY" \
-H "Content-Type: application/json" \
-d "{
\"domain\": [\"$DOMAIN\"],
\"jobLevel\": [\"C-Team\", \"VP\", \"Director\"],
\"jobFunction\": [\"Advertising & Marketing\", \"Sales & Business Development\"],
\"limit\": 3
}"Search returns a thin projection with no contact points. Each row carries its person_id at meta.source_ids.person_id. That is deliberate: you pay one record per person and see who they are before you pay to reach them. Loop over domains.txt for all 50 accounts. That is about 150 records.
Why filter by level and function instead of title? Titles vary ("Head of Growth", "VP Demand Gen"). Level and function are normalised, so one query covers the variants.
Step 4: Enrich the contacts you will actually use
Enrich by person_id from the search result. Pass reveal_email to get the address.
curl -s 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_3", "reveal_email": true}'An enrichment that finds nothing is a 404 and costs nothing. Read email_status before you send: bounced emails are not refunded. Phones come from GET /v2/people/phone, one record per call.
Enrich only the people in accounts you will touch this quarter. For a larger run, use POST /v1/exports (up to 50,000 rows a request, 500,000 a day, not on Free). The Exports page in the app shows the record price before you start.
What you get
Step 1 sizes the market. This is leadocean_count_companies run on 2026-10-21 with the Step 1 filters. The top three states are shown:
{
"total": 2316,
"totalIsExact": true,
"facets": {
"hq_state": [
{ "value": "California", "count": 672 },
{ "value": "New York", "count": 265 },
{ "value": "Texas", "count": 180 }
]
},
"credits": 0,
"unsupportedFilters": []
}So 2,316 US software companies of 201-500 people match, and the call spent no records.
To size the committee side, leadocean_count_leads ran on 2026-10-21 with jobLevel VP, jobFunction Advertising & Marketing and country US. It returned 49,523 people. Each has a verified, catch_all_valid or catch_all email, and together they span 24,142 companies. Without an email filter the same query matches 125,091 people. That is a count by email status, not a promise that each address will land.
A person record has this shape. It is the response shape from the API reference, with placeholder values:
{
"data": [
{
"profile_data": { "profile_full_name": "Jane Doe" },
"contact_data": {
"has_email": true,
"email_status": "verified",
"contact_current_experiences": [{ "job_title": "VP Marketing", "company_name": "Acme", "company_domain": "acme.com" }]
},
"meta": { "source_ids": { "person_id": "1234567890" } }
}
],
"meta": { "count": 1, "limit": 3, "credits": 1, "nextCursor": null }
}A search row has no address. The address arrives in contact_data.contact_emails[] when you enrich with reveal_email. Check openapi.json before you map columns.
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 |
| 429 | Above the plan's rate limit (5 a second on Free, 200 on Agency) | Wait for Retry-After, then slow the loop in Step 3 |
| 402 | Out of records on the Free plan | Check GET /v1/account, then move to Solo ($97 a month) or Agency ($497 a month) |
Empty data | A filter value is not an exact enum string | List the values with GET /v1/enums and copy them as written |
| 404 on enrich | We hold nothing for that person | Nothing is charged. Try another person at the account |
| Export refused | Over 50,000 rows a request or 500,000 a day, or on Free | Split the export or upgrade |
FAQ
How many accounts should an ABM list have?
Start with 50. One team can personalise to that many. Tier them: 10 get custom work, 40 get a shared template.
Does LeadOcean run the campaign?
No. LeadOcean is the data layer: accounts, people, emails and phones through an API, an MCP server and an Exports page. It has no sequencer, dialer, CRM or Chrome extension. Send the CSV to the tools you already run. See ABM orchestration for how the touches fit together.
Can I use direct mail or gifting with this list?
Yes, the account and contact export feeds any tool that takes a CSV. For one example of an engagement platform, see Sendoso.
Can Claude build the list for me?
Yes. The ABM list builder skill runs these steps through the MCP server, and the count tools are free.
What does it cost to scale this?
Free covers 1,000 records for life. Paid plans have a fair-use pace instead of credits. See pricing.
Build your first ABM account list free
Free to start. No credit card. 1,000 records to spend whenever you like.
Get your free API key →