Pre-Black Friday: 20% off, for as long as you stayEARLYBFon Solo and AgencyEnds Nov 28Start free

How-to guide

How to Test 11 Lead Enrichment Tools and Keep 5 (Sales Team Bake-Off)

One test set, one scoring sheet, one rule for cutting the list. Build it with the LeadOcean API in an afternoon.

Get your free API key →Free to start. No credit card. 1,000 records to spend whenever you like.

You pick enrichment tools by running them all on the same people and counting what comes back. Vendor fill-rate claims do not predict how a tool behaves on your accounts.

This guide is a method, not a report. We did not run this test for you, and we will not invent a winner. You build the test set, score eleven tools, and keep five. The test set comes from LeadOcean because it costs about 100 records and returns an email_status you can check.

TL;DR

  • Build one 100-person test set from your own ICP, run every tool on it, and score four numbers: match rate, verified-email rate, bounce rate and cost per usable contact.
  • It takes about 3 hours of your time and about 100 LeadOcean records: 50 search rows plus 50 enrichments. The sizing count in Step 1 is free.
  • Keep five tools, one per job: primary source, gap filler, phone, verifier and workflow glue. Cut any tool that does not win a job.

Prerequisites

  • A LeadOcean account. The free plan gives you 1,000 records, one-off, with no card: start free.
  • An API key in your shell: export LEADOCEAN_API_KEY=... (the app lists your keys).
  • curl, jq and Python 3. Every request goes to https://api.leadocean.io with the x-api-key header.
  • Trial or free access to the tools you are testing, and a small sending domain you can afford to burn for the bounce test.

Step 1: Size your ICP before you sample it

Count first. It is free and tells you if your ICP is big enough to sample fairly. Send count=true as a query parameter with limit 1 in the body.

bash
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 '{
    "jobLevel": ["VP"],
    "jobFunction": ["Sales & Business Development"],
    "country": ["US"],
    "employeeRange": ["51-200"],
    "limit": 1
  }' | jq '.meta | {total, totalIsExact, distinctCompanies}'

Swap in your own ICP. A test set drawn from a pool of 200 people tells you less than one drawn from 20,000, because the tools will have seen the same names.

Step 2: Draw a 50-person sample, then double it

Pull a first page of 50 and keep it as your ground truth. Each person returned costs one record. Cap limit at 50 for this pass.

bash
curl -s -X POST "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"],
    "employeeRange": ["51-200"],
    "limit": 50
  }' > sample.json

jq '.meta | {count, nextCursor}' sample.json

Pass meta.nextCursor back unchanged for a second page of 50. The other 50 should come from outside LeadOcean: your CRM, closed-won contacts, last quarter's bounced list. A test set drawn only from one vendor flatters that vendor. Mix both, and label each row with its origin.

Step 3: Build the input file every tool receives

Give all eleven tools the same keys. A LinkedIn profile URL is the most portable one. List the fields in a row first, since paths can differ between versions.

bash
jq '.data[0].profile_data | keys' sample.json
jq -r '.data[] | [.meta.source_ids.person_id] | @csv' sample.json > ids.csv

Then add the profile URL and company domain columns from the keys you found, and save the result as input.csv. Upload the same file to each tool, or loop through its API. Record the date and the tool's plan for every run.

Step 4: Get the LeadOcean answer with email status

Enrich each person by person_id with reveal_email set to true. A person we hold nothing for is a 404 and costs nothing. Keep the raw JSON, since you will score it in Step 5.

bash
mkdir -p lo
for ID in $(jq -r '.data[].meta.source_ids.person_id' sample.json); do
  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\": \"$ID\", \"reveal_email\": true}" > "lo/$ID.json"
  sleep 0.3
done
ls lo | wc -l

Free runs at 5 requests a second, so the pause keeps you under the limit. Use the same email-status rule on every tool's output: treat verified as send, catch_all as a small-batch risk, and everything else as not usable.

Step 5: Score all eleven tools with one script

Put each tool's output in a CSV with the columns person_id, email, status. Then run the same script on every file. Four numbers matter.

python
import csv, sys

rows = list(csv.DictReader(open(sys.argv[1])))
n = len(rows)
found = [r for r in rows if r["email"]]
usable = [r for r in found if r["status"] in ("verified", "catch_all_valid")]
print(f"match rate:   {len(found) / n:.0%}")
print(f"usable rate:  {len(usable) / n:.0%}")
cost = float(sys.argv[2])  # what you paid for this run, in dollars
print(f"cost per usable contact: ${cost / max(len(usable), 1):.2f}")

