A RevOps team needs nine enrichment jobs, and one API can run all of them. This guide gives each job as a request you can paste, with the output and what it costs in records.
The "nine tools" are nine calls against https://api.leadocean.io. You pick the ones your CRM is missing. If you want a vendor comparison first, read the best B2B data providers for RevOps teams.
TL;DR
- Nine jobs: size, search people, search companies, list a company's people, enrich a person, enrich a company, fetch a work email, fetch a phone, export in bulk.
- The sample run takes about 30 minutes and spends about 85 LeadOcean records. Sizing spends none.
- The Free plan has 1,000 records, one-off, with no card. Solo is $97 a month and Agency $497, with a fair-use pace instead of credits.
Prerequisites
- A LeadOcean API key from app.leadocean.io. Free keys get both the search and enrich scopes.
curlandjq. Every request sends the headerx-api-key.- The key in your shell, never pasted into a file:
export LEADOCEAN_API_KEY="paste-your-key-here"Every example uses placeholders: Acme, acme.com, Jane Doe and +1 415 555 0133. Swap in your own accounts.
Step 1: Size the list before you spend
Sizing is the first tool because it is free. Send count=true as a query parameter with limit 1, and the response carries a total and no rows. The body is flat JSON and every filter is an array.
curl -s "https://api.leadocean.io/v1/people/search?count=true" \
-H "x-api-key: $LEADOCEAN_API_KEY" -H "content-type: application/json" \
-d '{"title":["Revenue Operations"],"jobLevel":["Director","VP"],
"country":["US"],"limit":1}' | jq '.meta'meta.total is capped at 100,000. Filter values are exact strings: Director, not director. Check them with GET /v1/enums/job_level before you guess.
You can run the same count from an AI client. The hosted MCP server at https://api.leadocean.io/mcp has leadocean_count_leads, also free.
Use leadocean_count_leads with title ["Revenue Operations"], jobLevel ["Director","VP"],
country ["US"], facets false. Then repeat with emailStatus ["verified"].
Say what each total counted.Step 2: Search people by filter
People search turns a filter into rows. Each person returned is 1 record. The limit is 1 to 100 a page, and you page with a cursor.
curl -s "https://api.leadocean.io/v1/people/search" \
-H "x-api-key: $LEADOCEAN_API_KEY" -H "content-type: application/json" \
-d '{"title":["Revenue Operations"],"jobLevel":["Director","VP"],
"country":["US"],"limit":10}' | jq '.meta, .data[0].profile_data'Search never returns an address or a number. It returns flags that say whether one is on file, and meta.source_ids.person_id. Keep that id: Steps 5, 7 and 8 take it. Pass meta.nextCursor back unchanged to get the next page.
Step 3: Search companies
Company search builds an account list. Each company returned is 1 record. The filters sit in the same flat body, and the same exact-string rule applies.
curl -s "https://api.leadocean.io/v1/companies/search" \
-H "x-api-key: $LEADOCEAN_API_KEY" -H "content-type: application/json" \
-d '{"industry":["Computer Software"],"employeeRange":["201-500"],
"hqCountry":["US"],"limit":10}' | jq '.data[0]'Use the domains it returns as the join key everywhere else. A domain is a safer key than a company name, and there is no lookup by name.
Step 4: List the people at an account
This call returns the people we hold at one company, one page at a time. Each person returned is 1 record. It stops at 10,000 rows per company.
curl -s "https://api.leadocean.io/v1/companies/acme.com/people?limit=10" \
-H "x-api-key: $LEADOCEAN_API_KEY" | jq '.meta'It has no filter. To narrow by title or seniority, use Step 2 with the domain filter instead. Use this call when you want everyone at an account, such as for a coverage check on a target account.
Step 5: Enrich one person
Enrich turns one identifier into a full profile. Send exactly one of linkedin_url, email, phone or person_id. A hit is 1 record and a 404 costs nothing.
curl -s -X POST "https://api.leadocean.io/v1/people/enrich" \
-H "x-api-key: $LEADOCEAN_API_KEY" -H "content-type: application/json" \
-d '{"email":"jane.doe@acme.com"}' | jq '.data.contact_data.email_status'Set reveal_email to true when you want the address itself. It costs no extra record. This is the call to run on a CRM contact you already have, to check the email and the current role.
There is no name plus domain lookup. Search by domain first, then enrich by person_id.
Step 6: Enrich one company
Company enrich turns a domain into an account record: headcount, industry, HQ, funding and detected technologies. A hit is 1 record and a miss costs nothing.
curl -s -X POST "https://api.leadocean.io/v1/companies/enrich" \
-H "x-api-key: $LEADOCEAN_API_KEY" -H "content-type: application/json" \
-d '{"domain":"acme.com"}' | jq '.data.company_data'The response also carries company_detected_technologies and company_metrics. Use the domain as the join key back to your CRM account.
Step 7: Fetch a work email
The work email endpoint returns at most one current address for one person, or data: null. It takes a linkedin_url or a person_id. Every call is 1 record, including a call that finds nothing.
curl -s "https://api.leadocean.io/v2/people/email/work?person_id=1234567" \
-H "x-api-key: $LEADOCEAN_API_KEY"Read status before you send. There is no refund or credit for bounced emails. Only fetch emails for people who passed your filter, because a null still spends a record.
Step 8: Fetch a phone number
The phone endpoint returns numbers best first, each with the source's own type label, such as mobile, office or unknown. It takes the same inputs as Step 7. Every call is 1 record, including a call that finds nothing.
curl -s "https://api.leadocean.io/v2/people/phone?person_id=1234567" \
-H "x-api-key: $LEADOCEAN_API_KEY"Size phone coverage first. Search with hasPhone true and count=true gives a free total, so you know how many of your list can return a number at all.
Step 9: Export in bulk
Past a few hundred rows, stop paging and export. Bulk CSV export starts on Solo ($97 a month); it is not on Free. POST /v1/exports takes up to 50,000 rows a request and 500,000 a day. Every row costs 1 record.
curl -s -X POST https://api.leadocean.io/v1/exports \
-H "x-api-key: $LEADOCEAN_API_KEY" -H "content-type: application/json" \
-d '{"name":"revops-leaders-us","preset":"search","limit":50,
"filters":{"title":["Revenue Operations"],"jobLevel":["Director","VP"],"country":["US"]}}'The same job runs from the Exports page in app.leadocean.io. It has a filter builder, a column picker, the record price before you start and a CSV download. Use the app when you want a file and no code.
What you get
Steps 1 and 2 spend nothing to size. These are real results from the LeadOcean MCP server on 21 October 2026 for Directors and VPs with "Revenue Operations" in the title, located in the United States. Records spent: 0.
leadocean_list_enum_values name job_level
values: C-Team, Director, Manager, Other, Staff, VP
leadocean_count_leads title ["Revenue Operations"], jobLevel ["Director","VP"], country ["US"]
default mailable (verified, catch_all_valid, catch_all): 2,799
same filters, no email condition (totalAll): 4,951
leadocean_count_leads ... plus emailStatus ["verified"]
emailStatus verified only: 962The first total is the default mailable audience. The second is filtered to verified only, an upper bound until you enrich. A search row says an email is on file. Only Step 5 or Step 7 tells you the status of the address for one person.
Step 5 returns this shape. This is the response shape from the API reference, with placeholder values, trimmed to the fields a CRM sync reads.
{
"success": true,
"data": {
"contact_data": {
"email_status": "verified",
"email_type": "work",
"contact_current_experiences": [
{ "job_title": "Head of Sales", "company_name": "Acme", "company_domain": "acme.com" }
]
}
}
}Map email_status to a CRM field you can filter on. Treat verified, catch_all_valid and catch_all as sendable, and read the rest before any send. The job_title and company_domain fields tell you when a contact has moved on.
Step 8 returns this shape. This is the response shape from the API reference, with placeholder values, not a real person.
{
"success": true,
"data": {
"person_id": "1234567",
"found": true,
"phones": [ { "phone": "+14155550133", "type": "mobile" } ],
"best": { "phone": "+14155550133", "type": "mobile" }
}
}Troubleshooting
| Error | Cause | Fix |
|---|---|---|
| 401 | Missing, wrong or revoked key | Copy the key again from app.leadocean.io and re-export $LEADOCEAN_API_KEY. |
| 402 | The Free plan's 1,000 one-off records are spent | Run a shorter list, or move to Solo or Agency. Free records do not reset. |
| 429 | Above your plan's rate limit per account (5 a second on Free, 50 on Solo, 200 on Agency) | Slow the loop and retry after the Retry-After header. |
| Empty results | A filter value outside the list, such as director for Director | List exact strings with GET /v1/enums/job_level, then copy one. |
| 400 on enrich | Two identifiers in one call, or none | Send exactly one of linkedin_url, email, phone or person_id. |
| Export refused | Over 50,000 rows in one request, or over 500,000 in a day | Split the job into requests of 50,000 rows or fewer. Wait for the daily reset. |
FAQ
Which of the nine do I need first?
Start with Step 1, because it is free, then Step 5 on the contacts already in your CRM. A miss on enrich costs nothing. Add the others when a specific field is missing.
How many records does the sample run cost?
About 85. That is 10 each from Steps 2, 3 and 4, 1 each from Steps 5 to 8 and 50 from Step 9 (export needs Solo or above). Step 1 spends none. Cut the limits to 1 and the run costs about 10.
Can I look a person up by name and company?
Not directly. There is no name plus domain lookup. Search by domain first, then pass the person_id from the row to Step 5, 7 or 8.
Does a verified email guarantee no bounces?
No. Read email_status before you send, because LeadOcean gives no refund for bounces. A catch_all status means the domain accepts any address, so it cannot be confirmed.
Where do I compare vendors for these jobs?
Read the best lead enrichment tools for RevOps teams and the 8 enrichment tools that fix a messy CRM. See pricing for the four plans. More guides are in the blog hub.
Run all nine enrichment jobs on 1,000 free records
Free to start. No credit card. 1,000 records to spend whenever you like.
Get your free API key →