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

How-to guide

How to Use a Lead Enrichment API (From One Email to a Full Record)

A lead enrichment API takes one identifier and returns the person behind it. Here are the exact calls, the output and the costs.

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

A lead enrichment API takes one identifier you already hold (an email, a LinkedIn URL, a phone number) and returns the full record for that person: title, employer, location, career history and contact points. You send one request. You get one record back.

That is the whole idea. The rest of this page shows the calls, the output and what each one costs in LeadOcean records.

TL;DR

  • Enrichment is a lookup. You give one identifier, the API returns one person. In LeadOcean that is POST /v1/people/enrich.
  • The full loop takes about 20 minutes: size a list for free, search it, enrich the rows you want.
  • It spends about 3 records. Counts are free, and an enrich call that finds nobody returns a 404 and costs nothing.

Prerequisites

  • A LeadOcean account on the Free plan: 1,000 records for life, no card, 5 requests a second. Register at https://app.leadocean.io/register.
  • An API key from the app, exported as $LEADOCEAN_API_KEY.
  • curl and jq. Any HTTP client works the same way.
bash
export LEADOCEAN_API_KEY="paste-your-key-here"

Step 1: Understand what goes in and what comes out

An enrichment API has one job: map a thin input to a rich record. LeadOcean accepts exactly one of four inputs per call.

InputParameterUse it when
Work or personal emailemailYou have a form fill or a CSV of addresses
LinkedIn profile URLlinkedin_urlYou scraped or exported profiles
Phone number, any formatphoneYou have an inbound call or a dialer log
LeadOcean person IDperson_idYou found the person with search first

There is no name plus domain lookup. If you only have a name and a company, search by domain first, then enrich by person_id. Steps 2 and 3 do that.

Step 2: Size the list before you spend anything

Count first. A count call is free and tells you how many people match before you pull a single row.

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"],
    "country": ["US"],
    "limit": 1
  }' | jq '.meta | {total, totalIsExact, distinctCompanies}'

count=true goes in the query string, not the JSON body, because the body rejects unknown fields. meta.total is capped at 100,000, and data comes back empty with meta.countOnly true.

The MCP tool leadocean_count_leads does the same thing from Claude or ChatGPT. For companies, GET /v1/companies/count and the tool leadocean_count_companies are also free.

Step 3: Search to get identifiers

Search returns rows that carry a person_id. The body is flat JSON, filters are arrays, and limit runs from 1 to 100.

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 '{
    "domain": ["acme.com"],
    "jobLevel": ["VP", "C-Team"],
    "limit": 2
  }' | jq '{rows: (.data | length), person_id: .data[0].meta.source_ids.person_id}'

This costs 2 records, one per person returned. To page further, pass the cursor from the previous response. One search pages to 10,000 rows. The last page sets meta.depthCapped to true and has no nextCursor, so narrow the filters instead of walking the index.

Enum values are exact strings. Check them with leadocean_list_enum_values or GET /v1/enums before you filter, or the query returns nothing.

Step 4: Enrich one person

Now send the ID back to the enrich endpoint. This is the call the whole page is named after.

bash
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_FROM_STEP_3",
    "reveal_email": true
  }'

You can also enrich from an email you already hold:

bash
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"}'

An enrich call costs one record. reveal_email returns every email and phone we hold at no extra record. Without it you still get has_email and has_phone flags, so you can see what exists before you ask for it. If nobody matches, the answer is a 404 and it costs nothing.

Step 5: Know what the response holds

The enrich response has four blocks: profile_data, contact_data, resume_data and meta. Since October 2026 resume_data carries career history: past roles, educations, certifications, awards and more, each when held. Past employers do not carry a company_id yet.

Contact fields to read before you send anything:

  • contact_data.email_status is the deliverability of the best address. Values include verified, catch_all_valid, catch_all, risky and invalid.
  • contact_data.email_type tells you whether the address is work, work_other (a former employer) or personal.
  • contact_data.contact_current_experiences[] holds the current role.

LeadOcean does not refund bounced emails. Read email_status first.

Step 6: Put it in a loop

For a list, run enrich per row and stop on the first 429. Keep the pace under your plan's limit: 5 requests a second on Free, 50 on Solo, 200 on Agency.

bash
while read -r id; 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}" >> enriched.jsonl
  sleep 0.25
done < person_ids.txt

For thousands of rows, skip the loop. POST /v1/exports takes up to 50,000 rows a request and 500,000 a day. Bulk CSV export is not on Free, but it is included from Solo at $97 a month.

What you get

A live free count, run on 2026-10-21 through the leadocean_count_leads MCP tool, filtered to VP-level people in the US. The default counts only addresses worth sending to (verified, catch_all_valid or catch_all).

json
{
  "total": 1242801,
  "totalIsExact": true,
  "totalAll": 3102417,
  "distinctCompanies": 226527,
  "credits": 0
}

So 1,242,801 VP-level people in the US have a mailable address (verified, catch-all valid or catch-all). Without any email filter the same filters match 3,102,417. That count cost nothing.

The record shape, response shape from the API reference, with placeholder values:

json
{
  "success": true,
  "data": {
    "profile_data": { "profile_full_name": "Jane Doe", "profile_headline": "VP Sales at Acme" },
    "contact_data": {
      "has_email": true,
      "has_phone": true,
      "email_status": "verified",
      "email_type": "work",
      "contact_emails": [{ "email": "jane.doe@acme.com", "type": "work", "status": "verified" }],
      "contact_phones": [{ "phone": "+1 415 555 0133", "type": "mobile" }],
      "contact_current_experiences": [
        { "job_title": "VP Sales", "company_name": "Acme", "company_domain": "acme.com" }
      ]
    },
    "resume_data": {
      "experiences": [{ "job_title": "Director of Sales", "company_name": "Example Co" }],
      "educations": [],
      "certifications": []
    },
    "meta": { "schema": "leadocean.person.v1", "fetched_at": "2026-10-01" }
  },
  "meta": { "credits": 1, "source": "own" }
}

contact_emails and contact_phones appear only when you send reveal_email. The names and numbers above are placeholders, not a real person.

Troubleshooting

ErrorCauseFix
401Missing or wrong x-api-key headerRe-copy the key from the app and check $LEADOCEAN_API_KEY is exported
402The 1,000 free records are spentMove to Solo at $97 a month or Agency at $497 a month
404 on enrichNobody in the data matches the identifierCosts nothing. Try another identifier or search by domain first
429Requests above the plan's rate limit (5 a second on Free)Wait for the Retry-After header, then slow the loop
Empty search resultsA bad enum value, such as "vp" where the filter expects "VP"List the allowed values with GET /v1/enums
Export refusedThe request is over 50,000 rows or the 500,000 a day ceilingSplit the export across requests or days

FAQ

What is the difference between lead enrichment and a lead search?

Search finds people who match filters. Enrichment fills in one person you already know. In LeadOcean search spends one record per person returned, and enrich spends one per match.

How much does an enrichment call cost?

One record per person found. A miss is a 404 and is free. The Free plan holds 1,000 records for life. Paid plans use a fair-use pace instead of credits.

Can I run this from Claude instead of curl?

Yes. LeadOcean runs a hosted MCP server at https://api.leadocean.io/mcp with 13 tools and OAuth sign-in, so no key is pasted. Counting is free there too.

How fresh is the data?

The dataset is refreshed monthly. Each record also carries its own fetched_at date.

What should I read next?

Read the company version in what company enrichment is, the field-level view in profile enrichment, and the tool roundup in best lead enrichment tools. Plans are on pricing.

Enrich your first lead with a free API key

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

Get your free API key →