Skip to content

Instantly share code, notes, and snippets.

@crtag
Last active October 13, 2020 05:52
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save crtag/99176be730b6915c7d584406bb011a16 to your computer and use it in GitHub Desktop.
Save crtag/99176be730b6915c7d584406bb011a16 to your computer and use it in GitHub Desktop.
Hubspot workflow Node JS webhook to create a company record via API call.
// TODO: configure your own hubspot client
/**
* This webhook is triggered by Hubspot workflow and receives a full Hubspot contact object
* to create the company for. It does expect company name property, but will default
* company name to contact `${firstname} ${lastname} construct
*
*/
module.exports = async (req, res) => {
if (req.method !== 'POST') return res.sendStatus(405);
// You can also check signature of the call (X-HubSpot-Signature header)
const payload = req.body;
const contactVid = payload.vid;
if (!payload['is-contact']) {
console.log('Received unexpected object!');
return res.sendStatus(400)
};
if (0 == Object.keys(payload.properties || {})) {
console.log('Missing contact properties!');
return res.sendStatus(400)
};
// can't lazy initialise it as it's async
let hubspotClient;
try {
// TODO: it's up to you how to cinfiugure Hubspot client
// this example uses https://github.com/MadKudu/node-hubspot
hubspotClient = await hubspot();
} catch (error) {
console.log('Failed to create Hubspot API client');
return res.sendStatus(503);
}
// check if there's an associated company to contact - this would be a conflict
try {
// 1 - association contact to company from https://developers.hubspot.com/docs/methods/crm-associations/crm-associations-overview
console.log(`Test contact associations with a company.`);
const associations = await hubspotClient.apiRequest({
path: `/crm-associations/v1/associations/${contactVid}/HUBSPOT_DEFINED/1`,
});
if (0 != associations.results.length) {
console.log(`Found associations`);
console.log(JSON.stringify(associations.results));
console.log(`The contact [${contactVid}] is already associated with a company, nothing to do.`);
return res.sendStatus(204);
} else {
console.log(`No associations, proceed`);
}
} catch (error) {
console.log(`Failed to test contact [${contactVid}] associations with a company. Error stack: ${error}`);
return res.sendStatus(500);
}
const name = (payload.properties.company || {}).value || '';
const firstName = (payload.properties.firstname || {}).value || '';
const lastName = (payload.properties.lastname || {}).value || '';
// constructing company name - falling back to contact name
const companyName = name || `${firstName} ${lastName}`;
let companyVid;
try {
console.log(`Creating company via Hubspot API with name [${companyName}]`)
const company = await hubspotClient.companies.create({
properties: [
{
name: 'name',
value: companyName,
}
]
});
companyVid = company.companyId;
if (companyVid) {
console.log(`Created company with response:`);
console.log(JSON.stringify(company));
} else {
console.log(`Failed to create company with response:`);
console.log(JSON.stringify(company));
return res.sendStatus(500);
}
} catch(error) {
console.log(`Failed to create company via API call. Error stack: [${error}]`);
return res.sendStatus(500);
}
// associate contact with the company
try {
console.log(`Associating contact [${contactVid}] with company [${companyVid}] via Hubspot API call`)
await hubspotClient.apiRequest({
method: 'PUT',
path: `/crm-associations/v1/associations`,
body: {
fromObjectId: contactVid,
toObjectId: companyVid,
category: 'HUBSPOT_DEFINED',
definitionId: 1
},
});
// above API call returns 204 on success
} catch (error) {
console.log(`Failed to associate contact [${contactVid}] with company [${companyVid}] via API call. Error stack: [${error}]`);
// TODO: this is really bad is it will leave behind unassociated company and contact, need to sort out recovery mechanism
return res.sendStatus(500);
}
return res.sendStatus(204);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment