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

How-to guide

How to Use Real-Time Lead Data to Optimize Your B2B Sales Pipeline (LeadOcean API)

Three calls: size the audience, enrich at entry, re-check what has gone stale.

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

TL;DR

  • Pipeline data goes bad in three places: the list you start from, the lead at the moment it enters, and the contact that sits for 90 days. Fix each with one API call.
  • It takes about 45 minutes to wire up.
  • It spends about 60 of the 1,000 free records. Counts cost nothing.

"Real-time" here means on demand: every call reads the current record, and each record carries its own fetched_at date. The dataset itself is refreshed monthly, so this is not a live feed. If a vendor promises minute-level change streams, ask for the proof.

Prerequisites

  • A LeadOcean account on the free plan (1,000 records for life, no card, 5 requests a second).
  • An API key from app.leadocean.io, exported as $LEADOCEAN_API_KEY.
  • curl and jq.
  • A place where leads land: a form handler, a CRM webhook or a CSV. Any of them works.

Step 1: Size the audience before you spend a record

Start with a free count, so you know whether the segment is worth pulling. The count tool is free however often you call it.

Run it with the LeadOcean MCP tool leadocean_count_leads. These are the filters.

json
{
  "jobLevel": ["VP"],
  "jobFunction": ["Sales & Business Development"],
  "country": ["US"],
  "industry": ["Computer Software"],
  "facets": false
}

Or over REST, with count=true as a query parameter and 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"],"industry":["Computer Software"],"limit":1}'

If the number is under 100, widen the filters. If it is over 100,000, meta.total stops at 100,000, so narrow instead. Enum values are exact strings. Check them with leadocean_list_enum_values before you guess.

Step 2: Pull a first page of people

Pull a small first page and look at it before you pull more. Filters are arrays, the body is flat JSON, 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 '{
    "jobLevel": ["VP"],
    "jobFunction": ["Sales & Business Development"],
    "country": ["US"],
    "industry": ["Computer Software"],
    "emailStatus": ["verified"],
    "limit": 25
  }' | jq '.data[0:2], .meta'

This spends 25 records, one per person returned. Page on with cursor from meta.nextCursor. One search pages to 10,000 rows. When meta.depthCapped is true, narrow the filters instead of walking further.

Filter on emailStatus here, not after the pull. A bounce is not refunded, so you want the verified status decided before the record reaches a sequencer.

Step 3: Enrich each lead the moment it enters

A lead from a form or a CRM webhook usually has an email and nothing else. Enrich it on arrival, so routing rules see title, level and company, not a blank row.

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

Enrich takes exactly one of linkedin_url, email, phone or person_id. There is no name-plus-domain lookup: search by domain first, then enrich by person_id. A person we hold nothing for returns a 404 and costs nothing.

Use the result to route. A simple rule set:

text
jobLevel in (C-Team, VP)       -> senior rep, same day
jobLevel in (Director, Manager) -> SDR queue
no match (404)                 -> nurture, do not score

Ten test leads cost at most 10 records.

Step 4: Re-check stale contacts before you chase them

Deals stall when the champion has left. Before a rep follows up on a contact that is 90 days old, enrich again and compare the current role.

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_2"}' \
  | jq '{current: .data.contact_data.contact_current_experiences, past: .data.resume_data.experiences}'

Compare contact_data.contact_current_experiences[] with the company on the opportunity. If they differ, the contact moved. Past roles sit in resume_data.experiences[]. Past employers carry no company_id yet, so match on the company name.

Re-check only open opportunities past a set age. Re-enriching the whole database wastes records.

What you get

The count from Step 1, run through the free leadocean_count_leads tool on 2026-10-21:

json
{
  "total": 208,
  "totalIsExact": true,
  "totalAll": 807,
  "distinctCompanies": 136,
  "defaults": "Counted only addresses worth sending to (emailStatus: verified or catch_all_valid or catch_all)",
  "unsupportedFilters": []
}

That is 208 VPs of sales in US software with a mailable address (verified, catch_all_valid or catch_all), out of 807 who match the other filters. They work at 136 companies.

The enrich response shape from the API reference (placeholder values, not a real person):

json
{
  "success": true,
  "data": {
    "profile_data": { "profile_full_name": "Jane Doe" },
    "contact_data": {
      "has_email": true,
      "email_status": "verified",
      "contact_current_experiences": [ { "job_title": "VP Sales", "company_name": "Acme" } ]
    },
    "resume_data": {
      "experiences": [ { "...": "title, company name, start and end dates, job level" } ],
      "educations": []
    }
  }
}

Fields appear only when we hold them. Addresses and phones come back only when you send reveal_email.

Troubleshooting

ErrorCauseFix
401Missing or wrong x-api-key headerCheck $LEADOCEAN_API_KEY is exported and sent as x-api-key.
429Above the plan's rate limit (5 a second on Free, 200 on Agency)Honour the Retry-After header, queue the calls, or move to a plan with a higher limit.
402Out of records on the Free planThe 1,000 records are spent. Move to Solo ($97 a month) or Agency ($497 a month).
Empty resultsA bad enum value, such as "VP Sales" for jobLevelLook up the exact string with leadocean_list_enum_values.
Search stops with depthCappedOne search pages to 10,000 rowsNarrow the filters and run a second search.
Export refusedOver 50,000 rows a request or 500,000 a daySplit the export by country or seniority. Bulk CSV export is not on Free.

FAQ

Is LeadOcean data real-time?

No. The dataset is refreshed monthly, and each record carries its own fetched_at date. What is on demand is the call: you read the current record when you ask.

How many records does this recipe spend?

About 60: 25 for the first search page, up to 10 for test enrichments and a handful for re-checks. Counts, a 404 and an enrichment that finds nothing cost nothing.

Can I run Step 3 from n8n or Zapier?

Yes. Both can call an HTTP endpoint on a webhook. See 5 real-time enrichment tools that append data the moment a lead comes in for a working setup.

Can an AI agent do this instead of a script?

Yes. The hosted MCP server at https://api.leadocean.io/mcp exposes 13 tools, including the free count tool used in Step 1. See real-time B2B data provider for AI agents. For post-level signals, see social posts API for real-time B2B data.

What does it cost at volume?

Free covers 1,000 records for life. Solo is $97 a month and Agency is $497 a month, with a fair-use pace instead of credits. See pricing. More guides are in the blog.

Count your own pipeline segment for free, then enrich the first leads

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

Get your free API key →