Migrating from Resolve to Enrich

4 min read

Move identity resolution calls from the asynchronous /v2/resolve endpoints to the synchronous /v2/enrich endpoints.

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 webhookUrl in your requests.
  • The polling loop on GET /v2/webhooks/:webhookId.
  • The storage you use to correlate a webhookId with the original request.
  • The handling of the data-not-found, fetch-data-error and result-unavailable job error codes. A not-found is now a 404 response, 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

  1. Replace /v2/resolve/persons/email and /v2/resolve/persons/name with POST /v2/enrich/persons, and /v2/resolve/companies/live with POST /v2/enrich/companies.
  2. Remove webhookUrl from your requests and read the result from the response.
  3. Remove the polling loop, the callback endpoint and the webhookId correlation.
  4. Treat 404 as a normal no-match outcome.
  5. Read the person from data.person: the Resolve fields keep their names.
  6. Drop the Profile calls you used to chain after a resolution.
  7. Check data.alternativePersons before writing a match automatically.
  8. Remove fullProfile from your requests.

Previous

Migrating people search from persons to people

Next

Enrich profile