Identity resolution has a new home: POST /v2/enrich/persons and POST /v2/enrich/companies. They take the same inputs as Resolve, cost the same, and answer synchronously: the match comes back in the API response, with no job to track and no callback to receive.
The previous endpoints, POST /v2/resolve/persons/email, POST /v2/resolve/persons/name and POST /v2/resolve/companies/live, remain functional until October 13, 2026, when they are retired. See the endpoint transition overview for the full timeline. This guide covers everything that changes when you move to Enrich.
What changes
| Area | /v2/resolve/... |
/v2/enrich/... |
|---|---|---|
| Paths | One path per input type for persons, one for companies | One path for persons, one for companies |
| Delivery | Asynchronous: a webhookId, then polling or a webhook callback |
Synchronous: the match is in the response |
| Person result | A focused subset of the profile | The same fields, plus the full profile of the Profile endpoint |
| Other candidates | Not returned | data.alternativePersons, each one a full profile |
| Not found | data-not-found error code in the job result |
404 response |
| Pricing | 2 credits | 2 credits, only when a match is found |
Paths
| Before | After |
|---|---|
POST /v2/resolve/persons/email |
POST /v2/enrich/persons |
POST /v2/resolve/persons/name |
POST /v2/enrich/persons |
POST /v2/resolve/companies/live |
POST /v2/enrich/companies |
The method and the Authorization: Bearer YOUR_API_KEY header stay the same.
Inputs stay the same
Send the fields you already send today. The only field to drop is webhookUrl.
| Before | After |
|---|---|
/v2/resolve/persons/email with email |
/v2/enrich/persons with email |
/v2/resolve/persons/name with firstName, lastName and companyDomain or companyName |
/v2/enrich/persons with the same fields |
/v2/resolve/companies/live with domain |
/v2/enrich/companies with domain |
On /v2/enrich/persons, every field is optional and independent: provide at least one of email, firstName, lastName, companyDomain or companyName. You can also combine an email with a name and a company in a single request. See Best practices for the trade-off between match rate and certainty.
From asynchronous to synchronous
Resolve replied with a job acknowledgement and delivered the result later, through polling on GET /v2/webhooks/:webhookId or a callback to your webhookUrl. Enrich returns the match in the response to your request.
Before:
const trigger = await fetch("https://api.reversecontact.com/v2/resolve/persons/email", {
method: "POST",
headers: { "Authorization": "Bearer YOUR_API_KEY", "Content-Type": "application/json" },
body: JSON.stringify({ email: "[email protected]" })
});
const { data: { webhookId } } = await trigger.json();
while (true) {
const res = await fetch(`https://api.reversecontact.com/v2/webhooks/${webhookId}`, {
headers: { "Authorization": "Bearer YOUR_API_KEY" }
});
const { data } = await res.json();
if (data.status === "succeeded") { console.log(data.result); break; }
if (data.status === "errored") throw new Error(data.errorCode ?? "Job failed");
await new Promise(r => setTimeout(r, 2000));
}
After:
const response = await fetch("https://api.reversecontact.com/v2/enrich/persons", {
method: "POST",
headers: { "Authorization": "Bearer YOUR_API_KEY", "Content-Type": "application/json" },
body: JSON.stringify({ email: "[email protected]" })
});
if (response.status === 404) {
console.log("No match");
} else {
const { data } = await response.json();
console.log(data.person.firstName, data.person.currentCompanyName);
}
What you can remove from your integration:
- The callback endpoint you expose to receive Resolve results, and its
webhookUrlin your requests. - The polling loop on
GET /v2/webhooks/:webhookId. - The storage you use to correlate a
webhookIdwith the original request. - The handling of the
data-not-found,fetch-data-errorandresult-unavailablejob error codes. A not-found is now a404response, and other failures come back as standard HTTP errors, see Errors & retries.
Person results are full profiles
Resolve delivered a focused subset of the profile, and the documented flow was to chain into the Profile endpoint for the rest. Enrich returns the full profile in data.person, with currentPosition, experience, education, skills and the other sections documented on the Profile endpoint. If you chained a Profile call after each resolution, drop it.
Every field of the Resolve result keeps its name and its place: id, publicId, linkedinUrl, firstName, lastName, headline, currentPositionTitle, currentCompanyId, currentCompanyName, currentCompanyLinkedinId, updateDate and location. Your existing parsing keeps working once you read data.person instead of the job result, and the Profile sections come on top. The complete field reference is on the Profile endpoint.
In rare cases the full profile cannot be retrieved in time. data.isFullProfile is then false and data.person carries only the Resolve fields listed above, which you can complete with the Profile endpoint. See Light fallback.
Alternative candidates
When several people match your input, Enrich returns the best match in data.person and the other candidates in data.alternativePersons, ordered best first, up to nine. Each alternative is a full profile too, with currentCompanyId always null. Resolve had no equivalent, so use this array as an ambiguity signal: when it is not empty, route the record to review before writing it. See Data quality.
Pricing
Enrich costs 2 credits, the same price as Resolve, and only when a match is found. A 404 costs 0 credits. The full profile of persons, alternative candidates and companies is included in that price.
The fullProfile request field is deprecated and ignored on both Enrich endpoints: it is still accepted so existing requests keep working, and you can remove it.
Companies
POST /v2/enrich/companies takes the same domain as /v2/resolve/companies/live and returns the company in data.company as a full profile: the fields of the Resolve result keep their names, and the Company Profile fields come on top. See Enrich company for the full reference.
Migration checklist
- Replace
/v2/resolve/persons/emailand/v2/resolve/persons/namewithPOST /v2/enrich/persons, and/v2/resolve/companies/livewithPOST /v2/enrich/companies. - Remove
webhookUrlfrom your requests and read the result from the response. - Remove the polling loop, the callback endpoint and the
webhookIdcorrelation. - Treat
404as a normal no-match outcome. - Read the person from
data.person: the Resolve fields keep their names. - Drop the Profile calls you used to chain after a resolution.
- Check
data.alternativePersonsbefore writing a match automatically. - Remove
fullProfilefrom your requests.