TL;DR
- Search by title, then reveal the email only for people you will write to. Do not guess patterns.
- It takes about 15 minutes and about 12 LeadOcean records: 10 search rows and 2 reveals. The count in Step 1 is free.
- Read
email_statusbefore you send. Send toverified, treatcatch_allas a risk you choose, skip the rest.
Addresses for this role come from three places: company websites and press pages, public profiles, and a data provider that has already matched and checked them. Patterns like first.last@ are a fourth, weak source. They give you an address that may not exist, and a bounce costs sender reputation. LeadOcean returns the address it holds with a status, so you read the risk instead of guessing it.
A recruiting alias such as careers@ or talent@ reaches a shared inbox, not the person. Three checks make a found address safer to use:
- The status is
verified, not just present. - The person's current title matches what you searched.
- The address is a work address (
typeiswork), not a personal one.
Pitch them on a problem they own: time to hire, sourcing cost, recruiter capacity. A short, specific first line beats a long intro.
Prerequisites
- A LeadOcean account. The free plan gives 1,000 records, one-off, no card: start free.
- An API key in your shell:
export LEADOCEAN_API_KEY=... curlandjq, pluscsvkitfor Step 6. Every request goes tohttps://api.leadocean.iowith thex-api-keyheader.
Step 1: Count the mailable Heads of Talent Acquisition
Count first. It is free. Send count=true as a query parameter with limit 1 in the body.
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 '{
"title": ["Head of Talent Acquisition"],
"salesRegion": ["NORAM"],
"limit": 1
}' | jq '.meta | {total, totalIsExact}'Swap salesRegion for EMEA, APAC or LATAM to size each region. We ran the same title through the free MCP leadocean_count_leads tool on 21 October 2026. These are mailable counts: emailStatus verified, catch_all_valid or catch_all, the default.
| Region | Mailable Heads of Talent Acquisition |
|---|---|
| NORAM | 1,398 |
| EMEA | 1,435 |
| APAC | 810 |
| LATAM | 105 |
| All regions | 3,898 |
The four regions add to 3,748. The other 150 match the title but sit outside all four regions. Without the email condition the title matches 8,914 people, so about 44% have a mailable address. The title filter is a keyword match, so it also catches close variants. Add "Director of Talent Acquisition" or "VP Talent Acquisition" if you want a wider net.
Step 2: Pull a first page
Run the search without count. Each person returned costs one record, so keep limit small. Add emailStatus to keep only addresses worth sending to.
curl -s -X POST "https://api.leadocean.io/v1/people/search" \
-H "x-api-key: $LEADOCEAN_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"title": ["Head of Talent Acquisition"],
"country": ["US"],
"emailStatus": ["verified"],
"limit": 10
}' > heads.json
jq '.meta | {count, credits, nextCursor}' heads.jsonSearch rows are thin. They carry has_email and email_status but not the address. Pass meta.nextCursor back unchanged for the next page.
Step 3: Reveal the email for the people you want
Enrich by person_id with reveal_email set to true. Without it the call returns no address. It costs one record per person.
PERSON_ID=$(jq -r '.data[0].meta.source_ids.person_id' heads.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\": \"$PERSON_ID\", \"reveal_email\": true}" > reveal.json
jq '.data.contact_data.contact_emails' reveal.jsonThere is no name plus domain lookup. If you start from a company list, search by domain first, then enrich by person_id.
Step 4: Verify before you send
Read the status on every address. This reads the file from Step 3, so it spends nothing.
jq -r '.data.contact_data.contact_emails[]
| select(.type == "work")
| [.email, .status, .verified_batch_date] | @tsv' reveal.jsonverified: send.catch_all_valid: the mailbox was confirmed on a domain that accepts everything. Send.catch_all: the domain accepts everything, so a bounce is possible. Send a small batch and watch it.risky,unknown,untested,role,invalid: do not send.
There is no refund for bounced emails. This step is where you protect your domain.
Step 5: Export the whole list
When the count looks right, export instead of paging. One request takes up to 50,000 rows, 500,000 a day. Bulk CSV export is not on Free. Each row costs one 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": "talent-acquisition-heads-noram",
"filters": {
"title": ["Head of Talent Acquisition"],
"salesRegion": ["NORAM"],
"emailStatus": ["verified"]
},
"limit": 500,
"preset": "full",
"caps": {"emails": 1}
}'Poll GET /v1/exports/{id} until status is done, then download the CSV. Headers are email_1_address and email_1_status. The app (app.leadocean.io, Exports page) builds the same export and shows the record price first.
Step 6: Load the list into your sender
LeadOcean does not send email. It has no sequencer, dialer or CRM. Download the CSV from Step 5 and import it into the tool you already use. Map email_1_address to the email field and keep email_1_status as a column, so you can filter later.
csvgrep -c email_1_status -m verified talent-acquisition-heads-noram.csv > send-first.csvSend the verified rows first, in small batches, and watch bounces for a few days. Then add the catch_all rows if the first batch stays clean. Re-run the count each month. The dataset is refreshed monthly, and each record carries its own fetched_at date.
What you get
The free count for NORAM, from the MCP leadocean_count_leads tool on 21 October 2026:
{
"total": 1398,
"totalIsExact": true,
"totalAll": 2558,
"distinctCompanies": 1153,
"credits": 0
}A search row, as a response shape from the API reference. Values are placeholders and profile_data is abbreviated:
{
"success": true,
"data": [
{
"profile_data": {},
"contact_data": {
"has_email": true,
"email_status": "verified",
"email_type": "work"
},
"meta": { "source_ids": { "person_id": "1234567" } }
}
],
"meta": { "count": 1, "credits": 1, "nextCursor": "..." }
}After the reveal, contact_emails holds email, type, status and verified_batch_date, for example jane.doe@acme.com, work, verified.
Troubleshooting
| Error | Cause | Fix |
|---|---|---|
| 401 | Missing or wrong x-api-key header | Send the key in x-api-key, not as a bearer token. Check $LEADOCEAN_API_KEY. |
| 429 | Above the plan's rate limit (5 a second on Free, 200 on Agency) | Honour Retry-After and slow the loop. |
| 402 | Out of records. The 1,000 free records are one-off | Count first, lower limit, or move to Solo at $97 a month or Agency at $497 a month. |
Empty data | A filter value that is not an exact enum string | Check values with GET /v1/enums or the free list_enum_values tool. |
export_limit_rows (400) | limit above 50,000 rows in one export | Split into exports with narrower filters. |
export_limit_daily (429) | More than 500,000 rows exported in a day | Wait for resetsAt in the error. |
FAQ
Can I just guess the email pattern?
You can, but it fails often enough to hurt. A guessed address has no status, so you cannot tell a good one from a bounce. Use a found address with a status.
What title should I search for?
Start with Head of Talent Acquisition. Add "Director of Talent Acquisition", "VP Talent Acquisition" or "Head of Recruiting" to widen the list. Read titles in the results, since companies name this role differently.
How many records does one contact cost?
One for the search row and one to reveal the email. An export row costs one record and includes the address. Counts are free, and an enrichment that finds nothing costs nothing.
Can I find a phone number too?
Yes. GET /v2/people/phone returns numbers. v2 contact lookups cost one record per call, including a call that finds nothing.
Does the record show past roles?
Yes. Since 2026-10-17 person enrich returns career history in resume_data: past roles with title, company name and dates, plus education and certifications when held. Past employers carry no company_id yet.
Where do I go for other roles?
See the guides for a Head of RevOps, a Head of Product and a Head of Growth. More recipes live in the blog hub. Plans and limits are on the pricing page.
Count the talent acquisition leaders you can mail today, free
Free to start. No credit card. 1,000 records to spend whenever you like.
Get your free API key →