Zum Hauptinhalt springen
Um eine benutzerdefinierte Workflow-Aktion für eine App auf der neuen Entwicklerplattform zu definieren, schließen Sie ein workflow-actions-Verzeichnis zusammen mit einer *-hsmeta.json-Konfigurationsdatei in das Projekt ein.

Struktur des Projektverzeichnisses

├──src
   ├── app/
   └── app-hsmeta.json
   └── ...
   └── workflow-actions/
     └── custom-action-hsmeta.json
└──

Definition einer benutzerdefinierten Workflow-Aktion

Nachfolgend finden Sie die verfügbaren Konfigurationsoptionen für die *-hsmeta.json-Datei.
{
  "uid": "simple_notification_action",
  "type": "workflow-action",
  "config": {
    "actionUrl": "https://example.com",
    "isPublished": false,
    "supportedClients": [
      {
        "client": "WORKFLOWS"
      }
    ],
    "inputFields": [
      {
        "typeDefinition": {
          "name": "message",
          "type": "string",
          "fieldType": "textarea"
        },
        "supportedValueTypes": ["STATIC_VALUE"],
        "isRequired": true
      },
      {
        "typeDefinition": {
          "name": "priority",
          "type": "enumeration",
          "fieldType": "select",
          "options": [
            {
              "value": "high",
              "label": "High Priority"
            },
            {
              "value": "normal",
              "label": "Normal Priority"
            },
            {
              "value": "low",
              "label": "Low Priority"
            }
          ]
        },
        "supportedValueTypes": ["STATIC_VALUE"],
        "isRequired": true
      }
    ],
    "labels": {
      "en": {
        "actionName": "My Custom Action (via Projects V2)",
        "actionDescription": "Sends a notification with custom message and priority level",
        "actionCardContent": "Send {{priority}} priority notification",
        "inputFieldLabels": {
          "message": "Notification Message",
          "priority": "Priority Level"
        },
        "inputFieldDescriptions": {
          "message": "Enter the message to be sent in the notification",
          "priority": "Select the priority level for this notification"
        }
      }
    },
    "objectTypes": ["CONTACT"]
  }
}

Mit * markierte Felder sind Pflichtfelder.

