API reference
Search People
Searches LinkedIn live and returns up to limit leads (10 unless you say otherwise, at most 25). You pay per lead returned: ask for the number you want, and a search that finds nobody is free. Combine as many filters as you like: every filter narrows the result, and values inside one list are alternatives (["CFO", "CEO"] means CFO or CEO).
At least one filter is required. For more leads, send next_cursor back: it continues where this call stopped and keeps the result stable.
Every list filter takes 1 to 20 values of at most 200 characters. A value cannot contain a comma.
Authentication
Send your API key as a Bearer token: Authorization: Bearer gtk_…. Create the key under Connect assistant → API keys. A missing, invalid or revoked key is 401, including while an API is closed. On an endpoint of the Signals API or the Company API, a valid key while that API is closed for your organization answers 403 api_not_enabled, with what the key can do instead; the other endpoints work with every key. Every response includes mySDR-Api-Version, mySDR-Request-Id and Cache-Control: no-store, and a response to an accepted key also X-RateLimit-* (so not a 401, a 405, an OPTIONS or a 404 for an unknown path); every error has type, message, param and request_id.
Body parameters
keywordsstring— Free text, matched like the LinkedIn search box: name, headline, company.current_job_titlesstring[]— Job titles the person holds now, e.g.["CFO", "Head of Finance"]. Title matching is fuzzy: results are ranked by how well the title matches, so people with a different title can still appear. Addseniority_levelsorfunctionsfor a strict filter.past_job_titlesstring[]— Job titles the person held before.current_companiesstring[]— Where the person works now: company names or LinkedIn company URLs (https://www.linkedin.com/company/acme). URLs are the most precise.past_companiesstring[]— Where the person worked before; same format ascurrent_companies.exclude_current_companiesstring[]— Leave out people who work at these companies now.locationsstring[]— Where the person is based: country, region or city names in English, e.g.["Belgium", "Amsterdam"]. A two-letter code (BE,UK) is read as that country, so write a US state by its name (California, notCA).exclude_locationsstring[]— Leave out people based here; same format aslocations.schoolsstring[]— Schools or universities the person attended.first_namesstring[]— Exact first names.last_namesstring[]— Exact last names.seniority_levelsstring[]— Seniority of the current position. One of:in_training,entry_level,senior,strategic,entry_level_manager,experienced_manager,director,vice_president,cxo,owner_partner.exclude_seniority_levelsstring[]— Leave out these seniority levels. One of:in_training,entry_level,senior,strategic,entry_level_manager,experienced_manager,director,vice_president,cxo,owner_partner.functionsstring[]— Department of the current position. One of:accounting,administrative,arts_and_design,business_development,community_and_social_services,consulting,education,engineering,entrepreneurship,finance,healthcare_services,human_resources,information_technology,legal,marketing,media_and_communication,military_and_protective_services,operations,product_management,program_and_project_management,purchasing,quality_assurance,real_estate,research,sales,customer_success_and_support.exclude_functionsstring[]— Leave out these departments. One of:accounting,administrative,arts_and_design,business_development,community_and_social_services,consulting,education,engineering,entrepreneurship,finance,healthcare_services,human_resources,information_technology,legal,marketing,media_and_communication,military_and_protective_services,operations,product_management,program_and_project_management,purchasing,quality_assurance,real_estate,research,sales,customer_success_and_support.company_headcountsstring[]— Size of the current employer, as a headcount range. One of:self-employed,1-10,11-50,51-200,201-500,501-1000,1001-5000,5001-10000,10001+.years_of_experiencestring[]— Total years of work experience. One of:less_than_1,1_to_2,3_to_5,6_to_10,more_than_10.years_at_current_companystring[]— Years at the current employer. One of:less_than_1,1_to_2,3_to_5,6_to_10,more_than_10.profile_languagesstring[]— Language of the LinkedIn profile. One of:ar,cs,da,de,en,es,fr,in,it,ja,ko,ms,nl,no,pl,pt,ro,ru,sv,tl,tr,zh.recently_changed_jobsboolean— Only people who started a new position in the last 90 days.posted_on_linkedinboolean— Only people who posted on LinkedIn in the last 30 days.limitinteger— How many leads to return at most, 1 to 25. Defaults to 10. You pay 1 credit per lead returned, so this is also the most the call costs: 10 leads at most 10 credits.pageinteger— Start further down the result, 1 to 100. Defaults to 1. To continue a search, sendcursorinstead.cursorstring— Thenext_cursorof the previous response: continues where it stopped. Takes precedence overpage.max_creditsinteger— Stop before this call costs more than this. At 1 credit per lead, the call returns at most as many leads as fit (withtruncated_by: "max_credits"when that cut the result); below the price of one lead it is402max_credits_exceededand nothing is searched.
Response
resultsobject[]— The leads, at mostlimit. See the fields below.results[].linkedin_urlstring— Profile URL. Search returns the member-id form (/in/ACwAA…); it works as input for Enrich People, which returns the public URL.results[].linkedin_idstring | null— LinkedIn member id.results[].first_namestring | null— First name.results[].last_namestring | null— Last name.results[].full_namestring | null— First and last name together.results[].picture_urlstring | null— Profile photo. LinkedIn photo URLs expire after a few weeks.results[].locationobject—text: where the person is based, as LinkedIn shows it.results[].current_positionsobject[]— Positions held now:title,company_name,company_linkedin_url,started_on(year,month),tenure_at_positionandtenure_at_company(years,months).paginationobject—total_results(how many people match, as reported by the source),next_cursor(send it back for more leads; null when there are no more), andpageandtotal_pagesof the source.credits_usedinteger— Credits this call used: 1 credit per lead inresults, and 0 when nobody matched. When rows carrycredits_charged, each row carries its own 1.left_outobject— Only when someone was left out:excluded, how many people worked at a company on your exclusions (by name) or had their LinkedIn profile on them (GET /exclusions). They are not inresults, take no place inlimitand cost nothing.
Credits
1 credit per lead returned; no leads, no credits. 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— max_credits is below the price of one row, so nothing was looked up. Nothing was charged.
Example
cURL
curl -X POST "https://mysdr.app/api/v1/person/search" \
-H "Authorization: Bearer $MYSDR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"current_job_titles": [
"CFO",
"Head of Finance"
],
"locations": [
"Belgium"
],
"company_headcounts": [
"51-200",
"201-500"
],
"recently_changed_jobs": true,
"limit": 5
}'
JavaScript
const response = await fetch('https://mysdr.app/api/v1/person/search', {
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.MYSDR_API_KEY}`,
'Content-Type': 'application/json'
},
body: JSON.stringify({
"current_job_titles": [
"CFO",
"Head of Finance"
],
"locations": [
"Belgium"
],
"company_headcounts": [
"51-200",
"201-500"
],
"recently_changed_jobs": true,
"limit": 5
})
});
const body = await response.json();
Python
import json
import os
import urllib.request
payload = {
"current_job_titles": [
"CFO",
"Head of Finance"
],
"locations": [
"Belgium"
],
"company_headcounts": [
"51-200",
"201-500"
],
"recently_changed_jobs": True,
"limit": 5
}
request = urllib.request.Request(
"https://mysdr.app/api/v1/person/search",
headers={
"Authorization": f"Bearer {os.environ['MYSDR_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": [
{
"linkedin_url": "https://www.linkedin.com/in/ACwAAExample123",
"linkedin_id": "ACwAAExample123",
"first_name": "Jane",
"last_name": "Example",
"full_name": "Jane Example",
"picture_url": null,
"location": {
"text": "Ghent, Flemish Region, Belgium"
},
"current_positions": [
{
"title": "Chief Financial Officer",
"company_name": "Acme Analytics",
"company_linkedin_url": "https://www.linkedin.com/company/acme-analytics",
"started_on": {
"year": 2026,
"month": 7
},
"tenure_at_position": {
"years": 0,
"months": 2
},
"tenure_at_company": {
"years": 0,
"months": 2
}
}
]
}
],
"pagination": {
"page": 1,
"total_pages": 6,
"total_results": 131,
"next_cursor": "eyJwIjoyfQ"
},
"credits_used": 1
}