Setting Contact properties based on external API data in Workflows

Imagine you need to create a workflow that updates a Contact property based on information from an external service. In this guide we’ll walk you through the entire process step by step, so by the end, you’ll be able to implement this solution or the similar one on your own.

Imagine you need to create a workflow that updates a Contact property based on information from an external service. In this guide we’ll walk you through the entire process step by step, so by the end, you’ll be able to implement this solution or the similar one on your own.

We’ll focus on Contacts here, but of course the same technique can be used with any other CRM objects, like Companies or even Custom Objects.

Case study

In this guide we’ll cover the following process:

Every time the email address is set in Contact object, we’ll send request to external service and check if this email is on the emails list returned by this service. Based on the response, we’ll set a value of custom Contact property.

Preparation

For the purpose of this guide, I prepared a simple external API, which we’ll call during the workflow action. The API sends a simple list of test email addresses

Simple API response with a list of emails

We’ll use this API in the workflow we are going to create.

I also created a custom property in Contact, with a name `Found in external API`. This is just a true/false property and we’ll be setting it based on the response from external API.

Just in case you are not familiar with setting up custom properties, below is the simple guide. If you already know how to do that, you can just skip to `Step 1 - Setting up private app`.

  • Go to Contacts and select one of your contact from the list
Simple Contacts list
  • In the left sidebar, you’ll see `Actions` dropdown. Select `View all properties` from it
Contact details view
  • Click `Manage properties`
All available properties
  • Click `Create property` and the simple form will appear
Manage properties view
  • Fill the form using values from the screen below:
    • Object type: `Contact`
    • Group: `Contact information` (you can select different one if you want)
    • Label: `Found in external API` (you can choose different name)
    • Description can be left empty
Setting new property
  • Click `Next` button at the bottom and you’ll see a `Field type` form. Select `Single checkbox` and click `Next`
Setting new property
  • The last screen of the wizard is just a selection box where you define whether you want to see this property in forms or not. You can uncheck it.
  • Click `Create`

After coming back to `All properties` view, you can check if the property has been created. Write its name in search field and you should see it on the list.

New property visible in Contacts

The preparation is done, now we are ready to move further.

Step 1 - Setting up private app

Since we are going to connect external API, we will have to choose slightly different workflow then usual. We will also have to write a piece of code (don’t worry, I’ll guide you through it).

First, we have to set up the private app in HubSpot. Private app is a gateway for external services or pieces of code, which allows them to connect and manage parts of your HubSpot system. In this guide, our private app will have access to Contacts.

  • First, go to settings
Settings icon
  • Choose `Integrations` in the left sidebar and then `Private apps`
Private apps in settings view
  • Click `Create private app` button
  • The app creator will appear and you’ll have to set up a few parameters. First one is a name
Setting the name of private app
  • Next, click the `Scopes` tab in the middle of top bar above the form
  • You need to define the available scopes that the application will have access to. Just write `contacts` in the `Find a scope` input, and you’ll get the list of possible scopes related to Contacts
  • Choose `crm.objects.contacts` and `crm.schemas.contacts` from the CRM section. Select both - `Read` and `Write`.
Setting the scope of private app
  • Click `Create app` button which will be enabled and turned to orange after you selected the scopes
Enabled 'Create app' button
  • You’ll see a modal with confirmation that the app has been created. There will be a partially hidden token, which you will use in the workflow
App is created
  • Click `show token` next to the token input, and then copy it
Show token option

Your app is ready to use, so we can jump into the next step.

Step 2 - Creating workflow

This is the biggest and the most important section of the tutorial, so let’s go straight into the step-by-step guide.

  • Go to Automation->Workflows view from the main menu
  • Click `Create workflow` and select `From scratch`
Create workflow
  • Our workflow will be `Contact-based` so select that box on the left. Select `Blank workflow` in the middle section and click `Next`
Create workflow
  • You’ll see the initial workflow screen. Click on the trigger box (right arrow on the screen below) to set up the trigger
Setting up the trigger
  • On the left side, click `When an event occurs` box (green arrow on the screen above)
  • You’ll see a list of all accessible properties in Contact object