FeldTypBeschreibung
uid*ZeichenfolgeEine interne eindeutige ID für die Workflow-Aktion.
type*ZeichenfolgeDer Typ der Komponente, die in diesem Fall workflow-action sein sollte.
actionUrl*ZeichenfolgeDie Webhook-URL der API zur Übermittlung einer Anfrage zur Ausführung eines Workflows.
isPublishedBoolescherWertBestimmt, ob die Definition in Accounts sichtbar ist, die Ihre App installiert haben. Standardmäßig ist dies auf false festgelegt.
supportedClients*Array von ObjektenGibt die Clients an, die von der benutzerdefinierten Workflow-Aktion unterstützt werden. Jedes Objekt im Array sollte einen Client-Schlüssel mit einem Zeichenfolgenwert haben, der den Client-Typ angibt (z. B. WORKFLOWS).
inputFieldsArrayDie Werte für die Eingaben, die der Benutzer ausgefüllt hat.
typeDefinition.nameZeichenfolgeDer Name oder Schlüssel des Eingabefelds.
typeDefinition.typeZeichenfolgeDer Werttyp, der für das Eingabefeld gelten soll.
typeDefinition.fieldTypeZeichenfolgeDer Feldtyp, der den Benutzern angezeigt wird, die den Workflow erstellen.
typeDefinition.optionsArrayDieses Feld enthält für Aufzählungstypen eine Liste von Optionen. Jede Option muss über einen value verfügen, der auf den Eingaben des Benutzers basiert, und ein label, das die Option im Workflows-Tool erkennen lässt.
inputFieldDependenciesArrayEine Liste von Regeln, die die Beziehungen zwischen zwei oder mehr Eingaben basierend auf ihrem dependencyType definieren. Erfahren Sie mehr dazu in diesem Beispiel.
labels.<locale>*ZeichenfolgeGebietsschemaschlüssel, der der Gebietsschemadefinition zugeordnet ist. Er muss mindestens ein englisches Label (en) umfassen und seine Definition muss klar bestimmt sein.
labels.<locale>.inputFieldDescriptionsObjektEin Objekt, das die Details für die Eingaben für Ihre Aktion definiert. Im obigen Beispiel enthält dieses Objekt message- und priority-Felder.
labels.<locale>.inputFieldOptionLabelsObjektEin Objekt, das erforderlich ist, wenn Ihr(e) Eingabefeld(er) über Optionen verfügt/en. Bietet eine Zuordnung von Eingabefeldoptionslabeln, die durch den Wert oder das Label der Option geschlüsselt sind.
labels.<locale>.outputFieldLabelsObjektEin Objekt, das die Definitionen von outputFields den entsprechenden Label zuordnet, die im Workflows-Tool angezeigt werden.
labels.<locale>.actionName*ZeichenfolgeDer Name der Aktion, wie im Bereich Aktion auswählen im Workflows-Editor angezeigt.
labels.<locale>.appDisplayName*ZeichenfolgeDer Name des Abschnitts im Bereich Aktion auswählen, in dem alle Aktionen für die App angezeigt werden. Wenn appDisplayName für mehrere Aktionen definiert ist, wird die erstgefundene verwendet.
labels.<locale>.actionCardContentZeichenfolgeEine zusammengefasste Beschreibung, die auf der Karte der Aktion angezeigt wird.
labels.<locale>.executionRulesObjektEin Objekt, das die Definitionen von Ihren executionRules Nachrichten zuordnet, die im Rahmen der Ausführung im Workflow-Verlauf angezeigt werden.
objectTypesArrayDie verfügbaren CRM-Objekttypen, mit denen diese Aktion verwendet werden kann. Ist hier kein Wert vorhanden, ist die Aktion für alle Objekttypen verfügbar.
outputFieldsArrayDie Werte, die die Aktion ausgibt und die bei späteren Aktionen im Workflow verwendet werden können. Eine benutzerdefinierte Aktion kann einen Output von 0, 1 oder mehrere Outputs haben.
executionRulesObjektEine Liste der Definitionen, die Sie angeben können, damit dem Benutzer, der den Workflow erstellt, Fehler von Ihrem Dienst angezeigt werden.
Verwendete Funktion:
//
exports.main = (event, callback) => {
  callback({
    "data": {
      "myObjectId": event["object"]["objectId"],
      "myField": event["inputFields"]["widgetName"]
    }
  });
}
Erwartete Ausgabe:
//
{
  "data": {
    "myObjectId": 614,
    "myField": "My Widget Name"
  }
}

Eingabefelder

Die Eingabefelddefinitionen entsprechen dem folgenden Format:
  • name: der interne Name des Eingabefelds, getrennt von seinem Label. Das in der Benutzeroberfläche angezeigte Label muss über den labels-Abschnitt der benutzerdefinierten Aktionsdefinition definiert werden.
  • type: der Typ des Werts, der für die Eingabe erforderlich ist.
  • fieldType: gibt an, wie das Eingabefeld in der Benutzeroberfläche gerendert werden soll. Eingabefelder imitieren CRM-Eigenschaften. Erfahren Sie in diesem Artikel mehr über gültige type- und fieldType-Kombinationen
  • supportedValueTypes hat zwei gültige Werte:
    • OBJECT_PROPERTY: Der Benutzer kann eine Eigenschaft vom aufgenommenen Objekt oder eine Ausgabe aus einer vorherigen Aktion auswählen, die als Wert für das Feld verwendet werden soll.
    • STATIC_VALUE: Dies sollte in allen anderen Fällen verwendet werden. Es bedeutet, dass der Benutzer selbst einen Wert eingeben muss.
  • isRequired: Hiermit wird festgelegt, ob der Benutzer einen Wert für diese Eingabe angeben muss oder nicht
Eingabefelddefinitionen sollten wie folgt formatiert sein:
//
{
  "typeDefinition": {
    "name": "staticInput",
    "type": "string",
    "fieldType": "text"
  },
  "supportedValueTypes": ["STATIC_VALUE"],
  "isRequired": true
}
Sie können auch Hartcodierungsoptionen für den Benutzer auswählen:
//
{
  "typeDefinition": {
    "name": "widgetColor",
    "type": "enumeration",
    "fieldType": "select",
    "options": [
      {
        "value": "red",
        "label": "Red"
      },
      {
        "value": "blue",
        "label": "Blue"
      },
      {
        "value": "green",
        "label": "Green"
      }
    ]
  },
  "supportedValueTypes": ["STATIC_VALUE"]
}

