Search inputs
Use the people search API with natural-language criteria plus structured filters such as role, company, location, keywords, and pagination controls.
Send one JSON object. query, when present, must be a natural-language JSON string - never an Elasticsearch-style object. Put exact fields under custom_filters. For example, send {"query":"People currently working at acme.com","limit":1}, or a filter-only request such as {"custom_filters":{"companies":["acme.com"]},"limit":25}. Do not send {"query":{"company_domain":"acme.com"}}. Submit each page once. A new search returns 202 plus a request_id; a page already cached for that request can return 200 immediately. Poll GET /person/search?request_id=... with the same credentials every two seconds. A processing poll is 202 with data.completed: false; a completed poll is 200 with data.completed: true. Stop on completion or a terminal 4xx/5xx response. Polling is free. Alternatively, supply callback_url for webhook delivery. Use /company/employees for a broad company roster and /person/search when role, title, location, or other person criteria matter.
Manual credentials take precedence over your account key.
The People Search API finds matching people from a natural-language query and structured filters, then returns profile candidates you can qualify, enrich, or route into sales and data workflows.
Use the people search API with natural-language criteria plus structured filters such as role, company, location, keywords, and pagination controls.
Each result is a candidate person record with enough profile context to qualify the match before you enrich, score, or route it.
Send matched identifiers into Person Enrichment when you need a complete profile, contact fields, or social context.
query and/or structured custom_filters - at least one is required unless paginating with cursor or request_id. With no query, the search runs purely on custom_filters.insights.why_matched contains concise evidence chips showing the criterion, evidence type, confidence, and a safe short matched phrase when available. Most useful when a query is supplied.score (integer 1-5) ranking how well each profile matches the query. Most useful when a query is supplied.locations, titles, companies, universities, degrees, specialization_categories, plus the array filters industries (industry names, lowercase; common taxonomy synonyms accepted, e.g. ["fintech","financial services"]), keywords (free-text terms that must each appear in the profile text/skills/interests; multiple keywords are ANDed), and languages (spoken languages, 2-3 common forms each, e.g. ["spanish","espanol"] or ["chinese","mandarin","中文"]). companies matches current employers and accepts company names, domains such as acme.com, or company profile URLs. Employer-company filters include min_company_employee_count/max_company_employee_count, company_employee_count_scope, min_company_total_funding_raised/max_company_total_funding_raised, company_funding_stages, company_latest_funding_stages, company_investor_names, company_last_funding_after_date/company_last_funding_before_date, company_funding_round_filters, and company_funding_scope. Each company_funding_round_filters item binds its supplied stages, investor_names, min_amount/max_amount, funded_after_date/funded_before_date, and funded_within_days to the same funding event. Supports array filters (any-of), numeric ranges, booleans, and exact-match values.next_cursor. Submitting it fetches the next page.offset + limit may not exceed 10000.offset/limit to page through results, or poll for completion with a GET (polling never consumes credits).This endpoint is asynchronous. A successful submit returns a request_id while the job runs in the background. Poll the same path with a GET request - same authentication headers - passing the request_id as a query parameter:
Each poll returns the job's current status; once it is completed the payload carries the result shown under Responses. Polling an
unknown or expired request_id returns 404 request_not_found.
| Status | Meaning |
|---|---|
| queued · processing · pending | The job is still running - keep polling. |
| completed | The job finished; the payload carries the result and completed: true. |
| failed | Terminal - the job could not complete; the error field explains why. |
Poll every few seconds at first, backing off for long-running jobs. Polling is free - status checks never burn credits.
callback_url parameter and the completed payload is POSTed to your endpoint
when the job finishes - no polling required. Delivery is retried up to 5 times with exponential backoff (1s,
5s, 15s, 1m, 5m) and a 30-second timeout per attempt; respond with a 2xx status to acknowledge receipt.A completed search returns one page of results plus the cursor and counters you need to walk the rest. Each search request (a POST) that returns results is billed for the results on that page; only polling an in-flight search with a GET + request_id is free. offset + limit may not exceed 10000.
Every completed response carries these fields - read them to decide whether to fetch another page:
| Field | What it tells you |
|---|---|
| has_more | true means more results are available beyond this page - fetch the next page. false means you have reached the end; stop. |
| next_cursor | An opaque token for the next page. Present only when has_more is true (omitted on the last page). Pass it back as the cursor parameter - it already encodes the next offset, limit and request_id. |
| total_estimate | Approximate total number of matches for the query. Use it to size a progress bar or decide how many pages to pull; treat it as an estimate, not an exact count. |
| offset / limit | The slice this response represents: results offset through offset + limit - 1. |
| Method | How |
|---|---|
| Cursor (recommended) | Take next_cursor from the response and send it as cursor on the next request (no other params needed). Repeat until has_more is false. |
| request_id + offset | Re-send the original request_id with an increasing offset (e.g. offset: 25, then 50, using your chosen limit). |
| Repeat the query + offset | Re-submit the same query (and identical custom_filters) with a higher offset. The service matches it to the existing search session. Prefer cursor or request_id when you have them - they are unambiguous. |
Pagination is forward-only and consistent within a search session: results keep their position, so paging never skips or duplicates a person. Each page you request with a POST is charged for the results it returns; checking status with a GET and a request_id is always free, so you can re-read data you have already retrieved without being charged again.
Credits are charged based on the matched configuration. The listed cost is the per-result unit price.
| Feature | Credits | Notes |
|---|---|---|
| Person Search | 1 | base credits per result returned |
| Smart Ranking | +1 | per result when profile_scoring: true |
| Candidate Insights | +1 | per result when insights: true |
| Structured Filters | +1 | per result when custom_filters is non-empty |
| Email Data | +6 | per result when show_emails or require_emails is true |
| Phone Data | +6 | per result when show_phone_numbers or require_phone_numbers is true |
| Any Contact Data | +6 | per result when require_phones_or_emails is true and no email/phone add-on is already enabled |
A newly queued submit returns 202 Accepted. It contains the polling identifier, not the result:
{
"success": true,
"data": {
"request_id": "abc12345_1737123456_1234",
"status": "processing",
"completed": false,
"message": "Search request is being processed. Poll GET /person/search with request_id to check status.",
"offset": 0,
"limit": 10
},
"timestamp": "2026-01-01T00:00:00"
}A successful terminal poll returns 200 with the completed payload:
{
"success": true,
"data": {
"request_id": "abc12345_1737123456_1234",
"status": "completed",
"completed": true,
"results": [
{
"profile_id": "johnsmith",
"displayname": "John Smith",
"firstname": "John",
"middlename": "A",
"lastname": "Smith",
"gender": "male",
"headline": "Senior Sales Manager at Tech Corp",
"bio": "Enterprise sales leader with 15 years closing Fortune 500 accounts.",
"location": "San Francisco, CA",
"altemails": [
"john.smith@techcorp.com",
"john.smith@gmail.com"
],
"fullphone": [
{
"fullphone": "+1-555-123-4567",
"phone_type": "mobile"
}
],
"social_profiles": {
"linkedin": {
"url": "https://linkedin.com/in/johnsmith",
"username": "johnsmith",
"followers": 1200,
"connections": 500
}
},
"organizations": [
{
"name": "Tech Corp",
"company_domain": "techcorp.com",
"company_employee_count": 1200,
"company_employee_count_range_start": 1001,
"company_employee_count_range_end": 5000,
"company_total_funding_raised": 25000000,
"company_latest_funding_stage": "series b",
"company_funding_stages": [
"seed",
"series a",
"series b"
],
"company_funding_rounds": [
{
"stage": "series b",
"date": "2025-10-03",
"amount": 15000000,
"investor_names": [
"sequoia capital"
]
}
],
"company_last_funding_date": "2025-10-03",
"company_investor_names": [
"sequoia capital"
],
"title": "Senior Sales Manager",
"startDate": "2020-03",
"endDate": null
}
],
"schools_info": [
{
"name": "University of California, Berkeley",
"degree": "BS",
"specialization_category": "Business",
"startDate": "2001",
"endDate": "2005"
}
],
"skills": [
"enterprise sales",
"negotiation"
],
"languages": [
"english"
],
"estimated_age": 42,
"score": 5,
"insights": {
"overall_summary": "Strong match: senior sales leadership at a large enterprise in the target metro.",
"why_matched": [
{
"criterion": "Sales managers at Fortune 500 companies",
"evidence_type": "work_experience",
"confidence": "strong",
"display_text": "Current role shows senior sales management at Tech Corp.",
"matched_phrase": "Senior Sales Manager at Tech Corp"
},
{
"criterion": "San Francisco",
"evidence_type": "location",
"confidence": "strong",
"display_text": "Profile location is in the requested metro."
}
],
"query_insights": [
{
"subquery_idx": 0,
"subquery": "Sales managers at Fortune 500 companies",
"priority": "Essential",
"match_level": "Meets Expectations",
"short_rationale": "Senior Sales Manager at a Fortune 500 company.",
"rationale": "Currently Senior Sales Manager at Tech Corp, a Fortune 500 enterprise.",
"short_quotes": [
"Senior Sales Manager at Tech Corp"
]
}
]
}
}
],
"offset": 0,
"limit": 10,
"total_estimate": 500,
"has_more": true,
"next_cursor": "eyJvIjoxMCwiciI6ImFiYzEyMzQ1…",
"credits_charged": 160
},
"timestamp": "2026-01-01T00:00:00"
}