You get a two-step list pipeline. LeadOcean exports the people and tells you how sure it is about each email. VerifyHQ, a sibling product for email verification, then checks only the catch_all and untested rows. Rows LeadOcean marks verified or catch_all_valid skip the second check. The free plan has a key for this recipe, with 1,000 records to spend.
Related: the LeadOcean integrations hub, the LeadOcean, VerifyHQ and ReachHQ stack guide, and the pricing page.
How it works
The route is one export, one split, one verification pass and one merge. The script below needs only curl and Python 3.
- Get a LeadOcean key. Sign up at app.leadocean.io, open the API keys page and copy a key. The free plan needs a work email and no card.
- Create the export. POST to
/v1/exportswith your filters and the columns below. The API answers 202 with a jobid. - Poll and download. Check
GET /v1/exports/{id}untildata.statusisdone, then download the CSV. - Split by email status. Rows with
email_1_statusofcatch_alloruntestedgo toto_verify.csv. Everything else goes tokeep.csv. - Verify the subset. Upload
to_verify.csvto VerifyHQ as a bulk CSV. VerifyHQ says it takes files up to 500K rows. - Merge and filter. Download the VerifyHQ results, keep the rows that meet your score threshold, and append them to
keep.csv.
For a few addresses, skip the upload and call VerifyHQ's single-email endpoint from the configuration below.
VerifyHQ does not publish the bulk upload menu path or the expected email column header. The app sits behind a login. Open the bulk option in your VerifyHQ dashboard and map the email_1_address column if it asks.
Configuration
Step 2 sends the export request. Filters join with AND, and several values inside one filter join with OR. The emailStatus filter for catch_all also matches catch_all_valid, so the split in step 4 is what separates them.
curl -X POST https://api.leadocean.io/v1/exports \
-H "x-api-key: $LEADOCEAN_API_KEY" \
-H "Content-Type: application/json" \
-d '{"name":"verifyhq test","filters":{"jobLevel":["VP"],"country":["CA"],"emailStatus":["verified","catch_all","untested"]},"limit":100,"columns":["person_id","profile_full_name","current_company_domain","email_N_address","email_N_status"]}'
curl -H "x-api-key: $LEADOCEAN_API_KEY" https://api.leadocean.io/v1/exports/EXPORT_ID
curl -H "x-api-key: $LEADOCEAN_API_KEY" -o leads.csv https://api.leadocean.io/v1/exports/EXPORT_ID/downloadEmail columns need a key with the enrich scope. Keys on the Free plan get both scopes, search and enrich, inside the 1,000 one-off records.
Step 4 is a short script. It reads the CSV header as column ids.
import csv
send = ("catch_all", "untested")
keep, check = [], []
with open("leads.csv", newline="") as f:
reader = csv.DictReader(f)
fields = reader.fieldnames
for row in reader:
(check if row["email_1_status"] in send else keep).append(row)
for name, rows in (("keep.csv", keep), ("to_verify.csv", check)):
with open(name, "w", newline="") as f:
w = csv.DictWriter(f, fieldnames=fields)
w.writeheader()
w.writerows(rows)To test one address against VerifyHQ, use the request from its homepage API section. Your VerifyHQ key goes in a second variable.
curl -X POST https://api.verifyhq.io/api/public/verify \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $VERIFYHQ_API_KEY" \
-d '{"email": "jane@example.com"}'The response carries email, result, score, tier, do_not_mail, reason, checks, hosting and domain. VerifyHQ does not publish a rate limit. Its public pages do not say where the API key is created either, and the homepage API section only shows the Bearer header. Create the key in your VerifyHQ account. Ask support@verifyhq.io for the limit before a large run (VerifyHQ homepage, October 2026).
Field mapping
The LeadOcean export is a flat CSV. The VerifyHQ fields come from the sample response on its homepage, September 2026.
| LeadOcean field | Target field | Note |
|---|---|---|
email_1_address | VerifyHQ email | The address to check. Best address first. |
email_1_status | Split rule | catch_all and untested go to VerifyHQ. verified and catch_all_valid stay. |
person_id | Join key | Stable across exports. Use it to merge results back. |
profile_full_name | Not sent | Kept in your file only. |
current_company_domain | Compare with VerifyHQ domain | A quick sanity check on the address. |
VerifyHQ result | New column, for example vhq_result | Sample shows deliverable. |
VerifyHQ score | New column vhq_score | A 0 to 100 score you can threshold. |
VerifyHQ tier | New column vhq_tier | Sample shows safe. |
VerifyHQ do_not_mail | New column | Drop any row where this is true. |
VerifyHQ's homepage names three tiers: Safe, Risky and Bad. The sample response shows safe. VerifyHQ does not publish the full list of result values or the exact tier strings (VerifyHQ homepage, October 2026). Filter on tier and score, and send any value you do not recognise to review.
VerifyHQ's own page suggests sending above a score of 80 and reviewing 50 to 80. Treat that as a starting point. Tune it on your own bounce data, and keep the vhq_score column so you can change the cutoff later without re-running the check.
Cost at 10,000 rows
For 10,000 rows, LeadOcean needs Pro at $499 flat and VerifyHQ lists Lite at $9.99 a month. Only the catch_all and untested subset goes to VerifyHQ, so its bill is at most the size of that subset.
| Item | Free LeadOcean | Pro |
|---|---|---|
| LeadOcean export | 1,000 records, one-off | $499 a month, flat |
| VerifyHQ Lite | $9.99 a month, 10K verification credits | $9.99 a month, 10K verification credits |
| 10,000 rows | Covers 1,000 rows of export | $508.99 for the month at most |
VerifyHQ figures come from the VerifyHQ homepage, checked September 2026. Its pricing page still shows placeholder tiers ($29 and $79), so the homepage pricing block is the source here. It lists Lite at $9.99 a month with 10K verification credits a month. That is at the default AutoClean setting of 4K a day, and the price may move with that slider (VerifyHQ homepage, October 2026).
The homepage says add-on credit packs do not expire, and it offers free verifications to new accounts with no card. The hero button reads "Verify 100 emails for free". The FAQ only says new accounts get free credits, so confirm the amount at signup.
VerifyHQ does not say how many credits one address uses, including a catch-all it resolves, so the Lite figure below assumes one credit per address.
An export costs one LeadOcean record per row, whatever the columns. LeadOcean has no per-record price, no credits and no overage invoice. A very large month is paced down to one request a minute until the reset, rather than cut off.
Troubleshooting
| Symptom | Cause | Fix |
|---|---|---|
| 402 on export create | Fewer records left than limit reserves. | Lower limit, or move to Pro. |
| 403 on export create | Email columns asked without the enrich scope. | Use a key with that scope. |
| 409 on download | The export is still running. | Poll data.status until it is done. |
| 410 on download | The download file expired. | Create the export again. |
KeyError: email_1_status | The column was left out of columns. | Add email_N_status and email_N_address to columns; the CSV headers come back as email_1_.... |
Verified rows show up in to_verify.csv | The emailStatus filter for catch_all also matches catch_all_valid. | Split on the column, as in step 4. |
| 401 from VerifyHQ | The Bearer key is missing or wrong. | Send Authorization: Bearer $VERIFYHQ_API_KEY. |
Search counts more verified than an export shows | Search counts are an upper bound. | Trust the export value. LeadOcean applies the stricter rule on enrichment. |
FAQ
Why not verify the whole list?
Because LeadOcean has already tested some addresses. A verified address means LeadOcean's own verifier sent to it and it accepted. Re-checking those rows adds cost and no new information. Spend the VerifyHQ credits on the rows where the answer is still open.
Why send catch_all rows to VerifyHQ?
A catch-all domain accepts any address, so LeadOcean cannot confirm the mailbox exists. VerifyHQ says it resolves catch-all domains to mailbox-level validity, which is the gap this recipe fills.
What about untested rows?
untested means nobody has checked the address yet. It may be fine. Sending those rows to VerifyHQ is a cheap way to find out before you send.
Does VerifyHQ connect to my sender directly?
VerifyHQ lists live integrations with Instantly, Smartlead, Lemlist, Apollo, HubSpot, ActiveCampaign, Zapier and a custom webhook, as of September 2026. Its Clay integration is listed as coming soon. See its integrations page.
Verify only the catch-all rows from your first free export
Free to start. No credit card. 1,000 records to spend whenever you like.
Get your free API key →