Setting up the trigger
  • Select `Property value changed`, which is under `CRM` section. You can also search for it by starting writing the name in `Search field` input
Trigger setup
  • When you click on it, you’ll have to select the property name, which the workflow will listen to. Find the `Email`
Trigger setup
Trigger setup
  • Now you have to define the property value. Since we just want to check if the email is set, select `is known`
Trigger setup
  • Click `Save`
T
  • You should see the trigger box similar to the one on the screen
Trigger view

Now let’s create another action.

  • Click on a `plus` button below the box with created trigger
  • Select `Data ops` and `Custom code` from the left sidebar
Custom code action
  • Sidebar will change and you’ll see a form with couple of properties to set, as well as the code editor
Side panel
Side panel
  • To be able to connect our code to HubSpot Contacts, we have to use our previously created private app. Click the `Secrets` dropdown and select `Add secret`
Add secret
  • Write a name (can be just `SECRET`) and paste private app access token into the value field
Add secret value
  • Click `Save`

Let’s take a look at the code editor. It’s written in NodeJS and by default it looks like this:

Default code

There are some elements which have to be present to execute the code. First one is export.main :

exports.main = async (event, callback) => { ... }

It takes 2 arguments:

  • event which is the workflow event we are working on
  • callback which is a function which returns values to next workflow actions

Second must-have part is a callback function execution, which defines the output of the code

You can see that there is also a part which gets email from event.inputFields list.

To make it all work, we have to do some configuration.

  • Find a section under `Secrets` with name `Property to include in code`. It has two inputs - `key` and `value`
  • Write `email` as a `key`
  • Select `Email` as a `value`
Setting up input field
  • You’ll end up with filled form like the one on a screen
Setting up input field value

Below is the full code we’re going to use in this action. You can copy it and paste into your editor.

const hubspot = require('@hubspot/api-client');

exports.main = async (event, callback) => {
  let contactFoundInExternalAPI = false;
  const email = event.inputFields['email'];

  const response = await fetch('https://d127-87-206-14-190.ngrok-free.app/v1/api/test');
  const data = await response.json();

  if(data) {
    contactFoundInExternalAPI = data.includes(email);

    const hubspotClient = new hubspot.Client({
      accessToken: process.env.SECRET,
    });
    
    const contactID = event.object.objectId;
    await hubspotClient.crm.contacts.basicApi.update(contactID, {
      properties: { found_in_external_api: contactFoundInExternalAPI },
    });
  }

  callback({
    outputFields: {
      contactFound: contactFoundInExternalAPI,
    }
  });
}

Let’s go through it so you can understand, what’s going on:

  • In workflows custom actions we have access to some basic NodeJS libraries and one of them is @hubspot/api-client which allows us to connect to HubSpot API. We import it into the code:

const hubspot = require('@hubspot/api-client');

  • The main code section contains a result variable declaration and getting email from input fields we declared above