Match rate says how often a tool returns anything. Usable rate says how often that something is safe to send. Cost per usable contact puts tools with different pricing models on one scale. Use monthly list price first and the billed-yearly figure after it, and write down which you used.

The fourth number is the bounce rate. Send 25 emails per tool from the burner domain, then count hard bounces after 48 hours. LeadOcean gives no refund for bounced emails, so measure bounces before you pay at volume. Check each vendor's own refund terms.

Step 6: Cut eleven to five

Keep one tool per job. Do not keep two tools for the same job.

JobKeep the tool that wins on
Primary sourceHighest usable rate on your 100 people, at a pace you can run all month
Gap fillerMost usable emails on the rows the primary missed
PhoneHighest direct-dial hit rate on the rows you must call
VerifierLowest bounce rate on the 25-email send
Workflow glueConnects your CRM and sequencer without code

A tool that wins no row of this table gets cut, however good its demo was. If your team does not call, drop the phone job and keep four. Our view: test the verifier as hard as the primary source.

Step 7: Check the result against your sales team

Numbers pick the shortlist. Reps confirm it. Give the five survivors to three reps for two weeks and ask one question each Friday: which tool did you open first?

Log every lookup a rep makes with the tool name, the outcome and the time it took. A tool with a slightly higher usable rate that needs six clicks can lose to one that fills the CRM field on its own. Then compare the log with Step 5. If a rep keeps opening a tool the score ranked fourth, find out why before you cut it.

Run one more check on price. Multiply your monthly lookup volume by each tool's cost per usable contact from Step 5. Compare that to the plan prices on the vendors' own pricing pages, and note the month you read them. On LeadOcean, Solo is $97 a month, Agency is $497 a month and Platform is $1,997 a month. Paid plans run on a fair-use pace, not credits, so your cost per usable contact is the plan price divided by the volume you run. See pricing.

What you get

The free count for the Step 1 filter, from the MCP leadocean_count_leads tool on 21 October 2026. These are mailable counts: emailStatus verified, catch_all_valid or catch_all, the default.

json
{
  "total": 18567,
  "totalIsExact": true,
  "totalAll": 60456,
  "distinctCompanies": 12192,
  "credits": 0
}

So 18,567 of the 60,456 matching people hold a mailable address, across 12,192 companies. That is a big enough pool for a fair 100-person sample.

A search row, as a response shape from the API reference. Values are placeholders and profile_data is abbreviated:

json
{
  "success": true,
  "data": [
    {
      "profile_data": {},
      "contact_data": {
        "has_email": true,
        "has_phone": false,
        "email_status": "verified",
        "email_type": "work"
      },
      "meta": { "source_ids": { "person_id": "1234567" } }
    }
  ],
  "meta": { "count": 1, "nextCursor": "..." }
}

After the reveal, contact_data.contact_emails holds objects with email, type, status and verified_batch_date, for example jane.doe@acme.com, work, verified.

Troubleshooting

ErrorCauseFix
401Missing or wrong x-api-keyRe-copy the key from the app and check echo $LEADOCEAN_API_KEY
429Above the plan's rate limit (5 requests a second on Free, 200 on Agency)Keep the sleep in the loop, or honor Retry-After
402The 1,000 free records are spentUpgrade, or shrink the sample. Counts and 404s stay free
404 on enrichWe hold nothing for that person_idSkip it. It costs nothing and counts as a miss in your score
Empty data arrayA bad enum value, such as vp where jobLevel wants VPCheck exact strings with GET /v1/enums or leadocean_list_enum_values
Export refusedOver 50,000 rows a request or 500,000 a day, or Free planBulk CSV export is not on Free. Split the export by filter

FAQ

Why 100 people and not 1,000?

A hundred rows is enough to separate a 40% usable rate from a 70% one. It is not enough to rank two tools 3 points apart. If two tools tie, re-run both on a fresh 100 before you decide.

Can I run the test on the free plan?

Yes. The method spends about 100 of your 1,000 free records, and the count in Step 1 spends none. The other ten tools need their own free or trial access.

Should I test the vendors' own sample data?

No. Send them your people. Samples picked by a vendor show the vendor's best rows.

Where do the other related guides fit?

The enrichment API roundup covers what each API offers. The RevOps list and the enterprise list help you build the eleven-tool long list.

Do I need eleven tools?

No. Eleven is a long list to start from. Cut it to five after Step 6, and re-test once a year, since coverage and pricing change.

Run your 100-person enrichment test on LeadOcean

Free to start. No credit card. 1,000 records to spend whenever you like.

Get your free API key →