Last modified: September 3, 2025
If you have an Operations Hub Professional or Enterprise account, you can use the Custom code action in workflows to write and execute JavaScript or Python (in beta). With custom code actions, you can extend workflow functionality within and outside of HubSpot. To see examples of common custom code actions, view HubSpot’s Programmable Automation Use Cases.
Custom code actions support JavaScript using the Node.js runtime framework. If you’re using Python for your custom code action, the custom code action will use Python runtime framework. When an action executes, the runtime compute is managed through a serverless function by HubSpot and AWS Lambda.
If you encounter any general issues implementing your custom code action, you can reach out to HubSpot support. However, if you’re facing any issues with your written custom code, it’s recommended to search and post on the HubSpot Developer’s Forum to get help with troubleshooting your code.
Node.js supported libraries
If you’re using Node.js, the following libraries are available for use within the code action. These libraries can be loaded using the normalrequire()
function at the top of your code.
@hubspot/api-client
:^10
async
:^3.2.0
aws-sdk
:^2.744.0
axios
:^1.2.0
lodash
:^4.17.20
mongoose
:^6.8.0
mysql
:^2.18.1
redis
:^4.5.1
request
:^2.88.2
bluebird
:^3.7.2
random-number-csprng
:^1.0.2
googleapis
:^67.0.0
Please note:The v4 Associations API is supported in Version 9.0.0 or later of the NodeJS HubSpot Client and in Version 8 of the NodeJS HubSpot Client.
Python supported libraries
If you’re using Python, you can load the following libraries with an import statement at the top of your code. The import statement should be formatted asfrom [libraryname] import [item]
, such as from redis.client import redis
.
requests 2.28.2
@hubspot/api-client ^8
google-api-python-client 2.74.0
mysql-connector-python 8.0.32
redis 4.4.2
nltk 3.8.1
import
, such as import os
.
Get started
Use the code samples below to begin using custom code workflow actions.Code samples
- Python
Create a custom code action
To add a custom code action to a workflow:- In your HubSpot account, navigate to Automation > Workflows.
- Click the name of a workflow, or create a new workflow.
- Click the + plus icon to add a workflow action.
- In the left panel, search for and select Custom code.

- By default, custom code actions will use Node.js. If you’re in the Python beta and want to build your action with Python, click the Language dropdown menu, then select Python.
- In the Description field, enter a description for your custom workflow action. This description will appear in the corresponding workflow action card.
- You can use a secret with your custom code action, such as a private app access token. The app must include the respective scopes of any data that you’re trying to pull from HubSpot, such as
contacts
orforms
. Learn more about HubSpot private apps.- To use an existing secret, click Add secret. Then, select the checkbox next to the secret that you’d like to add.
- To add a new secret, click Add secret. In the dialog box, enter the Secret name and Secret value. Then, click Save. You can now select this secret in future custom code actions.
- To edit or delete existing secrets, click Manage secrets.
- To include properties in your custom code:
- Click the Select a property, then select a property from the data panel. You can use existing properties or previously formatted property values in the workflow. After selecting your property, enter a Property name to use in your code. Learn how to reference a property in your custom code.
- To add another property, click Add property. Each property can only be added once and must have a unique Variable ID. You can use up to 50 properties with your custom code.
- To delete a property, click the delete icon.
- In the code field, enter your JavaScript or Python.
- To define data outputs that can be used as inputs later in the workflow, for example with an Edit records action:
- Under Data outputs, click Add output.
- Click the Data type dropdown menu, and select a type of data.
- In the Name field, enter a name for the data output.
- To add multiple outputs, click Add output.
- At the top, click Save.

Please note:The code field will not display lint errors when using Python.
- The
def main(event):
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 theexports.main
function. This can only be used with Node.js.
event
object will contain the following data:
Set a rate limit for your action
Set a rate limit to determine how often the custom code action should execute. The rate limit will also impact all following actions in the workflow after the custom code action.- In the workflow editor, click the custom code action.
- At the bottom, click Configure rate limit to expand the rate limit section.
- Click to toggle the Turn on rate limiting switch on. By default, this setting is turned off.
- Set up your rate limit:
- Action executions: set the maximum number of executions per time period.
- Time frame: set the time frame for your rate limit. You can set this time frame to Seconds, Minutes, or Hours.