Verwenden externer Daten

Anstelle von Optionen für Hartcodierungsfelder können Sie auch externe Daten mit externen Datenfeldern abrufen. Sie können beispielsweise eine Liste mit Meetingprojekten oder eine Liste mit Produkten als Eingaben abrufen. Das Eingabefeld sollte wie folgt formatiert sein:
//
{
  "typeDefinition": {
    "name": "optionsInput",
    "type": "enumeration",
    "fieldType": "select",
    "optionsUrl": "https://your-url-here.com"
  },
  "supportedValueTypes": ["STATIC_VALUE"]
}
Die an das optionsURL gesendete Payload ist wie folgt formatiert:
//
{
  "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="
  }
}
FeldBeschreibung
portalIdDie ID des HubSpot-Accounts.
actionDefinitionIdDie Definition-ID Ihrer benutzerdefinierten Aktion.
actionDefinitionVersionDie Definitionsversion Ihrer benutzerdefinierten Aktion.
objectTypeIdDer Workflow-Objekttyp, in dem die Aktion verwendet wird.
inputFieldNameDas Eingabefeld, für das Sie Optionen abrufen.
inputFieldsDie Werte für die Felder, die bereits vom Benutzer des Workflows ausgefüllt wurden.
qDie vom Benutzer angegebene Suchanfrage. Dies sollte verwendet werden, um die zurückgegebenen Optionen zu filtern. Dies wird nur berücksichtigt, wenn der vorherige Optionsabruf zurückgegeben searchable: true wurde und der Benutzer eine Suchanfrage eingegeben hat.
afterDer Paginierungscursor. Dies ist derselbe Paginierungscursor, der vom vorherigen Optionsabruf zurückgegeben wurde. Es kann verwendet werden, um nachzuverfolgen, welche Optionen bereits abgerufen wurden.
Die erwartete Antwort sollte wie folgt formatiert sein:
//
{
  "options": [
    {
      "label": "Big Widget",
      "description": "Big Widget",
      "value": "10"
    },
    {
      "label": "Small Widget",
      "description": "Small Widget",
      "value": "1"
    }
  ],

  "after": "1234=",
  "searchable": true
}
FeldBeschreibung
qDer Paginierungscursor. Wenn dies angegeben ist, rendert die Workflows-App am unteren Rand der Optionsliste eine Schaltfläche zum Laden weiterer Ergebnisse, wenn ein Benutzer eine Option auswählt, und sobald die nächste Seite geladen wird, wird dieser Wert in der Anfrage-Payload unter fetchOptions.afterberücksichtigt. Dieses Feld ist optional.
afterDer Standardwert ist false. Wenn dies true ist, rendert die Workflows-App ein Suchfeld, damit ein Benutzer die verfügbaren Optionen durch eine Suchanfrage filtern kann. Wenn eine Suchanfrage eingegeben wird, werden Optionen mit diesem Suchbegriff in der Anfrage-Payload unter fetchOptions.q erneut abgerufen. Dieses Feld ist optional.

Externe Daten ändern

Um externe Daten zu verwalten, können Sie zwei Hooks hinzufügen, um den Lebenszyklus eines Abrufs von Feldoptionen anzupassen:
  • PRE_FETCH_OPTIONS: eine Funktion, die die von HubSpot gesendete Payload konfiguriert.
  • POST_FETCH_OPTIONS: eine Funktion, die die Antwort Ihres Dienstes in ein Format umwandelt, das von HubSpot verstanden wird.

PRE_FETCH_OPTIONS

