API reference
Enrich People
Fetches each profile live from LinkedIn: current and past positions, education, skills, languages and certifications. Send up to 25 URLs per call; each gets its own entry in `results`, in the order you sent them.
Fetches each profile live from LinkedIn: current and past positions, education, skills, languages and certifications. Send up to 25 URLs per call; each gets its own entry in results, in the order you sent them.
A profile that does not exist, or a URL that is not a LinkedIn profile, costs nothing. With include_email, we also look for a work email (name and company domain, checked over SMTP) — if we only find a personal address, you get that one instead.
Calls with many profiles take a while: count on about 5 seconds per profile, spread over parallel lookups. Set your HTTP timeout to at least 120 seconds. A found profile costs 2 credits. A found email adds 10. This endpoint has no phone field. A work email together with a phone number is the in-app contact reveal (40 credits) and is not a call on this API.
Authentication
Send Authorization: Bearer gtk_…. This People endpoint answers when your key is valid. max_credits, and person_ids on enrich, are accepted only when the Signals API is open for your organization. Otherwise those fields are unknown and the call is 400.
Body parameters
profile_urlsstring[]— 1 to 25 LinkedIn profile URLs, e.g.https://www.linkedin.com/in/jane-example. The member-id form that Search People returns works too. Send this orperson_ids, not both.person_idsstring[]— 1 to 25 person ids (per_…) from an earlier response of your organization, kept for 30 days. An id this organization does not know isnot_foundand costs nothing. Accepted when the Signals API is open for your organization.include_emailboolean— Also look for an email address. Adds 10 credits per address found. Defaults to false. This endpoint does not look up a phone number.max_creditsinteger— Stop before the call costs more than this. A profile that would not fit is not looked up. Below the cost of one profile the call is402max_credits_exceededand nothing is looked up. Accepted when the Signals API is open for your organization.
Response
resultsobject[]— One entry per URL you sent, in the same order.results[].inputstring— The URL as you sent it.results[].statusstring—matched,not_found(no such profile),invalid_url(not a LinkedIn profile URL) orerror(lookup failed; retry later). One of:matched,not_found,invalid_url,error.results[].personobject | null— The profile when the status ismatched, otherwise null. See the fields below.person.linkedin_urlstring— Public profile URL.person.linkedin_idstring | null— LinkedIn member id.person.public_identifierstring | null— The slug in the profile URL.person.first_name / last_name / full_namestring | null— Name.person.headlinestring | null— Headline under the name.person.aboutstring | null— The About section.person.locationobject—textas LinkedIn shows it, pluscity,state,countryandcountry_code(ISO 3166-1 alpha-2) when known.person.picture_urlstring | null— Profile photo. LinkedIn photo URLs expire after a few weeks.person.connections_count / follower_countinteger | null— Network size.person.open_to_work / hiring / premiumboolean | null— Profile badges.person.current_positionsobject[]— The entries ofexperiencethat are still ongoing.person.experienceobject[]— Positions, newest first:title,company_name,company_linkedin_url,location,employment_type,workplace_type,start_dateandend_date(year,month;end_dateis null while ongoing),is_current,duration,description.person.educationobject[]—school_name,school_linkedin_url,degree,field_of_study,start_date,end_date,description.person.skillsstring[]— Skills, top skills first.person.languagesobject[]—nameandproficiency.person.certificationsobject[]—name,issued_by,issued_at.person.emailobject | null— Only withinclude_email:address,type(workorpersonal),deliverableandcatch_all(booleans from the SMTP check; null when unknown) andquality_score. Null when nothing was found.credits_usedinteger— Credits this call used.
Credits
2 credits per profile found, +10 per email found Errors and empty lookups are free. A call that spent credits puts that number in credits_used, in X-Credits-Used and in X-Credits-Charged. When the wallet can be read, the response also sends X-Credits-Remaining.
Errors
- 400
invalid_request— The body is not valid JSON, a field is unknown or has the wrong type, or a value is not allowed. - 401
authentication_error— The Authorization header is missing, or the key is unknown or revoked. - 403
permission_error— API access is not part of your plan, or your account is suspended. - 429
rate_limit_error— More than 60 requests per minute, or more than 3 at the same time, on one key. Wait for the Retry-After header. - 429
daily_limit_reached— The request could take your organization over its daily credit limit. The limit resets at midnight (Europe/Brussels). - 502
upstream_error— The data source did not answer. Retry later. - 503
service_unavailable— The API is temporarily unavailable. Retry later. - 500
internal_error— Something went wrong on our side. - 402
max_credits_exceeded— Only when the Signals API is open and max_credits is below one row.
Example
cURL
curl -X POST "https://foundermcp.dev/api/v1/person/enrich" \
-H "Authorization: Bearer $FOUNDERMCP_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"profile_urls": [
"https://www.linkedin.com/in/jane-example",
"https://www.linkedin.com/in/does-not-exist-123"
],
"include_email": true
}'
JavaScript
const response = await fetch('https://foundermcp.dev/api/v1/person/enrich', {
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.FOUNDERMCP_API_KEY}`,
'Content-Type': 'application/json'
},
body: JSON.stringify({
"profile_urls": [
"https://www.linkedin.com/in/jane-example",
"https://www.linkedin.com/in/does-not-exist-123"
],
"include_email": true
})
});
const body = await response.json();
Python
import json
import os
import urllib.request
payload = {
"profile_urls": [
"https://www.linkedin.com/in/jane-example",
"https://www.linkedin.com/in/does-not-exist-123"
],
"include_email": true
}
request = urllib.request.Request(
"https://foundermcp.dev/api/v1/person/enrich",
headers={
"Authorization": f"Bearer {os.environ['FOUNDERMCP_API_KEY']}",
"Content-Type": "application/json"
},
data=json.dumps(payload).encode(),
method="POST",
)
with urllib.request.urlopen(request) as response:
body = json.load(response)
Example response
{
"results": [
{
"input": "https://www.linkedin.com/in/jane-example",
"status": "matched",
"person": {
"linkedin_url": "https://www.linkedin.com/in/jane-example",
"linkedin_id": "ACwAAExample123",
"public_identifier": "jane-example",
"first_name": "Jane",
"last_name": "Example",
"full_name": "Jane Example",
"headline": "CFO at Acme Analytics",
"about": null,
"location": {
"text": "Ghent, Flemish Region, Belgium",
"city": "Ghent",
"state": "Flemish Region",
"country": "Belgium",
"country_code": "BE"
},
"picture_url": null,
"connections_count": 500,
"follower_count": 1204,
"open_to_work": false,
"hiring": false,
"premium": true,
"current_positions": [
{
"title": "Chief Financial Officer",
"company_name": "Acme Analytics",
"company_linkedin_url": "https://www.linkedin.com/company/acme-analytics",
"location": "Ghent, Belgium",
"employment_type": "Full-time",
"workplace_type": "Hybrid",
"start_date": {
"year": 2026,
"month": 7
},
"end_date": null,
"is_current": true,
"duration": "3 mos",
"description": null
}
],
"experience": [
{
"title": "Chief Financial Officer",
"company_name": "Acme Analytics",
"company_linkedin_url": "https://www.linkedin.com/company/acme-analytics",
"location": "Ghent, Belgium",
"employment_type": "Full-time",
"workplace_type": "Hybrid",
"start_date": {
"year": 2026,
"month": 7
},
"end_date": null,
"is_current": true,
"duration": "3 mos",
"description": null
}
],
"education": [
{
"school_name": "Ghent University",
"school_linkedin_url": null,
"degree": "Master of Science",
"field_of_study": "Business Economics",
"start_date": {
"year": 2008,
"month": null
},
"end_date": {
"year": 2012,
"month": null
},
"description": null
}
],
"skills": [
"Financial Planning",
"M&A"
],
"languages": [
{
"name": "Dutch",
"proficiency": "Native or bilingual proficiency"
}
],
"certifications": [],
"email": {
"address": "jane@acme-analytics.example",
"type": "work",
"deliverable": true,
"catch_all": false,
"quality_score": 95
}
}
},
{
"input": "https://www.linkedin.com/in/does-not-exist-123",
"status": "not_found",
"person": null
}
],
"credits_used": 12
}