Send the email to GET /v2/people/reverse and read linkedin_url from the response. You skip the manual search. Each call costs 1 record, including a call that finds nobody.
This guide covers one address, the cases where the URL comes back empty, and a bash loop for a list.
TL;DR
- One call to
GET /v2/people/reversewithemail=returns the person, title, company and LinkedIn URL. - Setup takes about 10 minutes. The loop runs at up to 5 requests a second on Free and 200 on Agency.
- Each reverse call spends 1 record, hit or miss. Enrich by email charges only for matches. Free gives you 1,000 records once, no card.
Prerequisites
- A LeadOcean API key with the
enrichscope, exported as$LEADOCEAN_API_KEY. Start free: Free keys get both scopes. curlandjq.- A list of emails to look up, one per line, in
emails.txt.
Step 1: Look up one email
Pass the address as a query parameter. Use -G with --data-urlencode so a + in the address survives.
curl -s -G "https://api.leadocean.io/v2/people/reverse" \
--data-urlencode "email=jane.doe@acme.com" \
-H "x-api-key: $LEADOCEAN_API_KEY"The same endpoint also takes phone= instead of email=. Send one, never both. There is a POST version with a JSON body ({"email": "jane.doe@acme.com"}) if you prefer it.
If you expect many misses, send the address to POST /v1/people/enrich with email instead. A person we hold nothing for is a 404 there and costs nothing. The full record carries the profile link at profile_data.profile_url (enrich docs).
Step 2: Read the profile URL
Pipe the response through jq to keep only what you need.
curl -s -G "https://api.leadocean.io/v2/people/reverse" \
--data-urlencode "email=jane.doe@acme.com" \
-H "x-api-key: $LEADOCEAN_API_KEY" \
| jq '.data | {linkedin_url, full_name, job_title, company_name, person_id}'Two fields matter most. linkedin_url is the profile. person_id is the handle you keep if the URL is empty.
Step 3: Handle a missing LinkedIn URL
About one person in five has no LinkedIn URL on record, so linkedin_url can be null on a real match. Keep the person_id and enrich it for the full record.
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": "1234567"}'Enrich takes exactly one of linkedin_url, email, phone or person_id. It costs 1 more record, so call it only for the rows that need it. Since October 2026 it also returns career history: past roles, education and certifications.
Step 4: Run a list
The docs describe no batch version of the reverse endpoint, so a list is one call per address. This loop writes a CSV of email,linkedin_url, skips misses and backs off on a 429. Every call spends 1 record, including the misses.
#!/usr/bin/env bash
echo "email,linkedin_url,full_name,job_title"
while read -r email; do
while :; do
code=$(curl -s -o /tmp/lo.json -w "%{http_code}" -G \
"https://api.leadocean.io/v2/people/reverse" \
--data-urlencode "email=$email" \
-H "x-api-key: $LEADOCEAN_API_KEY")
[ "$code" = "429" ] && { sleep 1; continue; }
break
done
if [ "$code" = "200" ]; then
jq -r --arg e "$email" \
'.data | [$e, (.linkedin_url // ""), (.full_name // ""), (.job_title // "")] | @csv' /tmp/lo.json
fi
sleep 0.25
done < "$1"Save it as lookup.sh and run ./lookup.sh emails.txt > profiles.csv. The sleep 0.25 keeps you under the Free limit of 5 requests a second. On Agency (200 a second) shorten it. Keep one key per script, because the limit is per key.
Step 5: Run it from an AI agent
The MCP server has no tool named for reverse lookup. Use leadocean_get_lead and pass the email. It returns the full person record and counts as 1 record.
Find the LinkedIn profile for jane.doe@acme.com.
Return the profile URL, the job title and the company.Connect the server at https://api.leadocean.io/mcp. Sign-in is OAuth, so no key is pasted. The email to LinkedIn page has the setup.
What you get
This is the response shape from the API reference, with placeholder values. It is not a live record.
{
"success": true,
"data": {
"person_id": "1234567",
"person_group_id": "1234567",
"linkedin_url": "https://www.linkedin.com/in/jane-doe",
"full_name": "Jane Doe",
"job_title": "Finance Manager",
"company_name": "Acme",
"company_domain": "acme.com",
"query": { "email": "jane.doe@acme.com" },
"matched": { "email": "jane.doe@acme.com", "status": "verified",
"verified_batch_date": "2026-09-14", "type": "work" },
"matched_in_record": true
},
"meta": { "source": "leadocean", "schema": "leadocean.contact.reverse.v2",
"stability": "stable", "credits": 1 }
}Check matched_in_record. When it is false, the person was matched on your email upstream but the record does not list that exact address. Verify the profile before you act on it.
If nobody holds the address, the API answers 404. A v2 contact call still costs 1 record when it finds nothing.
Check the match before you use it
A match is evidence, not proof. Three checks take seconds and catch most bad rows.
matched_in_record.truemeans the record lists the exact address you sent.falsemeans the match came through another route, so look at the profile yourself.matched.status. It carries the deliverability status of the address you sent, such asverifiedorcatch_all. A profile found from aninvalidaddress is weaker evidence.company_domain. Compare it with the domain in the email. A work address at acme.com should return a person at acme.com. If it does not, the person may have changed jobs, so checkjob_titleand the profile.
Records can duplicate. The same person may appear under different person_id values. Compare person_group_id to deduplicate your output.
Pick the cheapest path for your volume
Reverse lookup spends 1 record per call, hit or miss. Enrich by email spends 1 record per match only. Either way a sample run is cheap.
- Under 1,000 emails, one time. The Free plan covers it. No card, no monthly fee.
- A list you refresh every week. Solo is $97 a month for one person, with phones and bulk CSV export included.
- A team or an agency. Agency is $497 a month with 5 keys and 200 requests a second. Paid plans run on a fair-use pace, not credits.
Run 100 addresses first and count the 404s. That is your real match rate on your own list. The docs publish no match rate for reverse lookups, so your sample is the only honest number. Plans and limits are on the pricing page.
Troubleshooting
| Error | Cause | Fix |
|---|---|---|
| 401 | Missing or wrong x-api-key header | Check that $LEADOCEAN_API_KEY is set in the shell that runs the script. |
| 403 | The key lacks the enrich scope | Create a key with the enrich scope in app.leadocean.io. |
| 404 | No person holds that email or phone | Expected for some addresses. Skip the row. For free misses, enrich by email instead. |
| 429 | Above the plan's rate limit: 5 a second on Free, 200 on Agency | Wait for the Retry-After header, then retry. The loop above sleeps 1 second. |
| 402 | The key has spent its records | Free allows 1,000 once. Move to Solo or Agency. A 402 is never billed. |
200 with linkedin_url null | The person has no LinkedIn URL on record | Enrich by person_id (Step 3). |
FAQ
Can I search LinkedIn itself by email?
You query a dataset that holds the email next to the profile, not LinkedIn. LeadOcean holds 693M people, 366M with an email (measured 2026-09-23).
Does a personal email work?
The endpoint takes any email address, and matched.type labels the one you sent. The docs publish no match rate per address type. Test a sample of your own list first.
How many records does a list cost?
One per email on the reverse endpoint, hit or miss. On enrich by email only matches cost, so 10,000 emails cost 10,000 records or fewer. Free covers the first 1,000 once. Agency is $497 a month with no per-record price, inside fair use.
Can I go from a LinkedIn URL to an email instead?
Yes. See LinkedIn to email and the guide to finding an email from a LinkedIn profile. More guides are on the blog.
Look up your first LinkedIn profile by email, free
Free to start. No credit card. 1,000 records to spend whenever you like.
Get your free API key →