Wenn diese Funktion berücksichtigt wird, gilt sie für jedes Eingabefeld. Sie können es auf ein bestimmtes Eingabefeld anwenden, indem Sie eine id in der Funktionsdefinition angeben.
//
{
  "functionType": "PRE_FETCH_OPTIONS",
  "functionSource": "...",
  "id": "inputField"
}
Die von HubSpot gesendete Payload ist wie folgt formatiert:
//
{
  "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="
    }
  }
}
FeldBeschreibung
portalIdDie ID des HubSpot-Accounts.
actionDefinitionIdDie Definition-ID Ihrer benutzerdefinierten Aktion.
actionDefinitionVersionDie Definitionsversion Ihrer benutzerdefinierten Aktion.
objectTypeIdDer Workflow-Objekttyp, in dem die Aktion verwendet wird.
inputFieldNameDas Eingabefeld, für das Sie Optionen abrufen.
inputFieldsDie Werte für die Felder, die bereits vom Benutzer des Workflows ausgefüllt wurden.
qDie vom Benutzer angegebene Suchanfrage. Dies sollte verwendet werden, um die zurückgegebenen Optionen zu filtern. Dies wird nur berücksichtigt, wenn der vorherige Optionsabruf zurückgegeben searchable: true wurde und der Benutzer eine Suchanfrage eingegeben hat.
afterDer Paginierungscursor. Dies ist derselbe Paginierungscursor, der vom vorherigen Optionsabruf zurückgegeben wurde. Es kann verwendet werden, um nachzuverfolgen, welche Optionen bereits abgerufen wurden.
Die Antwort sollte dann wie folgt formatiert sein:
//
{
  "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"
}
FeldBeschreibung
webhookUrlDie von HubSpot aufzurufende Webhook-URL.
bodyDer Anforderungstext. Dies ist optional.
httpHeadersEine Zuordnung der hinzuzufügenden benutzerdefinierten Anfrage-Header. Dies ist optional.
contentTypeDer Content-Type der Anfrage Der Standardwert ist application/json. Dies ist optional.
acceptDie Accept-Art der Anfrage Der Standardwert ist application/json. Dies ist optional.
httpMethodDie HTTP-Methode, mit der die Anfrage durchgeführt werden soll. Der Standardwert ist POST, aber andere gültige Werte sind GET, POST, PUT, PATCH und DELETE. Dies ist optional.

POST_FETCH_OPTIONS

Um die Antwort in ein erwartetes Format zu analysieren, verwenden Sie gemäß den externen Datenfeldern eine POST_FETCH_OPTIONS-Funktion. Die Definition einer POST_FETCH_OPTIONS-Funktion entspricht der einer PRE_FETCH_OPTIONS-Funktion. Wenn externe Datenabrufoptionen definiert sind, wird ein Dropdown-Menü in den Eingabeoptionen für die Aktion gerendert.
//
{
  "functionType": "POST_FETCH_OPTIONS",
  "functionSource": "...",
  "id": "inputField"
}
Die Funktionseingabe ist folgendermaßen formatiert:
//
{
  // The requested field key
  "fieldKey": "widgetSize",

  // The webhook response body from your service
  "responseBody": "{\"widgetSizes\": [10, 1]}"
}
Die Funktionsausgabe ist folgendermaßen formatiert:
//
{
  "options": [
    {
      "label": "Big Widget",
      "description": "Big Widget",
      "value": "10"
    },
    {
      "label": "Small Widget",
      "description": "Small Widget",
      "value": "1"
    }
  ]
}

Ausgabefelder

Verwenden Sie Ausgabefelder, um Werte von Ihrer benutzerdefinierten Aktion für andere Aktionen auszugeben. Die Definition für Ausgabefelder ähnelt der Definition für Eingabefelder:
  • name: Wie dieses Feld in anderen Teilen der benutzerdefinierten Aktion referenziert wird. Das in der Benutzeroberfläche angezeigte Label muss über den `labels`-Abschnitt der benutzerdefinierten Aktion definiert werden.
  • type: Der Typ des Werts, der für die Eingabe erforderlich ist.
  • fieldType: gbt an, wie das Eingabefeld in der Benutzeroberfläche gerendert werden soll. Eingabefelder imitieren CRM-Eigenschaften. Erfahren Sie in diesem Artikel mehr über gültige type- und fieldType-Kombinationen
