I was using the default merge duplicates code and updated the property that I need to merge contacts by which is "rim_no" (a unique customer identifyer in our database). I have set up the API key in "Secrets" but after a lot of trouble shooting, I just can't figure it out. Anyone have any ideas?
/** * Searches for another contact with the same value of DEDUPE_PROPERTY. * - If no matches are found, nothing happens * - If one match is found, the enrolled contact is merged into the matching contact * - If more than one match is found, the action fails */
const DEDUPE_PROPERTY = 'rim_no';
const hubspot = require('@hubspot/api-client');
exports.main = (event, callback) => { // Make sure to add your API key under "Secrets" above. const hubspotClient = new hubspot.Client({ accessToken: process.env.SECRET_NAME, });
hubspotClient.crm.contacts.basicApi .getById(event.object.objectId, [DEDUPE_PROPERTY]) .then(contactResult => { let dedupePropValue = contactResult.body.properties[DEDUPE_PROPERTY];
// console.log(`Looking for duplicates based on ${DEDUPE_PROPERTY} = ${dedupePropValue}`); hubspotClient.crm.contacts.searchApi .doSearch({ filterGroups: [{ filters: [{ propertyName: DEDUPE_PROPERTY, operator: 'EQ', value: dedupePropValue }] }] }) .then(searchResults => { let idsToMerge = searchResults.body.results .map(object => object.id) .filter(vid => Number(vid) !== Number(event.object.objectId));
if (idsToMerge.length == 0) { console.log('No matching contact, nothing to merge'); return; } else if (idsToMerge.length > 1) { console.log(`Found multiple potential contact IDs ${idsToMerge.join(', ')} to merge`); throw new Error("Ambiguous merge; more than one matching contact"); }
WARNING: The logs for this function have exceeded the 4KB limit.
...
ontrol-allow-credentials\":\"false\",\"cf-cache-status\":\"DYNAMIC\",\"cf-ray\":\"8a848b6a5f2887ac-IAD\",\"connection\":\"close\",\"content-length\":\"299\",\"content-type\":\"application/json;charset=utf-8\",\"date\":\"Wed, 24 Jul 2024 14:19:20 GMT\",\"nel\":\"{\\\"success_fraction\\\":0.01,\\\"report_to\\\":\\\"cf-nel\\\",\\\"max_age\\\":604800}\",\"report-to\":\"{\\\"endpoints\\\":[{\\\"url\\\":\\\"https:\\\\/\\\\/a.nel.cloudflare.com\\\\/report\\\\/v4?s=R2f5tgv4JVSRn%2FjWX2DmhksTGsVDCYh2KRLzkRPRHy6lR2%2BLNg0brV8fmXULq03p%2F9Sy8CyIfBqFoAT0dCrNOaRLH3%2FlYCa8AbHa5WufRcjIuF7wPZB%2FR3hfQN5raPot\\\"}],\\\"group\\\":\\\"cf-nel\\\",\\\"max_age\\\":604800}\",\"server\":\"cloudflare\",\"strict-transport-security\":\"max-age=31536000; includeSubDomains; preload\",\"vary\":\"origin, Accept-Encoding\",\"x-content-type-options\":\"nosniff\",\"x-envoy-upstream-service-time\":\"4\",\"x-evy-trace-listener\":\"listener_https\",\"x-evy-trace-route-configuration\":\"listener_https/all\",\"x-evy-trace-route-service-name\":\"envoyset-translator\",\"x-evy-trace-served-by-pod\":\"iad02/hubapi-td/envoy-proxy-7dd59b876-mtwxl\",\"x-evy-trace-virtual-host\":\"all\",\"x-hubspot-auth-failure\":\"401 Unauthorized\",\"x-hubspot-correlation-id\":\"5cb63b81-60bd-445e-93de-b503bbdacda5\",\"x-request-id\":\"5cb63b81-60bd-445e-93de-b503bbdacda5\"}"," at BasicApiResponseProcessor.<anonymous> (/opt/nodejs/node_modules/@hubspot/api-client/lib/codegen/crm/contacts/apis/BasicApi.js:227:23)"," at Generator.next (<anonymous>)"," at fulfilled (/opt/nodejs/node_modules/@hubspot/api-client/lib/codegen/crm/contacts/apis/BasicApi.js:5:58)"," at processTicksAndRejections (node:internal/process/task_queues:96:5)"]},"promise":{},"stack":["Runtime.UnhandledPromiseRejection: Error: HTTP-Code: 401","Message: An error occurred.","Body: {\"status\":\"error\",\"message\":\"Authentication credentials not found. This API supports OAuth 2.0 authentication and you can find more details at https://developers.hubspot.com/docs/methods/auth/oauth-overview\",\"correlationId\":\"5cb63b81-60bd-445e-93de-b503bbdacda5\",\"category\":\"INVALID_AUTHENTICATION\"}","Headers: {\"access-control-allow-credentials\":\"false\",\"cf-cache-status\":\"DYNAMIC\",\"cf-ray\":\"8a848b6a5f2887ac-IAD\",\"connection\":\"close\",\"content-length\":\"299\",\"content-type\":\"application/json;charset=utf-8\",\"date\":\"Wed, 24 Jul 2024 14:19:20 GMT\",\"nel\":\"{\\\"success_fraction\\\":0.01,\\\"report_to\\\":\\\"cf-nel\\\",\\\"max_age\\\":604800}\",\"report-to\":\"{\\\"endpoints\\\":[{\\\"url\\\":\\\"https:\\\\/\\\\/a.nel.cloudflare.com\\\\/report\\\\/v4?s=R2f5tgv4JVSRn%2FjWX2DmhksTGsVDCYh2KRLzkRPRHy6lR2%2BLNg0brV8fmXULq03p%2F9Sy8CyIfBqFoAT0dCrNOaRLH3%2FlYCa8AbHa5WufRcjIuF7wPZB%2FR3hfQN5raPot\\\"}],\\\"group\\\":\\\"cf-nel\\\",\\\"max_age\\\":604800}\",\"server\":\"cloudflare\",\"strict-transport-security\":\"max-age=31536000; includeSubDomains; preload\",\"vary\":\"origin, Accept-Encoding\",\"x-content-type-options\":\"nosniff\",\"x-envoy-upstream-service-time\":\"4\",\"x-evy-trace-listener\":\"listener_https\",\"x-evy-trace-route-configuration\":\"listener_https/all\",\"x-evy-trace-route-service-name\":\"envoyset-translator\",\"x-evy-trace-served-by-pod\":\"iad02/hubapi-td/envoy-proxy-7dd59b876-mtwxl\",\"x-evy-trace-virtual-host\":\"all\",\"x-hubspot-auth-failure\":\"401 Unauthorized\",\"x-hubspot-correlation-id\":\"5cb63b81-60bd-445e-93de-b503bbdacda5\",\"x-request-id\":\"5cb63b81-60bd-445e-93de-b503bbdacda5\"}"," at process.<anonymous> (file:///var/runtime/index.mjs:1276:17)"," at process.emit (node:events:513:28)"," at emit (node:internal/process/promises:140:20)"," at processPromiseRejections (node:internal/process/promises:274:27)"," at processTicksAndRejections (node:internal/process/task_queues:97:32)"]}
Unknown application error occurred
Runtime.Unknown
Memory: 75/128 MB
Runtime: 1163.15 ms
Looks like you've just referenced some keys that weren't present in the HubSpot API responses. Remove "body" from your "contactResult" and "searchResults" object chains. This has worked on my end, so please feel free to give it a try:
/**
* Searches for another contact with the same value of DEDUPE_PROPERTY.
* - If no matches are found, nothing happens
* - If one match is found, the enrolled contact is merged into the matching contact
* - If more than one match is found, the action fails
*/
const DEDUPE_PROPERTY = 'rim_no';
const hubspot = require('@hubspot/api-client');
exports.main = (event, callback) => {
// Make sure to add your API key under "Secrets" above.
const hubspotClient = new hubspot.Client({
accessToken: process.env.[INSERT ACCESS TOKEN]
});
hubspotClient.crm.contacts.basicApi
.getById(event.object.objectId, [DEDUPE_PROPERTY])
.then(contactResult => {
let dedupePropValue = contactResult.properties[DEDUPE_PROPERTY];
console.log(`Looking for duplicates based on ${DEDUPE_PROPERTY} = ${dedupePropValue}`);
hubspotClient.crm.contacts.searchApi
.doSearch({
filterGroups: [{
filters: [{
propertyName: DEDUPE_PROPERTY,
operator: 'EQ',
value: dedupePropValue
}]
}]
})
.then(searchResults => {
let idsToMerge = searchResults.results
.map(object => object.id)
.filter(vid => Number(vid) !== Number(event.object.objectId));
if (idsToMerge.length == 0) {
console.log('No matching contact, nothing to merge');
return;
} else if (idsToMerge.length > 1) {
console.log(`Found multiple potential contact IDs ${idsToMerge.join(', ')} to merge`);
throw new Error("Ambiguous merge; more than one matching contact");
}
let idToMerge = idsToMerge[0];
console.log(`Merging enrolled contact id=${event.object.objectId} into contact id=${idToMerge}`);
hubspotClient
.apiRequest({
method: 'POST',
path: `/contacts/v1/contact/merge-vids/${idToMerge}`,
body: {
vidToMerge: event.object.objectId
}
})
.then(mergeResult => {
console.log('Contacts merged!');
});
});
});
};
Finally, if you're ever looking for an app to handle the merging of Contacts via workflows, you might like to consider Utilities for HubSpot.
I hope this proves helpful. Please let me know if you have any follow-up questions 🙂
All the best,
Zach
--
Zach Klein HubSpot Integrations & App Developer Meanjin / Brisbane, Australia
I have continued troubleshooting using the resources provided, but I'm still running into errors.
Here the updated code:
/**
* Searches for another contact with the same value of DEDUPE_PROPERTY.
* - If no matches are found, nothing happens
* - If one match is found, the enrolled contact is merged into the matching contact
* - If more than one match is found, the action fails
*/
const DEDUPE_PROPERTY = 'rim_no';
const hubspot = require('@hubspot/api-client');
exports.main = (event, callback) => {
// Make sure to add your API key under "Secrets" above.
const hubspotClient = new hubspot.Client({
accessToken: process.env.[INSERT ACCESS TOKEN]
});
hubspotClient.crm.contacts.basicApi
.getById(event.object.objectId, [DEDUPE_PROPERTY])
.then(contactResult => {
let dedupePropValue = contactResult.body.properties[DEDUPE_PROPERTY];
console.log(`Looking for duplicates based on ${DEDUPE_PROPERTY} = ${dedupePropValue}`);
hubspotClient.crm.contacts.searchApi
.doSearch({
filterGroups: [{
filters: [{
propertyName: DEDUPE_PROPERTY,
operator: 'EQ',
value: dedupePropValue
}]
}]
})
.then(searchResults => {
let idsToMerge = searchResults.body.results
.map(object => object.id)
.filter(vid => Number(vid) !== Number(event.object.objectId));
if (idsToMerge.length == 0) {
console.log('No matching contact, nothing to merge');
return;
} else if (idsToMerge.length > 1) {
console.log(`Found multiple potential contact IDs ${idsToMerge.join(', ')} to merge`);
throw new Error("Ambiguous merge; more than one matching contact");
}
let idToMerge = idsToMerge[0];
console.log(`Merging enrolled contact id=${event.object.objectId} into contact id=${idToMerge}`);
hubspotClient
.apiRequest({
method: 'POST',
path: `/contacts/v1/contact/merge-vids/${idToMerge}`,
body: {
vidToMerge: event.object.objectId
}
})
.then(mergeResult => {
console.log('Contacts merged!');
});
});
});
};
Here's the new error:
2024-07-25T19:04:33.715Z ERROR Unhandled Promise Rejection {"errorType":"Runtime.UnhandledPromiseRejection","errorMessage":"TypeError: Cannot read properties of undefined (reading 'properties')","reason":{"errorType":"TypeError","errorMessage":"Cannot read properties of undefined (reading 'properties')","stack":["TypeError: Cannot read properties of undefined (reading 'properties')"," at /var/task/file.js:21:48"," at processTicksAndRejections (node:internal/process/task_queues:96:5)"]},"promise":{},"stack":["Runtime.UnhandledPromiseRejection: TypeError: Cannot read properties of undefined (reading 'properties')"," at process.<anonymous> (file:///var/runtime/index.mjs:1276:17)"," at process.emit (node:events:513:28)"," at emit (node:internal/process/promises:140:20)"," at processPromiseRejections (node:internal/process/promises:274:27)"," at processTicksAndRejections (node:internal/process/task_queues:97:32)"]}
Unknown application error occurred
Runtime.Unknown
Memory: 75/128 MB
Runtime: 1438.88 ms
Looks like you've just referenced some keys that weren't present in the HubSpot API responses. Remove "body" from your "contactResult" and "searchResults" object chains. This has worked on my end, so please feel free to give it a try:
/**
* Searches for another contact with the same value of DEDUPE_PROPERTY.
* - If no matches are found, nothing happens
* - If one match is found, the enrolled contact is merged into the matching contact
* - If more than one match is found, the action fails
*/
const DEDUPE_PROPERTY = 'rim_no';
const hubspot = require('@hubspot/api-client');
exports.main = (event, callback) => {
// Make sure to add your API key under "Secrets" above.
const hubspotClient = new hubspot.Client({
accessToken: process.env.[INSERT ACCESS TOKEN]
});
hubspotClient.crm.contacts.basicApi
.getById(event.object.objectId, [DEDUPE_PROPERTY])
.then(contactResult => {
let dedupePropValue = contactResult.properties[DEDUPE_PROPERTY];
console.log(`Looking for duplicates based on ${DEDUPE_PROPERTY} = ${dedupePropValue}`);
hubspotClient.crm.contacts.searchApi
.doSearch({
filterGroups: [{
filters: [{
propertyName: DEDUPE_PROPERTY,
operator: 'EQ',
value: dedupePropValue
}]
}]
})
.then(searchResults => {
let idsToMerge = searchResults.results
.map(object => object.id)
.filter(vid => Number(vid) !== Number(event.object.objectId));
if (idsToMerge.length == 0) {
console.log('No matching contact, nothing to merge');
return;
} else if (idsToMerge.length > 1) {
console.log(`Found multiple potential contact IDs ${idsToMerge.join(', ')} to merge`);
throw new Error("Ambiguous merge; more than one matching contact");
}
let idToMerge = idsToMerge[0];
console.log(`Merging enrolled contact id=${event.object.objectId} into contact id=${idToMerge}`);
hubspotClient
.apiRequest({
method: 'POST',
path: `/contacts/v1/contact/merge-vids/${idToMerge}`,
body: {
vidToMerge: event.object.objectId
}
})
.then(mergeResult => {
console.log('Contacts merged!');
});
});
});
};
Finally, if you're ever looking for an app to handle the merging of Contacts via workflows, you might like to consider Utilities for HubSpot.
I hope this proves helpful. Please let me know if you have any follow-up questions 🙂
All the best,
Zach
--
Zach Klein HubSpot Integrations & App Developer Meanjin / Brisbane, Australia
Also, I'd like to invite a couple of subject matter experts and Community Members to this conversation: Hi @andreaska, @himanshurauthan and @zach_threadint do you have troubleshooting steps to help @CSteinbach, please?
Thank you very much and have a great day!
Best, Bérangère
HubSpot’s AI-powered customer agent resolves up to 50% of customer queries instantly, with some customers reaching up to 90% resolution rates. Learn More.