Documentation
Find people and companies by ICP rather than one at a time. 693M people, 63M companies, 50 people filters and 34 company filters, with cursor paging and a stable response envelope.
/v1/people/search and /v1/companies/search answer from an index of 693,080,309 people and 63,569,167 companies. Page with meta.nextCursor; one record is counted per person returned. A 503 from these endpoints now means the index is temporarily unreachable rather than absent — retry with backoff.Person enrichment and company lookup answer today, from our own store.
GET /v1/people/search · 1 record per person returned · scope search
Also accepted as POST with a JSON body, which is easier once you have more than a handful of filters. Combine any of the people filters; they join with AND, while several values inside one filter join with OR.
| Field | Type | Meaning |
|---|---|---|
| (filters) | see the filter reference | Any people filter. Arrays are comma-separated in a query string, JSON arrays in a POST body. |
| limit | integer · 1–100 · default 25 | People per page. Each person returned counts one record. |
| count | boolean · default false | Also return meta.total, capped at 100,000. With limit=1 this is a free sizing call: no rows, no records spent, meta.countOnly: true. |
| cursor | string | meta.nextCursor from the previous page, passed back exactly as it was handed to you. |
Results are thin person records — identity, headline, current role and company, location, and the has_email / email_status / email_type flags. That is enough to decide who is worth pursuing. Contact points come from enrichment, which is a separate call on the people you actually chose.
email_type says what kind the person’s best address is, and the emailType filter takes the same values — so emailStatus=verified&emailType=work asks for a deliverable address at the company they work for now. Without it a B2B list quietly includes people whose only good address is webmail, or worse is at an employer they left: that is work_other, and it is a separate value precisely so you never get it by asking for work. Use work_any when you want both.
GET /v1/companies/search · 1 record per company returned · scope search
The same idea, company-side: industry, headcount, revenue, funding, technologies and headquarters. Also accepted as POST. Records come back in the leadocean.company.v1 shape.
| Field | Type | Meaning |
|---|---|---|
| (filters) | see the filter reference | Any company filter — industry, headcount, revenue, funding, technologies, headquarters. |
| limit | integer · 1–100 · default 25 | Companies per page. Each company returned counts one record. |
| count | boolean · default false | Same as for people — with limit=1 it is free. |
| cursor | string | meta.nextCursor from the previous page, passed back exactly as it was handed to you. |
Page with meta.nextCursor: pass it back as cursor on the next request. A page with no nextCursor is the last one, and a cursor is tied to one filter set — change a filter and you start a new search rather than resuming the old one.
A cursor is opaque and signed. Pass back exactly the string we gave you. There is nothing inside it to read, and one that has been edited, truncated or built by hand is a 400 Invalid cursor rather than a page from somewhere else in the results. Treat it as good for the walk you are in the middle of and not as something to keep: cursors issued before 19 September 2026 are no longer valid, so a caller still holding one starts again at page one.
Paging also stops at a fixed depth — 10,000 rows per search by default. The page that reaches it carries meta.depthCapped: true and no further cursor. That is rows walked, not records bought; records, limits and errors spells out the difference.
| meta field | Meaning |
|---|---|
| nextCursor | Opaque cursor for the next page, or absent on the last page. |
| depthCapped | true on the page that reaches the depth limit, and absent otherwise. No further cursor is issued — narrow the filters and search again. |
| total | Size of the segment, where the answering source can give one. Treat it as an estimate, not a count you can page to exactly. |
| unsupportedFilters | Names any filter the answering dataset ignored, so a query never silently returns more than you asked for. |
| notice | Present when something about the answer needs explaining — being paced past your records, for one. |
A search page is trimmed to whatever records you have left rather than overshooting them — see records, limits and errors. Every filter, with its type and allowed values, is on the filter reference.