Das Ausgabefeld sollte wie folgt formatiert sein:
//
{
  "outputFields": [
    {
      "typeDefinition": {
        "name": "myOutput",
        "type": "string",
        "fieldType": "text"
      }
    }
  ]
}
Bei Verwendung eines Ausgabefelds werden Werte von der Antwort von der actionURL analysiert. Beispielsweise können Sie Ausgabefelder in eine vorhandene Eigenschaft in HubSpot kopieren.

Labels

Verwenden Sie Labels, um Ihren Ausgaben oder Eingaben im Workflow-Editor Text hinzuzufügen. Es kann einige Minuten dauern, bis Labels im Sprachdienst von HubSpot angezeigt werden. Portale, die auf verschiedene Regionen oder Sprachen festgelegt sind, zeigen die Bezeichnung in der entsprechenden Sprache an, falls verfügbar.
  • labels: Text, der beschreibt, was die Felder der Aktion darstellen und was die Aktion macht. Englische Label sind erforderlich, aber Label können auch in einer der folgenden unterstützten Sprachen angegeben werden: Deutsch (de), Französisch (fr), Japanisch (ja), Spanisch (es), Brasilianisches Portugiesisch (pt-br) und Niederländisch (nl).
  • actionName: der im Bereich „Aktion auswählen“ im Workflow-Editor angezeigte Name der Aktion.
  • actionDescription: eine detaillierte Beschreibung für die Aktion, die beim Konfigurieren der benutzerdefinierten Aktion angezeigt wird.
  • actionCardContent: eine zusammengefasste Beschreibung, die auf der Karte der Aktion angezeigt wird.
  • appDisplayName: Der Name des Abschnitts im Bereich „Aktion auswählen“, in dem alle Aktionen für die App angezeigt werden Wenn appDisplayName für mehrere Aktionen definiert ist, wird die erste gefundene Aktion verwendet.
  • inputFieldLabels: ein Objekt, das die Definitionen von inputFields den entsprechenden Label zuordnet, die der Benutzer beim Konfigurieren der Aktion sieht.
  • outputFieldLabels: ein Objekt, das die Definitionen von den outputFields entsprechenden Label zuordnet, die im Workflows-Tool angezeigt werden.
  • inputFieldDescriptions: ein Objekt, das die Definitionen von inputFields den Beschreibungen unterhalb der entsprechenden Label zuordnet.
  • executionRules: ein Objekt, das die Definitionen von Ihren executionRules den Nachrichten zuordnet, die für die Ergebnisse der Aktionsausführung im Workflow-Verlauf angezeigt werden. In diesen Dokumenten gibt es einen separaten Abschnitt für Ausführungsregeln.
Label-Definitionen sollten wie folgt formatiert sein:
// {
  "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"
      }
    }
  }
}

Ausführung

Wenn eine Ausführung ausgeführt wird, wird eine https-Anfrage an die actionUrl gesendet.
  • callbackId: eine eindeutige ID für die spezifische Ausführung. Wenn die Ausführung der benutzerdefinierten Aktion blockiert wird, verwenden Sie diese ID.
  • object: die Werte der in objectRequestOptions angefragten Eigenschaften.
  • InputFields: die Werte für die Eingaben, die der Benutzer ausgefüllt hat.
Die Payload der Ausführung ist folgendermaßen formatiert:
// {
  "callbackId": "ap-102670506-56776413549-7-0",
  "origin": {
    "portalId": 102670506,
    "actionDefinitionId": 10646377,
    "actionDefinitionVersion": 1
  },
  "context": {
    "source": "WORKFLOWS",
    "workflowId": 192814114
  },
  "object": {
    "objectId": 904,
    "properties": {
      "email": "[email protected]"
    },
    "objectType": "CONTACT"
  },
  "inputFields": {
    "staticInput": "My Static Input",
    "objectInput": "995",
    "optionsInput": "1"
  }
}
Die erwartete Antwort sollte wie folgt formatiert sein:
//
{
  "outputFields": {
    "myOutput": "Some value",
    "hs_execution_state": "SUCCESS"
  }
}
Für die Ausführungsantwort gilt:
  • outputFields: die Werte der zuvor definierten Ausgabefelder. Diese Werte können in späteren Aktionen verwendet werden.
  • hs_execution_state: ein optionaler spezieller Wert, der zu outputFields hinzugefügt werden kann. Es ist nicht möglich, einen neuen Versuch anzugeben, es können nur die folgenden Werte hinzugefügt werden:
    • SUCCESS
    • FAIL_CONTINUE
    • BLOCK
    • ASYNC
