Custom Workflow Actions
Use HubSpot's workflows tool to automate business processes and allow your team to be more efficient. You can create custom workflow actions to integrate your service with HubSpot's workflows.
After setting up your custom action, when users install your application, they can add the custom action to their workflows.
When those workflows execute, HTTPS requests will send to the configured URL with the payload that you set up. Requests made for your custom action will use the v2 version of the X-HubSpot-Signature. Learn more about validating requests from HubSpot.
You can also skip forward to the following sections:
- Before you get started
- Define your custom action
- Functions
- Input fields
- Fetch external data fields
- Output fields
- Labels
- Execution
- Asynchronous custom action execution
- Add custom execution messages with execution rules
- Test and publish your custom action
The final section in this article provides several custom action examples.
- You'll need a HubSpot developer account with a HubSpot app. Your app logo will be used as the icon for the custom action.
- When making requests to the custom workflow action endpoints, you must include your HubSpot developer account key in the request URL. For example:
https://api.hubspot.com/automation/v4/actions/{appId}?hapikey={developer_API_key}
To create a custom workflow action, you'll need to define the action using the following fields. This also specifies the request format for requests coming from HubSpot, as well as the handling of responses from your service.
actionUrl
: the URL where an HTTPS request is sent when the action is executed. The request body will contain information about which user the action is executing on behalf of, and what values were entered for the input fields.objectTypes
: which CRM objects this action can be used with.published
: by default, custom actions are created in an unpublished state. Unpublished actions are only visible in the developer portal associated with your HubSpot application. To make a custom action visible to users, update the published flag on your action definition to true.inputFields
: the inputs that the action receives. These will be filled by the user.inputFieldDependencies
: these rules allow fields to be grayed out until other fields meet specific conditions.outputFields
: the values that the action will output that can be used by later actions in the workflow. A custom action can have zero, one, or many outputs.objectRequestOptions
: properties of the enrolled object included in the payload to the actionUrl.labels
: copy that describes to the user what the action's fields represent and what the action does. English labels are required, but labels can be specified in any of the following supported languages as well: French (fr
), German (de
), Japanese (ja
), Spanish (es
), Brazilian Portuguese (pt-br
), and Dutch (nl
).executionRules
: a list of definitions you can specify to surface errors from your service to the user creating the workflow.functions
: code snippets that are run in order to transform the payload being sent to a url and/or transform the response from that url.
Example custom action definition
The above definition will render the following in the workflows tool:
There are two types of calls made for custom workflow actions:
- Field option fetches: populate a list of valid options when a user is configuring a field. Learn more about using field option fetches to fetch external data fields.
- Action execution requests: made when an action is being executed by a workflow that includes your custom action.
Functions are snippets of code used to modify payloads before sending them to an API. You can also use functions to parse results from an API. HubSpot's functions are backed by AWS Lambda. In the following code:
event
contains the data that is passed to the functionexports.main
is the method that will be called when the function is run.- The
callback
function can be used to return a result.
The code should be formatted as follows:
When setting up a function, the functionSource
format will be in string. Ensure that the characters in the code have been escaped.
Generally, the definition of a function will follow the format:
In the example below, examine the input code, the function used, and the output produced.
Function input:
Function used:
Output expected:
Input field definitions will adhere to the following format:
name
: the internal name of the input field, separate from its label. The label displayed in the UI must be defined using the labels section of the custom action definition.type
: the type of value required by the input.fieldType
: how the input field should be rendered in the UI. Input fields mimic CRM properties, learn more about validtype
andfieldType
combinationssupportedValueTypes
have two valid values:OBJECT_PROPERTY
: the user can select a property from the enrolled object or an output from a previous action to use as the value of the field.STATIC_VALUE
: this should be used in all other cases. It denotes that the user must enter a value themselves.
isRequired
: this determines whether the user must give a value for this input or not
Input field definitions should be formatted as follows:
You can also hard code options for the user to select:
The payload sent to the optionsURL
will be formatted as follows:
The expected response should be formatted as follows:
In the code above, note that there's pagination being set to limit the number of returned options. This instructs the workflow that more options can be loaded.
In addition, the list of options is made searchable by including searchable:true
.
To manage external data, you can include two hooks to customize the field option fetch lifecycle:
PRE_FETCH_OPTIONS
: a function that configures the payload sent from HubSpot.POST_FETCH_OPTIONS
: a function that transforms the response from your service into a format that's understood by HubSpot.
When included, this function will apply to each input field. You can apply it to a specific input field by specifying an id
in the function definition.
The payload sent from HubSpot will be formatted as follows:
The response should then be formatted as follows:
To parse the response into an expected format, per the external data fields, use a POST_FETCH_OPTIONS
function. The definition for a POST_FETCH_OPTIONS
function is the same as a PRE_FETCH_OPTIONS
function. When external external data fetch options are defined, a dropdown menu will be rendered in the input options for the action.
The function input will be formatted as follows:
The function output will be formatted as follows:
Use output fields to output values from your custom action to use in other actions. The definition for output fields is similar to the definition for input fields:
- name: how this field is referenced in other parts of the Custom Action. The label displayed in the UI must be defined using the `labels` section of the Custom Action
- type: the type of value required by the input.
- fieldType: is how the input field should be rendered in the UI. Input fields mimic CRM properties, learn more about valid
type
andfieldType
combinations
The output field should be formatted as follows:
When using an output field, values are parsed from the response from the actionURL
. For example, you can copy output fields to an existing property in HubSpot.
Use labels to add text to your outputs or inputs in the workflow editor. Labels are loaded into HubSpot's language service and may take a few minutes to display. Portals set to different regions or languages will display the label in the corresponding language, if available.
labels
: copy describing what the action's fields represent and what the action does. English labels are required, but labels can be specified in any of the following supported languages as well: French (fr
), German (de
), Japanese (ja
), Spanish (es
), Brazilian Portuguese (pt-br
), and Dutch (nl
).actionName
: the action's name shown in the Choose an action panel in the workflow editor.actionDescription
: a detailed description for the action shown when the user is configuring the custom action.actionCardContent
: a summarized description shown in the action's card.appDisplayName
: The name of the section in the “Choose an Action” panel where all the actions for the app are displayed. If appDisplayName is defined for multiple actions, the first one found is used.inputFieldLabels
: an object that maps the definitions from inputFields to the corresponding labels the user will see when configuring the action.outputFieldLabels
: an object that maps the definitions from outputFields to the corresponding labels shown in the workflows tool.inputFieldDescriptions
: an object that maps the definitions from inputFields to the descriptions below the corresponding labels.executionRules
: an object that maps the definitions from your executionRules to messages that will be shown for action execution results on the workflow history. There is a separate section in these docs for execution rules.
Label definitions should be formatted as follows:
When an execution executes, a https request is sent to the actionUrl
.
callbackId
: a unique ID for the specific execution. If the custom action execution is blocking, use this ID.object
: the values of the properties requested inobjectRequestOptions
.InputFields
: the values for the inputs that the user has filled out.
The execution payload will be formatted as follows:
The expected response should be formatted as follows:
When looking at the execution response:
outputFields
: the values of the output fields defined earlier. These values can be used in later actions.hs_execution_state
: an optional special value that can added to outputFields. It is not possible to specify a retry, only the following values can be added:- SUCCESS
- FAIL_CONTINUE
- BLOCK
- ASYNC
SUCCESS
and FAIL_CONTINUE
indicate that the action has completed and the workflow should move on to the next action to execute. If no execution state is specified, status codes will be used to determine the result of an action:
- 2xx status codes: the action has completed successfully.
- 4xx status codes: the action has failed. The exception is 429 Rate Limited status codes, which are re-treated as retries, and the Retry-After header is respected.
- 5xx status codes: there was a temporary problem with the service, and the action will be retried at a later time. An exponential backoff system is used for retries, retries will continue for up to 3 days before failing.
Use execution functions to format data before sending to the actionURL
and parse data from the actionURL
. There are two types of execution functions:
PRE_ACTION_EXECUTION
POST_ACTION_EXECUTION
PRE_ACTION_EXECUTION function
Use PRE_ACTION_EXECUTION
functions to format data before sending it to the actionURL
The function definition will be formatted as follows:
The function input should be formatted as follows:
The function output should be formatted as follows:
POST_ACTION_EXECUTION function
After receiving a response from the actionURL
, use a POST_ACTION_EXECUTION
function to format data for HubSpot.
The function definition will be formatted as follows:
The function input should be formatted as follows:
The function output should be formatted as follows:
Execute custom workflow actions asynchronously by blocking and later completing the action.
Use custom actions to block workflow execution. Instead of executing the next action in the workflow after your custom action after receiving a completed (2xx or 4xx status code)
response from your service, the workflow will stop executing ("block") that enrollment until you tell the workflow to continue.
When blocking, you can specify a value for the hs_default_expiration
field, after which your custom action will be considered expired. The execution of the workflow will then resume and the action following your custom action will be executed, even if the action is not completed.
To block a custom action, your action execution response must have the following format:
To complete a blocked custom action execution, use the following endpoint: /callbacks/{callbackId}/complete
Format the request body as follows:
The actual messages can be specified in the labels section of the custom action:
The executionRules
will be tested in the order provided. If there are multiple matches, only the message from the first rule that matches is displayed to the user.
The rule matches when the execution output corresponds to a specified value in the rule. For example, consider this set of executionRules
:
With the above, the following matches would occur:
{"errorCode": "ALREADY_EXISTS", "widgetName": "Test widget"}
: This would match the first rule, sinceerrorCode
is equal toALREADY_EXISTS
. In this instance, even though there is awidgetName
output, it isn't used in the rule definition so any value is allowed.{"errorCode": "WIDGET_SIZE", "sizeError": "TOO_SMALL"}
: This would match the second rule, sinceTOO_SMALL
is one of the matchingsizeError
s, anderrorCode
isWIDGET_SIZE
.{"errorCode": "WIDGET_SIZE", "sizeError": "NOT_A_NUMBER"}
: This would match the third rule, since even though theerrorCode
isWIDGET_SIZE
, thesizeError
does not match any of the values specified by the second rule (TOO_SMALL
orTOO_BIG
).
This matching mechanism allows you to specify fallback errors, so that you can have specific errors for important error cases, but fall back to more generic error messages for less common errors. Here is an example of how the custom message would display:
After creating your new custom action, you can test and publish it.
Testing custom actions before publishing
Before publishing your custom action, you can test action execution and fetching options by pointing the URL to webhook.site. This allows you to inspect the payload and return a specific response.
You can also test the action in your developer portal by creating a workflow in the workflows tool. Then, adding your new action.
When you've complete your testing, it is recommended to archive your test actions. Learn more about archiving actions in the Archive a custom action section in the Endpoints tab at the top of this article..
Publishing custom actions
By default, custom actions are created in an unpublished state. Unpublished custom actions are only visible in the developer portal associated with the corresponding HubSpot application. To make a custom action visible to users, update the published
flag on your action definition to true
. If an action is unpublished, portals that have already added the action to their workflow will still be able to edit and execute already added actions. But, they won't be able to add the action again.
The code snippets below provide examples of several common use-cases for custom actions, such as defining a widget or invoking a serverless function.
This example features the following input fields, created for contact and deal workflows:
widgetName
: a static input fieldwidgetColor
: a dropdown field with optionswidgetOwner
: a field representing a HubSpot owner.widgetQuantity
: a field whose derived from a property (that the user creating the workflow selects) on the enrolled object.
The following custom action uses a serverless function to transform the payload that is sent to the configured actionUrl. Since the objectTypes
field isn't specified in the custom action definition, this action will be available in all workflows types.
The following custom action has field dependencies and options that are fetched from an external API. Because the widget size depends on the widget color, the user won't be able to input a value for the widget size until a widget color is chosen.
The widget cost is also dependent on the widget color, but it is conditional on the value that the user selects for the widget color; the user won't be able to input a value for the widget cost unless Red is selected as the widget color.
Thank you for your feedback, it means a lot to us.