What data enrichment actually costs is the number of records you will really receive, times what each one costs in that vendor's units. Credits, misses and expiry all move that number. You can find it in about 20 minutes, for free.
This is the short version, with real queries. You will size the list, test 20 rows, then price it three ways.
TL;DR
- Three steps: count the list (free), enrich a 20-row sample, multiply by the vendor's unit. About 20 minutes.
- On LeadOcean the whole exercise spends 0 to about 20 of your 1,000 free records. Counts and misses cost nothing.
- Credit prices hide the real cost in add-ons. Apollo charges 8 credits for a phone on top of 1 for the email (Apollo API pricing, September 2026).
Prerequisites
- A LeadOcean key from app.leadocean.io/register. Free has no card, 1,000 records for life and 5 requests a second.
- Your key in the shell:
export LEADOCEAN_API_KEY=... curlfor Steps 1 and 2, Python 3 withrequestsfor Step 3.- A short list of 20 LinkedIn URLs or work emails from your own CRM. Use any list you have.
Step 1: Size the list before you pay for anything
The first cost question is how many records you need, so count them first. Send count=true as a query parameter on the search endpoint. The filters and limit 1 go in a flat JSON body, with filters as arrays.
curl -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": ["CA"], "limit": 1}'This spends no records. data comes back empty and meta.countOnly is true. meta.total is capped at 100,000, so a wide filter reads as a floor, not a total.
Most vendors do not give you a free count. Crustdata charges 0.03 credits per search result (Crustdata docs, September 2026). So sizing a list there is already a line item.
Step 2: Enrich a 20-row sample and read the hit rate
The hit rate is the biggest hidden multiplier. A vendor that bills only on a match costs less per row than its price suggests. One that bills per call costs more.
On LeadOcean, POST /v1/people/enrich takes exactly one of linkedin_url, email, phone or person_id. A person we hold nothing for is a 404 and costs nothing. A hit costs one record.
curl -X POST https://api.leadocean.io/v1/people/enrich \
-H "x-api-key: $LEADOCEAN_API_KEY" \
-H "Content-Type: application/json" \
-d '{"linkedin_url": "https://www.linkedin.com/in/jane-doe-example", "reveal_email": true}'reveal_email costs no extra record. Phones through the v2 endpoints are different: GET /v2/people/phone costs one record per call, including a call that finds nothing. Test them separately.
Step 3: Turn the sample into a projected bill
Run your 20 rows through a script that counts hits, then scale to the full list. This one reads sample.csv with a linkedin_url column and prints the projection.
import csv, os, time, requests
URL = "https://api.leadocean.io/v1/people/enrich"
HEAD = {"x-api-key": os.environ["LEADOCEAN_API_KEY"]}
LIST_SIZE = 10_000 # from Step 1
hits = rows = verified = 0
with open("sample.csv") as f:
for row in csv.DictReader(f):
rows += 1
r = requests.post(URL, headers=HEAD,
json={"linkedin_url": row["linkedin_url"], "reveal_email": True})
if r.status_code == 404:
continue # a miss, costs 0
r.raise_for_status()
hits += 1
c = r.json()["data"]["contact_data"]
verified += c.get("email_status") == "verified"
time.sleep(0.25) # stay under 5 requests a second
rate = hits / rows
print(f"hit rate {rate:.0%}, verified {verified}/{hits}")
print(f"records for {LIST_SIZE:,} rows: about {int(LIST_SIZE * rate):,}")Read email_status before you send. A bounced email is not refunded. Count only the statuses you will actually mail when you price the list.
Step 4: Price the same 10,000 records in each vendor's unit
Convert to the vendor's unit, then to dollars. Here is the same job, 10,000 people with a work email and a mobile number, using the published rates.
| Vendor | Unit and rate | 10,000 people, email + phone | Source |
|---|---|---|---|
| Apollo | 1 credit per email, plus 8 if a mobile is returned | Up to 90,000 credits | API pricing, September 2026 |
| People Data Labs | 1 credit per match, about $0.20 to $0.28 on Pro | About $2,000 to $2,800 | PDL blog, February 2026 |
| LeadOcean Solo | $97 a month, fair-use pace, no credits | $97 (10k enrichments fit one 5-hour window) | leadocean.io/pricing |
Now turn Apollo's credits into money. Professional is $99 a month per seat for 4,000 credits, or $79 billed yearly for 48,000 credits a year (Apollo pricing, September 2026). 90,000 credits is 22.5 seat-months of Professional: 23 seats for one month, or $2,277 at the monthly price. Credits expire at the end of each billing cycle and do not roll over (Apollo API pricing, September 2026).
PDL's $0.28 is the entry rate: $98 a month for 350 credits (PDL pricing, September 2026). It is not a volume price, and PDL sends buyers above roughly 100,000 profiles a year to sales (PDL, September 2026). For a million rows, see what 1M records cost at 20 data providers.
Step 5: Add the costs the rate card leaves out
Four things move the real number. Check each against your sample before you sign.
- Misses. PDL does not bill a 404 (PDL docs, September 2026). Crustdata does not bill misses on contact enrich, an enterprise-only endpoint (Crustdata docs, September 2026). We did not find Apollo's rule for misses in the sources above. Ask before you buy.
- Add-ons. Crustdata person enrich is 1 to 7 credits depending on email, phone and platform fields (Crustdata docs, September 2026). Quote the cost of the fields you need, not the base.
- Expiry. Apollo credits expire every billing cycle. Crustdata's purchased credits expire 12 months after purchase (Crustdata docs, September 2026). Credits you do not use are a loss.
- Seats. Per-seat plans multiply with every person who needs the API. LeadOcean Solo is one person, Agency is $497 a month for teams with 5 keys.
On LeadOcean the same list is a fair-use pace, not credits. Solo covers 10k enrichments every 5 hours and 50k a week. Reaching the pace slows the key until the window resets. Nothing stops and nothing expires.
What you get
Output from Step 1 looks like this (response shape from the API reference, placeholder values):
{
"data": [],
"meta": { "countOnly": true, "total": 5574 }
}For a real figure: on 21 October 2026, leadocean_count_leads with jobLevel VP, jobFunction Sales & Business Development and country CA returned 5,574 mailable people on the tool's default filter (best email verified, catch_all_valid or catch_all), and 18,800 with no email condition. That count cost 0 records. A count with a phone or email filter is not the same as a mailable count, so label what you filtered.
Step 3 prints two lines. These are placeholder values:
hit rate 85%, verified 14/17
records for 10,000 rows: about 8,500At an 85% hit rate, 10,000 rows bill 8,500 records on a hit-only model. The same list on a per-call model bills 10,000.
Troubleshooting
| Error | Cause | Fix |
|---|---|---|
| 401 | Missing or wrong x-api-key | Check $LEADOCEAN_API_KEY is set in this shell. Copy the key again from the app. |
| 429 | Above the plan's rate limit (5 a second on Free, 200 on Agency) | Honour Retry-After. Keep the sleep in Step 3. |
| 402 | Records spent | Free is 1,000 for life. Move to Solo at $97 a month. |
| Empty results | A filter value is not an exact enum string | Look it up with leadocean_list_enum_values. jobLevel is VP, not Vice President. |
meta.total stops at 100,000 | The count is capped | Narrow the filters until totalIsExact is true. |
| Export refused | Over 50,000 rows a request or 500,000 a day | Split the job by country or headcount band. |
FAQ
What does data enrichment cost per record?
It ranges from about $0.20 to $0.28 a profile at PDL's published Pro rates (PDL blog, February 2026) to a flat plan price with no per-record charge. Compare the cost of the fields you need, not the headline rate.
Why do credit prices mislead?
Because add-ons are priced separately. Apollo bills a phone at 8 credits against 1 for an email. A rate card that quotes only the email credit understates the cost of a full contact by 9x.
Is a miss billed?
It depends on the vendor. On LeadOcean a person we hold nothing for is a 404 and costs nothing. The v2 contact endpoints are the exception: they cost one record per call, including a miss.
Can I size a list without paying?
On LeadOcean, yes. The count, filter list and enum lookup are free through the API and the MCP server. Company lists have a free count at GET /v1/companies/count.
Price your own list before you pay anyone
Free to start. No credit card. 1,000 records to spend whenever you like.
Get your free API key →