SUCCESS und FAIL_CONTINUE zeigen an, dass die Aktion abgeschlossen ist und der Workflow mit der nächsten auszuführenden Aktion fortfahren sollte. Wenn kein Ausführungszustand angegeben ist, werden Statuscodes verwendet, um das Ergebnis einer Aktion zu bestimmen:
  • 2xx-Statuscodes: Die Aktion wurde erfolgreich abgeschlossen.
  • 4xx-Statuscodes: Die Aktion ist fehlgeschlagen. Die Ausnahme sind 429-Statuscodes vom Typ „Rate beschränkt“. Diese werden als erneute Versuche behandelt, und der „Erneut versuchen nach“-Header wird befolgt.
  • 5xx-Statuscodes: Es ist ein vorübergehendes Problem mit Ihrem Dienst aufgetreten und die Aktion wird später erneut versucht. Ein exponentielles Backoff-System wird für erneute Versuche verwendet. Erneute Versuche werden bis zu drei Tage lang fortgesetzt, bevor sie fehlschlagen.

Ausführungsfunktionen

Verwenden Sie Ausführungsfunktionen, um Daten vor dem Senden an die actionURL zu formatieren und Daten von der actionURL zu analysieren. Es gibt zwei Typen von Ausführungsfunktionen:
  • PRE_ACTION_EXECUTION
  • POST_ACTION_EXECUTION

PRE_ACTION_EXECUTION-Funktion

Verwenden Sie PRE_ACTION_EXECUTION-Funktionen zum Formatieren von Daten, bevor Sie sie an die actionURL senden. Die Funktionsdefinition ist folgendermaßen formatiert:
//
{
  "functionType": "PRE_ACTION_EXECUTION",
  "functionSource": "..."
}
Die Funktionseingabe sollte wie folgt formatiert sein:
//
{
  "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": "[email protected]"
    },
    "objectType": "CONTACT"
  },
  "inputFields": {
    "staticInput": "My Static Input",
    "objectInput": "995",
    "optionsInput": "1"
  }
}
Die Funktionsausgabe sollte wie folgt formatiert sein:
//
{
  // 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"
}

POST_ACTION_EXECUTION-Funktion

Nachdem Sie eine Antwort von der actionURL erhalten haben, verwenden Sie eine POST_ACTION_EXECUTION-Funktion, um Daten für HubSpot zu formatieren. Die Funktionsdefinition ist folgendermaßen formatiert:
//
{
  "functionType": "POST_ACTION_EXECUTION",
  "functionSource": "..."
}
Die Funktionseingabe sollte wie folgt formatiert sein:
//
{
  "responseBody": "{\r\n  \"returnValue\":\"Hello World!\"\r\n}"
}
Die Funktionsausgabe sollte wie folgt formatiert sein:
//
{
  "outputFields": {
    "myOutput": "Some value",
    "hs_execution_state": "SUCCESS"
  }
}

Asynchrone Ausführung

Führen Sie benutzerdefinierte Workflow-Aktionen asynchron aus, indem Sie die Aktion blockieren und später abschließen.

Blockieren der Ausführung einer Aktion

