You can turn a GitHub handle into a contactable candidate record in three calls, but not with one lookup. LeadOcean's enrich endpoint takes a LinkedIn URL, an email, a phone or a person_id. It does not take a GitHub URL. This guide shows the bridge: GitHub's public API gives you a name, a company and sometimes an email, and LeadOcean resolves the person from there.
Some APIs do take a GitHub URL directly. Crustdata's guide resolves a handle and returns a match confidence score (Crustdata blog, September 2026). If one-call handle lookup matters more to you than record cost, test that route. If you want a flat monthly plan with no per-record price, which you can script and verify yourself, read on.
TL;DR
- Fetch the profile from GitHub's public API, then enrich by email when GitHub shows one, or search by name and company when it does not.
- Time: about 15 minutes to wire up, under a second per candidate after that.
- Records: 1 when GitHub exposes an email, up to 4 when you need a search first (3 search rows plus 1 enrich).
Prerequisites
- A LeadOcean API key in
$LEADOCEAN_API_KEY. The Free plan has 1,000 records, one-off, no card (sign up). Free keys get both the search and enrich scopes. curlandjq.- A GitHub handle. Examples use the placeholder
janedoe. A GitHub token is optional. Without one, GitHub allows 60 requests an hour per IP address (GitHub docs, September 2026).
Step 1: Pull the profile from GitHub
GitHub's GET /users/{username} returns the fields you need for matching: name, company, location, blog, email and bio (GitHub docs, September 2026). Each field is null when the user left it blank.
curl -s https://api.github.com/users/janedoe \
| jq '{login, name, company, location, blog, email, bio}'The response, with placeholder values:
{
"login": "janedoe",
"name": "Jane Doe",
"company": "@acme",
"location": "Berlin, Germany",
"blog": "https://janedoe.example",
"email": null,
"bio": "Systems engineer. Rust, Postgres."
}Expect email to be null most of the time. GitHub also lets people commit under a noreply address (GitHub docs, September 2026), which is not an inbox. Do not enrich on it.
Step 2: Pick the route
Three cases cover almost every profile. The first one that applies wins.
| GitHub gives you | LeadOcean call | Records |
|---|---|---|
A LinkedIn URL in blog or bio | POST /v1/people/enrich with linkedin_url | 1 |
A public email | POST /v1/people/enrich with email | 1 |
| Only name, company, location | POST /v1/people/search, then enrich by person_id | up to 4 |
A 404 on enrich costs nothing, so trying the cheap routes first is free when they miss.
Step 3: Enrich by LinkedIn URL or email
Send exactly one identifier. Sending two is a 400. Set reveal_email to true to get addresses and phones back. It costs no extra 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 '{"email": "jane.doe@acme.com", "reveal_email": true}'Swap the body for {"linkedin_url": "https://www.linkedin.com/in/janedoe-example", "reveal_email": true} when the blog field holds a profile link. Both bodies go to the same endpoint. A work address works best. A personal address may 404, and a 404 is free.
Step 4: No email? Search by name and company
Search takes a flat JSON body. q is free text over name, headline, title and company, and companyName is an array. Keep limit small: every row returned is a record.
curl -s -X POST https://api.leadocean.io/v1/people/search \
-H "x-api-key: $LEADOCEAN_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"q": "Jane Doe",
"companyName": ["Acme"],
"country": ["DE"],
"limit": 3
}'Search rows are a thin projection with no contact points. Read three things per row before you spend again: the name and company against GitHub, contact_data.has_email, and meta.source_ids.person_id. About a fifth of people have no LinkedIn URL, so person_id is the key that always works.
Step 5: Enrich the matching row
Send the person_id back exactly as the search returned it.
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": "1234567890", "reveal_email": true}' \
| jq '{name: .data.profile_data.full_name,
emails: [.data.contact_data.contact_emails[] | {email, type, status}]}'Do not trust the first row blindly. LeadOcean returns no confidence score for a GitHub match, because it never sees the handle. Check at least two signals: current company against the GitHub company field, and city against location. If two candidates fit, pick none and send a human a short list.
What you get
Sizing comes first, and it is free. Say you want Rust engineers in Germany to cross-check against your GitHub shortlist. The MCP tool leadocean_count_leads ran on 2026-10-21 with these filters and spent 0 records:
title: ["Software Engineer"], keywords: ["Rust"], country: ["DE"]
-> total 607, totalIsExact true, totalAll 1,860, credits 0
keywords: ["Rust"], jobFunction: ["Engineering"], country: ["DE"]
-> total 1,418, totalIsExact true, totalAll 4,669, credits 0Both counts are mailable audiences. They count only verified, catch_all_valid and catch_all addresses, which is the tool's default. totalAll is the same filters with no email condition.
The enrich response, as documented in the API reference (response shape from the API reference, placeholder values only):
{
"success": true,
"data": {
"profile_data": {
"full_name": "Jane Doe"
},
"contact_data": {
"has_email": true,
"email_status": "verified",
"email_type": "work",
"contact_emails": [
{
"email": "jane.doe@acme.com",
"type": "work",
"status": "verified",
"verified_batch_date": "2026-09-20"
}
]
},
"resume_data": { "experiences": [], "educations": [], "skills": [] },
"meta": { "schema": "leadocean.person.v1", "fetched_at": "2026-09-20" }
},
"meta": { "credits": 1 }
}Since October 2026, resume_data carries career history. Past roles sit in experiences[] with title, company and dates, plus education and skills when held. Compare the past employers with the GitHub company field. Read email_type and email_status before you send. work means the address is at their current employer. work_other is a former employer and the likeliest to bounce. There is no refund for bounced emails.
Troubleshooting
| Error | Cause | Fix |
|---|---|---|
| 401 | Missing, wrong or revoked key | Check the x-api-key header and that $LEADOCEAN_API_KEY is set in this shell. |
| 403 | The key lacks the search or enrich scope | Create a key with both scopes in the app. |
| 400 on enrich | More than one identifier sent | Send one of linkedin_url, email, phone or person_id. |
| 404 on enrich | Nobody matched, or no contact point is held | Free. Try another identifier or move to the search route. |
Empty search data | A filter value is not an exact enum string | Check values with leadocean_list_enum_values or GET /v1/enums. |
| 429 | Above your plan's rate limit per account (5 a second on Free, 50 on Solo, 200 on Agency) | Wait for Retry-After and retry. |
| 402 | Free plan: the 1,000 records are spent | They do not reset. Move to Solo, $97 a month (pricing). |
FAQ
Can LeadOcean look up a candidate by GitHub URL?
No. Enrich takes a LinkedIn URL, an email, a phone or a person_id. Use GitHub's own API to get a name, company or email first, then resolve the person here.
How many records does one candidate cost?
One if GitHub shows a LinkedIn link or a public email. Up to four if you search first: three rows at limit 3, then one enrich. A 404 on enrich costs nothing.
Is a public GitHub email enough to enrich?
Often yes, if it is a real address. A noreply address will not match anyone. A personal address may 404, which costs nothing, so fall back to the name and company search.
Can I run this from an AI agent instead of curl?
Yes. The hosted MCP server at https://api.leadocean.io/mcp signs in with OAuth and exposes search_leads and get_lead as tools. They spend records exactly as the REST calls do. For a related recipe, see web search to enrich candidates with papers, talks and posts.
Where do I compare this with other people APIs?
Start with the best people search APIs and the people data API page. More guides are on the blog.
Turn your GitHub shortlist into contactable candidates
Free to start. No credit card. 1,000 records to spend whenever you like.
Get your free API key →