Última modificação: 28 de agosto de 2025
Use Ferramenta de fluxos de trabalho da HubSpot para automatizar os processos de negócios e melhorar a eficiência da equipe. Você pode criar ações de fluxo de trabalho personalizadas para integrar seu serviço a fluxos de trabalho do HubSpot.
Depois de configurar sua ação personalizada, quando os usuários instalarem o aplicativo, eles poderão adicionar a ação personalizada aos seus fluxos de trabalho.
Quando esses fluxos de trabalho forem executados, as solicitações HTTPS serão enviadas à URL configurada com a payload definida. As solicitações feitas para sua ação personalizada usarão a versão v2 do X-HubSpot-Signature. Saiba mais sobre como validar solicitações do HubSpot.
Você também pode avançar para as seguintes seções:
A seção final deste artigo fornece vários exemplos de ações personalizadas.
Antes de começar
Definir sua ação personalizada
Para criar uma ação de fluxo de trabalho personalizada, você precisará definir a ação usando os seguintes campos. Isso também especifica o formato das solicitações provenientes do HubSpot, bem como o tratamento das respostas pelo seu serviço.
-
actionUrl
: a URL para a qual uma solicitação HTTPS é enviada quando a ação é executada. O corpo da solicitação conterá informações sobre o usuário para o qual ação está sendo executada e quais valores foram inseridos para os campos de entrada.
-
objectTypes
: em quais objetos do CRM esta ação pode ser usada.
-
published
: por padrão, as ações personalizadas são criadas em um estado não publicado. As ações não publicadas ficam visíveis somente no portal do desenvolvedor associado ao seu aplicativo HubSpot. Para tornar uma ação personalizada visível para os usuários, atualize o sinalizador published na definição da ação para true.
-
inputFields
: as entradas recebidas pela ação. Os campos serão preenchidos pelo usuário.
-
inputFieldDependencies
: essas regras definem as relações entre duas ou mais entradas, com base em suas dependencyType
, como neste exemplo aqui. Você pode usar as seguintes dependencyType
opções:
SINGLE_FIELD
: essas regras permitem que os campos fiquem esmaecidos até que outros campos atendam a condições específicas. Use esta opção para verificar se um campo está pré-preenchido antes de permitir que os visitantes continuem preenchendo o restante do formulário. Os campos de controle (pai) fornecerão valores para os campos dependentes (filho) correspondentes.
CONDITIONAL_SINGLE_FIELD
: essas regras permitem que os campos sejam ocultados até que outros campos atendam a condições específicas. Use esta opção para mostrar ou ocultar campos específicos com base em uma seleção anterior. Por exemplo, se sua empresa for uma padaria, você poderá adicionar uma caixa de seleção para perguntar aos visitantes se eles gostam de bolo e, somente se a caixa de seleção estiver marcada, exibir um campo para perguntar de que tipo de bolo eles gostam.
-
outputFields
: os valores que a ação enviará e que poderão ser usados por ações posteriores no fluxo de trabalho. Uma ação personalizada pode ter zero, uma ou muitas saídas.
-
objectRequestOptions
: propriedades do objeto inscrito incluídas na payload de actionUrl.
-
labels
: texto que descreve o que os campos de ação representam e o que a ação faz ao usuário. Rótulos em inglês são obrigatórios, mas os rótulos podem ser especificados em qualquer um dos seguintes idiomas permitidos:
- Francês (
fr
)
- Alemão (
de
)
- Japonês
ja
)
- Espanhol (
es
)
- Português do Brasil (
pt-br
)
- Holandês (
nl
)
- Polonês (
pl
)
- Sueco (
sv
)
- Italiano (
it
)
- Dinamarquês - Dinamarca (
da_dk
)
- Finlandês (
fi
)
- Norueguês (
no
)
- Chinês tradicional - Taiwan (
zh-tw
)
-
executionRules
: uma lista de definições que você pode especificar para revelar erros do seu serviço ao usuário que cria o fluxo de trabalho.
-
functions
: snippets de código que são executados para transformar a payload que está sendo enviada para um URL e/ou transformar a resposta desse URL.
Exemplo de definição de ação personalizada
//
{
"actionUrl": "https://webhook.site/94d09471-6f4c-4a7f-bae2-c9a585dd41e0",
"objectTypes": ["CONTACT"],
"inputFields": [
{
"typeDefinition": {
"name": "staticInput",
"type": "string",
"fieldType": "text"
},
"supportedValueTypes": ["STATIC_VALUE"],
"isRequired": true
},
{
"typeDefinition": {
"name": "objectInput",
"type": "string",
"fieldType": "text"
},
"supportedValueTypes": ["OBJECT_PROPERTY"],
"isRequired": true
},
{
"typeDefinition": {
"name": "optionsInput",
"type": "enumeration",
"fieldType": "select",
"optionsUrl": "https://webhook.site/94d09471-6f4c-4a7f-bae2-c9a585dd41e0"
},
"supportedValueTypes": ["STATIC_VALUE"]
}
],
"inputFieldDependencies": [
{
"dependencyType": "SINGLE_FIELD",
"dependentFieldNames": ["objectInput"],
"controllingFieldName": "staticInput"
}
],
"outputFields": [
{
"typeDefinition": {
"name": "myOutput",
"type": "string",
"fieldType": "text"
},
"supportedValueTypes": ["STATIC_VALUE"]
}
],
"objectRequestOptions": {
"properties": ["email"]
},
"labels": {
"en": {
"inputFieldLabels": {
"staticInput": "Static Input",
"objectInput": "Object Property Input",
"optionsInput": "External Options Input"
},
"actionName": "My Extension",
"actionDescription": "My Extension Description",
"appDisplayName": "My App Display Name",
"actionCardContent": "My Action Card Content"
}
},
"functions": [
{
"functionType": "POST_ACTION_EXECUTION",
"functionSource": "exports.main = (event, callback) => {\r\n callback({\r\n outputFields: {\r\n myOutput: \"example output value\"\r\n }\r\n });\r\n}"
},
{
"functionType": "POST_FETCH_OPTIONS",
"functionSource": "exports.main = (event, callback) => {\r\n callback({\r\n \"options\": [{\r\n \"label\": \"Big Widget\",\r\n \"description\": \"Big Widget\",\r\n \"value\": \"10\"\r\n },\r\n {\r\n \"label\": \"Small Widget\",\r\n \"description\": \"Small Widget\",\r\n \"value\": \"1\"\r\n }\r\n ]\r\n });\r\n}"
}
]
}
A definição acima renderizará o seguinte na ferramenta de fluxos de trabalho:
Há dois tipos de chamadas feitas para ações de fluxo de trabalho personalizado:
- Buscas de opção de campo: preencha uma lista de opções válidas quando um usuário está configurando um campo. Saiba mais sobre como usar as buscas de opção de campo para buscar campos de dados externos.
- Solicitações de execução de ação: feitas quando uma ação está sendo executada por um fluxo de trabalho que inclui a ação personalizada.
Funções
Funções são snippets usados para modificar payloads antes de enviá-las a uma API. Você também pode usar funções para analisar os resultados de uma API. As funções do HubSpot têm o suporte do AWS Lambda. No seguinte código:
event
contém os dados passados para a função
exports.main
é o método que será chamado quando a função for executada.
- A função
callback
pode ser usada para retornar um resultado.
O código deve ser formatado da seguinte forma:
exports.main = (event, callback) => {
callback({
"data": {
"field": "email",
"phone": "1234567890"
}
});
}
Ao configurar uma função, o formato functionSource
será uma string. Verifique se os caracteres no código passaram por escape.
Geralmente, a definição de uma função seguirá o formato:
//
{
"functionType": "PRE_ACTION_EXECUTION",
"functionSource": "exports.main = (event, callback) => {\r\n callback({\r\n \"data\": {\r\n \"field\": \"email\",\r\n \"phone\": \"1234567890\" \r\n }\r\n });\r\n"
}
Exemplo de função
No exemplo abaixo, examine o código de entrada, a função usada e a saída produzida.
Entrada de função:
//
{
"callbackId": "ap-102670506-56777914962-11-0",
"origin": {
"portalId": 102670506,
"actionDefinitionId": 10860211,
"actionDefinitionVersion": 1,
"extensionDefinitionId": 10860211,
"extensionDefinitionVersionId": 1
},
"context": {
"source": "WORKFLOWS",
"workflowId": 192814114
},
"object": {
"objectId": 614,
"objectType": "CONTACT"
},
"inputFields": {
"widgetOwner": "10887165",
"widgetName": "My Widget Name"
}
}
Função usada:
//
exports.main = (event, callback) => {
callback({
"data": {
"myObjectId": event["object"]["objectId"],
"myField": event["inputFields"]["widgetName"]
}
});
}
Resultado esperado:
//
{
"data": {
"myObjectId": 614,
"myField": "My Widget Name"
}
}
Campos de entrada
As definições do campo de entrada seguirão o seguinte formato:
name
: o nome interno do campo de entrada, separado do seu rótulo. O rótulo exibido na interface do usuário deve ser definido usando a seção de rótulos da definição de ação personalizada.
type
: o tipo de valor exigido pela entrada.
fieldType
: como o campo de entrada deve ser renderizado na interface do usuário. Os campos de entrada imitam as propriedades do CRM; saiba mais sobre as combinações válidas de type
e fieldType
supportedValueTypes
têm dois valores válidos:
OBJECT_PROPERTY
: o usuário pode selecionar uma propriedade do objeto inscrito ou uma saída de uma ação anterior para usar como o valor do campo.
STATIC_VALUE
: deve ser usado em todos os outros casos. Indica que o usuário deve inserir um valor.
isRequired
: determina se o usuário deve fornecer um valor para esta entrada
As definições do campo de entrada devem ser formatadas da seguinte forma:
//
{
"typeDefinition": {
"name": "staticInput",
"type": "string",
"fieldType": "text"
},
"supportedValueTypes": ["STATIC_VALUE"],
"isRequired": true
}
Você também pode embutir opções para o usuário selecionar:
//
{
"typeDefinition": {
"name": "widgetColor",
"type": "enumeration",
"fieldType": "select",
"options": [
{
"value": "red",
"label": "Red"
},
{
"value": "blue",
"label": "Blue"
},
{
"value": "green",
"label": "Green"
}
]
},
"supportedValueTypes": ["STATIC_VALUE"]
}
Usar dados externos
Em vez de embutir opções de campo, você também pode buscar dados externos com campos de dados externos. Por exemplo, você pode recuperar uma lista de projetos de reunião ou uma lista de produtos para servir como entradas.
Observação:
Para passar dados de entrada para outras entradas, você deve definir seu relacionamento usando inputFieldDependencies
. Saiba mais sobre como definir sua ação personalizada.
O campo de entrada deve ser formatado da seguinte forma:
//
{
"typeDefinition": {
"name": "optionsInput",
"type": "enumeration",
"fieldType": "select",
"optionsUrl": "https://your-url-here.com"
},
"supportedValueTypes": ["STATIC_VALUE"]
}
A payload enviada para optionsURL
será formatada da seguinte forma:
//
{
"origin": {
"portalId": 1,
"actionDefinitionId": 2,
"actionDefinitionVersion": 3
},
"objectTypeId": "0-1",
"inputFieldName": "optionsInput",
"inputFields": {
"widgetName": {
"type": "OBJECT_PROPERTY",
"propertyName": "widget_name"
},
"widgetColor": {
"type": "STATIC_VALUE",
"value": "blue"
}
},
"fetchOptions": {
"q": "option label",
"after": "1234="
}
}
Campo | Descrição |
---|
portalId | A ID da conta HubSpot. |
actionDefinitionId | Sua ID de definição de ação personalizada. |
actionDefinitionVersion | Sua versão de definição de ação personalizada. |
objectTypeId | O tipo de objeto do fluxo de trabalho a ação está sendo usada no. |
inputFieldName | O campo de entrada para o qual você está buscando opções. |
inputFields | Os valores dos campos que já foram preenchidos pelo usuário do fluxo de trabalho. |
q | A consulta de pesquisa fornecida pelo usuário. Isso deve ser usado para filtrar as opções retornadas. Isso só será incluído se a busca de opção anterior retornar searchable: true e o usuário inseriu uma consulta de pesquisa. |
after | O cursor de paginação. Este será o mesmo cursor de paginação que foi devolvido pela extração de opções anterior; ele pode ser usado para manter o controle de quais opções já foram obtidas. |
A resposta esperada deve estar formatada da seguinte forma:
//
{
"options": [
{
"label": "Big Widget",
"description": "Big Widget",
"value": "10"
},
{
"label": "Small Widget",
"description": "Small Widget",
"value": "1"
}
],
"after": "1234=",
"searchable": true
}
Campo | Descrição |
---|
q | O cursor de paginação. Se isso for fornecido, o aplicativo de fluxos de trabalho renderizará um botão para carregar mais resultados na parte inferior da lista de opções quando um usuário estiver selecionando uma opção e quando a próxima página for carregada, esse valor será incluído na carga útil da solicitação em fetchOptions.after . Este campo é opcional. |
after | O valor padrão é false . Se for true , o aplicativo de fluxos de trabalho renderizará um campo de pesquisa para permitir que um usuário filtre as opções disponíveis por uma consulta de pesquisa. Quando uma consulta de pesquisa é inserida, as opções serão buscadas novamente com esse termo de pesquisa na carga útil da solicitação em fetchOptions.q . Este campo é opcional. |
No código acima, observe que há uma paginação sendo definida para limitar o número de opções retornadas. Isso instrui o fluxo de trabalho de que mais opções podem ser carregadas.Além disso, a lista de opções se torna pesquisável ao incluir searchable:true
.
Modificar dados externos
Para gerenciar dados externos, você pode incluir dois ganchos para personalizar o ciclo de vida de busca de opção de campo:
PRE_FETCH_OPTIONS
: uma função que configura a payload enviada do HubSpot.
POST_FETCH_OPTIONS
: uma função que transforma a resposta do seu serviço em um formato compreendido pelo HubSpot.
PRE_FETCH_OPTIONS
Quando incluída, esta função será aplicada a cada campo de entrada. Você pode aplicá-la a um campo de entrada específico especificando um id
na definição da função.
//
{
"functionType": "PRE_FETCH_OPTIONS",
"functionSource": "...",
"id": "inputField"
}
A payload enviada do HubSpot será formatada da seguinte forma:
//
{
"origin": {
"portalId": 1,
"actionDefinitionId": 2,
"actionDefinitionVersion": 3
},
"inputFieldName": "optionsInput",
"webhookUrl": "https://myapi.com/hubspot/widget-sizes",
"inputFields": {
"widgetName": {
"type": "OBJECT_PROPERTY",
"propertyName": "widget_name"
},
"widgetColor": {
"type": "STATIC_VALUE",
"value": "blue"
},
"fetchOptions": {
"q": "option label",
"after": "1234="
}
}
}
Campo | Descrição |
---|
portalId | A ID da conta HubSpot. |
actionDefinitionId | Sua ID de definição de ação personalizada. |
actionDefinitionVersion | Sua versão de definição de ação personalizada. |
objectTypeId | O tipo de objeto do fluxo de trabalho a ação está sendo usada no. |
inputFieldName | O campo de entrada para o qual você está buscando opções. |
inputFields | Os valores dos campos que já foram preenchidos pelo usuário do fluxo de trabalho. |
q | A consulta de pesquisa fornecida pelo usuário. Isso deve ser usado para filtrar as opções retornadas. Isso só será incluído se a busca de opção anterior retornar searchable: true e o usuário inseriu uma consulta de pesquisa. |
after | O cursor de paginação. Este será o mesmo cursor de paginação que foi devolvido pela extração de opções anterior; ele pode ser usado para manter o controle de quais opções já foram obtidas. |
A resposta deve ser formatada da seguinte forma:
//
{
"webhookUrl": "https://myapi.com/hubspot",
"body": "{\"widgetName\": \"My new widget\", \"widgetColor\": \"blue\"}",
"httpHeaders": {
"My-Custom-Header": "header value"
},
"contentType": "application/json",
"accept": "application/json",
"httpMethod": "POST"
}
Campo | Descrição |
---|
webhookUrl | A URL do webhook para chamada da HubSpot. |
body | O corpo da solicitação. Isso é opcional. |
httpHeaders | Um mapa de cabeçalhos de solicitação personalizados para adicionar. Isso é opcional. |
contentType | O Content-Type do pedido. O valor padrão é application/json . Isso é opcional. |
accept | O tipo de Accept da solicitação. O valor padrão é application/json . Isso é opcional. |
httpMethod | O método HTTP com o qual fazer a solicitação. O padrão é POST , mas outros valores válidos incluem GET , POST , PUT , PATCH e DELETE . Isso é opcional. |
POST_FETCH_OPTIONS
Para analisar a resposta em um formato esperado, de acordo com os campos de dados externos, use a função POST_FETCH_OPTIONS
. A definição para a função POST_FETCH_OPTIONS
é a mesma que para a função PRE_FETCH_OPTIONS
. Quando opções externas de busca de dados estiverem definidas, um menu suspenso será renderizado nas opções de entrada para a ação.
//
{
"functionType": "POST_FETCH_OPTIONS",
"functionSource": "...",
"id": "inputField"
}
A entrada da função será formatada da seguinte forma:
//
{
// The requested field key
"fieldKey": "widgetSize",
// The webhook response body from your service
"responseBody": "{\"widgetSizes\": [10, 1]}"
}
A saída da função será formatada da seguinte forma:
//
{
"options": [
{
"label": "Big Widget",
"description": "Big Widget",
"value": "10"
},
{
"label": "Small Widget",
"description": "Small Widget",
"value": "1"
}
]
}
Campos de saída
Use campos de saída para gerar valores de ação personalizada para usar em outras ações. A definição dos campos de saída é similar à definição dos campos de entrada:
- name: a forma como este campo é referenciado em outras partes da Ação personalizada. O rótulo exibido na interface do usuário deve ser definido usando a seção `labels` da Ação personalizada
- type: o tipo de valor exigido pela entrada.
- fieldType: é como o campo de entrada deve ser renderizado na interface do usuário. Os campos de entrada imitam as propriedades do CRM; saiba mais sobre as combinações válidas de
type
e fieldType
O campo de saída deve ser formatado da seguinte forma:
//
{
"outputFields": [
{
"typeDefinition": {
"name": "myOutput",
"type": "string",
"fieldType": "text"
}
}
]
}
Ao usar um campo de saída, os valores são analisados a partir da resposta de actionURL
. Por exemplo, você pode copiar campos de saída para uma propriedade existente no HubSpot.
**
**
Rótulos
Use rótulos para adicionar texto às saídas ou entradas no editor de fluxo de trabalho. Os rótulos são carregados no serviço de linguagem do HubSpot e podem levar alguns minutos para serem exibidos. Os portais definidos para regiões ou idiomas diferentes exibirão o rótulo no idioma correspondente, se disponível.
labels
: texto que descreve o que os campos de ação representam e o que a ação faz. Rótulos em inglês são obrigatórios, mas os rótulos podem ser especificados em qualquer um dos seguintes idiomas permitidos: francês (fr
), alemão (de
), japonês (ja
), espanhol (es
), português do Brasil (pt-br
) e holandês (nl
).
actionName
: o nome da ação mostrado no painel Escolha uma ação no editor de fluxo de trabalho.
actionDescription
: uma descrição detalhada da ação exibida quando o usuário está configurando a ação personalizada.
actionCardContent
: uma descrição resumida exibida no cartão de ação.
appDisplayName
: O nome da seção no painel “Escolher uma ação”, em que todas as ações do aplicativo são exibidas. Se appDisplayName for definido para várias ações, a primeira ação encontrada será usada.
inputFieldLabels
: um objeto que mapeia as definições de inputFields para os rótulos correspondentes que o usuário verá ao configurar a ação.
outputFieldLabels
: um objeto que mapeia as definições de outputFields para os rótulos correspondentes mostrados na ferramenta de fluxos de trabalho.
inputFieldDescriptions
: um objeto que mapeia as definições de inputFields para as descrições abaixo dos rótulos correspondentes.
executionRules
: um objeto que mapeia as definições de executionRules às mensagens que serão mostradas para os resultados de execução das ações no histórico do fluxo de trabalho. Há uma seção separada nestes documentos para as regras de execução.
As definições de rótulo devem ser formatadas da seguinte forma:
// {
"labels":{
"en":{
"actionName":"Create Widget",
"actionDescription":"This action will create a new widget in our system. So cool!",
"actionCardContent":"Create widget {{widgetName}}",
"appDisplayName":"My App Display Name",
"inputFieldLabels":{
"widgetName":"Widget Name",
"widgetOwner":"Widget Owner"
},
"outputFieldLabels":{
"outputOne":"First Output"
},
"inputFieldDescriptions":{
"widgetName":"Enter the full widget name. I support <a href=\"https://hubspot.com\">links</a> too."
},
"executionRules":{
"alreadyExists":"The widget with name {{ widgetName }} already exists"
}
}
}
}
Execução
Quando uma execução é realizada, uma solicitação https é enviada para actionUrl
.
callbackId
: um ID exclusivo para a execução específica. Se a execução da ação personalizada for bloqueio, use este ID.
object
: os valores das propriedades solicitadas em objectRequestOptions
.
InputFields
: os valores para as entradas que o usuário preencheu.
A payload de execução será formatada da seguinte forma:
// {
"callbackId": "ap-102670506-56776413549-7-0",
"origin": {
"portalId": 102670506,
"actionDefinitionId": 10646377,
"actionDefinitionVersion": 1
},
"context": {
"source": "WORKFLOWS",
"workflowId": 192814114
},
"object": {
"objectId": 904,
"properties": {
"email": "ajenkenbb@gnu.org"
},
"objectType": "CONTACT"
},
"inputFields": {
"staticInput": "My Static Input",
"objectInput": "995",
"optionsInput": "1"
}
}
A resposta esperada deve estar formatada da seguinte forma:
//
{
"outputFields": {
"myOutput": "Some value",
"hs_execution_state": "SUCCESS"
}
}
Ao analisar a resposta de execução:
outputFields
: os valores dos campos de saída definidos anteriormente. Esses valores podem ser usados em ações posteriores.
hs_execution_state
: um valor especial opcional que pode ser adicionado a outputFields. Não é possível especificar uma nova tentativa; somente os seguintes valores podem ser adicionados:
- SUCCESS
- FAIL_CONTINUE
- BLOCK
- ASYNC
SUCCESS
e FAIL_CONTINUE
indicam que a ação foi concluída e que o fluxo de trabalho deve passar para a próxima ação a ser executada. Se nenhum estado de execução for especificado, os códigos de status serão usados para determinar o resultado de uma ação:
- Códigos de status 2xx: a ação foi concluída com sucesso.
- Códigos de status 4xx: a ação falhou. A exceção aqui são os códigos de status de taxa limitada 429, que são retratados como novas tentativas e o cabeçalho Retry-After é respeitado.
- Códigos de status 5xx: indicam que houve um problema temporário com o serviço e uma nova tentativa será realizada para a ação mais tarde. Um sistema de retirada exponencial é usado para novas tentativas; novas tentativas serão feitas por até 3 dias antes de falhar.
Funções de execução
Use as funções de execução para formatar os dados antes de enviá-los para actionURL
e analisar os dados de actionURL
. Há dois tipos de funções de execução:
PRE_ACTION_EXECUTION
POST_ACTION_EXECUTION
Função PRE_ACTION_EXECUTION
Use as funções PRE_ACTION_EXECUTION
para formatar os dados antes de enviá-los para actionURL
A definição da função será formatada da seguinte forma:
//
{
"functionType": "PRE_ACTION_EXECUTION",
"functionSource": "..."
}
A entrada da função deve ser formatada da seguinte forma:
//
{
"webhookUrl": "https://actionurl.com/",
"callbackId": "ap-102670506-56776413549-7-0",
"origin": {
"portalId": 102670506,
"actionDefinitionId": 10646377,
"actionDefinitionVersion": 1
},
"context": {
"source": "WORKFLOWS",
"workflowId": 192814114
},
"object": {
"objectId": 904,
"properties": {
"email": "ajenkenbb@gnu.org"
},
"objectType": "CONTACT"
},
"inputFields": {
"staticInput": "My Static Input",
"objectInput": "995",
"optionsInput": "1"
}
}
A saída da função deve ser formatada da seguinte forma:
//
{
// The webhook URL for HubSpot to call
"webhookUrl": "https://myapi.com/hubspot",
// Optional. The request body.
"body": "{\"widgetName\": \"My new widget\", \"widgetColor\": \"blue\"}",
// Optional. A map of custom request headers to add.
"httpHeaders": {
"My-Custom-Header": "header value"
},
// Optional. The Content-Type of the request. Default is application/json.
"contentType": "application/json",
// Optional. The Accept type of the request. Default is application/json.
"accept": "application/json",
// Optional. The HTTP method with which to make the request.
// Valid values are GET, POST, PUT, PATCH, and DELETE.
// Default is POST.
"httpMethod": "POST"
}
Função POST_ACTION_EXECUTION
Depois de receber uma resposta de actionURL
, use uma função POST_ACTION_EXECUTION
para formatar os dados para o HubSpot.
A definição da função será formatada da seguinte forma:
//
{
"functionType": "POST_ACTION_EXECUTION",
"functionSource": "..."
}
A entrada da função deve ser formatada da seguinte forma:
//
{
"responseBody": "{\r\n \"returnValue\":\"Hello World!\"\r\n}"
}
A saída da função deve ser formatada da seguinte forma:
//
{
"outputFields": {
"myOutput": "Some value",
"hs_execution_state": "SUCCESS"
}
}
Execução assíncrona
Execute ações de fluxo de trabalho personalizadas de forma assíncrona, bloqueando e, posteriormente, concluindo a ação.
Bloqueio da execução de ações personalizadas
Use ações personalizadas para bloquear a execução do fluxo de trabalho. Em vez de executar a próxima ação no fluxo de trabalho após a ação personalizada depois de receber uma resposta completed (2xx or 4xx status code)
do seu serviço, o fluxo de trabalho deixará de executar (“bloqueará”) essa inscrição até você instruir o fluxo de trabalho para continuar.
Ao bloquear, você pode especificar um valor para o campo hs_default_expiration
, após a qual a sua ação personalizada será considerada expirada. A execução do fluxo de trabalho será retomada e a ação que se segue à ação personalizada será executada, mesmo que a ação não tenha sido concluída.
Para bloquear uma ação personalizada, sua resposta de execução de ação precisa ter o seguinte formato:
//
{
"outputFields": {
"hs_execution_state": "BLOCK",
"hs_expiration_duration": "P1WT1H"
}
}
Campo | Descrição |
---|
hs_execution_state | Para bloquear a execução do fluxo de trabalho, isso deve ser definido como BLOCK para sua ação personalizada. Este é um campo obrigatório. |
hs_expiration_duration | A duração deve ser especificada em Formato de duração ISO 8601. Se não for fornecido, será usada a expiração padrão de 1 semana. Isso é opcional. |
Concluir uma execução bloqueada
Para concluir uma execução de ação personalizada bloqueada, use o ponto de extremidade a seguir: /callbacks/{callbackId}/complete
Formate o corpo da solicitação da seguinte maneira:
//
{
"outputFields": {
"hs_execution_state": "SUCCESS"
}
}
Campo | Descrição |
---|
hs_execution_state | O estado de execução final. Este é um campo obrigatório. Os valores válidos para este campo são SUCCESS para indicar que sua ação personalizada foi concluída com êxito e FAIL_CONTINUE para indicar que há um problema com a execução da ação personalizada. |
Especifique as regras na sua ação que determinam qual mensagem é exibida na página de histórico do fluxo de trabalho quando a ação for executada.
As regras corresponderão aos valores de saída da sua ação. Esses valores de saída devem ser fornecidos no corpo da resposta de actionURL
, no seguinte formato:
//
{
"outputFields": {
"errorCode": "ALREADY_EXISTS",
"widgetName": "Test widget"
}
}
As mensagens reais podem ser especificadas na seção de rótulos da ação personalizada:
//
{
"labels": {
"executionRules": {
"alreadyExists": "The widget with name {{ widgetName }} already exists",
"widgetWrongSize": "Wrong widget size",
"widgetInvalidSize": "Invalid widget size"
}
}
}
}
O executionRules
será testado na ordem fornecida. Se houver várias correspondências, apenas a mensagem da primeira regra que corresponde será mostrada ao usuário.
A regra corresponde quando a saída de execução corresponde a um valor especificado na regra. Por exemplo, considere esse conjunto de executionRules
:
//
[
{
// This matches the key of a label on the action's `labels.LANGUAGE.executionRules` map
"labelName": "alreadyExists",
"conditions": {
"errorCode": "ALREADY_EXISTS"
}
},
{
"labelName": "widgetWrongSize",
"conditions": {
"errorCode": "WIDGET_SIZE",
"sizeError": ["TOO_SMALL", "TOO_BIG"]
}
},
{
"labelName": "widgetInvalidSize",
"conditions": {
"errorCode": "WIDGET_SIZE"
}
}
]
Portanto, as seguintes correspondências ocorrerão:
{"errorCode": "ALREADY_EXISTS", "widgetName": "Test widget"}
: Isso corresponderia à primeira regra, pois errorCode
é igual a ALREADY_EXISTS
. Nesse caso, embora haja uma saída de widgetName
, ela não é usada na definição de regra, de forma que qualquer valor é permitido.
{"errorCode": "WIDGET_SIZE", "sizeError": "TOO_SMALL"}
: Isso corresponderia à segunda regra, pois TOO_SMALL
é um dos sizeError
correspondentes e errorCode
é WIDGET_SIZE
.
{"errorCode": "WIDGET_SIZE", "sizeError": "NOT_A_NUMBER"}
: Isso corresponderia à terceira regra, pois, embora errorCode
seja WIDGET_SIZE
, o sizeError
não corresponde a nenhum dos valores especificados pela segunda regra (TOO_SMALL
ou TOO_BIG
).
Esse mecanismo de correspondência permite especificar erros de fallback, para que você possa ter erros específicos para casos de erro importantes, mas retornar a mensagens de erro mais genéricas para erros menos comuns. Este é um exemplo de como a mensagem personalizada seria exibida:
Testar e publicar sua ação personalizada
Depois de criar sua nova ação personalizada, você pode testá-la e publicá-la.
Testar ações personalizadas antes de publicar
Antes de publicar sua ação personalizada, você pode testar a execução da ação e a busca de opções apontando a URL para webhook.site. Dessa forma, você pode inspecionar a payload e retornar uma resposta específica.
Você também pode testar a ação no portal do desenvolvedor criando um fluxo de trabalho na ferramenta de fluxos de trabalho. Em seguida, adicione sua nova ação.
Ao concluir o teste, é recomendável arquivar as ações de teste. Saiba mais sobre arquivamento de ações na documentação de referência.
Publicação de ações personalizadas
Por padrão, as ações personalizadas são criadas em um estado não publicado. Ações personalizadas não publicadas ficam visíveis somente no portal do desenvolvedor associado ao aplicativo HubSpot correspondente. Para tornar uma ação personalizada visível para os usuários, atualize o sinalizador published
na definição da ação para true
. Se uma ação não for publicada, os portais que já adicionaram a ação ao fluxo de trabalho ainda poderão editá-la e executá-la. Porém, não poderão adicionar a ação novamente.
Exemplos de ação personalizada
Os snippets de código abaixo fornecem exemplos de vários casos de uso comuns para ações personalizadas, como definir um widget ou invocar uma função sem servidor.
Exemplo 1
Este exemplo apresenta os seguintes campos de entrada, criados para fluxos de trabalho de contato e negócio:
widgetName
: um campo de entrada estática
widgetColor
: um campo suspenso com opções
widgetOwner
: um campo que representa um proprietário do HubSpot.
widgetQuantity
: um campo derivado de uma propriedade (selecionado pelo usuário que cria o fluxo de trabalho) no objeto inscrito.
//
{
"actionUrl": "https://example.com/hubspot",
"inputFields": [
{
"typeDefinition": {
"name": "widgetName",
"type": "string",
"fieldType": "text"
},
"supportedValueTypes": ["STATIC_VALUE"],
"isRequired": true
},
{
"typeDefinition": {
"name": "widgetColor",
"type": "enumeration",
"fieldType": "select",
"options": [
{ "value": "red", "label": "Red" },
{ "value": "blue", "label": "Blue" },
{ "value": "green", "label": "Green" }
]
},
"supportedValueTypes": ["STATIC_VALUE"]
},
{
"typeDefinition": {
"name": "widgetOwner",
"type": "enumeration",
"referencedObjectType": "OWNER"
},
"supportedValueTypes": ["STATIC_VALUE"]
},
{
"typeDefinition": {
"name": "widgetQuantity",
"type": "number"
},
"supportedValueTypes": ["OBJECT_PROPERTY"]
}
],
"labels": {
"en": {
"actionName": "Create Widget - Example 1",
"actionDescription": "This action will create a new widget in our system. So cool!",
"actionCardContent": "Create widget {{widgetName}}",
"inputFieldLabels": {
"widgetName": "Widget Name",
"widgetColor": "Widget Color",
"widgetOwner": "Widget Owner",
"widgetQuantity": "Widget Quantity"
},
"inputFieldDescriptions": {
"widgetName": "Enter the full widget name. I support <a href=\"https://hubspot.com\">links</a> too.",
"widgetColor": "This is the color that will be used to paint the widget."
}
}
},
"objectTypes": ["CONTACT", "DEAL"]
}
Exemplo 2
A ação personalizada a seguir usa uma função sem servidor para transformar a carga útil que é enviada ao actionUrl configurado. Como o campo objectTypes
não está especificado na definição de ação personalizada, essa ação estará disponível em todos os tipos de fluxos de trabalho.
//
{
"actionUrl": "https://example.com",
"inputFields": [
{
"typeDefinition": {
"name": "widgetName",
"type": "string",
"fieldType": "text"
},
"supportedValueTypes": ["STATIC_VALUE"],
"isRequired": true
}
],
"labels": {
"en": {
"actionName": "Create Widget - Example 2",
"actionCardContent": "Create widget {{widgetName}}",
"inputFieldLabels": {
"widgetName": "Widget Name"
}
}
},
"functions": [
{
"functionType": "PRE_ACTION_EXECUTION",
"functionSource": "exports.main = function(event, callback) { return callback(transformRequest(event)); }\nfunction transformRequest(request) { return { webhookUrl: request.webhookUrl, body: JSON.stringify(request.fields), contentType: 'application/x-www-form-urlencoded', accept: 'application/json', httpMethod: 'POST' }; }"
}
]
}
Exemplo 3
A ação personalizada a seguir tem dependências de campo e opções que são buscadas de uma API externa. Como o tamanho do widget depende da cor do widget, o usuário não poderá inserir um valor para o tamanho do widget até que uma cor de widget seja escolhida.
O custo do widget também depende da cor do widget, porém, está condicionado ao valor que o usuário seleciona para a cor do widget. O usuário não poderá inserir um valor para o custo do widget, a menos que Vermelho esteja selecionado como a cor do widget.
//
{
"actionUrl": "https://example.com/hubspot",
"inputFields": [
{
"typeDefinition": {
"name": "widgetName",
"type": "string",
"fieldType": "text"
},
"supportedValueTypes": ["STATIC_VALUE"],
"isRequired": true
},
{
"typeDefinition": {
"name": "widgetColor",
"type": "enumeration",
"fieldType": "select",
"options": [
{ "value": "red", "description": "red", "label": "Red" },
{ "value": "blue", "description": "blue", "label": "Blue" },
{ "value": "green", "description": "green", "label": "Green" }
]
},
"supportedValueTypes": ["STATIC_VALUE"]
},
{
"typeDefinition": {
"name": "widgetSize",
"type": "enumeration",
"fieldType": "select",
"optionsUrl": "https://api.example.com/v1/widget-sizes"
},
"supportedValueTypes": ["STATIC_VALUE"]
},
{
"typeDefinition": {
"name": "widgetCost",
"type": "number",
"fieldType": "number"
},
"supportedValueTypes": ["OBJECT_PROPERTY"]
}
],
"inputFieldDependencies": [
{
"dependencyType": "SINGLE_FIELD",
"controllingFieldName": "widgetColor",
"dependentFieldNames": ["widgetSize"]
},
{
"dependencyType": "CONDITIONAL_SINGLE_FIELD",
"controllingFieldName": "widgetColor",
"controllingFieldValue": "red",
"dependentFieldNames": ["widgetCost"]
}
],
"labels": {
"en": {
"actionName": "Create Widget - Example 3",
"actionCardContent": "Create widget {{widgetName}}",
"inputFieldLabels": {
"widgetName": "Widget Name",
"widgetColor": "Widget Color",
"widgetSize": "Widget Size",
"widgetCost": "Widget Cost"
}
}
},
"objectTypes": ["CONTACT", "DEAL"],
"functions": [
{
"functionType": "PRE_FETCH_OPTIONS",
"id": "widgetSize",
"functionSource": "exports.main = function(event, callback) { return callback(transformRequest(event)); }\nfunction transformRequest(request) { return { webhookUrl: request.webhookUrl + '?color=' + request.fields.widgetColor.value, body: JSON.stringify(request.fields), httpMethod: 'GET' }; }"
}
]
}