Verwenden Sie benutzerdefinierte Aktionen, um die Ausführung von Workflows zu blockieren. Anstatt nach dem Empfang einer Antwort vom Typ completed (2xx or 4xx status code) von Ihrem Dienst die nächste Aktion im Workflow nach Ihrer benutzerdefinierten Aktion auszuführen, hört der Workflow so lange mit dem Ausführen („blockieren“) dieser Aufnahme auf, bis Sie den Workflow zum Fortfahren anweisen. Wenn blockiert werden soll, können Sie einen Wert für das hs_default_expiration-Feld festlegen, nach dem Ihre benutzerdefinierte Aktion als abgelaufen gilt. Die Ausführung des Workflows wird dann wieder aufgenommen, und die Aktion im Anschluss an Ihre benutzerdefinierte Aktion wird ausgeführt, auch wenn die Aktion nicht abgeschlossen ist. Um eine benutzerdefinierte Aktion zu blockieren, muss Ihre Aktionsausführungsantwort folgendes Format haben:
//
{
  "outputFields": {
    "hs_execution_state": "BLOCK",
    "hs_expiration_duration": "P1WT1H"
  }
}
FeldBeschreibung
hs_execution_stateUm die Ausführung von Workflows zu blockieren, muss dies für Ihre benutzerdefinierte Aktion auf BLOCK festgelegt sein. Dies ist ein Pflichtfeld.
hs_expiration_durationDie Dauer muss im ISO 8601-Format „Dauer“ angegeben werden. Wenn nicht angegeben, wird eine Standardablauffrist von 1 Woche verwendet. Dies ist optional.

Ausführung einer blockierten Aktion abschließen

Um die blockierte Ausführung einer benutzerdefinierten Aktion abzuschließen, verwenden Sie den folgenden Endpunkt: /callbacks/{callbackId}/complete Formatieren Sie den Anfragetext wie folgt:
//
{
  "outputFields": {
    "hs_execution_state": "SUCCESS"
  }
}
FeldBeschreibung
hs_execution_stateDer endgültige Ausführungszustand. Dies ist ein Pflichtfeld Die gültigen Werte für dieses Feld sind SUCCESS, um anzuzeigen, dass Ihre benutzerdefinierte Aktion erfolgreich abgeschlossen wurde, und FAIL_CONTINUE, um anzuzeigen, dass es ein Problem mit der Ausführung Ihrer benutzerdefinierten Aktion gibt.

Benutzerdefinierte Ausführungsnachrichten mit Regeln hinzufügen

Geben Sie Regeln für Ihre Aktion an, um festzulegen, welche Nachricht auf der Verlaufsseite des Workflows angezeigt wird, wenn die Aktion ausgeführt wird. Die Regeln werden mit den Ausgangswerten von Ihrer Aktion abgeglichen. Diese Ausgabewerte sollten im Antworttext der actionURL im folgenden Format angegeben werden:
//
{
  "outputFields": {
    "errorCode": "ALREADY_EXISTS",
    "widgetName": "Test widget"
  }
}
Die tatsächlichen Nachrichten können im labels-Abschnitt der benutzerdefinierten Aktion angegeben werden:
//
{
  "labels": {
      "executionRules": {
        "alreadyExists": "The widget with name {{ widgetName }} already exists",
        "widgetWrongSize": "Wrong widget size",
        "widgetInvalidSize": "Invalid widget size"
      }
    }
  }
}
Die executionRules werden in der angegebenen Reihenfolge getestet. Wenn mehrere Treffer vorhanden sind, wird dem Benutzer nur die Nachricht von der ersten Regel, die übereinstimmt, angezeigt. Die Regel stimmt überein, wenn die Ausführungsausgabe einem bestimmten Wert in der Regel entspricht. Nehmen Sie beispielsweise diesen Satz an 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"
    }
  }
]
Die folgenden Treffer würden in diesem Fall auftreten:
  • {"errorCode": "ALREADY_EXISTS", "widgetName": "Test widget"}: Dies würde mit der ersten Regel übereinstimmen, da errorCode gleich ALREADY_EXISTS ist. In diesem Fall wird, auch wenn eine widgetName-Ausgabe vorliegt, diese nicht in der Regel verwendet, sodass jeder Wert zulässig ist.
  • {"errorCode": "WIDGET_SIZE", "sizeError": "TOO_SMALL"}: Dies würde mit der zweiten Regel übereinstimmen, da TOO_SMALL einer der übereinstimmenden Fehler vom Typ sizeError ist und errorCode WIDGET_SIZE ist.
  • {"errorCode": "WIDGET_SIZE", "sizeError": "NOT_A_NUMBER"}: Dies würde mit der dritten Regel übereinstimmen, da der sizeError, auch wenn der errorCode WIDGET_SIZE ist, keinem der von der zweiten Regel angegebenen Werte entspricht (TOO_SMALL oder TOO_BIG).
