Enrich each sign-up from the work email they typed, score the result against your ICP, then send the lead to sales, nurture or self-serve. It is one API call and about 40 lines of code.
TL;DR
- One
POST /v1/people/enrichcall per sign-up, keyed on the email. A miss is a 404 and costs nothing. - Takes about 45 minutes to wire up. A scoring function decides the route: sales, nurture or self-serve.
- Spends 1 LeadOcean record per matched sign-up. Free gives you 1,000 records, once, with no card.
Prerequisites
- A LeadOcean key with the
enrichscope, exported as$LEADOCEAN_API_KEY. Start free. - A webhook or queue that fires when a user signs up and hands you the email.
- Somewhere to send the result: a CRM, a Slack channel or a sequencer. This guide stops at a JSON payload.
curland Python 3.10 or later.
Step 1: Size your ICP first
Count the people you want before you wire anything. It tells you whether your scoring rules are realistic. leadocean_count_leads (and the search count=true parameter) spend no records.
Prompt for any MCP client connected to https://api.leadocean.io/mcp:
Use leadocean_count_leads with jobLevel ["VP","C-Team"],
jobFunction ["Sales & Business Development"],
employeeRange ["51-200","201-500"], country ["US"], facets false.On 2026-10-21 this returned 61,084 people with a verified, catch-all-valid or catch-all email (203,746 with no email condition), across 28,019 employers. Those are the people your ICP rules describe. A sign-up that matches them scores high.
Step 2: Enrich the sign-up by email
Send the email from the sign-up form. Send exactly one identifier. reveal_email stays false: you already have the address.
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@acme.com"}'Skip free-mail domains (gmail.com, outlook.com) before you call. The email input is for work addresses, and you save the record.
Step 3: Pull the fields you score on
The response carries the person's current role in contact_data.contact_current_experiences[], plus profile_data and, since October 2026, resume_data with past roles. Keep a small flat object.
import os, requests
API = "https://api.leadocean.io/v1/people/enrich"
HEADERS = {"x-api-key": os.environ["LEADOCEAN_API_KEY"]}
FREE_MAIL = {"gmail.com", "outlook.com", "yahoo.com", "icloud.com"}
def enrich(email: str):
if email.split("@")[-1].lower() in FREE_MAIL:
return None
r = requests.post(API, headers=HEADERS, json={"email": email}, timeout=15)
if r.status_code == 404: # nobody matched, costs nothing
return None
r.raise_for_status()
p = r.json()["data"]
cur = (p["contact_data"].get("contact_current_experiences") or [{}])[0]
return {
"name": p["profile_data"].get("profile_full_name"),
"title": cur.get("job_title", ""),
"company": cur.get("company_name"),
"domain": cur.get("company_domain"),
"headcount": (cur.get("company_employees") or {}).get("number_of_employees"),
"past_roles": len((p.get("resume_data") or {}).get("experiences", [])),
}Each item in contact_current_experiences[] carries job_title, company_name, company_domain and company_employees, per the enrich docs. Past roles sit in resume_data.experiences[].
Step 4: Score it
Keep scoring boring and visible. Four rules, each worth points. Tune the weights against the deals you actually closed.
def score(lead: dict | None) -> int:
if not lead:
return 0
s = 0
t = lead["title"].lower()
if any(k in t for k in ("vp", "head of", "chief", "director", "founder")):
s += 40
if any(k in t for k in ("sales", "revenue", "growth", "marketing", "revops")):
s += 25
n = lead.get("headcount") or 0
if 50 <= n <= 500:
s += 25
if lead["past_roles"] >= 3:
s += 10
return sStep 5: Route it
Three routes. Put the thresholds in one place so sales can change them without you.
def route(email: str) -> dict:
lead = enrich(email)
pts = score(lead)
if pts >= 70:
dest = "sales" # alert an owner, book a call
elif pts >= 40:
dest = "nurture" # onboarding emails for a team buyer
else:
dest = "self_serve" # product-led path, no human touch
return {"email": email, "score": pts, "route": dest, "lead": lead}Post that payload to your CRM or a Slack webhook. For a no-code version of the same idea, see enrich, classify and route leads from Typeform submissions.
Step 6: Make it safe to run on every sign-up
Sign-up webhooks retry, and the same person signs up twice. Cache the result by email so a retry never spends a second record. Never block the sign-up on the call: enrich after the account exists.
import json, sqlite3
db = sqlite3.connect("enriched.db")
db.execute("create table if not exists e (email text primary key, payload text)")
def route_once(email: str) -> dict:
row = db.execute("select payload from e where email=?", (email,)).fetchone()
if row:
return json.loads(row[0])
out = route(email)
db.execute("insert into e values (?,?)", (email, json.dumps(out)))
db.commit()
return outRun it from a background job, not the request that creates the account. If the call times out, route the sign-up to self-serve and retry later. A late score is better than a slow sign-up page.
Step 7: Check the funnel weekly
After a month, compare the three routes against what happened next. Which score band booked calls? Which self-serve sign-ups became paying teams anyway? Move the thresholds in route() until the sales band holds the sign-ups your reps would have picked by hand.
Check two numbers: the share of sign-ups that matched (your hit rate) and the share routed to sales. A hit rate under half usually means many personal emails. Fix that at the form, not in the scoring.
A sizing note: at 500 work-email sign-ups a month and a hit rate of 60 percent, you spend about 300 records a month. That fits a Solo plan at $97 a month with room to spare. The Free plan covers a test run of your first 1,000 matches.
What you get
The response shape from the API reference, with placeholder values. This is not a captured response.
{
"success": true,
"data": {
"profile_data": { "profile_full_name": "Jane Doe" },
"contact_data": {
"has_email": true,
"has_phone": false,
"email_status": "verified",
"email_type": "work",
"contact_current_experiences": [
{
"job_title": "VP Sales",
"company_name": "Acme",
"company_domain": "acme.com",
"company_employees": { "number_of_employees": 120 }
}
]
},
"resume_data": { "experiences": [ { "job_title": "Director of Sales", "company_name": "Example Co" } ] },
"meta": { "schema": "leadocean.person.v1" }
}
}And the router output for that sign-up:
{ "email": "jane@acme.com", "score": 75, "route": "sales" }Source: api.leadocean.io/openapi.json, September 2026. Enrichment sees what is public and held in the dataset, which is refreshed monthly. Treat the score as a prior, not a verdict.
Troubleshooting
| Error | Cause | Fix |
|---|---|---|
| 401 | Missing or wrong x-api-key | Check $LEADOCEAN_API_KEY and that the key has the enrich scope. |
| 400 | More than one identifier in the body | Send only email, not email plus linkedin_url. |
| 404 | Nobody matched the email | Costs nothing. Route to self-serve with score 0. |
| 429 | Above the plan's rate limit (5 a second on Free, 200 on Agency) | Honor Retry-After, queue sign-ups, or move up a plan. |
| 402 | Records spent | Free is 1,000 records for life. See pricing. |
Empty contact_current_experiences | Profile has no current role on file | Score 0 for title, fall back to a manual review route. |
FAQ
How many records does one sign-up cost?
One record per person we return. A 404 or an enrichment that finds nothing costs nothing. See pricing for what each plan includes.
Can I enrich by name and company instead of email?
No. Enrich takes one of linkedin_url, email, phone or person_id. If you only have a name and domain, search by domain first, then enrich by person_id.
Should I enrich personal-email sign-ups?
Usually not. A Gmail address gives the match little to work with. Ask for a work email at a later step, or route those sign-ups to self-serve.
Which enrichment tools can do this?
Several can. More guides like this one are on the blog. For a comparison, read best lead enrichment tools. To run the same job from an AI client, see the enrich leads prompt.
Enrich your next sign-up in one call
Free to start. No credit card. 1,000 records to spend whenever you like.
Get your free API key →