exports.main = async (event, callback) => {
  let contactFoundInExternalAPI = false;
  const email = event.inputFields['email'];
  
  ...
  • Now we can connect to external API. We’ll use simple fetch library which is natively available in NodeJS
const response = await fetch('https://d127-87-206-14-190.ngrok-free.app/v1/api/test');

const data = await response.json();

https://d127-87-206-14-190.ngrok-free.app/v1/api/test is an url of my simple API, which I created only for the purpose of writing this guide. Replace it with the url you want to connect to.

  • if server responded and we have the data, we can proceed and set a variable `contactFoundInExternalAPI` based on the response
if(data) {
  contactFoundInExternalAPI = data.includes(email);
  • now we have to connect to our Contacts through HubSpot API. We’ll use `SECRET`, which we defined in one of the previous steps. It is availble in process.env object
const hubspotClient = new hubspot.Client({
  accessToken: process.env.SECRET,
});
  • after setting the connection, we can update our Contact object. We’ll update only the Contact which triggers the workflow, so we have to get its id from event.object.objectId

    const contactID = event.object.objectId;

  • we are updating only the property which we created previously - `Found in external API`. HubSpot automatically creates property names with underscore based on labels, so in our case, the property name is `found_in_external_api`. We’ll use it in the code
await hubspotClient.crm.contacts.basicApi.update(contactID, {
  properties: { found_in_external_api: contactFoundInExternalAPI },
});
  • last part of code is just a callback which pass `outputFields` to another action (if needed). In our example, we’ll pass `contactFound` parameter, which will have `true` or `false` value
callback({
  outputFields: {
    contactFound: contactFoundInExternalAPI,
  }
});

Even if we defined `outputFields` in the code, we still have to add them to action output. To do that, find the `Add output` link placed below the code editor. Click it.

Add output
  • Fill the `Data type` which should be `Boolean`
Output data type
  • Fill the `Name` which should be exactly the same as in the `callback` action above. In our case it’s `contactFound`
Output data value

`Save` the action and you’ll see 2 boxes in workflows like on the image below.

Workflow actions

Step 3 - Testing

We are ready to test what we’ve created so far. If your left sidebar disappeared after save, you can bring it back by clicking the action box in the workflow - the one with `Custom code`.

Workflow actions

Now you are ready to test the action.

  • Scroll the sidebar to the very bottom. You’ll see the `Test action` expandable section. Click it.
  • Select any of your contacts you would like to test. For testing I strongly recommend using test contact
Contact select
Contact select
  • Click `Test`
  • You’ll see the confirmation modal, click `Test`
Test confirm
  • Just to remind, my simple API is responding with a list of the following email addresses
API response
  • When the test ends, you’ll see the response, like on the screen below. You’ll see the status of response (for example `Success` like on the screen), output fields which we defined previously and a few logs.
Test 1
  • My test contact has an email `bh@hubspot.com` and it’s not on the list. That’s why the `contactFound` value in output of the action is `false`
Test 1
  • If you switch to the Contacts view and check all properties for the selected contact, you’ll see that the value of the property `Found in external API` has been set to `No`, which equals to `false`
Property updated

Before executing next test, I made some adjustments in my API. I added `bh@hubspot.com` email address to the returned list.

API response extended

Now, after executing the same testing steps as above, this time I got `contactFound` value set to `true`, which means that this email has been found on the list.

Test 2

Again, switch to the Contacts view and this time you should see the property `Found in external API` set to `Yes` 🚀

Property updated

It’s also worth mentioning, that you can use console.log in the code if you want to debug it. For example, when I add console.log(‘data’, data) just to see what comes from the API, I’ll see this log at the bottom after executing the test.

Added console.log
Logs in tests

Step 4 - Possible further actions

If you wish to add next action in the workflow and use the property we've just set, you can do it the following way.

  • Click the `plus` icon below the `Custom code` box
Next action in workflow
  • Select action. Since the property we’ve created is true or false, the natural next action will be `Branch`
Action type
  • Select `One property or action input`
Action type
  • You’ll see the dropdown with properties. Click it
Select property

There is a dropdown at the top - `View properties or action outputs from`. If you set `Enrolled contact`, you’ll be able to find our `Found in external API` property in the list below. It will be visible under `Enumeration properties`, because it’s true or false

Properties list
Property in enrolled contacts

You can also switch to `Action output` in the dropdown and select `contactFound` field, which we created in a step before.

Action outputs

Step 5 - Review and turn on

Only a few steps left to run this workflow on production.

  • First, you have to give it a name. Click the pencil icon at the top bar and write a name of your workflow and save it
Set name icon
Set workflow name
  • Click `Review and publish` and you’ll see the review of what does the workflow do
Workflow review
  • If everything is ok, click `Turn on`
Turning on workflow

That’s it! Your workflow is up and running 😎

Conclusion

As you can see, adding a custom code action in workflows opens up a lot of automation possibilities. With such solution you can create highly customized workflows which meet your unique needs.

Cheers!

Subscribe to Master HubSpot with Expert Tutorials

Don’t miss out on the latest issues. Sign up now to get access to the library of members-only issues.
jamie@example.com
Subscribe