Mit diesem Übereinstimmungsmechanismus können Sie Fallback-Fehler festlegen, damit Sie spezifische Fehler für wichtige Fehlerereignisse haben können, aber auf etwas generischere Fehlermeldungen für weniger häufige Fehler zurückgreifen können. Hier ist ein Beispiel dafür, wie die benutzerdefinierte Nachricht angezeigt wird:

Ihre benutzerdefinierte Aktion testen und veröffentlichen

Nachdem Sie Ihre neue benutzerdefinierte Aktion erstellt haben, können Sie sie testen und veröffentlichen.

Testen von benutzerdefinierten Aktionen vor dem Veröffentlichen

Vor der Veröffentlichung Ihrer benutzerdefinierten Aktion können Sie die Ausführung von Aktionen und das Abrufen von Optionen testen, indem Sie die URL auf webhook.site verweisen. Dadurch können Sie die Payload überprüfen und eine bestimmte Antwort zurückgeben. Sie können die Aktion auch in Ihrem Entwicklerportal testen, indem Sie einen Workflow im Workflow-Tool erstellen. Fügen Sie dann Ihre neue Aktion hinzu. Wenn Sie Ihre Tests abgeschlossen haben, empfiehlt es sich, die Testaktionen zu archivieren. In der Referenzdokumentation erfahren Sie mehr über Archivierungsaktionen.

Veröffentlichen von benutzerdefinierten Aktionen

Standardmäßig werden benutzerdefinierte Aktionen in einem unveröffentlichten Zustand erstellt. Unveröffentlichte benutzerdefinierte Aktionen sind nur im Entwicklerportal sichtbar, das der entsprechenden HubSpot-Anwendung zugeordnet ist. Um eine benutzerdefinierte Aktion für Benutzer sichtbar zu machen, aktualisieren Sie das published-Flag in Ihrer Aktionsdefinition auf true. Wenn eine Aktion unveröffentlicht ist, können Portale, die die Aktion bereits zu ihrem Workflow hinzugefügt haben, bereits hinzugefügte Aktionen weiterhin bearbeiten und ausführen. Aber sie können die Aktion nicht wieder hinzuzufügen.

Beispiele für eine benutzerdefinierte Aktion

Die folgenden Codeausschnitte enthalten Beispiele für mehrere häufige Anwendungsfälle für benutzerdefinierte Aktionen, z. B. das Definieren eines Widgets oder das Aufrufen einer serverlosen Funktion.

Beispiel Nr. 1

Dieses Beispiel enthält die folgenden Eingabefelder, die für Kontakt- und Deal-Workflows erstellt wurden:
  • widgetName: ein statisches Eingabefeld
  • widgetColor: ein Dropdown-Feld mit Optionen
  • widgetOwner: ein Feld, das einen zuständigen Mitarbeiter in HubSpot darstellt.
  • widgetQuantity: ein Feld, das von einer Eigenschaft des aufgenommenen Objekts (die der Benutzer, der den Workflow erstellt, auswählt) abgeleitet ist.
//
{
  "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"]
}

Beispiel Nr. 2

Die folgende benutzerdefinierte Aktion verwendet eine serverlose Funktion, um die an die konfigurierte actionUrl gesendete Payload umzuwandeln. Da das objectTypes-Feld in der Definition der benutzerdefinierten Aktion nicht angegeben ist, steht diese Aktion in allen Workflows zur Verfügung.
//
{
  "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' }; }"
    }
  ]
}

Beispiel Nr. 3

Die folgende benutzerdefinierte Aktion verfügt über Feldabhängigkeiten und -optionen, die von einer externen API abgerufen werden. Da die Widget-Größe von der Widget-Farbe abhängig ist, kann der Benutzer so lange keinen Wert für die Widget-Größe eingeben, bis eine Widget-Farbe ausgewählt wurde. Die Widget-Kosten hängen ebenfalls von der Widget-Farbe ab, sie werden jedoch durch den Wert bedingt, den der Benutzer für die Widget-Farbe auswählt. Der Benutzer kann keinen Wert für die Widget-Kosten eingeben, es sei denn, Rot ist als Widget-Farbe ausgewählt.
//
{
  "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' }; }"
    }
  ]
}
Last modified on December 10, 2025