Skip to content

Migrations & changes

Migrating from Resolve to Enrich

New

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/...
PathsOne path per input type for persons, one for companiesOne path for persons, one for companies
DeliveryAsynchronous: a webhookId, then polling or a webhook callbackSynchronous: the match is in the response
Person resultA focused subset of the profileThe same fields, plus the full profile of the Profile endpoint
Other candidatesNot returneddata.alternativePersons, each one a full profile
Not founddata-not-found error code in the job result404 response
Pricing2 credits2 credits, only when a match is found

Paths

BeforeAfter
POST /v2/resolve/persons/emailPOST /v2/enrich/persons
POST /v2/resolve/persons/namePOST /v2/enrich/persons
POST /v2/resolve/companies/livePOST /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.

BeforeAfter
/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:

JavaScript
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: "jane.doe@acme.com" })
});
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:

JavaScript
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: "jane.doe@acme.com" })
});

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.