Finding email addresses
Set find_emails and every person you scrape comes back with a work email address beside them, for a flat +4.
On this page
Four operations return a person - profiles/enrich, profiles/enrich/detailed, sales/search/people and sales/search/employees - and all four take find_emails: true. Each person then carries an emails object alongside the LinkedIn record, with a work email address in it where there is one to find.
curl -X POST "https://api.easydata.win/v1/profiles/enrich" \
-H "X-API-Key: $API_KEY" \
-H "Content-Type: application/json" \
-d '{"targets":["https://linkedin.com/in/satyanadella"],"find_emails":true}'{
"status": "found",
"email": "[email protected]",
"pattern": "{first}.{last}@{domain}",
"domain": "microsoft.com",
"candidates": [
{ "email": "[email protected]", "pattern": "{first}.{last}@{domain}", "status": "deliverable" }
],
"checked_at": "2026-09-01T10:00:06Z"
}Read status, not email #
An address is the end of a process with four outcomes, and a bare string could only express two of them. status is the field to branch on.
| status | What it means | Charged |
|---|---|---|
| found | A mailbox that answered. As real as anything can be established without sending mail. | yes |
| catch_all | The domain accepts every address put to it, so email is our best-ranked guess and the server accepting it means nothing. | yes |
| not_found | The domain answered honestly and rejected everything tried. A fact about this person, not about us. | yes |
| unresolved | We never got to ask. reason says why. | no |
catch_all is the one to be careful with. The server said yes, and it would have said yes to anything - so the address is our ranking's best guess rather than a verified mailbox. Treating it as found is how you bounce. Whether to send to it is a judgement about your own domain reputation, which is why candidates is there.
not_found is charged, and that is deliberate. The work happened and the answer is a real one. A provider who stops charging for "no" starts finding reasons to tell you "maybe" instead, and a maybe you cannot act on is worth less than a no you can.
What unresolved means #
| reason | What to do |
|---|---|
| no_current_employer | Nothing. This profile lists no current role. We never guess against a past one: it would produce a deliverable address at a place they have left, and nothing downstream could tell it from a good one. |
| no_company_domain | Send domain on the target if you know it. Their employer publishes no usable website, or none we will guess against. |
| name_is_not_usable | Nothing. Their name field holds an emoji, a tagline or a phone number, and no address can be built from it. |
| lookup_failed | Retry the target. This one is ours, and you were not charged. |
| email_finding_is_not_available | Talk to us - it is not enabled on your deployment. |
Give us the domain if you have it #
A target may carry domain beside its identifier. It says where this person's mail lives and skips working it out from their employer, which makes the lookup faster and more accurate - your CRM knows your prospect's domain, while a LinkedIn page's website field is free text somebody typed years ago. It changes nothing about the price.
{
"targets": [
{ "url": "https://linkedin.com/in/example", "domain": "acme.com" }
],
"find_emails": true
}domain is read on profile targets only. A people search is a list of people at different employers, so one domain on the search would guess every row at the same company.
On a search #
find_emails works on sales/search/people without enrich, and the two are independent: a search card already carries the name and the current employer, which is everything a lookup needs, so you can buy addresses without buying full profile records. The surcharge is per ROW that reached a verdict, so a page of a hundred where sixty resolve is +240 rather than +400.
A page with find_emails set arrives whole rather than row by row, the same way an enriched page does: the addresses are inside the rows, so the page cannot be delivered half-built.
Addresses arrive after the scraping does #
On a batch, addresses are looked up in bulk once the scraping is done, so a batch with find_emails set has a second phase. The batch stays processing, pending holds the targets still waiting, and each result entry appears once - complete, with its emails filled in. Expect minutes rather than seconds for the tail of a large batch.
Nothing is ever delivered twice and no entry changes after you have read it, so a cursor you are already walking stays correct: an entry simply does not appear until it is true. A batch is completed when every entry is readable, addresses included, which is the same thing completed has always meant.
The synchronous path is the exception, and it is why find_emails is allowed there: /profiles/enrich/sync looks the address up inside the request, so one entity in is one complete record out.
The price #
A flat +4 per person we reach a verdict about, +8 on a /sync path like every other number there. Flat means flat: it does not move with how many mail servers were asked, how quickly the address was found, or whether we already knew the employer. What the work costs us is our problem, and a number that moved with it would be one you could not plan against.
find_emails is refused with 400 invalid_request on an operation that returns no person - companies/enrich, posts/enrich, a company search - rather than being accepted and ignored. A flag that is silently dropped is indistinguishable from one that worked, and you would have concluded that none of those companies have addresses.
It is also refused on /sales/search/people/sync, where it would be one lookup per row inside a single HTTP request. It is allowed on /profiles/enrich/sync, where one person is bounded work - and if that request runs out of time the profile still comes back and is charged, with emails.status: "unresolved" beside it and no surcharge.
What you are responsible for #
An address we find is a business contact detail, and sending to it is regulated where you are and where they are. GDPR, CAN-SPAM, CASL and PECR all apply to you as the sender; we are not your basis for processing and cannot be. Honour opted_out_of_data_sharing where a search row carries it, and keep your own suppression list - we do not have one, because we never see what you send.