Custom code workflow actions

Customers can now write and execute javascript inside a custom action in workflows. In the Workflow Actions panel there is a new action called "Custom Code Action"Image 2020-09-11 at 8.25.12 AM

This will open up a code editor to let you tell a workflow exactly what to do using Node.js.Image 2020-09-11 at 8.26.00 AM

The code will be triggered when the object reaches this stage of a workflow

There are three main things to keep in mind when working with code actions:

  • The exports.main() function is called when the code snippet action is executed.
  • The event argument is an object containing details for the workflow execution
  • The callback() function is used to pass data back to the workflow. It should be called in the exports.main function.

The event object will contain the following data:

//example payload
  "origin": {
    // Your portal ID
    "portalId": 1,    // Your custom action definition ID
    "actionDefinitionId": 2,
  "object": {
    // The type of CRM object that is enrolled in the workflow
    "objectType": "CONTACT",    // The ID of the CRM object that is enrolled in the workflow
    "objectId": 4,
  // A unique ID for this execution.
  "callbackId": "ap-123-456-7-8"

Available libraries

Several popular Node.js libraries are available for use within the code action.

  • "@hubspot/api-client": "^3.0.1",
  • "async": "^3.2.0",
  • "aws-sdk": "^2.744.0",
  • "axios": "^0.20.0",
  • "lodash": "^4.17.20",
  • "mongoose": "^5.10.2",
  • "mysql": "^2.18.1",
  • "redis": "^3.0.2",
  • "request": "^2.88.2"
  • bluebird 3.7.2
  • random-number-csprng 1.0.2googleapis 67.0.0

The libraries can be loaded using the normal require() function at the top of your code.


There are times you will want your code to reference something that shouldn't be widely shared.  Most often, this is a means of authentication, like an API key.  You can manage the secrets your function has access to directly in the workflow action definition.

Image 2020-09-11 at 8.26.44 AM

From there, you will be able to add whatever values you need, including your HubSpot API key

Once added, the secrets will be available as environment variables. 

// Sample Functiom Example

const hubspot = require('@hubspot/api-client');
exports.main = (event, callback) => {
  return callback(processEvent(event));
};function processEvent(event) {
  // secrets can be accessed via environment variables
  const hubspotClient = new hubspot.Client({ apiKey: process.env.HAPIKEY });
  hubspotClient.crm.contacts.basicApi.getById(event["object"]["objectId"], ["email", "phone"])
  .then(results => {
    let email = results.body["properties"]["email"]
    let phone = results.body["properties"]["phone"]
    // ...
  .catch(err => {


An important tool for developers is ability to print outputs from their code. It helps you debug issues and provide better support for your end users. To see the output of the logs, you can find them in the "History" tab of the workflow.  


How to Define Outputs

In the function define the output fields you want to use later in the workflow. Then select the data output type in the UI (number, string, boolean, datetime, enum, date phone number) and input the field you want to output.

The output fields should be part of a json object formatted like:



You can then use the output from your code action as in input to the Copy Property Action. This removes the need to make another API call to store the value as a property on your object.



Custom code actions must finish running within 20 seconds and can only use up to 128 MB of memory. Exceeding any of these limits will result in an error. 


It is common to fetch object properties using the HubSpot API or to call other HubSpot API endpoints. Like any other API call, you'll still need to follow the normal call limits. When those calls are coming from a custom code action, we'll automatically retry the action for secondly limits. 

Common Use Cases

  • Transforming data (i.e. turning a string into a date_time or changing the formatting of a phone number)
  • Data Hygiene (name capitalization, name concatenation etc)
  • Lead Assignment
  • Territory Management
  • SLA Management for Service Issues
  • Customizing webhook payloads: change the format of the request that gets made for the webhook action, and with the custom code action (and the requests library)

To help get you started, we're providing a number code samples you can use to then customize to your particular needs.  



Generating random numbers: it is common to use Math.random to generate random numbers but users may see the same numbers generated across different executions. This is because Math.random is seeded by the current time. Since we may enroll many objects into a workflow at the same time and we clear our state on every execution, different executions end up seeding Math.random in the same way. To get around this, make use of the random-number-csprng 1.0.2 library which guarantees cryptographically secure pseudo-random number generation. 

Was this page helpful? *
This form is for feedback on our developer docs. If you have feedback on the HubSpot product, please share it in our Idea Forum instead.