Test the action
When adding a custom code action to a workflow, you can test the action to ensure that your code runs as expected before turning the workflow on. When testing a custom code action, you’ll start by selecting a record to test the code with, then run the code. This test will run only the code in your custom action, not any of the other actions in the workflow. When the code is finished running, you’ll be able to view the code outputs and the log of your test.Please note:When testing your custom code, the code will run and any changes will apply to the selected test record. It’s recommended to create a dedicated test record if you want to avoid updating your live records.
- In the workflow preview, click the custom code action.
- At the bottom, click Test action to expand the testing section.
- Click the Object dropdown menu, then select a record to test your code with.
- If you’re using previously formatted property values in the workflow, enter a test value for the formatted data.

- To run the code, click Test.
- In the dialog box, confirm that you want to test your code against the selected record by clicking Test.
-
Once your code is done running, the results of your test will appear:
- Status: the success or failure status of your custom code action.
- Data outputs: the values that resulted for your defined data outputs. An alert will display next to any outputs that the code generated which weren’t defined either in the Data outputs section or in the code editor. You’ll need to add those outputs in order to use them later in the workflow.
- Logs: information about the test itself, such as how much memory the action took to execute and the total runtime.
- When you’re done testing the action, click Save to save your changes.

Secrets
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 a private app access token. You can manage the secrets your function has access to directly in the workflow action definition. When using multiple secrets within a custom code, the total length of all secret values must not exceed 1000 characters.
Add HubSpot properties to your custom code
At times, you may need to fetch object properties in your custom code action. Rather than using HubSpot’s APIs, you can add these properties directly in the workflow action definition. Add properties and set property names to reference properties in your code. Once added, the property can be referenced in the custom code. You can add up to 50 properties in each custom code action.
Logging
An important tool for developers is the ability to print output data from their code. It helps debug issues and provide better support for end users. To see the output of the logs, learn how to review your workflow’s action logs.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 (e.g., 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 accordingly, depending on the language used:
- If your data output type is in string format, the limit for string output values is 65,000 characters. Exceeding this limit will result in an
OUTPUT_VALUES_TOO_LARGE
error. - If you’re using the Edit records action, take note of compatible source and target properties.
- When updating date properties:
- If you’re using an output to update a datetime property, the output will need to be in UNIX millisecond format.
- If you’re using an output to update a date property instead of a datetime, the output will need to be in UNIX millisecond format and the time on the date will need to be set to midnight UTC.
currentDate.setUTCHours(0,0,0,0)

Limitations
Custom code actions must finish running within 20 seconds and can only use up to 128 MB of memory. Exceeding either of these limits will result in an error.Retries
You may need to fetch object properties using the HubSpot API or to call other HubSpot API endpoints in your custom code action. Like any other API call, you’ll still need to comply with HubSpot API rate limits.- If you’re using Node.js and encounter a rate limiting error but you want HubSpot to retry your call, you’ll need to throw the error in the
catch
block of your custom code action.

- If you’re using Python and encounter a rate limiting error but you want HubSpot to retry your call, you’ll need to raise the error in the
except
block of your custom code action.

Please note:If the call fails due to a rate limiting error, or a 429 or 5XX error from axios or @hubspot/api-client, HubSpot will reattempt to execute your action for up to three days, starting one minute after failure. Subsequent failures will be retried at increasing intervals, with a maximum gap of eight hours between tries.
Caveats
If you’re using Node.js for your custom code, take note of the following caveats:- Generating random numbers: it’s 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 HubSpot may enroll many objects into a workflow at the same time and clear the state on every execution, different executions end up seeding Math.random in the same way. Instead, you can use of random-number-csprng 1.0.2 library which guarantees cryptographically secure pseudo-random number generation.
- Variable re-use: to save memory, any variables declared outside the
exports.main
function may be re-used for future executions of the custom code action. This is useful when connecting to external services like a database, but any logic or information that needs to be unique to each execution of the custom code action should be inside theexports.main
function.
- Variable re-use: similar to the above, any variables declared outside the
def main
function may be re-used for future executions of the custom code action.- If you’ve declared a variable outside the
def main
function but do not plan on altering it, you can reference the variable directly. - If you plan on altering a variable, you can declare the variable within the
def main
function with a global keyword before referencing it.
- If you’ve declared a variable outside the