diff --git a/apps/docs/content/docs/en/triggers/hubspot.mdx b/apps/docs/content/docs/en/triggers/hubspot.mdx index 886f39e8e63..3e8e1c6708c 100644 --- a/apps/docs/content/docs/en/triggers/hubspot.mdx +++ b/apps/docs/content/docs/en/triggers/hubspot.mdx @@ -10,1135 +10,40 @@ import { BlockInfoCard } from "@/components/ui/block-info-card" color="#FF7A59" /> -HubSpot provides 27 triggers for automating workflows based on events. +HubSpot provides 1 trigger for automating workflows based on events. -## Triggers - -### HubSpot Company Created - -Trigger workflow when a new company is created in HubSpot - -#### Configuration - -| Parameter | Type | Required | Description | -| --------- | ---- | -------- | ----------- | -| `clientId` | string | Yes | Found in your HubSpot app settings under Auth tab | -| `clientSecret` | string | Yes | Found in your HubSpot app settings under Auth tab | -| `appId` | string | Yes | Found in your HubSpot app settings. Used to identify your app. | -| `developerApiKey` | string | Yes | Used for making API calls to HubSpot. Found in your HubSpot app settings. | - -#### Output - -| Parameter | Type | Description | -| --------- | ---- | ----------- | -| `payload` | array | Full webhook payload array from HubSpot containing event details | -| ↳ `objectId` | number | HubSpot object ID | -| ↳ `subscriptionType` | string | Type of subscription event | -| ↳ `portalId` | number | HubSpot portal ID | -| ↳ `occurredAt` | number | Timestamp when event occurred \(ms\) | -| ↳ `attemptNumber` | number | Webhook delivery attempt number | -| ↳ `eventId` | number | Event ID | -| ↳ `changeSource` | string | Source of the change | -| ↳ `propertyName` | string | Property name \(for propertyChange events\) | -| ↳ `propertyValue` | string | New property value \(for propertyChange events\) | -| `provider` | string | Provider name \(hubspot\) | -| `providerConfig` | object | Provider configuration | -| ↳ `appId` | string | HubSpot App ID | -| ↳ `clientId` | string | HubSpot Client ID | -| ↳ `triggerId` | string | Trigger ID \(e.g., hubspot_company_created\) | -| ↳ `clientSecret` | string | HubSpot Client Secret | -| ↳ `developerApiKey` | string | HubSpot Developer API Key | -| ↳ `curlSetWebhookUrl` | string | curl command to set webhook URL | -| ↳ `curlCreateSubscription` | string | curl command to create subscription | -| ↳ `webhookUrlDisplay` | string | Webhook URL display value | -| ↳ `propertyName` | string | Optional property name filter \(for property change triggers\) | - - ---- - -### HubSpot Company Deleted - -Trigger workflow when a company is deleted in HubSpot - -#### Configuration - -| Parameter | Type | Required | Description | -| --------- | ---- | -------- | ----------- | -| `clientId` | string | Yes | Found in your HubSpot app settings under Auth tab | -| `clientSecret` | string | Yes | Found in your HubSpot app settings under Auth tab | -| `appId` | string | Yes | Found in your HubSpot app settings. Used to identify your app. | -| `developerApiKey` | string | Yes | Used for making API calls to HubSpot. Found in your HubSpot app settings. | - -#### Output - -| Parameter | Type | Description | -| --------- | ---- | ----------- | -| `payload` | array | Full webhook payload array from HubSpot containing event details | -| ↳ `objectId` | number | HubSpot object ID | -| ↳ `subscriptionType` | string | Type of subscription event | -| ↳ `portalId` | number | HubSpot portal ID | -| ↳ `occurredAt` | number | Timestamp when event occurred \(ms\) | -| ↳ `attemptNumber` | number | Webhook delivery attempt number | -| ↳ `eventId` | number | Event ID | -| ↳ `changeSource` | string | Source of the change | -| ↳ `propertyName` | string | Property name \(for propertyChange events\) | -| ↳ `propertyValue` | string | New property value \(for propertyChange events\) | -| `provider` | string | Provider name \(hubspot\) | -| `providerConfig` | object | Provider configuration | -| ↳ `appId` | string | HubSpot App ID | -| ↳ `clientId` | string | HubSpot Client ID | -| ↳ `triggerId` | string | Trigger ID \(e.g., hubspot_company_created\) | -| ↳ `clientSecret` | string | HubSpot Client Secret | -| ↳ `developerApiKey` | string | HubSpot Developer API Key | -| ↳ `curlSetWebhookUrl` | string | curl command to set webhook URL | -| ↳ `curlCreateSubscription` | string | curl command to create subscription | -| ↳ `webhookUrlDisplay` | string | Webhook URL display value | -| ↳ `propertyName` | string | Optional property name filter \(for property change triggers\) | - - ---- - -### HubSpot Company Merged - -Trigger workflow when companies are merged in HubSpot - -#### Configuration - -| Parameter | Type | Required | Description | -| --------- | ---- | -------- | ----------- | -| `clientId` | string | Yes | Found in your HubSpot app settings under Auth tab | -| `clientSecret` | string | Yes | Found in your HubSpot app settings under Auth tab | -| `appId` | string | Yes | Found in your HubSpot app settings. Used to identify your app. | -| `developerApiKey` | string | Yes | Used for making API calls to HubSpot. Found in your HubSpot app settings. | - -#### Output - -| Parameter | Type | Description | -| --------- | ---- | ----------- | -| `payload` | array | Full webhook payload array from HubSpot containing merge event details | -| ↳ `objectId` | number | HubSpot object ID \(winning/primary record\) | -| ↳ `subscriptionType` | string | Type of subscription event | -| ↳ `portalId` | number | HubSpot portal ID | -| ↳ `occurredAt` | number | Timestamp when event occurred \(ms\) | -| ↳ `attemptNumber` | number | Webhook delivery attempt number | -| ↳ `eventId` | number | Event ID | -| ↳ `changeSource` | string | Source of the change | -| ↳ `mergedObjectIds` | array | IDs of the objects that were merged into the primary record | -| `provider` | string | Provider name \(hubspot\) | -| `providerConfig` | object | Provider configuration | -| ↳ `appId` | string | HubSpot App ID | -| ↳ `clientId` | string | HubSpot Client ID | -| ↳ `triggerId` | string | Trigger ID \(e.g., hubspot_contact_merged\) | -| ↳ `clientSecret` | string | HubSpot Client Secret | -| ↳ `developerApiKey` | string | HubSpot Developer API Key | -| ↳ `curlSetWebhookUrl` | string | curl command to set webhook URL | -| ↳ `curlCreateSubscription` | string | curl command to create subscription | -| ↳ `webhookUrlDisplay` | string | Webhook URL display value | - - ---- - -### HubSpot Company Property Changed - -Trigger workflow when any property of a company is updated in HubSpot - -#### Configuration - -| Parameter | Type | Required | Description | -| --------- | ---- | -------- | ----------- | -| `clientId` | string | Yes | Found in your HubSpot app settings under Auth tab | -| `clientSecret` | string | Yes | Found in your HubSpot app settings under Auth tab | -| `appId` | string | Yes | Found in your HubSpot app settings. Used to identify your app. | -| `developerApiKey` | string | Yes | Used for making API calls to HubSpot. Found in your HubSpot app settings. | -| `propertyName` | string | No | Optional: Filter to only trigger when a specific property changes. Leave empty to trigger on any property change. | - -#### Output - -| Parameter | Type | Description | -| --------- | ---- | ----------- | -| `payload` | array | Full webhook payload array from HubSpot containing event details | -| ↳ `objectId` | number | HubSpot object ID | -| ↳ `subscriptionType` | string | Type of subscription event | -| ↳ `portalId` | number | HubSpot portal ID | -| ↳ `occurredAt` | number | Timestamp when event occurred \(ms\) | -| ↳ `attemptNumber` | number | Webhook delivery attempt number | -| ↳ `eventId` | number | Event ID | -| ↳ `changeSource` | string | Source of the change | -| ↳ `propertyName` | string | Property name \(for propertyChange events\) | -| ↳ `propertyValue` | string | New property value \(for propertyChange events\) | -| `provider` | string | Provider name \(hubspot\) | -| `providerConfig` | object | Provider configuration | -| ↳ `appId` | string | HubSpot App ID | -| ↳ `clientId` | string | HubSpot Client ID | -| ↳ `triggerId` | string | Trigger ID \(e.g., hubspot_company_created\) | -| ↳ `clientSecret` | string | HubSpot Client Secret | -| ↳ `developerApiKey` | string | HubSpot Developer API Key | -| ↳ `curlSetWebhookUrl` | string | curl command to set webhook URL | -| ↳ `curlCreateSubscription` | string | curl command to create subscription | -| ↳ `webhookUrlDisplay` | string | Webhook URL display value | -| ↳ `propertyName` | string | Optional property name filter \(for property change triggers\) | - - ---- - -### HubSpot Company Restored - -Trigger workflow when a deleted company is restored in HubSpot - -#### Configuration - -| Parameter | Type | Required | Description | -| --------- | ---- | -------- | ----------- | -| `clientId` | string | Yes | Found in your HubSpot app settings under Auth tab | -| `clientSecret` | string | Yes | Found in your HubSpot app settings under Auth tab | -| `appId` | string | Yes | Found in your HubSpot app settings. Used to identify your app. | -| `developerApiKey` | string | Yes | Used for making API calls to HubSpot. Found in your HubSpot app settings. | - -#### Output - -| Parameter | Type | Description | -| --------- | ---- | ----------- | -| `payload` | array | Full webhook payload array from HubSpot containing event details | -| ↳ `objectId` | number | HubSpot object ID | -| ↳ `subscriptionType` | string | Type of subscription event | -| ↳ `portalId` | number | HubSpot portal ID | -| ↳ `occurredAt` | number | Timestamp when event occurred \(ms\) | -| ↳ `attemptNumber` | number | Webhook delivery attempt number | -| ↳ `eventId` | number | Event ID | -| ↳ `changeSource` | string | Source of the change | -| ↳ `propertyName` | string | Property name \(for propertyChange events\) | -| ↳ `propertyValue` | string | New property value \(for propertyChange events\) | -| `provider` | string | Provider name \(hubspot\) | -| `providerConfig` | object | Provider configuration | -| ↳ `appId` | string | HubSpot App ID | -| ↳ `clientId` | string | HubSpot Client ID | -| ↳ `triggerId` | string | Trigger ID \(e.g., hubspot_company_created\) | -| ↳ `clientSecret` | string | HubSpot Client Secret | -| ↳ `developerApiKey` | string | HubSpot Developer API Key | -| ↳ `curlSetWebhookUrl` | string | curl command to set webhook URL | -| ↳ `curlCreateSubscription` | string | curl command to create subscription | -| ↳ `webhookUrlDisplay` | string | Webhook URL display value | -| ↳ `propertyName` | string | Optional property name filter \(for property change triggers\) | - - ---- - -### HubSpot Contact Created - -Trigger workflow when a new contact is created in HubSpot - -#### Configuration - -| Parameter | Type | Required | Description | -| --------- | ---- | -------- | ----------- | -| `clientId` | string | Yes | Found in your HubSpot app settings under Auth tab | -| `clientSecret` | string | Yes | Found in your HubSpot app settings under Auth tab | -| `appId` | string | Yes | Found in your HubSpot app settings. Used to identify your app. | -| `developerApiKey` | string | Yes | Used for making API calls to HubSpot. Found in your HubSpot app settings. | - -#### Output - -| Parameter | Type | Description | -| --------- | ---- | ----------- | -| `payload` | array | Full webhook payload array from HubSpot containing event details | -| ↳ `objectId` | number | HubSpot object ID | -| ↳ `subscriptionType` | string | Type of subscription event | -| ↳ `portalId` | number | HubSpot portal ID | -| ↳ `occurredAt` | number | Timestamp when event occurred \(ms\) | -| ↳ `attemptNumber` | number | Webhook delivery attempt number | -| ↳ `eventId` | number | Event ID | -| ↳ `changeSource` | string | Source of the change | -| ↳ `propertyName` | string | Property name \(for propertyChange events\) | -| ↳ `propertyValue` | string | New property value \(for propertyChange events\) | -| `provider` | string | Provider name \(hubspot\) | -| `providerConfig` | object | Provider configuration | -| ↳ `appId` | string | HubSpot App ID | -| ↳ `clientId` | string | HubSpot Client ID | -| ↳ `triggerId` | string | Trigger ID \(e.g., hubspot_company_created\) | -| ↳ `clientSecret` | string | HubSpot Client Secret | -| ↳ `developerApiKey` | string | HubSpot Developer API Key | -| ↳ `curlSetWebhookUrl` | string | curl command to set webhook URL | -| ↳ `curlCreateSubscription` | string | curl command to create subscription | -| ↳ `webhookUrlDisplay` | string | Webhook URL display value | -| ↳ `propertyName` | string | Optional property name filter \(for property change triggers\) | - - ---- - -### HubSpot Contact Deleted - -Trigger workflow when a contact is deleted in HubSpot - -#### Configuration - -| Parameter | Type | Required | Description | -| --------- | ---- | -------- | ----------- | -| `clientId` | string | Yes | Found in your HubSpot app settings under Auth tab | -| `clientSecret` | string | Yes | Found in your HubSpot app settings under Auth tab | -| `appId` | string | Yes | Found in your HubSpot app settings. Used to identify your app. | -| `developerApiKey` | string | Yes | Used for making API calls to HubSpot. Found in your HubSpot app settings. | - -#### Output - -| Parameter | Type | Description | -| --------- | ---- | ----------- | -| `payload` | array | Full webhook payload array from HubSpot containing event details | -| ↳ `objectId` | number | HubSpot object ID | -| ↳ `subscriptionType` | string | Type of subscription event | -| ↳ `portalId` | number | HubSpot portal ID | -| ↳ `occurredAt` | number | Timestamp when event occurred \(ms\) | -| ↳ `attemptNumber` | number | Webhook delivery attempt number | -| ↳ `eventId` | number | Event ID | -| ↳ `changeSource` | string | Source of the change | -| ↳ `propertyName` | string | Property name \(for propertyChange events\) | -| ↳ `propertyValue` | string | New property value \(for propertyChange events\) | -| `provider` | string | Provider name \(hubspot\) | -| `providerConfig` | object | Provider configuration | -| ↳ `appId` | string | HubSpot App ID | -| ↳ `clientId` | string | HubSpot Client ID | -| ↳ `triggerId` | string | Trigger ID \(e.g., hubspot_company_created\) | -| ↳ `clientSecret` | string | HubSpot Client Secret | -| ↳ `developerApiKey` | string | HubSpot Developer API Key | -| ↳ `curlSetWebhookUrl` | string | curl command to set webhook URL | -| ↳ `curlCreateSubscription` | string | curl command to create subscription | -| ↳ `webhookUrlDisplay` | string | Webhook URL display value | -| ↳ `propertyName` | string | Optional property name filter \(for property change triggers\) | - - ---- - -### HubSpot Contact Merged - -Trigger workflow when contacts are merged in HubSpot - -#### Configuration - -| Parameter | Type | Required | Description | -| --------- | ---- | -------- | ----------- | -| `clientId` | string | Yes | Found in your HubSpot app settings under Auth tab | -| `clientSecret` | string | Yes | Found in your HubSpot app settings under Auth tab | -| `appId` | string | Yes | Found in your HubSpot app settings. Used to identify your app. | -| `developerApiKey` | string | Yes | Used for making API calls to HubSpot. Found in your HubSpot app settings. | - -#### Output - -| Parameter | Type | Description | -| --------- | ---- | ----------- | -| `payload` | array | Full webhook payload array from HubSpot containing merge event details | -| ↳ `objectId` | number | HubSpot object ID \(winning/primary record\) | -| ↳ `subscriptionType` | string | Type of subscription event | -| ↳ `portalId` | number | HubSpot portal ID | -| ↳ `occurredAt` | number | Timestamp when event occurred \(ms\) | -| ↳ `attemptNumber` | number | Webhook delivery attempt number | -| ↳ `eventId` | number | Event ID | -| ↳ `changeSource` | string | Source of the change | -| ↳ `mergedObjectIds` | array | IDs of the objects that were merged into the primary record | -| `provider` | string | Provider name \(hubspot\) | -| `providerConfig` | object | Provider configuration | -| ↳ `appId` | string | HubSpot App ID | -| ↳ `clientId` | string | HubSpot Client ID | -| ↳ `triggerId` | string | Trigger ID \(e.g., hubspot_contact_merged\) | -| ↳ `clientSecret` | string | HubSpot Client Secret | -| ↳ `developerApiKey` | string | HubSpot Developer API Key | -| ↳ `curlSetWebhookUrl` | string | curl command to set webhook URL | -| ↳ `curlCreateSubscription` | string | curl command to create subscription | -| ↳ `webhookUrlDisplay` | string | Webhook URL display value | - - ---- - -### HubSpot Contact Privacy Deleted - -Trigger workflow when a contact is deleted for privacy compliance (GDPR, CCPA, etc.) in HubSpot - -#### Configuration - -| Parameter | Type | Required | Description | -| --------- | ---- | -------- | ----------- | -| `clientId` | string | Yes | Found in your HubSpot app settings under Auth tab | -| `clientSecret` | string | Yes | Found in your HubSpot app settings under Auth tab | -| `appId` | string | Yes | Found in your HubSpot app settings. Used to identify your app. | -| `developerApiKey` | string | Yes | Used for making API calls to HubSpot. Found in your HubSpot app settings. | - -#### Output - -| Parameter | Type | Description | -| --------- | ---- | ----------- | -| `payload` | array | Full webhook payload array from HubSpot containing event details | -| ↳ `objectId` | number | HubSpot object ID | -| ↳ `subscriptionType` | string | Type of subscription event | -| ↳ `portalId` | number | HubSpot portal ID | -| ↳ `occurredAt` | number | Timestamp when event occurred \(ms\) | -| ↳ `attemptNumber` | number | Webhook delivery attempt number | -| ↳ `eventId` | number | Event ID | -| ↳ `changeSource` | string | Source of the change | -| ↳ `propertyName` | string | Property name \(for propertyChange events\) | -| ↳ `propertyValue` | string | New property value \(for propertyChange events\) | -| `provider` | string | Provider name \(hubspot\) | -| `providerConfig` | object | Provider configuration | -| ↳ `appId` | string | HubSpot App ID | -| ↳ `clientId` | string | HubSpot Client ID | -| ↳ `triggerId` | string | Trigger ID \(e.g., hubspot_company_created\) | -| ↳ `clientSecret` | string | HubSpot Client Secret | -| ↳ `developerApiKey` | string | HubSpot Developer API Key | -| ↳ `curlSetWebhookUrl` | string | curl command to set webhook URL | -| ↳ `curlCreateSubscription` | string | curl command to create subscription | -| ↳ `webhookUrlDisplay` | string | Webhook URL display value | -| ↳ `propertyName` | string | Optional property name filter \(for property change triggers\) | - - ---- - -### HubSpot Contact Property Changed - -Trigger workflow when any property of a contact is updated in HubSpot - -#### Configuration - -| Parameter | Type | Required | Description | -| --------- | ---- | -------- | ----------- | -| `clientId` | string | Yes | Found in your HubSpot app settings under Auth tab | -| `clientSecret` | string | Yes | Found in your HubSpot app settings under Auth tab | -| `appId` | string | Yes | Found in your HubSpot app settings. Used to identify your app. | -| `developerApiKey` | string | Yes | Used for making API calls to HubSpot. Found in your HubSpot app settings. | -| `propertyName` | string | No | Optional: Filter to only trigger when a specific property changes. Leave empty to trigger on any property change. | - -#### Output - -| Parameter | Type | Description | -| --------- | ---- | ----------- | -| `payload` | array | Full webhook payload array from HubSpot containing event details | -| ↳ `objectId` | number | HubSpot object ID | -| ↳ `subscriptionType` | string | Type of subscription event | -| ↳ `portalId` | number | HubSpot portal ID | -| ↳ `occurredAt` | number | Timestamp when event occurred \(ms\) | -| ↳ `attemptNumber` | number | Webhook delivery attempt number | -| ↳ `eventId` | number | Event ID | -| ↳ `changeSource` | string | Source of the change | -| ↳ `propertyName` | string | Property name \(for propertyChange events\) | -| ↳ `propertyValue` | string | New property value \(for propertyChange events\) | -| `provider` | string | Provider name \(hubspot\) | -| `providerConfig` | object | Provider configuration | -| ↳ `appId` | string | HubSpot App ID | -| ↳ `clientId` | string | HubSpot Client ID | -| ↳ `triggerId` | string | Trigger ID \(e.g., hubspot_company_created\) | -| ↳ `clientSecret` | string | HubSpot Client Secret | -| ↳ `developerApiKey` | string | HubSpot Developer API Key | -| ↳ `curlSetWebhookUrl` | string | curl command to set webhook URL | -| ↳ `curlCreateSubscription` | string | curl command to create subscription | -| ↳ `webhookUrlDisplay` | string | Webhook URL display value | -| ↳ `propertyName` | string | Optional property name filter \(for property change triggers\) | - - ---- - -### HubSpot Contact Restored - -Trigger workflow when a deleted contact is restored in HubSpot - -#### Configuration - -| Parameter | Type | Required | Description | -| --------- | ---- | -------- | ----------- | -| `clientId` | string | Yes | Found in your HubSpot app settings under Auth tab | -| `clientSecret` | string | Yes | Found in your HubSpot app settings under Auth tab | -| `appId` | string | Yes | Found in your HubSpot app settings. Used to identify your app. | -| `developerApiKey` | string | Yes | Used for making API calls to HubSpot. Found in your HubSpot app settings. | - -#### Output - -| Parameter | Type | Description | -| --------- | ---- | ----------- | -| `payload` | array | Full webhook payload array from HubSpot containing event details | -| ↳ `objectId` | number | HubSpot object ID | -| ↳ `subscriptionType` | string | Type of subscription event | -| ↳ `portalId` | number | HubSpot portal ID | -| ↳ `occurredAt` | number | Timestamp when event occurred \(ms\) | -| ↳ `attemptNumber` | number | Webhook delivery attempt number | -| ↳ `eventId` | number | Event ID | -| ↳ `changeSource` | string | Source of the change | -| ↳ `propertyName` | string | Property name \(for propertyChange events\) | -| ↳ `propertyValue` | string | New property value \(for propertyChange events\) | -| `provider` | string | Provider name \(hubspot\) | -| `providerConfig` | object | Provider configuration | -| ↳ `appId` | string | HubSpot App ID | -| ↳ `clientId` | string | HubSpot Client ID | -| ↳ `triggerId` | string | Trigger ID \(e.g., hubspot_company_created\) | -| ↳ `clientSecret` | string | HubSpot Client Secret | -| ↳ `developerApiKey` | string | HubSpot Developer API Key | -| ↳ `curlSetWebhookUrl` | string | curl command to set webhook URL | -| ↳ `curlCreateSubscription` | string | curl command to create subscription | -| ↳ `webhookUrlDisplay` | string | Webhook URL display value | -| ↳ `propertyName` | string | Optional property name filter \(for property change triggers\) | - - ---- - -### HubSpot Conversation Creation - -Trigger workflow when a new conversation is created in HubSpot - -#### Configuration - -| Parameter | Type | Required | Description | -| --------- | ---- | -------- | ----------- | -| `clientId` | string | Yes | Found in your HubSpot app settings under Auth tab | -| `clientSecret` | string | Yes | Found in your HubSpot app settings under Auth tab | -| `appId` | string | Yes | Found in your HubSpot app settings. Used to identify your app. | -| `developerApiKey` | string | Yes | Used for making API calls to HubSpot. Found in your HubSpot app settings. | - -#### Output - -| Parameter | Type | Description | -| --------- | ---- | ----------- | -| `payload` | array | Full webhook payload array from HubSpot containing event details | -| ↳ `objectId` | number | HubSpot object ID | -| ↳ `subscriptionType` | string | Type of subscription event | -| ↳ `portalId` | number | HubSpot portal ID | -| ↳ `occurredAt` | number | Timestamp when event occurred \(ms\) | -| ↳ `attemptNumber` | number | Webhook delivery attempt number | -| ↳ `eventId` | number | Event ID | -| ↳ `changeSource` | string | Source of the change | -| ↳ `propertyName` | string | Property name \(for propertyChange events\) | -| ↳ `propertyValue` | string | New property value \(for propertyChange events\) | -| `provider` | string | Provider name \(hubspot\) | -| `providerConfig` | object | Provider configuration | -| ↳ `appId` | string | HubSpot App ID | -| ↳ `clientId` | string | HubSpot Client ID | -| ↳ `triggerId` | string | Trigger ID \(e.g., hubspot_company_created\) | -| ↳ `clientSecret` | string | HubSpot Client Secret | -| ↳ `developerApiKey` | string | HubSpot Developer API Key | -| ↳ `curlSetWebhookUrl` | string | curl command to set webhook URL | -| ↳ `curlCreateSubscription` | string | curl command to create subscription | -| ↳ `webhookUrlDisplay` | string | Webhook URL display value | -| ↳ `propertyName` | string | Optional property name filter \(for property change triggers\) | - - ---- - -### HubSpot Conversation Deletion - -Trigger workflow when a conversation is deleted in HubSpot - -#### Configuration - -| Parameter | Type | Required | Description | -| --------- | ---- | -------- | ----------- | -| `clientId` | string | Yes | Found in your HubSpot app settings under Auth tab | -| `clientSecret` | string | Yes | Found in your HubSpot app settings under Auth tab | -| `appId` | string | Yes | Found in your HubSpot app settings. Used to identify your app. | -| `developerApiKey` | string | Yes | Used for making API calls to HubSpot. Found in your HubSpot app settings. | - -#### Output - -| Parameter | Type | Description | -| --------- | ---- | ----------- | -| `payload` | array | Full webhook payload array from HubSpot containing event details | -| ↳ `objectId` | number | HubSpot object ID | -| ↳ `subscriptionType` | string | Type of subscription event | -| ↳ `portalId` | number | HubSpot portal ID | -| ↳ `occurredAt` | number | Timestamp when event occurred \(ms\) | -| ↳ `attemptNumber` | number | Webhook delivery attempt number | -| ↳ `eventId` | number | Event ID | -| ↳ `changeSource` | string | Source of the change | -| ↳ `propertyName` | string | Property name \(for propertyChange events\) | -| ↳ `propertyValue` | string | New property value \(for propertyChange events\) | -| `provider` | string | Provider name \(hubspot\) | -| `providerConfig` | object | Provider configuration | -| ↳ `appId` | string | HubSpot App ID | -| ↳ `clientId` | string | HubSpot Client ID | -| ↳ `triggerId` | string | Trigger ID \(e.g., hubspot_company_created\) | -| ↳ `clientSecret` | string | HubSpot Client Secret | -| ↳ `developerApiKey` | string | HubSpot Developer API Key | -| ↳ `curlSetWebhookUrl` | string | curl command to set webhook URL | -| ↳ `curlCreateSubscription` | string | curl command to create subscription | -| ↳ `webhookUrlDisplay` | string | Webhook URL display value | -| ↳ `propertyName` | string | Optional property name filter \(for property change triggers\) | - - ---- +All triggers below are **polling-based** — they check for new data on a schedule rather than receiving push notifications. -### HubSpot Conversation New Message - -Trigger workflow when a new message is added to a conversation in HubSpot - -#### Configuration - -| Parameter | Type | Required | Description | -| --------- | ---- | -------- | ----------- | -| `clientId` | string | Yes | Found in your HubSpot app settings under Auth tab | -| `clientSecret` | string | Yes | Found in your HubSpot app settings under Auth tab | -| `appId` | string | Yes | Found in your HubSpot app settings. Used to identify your app. | -| `developerApiKey` | string | Yes | Used for making API calls to HubSpot. Found in your HubSpot app settings. | - -#### Output - -| Parameter | Type | Description | -| --------- | ---- | ----------- | -| `payload` | array | Full webhook payload array from HubSpot containing event details | -| ↳ `objectId` | number | HubSpot object ID | -| ↳ `subscriptionType` | string | Type of subscription event | -| ↳ `portalId` | number | HubSpot portal ID | -| ↳ `occurredAt` | number | Timestamp when event occurred \(ms\) | -| ↳ `attemptNumber` | number | Webhook delivery attempt number | -| ↳ `eventId` | number | Event ID | -| ↳ `changeSource` | string | Source of the change | -| ↳ `propertyName` | string | Property name \(for propertyChange events\) | -| ↳ `propertyValue` | string | New property value \(for propertyChange events\) | -| `provider` | string | Provider name \(hubspot\) | -| `providerConfig` | object | Provider configuration | -| ↳ `appId` | string | HubSpot App ID | -| ↳ `clientId` | string | HubSpot Client ID | -| ↳ `triggerId` | string | Trigger ID \(e.g., hubspot_company_created\) | -| ↳ `clientSecret` | string | HubSpot Client Secret | -| ↳ `developerApiKey` | string | HubSpot Developer API Key | -| ↳ `curlSetWebhookUrl` | string | curl command to set webhook URL | -| ↳ `curlCreateSubscription` | string | curl command to create subscription | -| ↳ `webhookUrlDisplay` | string | Webhook URL display value | -| ↳ `propertyName` | string | Optional property name filter \(for property change triggers\) | - - ---- - -### HubSpot Conversation Privacy Deletion - -Trigger workflow when a conversation is deleted for privacy compliance (GDPR, CCPA, etc.) in HubSpot - -#### Configuration - -| Parameter | Type | Required | Description | -| --------- | ---- | -------- | ----------- | -| `clientId` | string | Yes | Found in your HubSpot app settings under Auth tab | -| `clientSecret` | string | Yes | Found in your HubSpot app settings under Auth tab | -| `appId` | string | Yes | Found in your HubSpot app settings. Used to identify your app. | -| `developerApiKey` | string | Yes | Used for making API calls to HubSpot. Found in your HubSpot app settings. | - -#### Output - -| Parameter | Type | Description | -| --------- | ---- | ----------- | -| `payload` | array | Full webhook payload array from HubSpot containing event details | -| ↳ `objectId` | number | HubSpot object ID | -| ↳ `subscriptionType` | string | Type of subscription event | -| ↳ `portalId` | number | HubSpot portal ID | -| ↳ `occurredAt` | number | Timestamp when event occurred \(ms\) | -| ↳ `attemptNumber` | number | Webhook delivery attempt number | -| ↳ `eventId` | number | Event ID | -| ↳ `changeSource` | string | Source of the change | -| ↳ `propertyName` | string | Property name \(for propertyChange events\) | -| ↳ `propertyValue` | string | New property value \(for propertyChange events\) | -| `provider` | string | Provider name \(hubspot\) | -| `providerConfig` | object | Provider configuration | -| ↳ `appId` | string | HubSpot App ID | -| ↳ `clientId` | string | HubSpot Client ID | -| ↳ `triggerId` | string | Trigger ID \(e.g., hubspot_company_created\) | -| ↳ `clientSecret` | string | HubSpot Client Secret | -| ↳ `developerApiKey` | string | HubSpot Developer API Key | -| ↳ `curlSetWebhookUrl` | string | curl command to set webhook URL | -| ↳ `curlCreateSubscription` | string | curl command to create subscription | -| ↳ `webhookUrlDisplay` | string | Webhook URL display value | -| ↳ `propertyName` | string | Optional property name filter \(for property change triggers\) | - - ---- - -### HubSpot Conversation Property Changed - -Trigger workflow when any property of a conversation is updated in HubSpot - -#### Configuration - -| Parameter | Type | Required | Description | -| --------- | ---- | -------- | ----------- | -| `clientId` | string | Yes | Found in your HubSpot app settings under Auth tab | -| `clientSecret` | string | Yes | Found in your HubSpot app settings under Auth tab | -| `appId` | string | Yes | Found in your HubSpot app settings. Used to identify your app. | -| `developerApiKey` | string | Yes | Used for making API calls to HubSpot. Found in your HubSpot app settings. | -| `propertyName` | string | No | Optional: Filter to only trigger when a specific property changes. Leave empty to trigger on any property change. | - -#### Output - -| Parameter | Type | Description | -| --------- | ---- | ----------- | -| `payload` | array | Full webhook payload array from HubSpot containing event details | -| ↳ `objectId` | number | HubSpot object ID | -| ↳ `subscriptionType` | string | Type of subscription event | -| ↳ `portalId` | number | HubSpot portal ID | -| ↳ `occurredAt` | number | Timestamp when event occurred \(ms\) | -| ↳ `attemptNumber` | number | Webhook delivery attempt number | -| ↳ `eventId` | number | Event ID | -| ↳ `changeSource` | string | Source of the change | -| ↳ `propertyName` | string | Property name \(for propertyChange events\) | -| ↳ `propertyValue` | string | New property value \(for propertyChange events\) | -| `provider` | string | Provider name \(hubspot\) | -| `providerConfig` | object | Provider configuration | -| ↳ `appId` | string | HubSpot App ID | -| ↳ `clientId` | string | HubSpot Client ID | -| ↳ `triggerId` | string | Trigger ID \(e.g., hubspot_company_created\) | -| ↳ `clientSecret` | string | HubSpot Client Secret | -| ↳ `developerApiKey` | string | HubSpot Developer API Key | -| ↳ `curlSetWebhookUrl` | string | curl command to set webhook URL | -| ↳ `curlCreateSubscription` | string | curl command to create subscription | -| ↳ `webhookUrlDisplay` | string | Webhook URL display value | -| ↳ `propertyName` | string | Optional property name filter \(for property change triggers\) | - - ---- - -### HubSpot Deal Created - -Trigger workflow when a new deal is created in HubSpot - -#### Configuration - -| Parameter | Type | Required | Description | -| --------- | ---- | -------- | ----------- | -| `clientId` | string | Yes | Found in your HubSpot app settings under Auth tab | -| `clientSecret` | string | Yes | Found in your HubSpot app settings under Auth tab | -| `appId` | string | Yes | Found in your HubSpot app settings. Used to identify your app. | -| `developerApiKey` | string | Yes | Used for making API calls to HubSpot. Found in your HubSpot app settings. | - -#### Output - -| Parameter | Type | Description | -| --------- | ---- | ----------- | -| `payload` | array | Full webhook payload array from HubSpot containing event details | -| ↳ `objectId` | number | HubSpot object ID | -| ↳ `subscriptionType` | string | Type of subscription event | -| ↳ `portalId` | number | HubSpot portal ID | -| ↳ `occurredAt` | number | Timestamp when event occurred \(ms\) | -| ↳ `attemptNumber` | number | Webhook delivery attempt number | -| ↳ `eventId` | number | Event ID | -| ↳ `changeSource` | string | Source of the change | -| ↳ `propertyName` | string | Property name \(for propertyChange events\) | -| ↳ `propertyValue` | string | New property value \(for propertyChange events\) | -| `provider` | string | Provider name \(hubspot\) | -| `providerConfig` | object | Provider configuration | -| ↳ `appId` | string | HubSpot App ID | -| ↳ `clientId` | string | HubSpot Client ID | -| ↳ `triggerId` | string | Trigger ID \(e.g., hubspot_company_created\) | -| ↳ `clientSecret` | string | HubSpot Client Secret | -| ↳ `developerApiKey` | string | HubSpot Developer API Key | -| ↳ `curlSetWebhookUrl` | string | curl command to set webhook URL | -| ↳ `curlCreateSubscription` | string | curl command to create subscription | -| ↳ `webhookUrlDisplay` | string | Webhook URL display value | -| ↳ `propertyName` | string | Optional property name filter \(for property change triggers\) | - - ---- - -### HubSpot Deal Deleted - -Trigger workflow when a deal is deleted in HubSpot - -#### Configuration - -| Parameter | Type | Required | Description | -| --------- | ---- | -------- | ----------- | -| `clientId` | string | Yes | Found in your HubSpot app settings under Auth tab | -| `clientSecret` | string | Yes | Found in your HubSpot app settings under Auth tab | -| `appId` | string | Yes | Found in your HubSpot app settings. Used to identify your app. | -| `developerApiKey` | string | Yes | Used for making API calls to HubSpot. Found in your HubSpot app settings. | - -#### Output - -| Parameter | Type | Description | -| --------- | ---- | ----------- | -| `payload` | array | Full webhook payload array from HubSpot containing event details | -| ↳ `objectId` | number | HubSpot object ID | -| ↳ `subscriptionType` | string | Type of subscription event | -| ↳ `portalId` | number | HubSpot portal ID | -| ↳ `occurredAt` | number | Timestamp when event occurred \(ms\) | -| ↳ `attemptNumber` | number | Webhook delivery attempt number | -| ↳ `eventId` | number | Event ID | -| ↳ `changeSource` | string | Source of the change | -| ↳ `propertyName` | string | Property name \(for propertyChange events\) | -| ↳ `propertyValue` | string | New property value \(for propertyChange events\) | -| `provider` | string | Provider name \(hubspot\) | -| `providerConfig` | object | Provider configuration | -| ↳ `appId` | string | HubSpot App ID | -| ↳ `clientId` | string | HubSpot Client ID | -| ↳ `triggerId` | string | Trigger ID \(e.g., hubspot_company_created\) | -| ↳ `clientSecret` | string | HubSpot Client Secret | -| ↳ `developerApiKey` | string | HubSpot Developer API Key | -| ↳ `curlSetWebhookUrl` | string | curl command to set webhook URL | -| ↳ `curlCreateSubscription` | string | curl command to create subscription | -| ↳ `webhookUrlDisplay` | string | Webhook URL display value | -| ↳ `propertyName` | string | Optional property name filter \(for property change triggers\) | - - ---- - -### HubSpot Deal Merged - -Trigger workflow when deals are merged in HubSpot - -#### Configuration - -| Parameter | Type | Required | Description | -| --------- | ---- | -------- | ----------- | -| `clientId` | string | Yes | Found in your HubSpot app settings under Auth tab | -| `clientSecret` | string | Yes | Found in your HubSpot app settings under Auth tab | -| `appId` | string | Yes | Found in your HubSpot app settings. Used to identify your app. | -| `developerApiKey` | string | Yes | Used for making API calls to HubSpot. Found in your HubSpot app settings. | - -#### Output - -| Parameter | Type | Description | -| --------- | ---- | ----------- | -| `payload` | array | Full webhook payload array from HubSpot containing merge event details | -| ↳ `objectId` | number | HubSpot object ID \(winning/primary record\) | -| ↳ `subscriptionType` | string | Type of subscription event | -| ↳ `portalId` | number | HubSpot portal ID | -| ↳ `occurredAt` | number | Timestamp when event occurred \(ms\) | -| ↳ `attemptNumber` | number | Webhook delivery attempt number | -| ↳ `eventId` | number | Event ID | -| ↳ `changeSource` | string | Source of the change | -| ↳ `mergedObjectIds` | array | IDs of the objects that were merged into the primary record | -| `provider` | string | Provider name \(hubspot\) | -| `providerConfig` | object | Provider configuration | -| ↳ `appId` | string | HubSpot App ID | -| ↳ `clientId` | string | HubSpot Client ID | -| ↳ `triggerId` | string | Trigger ID \(e.g., hubspot_contact_merged\) | -| ↳ `clientSecret` | string | HubSpot Client Secret | -| ↳ `developerApiKey` | string | HubSpot Developer API Key | -| ↳ `curlSetWebhookUrl` | string | curl command to set webhook URL | -| ↳ `curlCreateSubscription` | string | curl command to create subscription | -| ↳ `webhookUrlDisplay` | string | Webhook URL display value | - - ---- - -### HubSpot Deal Property Changed - -Trigger workflow when any property of a deal is updated in HubSpot - -#### Configuration - -| Parameter | Type | Required | Description | -| --------- | ---- | -------- | ----------- | -| `clientId` | string | Yes | Found in your HubSpot app settings under Auth tab | -| `clientSecret` | string | Yes | Found in your HubSpot app settings under Auth tab | -| `appId` | string | Yes | Found in your HubSpot app settings. Used to identify your app. | -| `developerApiKey` | string | Yes | Used for making API calls to HubSpot. Found in your HubSpot app settings. | -| `propertyName` | string | No | Optional: Filter to only trigger when a specific property changes. Leave empty to trigger on any property change. | - -#### Output - -| Parameter | Type | Description | -| --------- | ---- | ----------- | -| `payload` | array | Full webhook payload array from HubSpot containing event details | -| ↳ `objectId` | number | HubSpot object ID | -| ↳ `subscriptionType` | string | Type of subscription event | -| ↳ `portalId` | number | HubSpot portal ID | -| ↳ `occurredAt` | number | Timestamp when event occurred \(ms\) | -| ↳ `attemptNumber` | number | Webhook delivery attempt number | -| ↳ `eventId` | number | Event ID | -| ↳ `changeSource` | string | Source of the change | -| ↳ `propertyName` | string | Property name \(for propertyChange events\) | -| ↳ `propertyValue` | string | New property value \(for propertyChange events\) | -| `provider` | string | Provider name \(hubspot\) | -| `providerConfig` | object | Provider configuration | -| ↳ `appId` | string | HubSpot App ID | -| ↳ `clientId` | string | HubSpot Client ID | -| ↳ `triggerId` | string | Trigger ID \(e.g., hubspot_company_created\) | -| ↳ `clientSecret` | string | HubSpot Client Secret | -| ↳ `developerApiKey` | string | HubSpot Developer API Key | -| ↳ `curlSetWebhookUrl` | string | curl command to set webhook URL | -| ↳ `curlCreateSubscription` | string | curl command to create subscription | -| ↳ `webhookUrlDisplay` | string | Webhook URL display value | -| ↳ `propertyName` | string | Optional property name filter \(for property change triggers\) | - - ---- - -### HubSpot Deal Restored - -Trigger workflow when a deleted deal is restored in HubSpot - -#### Configuration - -| Parameter | Type | Required | Description | -| --------- | ---- | -------- | ----------- | -| `clientId` | string | Yes | Found in your HubSpot app settings under Auth tab | -| `clientSecret` | string | Yes | Found in your HubSpot app settings under Auth tab | -| `appId` | string | Yes | Found in your HubSpot app settings. Used to identify your app. | -| `developerApiKey` | string | Yes | Used for making API calls to HubSpot. Found in your HubSpot app settings. | - -#### Output - -| Parameter | Type | Description | -| --------- | ---- | ----------- | -| `payload` | array | Full webhook payload array from HubSpot containing event details | -| ↳ `objectId` | number | HubSpot object ID | -| ↳ `subscriptionType` | string | Type of subscription event | -| ↳ `portalId` | number | HubSpot portal ID | -| ↳ `occurredAt` | number | Timestamp when event occurred \(ms\) | -| ↳ `attemptNumber` | number | Webhook delivery attempt number | -| ↳ `eventId` | number | Event ID | -| ↳ `changeSource` | string | Source of the change | -| ↳ `propertyName` | string | Property name \(for propertyChange events\) | -| ↳ `propertyValue` | string | New property value \(for propertyChange events\) | -| `provider` | string | Provider name \(hubspot\) | -| `providerConfig` | object | Provider configuration | -| ↳ `appId` | string | HubSpot App ID | -| ↳ `clientId` | string | HubSpot Client ID | -| ↳ `triggerId` | string | Trigger ID \(e.g., hubspot_company_created\) | -| ↳ `clientSecret` | string | HubSpot Client Secret | -| ↳ `developerApiKey` | string | HubSpot Developer API Key | -| ↳ `curlSetWebhookUrl` | string | curl command to set webhook URL | -| ↳ `curlCreateSubscription` | string | curl command to create subscription | -| ↳ `webhookUrlDisplay` | string | Webhook URL display value | -| ↳ `propertyName` | string | Optional property name filter \(for property change triggers\) | - - ---- - -### HubSpot Ticket Created - -Trigger workflow when a new ticket is created in HubSpot - -#### Configuration - -| Parameter | Type | Required | Description | -| --------- | ---- | -------- | ----------- | -| `clientId` | string | Yes | Found in your HubSpot app settings under Auth tab | -| `clientSecret` | string | Yes | Found in your HubSpot app settings under Auth tab | -| `appId` | string | Yes | Found in your HubSpot app settings. Used to identify your app. | -| `developerApiKey` | string | Yes | Used for making API calls to HubSpot. Found in your HubSpot app settings. | - -#### Output - -| Parameter | Type | Description | -| --------- | ---- | ----------- | -| `payload` | array | Full webhook payload array from HubSpot containing event details | -| ↳ `objectId` | number | HubSpot object ID | -| ↳ `subscriptionType` | string | Type of subscription event | -| ↳ `portalId` | number | HubSpot portal ID | -| ↳ `occurredAt` | number | Timestamp when event occurred \(ms\) | -| ↳ `attemptNumber` | number | Webhook delivery attempt number | -| ↳ `eventId` | number | Event ID | -| ↳ `changeSource` | string | Source of the change | -| ↳ `propertyName` | string | Property name \(for propertyChange events\) | -| ↳ `propertyValue` | string | New property value \(for propertyChange events\) | -| `provider` | string | Provider name \(hubspot\) | -| `providerConfig` | object | Provider configuration | -| ↳ `appId` | string | HubSpot App ID | -| ↳ `clientId` | string | HubSpot Client ID | -| ↳ `triggerId` | string | Trigger ID \(e.g., hubspot_company_created\) | -| ↳ `clientSecret` | string | HubSpot Client Secret | -| ↳ `developerApiKey` | string | HubSpot Developer API Key | -| ↳ `curlSetWebhookUrl` | string | curl command to set webhook URL | -| ↳ `curlCreateSubscription` | string | curl command to create subscription | -| ↳ `webhookUrlDisplay` | string | Webhook URL display value | -| ↳ `propertyName` | string | Optional property name filter \(for property change triggers\) | - - ---- - -### HubSpot Ticket Deleted - -Trigger workflow when a ticket is deleted in HubSpot - -#### Configuration - -| Parameter | Type | Required | Description | -| --------- | ---- | -------- | ----------- | -| `clientId` | string | Yes | Found in your HubSpot app settings under Auth tab | -| `clientSecret` | string | Yes | Found in your HubSpot app settings under Auth tab | -| `appId` | string | Yes | Found in your HubSpot app settings. Used to identify your app. | -| `developerApiKey` | string | Yes | Used for making API calls to HubSpot. Found in your HubSpot app settings. | - -#### Output - -| Parameter | Type | Description | -| --------- | ---- | ----------- | -| `payload` | array | Full webhook payload array from HubSpot containing event details | -| ↳ `objectId` | number | HubSpot object ID | -| ↳ `subscriptionType` | string | Type of subscription event | -| ↳ `portalId` | number | HubSpot portal ID | -| ↳ `occurredAt` | number | Timestamp when event occurred \(ms\) | -| ↳ `attemptNumber` | number | Webhook delivery attempt number | -| ↳ `eventId` | number | Event ID | -| ↳ `changeSource` | string | Source of the change | -| ↳ `propertyName` | string | Property name \(for propertyChange events\) | -| ↳ `propertyValue` | string | New property value \(for propertyChange events\) | -| `provider` | string | Provider name \(hubspot\) | -| `providerConfig` | object | Provider configuration | -| ↳ `appId` | string | HubSpot App ID | -| ↳ `clientId` | string | HubSpot Client ID | -| ↳ `triggerId` | string | Trigger ID \(e.g., hubspot_company_created\) | -| ↳ `clientSecret` | string | HubSpot Client Secret | -| ↳ `developerApiKey` | string | HubSpot Developer API Key | -| ↳ `curlSetWebhookUrl` | string | curl command to set webhook URL | -| ↳ `curlCreateSubscription` | string | curl command to create subscription | -| ↳ `webhookUrlDisplay` | string | Webhook URL display value | -| ↳ `propertyName` | string | Optional property name filter \(for property change triggers\) | - - ---- - -### HubSpot Ticket Merged - -Trigger workflow when tickets are merged in HubSpot - -#### Configuration - -| Parameter | Type | Required | Description | -| --------- | ---- | -------- | ----------- | -| `clientId` | string | Yes | Found in your HubSpot app settings under Auth tab | -| `clientSecret` | string | Yes | Found in your HubSpot app settings under Auth tab | -| `appId` | string | Yes | Found in your HubSpot app settings. Used to identify your app. | -| `developerApiKey` | string | Yes | Used for making API calls to HubSpot. Found in your HubSpot app settings. | - -#### Output - -| Parameter | Type | Description | -| --------- | ---- | ----------- | -| `payload` | array | Full webhook payload array from HubSpot containing merge event details | -| ↳ `objectId` | number | HubSpot object ID \(winning/primary record\) | -| ↳ `subscriptionType` | string | Type of subscription event | -| ↳ `portalId` | number | HubSpot portal ID | -| ↳ `occurredAt` | number | Timestamp when event occurred \(ms\) | -| ↳ `attemptNumber` | number | Webhook delivery attempt number | -| ↳ `eventId` | number | Event ID | -| ↳ `changeSource` | string | Source of the change | -| ↳ `mergedObjectIds` | array | IDs of the objects that were merged into the primary record | -| `provider` | string | Provider name \(hubspot\) | -| `providerConfig` | object | Provider configuration | -| ↳ `appId` | string | HubSpot App ID | -| ↳ `clientId` | string | HubSpot Client ID | -| ↳ `triggerId` | string | Trigger ID \(e.g., hubspot_contact_merged\) | -| ↳ `clientSecret` | string | HubSpot Client Secret | -| ↳ `developerApiKey` | string | HubSpot Developer API Key | -| ↳ `curlSetWebhookUrl` | string | curl command to set webhook URL | -| ↳ `curlCreateSubscription` | string | curl command to create subscription | -| ↳ `webhookUrlDisplay` | string | Webhook URL display value | - - ---- - -### HubSpot Ticket Property Changed - -Trigger workflow when any property of a ticket is updated in HubSpot - -#### Configuration - -| Parameter | Type | Required | Description | -| --------- | ---- | -------- | ----------- | -| `clientId` | string | Yes | Found in your HubSpot app settings under Auth tab | -| `clientSecret` | string | Yes | Found in your HubSpot app settings under Auth tab | -| `appId` | string | Yes | Found in your HubSpot app settings. Used to identify your app. | -| `developerApiKey` | string | Yes | Used for making API calls to HubSpot. Found in your HubSpot app settings. | -| `propertyName` | string | No | Optional: Filter to only trigger when a specific property changes. Leave empty to trigger on any property change. | - -#### Output - -| Parameter | Type | Description | -| --------- | ---- | ----------- | -| `payload` | array | Full webhook payload array from HubSpot containing event details | -| ↳ `objectId` | number | HubSpot object ID | -| ↳ `subscriptionType` | string | Type of subscription event | -| ↳ `portalId` | number | HubSpot portal ID | -| ↳ `occurredAt` | number | Timestamp when event occurred \(ms\) | -| ↳ `attemptNumber` | number | Webhook delivery attempt number | -| ↳ `eventId` | number | Event ID | -| ↳ `changeSource` | string | Source of the change | -| ↳ `propertyName` | string | Property name \(for propertyChange events\) | -| ↳ `propertyValue` | string | New property value \(for propertyChange events\) | -| `provider` | string | Provider name \(hubspot\) | -| `providerConfig` | object | Provider configuration | -| ↳ `appId` | string | HubSpot App ID | -| ↳ `clientId` | string | HubSpot Client ID | -| ↳ `triggerId` | string | Trigger ID \(e.g., hubspot_company_created\) | -| ↳ `clientSecret` | string | HubSpot Client Secret | -| ↳ `developerApiKey` | string | HubSpot Developer API Key | -| ↳ `curlSetWebhookUrl` | string | curl command to set webhook URL | -| ↳ `curlCreateSubscription` | string | curl command to create subscription | -| ↳ `webhookUrlDisplay` | string | Webhook URL display value | -| ↳ `propertyName` | string | Optional property name filter \(for property change triggers\) | - - ---- - -### HubSpot Ticket Restored - -Trigger workflow when a deleted ticket is restored in HubSpot - -#### Configuration - -| Parameter | Type | Required | Description | -| --------- | ---- | -------- | ----------- | -| `clientId` | string | Yes | Found in your HubSpot app settings under Auth tab | -| `clientSecret` | string | Yes | Found in your HubSpot app settings under Auth tab | -| `appId` | string | Yes | Found in your HubSpot app settings. Used to identify your app. | -| `developerApiKey` | string | Yes | Used for making API calls to HubSpot. Found in your HubSpot app settings. | - -#### Output - -| Parameter | Type | Description | -| --------- | ---- | ----------- | -| `payload` | array | Full webhook payload array from HubSpot containing event details | -| ↳ `objectId` | number | HubSpot object ID | -| ↳ `subscriptionType` | string | Type of subscription event | -| ↳ `portalId` | number | HubSpot portal ID | -| ↳ `occurredAt` | number | Timestamp when event occurred \(ms\) | -| ↳ `attemptNumber` | number | Webhook delivery attempt number | -| ↳ `eventId` | number | Event ID | -| ↳ `changeSource` | string | Source of the change | -| ↳ `propertyName` | string | Property name \(for propertyChange events\) | -| ↳ `propertyValue` | string | New property value \(for propertyChange events\) | -| `provider` | string | Provider name \(hubspot\) | -| `providerConfig` | object | Provider configuration | -| ↳ `appId` | string | HubSpot App ID | -| ↳ `clientId` | string | HubSpot Client ID | -| ↳ `triggerId` | string | Trigger ID \(e.g., hubspot_company_created\) | -| ↳ `clientSecret` | string | HubSpot Client Secret | -| ↳ `developerApiKey` | string | HubSpot Developer API Key | -| ↳ `curlSetWebhookUrl` | string | curl command to set webhook URL | -| ↳ `curlCreateSubscription` | string | curl command to create subscription | -| ↳ `webhookUrlDisplay` | string | Webhook URL display value | -| ↳ `propertyName` | string | Optional property name filter \(for property change triggers\) | - - ---- +## Triggers -### HubSpot Webhook (All Events) +### HubSpot Trigger -Trigger workflow on any HubSpot webhook event +Triggers when a HubSpot record (contact, company, deal, ticket, or custom object) is created or updated #### Configuration | Parameter | Type | Required | Description | | --------- | ---- | -------- | ----------- | -| `clientId` | string | Yes | Found in your HubSpot app settings under Auth tab | -| `clientSecret` | string | Yes | Found in your HubSpot app settings under Auth tab | -| `appId` | string | Yes | Found in your HubSpot app settings. Used to identify your app. | -| `developerApiKey` | string | Yes | Used for making API calls to HubSpot. Found in your HubSpot app settings. | +| `triggerCredentials` | string | Yes | Connect a HubSpot account so Sim can poll your CRM on your behalf. | +| `objectType` | string | Yes | Which HubSpot CRM object to watch. Pick | +| `customObjectTypeId` | string | Yes | HubSpot custom object type ID \(e.g. | +| `eventType` | string | Yes | Created fires once per new record. Updated fires whenever the record changes \(and on creation\). | +| `properties` | string | No | Comma- or newline-separated list of HubSpot property names to include on each record. Leave empty to use sensible defaults. Sim always includes the timestamp properties Sim needs internally, regardless of this list. | +| `filterPropertyName` | string | No | Only emit records where this property equals the value below. Leave both fields empty to emit every change. | +| `filterPropertyValue` | string | No | Value the filter property must match \(exact match, case-sensitive\). | +| `maxRecordsPerPoll` | string | No | Cap on records emitted per poll \(default 50, max 1000\). Excess rolls over to the next poll. | #### Output | Parameter | Type | Description | | --------- | ---- | ----------- | -| `payload` | array | Full webhook payload array from HubSpot containing event details | -| ↳ `objectId` | number | HubSpot object ID | -| ↳ `subscriptionType` | string | Type of subscription event | -| ↳ `portalId` | number | HubSpot portal ID | -| ↳ `occurredAt` | number | Timestamp when event occurred \(ms\) | -| ↳ `attemptNumber` | number | Webhook delivery attempt number | -| ↳ `eventId` | number | Event ID | -| ↳ `changeSource` | string | Source of the change | -| ↳ `propertyName` | string | Property name \(for propertyChange events\) | -| ↳ `propertyValue` | string | New property value \(for propertyChange events\) | -| `provider` | string | Provider name \(hubspot\) | -| `providerConfig` | object | Provider configuration | -| ↳ `appId` | string | HubSpot App ID | -| ↳ `clientId` | string | HubSpot Client ID | -| ↳ `triggerId` | string | Trigger ID \(e.g., hubspot_company_created\) | -| ↳ `clientSecret` | string | HubSpot Client Secret | -| ↳ `developerApiKey` | string | HubSpot Developer API Key | -| ↳ `curlSetWebhookUrl` | string | curl command to set webhook URL | -| ↳ `curlCreateSubscription` | string | curl command to create subscription | -| ↳ `webhookUrlDisplay` | string | Webhook URL display value | -| ↳ `propertyName` | string | Optional property name filter \(for property change triggers\) | +| `objectType` | string | HubSpot object type that fired the trigger \(contact, company, deal, ticket, or custom object type ID\) | +| `eventType` | string | Event type that fired the trigger \(created or updated\) | +| `objectId` | string | HubSpot ID of the affected record | +| `occurredAt` | string | ISO timestamp of the create or update on the record \(sourced from the relevant HubSpot timestamp property\) | +| `properties` | json | HubSpot properties returned for the record \(object of property name to value\) | +| `createdAt` | string | ISO timestamp when the record was created in HubSpot | +| `updatedAt` | string | ISO timestamp when the record was last updated in HubSpot | +| `archived` | boolean | Whether the record is archived | +| `timestamp` | string | ISO timestamp when Sim emitted the event | diff --git a/apps/sim/app/api/tools/hubspot/lists/route.ts b/apps/sim/app/api/tools/hubspot/lists/route.ts new file mode 100644 index 00000000000..0ee11b7c043 --- /dev/null +++ b/apps/sim/app/api/tools/hubspot/lists/route.ts @@ -0,0 +1,99 @@ +import { createLogger } from '@sim/logger' +import { type NextRequest, NextResponse } from 'next/server' +import { hubspotListsSelectorContract } from '@/lib/api/contracts/selectors/hubspot' +import { parseRequest } from '@/lib/api/server' +import { authorizeCredentialUse } from '@/lib/auth/credential-access' +import { generateRequestId } from '@/lib/core/utils/request' +import { withRouteHandler } from '@/lib/core/utils/with-route-handler' +import { refreshAccessTokenIfNeeded } from '@/app/api/auth/oauth/utils' + +export const dynamic = 'force-dynamic' + +const logger = createLogger('HubSpotListsAPI') + +interface HubSpotList { + listId: string + name: string + objectTypeId?: string + processingType?: string + deletedAt?: string | null +} + +export const GET = withRouteHandler(async (request: NextRequest) => { + const requestId = generateRequestId() + + try { + const parsed = await parseRequest(hubspotListsSelectorContract, request, {}) + if (!parsed.success) return parsed.response + const { credentialId, objectTypeId, query } = parsed.data.query + + const authz = await authorizeCredentialUse(request, { + credentialId, + requireWorkflowIdForInternal: false, + }) + if (!authz.ok || !authz.credentialOwnerUserId || !authz.resolvedCredentialId) { + return NextResponse.json({ error: authz.error || 'Unauthorized' }, { status: 403 }) + } + + const accessToken = await refreshAccessTokenIfNeeded( + credentialId, + authz.credentialOwnerUserId, + requestId + ) + if (!accessToken) { + return NextResponse.json({ error: 'Failed to obtain valid access token' }, { status: 401 }) + } + + const params = new URLSearchParams() + if (objectTypeId) params.set('objectTypeId', objectTypeId as string) + params.set('count', '500') + + const response = await fetch( + `https://api.hubapi.com/crm/v3/lists/search?${params.toString()}`, + { + method: 'POST', + headers: { + Authorization: `Bearer ${accessToken}`, + 'Content-Type': 'application/json', + }, + body: JSON.stringify({ + query: '', + processingTypes: ['MANUAL', 'DYNAMIC', 'SNAPSHOT'], + ...(objectTypeId ? { additionalProperties: ['hs_object_id'] } : {}), + }), + } + ) + + if (!response.ok) { + const errorText = await response.text().catch(() => '') + logger.error(`[${requestId}] HubSpot lists API error ${response.status}: ${errorText}`) + return NextResponse.json( + { error: errorText || 'Failed to fetch HubSpot lists' }, + { status: response.status } + ) + } + + const data = (await response.json()) as { lists?: HubSpotList[] } + const filterTerm = (query as string | undefined)?.toLowerCase() + const lists = (data.lists ?? []) + .filter((l) => !l.deletedAt) + .map((l) => ({ + id: l.listId, + name: l.name, + objectType: l.objectTypeId, + processingType: l.processingType, + })) + .filter( + (l) => + !filterTerm || + l.id.toLowerCase().includes(filterTerm) || + l.name.toLowerCase().includes(filterTerm) + ) + .sort((a, b) => a.name.localeCompare(b.name)) + + return NextResponse.json({ lists }, { status: 200 }) + } catch (error) { + logger.error(`[${requestId}] Error fetching HubSpot lists:`, error) + return NextResponse.json({ error: 'Failed to fetch HubSpot lists' }, { status: 500 }) + } +}) diff --git a/apps/sim/app/api/tools/hubspot/owners/route.ts b/apps/sim/app/api/tools/hubspot/owners/route.ts new file mode 100644 index 00000000000..da58d59b2bf --- /dev/null +++ b/apps/sim/app/api/tools/hubspot/owners/route.ts @@ -0,0 +1,96 @@ +import { createLogger } from '@sim/logger' +import { type NextRequest, NextResponse } from 'next/server' +import { hubspotOwnersSelectorContract } from '@/lib/api/contracts/selectors/hubspot' +import { parseRequest } from '@/lib/api/server' +import { authorizeCredentialUse } from '@/lib/auth/credential-access' +import { generateRequestId } from '@/lib/core/utils/request' +import { withRouteHandler } from '@/lib/core/utils/with-route-handler' +import { refreshAccessTokenIfNeeded } from '@/app/api/auth/oauth/utils' + +export const dynamic = 'force-dynamic' + +const logger = createLogger('HubSpotOwnersAPI') + +interface HubSpotOwner { + id: string + email?: string + firstName?: string + lastName?: string + archived?: boolean +} + +export const GET = withRouteHandler(async (request: NextRequest) => { + const requestId = generateRequestId() + + try { + const parsed = await parseRequest(hubspotOwnersSelectorContract, request, {}) + if (!parsed.success) return parsed.response + const { credentialId, query } = parsed.data.query + + const authz = await authorizeCredentialUse(request, { + credentialId, + requireWorkflowIdForInternal: false, + }) + if (!authz.ok || !authz.credentialOwnerUserId || !authz.resolvedCredentialId) { + return NextResponse.json({ error: authz.error || 'Unauthorized' }, { status: 403 }) + } + + const accessToken = await refreshAccessTokenIfNeeded( + credentialId, + authz.credentialOwnerUserId, + requestId + ) + if (!accessToken) { + return NextResponse.json({ error: 'Failed to obtain valid access token' }, { status: 401 }) + } + + const collected: HubSpotOwner[] = [] + let after: string | undefined + let pages = 0 + do { + const params = new URLSearchParams({ limit: '100' }) + if (after) params.set('after', after) + const response = await fetch(`https://api.hubapi.com/crm/v3/owners?${params.toString()}`, { + headers: { Authorization: `Bearer ${accessToken}` }, + }) + + if (!response.ok) { + const errorText = await response.text().catch(() => '') + logger.error(`[${requestId}] HubSpot owners API error ${response.status}: ${errorText}`) + return NextResponse.json( + { error: errorText || 'Failed to fetch HubSpot owners' }, + { status: response.status } + ) + } + + const data = (await response.json()) as { + results?: HubSpotOwner[] + paging?: { next?: { after?: string } } + } + if (data.results?.length) collected.push(...data.results) + after = data.paging?.next?.after + pages++ + } while (after && pages < 10) + + const filterTerm = (query as string | undefined)?.toLowerCase() + const owners = collected + .filter((o) => !o.archived) + .map((o) => ({ + id: o.id, + name: [o.firstName, o.lastName].filter(Boolean).join(' ') || o.email || o.id, + email: o.email, + })) + .filter( + (o) => + !filterTerm || + o.name.toLowerCase().includes(filterTerm) || + (o.email?.toLowerCase().includes(filterTerm) ?? false) + ) + .sort((a, b) => a.name.localeCompare(b.name)) + + return NextResponse.json({ owners }, { status: 200 }) + } catch (error) { + logger.error(`[${requestId}] Error fetching HubSpot owners:`, error) + return NextResponse.json({ error: 'Failed to fetch HubSpot owners' }, { status: 500 }) + } +}) diff --git a/apps/sim/app/api/tools/hubspot/pipelines/route.ts b/apps/sim/app/api/tools/hubspot/pipelines/route.ts new file mode 100644 index 00000000000..7543120e571 --- /dev/null +++ b/apps/sim/app/api/tools/hubspot/pipelines/route.ts @@ -0,0 +1,83 @@ +import { createLogger } from '@sim/logger' +import { type NextRequest, NextResponse } from 'next/server' +import { hubspotPipelinesSelectorContract } from '@/lib/api/contracts/selectors/hubspot' +import { parseRequest } from '@/lib/api/server' +import { authorizeCredentialUse } from '@/lib/auth/credential-access' +import { generateRequestId } from '@/lib/core/utils/request' +import { withRouteHandler } from '@/lib/core/utils/with-route-handler' +import { refreshAccessTokenIfNeeded } from '@/app/api/auth/oauth/utils' + +export const dynamic = 'force-dynamic' + +const logger = createLogger('HubSpotPipelinesAPI') + +const BUILT_IN_PATH: Record = { + contact: 'contacts', + company: 'companies', + deal: 'deals', + ticket: 'tickets', +} + +interface HubSpotPipeline { + id: string + label: string + stages?: Array<{ id: string; label: string }> + archived?: boolean +} + +export const GET = withRouteHandler(async (request: NextRequest) => { + const requestId = generateRequestId() + + try { + const parsed = await parseRequest(hubspotPipelinesSelectorContract, request, {}) + if (!parsed.success) return parsed.response + const { credentialId, objectType } = parsed.data.query + + const authz = await authorizeCredentialUse(request, { + credentialId, + requireWorkflowIdForInternal: false, + }) + if (!authz.ok || !authz.credentialOwnerUserId || !authz.resolvedCredentialId) { + return NextResponse.json({ error: authz.error || 'Unauthorized' }, { status: 403 }) + } + + const accessToken = await refreshAccessTokenIfNeeded( + credentialId, + authz.credentialOwnerUserId, + requestId + ) + if (!accessToken) { + return NextResponse.json({ error: 'Failed to obtain valid access token' }, { status: 401 }) + } + + const pathSegment = BUILT_IN_PATH[objectType] ?? objectType + const response = await fetch( + `https://api.hubapi.com/crm/v3/pipelines/${encodeURIComponent(pathSegment)}`, + { headers: { Authorization: `Bearer ${accessToken}` } } + ) + + if (!response.ok) { + const errorText = await response.text().catch(() => '') + logger.error(`[${requestId}] HubSpot pipelines API error ${response.status}: ${errorText}`) + return NextResponse.json( + { error: errorText || 'Failed to fetch HubSpot pipelines' }, + { status: response.status } + ) + } + + const data = (await response.json()) as { results?: HubSpotPipeline[] } + const pipelines = (data.results ?? []) + .filter((p) => !p.archived) + .map((p) => ({ + id: p.id, + name: p.label, + stages: p.stages?.map((s) => ({ id: s.id, label: s.label })), + })) + .sort((a, b) => a.name.localeCompare(b.name)) + + return NextResponse.json({ pipelines }, { status: 200 }) + } catch (error) { + logger.error(`[${requestId}] Error fetching HubSpot pipelines:`, error) + return NextResponse.json({ error: 'Failed to fetch HubSpot pipelines' }, { status: 500 }) + } +}) diff --git a/apps/sim/app/api/tools/hubspot/properties/route.ts b/apps/sim/app/api/tools/hubspot/properties/route.ts new file mode 100644 index 00000000000..1fafcaab6f0 --- /dev/null +++ b/apps/sim/app/api/tools/hubspot/properties/route.ts @@ -0,0 +1,99 @@ +import { createLogger } from '@sim/logger' +import { type NextRequest, NextResponse } from 'next/server' +import { hubspotPropertiesSelectorContract } from '@/lib/api/contracts/selectors/hubspot' +import { parseRequest } from '@/lib/api/server' +import { authorizeCredentialUse } from '@/lib/auth/credential-access' +import { generateRequestId } from '@/lib/core/utils/request' +import { withRouteHandler } from '@/lib/core/utils/with-route-handler' +import { refreshAccessTokenIfNeeded } from '@/app/api/auth/oauth/utils' + +export const dynamic = 'force-dynamic' + +const logger = createLogger('HubSpotPropertiesAPI') + +const BUILT_IN_PATH: Record = { + contact: 'contacts', + company: 'companies', + deal: 'deals', + ticket: 'tickets', +} + +interface HubSpotProperty { + name: string + label: string + type?: string + fieldType?: string + groupName?: string + hidden?: boolean + archived?: boolean +} + +export const GET = withRouteHandler(async (request: NextRequest) => { + const requestId = generateRequestId() + + try { + const parsed = await parseRequest(hubspotPropertiesSelectorContract, request, {}) + if (!parsed.success) return parsed.response + const { credentialId, objectType, query } = parsed.data.query + + const authz = await authorizeCredentialUse(request, { + credentialId, + requireWorkflowIdForInternal: false, + }) + if (!authz.ok || !authz.credentialOwnerUserId || !authz.resolvedCredentialId) { + return NextResponse.json({ error: authz.error || 'Unauthorized' }, { status: 403 }) + } + + const accessToken = await refreshAccessTokenIfNeeded( + credentialId, + authz.credentialOwnerUserId, + requestId + ) + if (!accessToken) { + return NextResponse.json({ error: 'Failed to obtain valid access token' }, { status: 401 }) + } + + const pathSegment = BUILT_IN_PATH[objectType] ?? objectType + const response = await fetch( + `https://api.hubapi.com/crm/v3/properties/${encodeURIComponent(pathSegment)}`, + { headers: { Authorization: `Bearer ${accessToken}` } } + ) + + if (!response.ok) { + const errorText = await response.text().catch(() => '') + logger.error(`[${requestId}] HubSpot properties API error ${response.status}: ${errorText}`) + return NextResponse.json( + { error: errorText || 'Failed to fetch HubSpot properties' }, + { status: response.status } + ) + } + + const data = (await response.json()) as { results?: HubSpotProperty[] } + if (!Array.isArray(data.results)) { + return NextResponse.json({ error: 'Invalid HubSpot properties response' }, { status: 500 }) + } + + const filterTerm = (query as string | undefined)?.toLowerCase() + const properties = data.results + .filter((p) => !p.hidden && !p.archived) + .map((p) => ({ + id: p.name, + name: p.label || p.name, + type: p.type, + fieldType: p.fieldType, + groupName: p.groupName, + })) + .filter( + (p) => + !filterTerm || + p.id.toLowerCase().includes(filterTerm) || + p.name.toLowerCase().includes(filterTerm) + ) + .sort((a, b) => a.name.localeCompare(b.name)) + + return NextResponse.json({ properties }, { status: 200 }) + } catch (error) { + logger.error(`[${requestId}] Error fetching HubSpot properties:`, error) + return NextResponse.json({ error: 'Failed to fetch HubSpot properties' }, { status: 500 }) + } +}) diff --git a/apps/sim/blocks/blocks/hubspot.ts b/apps/sim/blocks/blocks/hubspot.ts index 5cbd9210264..c107edc71c9 100644 --- a/apps/sim/blocks/blocks/hubspot.ts +++ b/apps/sim/blocks/blocks/hubspot.ts @@ -4,7 +4,6 @@ import type { BlockConfig } from '@/blocks/types' import { AuthMode, IntegrationType } from '@/blocks/types' import type { HubSpotResponse } from '@/tools/hubspot/types' import { getTrigger } from '@/triggers' -import { hubspotAllTriggerOptions } from '@/triggers/hubspot/utils' export const HubSpotBlock: BlockConfig = { type: 'hubspot', @@ -12,7 +11,7 @@ export const HubSpotBlock: BlockConfig = { description: 'Interact with HubSpot CRM or trigger workflows from HubSpot events', authMode: AuthMode.OAuth, longDescription: - 'Integrate HubSpot into your workflow. Manage contacts, companies, deals, tickets, and other CRM objects with powerful automation capabilities. Can be used in trigger mode to start workflows when contacts are created, deleted, or updated.', + 'Integrate HubSpot into your workflow. Manage contacts, companies, deals, tickets, and other CRM objects with powerful automation capabilities. Can be used in trigger mode to start workflows when records are created, updated, a specific property changes, or a contact joins a list.', docsLink: 'https://docs.sim.ai/tools/hubspot', category: 'tools', integrationType: IntegrationType.CRM, @@ -974,42 +973,7 @@ Return ONLY the JSON array of property names - no explanations, no markdown, no generationType: 'json-object', }, }, - { - id: 'selectedTriggerId', - title: 'Trigger Type', - type: 'dropdown', - mode: 'trigger', - options: hubspotAllTriggerOptions, - value: () => 'hubspot_contact_created', - required: true, - }, - ...getTrigger('hubspot_contact_created').subBlocks.slice(1), - ...getTrigger('hubspot_contact_deleted').subBlocks.slice(1), - ...getTrigger('hubspot_contact_merged').subBlocks.slice(1), - ...getTrigger('hubspot_contact_privacy_deleted').subBlocks.slice(1), - ...getTrigger('hubspot_contact_property_changed').subBlocks.slice(1), - ...getTrigger('hubspot_contact_restored').subBlocks.slice(1), - ...getTrigger('hubspot_company_created').subBlocks.slice(1), - ...getTrigger('hubspot_company_deleted').subBlocks.slice(1), - ...getTrigger('hubspot_company_merged').subBlocks.slice(1), - ...getTrigger('hubspot_company_property_changed').subBlocks.slice(1), - ...getTrigger('hubspot_company_restored').subBlocks.slice(1), - ...getTrigger('hubspot_conversation_creation').subBlocks.slice(1), - ...getTrigger('hubspot_conversation_deletion').subBlocks.slice(1), - ...getTrigger('hubspot_conversation_new_message').subBlocks.slice(1), - ...getTrigger('hubspot_conversation_privacy_deletion').subBlocks.slice(1), - ...getTrigger('hubspot_conversation_property_changed').subBlocks.slice(1), - ...getTrigger('hubspot_deal_created').subBlocks.slice(1), - ...getTrigger('hubspot_deal_deleted').subBlocks.slice(1), - ...getTrigger('hubspot_deal_merged').subBlocks.slice(1), - ...getTrigger('hubspot_deal_property_changed').subBlocks.slice(1), - ...getTrigger('hubspot_deal_restored').subBlocks.slice(1), - ...getTrigger('hubspot_ticket_created').subBlocks.slice(1), - ...getTrigger('hubspot_ticket_deleted').subBlocks.slice(1), - ...getTrigger('hubspot_ticket_merged').subBlocks.slice(1), - ...getTrigger('hubspot_ticket_property_changed').subBlocks.slice(1), - ...getTrigger('hubspot_ticket_restored').subBlocks.slice(1), - ...getTrigger('hubspot_webhook').subBlocks.slice(1), + ...getTrigger('hubspot_poller').subBlocks, ], tools: { access: [ @@ -1285,84 +1249,10 @@ Return ONLY the JSON array of property names - no explanations, no markdown, no paging: { type: 'json', description: 'Pagination info with next/prev cursors' }, metadata: { type: 'json', description: 'Operation metadata' }, success: { type: 'boolean', description: 'Operation success status' }, - payload: { - type: 'json', - description: 'Full webhook payload array from HubSpot containing event details', - }, - provider: { - type: 'string', - description: 'Provider name (hubspot)', - }, - providerConfig: { - appId: { - type: 'string', - description: 'HubSpot App ID', - }, - clientId: { - type: 'string', - description: 'HubSpot Client ID', - }, - triggerId: { - type: 'string', - description: 'Trigger ID (e.g., hubspot_company_created)', - }, - clientSecret: { - type: 'string', - description: 'HubSpot Client Secret', - }, - developerApiKey: { - type: 'string', - description: 'HubSpot Developer API Key', - }, - curlSetWebhookUrl: { - type: 'string', - description: 'curl command to set webhook URL', - }, - curlCreateSubscription: { - type: 'string', - description: 'curl command to create subscription', - }, - webhookUrlDisplay: { - type: 'string', - description: 'Webhook URL display value', - }, - propertyName: { - type: 'string', - description: 'Optional property name filter (for property change triggers)', - }, - }, } as any, triggerAllowed: true, triggers: { enabled: true, - available: [ - 'hubspot_contact_created', - 'hubspot_contact_deleted', - 'hubspot_contact_merged', - 'hubspot_contact_privacy_deleted', - 'hubspot_contact_property_changed', - 'hubspot_contact_restored', - 'hubspot_company_created', - 'hubspot_company_deleted', - 'hubspot_company_merged', - 'hubspot_company_property_changed', - 'hubspot_company_restored', - 'hubspot_conversation_creation', - 'hubspot_conversation_deletion', - 'hubspot_conversation_new_message', - 'hubspot_conversation_privacy_deletion', - 'hubspot_conversation_property_changed', - 'hubspot_deal_created', - 'hubspot_deal_deleted', - 'hubspot_deal_merged', - 'hubspot_deal_property_changed', - 'hubspot_deal_restored', - 'hubspot_ticket_created', - 'hubspot_ticket_deleted', - 'hubspot_ticket_merged', - 'hubspot_ticket_property_changed', - 'hubspot_ticket_restored', - 'hubspot_webhook', - ], + available: ['hubspot_poller'], }, } diff --git a/apps/sim/lib/api/contracts/selectors/hubspot.ts b/apps/sim/lib/api/contracts/selectors/hubspot.ts new file mode 100644 index 00000000000..b8c44aadf59 --- /dev/null +++ b/apps/sim/lib/api/contracts/selectors/hubspot.ts @@ -0,0 +1,110 @@ +import { z } from 'zod' +import { + credentialIdQuerySchema, + defineGetSelector, + optionalString, +} from '@/lib/api/contracts/selectors/shared' +import type { ContractJsonResponse, ContractQueryInput } from '@/lib/api/contracts/types' + +const hubspotPropertySchema = z + .object({ + id: z.string(), + name: z.string(), + type: z.string().optional(), + fieldType: z.string().optional(), + groupName: z.string().optional(), + }) + .passthrough() + +const hubspotListSchema = z + .object({ + id: z.string(), + name: z.string(), + objectType: z.string().optional(), + processingType: z.string().optional(), + }) + .passthrough() + +const hubspotPipelineSchema = z + .object({ + id: z.string(), + name: z.string(), + stages: z.array(z.object({ id: z.string(), label: z.string() }).passthrough()).optional(), + }) + .passthrough() + +const hubspotOwnerSchema = z + .object({ + id: z.string(), + name: z.string(), + email: z.string().optional(), + }) + .passthrough() + +const hubspotPropertiesQuerySchema = credentialIdQuerySchema.extend({ + objectType: z + .string() + .min(1, 'objectType is required') + .describe('Built-in slug or custom object type id'), + query: optionalString, +}) + +const hubspotListsQuerySchema = credentialIdQuerySchema.extend({ + objectTypeId: optionalString.describe('Limit to lists targeting this object type'), + query: optionalString, +}) + +const hubspotPipelinesQuerySchema = credentialIdQuerySchema.extend({ + objectType: z + .string() + .min(1, 'objectType is required') + .describe("Object type for which to fetch pipelines (e.g., 'deal' or 'ticket')"), +}) + +const hubspotOwnersQuerySchema = credentialIdQuerySchema.extend({ + query: optionalString, +}) + +export const hubspotPropertiesSelectorContract = defineGetSelector( + '/api/tools/hubspot/properties', + hubspotPropertiesQuerySchema, + z.object({ properties: z.array(hubspotPropertySchema) }) +) + +export const hubspotListsSelectorContract = defineGetSelector( + '/api/tools/hubspot/lists', + hubspotListsQuerySchema, + z.object({ lists: z.array(hubspotListSchema) }) +) + +export const hubspotPipelinesSelectorContract = defineGetSelector( + '/api/tools/hubspot/pipelines', + hubspotPipelinesQuerySchema, + z.object({ pipelines: z.array(hubspotPipelineSchema) }) +) + +export const hubspotOwnersSelectorContract = defineGetSelector( + '/api/tools/hubspot/owners', + hubspotOwnersQuerySchema, + z.object({ owners: z.array(hubspotOwnerSchema) }) +) + +export type HubspotPropertiesSelectorQuery = ContractQueryInput< + typeof hubspotPropertiesSelectorContract +> +export type HubspotListsSelectorQuery = ContractQueryInput +export type HubspotPipelinesSelectorQuery = ContractQueryInput< + typeof hubspotPipelinesSelectorContract +> +export type HubspotOwnersSelectorQuery = ContractQueryInput + +export type HubspotPropertiesSelectorResponse = ContractJsonResponse< + typeof hubspotPropertiesSelectorContract +> +export type HubspotListsSelectorResponse = ContractJsonResponse +export type HubspotPipelinesSelectorResponse = ContractJsonResponse< + typeof hubspotPipelinesSelectorContract +> +export type HubspotOwnersSelectorResponse = ContractJsonResponse< + typeof hubspotOwnersSelectorContract +> diff --git a/apps/sim/lib/api/contracts/selectors/index.ts b/apps/sim/lib/api/contracts/selectors/index.ts index 7d3484dd1f1..8bab27ce372 100644 --- a/apps/sim/lib/api/contracts/selectors/index.ts +++ b/apps/sim/lib/api/contracts/selectors/index.ts @@ -33,6 +33,12 @@ import { googleSheetsSelectorContract, googleTasksTaskListsSelectorContract, } from '@/lib/api/contracts/selectors/google' +import { + hubspotListsSelectorContract, + hubspotOwnersSelectorContract, + hubspotPipelinesSelectorContract, + hubspotPropertiesSelectorContract, +} from '@/lib/api/contracts/selectors/hubspot' import { jiraIssueSelectorContract, jiraIssuesSelectorContract, @@ -104,6 +110,7 @@ export * from '@/lib/api/contracts/selectors/calcom' export * from '@/lib/api/contracts/selectors/cloudwatch' export * from '@/lib/api/contracts/selectors/confluence' export * from '@/lib/api/contracts/selectors/google' +export * from '@/lib/api/contracts/selectors/hubspot' export * from '@/lib/api/contracts/selectors/jira' export * from '@/lib/api/contracts/selectors/jsm' export * from '@/lib/api/contracts/selectors/knowledge' @@ -149,6 +156,10 @@ export const selectorContractsByPath = { '/api/tools/slack/users:detail': slackUserSelectorContract, '/api/tools/gmail/labels': gmailLabelsSelectorContract, '/api/tools/gmail/label': gmailLabelSelectorContract, + '/api/tools/hubspot/properties': hubspotPropertiesSelectorContract, + '/api/tools/hubspot/lists': hubspotListsSelectorContract, + '/api/tools/hubspot/pipelines': hubspotPipelinesSelectorContract, + '/api/tools/hubspot/owners': hubspotOwnersSelectorContract, '/api/tools/outlook/folders': outlookFoldersSelectorContract, '/api/tools/google_calendar/calendars': googleCalendarSelectorContract, '/api/tools/microsoft-teams/teams': microsoftTeamsSelectorContract, diff --git a/apps/sim/lib/webhooks/polling/hubspot.ts b/apps/sim/lib/webhooks/polling/hubspot.ts new file mode 100644 index 00000000000..a714d269264 --- /dev/null +++ b/apps/sim/lib/webhooks/polling/hubspot.ts @@ -0,0 +1,974 @@ +import type { Logger } from '@sim/logger' +import { getErrorMessage } from '@sim/utils/errors' +import { pollingIdempotency } from '@/lib/core/idempotency/service' +import { + getProviderConfig, + type PollingProviderHandler, + type PollWebhookContext, +} from '@/lib/webhooks/polling/types' +import { + markWebhookFailed, + markWebhookSuccess, + resolveOAuthCredential, + updateWebhookProviderConfig, +} from '@/lib/webhooks/polling/utils' +import { processPolledWebhookEvent } from '@/lib/webhooks/processor' + +type HubSpotBuiltInObjectType = 'contact' | 'company' | 'deal' | 'ticket' +type HubSpotEventType = 'created' | 'updated' | 'property_changed' + +interface FilterClause { + propertyName: string + operator: string + value?: string + values?: string[] +} + +interface HubSpotWebhookConfig { + credentialId?: string + /** + * Built-in slug, 'custom' (defers to customObjectTypeId), 'list_membership', + * or a raw HubSpot custom object type id ('2-12345'). + */ + objectType?: string + customObjectTypeId?: string + listId?: string + eventType?: HubSpotEventType + targetPropertyName?: string + properties?: string[] | string + pipelineId?: string + stageId?: string + ownerId?: string + /** User-supplied AND-combined filters — string list or JSON-array string. */ + filters?: string | FilterClause[] + maxRecordsPerPoll?: number + lastSeenTimestampMs?: string + lastSeenObjectId?: string + /** + * List-membership cursor — the `after` value to pass to the next + * `/lists/{id}/memberships/join-order` request. The HubSpot endpoint walks + * ASC by default (oldest first); we use cursor-based resume because + * `before`-mode (DESC) has ambiguous bootstrap semantics. + */ + lastSeenMembershipCursor?: string + /** + * True once we've walked to the end of the list once. While this is false we + * are still in the seed pass — we paginate forward without emitting so the + * workflow doesn't see a flood of historical members on activation. + */ + membershipSeedComplete?: boolean + /** + * Snapshot of the watched property's last-seen value per record (property_changed event). + * Persisted as an entries array (not a `Record`) because HubSpot record ids are numeric + * strings, and JS engines enumerate integer-indexed object keys in numeric order + * regardless of insertion — which would break LRU-style trimming. Array order is stable. + */ + propertySnapshot?: { + property: string + /** `[recordId, value]` pairs in LRU order — oldest first. */ + entries: Array<[string, string | null]> + } + lastCheckedTimestamp?: string +} + +/** + * In-memory snapshot state used during a single poll. Uses a Map (not a plain object) so + * insertion-order iteration is honored even for numeric-string keys. + */ +interface PropertySnapshotState { + property: string + values: Map +} + +interface HubSpotSearchResult { + id: string + properties: Record + createdAt: string + updatedAt: string + archived: boolean +} + +interface HubSpotSearchResponse { + total: number + results: HubSpotSearchResult[] + paging?: { next?: { after?: string } } +} + +const HUBSPOT_PAGE_LIMIT = 100 +const DEFAULT_MAX_RECORDS = 50 +const MAX_MAX_RECORDS = 1000 +/** HubSpot Search API: 10k result hard cap, 5 req/s rate limit. */ +const MAX_PAGES_PER_POLL = 10 +/** Cap on property-change snapshot size to bound providerConfig payload. */ +const MAX_SNAPSHOT_SIZE = 1000 + +const BUILT_IN_PATH: Record = { + contact: 'contacts', + company: 'companies', + deal: 'deals', + ticket: 'tickets', +} + +const VALID_OPERATORS = new Set([ + 'EQ', + 'NEQ', + 'CONTAINS_TOKEN', + 'NOT_CONTAINS_TOKEN', + 'GT', + 'GTE', + 'LT', + 'LTE', + 'BETWEEN', + 'IN', + 'NOT_IN', + 'HAS_PROPERTY', + 'NOT_HAS_PROPERTY', +]) + +function resolveSearchPath(objectType: string): string { + if (objectType in BUILT_IN_PATH) { + return BUILT_IN_PATH[objectType as HubSpotBuiltInObjectType] + } + return objectType +} + +/** Contacts use `lastmodifieddate`; the `hs_lastmodifieddate` property is null on contacts. */ +function resolveModifiedDateProperty(objectType: string): string { + return objectType === 'contact' ? 'lastmodifieddate' : 'hs_lastmodifieddate' +} + +const DEFAULT_PROPERTIES: Record = { + contact: [ + 'firstname', + 'lastname', + 'email', + 'phone', + 'company', + 'lifecyclestage', + 'hs_lead_status', + 'hubspot_owner_id', + 'createdate', + 'lastmodifieddate', + ], + company: [ + 'name', + 'domain', + 'industry', + 'lifecyclestage', + 'hubspot_owner_id', + 'createdate', + 'hs_lastmodifieddate', + ], + deal: [ + 'dealname', + 'amount', + 'dealstage', + 'pipeline', + 'closedate', + 'hubspot_owner_id', + 'createdate', + 'hs_lastmodifieddate', + ], + ticket: [ + 'subject', + 'content', + 'hs_pipeline', + 'hs_pipeline_stage', + 'hs_ticket_priority', + 'hubspot_owner_id', + 'createdate', + 'hs_lastmodifieddate', + ], +} + +export const hubspotPollingHandler: PollingProviderHandler = { + provider: 'hubspot', + label: 'HubSpot', + + async pollWebhook(ctx: PollWebhookContext): Promise<'success' | 'failure'> { + const { webhookData, requestId, logger } = ctx + const webhookId = webhookData.id + + try { + const accessToken = await resolveOAuthCredential(webhookData, 'hubspot', requestId, logger) + const config = getProviderConfig(webhookData.providerConfig) + + if (config.objectType === 'list_membership') { + return await pollListMembership(ctx, config, accessToken) + } + return await pollSearchBased(ctx, config, accessToken) + } catch (error) { + logger.error(`[${requestId}] Error processing HubSpot webhook ${webhookId}:`, error) + await markWebhookFailed(webhookId, logger) + return 'failure' + } + }, +} + +async function pollSearchBased( + ctx: PollWebhookContext, + config: HubSpotWebhookConfig, + accessToken: string +): Promise<'success' | 'failure'> { + const { webhookData, workflowData, requestId, logger } = ctx + const webhookId = webhookData.id + + const objectType = resolveObjectType(config) + const eventType = config.eventType + if (!objectType) { + throw new Error(`HubSpot webhook ${webhookId} is missing objectType`) + } + if (eventType !== 'created' && eventType !== 'updated' && eventType !== 'property_changed') { + throw new Error(`HubSpot webhook ${webhookId} is missing or has invalid eventType`) + } + if (eventType === 'property_changed' && !config.targetPropertyName?.trim()) { + throw new Error( + `HubSpot webhook ${webhookId} uses property_changed event but has no targetPropertyName` + ) + } + + // property_changed walks the modified-date stream and diffs the watched property locally. + const filterProperty = + eventType === 'created' ? 'createdate' : resolveModifiedDateProperty(objectType) + const nowMs = Date.now() + + if (!config.lastSeenTimestampMs) { + await updateWebhookProviderConfig( + webhookId, + { + lastSeenTimestampMs: String(nowMs), + lastCheckedTimestamp: new Date(nowMs).toISOString(), + ...(eventType === 'property_changed' + ? { + propertySnapshot: { + property: config.targetPropertyName?.trim() ?? '', + entries: [], + }, + } + : {}), + }, + logger + ) + await markWebhookSuccess(webhookId, logger) + logger.info( + `[${requestId}] Seeded HubSpot webhook ${webhookId} watermark to ${nowMs} (${objectType}/${eventType}/${filterProperty})` + ) + return 'success' + } + + const watermarkMs = Number(config.lastSeenTimestampMs) + if (!Number.isFinite(watermarkMs)) { + throw new Error( + `HubSpot webhook ${webhookId} has corrupt watermark ${config.lastSeenTimestampMs}` + ) + } + + const userFilters = buildUserFilters(config, logger, requestId) + const properties = resolveRequestedProperties(config, objectType, filterProperty, userFilters) + const maxRecords = Math.min( + Math.max(config.maxRecordsPerPoll ?? DEFAULT_MAX_RECORDS, 1), + MAX_MAX_RECORDS + ) + const lastSeenObjectId = config.lastSeenObjectId + + const records = await fetchHubSpotChanges({ + accessToken, + objectType, + filterProperty, + watermarkMs, + lastSeenObjectId, + properties, + userFilters, + maxRecords, + requestId, + logger, + }) + + if (records.length === 0) { + await updateWebhookProviderConfig( + webhookId, + { lastCheckedTimestamp: new Date(nowMs).toISOString() }, + logger + ) + await markWebhookSuccess(webhookId, logger) + logger.info(`[${requestId}] No new HubSpot ${objectType} ${eventType} for webhook ${webhookId}`) + return 'success' + } + + logger.info( + `[${requestId}] Found ${records.length} HubSpot ${objectType} ${eventType} candidates for webhook ${webhookId}` + ) + + const targetProperty = config.targetPropertyName?.trim() || undefined + const snapshotForRun = + eventType === 'property_changed' && targetProperty + ? resolvePropertySnapshot(config, targetProperty) + : null + + const { processedCount, failedCount, skippedCount, highestSeenMs, maxIdAtHighestTimestamp } = + await processRecords( + records, + webhookData, + workflowData, + objectType, + eventType, + filterProperty, + targetProperty, + snapshotForRun, + requestId, + logger + ) + + const newTimestampMs = highestSeenMs > watermarkMs ? highestSeenMs : watermarkMs + const newObjectId = maxIdAtHighestTimestamp || lastSeenObjectId || '' + + const update: Record = { + lastSeenTimestampMs: String(newTimestampMs), + lastSeenObjectId: newObjectId, + lastCheckedTimestamp: new Date(nowMs).toISOString(), + } + if (snapshotForRun) { + update.propertySnapshot = serializeSnapshot(snapshotForRun) + } + await updateWebhookProviderConfig(webhookId, update, logger) + + if (failedCount > 0 && processedCount === 0) { + await markWebhookFailed(webhookId, logger) + logger.warn( + `[${requestId}] All ${failedCount} HubSpot records failed to process for webhook ${webhookId}` + ) + return 'failure' + } + + await markWebhookSuccess(webhookId, logger) + logger.info( + `[${requestId}] Processed ${processedCount} HubSpot records${skippedCount ? `, skipped ${skippedCount} (no property change)` : ''}${failedCount ? `, ${failedCount} failed` : ''} for webhook ${webhookId}` + ) + return 'success' +} + +async function pollListMembership( + ctx: PollWebhookContext, + config: HubSpotWebhookConfig, + accessToken: string +): Promise<'success' | 'failure'> { + const { webhookData, workflowData, requestId, logger } = ctx + const webhookId = webhookData.id + + const listId = config.listId?.trim() + if (!listId) { + throw new Error(`HubSpot list_membership trigger ${webhookId} is missing listId`) + } + const nowMs = Date.now() + const seedComplete = config.membershipSeedComplete === true + const maxRecords = Math.min( + Math.max(config.maxRecordsPerPoll ?? DEFAULT_MAX_RECORDS, 1), + MAX_MAX_RECORDS + ) + + // The HubSpot endpoint walks ASC by default. We resume from a stored `after` cursor — + // empty cursor means "from the beginning of the list". During the seed pass we paginate + // forward without emitting; once we reach the end (no `paging.next.after`) we mark the + // seed complete and re-fetch from the cursor-to-last-page on each normal poll. New + // members appended to the list show up on subsequent fetches; the idempotency layer + // dedups the records we've already seen on the boundary page. + const result = await fetchListMembershipPages({ + listId, + accessToken, + initialAfter: config.lastSeenMembershipCursor?.trim() || undefined, + pageLimit: seedComplete ? maxRecords : MAX_PAGES_PER_POLL * HUBSPOT_PAGE_LIMIT, + requestId, + logger, + }) + + if (!seedComplete) { + // Seed phase: don't emit. Just save the cursor and (when reached) flip the flag. + const update: Record = { + lastCheckedTimestamp: new Date(nowMs).toISOString(), + lastSeenMembershipCursor: result.resumeCursor ?? '', + } + if (result.reachedEnd) { + update.membershipSeedComplete = true + logger.info( + `[${requestId}] HubSpot list_membership ${webhookId} seed complete (list=${listId})` + ) + } else { + logger.info( + `[${requestId}] HubSpot list_membership ${webhookId} seed in progress (list=${listId}, scanned ${result.scanned})` + ) + } + await updateWebhookProviderConfig(webhookId, update, logger) + await markWebhookSuccess(webhookId, logger) + return 'success' + } + + if (result.records.length === 0) { + await updateWebhookProviderConfig( + webhookId, + { + lastCheckedTimestamp: new Date(nowMs).toISOString(), + lastSeenMembershipCursor: result.resumeCursor ?? '', + }, + logger + ) + await markWebhookSuccess(webhookId, logger) + return 'success' + } + + logger.info( + `[${requestId}] Found ${result.records.length} HubSpot list memberships for webhook ${webhookId}` + ) + + let processedCount = 0 + let failedCount = 0 + + for (const member of result.records) { + try { + await pollingIdempotency.executeWithIdempotency( + 'hubspot', + `${webhookId}:list_membership:${listId}:${member.recordId}:${member.membershipTimestamp}`, + async () => { + const payload = { + objectType: 'list_membership', + eventType: 'joined', + objectId: member.recordId, + occurredAt: member.membershipTimestamp, + listId, + timestamp: new Date().toISOString(), + } + const wfResult = await processPolledWebhookEvent( + webhookData, + workflowData, + payload, + requestId + ) + if (!wfResult.success) { + throw new Error( + `Webhook processing failed (${wfResult.statusCode}): ${wfResult.error ?? 'unknown'}` + ) + } + return { recordId: member.recordId, processed: true } + } + ) + processedCount++ + } catch (error) { + failedCount++ + logger.error( + `[${requestId}] Error processing HubSpot list membership ${member.recordId}:`, + getErrorMessage(error, 'Unknown error') + ) + } + } + + // HubSpot's `paging.next.after` is page-granular — there's no per-record cursor we can + // freeze on. Advance the cursor only when the entire batch succeeded; otherwise replay + // the page next poll and let idempotency dedup the records that already landed. + const advanceCursor = failedCount === 0 + const nextCursor = advanceCursor + ? (result.resumeCursor ?? '') + : (config.lastSeenMembershipCursor?.trim() ?? '') + await updateWebhookProviderConfig( + webhookId, + { + lastSeenMembershipCursor: nextCursor, + lastCheckedTimestamp: new Date(nowMs).toISOString(), + }, + logger + ) + + if (failedCount > 0 && processedCount === 0) { + await markWebhookFailed(webhookId, logger) + return 'failure' + } + + await markWebhookSuccess(webhookId, logger) + return 'success' +} + +function resolveObjectType(config: HubSpotWebhookConfig): string { + const raw = config.objectType?.trim() + if (raw === 'custom') { + return config.customObjectTypeId?.trim() ?? '' + } + return raw ?? '' +} + +function resolveRequestedProperties( + config: HubSpotWebhookConfig, + objectType: string, + filterProperty: string, + userFilters: FilterClause[] +): string[] { + const requested = new Set() + + const userProperties = Array.isArray(config.properties) + ? config.properties + : typeof config.properties === 'string' + ? config.properties.split(/[\n,]/) + : [] + + for (const name of userProperties) { + const trimmed = name.trim() + if (trimmed) requested.add(trimmed) + } + + if (requested.size === 0 && objectType in BUILT_IN_PATH) { + for (const name of DEFAULT_PROPERTIES[objectType as HubSpotBuiltInObjectType]) { + requested.add(name) + } + } + + requested.add('createdate') + requested.add(filterProperty) + if (config.targetPropertyName?.trim()) { + requested.add(config.targetPropertyName.trim()) + } + for (const f of userFilters) { + if (f.propertyName) requested.add(f.propertyName) + } + + return [...requested] +} + +function buildUserFilters( + config: HubSpotWebhookConfig, + logger?: Logger, + requestId?: string +): FilterClause[] { + const filters: FilterClause[] = [] + + // Shortcut fields translate to common HubSpot filter conditions. + if (config.pipelineId?.trim()) { + const property = config.objectType === 'ticket' ? 'hs_pipeline' : 'pipeline' + filters.push({ propertyName: property, operator: 'EQ', value: config.pipelineId.trim() }) + } + if (config.stageId?.trim()) { + const property = config.objectType === 'ticket' ? 'hs_pipeline_stage' : 'dealstage' + filters.push({ propertyName: property, operator: 'EQ', value: config.stageId.trim() }) + } + if (config.ownerId?.trim()) { + filters.push({ propertyName: 'hubspot_owner_id', operator: 'EQ', value: config.ownerId.trim() }) + } + + const raw = config.filters + if (raw) { + try { + const parsed = typeof raw === 'string' ? JSON.parse(raw) : raw + if (Array.isArray(parsed)) { + for (const entry of parsed) { + if (!entry || typeof entry !== 'object') continue + const propertyName = String((entry as FilterClause).propertyName ?? '').trim() + const operator = String((entry as FilterClause).operator ?? '').trim() + if (!propertyName || !VALID_OPERATORS.has(operator)) continue + const clause: FilterClause = { propertyName, operator } + if (Array.isArray((entry as FilterClause).values)) { + clause.values = (entry as FilterClause).values + } else if ((entry as FilterClause).value !== undefined) { + clause.value = String((entry as FilterClause).value) + } + filters.push(clause) + } + } + } catch (error) { + logger?.warn( + `[${requestId ?? ''}] Could not parse user filters as JSON, ignoring:`, + getErrorMessage(error, 'parse error') + ) + } + } + + return filters +} + +function resolvePropertySnapshot( + config: HubSpotWebhookConfig, + property: string +): PropertySnapshotState { + const existing = config.propertySnapshot + if (existing && existing.property === property && Array.isArray(existing.entries)) { + return { property, values: new Map(existing.entries) } + } + // Property changed since last config — start fresh so we don't compare against stale values. + return { property, values: new Map() } +} + +function serializeSnapshot(state: PropertySnapshotState): { + property: string + entries: Array<[string, string | null]> +} { + let entries = [...state.values.entries()] + // Drop oldest by insertion order; Map preserves it regardless of key type. + if (entries.length > MAX_SNAPSHOT_SIZE) { + entries = entries.slice(entries.length - MAX_SNAPSHOT_SIZE) + } + return { property: state.property, entries } +} + +interface FetchArgs { + accessToken: string + objectType: string + filterProperty: string + watermarkMs: number + lastSeenObjectId?: string + properties: string[] + userFilters: FilterClause[] + maxRecords: number + requestId: string + logger: Logger +} + +async function fetchHubSpotChanges(args: FetchArgs): Promise { + const { + accessToken, + objectType, + filterProperty, + watermarkMs, + lastSeenObjectId, + properties, + userFilters, + maxRecords, + requestId, + logger, + } = args + + const url = `https://api.hubapi.com/crm/v3/objects/${encodeURIComponent(resolveSearchPath(objectType))}/search` + const accumulated: HubSpotSearchResult[] = [] + let after: string | undefined + let pages = 0 + + // Two OR-combined filter groups give a strict monotonic cursor over (timestamp, id): + // A: filterProperty > watermark (next timestamps) + // B: filterProperty == watermark AND id > lastSeenObjectId (more ids at boundary) + // User filters AND into both groups so they apply regardless of which side matches. + // Group B is dropped on the first poll after seeding so we don't emit boundary + // records the seed point already skipped past. + const buildBody = (cursor?: string) => { + const groupA: FilterClause[] = [ + { propertyName: filterProperty, operator: 'GT', value: String(watermarkMs) }, + ...userFilters, + ] + const groups = [{ filters: groupA }] + if (lastSeenObjectId) { + const groupB: FilterClause[] = [ + { propertyName: filterProperty, operator: 'EQ', value: String(watermarkMs) }, + { propertyName: 'hs_object_id', operator: 'GT', value: String(lastSeenObjectId) }, + ...userFilters, + ] + groups.push({ filters: groupB }) + } + return { + filterGroups: groups, + sorts: [{ propertyName: filterProperty, direction: 'ASCENDING' }], + properties, + limit: HUBSPOT_PAGE_LIMIT, + ...(cursor ? { after: cursor } : {}), + } + } + + do { + const response = await fetch(url, { + method: 'POST', + headers: { + Authorization: `Bearer ${accessToken}`, + 'Content-Type': 'application/json', + }, + body: JSON.stringify(buildBody(after)), + }) + + if (!response.ok) { + const errorBody = await response.text().catch(() => '') + logger.error(`[${requestId}] HubSpot search API error:`, { + status: response.status, + objectType, + error: errorBody, + }) + throw new Error(`HubSpot search API ${response.status}: ${errorBody.slice(0, 500)}`) + } + + const data = (await response.json()) as HubSpotSearchResponse + if (data.results?.length) accumulated.push(...data.results) + + after = data.paging?.next?.after + pages++ + + if (accumulated.length >= maxRecords) break + if (pages >= MAX_PAGES_PER_POLL) { + logger.warn( + `[${requestId}] HubSpot poll hit MAX_PAGES_PER_POLL=${MAX_PAGES_PER_POLL} — remaining records will roll over to next poll` + ) + break + } + } while (after) + + // HubSpot's intra-timestamp ordering is undocumented. Sorting locally by (timestamp, id) + // before slicing keeps the lowest-(timestamp, id) records, so any unemitted record is + // guaranteed to match Group A or Group B on the next poll. Without this the cursor could + // overshoot and silently skip records. + accumulated.sort((a, b) => { + const aTs = extractPropertyTimestampMs(a, filterProperty) + const bTs = extractPropertyTimestampMs(b, filterProperty) + if (aTs !== bTs) { + if (!Number.isFinite(aTs)) return 1 + if (!Number.isFinite(bTs)) return -1 + return aTs - bTs + } + return compareObjectIds(a.id, b.id) + }) + + return accumulated.slice(0, maxRecords) +} + +function extractPropertyTimestampMs(record: HubSpotSearchResult, propertyName: string): number { + const raw = record.properties?.[propertyName] + if (raw) { + const ms = Date.parse(raw) + if (Number.isFinite(ms)) return ms + } + const fallback = propertyName === 'createdate' ? record.createdAt : record.updatedAt + return fallback ? Date.parse(fallback) : Number.NaN +} + +async function processRecords( + records: HubSpotSearchResult[], + webhookData: PollWebhookContext['webhookData'], + workflowData: PollWebhookContext['workflowData'], + objectType: string, + eventType: HubSpotEventType, + filterProperty: string, + targetProperty: string | undefined, + snapshot: PropertySnapshotState | null, + requestId: string, + logger: Logger +): Promise<{ + processedCount: number + failedCount: number + skippedCount: number + highestSeenMs: number + maxIdAtHighestTimestamp: string +}> { + let processedCount = 0 + let failedCount = 0 + let skippedCount = 0 + let highestSeenMs = 0 + let maxIdAtHighestTimestamp = '' + // Stop advancing the cursor at the first failure so that the failed record and all later + // records (sorted ASC) get re-fetched on the next poll. Without this gate, a transient + // failure on a record at a high timestamp would advance the cursor past it permanently. + let cursorFrozen = false + + for (const record of records) { + const occurredAtMs = extractPropertyTimestampMs(record, filterProperty) + + let previousValue: string | null | undefined + let propertyValue: string | null | undefined + let handledBySkip = false + if (eventType === 'property_changed' && targetProperty && snapshot) { + propertyValue = record.properties?.[targetProperty] ?? null + const had = snapshot.values.has(record.id) + previousValue = had ? snapshot.values.get(record.id) : undefined + if (had && (previousValue ?? null) === (propertyValue ?? null)) { + // Touch the snapshot so this record's entry moves to the end of the LRU order. + // Map.delete + Map.set re-inserts at the tail, regardless of key type. + snapshot.values.delete(record.id) + snapshot.values.set(record.id, propertyValue ?? null) + skippedCount++ + handledBySkip = true + } + // Note: we do NOT pre-update the snapshot before processing. If emission fails the + // record must re-fetch on the next poll AND still appear as a change vs. the prior + // snapshot — otherwise we'd silently skip it on retry. + } + + let handledSuccessfully = handledBySkip + if (!handledBySkip) { + try { + await pollingIdempotency.executeWithIdempotency( + 'hubspot', + `${webhookData.id}:${objectType}:${eventType}:${record.id}:${Number.isFinite(occurredAtMs) ? occurredAtMs : record.updatedAt}`, + async () => { + const payload: Record = { + objectType, + eventType, + objectId: record.id, + occurredAt: Number.isFinite(occurredAtMs) + ? new Date(occurredAtMs).toISOString() + : record.updatedAt, + properties: record.properties, + createdAt: record.createdAt, + updatedAt: record.updatedAt, + archived: record.archived, + timestamp: new Date().toISOString(), + } + if (eventType === 'property_changed' && targetProperty) { + payload.propertyName = targetProperty + payload.propertyValue = propertyValue ?? null + payload.previousValue = previousValue ?? null + } + + const result = await processPolledWebhookEvent( + webhookData, + workflowData, + payload, + requestId + ) + if (!result.success) { + throw new Error( + `Webhook processing failed (${result.statusCode}): ${result.error ?? 'unknown'}` + ) + } + return { recordId: record.id, processed: true } + } + ) + + processedCount++ + handledSuccessfully = true + if (eventType === 'property_changed' && targetProperty && snapshot) { + // Same delete+set dance so an updated value moves to the tail of the LRU order. + snapshot.values.delete(record.id) + snapshot.values.set(record.id, propertyValue ?? null) + } + } catch (error) { + failedCount++ + cursorFrozen = true + logger.error( + `[${requestId}] Error processing HubSpot ${objectType} ${record.id}:`, + getErrorMessage(error, 'Unknown error') + ) + } + } + + // Advance the cursor only for records handled (emitted or intentionally skipped) WITHOUT + // any prior failure in this batch. Records are pre-sorted (timestamp ASC, id ASC), so + // the watermark we persist is the highest contiguously-successful (timestamp, id) pair. + // Anything after the first failure stays unfrozen so it gets re-fetched next poll. + if (handledSuccessfully && !cursorFrozen && Number.isFinite(occurredAtMs)) { + if (occurredAtMs > highestSeenMs) { + highestSeenMs = occurredAtMs + maxIdAtHighestTimestamp = record.id + } else if (occurredAtMs === highestSeenMs) { + if (compareObjectIds(record.id, maxIdAtHighestTimestamp) > 0) { + maxIdAtHighestTimestamp = record.id + } + } + } + } + + return { + processedCount, + failedCount, + skippedCount, + highestSeenMs, + maxIdAtHighestTimestamp, + } +} + +interface ListMembershipRecord { + recordId: string + membershipTimestamp: string +} + +interface FetchListMembershipPagesArgs { + listId: string + accessToken: string + initialAfter: string | undefined + /** Soft cap on emitted records (normal mode) or pages × HUBSPOT_PAGE_LIMIT (seed mode). */ + pageLimit: number + requestId: string + logger: Logger +} + +interface FetchListMembershipPagesResult { + records: ListMembershipRecord[] + /** Cursor to persist for the next poll; empty if we are at the very start. */ + resumeCursor: string | undefined + /** True when the API stopped returning `paging.next.after` — we've consumed everything. */ + reachedEnd: boolean + /** Total records scanned across pages (useful for seed-progress logging). */ + scanned: number +} + +/** + * Walks `/lists/{listId}/memberships/join-order` ASC from an optional cursor until either + * (a) the per-poll page cap is reached or (b) the API stops returning a next cursor. + * + * The endpoint returns members in ascending join-order by default. We never use `before` + * (DESC mode) because its bootstrap semantics — what value to pass for "newest first" — + * are undocumented in HubSpot's SDK type and behave inconsistently in practice. ASC + a + * stored cursor is provably correct and lets new members appear on subsequent polls as + * they're appended past our cursor's position. + */ +async function fetchListMembershipPages( + args: FetchListMembershipPagesArgs +): Promise { + const { listId, accessToken, initialAfter, pageLimit, requestId, logger } = args + + const records: ListMembershipRecord[] = [] + let after: string | undefined = initialAfter + let pages = 0 + let reachedEnd = false + let scanned = 0 + + while (pages < MAX_PAGES_PER_POLL) { + const params = new URLSearchParams({ limit: String(HUBSPOT_PAGE_LIMIT) }) + if (after) params.set('after', after) + const url = `https://api.hubapi.com/crm/v3/lists/${encodeURIComponent(listId)}/memberships/join-order?${params.toString()}` + const response = await fetch(url, { headers: { Authorization: `Bearer ${accessToken}` } }) + + if (!response.ok) { + const errorText = await response.text().catch(() => '') + logger.error( + `[${requestId}] HubSpot list memberships fetch failed ${response.status}: ${errorText}` + ) + throw new Error( + `HubSpot list memberships fetch ${response.status}: ${errorText.slice(0, 500)}` + ) + } + + const data = (await response.json()) as { + results?: Array<{ recordId: string; membershipTimestamp: string }> + paging?: { next?: { after?: string } } + } + const batch = data.results ?? [] + scanned += batch.length + const nextAfter = data.paging?.next?.after + + for (const m of batch) { + records.push({ + recordId: m.recordId, + membershipTimestamp: m.membershipTimestamp, + }) + } + + pages++ + if (!nextAfter) { + reachedEnd = true + break + } + after = nextAfter + if (records.length >= pageLimit) break + } + + return { + records, + // If we walked to the end, hold onto the cursor we LAST used so the next poll re-fetches + // the tail page and picks up any members appended since. If we stopped early, the next + // cursor walks us forward through the rest of the list. + resumeCursor: after, + reachedEnd, + scanned, + } +} + +/** Numeric compare for HubSpot ids (decimal strings, treated numerically by GT/LT). */ +function compareObjectIds(a: string, b: string): number { + if (!a) return b ? -1 : 0 + if (!b) return 1 + const an = Number(a) + const bn = Number(b) + if (Number.isFinite(an) && Number.isFinite(bn)) { + if (an === bn) return 0 + return an > bn ? 1 : -1 + } + if (a === b) return 0 + return a > b ? 1 : -1 +} diff --git a/apps/sim/lib/webhooks/polling/registry.ts b/apps/sim/lib/webhooks/polling/registry.ts index a0b81d25a1c..e3b7205fae7 100644 --- a/apps/sim/lib/webhooks/polling/registry.ts +++ b/apps/sim/lib/webhooks/polling/registry.ts @@ -2,6 +2,7 @@ import { gmailPollingHandler } from '@/lib/webhooks/polling/gmail' import { googleCalendarPollingHandler } from '@/lib/webhooks/polling/google-calendar' import { googleDrivePollingHandler } from '@/lib/webhooks/polling/google-drive' import { googleSheetsPollingHandler } from '@/lib/webhooks/polling/google-sheets' +import { hubspotPollingHandler } from '@/lib/webhooks/polling/hubspot' import { imapPollingHandler } from '@/lib/webhooks/polling/imap' import { outlookPollingHandler } from '@/lib/webhooks/polling/outlook' import { rssPollingHandler } from '@/lib/webhooks/polling/rss' @@ -12,6 +13,7 @@ const POLLING_HANDLERS: Record = { 'google-calendar': googleCalendarPollingHandler, 'google-drive': googleDrivePollingHandler, 'google-sheets': googleSheetsPollingHandler, + hubspot: hubspotPollingHandler, imap: imapPollingHandler, outlook: outlookPollingHandler, rss: rssPollingHandler, diff --git a/apps/sim/lib/webhooks/processor.test.ts b/apps/sim/lib/webhooks/processor.test.ts index 03123a2bd3d..c5f3894707f 100644 --- a/apps/sim/lib/webhooks/processor.test.ts +++ b/apps/sim/lib/webhooks/processor.test.ts @@ -105,10 +105,6 @@ vi.mock('@/triggers/github/utils', () => ({ isGitHubEventMatch: vi.fn().mockReturnValue(true), })) -vi.mock('@/triggers/hubspot/utils', () => ({ - isHubSpotContactEventMatch: vi.fn().mockReturnValue(true), -})) - vi.mock('@/triggers/jira/utils', () => ({ isJiraEventMatch: vi.fn().mockReturnValue(true), })) diff --git a/apps/sim/lib/webhooks/providers/hubspot.ts b/apps/sim/lib/webhooks/providers/hubspot.ts deleted file mode 100644 index 2591ee40175..00000000000 --- a/apps/sim/lib/webhooks/providers/hubspot.ts +++ /dev/null @@ -1,75 +0,0 @@ -import { createLogger } from '@sim/logger' -import type { - EventMatchContext, - FormatInputContext, - FormatInputResult, - WebhookProviderHandler, -} from '@/lib/webhooks/providers/types' - -const logger = createLogger('WebhookProvider:HubSpot') - -export const hubspotHandler: WebhookProviderHandler = { - async matchEvent({ webhook, workflow, body, requestId, providerConfig }: EventMatchContext) { - const triggerId = providerConfig.triggerId as string | undefined - - if (triggerId?.startsWith('hubspot_')) { - const events = Array.isArray(body) ? body : [body] - const firstEvent = events[0] as Record | undefined - const subscriptionType = firstEvent?.subscriptionType as string | undefined - - const { isHubSpotContactEventMatch } = await import('@/triggers/hubspot/utils') - if (!isHubSpotContactEventMatch(triggerId, subscriptionType || '')) { - logger.debug( - `[${requestId}] HubSpot event mismatch for trigger ${triggerId}. Event: ${subscriptionType}. Skipping execution.`, - { - webhookId: webhook.id, - workflowId: workflow.id, - triggerId, - receivedEvent: subscriptionType, - } - ) - return false - } - - logger.info( - `[${requestId}] HubSpot event match confirmed for trigger ${triggerId}. Event: ${subscriptionType}`, - { - webhookId: webhook.id, - workflowId: workflow.id, - triggerId, - receivedEvent: subscriptionType, - } - ) - } - - return true - }, - - async formatInput({ body, webhook }: FormatInputContext): Promise { - const b = body as Record - const events = Array.isArray(b) ? b : [b] - const event = events[0] as Record | undefined - if (!event) { - logger.warn('HubSpot webhook received with empty payload') - return { input: null } - } - logger.info('Formatting HubSpot webhook input', { - subscriptionType: event.subscriptionType, - objectId: event.objectId, - portalId: event.portalId, - }) - return { - input: { payload: body, provider: 'hubspot', providerConfig: webhook.providerConfig }, - } - }, - - extractIdempotencyId(body: unknown) { - if (Array.isArray(body) && body.length > 0) { - const first = body[0] as Record - if (first?.eventId) { - return String(first.eventId) - } - } - return null - }, -} diff --git a/apps/sim/lib/webhooks/providers/registry.ts b/apps/sim/lib/webhooks/providers/registry.ts index 5c4d8eaea73..204be8f8a4b 100644 --- a/apps/sim/lib/webhooks/providers/registry.ts +++ b/apps/sim/lib/webhooks/providers/registry.ts @@ -18,7 +18,6 @@ import { gongHandler } from '@/lib/webhooks/providers/gong' import { googleFormsHandler } from '@/lib/webhooks/providers/google-forms' import { grainHandler } from '@/lib/webhooks/providers/grain' import { greenhouseHandler } from '@/lib/webhooks/providers/greenhouse' -import { hubspotHandler } from '@/lib/webhooks/providers/hubspot' import { imapHandler } from '@/lib/webhooks/providers/imap' import { intercomHandler } from '@/lib/webhooks/providers/intercom' import { jiraHandler } from '@/lib/webhooks/providers/jira' @@ -68,7 +67,6 @@ const PROVIDER_HANDLERS: Record = { fathom: fathomHandler, grain: grainHandler, greenhouse: greenhouseHandler, - hubspot: hubspotHandler, imap: imapHandler, intercom: intercomHandler, jira: jiraHandler, diff --git a/apps/sim/triggers/constants.ts b/apps/sim/triggers/constants.ts index 800ee7e7094..57eab0b7751 100644 --- a/apps/sim/triggers/constants.ts +++ b/apps/sim/triggers/constants.ts @@ -47,6 +47,7 @@ export const POLLING_PROVIDERS = new Set([ 'google-calendar', 'google-drive', 'google-sheets', + 'hubspot', 'imap', 'outlook', 'rss', diff --git a/apps/sim/triggers/hubspot/company_created.ts b/apps/sim/triggers/hubspot/company_created.ts deleted file mode 100644 index 54458cfc220..00000000000 --- a/apps/sim/triggers/hubspot/company_created.ts +++ /dev/null @@ -1,205 +0,0 @@ -import { HubspotIcon } from '@/components/icons' -import { - buildCompanyCreatedOutputs, - hubspotCompanyTriggerOptions, - hubspotSetupInstructions, -} from '@/triggers/hubspot/utils' -import type { TriggerConfig } from '@/triggers/types' - -export const hubspotCompanyCreatedTrigger: TriggerConfig = { - id: 'hubspot_company_created', - name: 'HubSpot Company Created', - provider: 'hubspot', - description: 'Trigger workflow when a new company is created in HubSpot', - version: '1.0.0', - icon: HubspotIcon, - - subBlocks: [ - { - id: 'selectedTriggerId', - title: 'Trigger Type', - type: 'dropdown', - mode: 'trigger', - options: hubspotCompanyTriggerOptions, - value: () => 'hubspot_company_created', - required: true, - }, - { - id: 'clientId', - title: 'Client ID', - type: 'short-input', - placeholder: 'Enter your HubSpot app Client ID', - description: 'Found in your HubSpot app settings under Auth tab', - required: true, - mode: 'trigger', - condition: { - field: 'selectedTriggerId', - value: 'hubspot_company_created', - }, - }, - { - id: 'clientSecret', - title: 'Client Secret', - type: 'short-input', - placeholder: 'Enter your HubSpot app Client Secret', - description: 'Found in your HubSpot app settings under Auth tab', - password: true, - required: true, - mode: 'trigger', - condition: { - field: 'selectedTriggerId', - value: 'hubspot_company_created', - }, - }, - { - id: 'appId', - title: 'App ID', - type: 'short-input', - placeholder: 'Enter your HubSpot App ID', - description: 'Found in your HubSpot app settings. Used to identify your app.', - required: true, - mode: 'trigger', - condition: { - field: 'selectedTriggerId', - value: 'hubspot_company_created', - }, - }, - { - id: 'developerApiKey', - title: 'Developer API Key', - type: 'short-input', - placeholder: 'Enter your HubSpot Developer API Key', - description: 'Used for making API calls to HubSpot. Found in your HubSpot app settings.', - password: true, - required: true, - mode: 'trigger', - condition: { - field: 'selectedTriggerId', - value: 'hubspot_company_created', - }, - }, - { - id: 'webhookUrlDisplay', - title: 'Webhook URL', - type: 'short-input', - readOnly: true, - showCopyButton: true, - useWebhookUrl: true, - placeholder: 'Webhook URL will be generated', - description: 'Copy this URL and paste it into your HubSpot app webhook subscription settings', - mode: 'trigger', - condition: { - field: 'selectedTriggerId', - value: 'hubspot_company_created', - }, - }, - { - id: 'triggerInstructions', - title: 'Setup Instructions', - type: 'text', - defaultValue: hubspotSetupInstructions( - 'company.creation', - 'The webhook will trigger whenever a new company is created in your HubSpot account, regardless of the source (manual entry, form submission, API, import, etc.).' - ), - mode: 'trigger', - condition: { - field: 'selectedTriggerId', - value: 'hubspot_company_created', - }, - }, - { - id: 'curlSetWebhookUrl', - title: '1. Set Webhook Target URL', - type: 'code', - language: 'javascript', - value: (params: Record) => { - const webhookUrl = params.webhookUrlDisplay || '{YOUR_WEBHOOK_URL_FROM_ABOVE}' - return `curl -X PUT "https://api.hubapi.com/webhooks/v3/{YOUR_APP_ID}/settings?hapikey={YOUR_DEVELOPER_API_KEY}" \\ - -H "Content-Type: application/json" \\ - -d '{ - "targetUrl": "${webhookUrl}", - "throttling": { - "maxConcurrentRequests": 10 - } - }'` - }, - readOnly: true, - collapsible: true, - defaultCollapsed: true, - showCopyButton: true, - description: 'Run this command to set your webhook URL in HubSpot', - mode: 'trigger', - condition: { - field: 'selectedTriggerId', - value: 'hubspot_company_created', - }, - }, - { - id: 'curlCreateSubscription', - title: '2. Create Webhook Subscription', - type: 'code', - language: 'javascript', - defaultValue: `curl -X POST "https://api.hubapi.com/webhooks/v3/{YOUR_APP_ID}/subscriptions?hapikey={YOUR_DEVELOPER_API_KEY}" \\ - -H "Content-Type: application/json" \\ - -d '{ - "eventType": "company.creation", - "active": true - }'`, - readOnly: true, - collapsible: true, - defaultCollapsed: true, - showCopyButton: true, - description: 'Run this command to subscribe to company creation events', - mode: 'trigger', - condition: { - field: 'selectedTriggerId', - value: 'hubspot_company_created', - }, - }, - { - id: 'samplePayload', - title: 'Event Payload Example', - type: 'code', - language: 'json', - defaultValue: JSON.stringify( - [ - { - eventId: 3181526815, - subscriptionId: 4629975, - portalId: 244315265, - appId: 23608917, - occurredAt: 1762659213730, - subscriptionType: 'company.creation', - attemptNumber: 0, - objectId: 316126906050, - changeFlag: 'CREATED', - changeSource: 'CRM_UI', - sourceId: 'userId:84916424', - }, - ], - null, - 2 - ), - readOnly: true, - collapsible: true, - defaultCollapsed: true, - mode: 'trigger', - condition: { - field: 'selectedTriggerId', - value: 'hubspot_company_created', - }, - }, - ], - - outputs: buildCompanyCreatedOutputs(), - - webhook: { - method: 'POST', - headers: { - 'Content-Type': 'application/json', - 'X-HubSpot-Signature': 'sha256=...', - 'X-HubSpot-Request-Id': 'xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx', - 'User-Agent': 'HubSpot Webhooks', - }, - }, -} diff --git a/apps/sim/triggers/hubspot/company_deleted.ts b/apps/sim/triggers/hubspot/company_deleted.ts deleted file mode 100644 index 07bc0026bc4..00000000000 --- a/apps/sim/triggers/hubspot/company_deleted.ts +++ /dev/null @@ -1,205 +0,0 @@ -import { HubspotIcon } from '@/components/icons' -import { - buildCompanyDeletedOutputs, - hubspotCompanyTriggerOptions, - hubspotSetupInstructions, -} from '@/triggers/hubspot/utils' -import type { TriggerConfig } from '@/triggers/types' - -export const hubspotCompanyDeletedTrigger: TriggerConfig = { - id: 'hubspot_company_deleted', - name: 'HubSpot Company Deleted', - provider: 'hubspot', - description: 'Trigger workflow when a company is deleted in HubSpot', - version: '1.0.0', - icon: HubspotIcon, - - subBlocks: [ - { - id: 'selectedTriggerId', - title: 'Trigger Type', - type: 'dropdown', - mode: 'trigger', - options: hubspotCompanyTriggerOptions, - value: () => 'hubspot_company_deleted', - required: true, - }, - { - id: 'clientId', - title: 'Client ID', - type: 'short-input', - placeholder: 'Enter your HubSpot app Client ID', - description: 'Found in your HubSpot app settings under Auth tab', - required: true, - mode: 'trigger', - condition: { - field: 'selectedTriggerId', - value: 'hubspot_company_deleted', - }, - }, - { - id: 'clientSecret', - title: 'Client Secret', - type: 'short-input', - placeholder: 'Enter your HubSpot app Client Secret', - description: 'Found in your HubSpot app settings under Auth tab', - password: true, - required: true, - mode: 'trigger', - condition: { - field: 'selectedTriggerId', - value: 'hubspot_company_deleted', - }, - }, - { - id: 'appId', - title: 'App ID', - type: 'short-input', - placeholder: 'Enter your HubSpot App ID', - description: 'Found in your HubSpot app settings. Used to identify your app.', - required: true, - mode: 'trigger', - condition: { - field: 'selectedTriggerId', - value: 'hubspot_company_deleted', - }, - }, - { - id: 'developerApiKey', - title: 'Developer API Key', - type: 'short-input', - placeholder: 'Enter your HubSpot Developer API Key', - description: 'Used for making API calls to HubSpot. Found in your HubSpot app settings.', - password: true, - required: true, - mode: 'trigger', - condition: { - field: 'selectedTriggerId', - value: 'hubspot_company_deleted', - }, - }, - { - id: 'webhookUrlDisplay', - title: 'Webhook URL', - type: 'short-input', - readOnly: true, - showCopyButton: true, - useWebhookUrl: true, - placeholder: 'Webhook URL will be generated', - description: 'Copy this URL and paste it into your HubSpot app webhook subscription settings', - mode: 'trigger', - condition: { - field: 'selectedTriggerId', - value: 'hubspot_company_deleted', - }, - }, - { - id: 'triggerInstructions', - title: 'Setup Instructions', - type: 'text', - defaultValue: hubspotSetupInstructions( - 'company.deletion', - 'The webhook will trigger whenever a company is deleted from your HubSpot account.' - ), - mode: 'trigger', - condition: { - field: 'selectedTriggerId', - value: 'hubspot_company_deleted', - }, - }, - { - id: 'curlSetWebhookUrl', - title: '1. Set Webhook Target URL', - type: 'code', - language: 'javascript', - value: (params: Record) => { - const webhookUrl = params.webhookUrlDisplay || '{YOUR_WEBHOOK_URL_FROM_ABOVE}' - return `curl -X PUT "https://api.hubapi.com/webhooks/v3/{YOUR_APP_ID}/settings?hapikey={YOUR_DEVELOPER_API_KEY}" \\ - -H "Content-Type: application/json" \\ - -d '{ - "targetUrl": "${webhookUrl}", - "throttling": { - "maxConcurrentRequests": 10 - } - }'` - }, - readOnly: true, - collapsible: true, - defaultCollapsed: true, - showCopyButton: true, - description: 'Run this command to set your webhook URL in HubSpot', - mode: 'trigger', - condition: { - field: 'selectedTriggerId', - value: 'hubspot_company_deleted', - }, - }, - { - id: 'curlCreateSubscription', - title: '2. Create Webhook Subscription', - type: 'code', - language: 'javascript', - defaultValue: `curl -X POST "https://api.hubapi.com/webhooks/v3/{YOUR_APP_ID}/subscriptions?hapikey={YOUR_DEVELOPER_API_KEY}" \\ - -H "Content-Type: application/json" \\ - -d '{ - "eventType": "company.deletion", - "active": true - }'`, - readOnly: true, - collapsible: true, - defaultCollapsed: true, - showCopyButton: true, - description: 'Run this command to subscribe to company deletion events', - mode: 'trigger', - condition: { - field: 'selectedTriggerId', - value: 'hubspot_company_deleted', - }, - }, - { - id: 'samplePayload', - title: 'Event Payload Example', - type: 'code', - language: 'json', - defaultValue: JSON.stringify( - [ - { - eventId: 3181526816, - subscriptionId: 4629976, - portalId: 244315265, - appId: 23608917, - occurredAt: 1762659213730, - subscriptionType: 'company.deletion', - attemptNumber: 0, - objectId: 316126906050, - changeFlag: 'DELETED', - changeSource: 'CRM_UI', - sourceId: 'userId:84916424', - }, - ], - null, - 2 - ), - readOnly: true, - collapsible: true, - defaultCollapsed: true, - mode: 'trigger', - condition: { - field: 'selectedTriggerId', - value: 'hubspot_company_deleted', - }, - }, - ], - - outputs: buildCompanyDeletedOutputs(), - - webhook: { - method: 'POST', - headers: { - 'Content-Type': 'application/json', - 'X-HubSpot-Signature': 'sha256=...', - 'X-HubSpot-Request-Id': 'xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx', - 'User-Agent': 'HubSpot Webhooks', - }, - }, -} diff --git a/apps/sim/triggers/hubspot/company_merged.ts b/apps/sim/triggers/hubspot/company_merged.ts deleted file mode 100644 index a524bebc2f1..00000000000 --- a/apps/sim/triggers/hubspot/company_merged.ts +++ /dev/null @@ -1,206 +0,0 @@ -import { HubspotIcon } from '@/components/icons' -import { - buildCompanyMergedOutputs, - hubspotCompanyTriggerOptions, - hubspotSetupInstructions, -} from '@/triggers/hubspot/utils' -import type { TriggerConfig } from '@/triggers/types' - -export const hubspotCompanyMergedTrigger: TriggerConfig = { - id: 'hubspot_company_merged', - name: 'HubSpot Company Merged', - provider: 'hubspot', - description: 'Trigger workflow when companies are merged in HubSpot', - version: '1.0.0', - icon: HubspotIcon, - - subBlocks: [ - { - id: 'selectedTriggerId', - title: 'Trigger Type', - type: 'dropdown', - mode: 'trigger', - options: hubspotCompanyTriggerOptions, - value: () => 'hubspot_company_merged', - required: true, - }, - { - id: 'clientId', - title: 'Client ID', - type: 'short-input', - placeholder: 'Enter your HubSpot app Client ID', - description: 'Found in your HubSpot app settings under Auth tab', - required: true, - mode: 'trigger', - condition: { - field: 'selectedTriggerId', - value: 'hubspot_company_merged', - }, - }, - { - id: 'clientSecret', - title: 'Client Secret', - type: 'short-input', - placeholder: 'Enter your HubSpot app Client Secret', - description: 'Found in your HubSpot app settings under Auth tab', - password: true, - required: true, - mode: 'trigger', - condition: { - field: 'selectedTriggerId', - value: 'hubspot_company_merged', - }, - }, - { - id: 'appId', - title: 'App ID', - type: 'short-input', - placeholder: 'Enter your HubSpot App ID', - description: 'Found in your HubSpot app settings. Used to identify your app.', - required: true, - mode: 'trigger', - condition: { - field: 'selectedTriggerId', - value: 'hubspot_company_merged', - }, - }, - { - id: 'developerApiKey', - title: 'Developer API Key', - type: 'short-input', - placeholder: 'Enter your HubSpot Developer API Key', - description: 'Used for making API calls to HubSpot. Found in your HubSpot app settings.', - password: true, - required: true, - mode: 'trigger', - condition: { - field: 'selectedTriggerId', - value: 'hubspot_company_merged', - }, - }, - { - id: 'webhookUrlDisplay', - title: 'Webhook URL', - type: 'short-input', - readOnly: true, - showCopyButton: true, - useWebhookUrl: true, - placeholder: 'Webhook URL will be generated', - description: 'Copy this URL and paste it into your HubSpot app webhook subscription settings', - mode: 'trigger', - condition: { - field: 'selectedTriggerId', - value: 'hubspot_company_merged', - }, - }, - { - id: 'triggerInstructions', - title: 'Setup Instructions', - type: 'text', - defaultValue: hubspotSetupInstructions( - 'company.merge', - 'The webhook will trigger whenever two companies are merged in your HubSpot account. The objectId will be the winning (primary) company ID.' - ), - mode: 'trigger', - condition: { - field: 'selectedTriggerId', - value: 'hubspot_company_merged', - }, - }, - { - id: 'curlSetWebhookUrl', - title: '1. Set Webhook Target URL', - type: 'code', - language: 'javascript', - value: (params: Record) => { - const webhookUrl = params.webhookUrlDisplay || '{YOUR_WEBHOOK_URL_FROM_ABOVE}' - return `curl -X PUT "https://api.hubapi.com/webhooks/v3/{YOUR_APP_ID}/settings?hapikey={YOUR_DEVELOPER_API_KEY}" \\ - -H "Content-Type: application/json" \\ - -d '{ - "targetUrl": "${webhookUrl}", - "throttling": { - "maxConcurrentRequests": 10 - } - }'` - }, - readOnly: true, - collapsible: true, - defaultCollapsed: true, - showCopyButton: true, - description: 'Run this command to set your webhook URL in HubSpot', - mode: 'trigger', - condition: { - field: 'selectedTriggerId', - value: 'hubspot_company_merged', - }, - }, - { - id: 'curlCreateSubscription', - title: '2. Create Webhook Subscription', - type: 'code', - language: 'javascript', - defaultValue: `curl -X POST "https://api.hubapi.com/webhooks/v3/{YOUR_APP_ID}/subscriptions?hapikey={YOUR_DEVELOPER_API_KEY}" \\ - -H "Content-Type: application/json" \\ - -d '{ - "eventType": "company.merge", - "active": true - }'`, - readOnly: true, - collapsible: true, - defaultCollapsed: true, - showCopyButton: true, - description: 'Run this command to subscribe to company merge events', - mode: 'trigger', - condition: { - field: 'selectedTriggerId', - value: 'hubspot_company_merged', - }, - }, - { - id: 'samplePayload', - title: 'Event Payload Example', - type: 'code', - language: 'json', - defaultValue: JSON.stringify( - [ - { - eventId: 3181526813, - subscriptionId: 4629974, - portalId: 244315265, - appId: 23608917, - occurredAt: 1762659213730, - subscriptionType: 'company.merge', - attemptNumber: 0, - objectId: 216126906049, - changeFlag: 'MERGED', - changeSource: 'CRM_UI', - sourceId: 'userId:84916424', - mergedObjectIds: [216126906050], - }, - ], - null, - 2 - ), - readOnly: true, - collapsible: true, - defaultCollapsed: true, - mode: 'trigger', - condition: { - field: 'selectedTriggerId', - value: 'hubspot_company_merged', - }, - }, - ], - - outputs: buildCompanyMergedOutputs(), - - webhook: { - method: 'POST', - headers: { - 'Content-Type': 'application/json', - 'X-HubSpot-Signature': 'sha256=...', - 'X-HubSpot-Request-Id': 'xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx', - 'User-Agent': 'HubSpot Webhooks', - }, - }, -} diff --git a/apps/sim/triggers/hubspot/company_property_changed.ts b/apps/sim/triggers/hubspot/company_property_changed.ts deleted file mode 100644 index fb6d6e156c6..00000000000 --- a/apps/sim/triggers/hubspot/company_property_changed.ts +++ /dev/null @@ -1,221 +0,0 @@ -import { HubspotIcon } from '@/components/icons' -import { - buildCompanyPropertyChangedOutputs, - hubspotCompanyTriggerOptions, - hubspotSetupInstructions, -} from '@/triggers/hubspot/utils' -import type { TriggerConfig } from '@/triggers/types' - -export const hubspotCompanyPropertyChangedTrigger: TriggerConfig = { - id: 'hubspot_company_property_changed', - name: 'HubSpot Company Property Changed', - provider: 'hubspot', - description: 'Trigger workflow when any property of a company is updated in HubSpot', - version: '1.0.0', - icon: HubspotIcon, - - subBlocks: [ - { - id: 'selectedTriggerId', - title: 'Trigger Type', - type: 'dropdown', - mode: 'trigger', - options: hubspotCompanyTriggerOptions, - value: () => 'hubspot_company_property_changed', - required: true, - }, - { - id: 'clientId', - title: 'Client ID', - type: 'short-input', - placeholder: 'Enter your HubSpot app Client ID', - description: 'Found in your HubSpot app settings under Auth tab', - required: true, - mode: 'trigger', - condition: { - field: 'selectedTriggerId', - value: 'hubspot_company_property_changed', - }, - }, - { - id: 'clientSecret', - title: 'Client Secret', - type: 'short-input', - placeholder: 'Enter your HubSpot app Client Secret', - description: 'Found in your HubSpot app settings under Auth tab', - password: true, - required: true, - mode: 'trigger', - condition: { - field: 'selectedTriggerId', - value: 'hubspot_company_property_changed', - }, - }, - { - id: 'appId', - title: 'App ID', - type: 'short-input', - placeholder: 'Enter your HubSpot App ID', - description: 'Found in your HubSpot app settings. Used to identify your app.', - required: true, - mode: 'trigger', - condition: { - field: 'selectedTriggerId', - value: 'hubspot_company_property_changed', - }, - }, - { - id: 'developerApiKey', - title: 'Developer API Key', - type: 'short-input', - placeholder: 'Enter your HubSpot Developer API Key', - description: 'Used for making API calls to HubSpot. Found in your HubSpot app settings.', - password: true, - required: true, - mode: 'trigger', - condition: { - field: 'selectedTriggerId', - value: 'hubspot_company_property_changed', - }, - }, - { - id: 'webhookUrlDisplay', - title: 'Webhook URL', - type: 'short-input', - readOnly: true, - showCopyButton: true, - useWebhookUrl: true, - placeholder: 'Webhook URL will be generated', - description: 'Copy this URL and paste it into your HubSpot app webhook subscription settings', - mode: 'trigger', - condition: { - field: 'selectedTriggerId', - value: 'hubspot_company_property_changed', - }, - }, - { - id: 'propertyName', - title: 'Property Name (Optional)', - type: 'short-input', - placeholder: 'e.g., name, domain, industry', - description: - 'Optional: Filter to only trigger when a specific property changes. Leave empty to trigger on any property change.', - required: false, - mode: 'trigger', - condition: { - field: 'selectedTriggerId', - value: 'hubspot_company_property_changed', - }, - }, - { - id: 'triggerInstructions', - title: 'Setup Instructions', - type: 'text', - defaultValue: hubspotSetupInstructions( - 'company.propertyChange', - 'The webhook will trigger whenever any property of a company is updated. You can optionally filter by a specific property name to only receive events for that property. The webhook provides both the property name and new value in the payload.' - ), - mode: 'trigger', - condition: { - field: 'selectedTriggerId', - value: 'hubspot_company_property_changed', - }, - }, - { - id: 'curlSetWebhookUrl', - title: '1. Set Webhook Target URL', - type: 'code', - language: 'javascript', - value: (params: Record) => { - const webhookUrl = params.webhookUrlDisplay || '{YOUR_WEBHOOK_URL_FROM_ABOVE}' - return `curl -X PUT "https://api.hubapi.com/webhooks/v3/{YOUR_APP_ID}/settings?hapikey={YOUR_DEVELOPER_API_KEY}" \\ - -H "Content-Type: application/json" \\ - -d '{ - "targetUrl": "${webhookUrl}", - "throttling": { - "maxConcurrentRequests": 10 - } - }'` - }, - readOnly: true, - collapsible: true, - defaultCollapsed: true, - showCopyButton: true, - description: 'Run this command to set your webhook URL in HubSpot', - mode: 'trigger', - condition: { - field: 'selectedTriggerId', - value: 'hubspot_company_property_changed', - }, - }, - { - id: 'curlCreateSubscription', - title: '2. Create Webhook Subscription', - type: 'code', - language: 'javascript', - defaultValue: `curl -X POST "https://api.hubapi.com/webhooks/v3/{YOUR_APP_ID}/subscriptions?hapikey={YOUR_DEVELOPER_API_KEY}" \\ - -H "Content-Type: application/json" \\ - -d '{ - "eventType": "company.propertyChange", - "active": true - }'`, - readOnly: true, - collapsible: true, - defaultCollapsed: true, - showCopyButton: true, - description: 'Run this command to subscribe to company property change events', - mode: 'trigger', - condition: { - field: 'selectedTriggerId', - value: 'hubspot_company_property_changed', - }, - }, - { - id: 'samplePayload', - title: 'Event Payload Example', - type: 'code', - language: 'json', - defaultValue: JSON.stringify( - [ - { - eventId: 3181526817, - subscriptionId: 4629977, - portalId: 244315265, - appId: 23608917, - occurredAt: 1762659213730, - subscriptionType: 'company.propertyChange', - attemptNumber: 0, - objectId: 316126906050, - propertyName: 'industry', - propertyValue: 'Technology', - changeFlag: 'UPDATED', - changeSource: 'CRM_UI', - sourceId: 'userId:84916424', - }, - ], - null, - 2 - ), - readOnly: true, - collapsible: true, - defaultCollapsed: true, - mode: 'trigger', - condition: { - field: 'selectedTriggerId', - value: 'hubspot_company_property_changed', - }, - }, - ], - - outputs: buildCompanyPropertyChangedOutputs(), - - webhook: { - method: 'POST', - headers: { - 'Content-Type': 'application/json', - 'X-HubSpot-Signature': 'sha256=...', - 'X-HubSpot-Request-Id': 'xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx', - 'User-Agent': 'HubSpot Webhooks', - }, - }, -} diff --git a/apps/sim/triggers/hubspot/company_restored.ts b/apps/sim/triggers/hubspot/company_restored.ts deleted file mode 100644 index e7b3b9a88d4..00000000000 --- a/apps/sim/triggers/hubspot/company_restored.ts +++ /dev/null @@ -1,205 +0,0 @@ -import { HubspotIcon } from '@/components/icons' -import { - buildCompanyRestoredOutputs, - hubspotCompanyTriggerOptions, - hubspotSetupInstructions, -} from '@/triggers/hubspot/utils' -import type { TriggerConfig } from '@/triggers/types' - -export const hubspotCompanyRestoredTrigger: TriggerConfig = { - id: 'hubspot_company_restored', - name: 'HubSpot Company Restored', - provider: 'hubspot', - description: 'Trigger workflow when a deleted company is restored in HubSpot', - version: '1.0.0', - icon: HubspotIcon, - - subBlocks: [ - { - id: 'selectedTriggerId', - title: 'Trigger Type', - type: 'dropdown', - mode: 'trigger', - options: hubspotCompanyTriggerOptions, - value: () => 'hubspot_company_restored', - required: true, - }, - { - id: 'clientId', - title: 'Client ID', - type: 'short-input', - placeholder: 'Enter your HubSpot app Client ID', - description: 'Found in your HubSpot app settings under Auth tab', - required: true, - mode: 'trigger', - condition: { - field: 'selectedTriggerId', - value: 'hubspot_company_restored', - }, - }, - { - id: 'clientSecret', - title: 'Client Secret', - type: 'short-input', - placeholder: 'Enter your HubSpot app Client Secret', - description: 'Found in your HubSpot app settings under Auth tab', - password: true, - required: true, - mode: 'trigger', - condition: { - field: 'selectedTriggerId', - value: 'hubspot_company_restored', - }, - }, - { - id: 'appId', - title: 'App ID', - type: 'short-input', - placeholder: 'Enter your HubSpot App ID', - description: 'Found in your HubSpot app settings. Used to identify your app.', - required: true, - mode: 'trigger', - condition: { - field: 'selectedTriggerId', - value: 'hubspot_company_restored', - }, - }, - { - id: 'developerApiKey', - title: 'Developer API Key', - type: 'short-input', - placeholder: 'Enter your HubSpot Developer API Key', - description: 'Used for making API calls to HubSpot. Found in your HubSpot app settings.', - password: true, - required: true, - mode: 'trigger', - condition: { - field: 'selectedTriggerId', - value: 'hubspot_company_restored', - }, - }, - { - id: 'webhookUrlDisplay', - title: 'Webhook URL', - type: 'short-input', - readOnly: true, - showCopyButton: true, - useWebhookUrl: true, - placeholder: 'Webhook URL will be generated', - description: 'Copy this URL and paste it into your HubSpot app webhook subscription settings', - mode: 'trigger', - condition: { - field: 'selectedTriggerId', - value: 'hubspot_company_restored', - }, - }, - { - id: 'triggerInstructions', - title: 'Setup Instructions', - type: 'text', - defaultValue: hubspotSetupInstructions( - 'company.restore', - 'The webhook will trigger whenever a previously deleted company is restored in your HubSpot account.' - ), - mode: 'trigger', - condition: { - field: 'selectedTriggerId', - value: 'hubspot_company_restored', - }, - }, - { - id: 'curlSetWebhookUrl', - title: '1. Set Webhook Target URL', - type: 'code', - language: 'javascript', - value: (params: Record) => { - const webhookUrl = params.webhookUrlDisplay || '{YOUR_WEBHOOK_URL_FROM_ABOVE}' - return `curl -X PUT "https://api.hubapi.com/webhooks/v3/{YOUR_APP_ID}/settings?hapikey={YOUR_DEVELOPER_API_KEY}" \\ - -H "Content-Type: application/json" \\ - -d '{ - "targetUrl": "${webhookUrl}", - "throttling": { - "maxConcurrentRequests": 10 - } - }'` - }, - readOnly: true, - collapsible: true, - defaultCollapsed: true, - showCopyButton: true, - description: 'Run this command to set your webhook URL in HubSpot', - mode: 'trigger', - condition: { - field: 'selectedTriggerId', - value: 'hubspot_company_restored', - }, - }, - { - id: 'curlCreateSubscription', - title: '2. Create Webhook Subscription', - type: 'code', - language: 'javascript', - defaultValue: `curl -X POST "https://api.hubapi.com/webhooks/v3/{YOUR_APP_ID}/subscriptions?hapikey={YOUR_DEVELOPER_API_KEY}" \\ - -H "Content-Type: application/json" \\ - -d '{ - "eventType": "company.restore", - "active": true - }'`, - readOnly: true, - collapsible: true, - defaultCollapsed: true, - showCopyButton: true, - description: 'Run this command to subscribe to company restore events', - mode: 'trigger', - condition: { - field: 'selectedTriggerId', - value: 'hubspot_company_restored', - }, - }, - { - id: 'samplePayload', - title: 'Event Payload Example', - type: 'code', - language: 'json', - defaultValue: JSON.stringify( - [ - { - eventId: 3181526814, - subscriptionId: 4629975, - portalId: 244315265, - appId: 23608917, - occurredAt: 1762659213730, - subscriptionType: 'company.restore', - attemptNumber: 0, - objectId: 216126906049, - changeFlag: 'RESTORED', - changeSource: 'CRM_UI', - sourceId: 'userId:84916424', - }, - ], - null, - 2 - ), - readOnly: true, - collapsible: true, - defaultCollapsed: true, - mode: 'trigger', - condition: { - field: 'selectedTriggerId', - value: 'hubspot_company_restored', - }, - }, - ], - - outputs: buildCompanyRestoredOutputs(), - - webhook: { - method: 'POST', - headers: { - 'Content-Type': 'application/json', - 'X-HubSpot-Signature': 'sha256=...', - 'X-HubSpot-Request-Id': 'xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx', - 'User-Agent': 'HubSpot Webhooks', - }, - }, -} diff --git a/apps/sim/triggers/hubspot/contact_created.ts b/apps/sim/triggers/hubspot/contact_created.ts deleted file mode 100644 index 854850c185d..00000000000 --- a/apps/sim/triggers/hubspot/contact_created.ts +++ /dev/null @@ -1,205 +0,0 @@ -import { HubspotIcon } from '@/components/icons' -import { - buildContactCreatedOutputs, - hubspotContactTriggerOptions, - hubspotSetupInstructions, -} from '@/triggers/hubspot/utils' -import type { TriggerConfig } from '@/triggers/types' - -export const hubspotContactCreatedTrigger: TriggerConfig = { - id: 'hubspot_contact_created', - name: 'HubSpot Contact Created', - provider: 'hubspot', - description: 'Trigger workflow when a new contact is created in HubSpot', - version: '1.0.0', - icon: HubspotIcon, - - subBlocks: [ - { - id: 'selectedTriggerId', - title: 'Trigger Type', - type: 'dropdown', - mode: 'trigger', - options: hubspotContactTriggerOptions, - value: () => 'hubspot_contact_created', - required: true, - }, - { - id: 'clientId', - title: 'Client ID', - type: 'short-input', - placeholder: 'Enter your HubSpot app Client ID', - description: 'Found in your HubSpot app settings under Auth tab', - required: true, - mode: 'trigger', - condition: { - field: 'selectedTriggerId', - value: 'hubspot_contact_created', - }, - }, - { - id: 'clientSecret', - title: 'Client Secret', - type: 'short-input', - placeholder: 'Enter your HubSpot app Client Secret', - description: 'Found in your HubSpot app settings under Auth tab', - password: true, - required: true, - mode: 'trigger', - condition: { - field: 'selectedTriggerId', - value: 'hubspot_contact_created', - }, - }, - { - id: 'appId', - title: 'App ID', - type: 'short-input', - placeholder: 'Enter your HubSpot App ID', - description: 'Found in your HubSpot app settings. Used to identify your app.', - required: true, - mode: 'trigger', - condition: { - field: 'selectedTriggerId', - value: 'hubspot_contact_created', - }, - }, - { - id: 'developerApiKey', - title: 'Developer API Key', - type: 'short-input', - placeholder: 'Enter your HubSpot Developer API Key', - description: 'Used for making API calls to HubSpot. Found in your HubSpot app settings.', - password: true, - required: true, - mode: 'trigger', - condition: { - field: 'selectedTriggerId', - value: 'hubspot_contact_created', - }, - }, - { - id: 'webhookUrlDisplay', - title: 'Webhook URL', - type: 'short-input', - readOnly: true, - showCopyButton: true, - useWebhookUrl: true, - placeholder: 'Webhook URL will be generated', - description: 'Copy this URL and paste it into your HubSpot app webhook subscription settings', - mode: 'trigger', - condition: { - field: 'selectedTriggerId', - value: 'hubspot_contact_created', - }, - }, - { - id: 'triggerInstructions', - title: 'Setup Instructions', - type: 'text', - defaultValue: hubspotSetupInstructions( - 'contact.creation', - 'The webhook will trigger whenever a new contact is created in your HubSpot account, regardless of the source (manual entry, form submission, API, import, etc.).' - ), - mode: 'trigger', - condition: { - field: 'selectedTriggerId', - value: 'hubspot_contact_created', - }, - }, - { - id: 'curlSetWebhookUrl', - title: '1. Set Webhook Target URL', - type: 'code', - language: 'javascript', - value: (params: Record) => { - const webhookUrl = params.webhookUrlDisplay || '{YOUR_WEBHOOK_URL_FROM_ABOVE}' - return `curl -X PUT "https://api.hubapi.com/webhooks/v3/{YOUR_APP_ID}/settings?hapikey={YOUR_DEVELOPER_API_KEY}" \\ - -H "Content-Type: application/json" \\ - -d '{ - "targetUrl": "${webhookUrl}", - "throttling": { - "maxConcurrentRequests": 10 - } - }'` - }, - readOnly: true, - collapsible: true, - defaultCollapsed: true, - showCopyButton: true, - description: 'Run this command to set your webhook URL in HubSpot', - mode: 'trigger', - condition: { - field: 'selectedTriggerId', - value: 'hubspot_contact_created', - }, - }, - { - id: 'curlCreateSubscription', - title: '2. Create Webhook Subscription', - type: 'code', - language: 'javascript', - defaultValue: `curl -X POST "https://api.hubapi.com/webhooks/v3/{YOUR_APP_ID}/subscriptions?hapikey={YOUR_DEVELOPER_API_KEY}" \\ - -H "Content-Type: application/json" \\ - -d '{ - "eventType": "contact.creation", - "active": true - }'`, - readOnly: true, - collapsible: true, - defaultCollapsed: true, - showCopyButton: true, - description: 'Run this command to subscribe to contact creation events', - mode: 'trigger', - condition: { - field: 'selectedTriggerId', - value: 'hubspot_contact_created', - }, - }, - { - id: 'samplePayload', - title: 'Event Payload Example', - type: 'code', - language: 'json', - defaultValue: JSON.stringify( - [ - { - eventId: 3181526809, - subscriptionId: 4629970, - portalId: 244315265, - appId: 23608917, - occurredAt: 1762659213730, - subscriptionType: 'contact.creation', - attemptNumber: 0, - objectId: 316126906049, - changeFlag: 'CREATED', - changeSource: 'CRM_UI', - sourceId: 'userId:84916424', - }, - ], - null, - 2 - ), - readOnly: true, - collapsible: true, - defaultCollapsed: true, - mode: 'trigger', - condition: { - field: 'selectedTriggerId', - value: 'hubspot_contact_created', - }, - }, - ], - - outputs: buildContactCreatedOutputs(), - - webhook: { - method: 'POST', - headers: { - 'Content-Type': 'application/json', - 'X-HubSpot-Signature': 'sha256=...', - 'X-HubSpot-Request-Id': 'xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx', - 'User-Agent': 'HubSpot Webhooks', - }, - }, -} diff --git a/apps/sim/triggers/hubspot/contact_deleted.ts b/apps/sim/triggers/hubspot/contact_deleted.ts deleted file mode 100644 index fb0aa85f7c8..00000000000 --- a/apps/sim/triggers/hubspot/contact_deleted.ts +++ /dev/null @@ -1,205 +0,0 @@ -import { HubspotIcon } from '@/components/icons' -import { - buildContactDeletedOutputs, - hubspotContactTriggerOptions, - hubspotSetupInstructions, -} from '@/triggers/hubspot/utils' -import type { TriggerConfig } from '@/triggers/types' - -export const hubspotContactDeletedTrigger: TriggerConfig = { - id: 'hubspot_contact_deleted', - name: 'HubSpot Contact Deleted', - provider: 'hubspot', - description: 'Trigger workflow when a contact is deleted in HubSpot', - version: '1.0.0', - icon: HubspotIcon, - - subBlocks: [ - { - id: 'selectedTriggerId', - title: 'Trigger Type', - type: 'dropdown', - mode: 'trigger', - options: hubspotContactTriggerOptions, - value: () => 'hubspot_contact_deleted', - required: true, - }, - { - id: 'clientId', - title: 'Client ID', - type: 'short-input', - placeholder: 'Enter your HubSpot app Client ID', - description: 'Found in your HubSpot app settings under Auth tab', - required: true, - mode: 'trigger', - condition: { - field: 'selectedTriggerId', - value: 'hubspot_contact_deleted', - }, - }, - { - id: 'clientSecret', - title: 'Client Secret', - type: 'short-input', - placeholder: 'Enter your HubSpot app Client Secret', - description: 'Found in your HubSpot app settings under Auth tab', - password: true, - required: true, - mode: 'trigger', - condition: { - field: 'selectedTriggerId', - value: 'hubspot_contact_deleted', - }, - }, - { - id: 'appId', - title: 'App ID', - type: 'short-input', - placeholder: 'Enter your HubSpot App ID', - description: 'Found in your HubSpot app settings. Used to identify your app.', - required: true, - mode: 'trigger', - condition: { - field: 'selectedTriggerId', - value: 'hubspot_contact_deleted', - }, - }, - { - id: 'developerApiKey', - title: 'Developer API Key', - type: 'short-input', - placeholder: 'Enter your HubSpot Developer API Key', - description: 'Used for making API calls to HubSpot. Found in your HubSpot app settings.', - password: true, - required: true, - mode: 'trigger', - condition: { - field: 'selectedTriggerId', - value: 'hubspot_contact_deleted', - }, - }, - { - id: 'webhookUrlDisplay', - title: 'Webhook URL', - type: 'short-input', - readOnly: true, - showCopyButton: true, - useWebhookUrl: true, - placeholder: 'Webhook URL will be generated', - description: 'Copy this URL and paste it into your HubSpot app webhook subscription settings', - mode: 'trigger', - condition: { - field: 'selectedTriggerId', - value: 'hubspot_contact_deleted', - }, - }, - { - id: 'triggerInstructions', - title: 'Setup Instructions', - type: 'text', - defaultValue: hubspotSetupInstructions( - 'contact.deletion', - 'The webhook will trigger whenever a contact is deleted from your HubSpot account. Note: This does not include privacy deletions (GDPR compliance), which have a separate trigger.' - ), - mode: 'trigger', - condition: { - field: 'selectedTriggerId', - value: 'hubspot_contact_deleted', - }, - }, - { - id: 'curlSetWebhookUrl', - title: '1. Set Webhook Target URL', - type: 'code', - language: 'javascript', - value: (params: Record) => { - const webhookUrl = params.webhookUrlDisplay || '{YOUR_WEBHOOK_URL_FROM_ABOVE}' - return `curl -X PUT "https://api.hubapi.com/webhooks/v3/{YOUR_APP_ID}/settings?hapikey={YOUR_DEVELOPER_API_KEY}" \\ - -H "Content-Type: application/json" \\ - -d '{ - "targetUrl": "${webhookUrl}", - "throttling": { - "maxConcurrentRequests": 10 - } - }'` - }, - readOnly: true, - collapsible: true, - defaultCollapsed: true, - showCopyButton: true, - description: 'Run this command to set your webhook URL in HubSpot', - mode: 'trigger', - condition: { - field: 'selectedTriggerId', - value: 'hubspot_contact_deleted', - }, - }, - { - id: 'curlCreateSubscription', - title: '2. Create Webhook Subscription', - type: 'code', - language: 'javascript', - defaultValue: `curl -X POST "https://api.hubapi.com/webhooks/v3/{YOUR_APP_ID}/subscriptions?hapikey={YOUR_DEVELOPER_API_KEY}" \\ - -H "Content-Type: application/json" \\ - -d '{ - "eventType": "contact.deletion", - "active": true - }'`, - readOnly: true, - collapsible: true, - defaultCollapsed: true, - showCopyButton: true, - description: 'Run this command to subscribe to contact deletion events', - mode: 'trigger', - condition: { - field: 'selectedTriggerId', - value: 'hubspot_contact_deleted', - }, - }, - { - id: 'samplePayload', - title: 'Event Payload Example', - type: 'code', - language: 'json', - defaultValue: JSON.stringify( - [ - { - eventId: 3181526810, - subscriptionId: 4629971, - portalId: 244315265, - appId: 23608917, - occurredAt: 1762659213730, - subscriptionType: 'contact.deletion', - attemptNumber: 0, - objectId: 316126906049, - changeFlag: 'DELETED', - changeSource: 'CRM_UI', - sourceId: 'userId:84916424', - }, - ], - null, - 2 - ), - readOnly: true, - collapsible: true, - defaultCollapsed: true, - mode: 'trigger', - condition: { - field: 'selectedTriggerId', - value: 'hubspot_contact_deleted', - }, - }, - ], - - outputs: buildContactDeletedOutputs(), - - webhook: { - method: 'POST', - headers: { - 'Content-Type': 'application/json', - 'X-HubSpot-Signature': 'sha256=...', - 'X-HubSpot-Request-Id': 'xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx', - 'User-Agent': 'HubSpot Webhooks', - }, - }, -} diff --git a/apps/sim/triggers/hubspot/contact_merged.ts b/apps/sim/triggers/hubspot/contact_merged.ts deleted file mode 100644 index 125121f7442..00000000000 --- a/apps/sim/triggers/hubspot/contact_merged.ts +++ /dev/null @@ -1,206 +0,0 @@ -import { HubspotIcon } from '@/components/icons' -import { - buildContactMergedOutputs, - hubspotContactTriggerOptions, - hubspotSetupInstructions, -} from '@/triggers/hubspot/utils' -import type { TriggerConfig } from '@/triggers/types' - -export const hubspotContactMergedTrigger: TriggerConfig = { - id: 'hubspot_contact_merged', - name: 'HubSpot Contact Merged', - provider: 'hubspot', - description: 'Trigger workflow when contacts are merged in HubSpot', - version: '1.0.0', - icon: HubspotIcon, - - subBlocks: [ - { - id: 'selectedTriggerId', - title: 'Trigger Type', - type: 'dropdown', - mode: 'trigger', - options: hubspotContactTriggerOptions, - value: () => 'hubspot_contact_merged', - required: true, - }, - { - id: 'clientId', - title: 'Client ID', - type: 'short-input', - placeholder: 'Enter your HubSpot app Client ID', - description: 'Found in your HubSpot app settings under Auth tab', - required: true, - mode: 'trigger', - condition: { - field: 'selectedTriggerId', - value: 'hubspot_contact_merged', - }, - }, - { - id: 'clientSecret', - title: 'Client Secret', - type: 'short-input', - placeholder: 'Enter your HubSpot app Client Secret', - description: 'Found in your HubSpot app settings under Auth tab', - password: true, - required: true, - mode: 'trigger', - condition: { - field: 'selectedTriggerId', - value: 'hubspot_contact_merged', - }, - }, - { - id: 'appId', - title: 'App ID', - type: 'short-input', - placeholder: 'Enter your HubSpot App ID', - description: 'Found in your HubSpot app settings. Used to identify your app.', - required: true, - mode: 'trigger', - condition: { - field: 'selectedTriggerId', - value: 'hubspot_contact_merged', - }, - }, - { - id: 'developerApiKey', - title: 'Developer API Key', - type: 'short-input', - placeholder: 'Enter your HubSpot Developer API Key', - description: 'Used for making API calls to HubSpot. Found in your HubSpot app settings.', - password: true, - required: true, - mode: 'trigger', - condition: { - field: 'selectedTriggerId', - value: 'hubspot_contact_merged', - }, - }, - { - id: 'webhookUrlDisplay', - title: 'Webhook URL', - type: 'short-input', - readOnly: true, - showCopyButton: true, - useWebhookUrl: true, - placeholder: 'Webhook URL will be generated', - description: 'Copy this URL and paste it into your HubSpot app webhook subscription settings', - mode: 'trigger', - condition: { - field: 'selectedTriggerId', - value: 'hubspot_contact_merged', - }, - }, - { - id: 'triggerInstructions', - title: 'Setup Instructions', - type: 'text', - defaultValue: hubspotSetupInstructions( - 'contact.merge', - 'The webhook will trigger whenever two contacts are merged in your HubSpot account. The objectId will be the winning (primary) contact ID.' - ), - mode: 'trigger', - condition: { - field: 'selectedTriggerId', - value: 'hubspot_contact_merged', - }, - }, - { - id: 'curlSetWebhookUrl', - title: '1. Set Webhook Target URL', - type: 'code', - language: 'javascript', - value: (params: Record) => { - const webhookUrl = params.webhookUrlDisplay || '{YOUR_WEBHOOK_URL_FROM_ABOVE}' - return `curl -X PUT "https://api.hubapi.com/webhooks/v3/{YOUR_APP_ID}/settings?hapikey={YOUR_DEVELOPER_API_KEY}" \\ - -H "Content-Type: application/json" \\ - -d '{ - "targetUrl": "${webhookUrl}", - "throttling": { - "maxConcurrentRequests": 10 - } - }'` - }, - readOnly: true, - collapsible: true, - defaultCollapsed: true, - showCopyButton: true, - description: 'Run this command to set your webhook URL in HubSpot', - mode: 'trigger', - condition: { - field: 'selectedTriggerId', - value: 'hubspot_contact_merged', - }, - }, - { - id: 'curlCreateSubscription', - title: '2. Create Webhook Subscription', - type: 'code', - language: 'javascript', - defaultValue: `curl -X POST "https://api.hubapi.com/webhooks/v3/{YOUR_APP_ID}/subscriptions?hapikey={YOUR_DEVELOPER_API_KEY}" \\ - -H "Content-Type: application/json" \\ - -d '{ - "eventType": "contact.merge", - "active": true - }'`, - readOnly: true, - collapsible: true, - defaultCollapsed: true, - showCopyButton: true, - description: 'Run this command to subscribe to contact merge events', - mode: 'trigger', - condition: { - field: 'selectedTriggerId', - value: 'hubspot_contact_merged', - }, - }, - { - id: 'samplePayload', - title: 'Event Payload Example', - type: 'code', - language: 'json', - defaultValue: JSON.stringify( - [ - { - eventId: 3181526811, - subscriptionId: 4629972, - portalId: 244315265, - appId: 23608917, - occurredAt: 1762659213730, - subscriptionType: 'contact.merge', - attemptNumber: 0, - objectId: 316126906049, - changeFlag: 'MERGED', - changeSource: 'CRM_UI', - sourceId: 'userId:84916424', - mergedObjectIds: [316126906050], - }, - ], - null, - 2 - ), - readOnly: true, - collapsible: true, - defaultCollapsed: true, - mode: 'trigger', - condition: { - field: 'selectedTriggerId', - value: 'hubspot_contact_merged', - }, - }, - ], - - outputs: buildContactMergedOutputs(), - - webhook: { - method: 'POST', - headers: { - 'Content-Type': 'application/json', - 'X-HubSpot-Signature': 'sha256=...', - 'X-HubSpot-Request-Id': 'xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx', - 'User-Agent': 'HubSpot Webhooks', - }, - }, -} diff --git a/apps/sim/triggers/hubspot/contact_privacy_deleted.ts b/apps/sim/triggers/hubspot/contact_privacy_deleted.ts deleted file mode 100644 index 10fd627e200..00000000000 --- a/apps/sim/triggers/hubspot/contact_privacy_deleted.ts +++ /dev/null @@ -1,205 +0,0 @@ -import { HubspotIcon } from '@/components/icons' -import { - buildContactPrivacyDeletedOutputs, - hubspotContactTriggerOptions, - hubspotSetupInstructions, -} from '@/triggers/hubspot/utils' -import type { TriggerConfig } from '@/triggers/types' - -export const hubspotContactPrivacyDeletedTrigger: TriggerConfig = { - id: 'hubspot_contact_privacy_deleted', - name: 'HubSpot Contact Privacy Deleted', - provider: 'hubspot', - description: - 'Trigger workflow when a contact is deleted for privacy compliance (GDPR, CCPA, etc.) in HubSpot', - version: '1.0.0', - icon: HubspotIcon, - - subBlocks: [ - { - id: 'selectedTriggerId', - title: 'Trigger Type', - type: 'dropdown', - mode: 'trigger', - options: hubspotContactTriggerOptions, - value: () => 'hubspot_contact_privacy_deleted', - required: true, - }, - { - id: 'clientId', - title: 'Client ID', - type: 'short-input', - placeholder: 'Enter your HubSpot app Client ID', - description: 'Found in your HubSpot app settings under Auth tab', - required: true, - mode: 'trigger', - condition: { - field: 'selectedTriggerId', - value: 'hubspot_contact_privacy_deleted', - }, - }, - { - id: 'clientSecret', - title: 'Client Secret', - type: 'short-input', - placeholder: 'Enter your HubSpot app Client Secret', - description: 'Found in your HubSpot app settings under Auth tab', - password: true, - required: true, - mode: 'trigger', - condition: { - field: 'selectedTriggerId', - value: 'hubspot_contact_privacy_deleted', - }, - }, - { - id: 'appId', - title: 'App ID', - type: 'short-input', - placeholder: 'Enter your HubSpot App ID', - description: 'Found in your HubSpot app settings. Used to identify your app.', - required: true, - mode: 'trigger', - condition: { - field: 'selectedTriggerId', - value: 'hubspot_contact_privacy_deleted', - }, - }, - { - id: 'developerApiKey', - title: 'Developer API Key', - type: 'short-input', - placeholder: 'Enter your HubSpot Developer API Key', - description: 'Used for making API calls to HubSpot. Found in your HubSpot app settings.', - password: true, - required: true, - mode: 'trigger', - condition: { - field: 'selectedTriggerId', - value: 'hubspot_contact_privacy_deleted', - }, - }, - { - id: 'webhookUrlDisplay', - title: 'Webhook URL', - type: 'short-input', - readOnly: true, - showCopyButton: true, - useWebhookUrl: true, - placeholder: 'Webhook URL will be generated', - description: 'Copy this URL and paste it into your HubSpot app webhook subscription settings', - mode: 'trigger', - condition: { - field: 'selectedTriggerId', - value: 'hubspot_contact_privacy_deleted', - }, - }, - { - id: 'triggerInstructions', - title: 'Setup Instructions', - type: 'text', - defaultValue: hubspotSetupInstructions( - 'contact.privacyDeletion', - 'The webhook will trigger when a contact is deleted specifically for privacy compliance reasons (e.g., GDPR "right to be forgotten" requests). This is different from regular contact deletions and is used to track data privacy compliance actions.' - ), - mode: 'trigger', - condition: { - field: 'selectedTriggerId', - value: 'hubspot_contact_privacy_deleted', - }, - }, - { - id: 'curlSetWebhookUrl', - title: '1. Set Webhook Target URL', - type: 'code', - language: 'javascript', - value: (params: Record) => { - const webhookUrl = params.webhookUrlDisplay || '{YOUR_WEBHOOK_URL_FROM_ABOVE}' - return `curl -X PUT "https://api.hubapi.com/webhooks/v3/{YOUR_APP_ID}/settings?hapikey={YOUR_DEVELOPER_API_KEY}" \\ - -H "Content-Type: application/json" \\ - -d '{ - "targetUrl": "${webhookUrl}", - "throttling": { - "maxConcurrentRequests": 10 - } - }'` - }, - readOnly: true, - collapsible: true, - defaultCollapsed: true, - showCopyButton: true, - description: 'Run this command to set your webhook URL in HubSpot', - mode: 'trigger', - condition: { - field: 'selectedTriggerId', - value: 'hubspot_contact_privacy_deleted', - }, - }, - { - id: 'curlCreateSubscription', - title: '2. Create Webhook Subscription', - type: 'code', - language: 'javascript', - defaultValue: `curl -X POST "https://api.hubapi.com/webhooks/v3/{YOUR_APP_ID}/subscriptions?hapikey={YOUR_DEVELOPER_API_KEY}" \\ - -H "Content-Type: application/json" \\ - -d '{ - "eventType": "contact.privacyDeletion", - "active": true - }'`, - readOnly: true, - collapsible: true, - defaultCollapsed: true, - showCopyButton: true, - description: 'Run this command to subscribe to contact privacy deletion events', - mode: 'trigger', - condition: { - field: 'selectedTriggerId', - value: 'hubspot_contact_privacy_deleted', - }, - }, - { - id: 'samplePayload', - title: 'Event Payload Example', - type: 'code', - language: 'json', - defaultValue: JSON.stringify( - [ - { - eventId: 3181526811, - subscriptionId: 4629972, - portalId: 244315265, - appId: 23608917, - occurredAt: 1762659213730, - subscriptionType: 'contact.privacyDeletion', - attemptNumber: 0, - objectId: 316126906049, - changeFlag: 'PRIVACY_DELETED', - changeSource: 'GDPR', - }, - ], - null, - 2 - ), - readOnly: true, - collapsible: true, - defaultCollapsed: true, - mode: 'trigger', - condition: { - field: 'selectedTriggerId', - value: 'hubspot_contact_privacy_deleted', - }, - }, - ], - - outputs: buildContactPrivacyDeletedOutputs(), - - webhook: { - method: 'POST', - headers: { - 'Content-Type': 'application/json', - 'X-HubSpot-Signature': 'sha256=...', - 'X-HubSpot-Request-Id': 'xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx', - 'User-Agent': 'HubSpot Webhooks', - }, - }, -} diff --git a/apps/sim/triggers/hubspot/contact_property_changed.ts b/apps/sim/triggers/hubspot/contact_property_changed.ts deleted file mode 100644 index f68ef966fbc..00000000000 --- a/apps/sim/triggers/hubspot/contact_property_changed.ts +++ /dev/null @@ -1,221 +0,0 @@ -import { HubspotIcon } from '@/components/icons' -import { - buildContactPropertyChangedOutputs, - hubspotContactTriggerOptions, - hubspotSetupInstructions, -} from '@/triggers/hubspot/utils' -import type { TriggerConfig } from '@/triggers/types' - -export const hubspotContactPropertyChangedTrigger: TriggerConfig = { - id: 'hubspot_contact_property_changed', - name: 'HubSpot Contact Property Changed', - provider: 'hubspot', - description: 'Trigger workflow when any property of a contact is updated in HubSpot', - version: '1.0.0', - icon: HubspotIcon, - - subBlocks: [ - { - id: 'selectedTriggerId', - title: 'Trigger Type', - type: 'dropdown', - mode: 'trigger', - options: hubspotContactTriggerOptions, - value: () => 'hubspot_contact_property_changed', - required: true, - }, - { - id: 'clientId', - title: 'Client ID', - type: 'short-input', - placeholder: 'Enter your HubSpot app Client ID', - description: 'Found in your HubSpot app settings under Auth tab', - required: true, - mode: 'trigger', - condition: { - field: 'selectedTriggerId', - value: 'hubspot_contact_property_changed', - }, - }, - { - id: 'clientSecret', - title: 'Client Secret', - type: 'short-input', - placeholder: 'Enter your HubSpot app Client Secret', - description: 'Found in your HubSpot app settings under Auth tab', - password: true, - required: true, - mode: 'trigger', - condition: { - field: 'selectedTriggerId', - value: 'hubspot_contact_property_changed', - }, - }, - { - id: 'appId', - title: 'App ID', - type: 'short-input', - placeholder: 'Enter your HubSpot App ID', - description: 'Found in your HubSpot app settings. Used to identify your app.', - required: true, - mode: 'trigger', - condition: { - field: 'selectedTriggerId', - value: 'hubspot_contact_property_changed', - }, - }, - { - id: 'developerApiKey', - title: 'Developer API Key', - type: 'short-input', - placeholder: 'Enter your HubSpot Developer API Key', - description: 'Used for making API calls to HubSpot. Found in your HubSpot app settings.', - password: true, - required: true, - mode: 'trigger', - condition: { - field: 'selectedTriggerId', - value: 'hubspot_contact_property_changed', - }, - }, - { - id: 'webhookUrlDisplay', - title: 'Webhook URL', - type: 'short-input', - readOnly: true, - showCopyButton: true, - useWebhookUrl: true, - placeholder: 'Webhook URL will be generated', - description: 'Copy this URL and paste it into your HubSpot app webhook subscription settings', - mode: 'trigger', - condition: { - field: 'selectedTriggerId', - value: 'hubspot_contact_property_changed', - }, - }, - { - id: 'propertyName', - title: 'Property Name (Optional)', - type: 'short-input', - placeholder: 'e.g., email, firstname, lifecyclestage', - description: - 'Optional: Filter to only trigger when a specific property changes. Leave empty to trigger on any property change.', - required: false, - mode: 'trigger', - condition: { - field: 'selectedTriggerId', - value: 'hubspot_contact_property_changed', - }, - }, - { - id: 'triggerInstructions', - title: 'Setup Instructions', - type: 'text', - defaultValue: hubspotSetupInstructions( - 'contact.propertyChange', - 'The webhook will trigger whenever any property of a contact is updated. You can optionally filter by a specific property name to only receive events for that property. The webhook provides both the property name and new value in the payload.' - ), - mode: 'trigger', - condition: { - field: 'selectedTriggerId', - value: 'hubspot_contact_property_changed', - }, - }, - { - id: 'curlSetWebhookUrl', - title: '1. Set Webhook Target URL', - type: 'code', - language: 'javascript', - value: (params: Record) => { - const webhookUrl = params.webhookUrlDisplay || '{YOUR_WEBHOOK_URL_FROM_ABOVE}' - return `curl -X PUT "https://api.hubapi.com/webhooks/v3/{YOUR_APP_ID}/settings?hapikey={YOUR_DEVELOPER_API_KEY}" \\ - -H "Content-Type: application/json" \\ - -d '{ - "targetUrl": "${webhookUrl}", - "throttling": { - "maxConcurrentRequests": 10 - } - }'` - }, - readOnly: true, - collapsible: true, - defaultCollapsed: true, - showCopyButton: true, - description: 'Run this command to set your webhook URL in HubSpot', - mode: 'trigger', - condition: { - field: 'selectedTriggerId', - value: 'hubspot_contact_property_changed', - }, - }, - { - id: 'curlCreateSubscription', - title: '2. Create Webhook Subscription', - type: 'code', - language: 'javascript', - defaultValue: `curl -X POST "https://api.hubapi.com/webhooks/v3/{YOUR_APP_ID}/subscriptions?hapikey={YOUR_DEVELOPER_API_KEY}" \\ - -H "Content-Type: application/json" \\ - -d '{ - "eventType": "contact.propertyChange", - "active": true - }'`, - readOnly: true, - collapsible: true, - defaultCollapsed: true, - showCopyButton: true, - description: 'Run this command to subscribe to contact property change events', - mode: 'trigger', - condition: { - field: 'selectedTriggerId', - value: 'hubspot_contact_property_changed', - }, - }, - { - id: 'samplePayload', - title: 'Event Payload Example', - type: 'code', - language: 'json', - defaultValue: JSON.stringify( - [ - { - eventId: 3181526812, - subscriptionId: 4629973, - portalId: 244315265, - appId: 23608917, - occurredAt: 1762659213730, - subscriptionType: 'contact.propertyChange', - attemptNumber: 0, - objectId: 316126906049, - propertyName: 'lifecyclestage', - propertyValue: 'customer', - changeFlag: 'UPDATED', - changeSource: 'WORKFLOW', - sourceId: 'workflow_456', - }, - ], - null, - 2 - ), - readOnly: true, - collapsible: true, - defaultCollapsed: true, - mode: 'trigger', - condition: { - field: 'selectedTriggerId', - value: 'hubspot_contact_property_changed', - }, - }, - ], - - outputs: buildContactPropertyChangedOutputs(), - - webhook: { - method: 'POST', - headers: { - 'Content-Type': 'application/json', - 'X-HubSpot-Signature': 'sha256=...', - 'X-HubSpot-Request-Id': 'xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx', - 'User-Agent': 'HubSpot Webhooks', - }, - }, -} diff --git a/apps/sim/triggers/hubspot/contact_restored.ts b/apps/sim/triggers/hubspot/contact_restored.ts deleted file mode 100644 index e8c02123aa4..00000000000 --- a/apps/sim/triggers/hubspot/contact_restored.ts +++ /dev/null @@ -1,205 +0,0 @@ -import { HubspotIcon } from '@/components/icons' -import { - buildContactRestoredOutputs, - hubspotContactTriggerOptions, - hubspotSetupInstructions, -} from '@/triggers/hubspot/utils' -import type { TriggerConfig } from '@/triggers/types' - -export const hubspotContactRestoredTrigger: TriggerConfig = { - id: 'hubspot_contact_restored', - name: 'HubSpot Contact Restored', - provider: 'hubspot', - description: 'Trigger workflow when a deleted contact is restored in HubSpot', - version: '1.0.0', - icon: HubspotIcon, - - subBlocks: [ - { - id: 'selectedTriggerId', - title: 'Trigger Type', - type: 'dropdown', - mode: 'trigger', - options: hubspotContactTriggerOptions, - value: () => 'hubspot_contact_restored', - required: true, - }, - { - id: 'clientId', - title: 'Client ID', - type: 'short-input', - placeholder: 'Enter your HubSpot app Client ID', - description: 'Found in your HubSpot app settings under Auth tab', - required: true, - mode: 'trigger', - condition: { - field: 'selectedTriggerId', - value: 'hubspot_contact_restored', - }, - }, - { - id: 'clientSecret', - title: 'Client Secret', - type: 'short-input', - placeholder: 'Enter your HubSpot app Client Secret', - description: 'Found in your HubSpot app settings under Auth tab', - password: true, - required: true, - mode: 'trigger', - condition: { - field: 'selectedTriggerId', - value: 'hubspot_contact_restored', - }, - }, - { - id: 'appId', - title: 'App ID', - type: 'short-input', - placeholder: 'Enter your HubSpot App ID', - description: 'Found in your HubSpot app settings. Used to identify your app.', - required: true, - mode: 'trigger', - condition: { - field: 'selectedTriggerId', - value: 'hubspot_contact_restored', - }, - }, - { - id: 'developerApiKey', - title: 'Developer API Key', - type: 'short-input', - placeholder: 'Enter your HubSpot Developer API Key', - description: 'Used for making API calls to HubSpot. Found in your HubSpot app settings.', - password: true, - required: true, - mode: 'trigger', - condition: { - field: 'selectedTriggerId', - value: 'hubspot_contact_restored', - }, - }, - { - id: 'webhookUrlDisplay', - title: 'Webhook URL', - type: 'short-input', - readOnly: true, - showCopyButton: true, - useWebhookUrl: true, - placeholder: 'Webhook URL will be generated', - description: 'Copy this URL and paste it into your HubSpot app webhook subscription settings', - mode: 'trigger', - condition: { - field: 'selectedTriggerId', - value: 'hubspot_contact_restored', - }, - }, - { - id: 'triggerInstructions', - title: 'Setup Instructions', - type: 'text', - defaultValue: hubspotSetupInstructions( - 'contact.restore', - 'The webhook will trigger whenever a previously deleted contact is restored in your HubSpot account.' - ), - mode: 'trigger', - condition: { - field: 'selectedTriggerId', - value: 'hubspot_contact_restored', - }, - }, - { - id: 'curlSetWebhookUrl', - title: '1. Set Webhook Target URL', - type: 'code', - language: 'javascript', - value: (params: Record) => { - const webhookUrl = params.webhookUrlDisplay || '{YOUR_WEBHOOK_URL_FROM_ABOVE}' - return `curl -X PUT "https://api.hubapi.com/webhooks/v3/{YOUR_APP_ID}/settings?hapikey={YOUR_DEVELOPER_API_KEY}" \\ - -H "Content-Type: application/json" \\ - -d '{ - "targetUrl": "${webhookUrl}", - "throttling": { - "maxConcurrentRequests": 10 - } - }'` - }, - readOnly: true, - collapsible: true, - defaultCollapsed: true, - showCopyButton: true, - description: 'Run this command to set your webhook URL in HubSpot', - mode: 'trigger', - condition: { - field: 'selectedTriggerId', - value: 'hubspot_contact_restored', - }, - }, - { - id: 'curlCreateSubscription', - title: '2. Create Webhook Subscription', - type: 'code', - language: 'javascript', - defaultValue: `curl -X POST "https://api.hubapi.com/webhooks/v3/{YOUR_APP_ID}/subscriptions?hapikey={YOUR_DEVELOPER_API_KEY}" \\ - -H "Content-Type: application/json" \\ - -d '{ - "eventType": "contact.restore", - "active": true - }'`, - readOnly: true, - collapsible: true, - defaultCollapsed: true, - showCopyButton: true, - description: 'Run this command to subscribe to contact restore events', - mode: 'trigger', - condition: { - field: 'selectedTriggerId', - value: 'hubspot_contact_restored', - }, - }, - { - id: 'samplePayload', - title: 'Event Payload Example', - type: 'code', - language: 'json', - defaultValue: JSON.stringify( - [ - { - eventId: 3181526812, - subscriptionId: 4629973, - portalId: 244315265, - appId: 23608917, - occurredAt: 1762659213730, - subscriptionType: 'contact.restore', - attemptNumber: 0, - objectId: 316126906049, - changeFlag: 'RESTORED', - changeSource: 'CRM_UI', - sourceId: 'userId:84916424', - }, - ], - null, - 2 - ), - readOnly: true, - collapsible: true, - defaultCollapsed: true, - mode: 'trigger', - condition: { - field: 'selectedTriggerId', - value: 'hubspot_contact_restored', - }, - }, - ], - - outputs: buildContactRestoredOutputs(), - - webhook: { - method: 'POST', - headers: { - 'Content-Type': 'application/json', - 'X-HubSpot-Signature': 'sha256=...', - 'X-HubSpot-Request-Id': 'xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx', - 'User-Agent': 'HubSpot Webhooks', - }, - }, -} diff --git a/apps/sim/triggers/hubspot/conversation_creation.ts b/apps/sim/triggers/hubspot/conversation_creation.ts deleted file mode 100644 index 6cc12b3965c..00000000000 --- a/apps/sim/triggers/hubspot/conversation_creation.ts +++ /dev/null @@ -1,204 +0,0 @@ -import { HubspotIcon } from '@/components/icons' -import { - buildConversationCreationOutputs, - hubspotConversationTriggerOptions, - hubspotSetupInstructions, -} from '@/triggers/hubspot/utils' -import type { TriggerConfig } from '@/triggers/types' - -export const hubspotConversationCreationTrigger: TriggerConfig = { - id: 'hubspot_conversation_creation', - name: 'HubSpot Conversation Creation', - provider: 'hubspot', - description: 'Trigger workflow when a new conversation is created in HubSpot', - version: '1.0.0', - icon: HubspotIcon, - - subBlocks: [ - { - id: 'selectedTriggerId', - title: 'Trigger Type', - type: 'dropdown', - mode: 'trigger', - options: hubspotConversationTriggerOptions, - value: () => 'hubspot_conversation_creation', - required: true, - }, - { - id: 'clientId', - title: 'Client ID', - type: 'short-input', - placeholder: 'Enter your HubSpot app Client ID', - description: 'Found in your HubSpot app settings under Auth tab', - required: true, - mode: 'trigger', - condition: { - field: 'selectedTriggerId', - value: 'hubspot_conversation_creation', - }, - }, - { - id: 'clientSecret', - title: 'Client Secret', - type: 'short-input', - placeholder: 'Enter your HubSpot app Client Secret', - description: 'Found in your HubSpot app settings under Auth tab', - password: true, - required: true, - mode: 'trigger', - condition: { - field: 'selectedTriggerId', - value: 'hubspot_conversation_creation', - }, - }, - { - id: 'appId', - title: 'App ID', - type: 'short-input', - placeholder: 'Enter your HubSpot App ID', - description: 'Found in your HubSpot app settings. Used to identify your app.', - required: true, - mode: 'trigger', - condition: { - field: 'selectedTriggerId', - value: 'hubspot_conversation_creation', - }, - }, - { - id: 'developerApiKey', - title: 'Developer API Key', - type: 'short-input', - placeholder: 'Enter your HubSpot Developer API Key', - description: 'Used for making API calls to HubSpot. Found in your HubSpot app settings.', - password: true, - required: true, - mode: 'trigger', - condition: { - field: 'selectedTriggerId', - value: 'hubspot_conversation_creation', - }, - }, - { - id: 'webhookUrlDisplay', - title: 'Webhook URL', - type: 'short-input', - readOnly: true, - showCopyButton: true, - useWebhookUrl: true, - placeholder: 'Webhook URL will be generated', - description: 'Copy this URL and paste it into your HubSpot app webhook subscription settings', - mode: 'trigger', - condition: { - field: 'selectedTriggerId', - value: 'hubspot_conversation_creation', - }, - }, - { - id: 'triggerInstructions', - title: 'Setup Instructions', - type: 'text', - defaultValue: hubspotSetupInstructions( - 'conversation.creation', - 'The webhook will trigger whenever a new conversation is created in your HubSpot account, such as when a new email thread starts or a chat conversation begins.' - ), - mode: 'trigger', - condition: { - field: 'selectedTriggerId', - value: 'hubspot_conversation_creation', - }, - }, - { - id: 'curlSetWebhookUrl', - title: '1. Set Webhook Target URL', - type: 'code', - language: 'javascript', - value: (params: Record) => { - const webhookUrl = params.webhookUrlDisplay || '{YOUR_WEBHOOK_URL_FROM_ABOVE}' - return `curl -X PUT "https://api.hubapi.com/webhooks/v3/{YOUR_APP_ID}/settings?hapikey={YOUR_DEVELOPER_API_KEY}" \\ - -H "Content-Type: application/json" \\ - -d '{ - "targetUrl": "${webhookUrl}", - "throttling": { - "maxConcurrentRequests": 10 - } - }'` - }, - readOnly: true, - collapsible: true, - defaultCollapsed: true, - showCopyButton: true, - description: 'Run this command to set your webhook URL in HubSpot', - mode: 'trigger', - condition: { - field: 'selectedTriggerId', - value: 'hubspot_conversation_creation', - }, - }, - { - id: 'curlCreateSubscription', - title: '2. Create Webhook Subscription', - type: 'code', - language: 'javascript', - defaultValue: `curl -X POST "https://api.hubapi.com/webhooks/v3/{YOUR_APP_ID}/subscriptions?hapikey={YOUR_DEVELOPER_API_KEY}" \\ - -H "Content-Type: application/json" \\ - -d '{ - "eventType": "conversation.creation", - "active": true - }'`, - readOnly: true, - collapsible: true, - defaultCollapsed: true, - showCopyButton: true, - description: 'Run this command to subscribe to conversation creation events', - mode: 'trigger', - condition: { - field: 'selectedTriggerId', - value: 'hubspot_conversation_creation', - }, - }, - { - id: 'samplePayload', - title: 'Event Payload Example', - type: 'code', - language: 'json', - defaultValue: JSON.stringify( - [ - { - eventId: 3181526820, - subscriptionId: 4629980, - portalId: 244315265, - appId: 23608917, - occurredAt: 1762659213730, - subscriptionType: 'conversation.creation', - attemptNumber: 0, - objectId: 316126906055, - changeFlag: 'CREATED', - changeSource: 'EMAIL', - }, - ], - null, - 2 - ), - readOnly: true, - collapsible: true, - defaultCollapsed: true, - mode: 'trigger', - condition: { - field: 'selectedTriggerId', - value: 'hubspot_conversation_creation', - }, - }, - ], - - outputs: buildConversationCreationOutputs(), - - webhook: { - method: 'POST', - headers: { - 'Content-Type': 'application/json', - 'X-HubSpot-Signature': 'sha256=...', - 'X-HubSpot-Request-Id': 'xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx', - 'User-Agent': 'HubSpot Webhooks', - }, - }, -} diff --git a/apps/sim/triggers/hubspot/conversation_deletion.ts b/apps/sim/triggers/hubspot/conversation_deletion.ts deleted file mode 100644 index 1b0c7e2faaf..00000000000 --- a/apps/sim/triggers/hubspot/conversation_deletion.ts +++ /dev/null @@ -1,204 +0,0 @@ -import { HubspotIcon } from '@/components/icons' -import { - buildConversationDeletionOutputs, - hubspotConversationTriggerOptions, - hubspotSetupInstructions, -} from '@/triggers/hubspot/utils' -import type { TriggerConfig } from '@/triggers/types' - -export const hubspotConversationDeletionTrigger: TriggerConfig = { - id: 'hubspot_conversation_deletion', - name: 'HubSpot Conversation Deletion', - provider: 'hubspot', - description: 'Trigger workflow when a conversation is deleted in HubSpot', - version: '1.0.0', - icon: HubspotIcon, - - subBlocks: [ - { - id: 'selectedTriggerId', - title: 'Trigger Type', - type: 'dropdown', - mode: 'trigger', - options: hubspotConversationTriggerOptions, - value: () => 'hubspot_conversation_deletion', - required: true, - }, - { - id: 'clientId', - title: 'Client ID', - type: 'short-input', - placeholder: 'Enter your HubSpot app Client ID', - description: 'Found in your HubSpot app settings under Auth tab', - required: true, - mode: 'trigger', - condition: { - field: 'selectedTriggerId', - value: 'hubspot_conversation_deletion', - }, - }, - { - id: 'clientSecret', - title: 'Client Secret', - type: 'short-input', - placeholder: 'Enter your HubSpot app Client Secret', - description: 'Found in your HubSpot app settings under Auth tab', - password: true, - required: true, - mode: 'trigger', - condition: { - field: 'selectedTriggerId', - value: 'hubspot_conversation_deletion', - }, - }, - { - id: 'appId', - title: 'App ID', - type: 'short-input', - placeholder: 'Enter your HubSpot App ID', - description: 'Found in your HubSpot app settings. Used to identify your app.', - required: true, - mode: 'trigger', - condition: { - field: 'selectedTriggerId', - value: 'hubspot_conversation_deletion', - }, - }, - { - id: 'developerApiKey', - title: 'Developer API Key', - type: 'short-input', - placeholder: 'Enter your HubSpot Developer API Key', - description: 'Used for making API calls to HubSpot. Found in your HubSpot app settings.', - password: true, - required: true, - mode: 'trigger', - condition: { - field: 'selectedTriggerId', - value: 'hubspot_conversation_deletion', - }, - }, - { - id: 'webhookUrlDisplay', - title: 'Webhook URL', - type: 'short-input', - readOnly: true, - showCopyButton: true, - useWebhookUrl: true, - placeholder: 'Webhook URL will be generated', - description: 'Copy this URL and paste it into your HubSpot app webhook subscription settings', - mode: 'trigger', - condition: { - field: 'selectedTriggerId', - value: 'hubspot_conversation_deletion', - }, - }, - { - id: 'triggerInstructions', - title: 'Setup Instructions', - type: 'text', - defaultValue: hubspotSetupInstructions( - 'conversation.deletion', - 'The webhook will trigger whenever a conversation is deleted from your HubSpot account.' - ), - mode: 'trigger', - condition: { - field: 'selectedTriggerId', - value: 'hubspot_conversation_deletion', - }, - }, - { - id: 'curlSetWebhookUrl', - title: '1. Set Webhook Target URL', - type: 'code', - language: 'javascript', - value: (params: Record) => { - const webhookUrl = params.webhookUrlDisplay || '{YOUR_WEBHOOK_URL_FROM_ABOVE}' - return `curl -X PUT "https://api.hubapi.com/webhooks/v3/{YOUR_APP_ID}/settings?hapikey={YOUR_DEVELOPER_API_KEY}" \\ - -H "Content-Type: application/json" \\ - -d '{ - "targetUrl": "${webhookUrl}", - "throttling": { - "maxConcurrentRequests": 10 - } - }'` - }, - readOnly: true, - collapsible: true, - defaultCollapsed: true, - showCopyButton: true, - description: 'Run this command to set your webhook URL in HubSpot', - mode: 'trigger', - condition: { - field: 'selectedTriggerId', - value: 'hubspot_conversation_deletion', - }, - }, - { - id: 'curlCreateSubscription', - title: '2. Create Webhook Subscription', - type: 'code', - language: 'javascript', - defaultValue: `curl -X POST "https://api.hubapi.com/webhooks/v3/{YOUR_APP_ID}/subscriptions?hapikey={YOUR_DEVELOPER_API_KEY}" \\ - -H "Content-Type: application/json" \\ - -d '{ - "eventType": "conversation.deletion", - "active": true - }'`, - readOnly: true, - collapsible: true, - defaultCollapsed: true, - showCopyButton: true, - description: 'Run this command to subscribe to conversation deletion events', - mode: 'trigger', - condition: { - field: 'selectedTriggerId', - value: 'hubspot_conversation_deletion', - }, - }, - { - id: 'samplePayload', - title: 'Event Payload Example', - type: 'code', - language: 'json', - defaultValue: JSON.stringify( - [ - { - eventId: 3181526821, - subscriptionId: 4629981, - portalId: 244315265, - appId: 23608917, - occurredAt: 1762659213730, - subscriptionType: 'conversation.deletion', - attemptNumber: 0, - objectId: 316126906055, - changeFlag: 'DELETED', - changeSource: 'CRM_UI', - }, - ], - null, - 2 - ), - readOnly: true, - collapsible: true, - defaultCollapsed: true, - mode: 'trigger', - condition: { - field: 'selectedTriggerId', - value: 'hubspot_conversation_deletion', - }, - }, - ], - - outputs: buildConversationDeletionOutputs(), - - webhook: { - method: 'POST', - headers: { - 'Content-Type': 'application/json', - 'X-HubSpot-Signature': 'sha256=...', - 'X-HubSpot-Request-Id': 'xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx', - 'User-Agent': 'HubSpot Webhooks', - }, - }, -} diff --git a/apps/sim/triggers/hubspot/conversation_new_message.ts b/apps/sim/triggers/hubspot/conversation_new_message.ts deleted file mode 100644 index 8611f0845c2..00000000000 --- a/apps/sim/triggers/hubspot/conversation_new_message.ts +++ /dev/null @@ -1,205 +0,0 @@ -import { HubspotIcon } from '@/components/icons' -import { - buildConversationNewMessageOutputs, - hubspotConversationTriggerOptions, - hubspotSetupInstructions, -} from '@/triggers/hubspot/utils' -import type { TriggerConfig } from '@/triggers/types' - -export const hubspotConversationNewMessageTrigger: TriggerConfig = { - id: 'hubspot_conversation_new_message', - name: 'HubSpot Conversation New Message', - provider: 'hubspot', - description: 'Trigger workflow when a new message is added to a conversation in HubSpot', - version: '1.0.0', - icon: HubspotIcon, - - subBlocks: [ - { - id: 'selectedTriggerId', - title: 'Trigger Type', - type: 'dropdown', - mode: 'trigger', - options: hubspotConversationTriggerOptions, - value: () => 'hubspot_conversation_new_message', - required: true, - }, - { - id: 'clientId', - title: 'Client ID', - type: 'short-input', - placeholder: 'Enter your HubSpot app Client ID', - description: 'Found in your HubSpot app settings under Auth tab', - required: true, - mode: 'trigger', - condition: { - field: 'selectedTriggerId', - value: 'hubspot_conversation_new_message', - }, - }, - { - id: 'clientSecret', - title: 'Client Secret', - type: 'short-input', - placeholder: 'Enter your HubSpot app Client Secret', - description: 'Found in your HubSpot app settings under Auth tab', - password: true, - required: true, - mode: 'trigger', - condition: { - field: 'selectedTriggerId', - value: 'hubspot_conversation_new_message', - }, - }, - { - id: 'appId', - title: 'App ID', - type: 'short-input', - placeholder: 'Enter your HubSpot App ID', - description: 'Found in your HubSpot app settings. Used to identify your app.', - required: true, - mode: 'trigger', - condition: { - field: 'selectedTriggerId', - value: 'hubspot_conversation_new_message', - }, - }, - { - id: 'developerApiKey', - title: 'Developer API Key', - type: 'short-input', - placeholder: 'Enter your HubSpot Developer API Key', - description: 'Used for making API calls to HubSpot. Found in your HubSpot app settings.', - password: true, - required: true, - mode: 'trigger', - condition: { - field: 'selectedTriggerId', - value: 'hubspot_conversation_new_message', - }, - }, - { - id: 'webhookUrlDisplay', - title: 'Webhook URL', - type: 'short-input', - readOnly: true, - showCopyButton: true, - useWebhookUrl: true, - placeholder: 'Webhook URL will be generated', - description: 'Copy this URL and paste it into your HubSpot app webhook subscription settings', - mode: 'trigger', - condition: { - field: 'selectedTriggerId', - value: 'hubspot_conversation_new_message', - }, - }, - { - id: 'triggerInstructions', - title: 'Setup Instructions', - type: 'text', - defaultValue: hubspotSetupInstructions( - 'conversation.newMessage', - 'The webhook will trigger whenever a new message is added to any conversation in your HubSpot account. This includes emails, chat messages, and other conversation types.' - ), - mode: 'trigger', - condition: { - field: 'selectedTriggerId', - value: 'hubspot_conversation_new_message', - }, - }, - { - id: 'curlSetWebhookUrl', - title: '1. Set Webhook Target URL', - type: 'code', - language: 'javascript', - value: (params: Record) => { - const webhookUrl = params.webhookUrlDisplay || '{YOUR_WEBHOOK_URL_FROM_ABOVE}' - return `curl -X PUT "https://api.hubapi.com/webhooks/v3/{YOUR_APP_ID}/settings?hapikey={YOUR_DEVELOPER_API_KEY}" \\ - -H "Content-Type: application/json" \\ - -d '{ - "targetUrl": "${webhookUrl}", - "throttling": { - "maxConcurrentRequests": 10 - } - }'` - }, - readOnly: true, - collapsible: true, - defaultCollapsed: true, - showCopyButton: true, - description: 'Run this command to set your webhook URL in HubSpot', - mode: 'trigger', - condition: { - field: 'selectedTriggerId', - value: 'hubspot_conversation_new_message', - }, - }, - { - id: 'curlCreateSubscription', - title: '2. Create Webhook Subscription', - type: 'code', - language: 'javascript', - defaultValue: `curl -X POST "https://api.hubapi.com/webhooks/v3/{YOUR_APP_ID}/subscriptions?hapikey={YOUR_DEVELOPER_API_KEY}" \\ - -H "Content-Type: application/json" \\ - -d '{ - "eventType": "conversation.newMessage", - "active": true - }'`, - readOnly: true, - collapsible: true, - defaultCollapsed: true, - showCopyButton: true, - description: 'Run this command to subscribe to conversation new message events', - mode: 'trigger', - condition: { - field: 'selectedTriggerId', - value: 'hubspot_conversation_new_message', - }, - }, - { - id: 'samplePayload', - title: 'Event Payload Example', - type: 'code', - language: 'json', - defaultValue: JSON.stringify( - [ - { - eventId: 3181526822, - subscriptionId: 4629982, - portalId: 244315265, - appId: 23608917, - occurredAt: 1762659213730, - subscriptionType: 'conversation.newMessage', - attemptNumber: 0, - objectId: 316126906055, - messageId: '789123456', - changeFlag: 'NEW_MESSAGE', - changeSource: 'CHAT', - }, - ], - null, - 2 - ), - readOnly: true, - collapsible: true, - defaultCollapsed: true, - mode: 'trigger', - condition: { - field: 'selectedTriggerId', - value: 'hubspot_conversation_new_message', - }, - }, - ], - - outputs: buildConversationNewMessageOutputs(), - - webhook: { - method: 'POST', - headers: { - 'Content-Type': 'application/json', - 'X-HubSpot-Signature': 'sha256=...', - 'X-HubSpot-Request-Id': 'xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx', - 'User-Agent': 'HubSpot Webhooks', - }, - }, -} diff --git a/apps/sim/triggers/hubspot/conversation_privacy_deletion.ts b/apps/sim/triggers/hubspot/conversation_privacy_deletion.ts deleted file mode 100644 index 7d170c7b84a..00000000000 --- a/apps/sim/triggers/hubspot/conversation_privacy_deletion.ts +++ /dev/null @@ -1,205 +0,0 @@ -import { HubspotIcon } from '@/components/icons' -import { - buildConversationPrivacyDeletionOutputs, - hubspotConversationTriggerOptions, - hubspotSetupInstructions, -} from '@/triggers/hubspot/utils' -import type { TriggerConfig } from '@/triggers/types' - -export const hubspotConversationPrivacyDeletionTrigger: TriggerConfig = { - id: 'hubspot_conversation_privacy_deletion', - name: 'HubSpot Conversation Privacy Deletion', - provider: 'hubspot', - description: - 'Trigger workflow when a conversation is deleted for privacy compliance (GDPR, CCPA, etc.) in HubSpot', - version: '1.0.0', - icon: HubspotIcon, - - subBlocks: [ - { - id: 'selectedTriggerId', - title: 'Trigger Type', - type: 'dropdown', - mode: 'trigger', - options: hubspotConversationTriggerOptions, - value: () => 'hubspot_conversation_privacy_deletion', - required: true, - }, - { - id: 'clientId', - title: 'Client ID', - type: 'short-input', - placeholder: 'Enter your HubSpot app Client ID', - description: 'Found in your HubSpot app settings under Auth tab', - required: true, - mode: 'trigger', - condition: { - field: 'selectedTriggerId', - value: 'hubspot_conversation_privacy_deletion', - }, - }, - { - id: 'clientSecret', - title: 'Client Secret', - type: 'short-input', - placeholder: 'Enter your HubSpot app Client Secret', - description: 'Found in your HubSpot app settings under Auth tab', - password: true, - required: true, - mode: 'trigger', - condition: { - field: 'selectedTriggerId', - value: 'hubspot_conversation_privacy_deletion', - }, - }, - { - id: 'appId', - title: 'App ID', - type: 'short-input', - placeholder: 'Enter your HubSpot App ID', - description: 'Found in your HubSpot app settings. Used to identify your app.', - required: true, - mode: 'trigger', - condition: { - field: 'selectedTriggerId', - value: 'hubspot_conversation_privacy_deletion', - }, - }, - { - id: 'developerApiKey', - title: 'Developer API Key', - type: 'short-input', - placeholder: 'Enter your HubSpot Developer API Key', - description: 'Used for making API calls to HubSpot. Found in your HubSpot app settings.', - password: true, - required: true, - mode: 'trigger', - condition: { - field: 'selectedTriggerId', - value: 'hubspot_conversation_privacy_deletion', - }, - }, - { - id: 'webhookUrlDisplay', - title: 'Webhook URL', - type: 'short-input', - readOnly: true, - showCopyButton: true, - useWebhookUrl: true, - placeholder: 'Webhook URL will be generated', - description: 'Copy this URL and paste it into your HubSpot app webhook subscription settings', - mode: 'trigger', - condition: { - field: 'selectedTriggerId', - value: 'hubspot_conversation_privacy_deletion', - }, - }, - { - id: 'triggerInstructions', - title: 'Setup Instructions', - type: 'text', - defaultValue: hubspotSetupInstructions( - 'conversation.privacyDeletion', - 'The webhook will trigger when a conversation is deleted specifically for privacy compliance reasons (e.g., GDPR "right to be forgotten" requests). This is different from regular conversation deletions.' - ), - mode: 'trigger', - condition: { - field: 'selectedTriggerId', - value: 'hubspot_conversation_privacy_deletion', - }, - }, - { - id: 'curlSetWebhookUrl', - title: '1. Set Webhook Target URL', - type: 'code', - language: 'javascript', - value: (params: Record) => { - const webhookUrl = params.webhookUrlDisplay || '{YOUR_WEBHOOK_URL_FROM_ABOVE}' - return `curl -X PUT "https://api.hubapi.com/webhooks/v3/{YOUR_APP_ID}/settings?hapikey={YOUR_DEVELOPER_API_KEY}" \\ - -H "Content-Type: application/json" \\ - -d '{ - "targetUrl": "${webhookUrl}", - "throttling": { - "maxConcurrentRequests": 10 - } - }'` - }, - readOnly: true, - collapsible: true, - defaultCollapsed: true, - showCopyButton: true, - description: 'Run this command to set your webhook URL in HubSpot', - mode: 'trigger', - condition: { - field: 'selectedTriggerId', - value: 'hubspot_conversation_privacy_deletion', - }, - }, - { - id: 'curlCreateSubscription', - title: '2. Create Webhook Subscription', - type: 'code', - language: 'javascript', - defaultValue: `curl -X POST "https://api.hubapi.com/webhooks/v3/{YOUR_APP_ID}/subscriptions?hapikey={YOUR_DEVELOPER_API_KEY}" \\ - -H "Content-Type: application/json" \\ - -d '{ - "eventType": "conversation.privacyDeletion", - "active": true - }'`, - readOnly: true, - collapsible: true, - defaultCollapsed: true, - showCopyButton: true, - description: 'Run this command to subscribe to conversation privacy deletion events', - mode: 'trigger', - condition: { - field: 'selectedTriggerId', - value: 'hubspot_conversation_privacy_deletion', - }, - }, - { - id: 'samplePayload', - title: 'Event Payload Example', - type: 'code', - language: 'json', - defaultValue: JSON.stringify( - [ - { - eventId: 3181526823, - subscriptionId: 4629983, - portalId: 244315265, - appId: 23608917, - occurredAt: 1762659213730, - subscriptionType: 'conversation.privacyDeletion', - attemptNumber: 0, - objectId: 316126906055, - changeFlag: 'PRIVACY_DELETED', - changeSource: 'GDPR', - }, - ], - null, - 2 - ), - readOnly: true, - collapsible: true, - defaultCollapsed: true, - mode: 'trigger', - condition: { - field: 'selectedTriggerId', - value: 'hubspot_conversation_privacy_deletion', - }, - }, - ], - - outputs: buildConversationPrivacyDeletionOutputs(), - - webhook: { - method: 'POST', - headers: { - 'Content-Type': 'application/json', - 'X-HubSpot-Signature': 'sha256=...', - 'X-HubSpot-Request-Id': 'xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx', - 'User-Agent': 'HubSpot Webhooks', - }, - }, -} diff --git a/apps/sim/triggers/hubspot/conversation_property_changed.ts b/apps/sim/triggers/hubspot/conversation_property_changed.ts deleted file mode 100644 index 8d3fabd66db..00000000000 --- a/apps/sim/triggers/hubspot/conversation_property_changed.ts +++ /dev/null @@ -1,221 +0,0 @@ -import { HubspotIcon } from '@/components/icons' -import { - buildConversationPropertyChangedOutputs, - hubspotConversationTriggerOptions, - hubspotSetupInstructions, -} from '@/triggers/hubspot/utils' -import type { TriggerConfig } from '@/triggers/types' - -export const hubspotConversationPropertyChangedTrigger: TriggerConfig = { - id: 'hubspot_conversation_property_changed', - name: 'HubSpot Conversation Property Changed', - provider: 'hubspot', - description: 'Trigger workflow when any property of a conversation is updated in HubSpot', - version: '1.0.0', - icon: HubspotIcon, - - subBlocks: [ - { - id: 'selectedTriggerId', - title: 'Trigger Type', - type: 'dropdown', - mode: 'trigger', - options: hubspotConversationTriggerOptions, - value: () => 'hubspot_conversation_property_changed', - required: true, - }, - { - id: 'clientId', - title: 'Client ID', - type: 'short-input', - placeholder: 'Enter your HubSpot app Client ID', - description: 'Found in your HubSpot app settings under Auth tab', - required: true, - mode: 'trigger', - condition: { - field: 'selectedTriggerId', - value: 'hubspot_conversation_property_changed', - }, - }, - { - id: 'clientSecret', - title: 'Client Secret', - type: 'short-input', - placeholder: 'Enter your HubSpot app Client Secret', - description: 'Found in your HubSpot app settings under Auth tab', - password: true, - required: true, - mode: 'trigger', - condition: { - field: 'selectedTriggerId', - value: 'hubspot_conversation_property_changed', - }, - }, - { - id: 'appId', - title: 'App ID', - type: 'short-input', - placeholder: 'Enter your HubSpot App ID', - description: 'Found in your HubSpot app settings. Used to identify your app.', - required: true, - mode: 'trigger', - condition: { - field: 'selectedTriggerId', - value: 'hubspot_conversation_property_changed', - }, - }, - { - id: 'developerApiKey', - title: 'Developer API Key', - type: 'short-input', - placeholder: 'Enter your HubSpot Developer API Key', - description: 'Used for making API calls to HubSpot. Found in your HubSpot app settings.', - password: true, - required: true, - mode: 'trigger', - condition: { - field: 'selectedTriggerId', - value: 'hubspot_conversation_property_changed', - }, - }, - { - id: 'webhookUrlDisplay', - title: 'Webhook URL', - type: 'short-input', - readOnly: true, - showCopyButton: true, - useWebhookUrl: true, - placeholder: 'Webhook URL will be generated', - description: 'Copy this URL and paste it into your HubSpot app webhook subscription settings', - mode: 'trigger', - condition: { - field: 'selectedTriggerId', - value: 'hubspot_conversation_property_changed', - }, - }, - { - id: 'propertyName', - title: 'Property Name (Optional)', - type: 'short-input', - placeholder: 'e.g., status, assignedTo', - description: - 'Optional: Filter to only trigger when a specific property changes. Leave empty to trigger on any property change.', - required: false, - mode: 'trigger', - condition: { - field: 'selectedTriggerId', - value: 'hubspot_conversation_property_changed', - }, - }, - { - id: 'triggerInstructions', - title: 'Setup Instructions', - type: 'text', - defaultValue: hubspotSetupInstructions( - 'conversation.propertyChange', - 'The webhook will trigger whenever any property of a conversation is updated. You can optionally filter by a specific property name to only receive events for that property. The webhook provides both the property name and new value in the payload.' - ), - mode: 'trigger', - condition: { - field: 'selectedTriggerId', - value: 'hubspot_conversation_property_changed', - }, - }, - { - id: 'curlSetWebhookUrl', - title: '1. Set Webhook Target URL', - type: 'code', - language: 'javascript', - value: (params: Record) => { - const webhookUrl = params.webhookUrlDisplay || '{YOUR_WEBHOOK_URL_FROM_ABOVE}' - return `curl -X PUT "https://api.hubapi.com/webhooks/v3/{YOUR_APP_ID}/settings?hapikey={YOUR_DEVELOPER_API_KEY}" \\ - -H "Content-Type: application/json" \\ - -d '{ - "targetUrl": "${webhookUrl}", - "throttling": { - "maxConcurrentRequests": 10 - } - }'` - }, - readOnly: true, - collapsible: true, - defaultCollapsed: true, - showCopyButton: true, - description: 'Run this command to set your webhook URL in HubSpot', - mode: 'trigger', - condition: { - field: 'selectedTriggerId', - value: 'hubspot_conversation_property_changed', - }, - }, - { - id: 'curlCreateSubscription', - title: '2. Create Webhook Subscription', - type: 'code', - language: 'javascript', - defaultValue: `curl -X POST "https://api.hubapi.com/webhooks/v3/{YOUR_APP_ID}/subscriptions?hapikey={YOUR_DEVELOPER_API_KEY}" \\ - -H "Content-Type: application/json" \\ - -d '{ - "eventType": "conversation.propertyChange", - "active": true - }'`, - readOnly: true, - collapsible: true, - defaultCollapsed: true, - showCopyButton: true, - description: 'Run this command to subscribe to conversation property change events', - mode: 'trigger', - condition: { - field: 'selectedTriggerId', - value: 'hubspot_conversation_property_changed', - }, - }, - { - id: 'samplePayload', - title: 'Event Payload Example', - type: 'code', - language: 'json', - defaultValue: JSON.stringify( - [ - { - eventId: 3181526824, - subscriptionId: 4629984, - portalId: 244315265, - appId: 23608917, - occurredAt: 1762659213730, - subscriptionType: 'conversation.propertyChange', - attemptNumber: 0, - objectId: 316126906055, - propertyName: 'status', - propertyValue: 'closed', - changeFlag: 'UPDATED', - changeSource: 'CRM_UI', - sourceId: 'userId:84916424', - }, - ], - null, - 2 - ), - readOnly: true, - collapsible: true, - defaultCollapsed: true, - mode: 'trigger', - condition: { - field: 'selectedTriggerId', - value: 'hubspot_conversation_property_changed', - }, - }, - ], - - outputs: buildConversationPropertyChangedOutputs(), - - webhook: { - method: 'POST', - headers: { - 'Content-Type': 'application/json', - 'X-HubSpot-Signature': 'sha256=...', - 'X-HubSpot-Request-Id': 'xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx', - 'User-Agent': 'HubSpot Webhooks', - }, - }, -} diff --git a/apps/sim/triggers/hubspot/deal_created.ts b/apps/sim/triggers/hubspot/deal_created.ts deleted file mode 100644 index f1e6838577a..00000000000 --- a/apps/sim/triggers/hubspot/deal_created.ts +++ /dev/null @@ -1,205 +0,0 @@ -import { HubspotIcon } from '@/components/icons' -import { - buildDealCreatedOutputs, - hubspotDealTriggerOptions, - hubspotSetupInstructions, -} from '@/triggers/hubspot/utils' -import type { TriggerConfig } from '@/triggers/types' - -export const hubspotDealCreatedTrigger: TriggerConfig = { - id: 'hubspot_deal_created', - name: 'HubSpot Deal Created', - provider: 'hubspot', - description: 'Trigger workflow when a new deal is created in HubSpot', - version: '1.0.0', - icon: HubspotIcon, - - subBlocks: [ - { - id: 'selectedTriggerId', - title: 'Trigger Type', - type: 'dropdown', - mode: 'trigger', - options: hubspotDealTriggerOptions, - value: () => 'hubspot_deal_created', - required: true, - }, - { - id: 'clientId', - title: 'Client ID', - type: 'short-input', - placeholder: 'Enter your HubSpot app Client ID', - description: 'Found in your HubSpot app settings under Auth tab', - required: true, - mode: 'trigger', - condition: { - field: 'selectedTriggerId', - value: 'hubspot_deal_created', - }, - }, - { - id: 'clientSecret', - title: 'Client Secret', - type: 'short-input', - placeholder: 'Enter your HubSpot app Client Secret', - description: 'Found in your HubSpot app settings under Auth tab', - password: true, - required: true, - mode: 'trigger', - condition: { - field: 'selectedTriggerId', - value: 'hubspot_deal_created', - }, - }, - { - id: 'appId', - title: 'App ID', - type: 'short-input', - placeholder: 'Enter your HubSpot App ID', - description: 'Found in your HubSpot app settings. Used to identify your app.', - required: true, - mode: 'trigger', - condition: { - field: 'selectedTriggerId', - value: 'hubspot_deal_created', - }, - }, - { - id: 'developerApiKey', - title: 'Developer API Key', - type: 'short-input', - placeholder: 'Enter your HubSpot Developer API Key', - description: 'Used for making API calls to HubSpot. Found in your HubSpot app settings.', - password: true, - required: true, - mode: 'trigger', - condition: { - field: 'selectedTriggerId', - value: 'hubspot_deal_created', - }, - }, - { - id: 'webhookUrlDisplay', - title: 'Webhook URL', - type: 'short-input', - readOnly: true, - showCopyButton: true, - useWebhookUrl: true, - placeholder: 'Webhook URL will be generated', - description: 'Copy this URL and paste it into your HubSpot app webhook subscription settings', - mode: 'trigger', - condition: { - field: 'selectedTriggerId', - value: 'hubspot_deal_created', - }, - }, - { - id: 'triggerInstructions', - title: 'Setup Instructions', - type: 'text', - defaultValue: hubspotSetupInstructions( - 'deal.creation', - 'The webhook will trigger whenever a new deal is created in your HubSpot account, regardless of the source (manual entry, API, import, etc.).' - ), - mode: 'trigger', - condition: { - field: 'selectedTriggerId', - value: 'hubspot_deal_created', - }, - }, - { - id: 'curlSetWebhookUrl', - title: '1. Set Webhook Target URL', - type: 'code', - language: 'javascript', - value: (params: Record) => { - const webhookUrl = params.webhookUrlDisplay || '{YOUR_WEBHOOK_URL_FROM_ABOVE}' - return `curl -X PUT "https://api.hubapi.com/webhooks/v3/{YOUR_APP_ID}/settings?hapikey={YOUR_DEVELOPER_API_KEY}" \\ - -H "Content-Type: application/json" \\ - -d '{ - "targetUrl": "${webhookUrl}", - "throttling": { - "maxConcurrentRequests": 10 - } - }'` - }, - readOnly: true, - collapsible: true, - defaultCollapsed: true, - showCopyButton: true, - description: 'Run this command to set your webhook URL in HubSpot', - mode: 'trigger', - condition: { - field: 'selectedTriggerId', - value: 'hubspot_deal_created', - }, - }, - { - id: 'curlCreateSubscription', - title: '2. Create Webhook Subscription', - type: 'code', - language: 'javascript', - defaultValue: `curl -X POST "https://api.hubapi.com/webhooks/v3/{YOUR_APP_ID}/subscriptions?hapikey={YOUR_DEVELOPER_API_KEY}" \\ - -H "Content-Type: application/json" \\ - -d '{ - "eventType": "deal.creation", - "active": true - }'`, - readOnly: true, - collapsible: true, - defaultCollapsed: true, - showCopyButton: true, - description: 'Run this command to subscribe to deal creation events', - mode: 'trigger', - condition: { - field: 'selectedTriggerId', - value: 'hubspot_deal_created', - }, - }, - { - id: 'samplePayload', - title: 'Event Payload Example', - type: 'code', - language: 'json', - defaultValue: JSON.stringify( - [ - { - eventId: 3181526825, - subscriptionId: 4629985, - portalId: 244315265, - appId: 23608917, - occurredAt: 1762659213730, - subscriptionType: 'deal.creation', - attemptNumber: 0, - objectId: 316126906060, - changeFlag: 'CREATED', - changeSource: 'CRM_UI', - sourceId: 'userId:84916424', - }, - ], - null, - 2 - ), - readOnly: true, - collapsible: true, - defaultCollapsed: true, - mode: 'trigger', - condition: { - field: 'selectedTriggerId', - value: 'hubspot_deal_created', - }, - }, - ], - - outputs: buildDealCreatedOutputs(), - - webhook: { - method: 'POST', - headers: { - 'Content-Type': 'application/json', - 'X-HubSpot-Signature': 'sha256=...', - 'X-HubSpot-Request-Id': 'xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx', - 'User-Agent': 'HubSpot Webhooks', - }, - }, -} diff --git a/apps/sim/triggers/hubspot/deal_deleted.ts b/apps/sim/triggers/hubspot/deal_deleted.ts deleted file mode 100644 index 92765a970ae..00000000000 --- a/apps/sim/triggers/hubspot/deal_deleted.ts +++ /dev/null @@ -1,205 +0,0 @@ -import { HubspotIcon } from '@/components/icons' -import { - buildDealDeletedOutputs, - hubspotDealTriggerOptions, - hubspotSetupInstructions, -} from '@/triggers/hubspot/utils' -import type { TriggerConfig } from '@/triggers/types' - -export const hubspotDealDeletedTrigger: TriggerConfig = { - id: 'hubspot_deal_deleted', - name: 'HubSpot Deal Deleted', - provider: 'hubspot', - description: 'Trigger workflow when a deal is deleted in HubSpot', - version: '1.0.0', - icon: HubspotIcon, - - subBlocks: [ - { - id: 'selectedTriggerId', - title: 'Trigger Type', - type: 'dropdown', - mode: 'trigger', - options: hubspotDealTriggerOptions, - value: () => 'hubspot_deal_deleted', - required: true, - }, - { - id: 'clientId', - title: 'Client ID', - type: 'short-input', - placeholder: 'Enter your HubSpot app Client ID', - description: 'Found in your HubSpot app settings under Auth tab', - required: true, - mode: 'trigger', - condition: { - field: 'selectedTriggerId', - value: 'hubspot_deal_deleted', - }, - }, - { - id: 'clientSecret', - title: 'Client Secret', - type: 'short-input', - placeholder: 'Enter your HubSpot app Client Secret', - description: 'Found in your HubSpot app settings under Auth tab', - password: true, - required: true, - mode: 'trigger', - condition: { - field: 'selectedTriggerId', - value: 'hubspot_deal_deleted', - }, - }, - { - id: 'appId', - title: 'App ID', - type: 'short-input', - placeholder: 'Enter your HubSpot App ID', - description: 'Found in your HubSpot app settings. Used to identify your app.', - required: true, - mode: 'trigger', - condition: { - field: 'selectedTriggerId', - value: 'hubspot_deal_deleted', - }, - }, - { - id: 'developerApiKey', - title: 'Developer API Key', - type: 'short-input', - placeholder: 'Enter your HubSpot Developer API Key', - description: 'Used for making API calls to HubSpot. Found in your HubSpot app settings.', - password: true, - required: true, - mode: 'trigger', - condition: { - field: 'selectedTriggerId', - value: 'hubspot_deal_deleted', - }, - }, - { - id: 'webhookUrlDisplay', - title: 'Webhook URL', - type: 'short-input', - readOnly: true, - showCopyButton: true, - useWebhookUrl: true, - placeholder: 'Webhook URL will be generated', - description: 'Copy this URL and paste it into your HubSpot app webhook subscription settings', - mode: 'trigger', - condition: { - field: 'selectedTriggerId', - value: 'hubspot_deal_deleted', - }, - }, - { - id: 'triggerInstructions', - title: 'Setup Instructions', - type: 'text', - defaultValue: hubspotSetupInstructions( - 'deal.deletion', - 'The webhook will trigger whenever a deal is deleted from your HubSpot account.' - ), - mode: 'trigger', - condition: { - field: 'selectedTriggerId', - value: 'hubspot_deal_deleted', - }, - }, - { - id: 'curlSetWebhookUrl', - title: '1. Set Webhook Target URL', - type: 'code', - language: 'javascript', - value: (params: Record) => { - const webhookUrl = params.webhookUrlDisplay || '{YOUR_WEBHOOK_URL_FROM_ABOVE}' - return `curl -X PUT "https://api.hubapi.com/webhooks/v3/{YOUR_APP_ID}/settings?hapikey={YOUR_DEVELOPER_API_KEY}" \\ - -H "Content-Type: application/json" \\ - -d '{ - "targetUrl": "${webhookUrl}", - "throttling": { - "maxConcurrentRequests": 10 - } - }'` - }, - readOnly: true, - collapsible: true, - defaultCollapsed: true, - showCopyButton: true, - description: 'Run this command to set your webhook URL in HubSpot', - mode: 'trigger', - condition: { - field: 'selectedTriggerId', - value: 'hubspot_deal_deleted', - }, - }, - { - id: 'curlCreateSubscription', - title: '2. Create Webhook Subscription', - type: 'code', - language: 'javascript', - defaultValue: `curl -X POST "https://api.hubapi.com/webhooks/v3/{YOUR_APP_ID}/subscriptions?hapikey={YOUR_DEVELOPER_API_KEY}" \\ - -H "Content-Type: application/json" \\ - -d '{ - "eventType": "deal.deletion", - "active": true - }'`, - readOnly: true, - collapsible: true, - defaultCollapsed: true, - showCopyButton: true, - description: 'Run this command to subscribe to deal deletion events', - mode: 'trigger', - condition: { - field: 'selectedTriggerId', - value: 'hubspot_deal_deleted', - }, - }, - { - id: 'samplePayload', - title: 'Event Payload Example', - type: 'code', - language: 'json', - defaultValue: JSON.stringify( - [ - { - eventId: 3181526826, - subscriptionId: 4629986, - portalId: 244315265, - appId: 23608917, - occurredAt: 1762659213730, - subscriptionType: 'deal.deletion', - attemptNumber: 0, - objectId: 316126906060, - changeFlag: 'DELETED', - changeSource: 'CRM_UI', - sourceId: 'userId:84916424', - }, - ], - null, - 2 - ), - readOnly: true, - collapsible: true, - defaultCollapsed: true, - mode: 'trigger', - condition: { - field: 'selectedTriggerId', - value: 'hubspot_deal_deleted', - }, - }, - ], - - outputs: buildDealDeletedOutputs(), - - webhook: { - method: 'POST', - headers: { - 'Content-Type': 'application/json', - 'X-HubSpot-Signature': 'sha256=...', - 'X-HubSpot-Request-Id': 'xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx', - 'User-Agent': 'HubSpot Webhooks', - }, - }, -} diff --git a/apps/sim/triggers/hubspot/deal_merged.ts b/apps/sim/triggers/hubspot/deal_merged.ts deleted file mode 100644 index 06ce88fc4f4..00000000000 --- a/apps/sim/triggers/hubspot/deal_merged.ts +++ /dev/null @@ -1,206 +0,0 @@ -import { HubspotIcon } from '@/components/icons' -import { - buildDealMergedOutputs, - hubspotDealTriggerOptions, - hubspotSetupInstructions, -} from '@/triggers/hubspot/utils' -import type { TriggerConfig } from '@/triggers/types' - -export const hubspotDealMergedTrigger: TriggerConfig = { - id: 'hubspot_deal_merged', - name: 'HubSpot Deal Merged', - provider: 'hubspot', - description: 'Trigger workflow when deals are merged in HubSpot', - version: '1.0.0', - icon: HubspotIcon, - - subBlocks: [ - { - id: 'selectedTriggerId', - title: 'Trigger Type', - type: 'dropdown', - mode: 'trigger', - options: hubspotDealTriggerOptions, - value: () => 'hubspot_deal_merged', - required: true, - }, - { - id: 'clientId', - title: 'Client ID', - type: 'short-input', - placeholder: 'Enter your HubSpot app Client ID', - description: 'Found in your HubSpot app settings under Auth tab', - required: true, - mode: 'trigger', - condition: { - field: 'selectedTriggerId', - value: 'hubspot_deal_merged', - }, - }, - { - id: 'clientSecret', - title: 'Client Secret', - type: 'short-input', - placeholder: 'Enter your HubSpot app Client Secret', - description: 'Found in your HubSpot app settings under Auth tab', - password: true, - required: true, - mode: 'trigger', - condition: { - field: 'selectedTriggerId', - value: 'hubspot_deal_merged', - }, - }, - { - id: 'appId', - title: 'App ID', - type: 'short-input', - placeholder: 'Enter your HubSpot App ID', - description: 'Found in your HubSpot app settings. Used to identify your app.', - required: true, - mode: 'trigger', - condition: { - field: 'selectedTriggerId', - value: 'hubspot_deal_merged', - }, - }, - { - id: 'developerApiKey', - title: 'Developer API Key', - type: 'short-input', - placeholder: 'Enter your HubSpot Developer API Key', - description: 'Used for making API calls to HubSpot. Found in your HubSpot app settings.', - password: true, - required: true, - mode: 'trigger', - condition: { - field: 'selectedTriggerId', - value: 'hubspot_deal_merged', - }, - }, - { - id: 'webhookUrlDisplay', - title: 'Webhook URL', - type: 'short-input', - readOnly: true, - showCopyButton: true, - useWebhookUrl: true, - placeholder: 'Webhook URL will be generated', - description: 'Copy this URL and paste it into your HubSpot app webhook subscription settings', - mode: 'trigger', - condition: { - field: 'selectedTriggerId', - value: 'hubspot_deal_merged', - }, - }, - { - id: 'triggerInstructions', - title: 'Setup Instructions', - type: 'text', - defaultValue: hubspotSetupInstructions( - 'deal.merge', - 'The webhook will trigger whenever two deals are merged in your HubSpot account. The objectId will be the winning (primary) deal ID.' - ), - mode: 'trigger', - condition: { - field: 'selectedTriggerId', - value: 'hubspot_deal_merged', - }, - }, - { - id: 'curlSetWebhookUrl', - title: '1. Set Webhook Target URL', - type: 'code', - language: 'javascript', - value: (params: Record) => { - const webhookUrl = params.webhookUrlDisplay || '{YOUR_WEBHOOK_URL_FROM_ABOVE}' - return `curl -X PUT "https://api.hubapi.com/webhooks/v3/{YOUR_APP_ID}/settings?hapikey={YOUR_DEVELOPER_API_KEY}" \\ - -H "Content-Type: application/json" \\ - -d '{ - "targetUrl": "${webhookUrl}", - "throttling": { - "maxConcurrentRequests": 10 - } - }'` - }, - readOnly: true, - collapsible: true, - defaultCollapsed: true, - showCopyButton: true, - description: 'Run this command to set your webhook URL in HubSpot', - mode: 'trigger', - condition: { - field: 'selectedTriggerId', - value: 'hubspot_deal_merged', - }, - }, - { - id: 'curlCreateSubscription', - title: '2. Create Webhook Subscription', - type: 'code', - language: 'javascript', - defaultValue: `curl -X POST "https://api.hubapi.com/webhooks/v3/{YOUR_APP_ID}/subscriptions?hapikey={YOUR_DEVELOPER_API_KEY}" \\ - -H "Content-Type: application/json" \\ - -d '{ - "eventType": "deal.merge", - "active": true - }'`, - readOnly: true, - collapsible: true, - defaultCollapsed: true, - showCopyButton: true, - description: 'Run this command to subscribe to deal merge events', - mode: 'trigger', - condition: { - field: 'selectedTriggerId', - value: 'hubspot_deal_merged', - }, - }, - { - id: 'samplePayload', - title: 'Event Payload Example', - type: 'code', - language: 'json', - defaultValue: JSON.stringify( - [ - { - eventId: 3181526815, - subscriptionId: 4629976, - portalId: 244315265, - appId: 23608917, - occurredAt: 1762659213730, - subscriptionType: 'deal.merge', - attemptNumber: 0, - objectId: 416126906049, - changeFlag: 'MERGED', - changeSource: 'CRM_UI', - sourceId: 'userId:84916424', - mergedObjectIds: [416126906050], - }, - ], - null, - 2 - ), - readOnly: true, - collapsible: true, - defaultCollapsed: true, - mode: 'trigger', - condition: { - field: 'selectedTriggerId', - value: 'hubspot_deal_merged', - }, - }, - ], - - outputs: buildDealMergedOutputs(), - - webhook: { - method: 'POST', - headers: { - 'Content-Type': 'application/json', - 'X-HubSpot-Signature': 'sha256=...', - 'X-HubSpot-Request-Id': 'xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx', - 'User-Agent': 'HubSpot Webhooks', - }, - }, -} diff --git a/apps/sim/triggers/hubspot/deal_property_changed.ts b/apps/sim/triggers/hubspot/deal_property_changed.ts deleted file mode 100644 index f4e58b3147a..00000000000 --- a/apps/sim/triggers/hubspot/deal_property_changed.ts +++ /dev/null @@ -1,221 +0,0 @@ -import { HubspotIcon } from '@/components/icons' -import { - buildDealPropertyChangedOutputs, - hubspotDealTriggerOptions, - hubspotSetupInstructions, -} from '@/triggers/hubspot/utils' -import type { TriggerConfig } from '@/triggers/types' - -export const hubspotDealPropertyChangedTrigger: TriggerConfig = { - id: 'hubspot_deal_property_changed', - name: 'HubSpot Deal Property Changed', - provider: 'hubspot', - description: 'Trigger workflow when any property of a deal is updated in HubSpot', - version: '1.0.0', - icon: HubspotIcon, - - subBlocks: [ - { - id: 'selectedTriggerId', - title: 'Trigger Type', - type: 'dropdown', - mode: 'trigger', - options: hubspotDealTriggerOptions, - value: () => 'hubspot_deal_property_changed', - required: true, - }, - { - id: 'clientId', - title: 'Client ID', - type: 'short-input', - placeholder: 'Enter your HubSpot app Client ID', - description: 'Found in your HubSpot app settings under Auth tab', - required: true, - mode: 'trigger', - condition: { - field: 'selectedTriggerId', - value: 'hubspot_deal_property_changed', - }, - }, - { - id: 'clientSecret', - title: 'Client Secret', - type: 'short-input', - placeholder: 'Enter your HubSpot app Client Secret', - description: 'Found in your HubSpot app settings under Auth tab', - password: true, - required: true, - mode: 'trigger', - condition: { - field: 'selectedTriggerId', - value: 'hubspot_deal_property_changed', - }, - }, - { - id: 'appId', - title: 'App ID', - type: 'short-input', - placeholder: 'Enter your HubSpot App ID', - description: 'Found in your HubSpot app settings. Used to identify your app.', - required: true, - mode: 'trigger', - condition: { - field: 'selectedTriggerId', - value: 'hubspot_deal_property_changed', - }, - }, - { - id: 'developerApiKey', - title: 'Developer API Key', - type: 'short-input', - placeholder: 'Enter your HubSpot Developer API Key', - description: 'Used for making API calls to HubSpot. Found in your HubSpot app settings.', - password: true, - required: true, - mode: 'trigger', - condition: { - field: 'selectedTriggerId', - value: 'hubspot_deal_property_changed', - }, - }, - { - id: 'webhookUrlDisplay', - title: 'Webhook URL', - type: 'short-input', - readOnly: true, - showCopyButton: true, - useWebhookUrl: true, - placeholder: 'Webhook URL will be generated', - description: 'Copy this URL and paste it into your HubSpot app webhook subscription settings', - mode: 'trigger', - condition: { - field: 'selectedTriggerId', - value: 'hubspot_deal_property_changed', - }, - }, - { - id: 'propertyName', - title: 'Property Name (Optional)', - type: 'short-input', - placeholder: 'e.g., dealstage, amount, closedate', - description: - 'Optional: Filter to only trigger when a specific property changes. Leave empty to trigger on any property change.', - required: false, - mode: 'trigger', - condition: { - field: 'selectedTriggerId', - value: 'hubspot_deal_property_changed', - }, - }, - { - id: 'triggerInstructions', - title: 'Setup Instructions', - type: 'text', - defaultValue: hubspotSetupInstructions( - 'deal.propertyChange', - 'The webhook will trigger whenever any property of a deal is updated. You can optionally filter by a specific property name to only receive events for that property. The webhook provides both the property name and new value in the payload.' - ), - mode: 'trigger', - condition: { - field: 'selectedTriggerId', - value: 'hubspot_deal_property_changed', - }, - }, - { - id: 'curlSetWebhookUrl', - title: '1. Set Webhook Target URL', - type: 'code', - language: 'javascript', - value: (params: Record) => { - const webhookUrl = params.webhookUrlDisplay || '{YOUR_WEBHOOK_URL_FROM_ABOVE}' - return `curl -X PUT "https://api.hubapi.com/webhooks/v3/{YOUR_APP_ID}/settings?hapikey={YOUR_DEVELOPER_API_KEY}" \\ - -H "Content-Type: application/json" \\ - -d '{ - "targetUrl": "${webhookUrl}", - "throttling": { - "maxConcurrentRequests": 10 - } - }'` - }, - readOnly: true, - collapsible: true, - defaultCollapsed: true, - showCopyButton: true, - description: 'Run this command to set your webhook URL in HubSpot', - mode: 'trigger', - condition: { - field: 'selectedTriggerId', - value: 'hubspot_deal_property_changed', - }, - }, - { - id: 'curlCreateSubscription', - title: '2. Create Webhook Subscription', - type: 'code', - language: 'javascript', - defaultValue: `curl -X POST "https://api.hubapi.com/webhooks/v3/{YOUR_APP_ID}/subscriptions?hapikey={YOUR_DEVELOPER_API_KEY}" \\ - -H "Content-Type: application/json" \\ - -d '{ - "eventType": "deal.propertyChange", - "active": true - }'`, - readOnly: true, - collapsible: true, - defaultCollapsed: true, - showCopyButton: true, - description: 'Run this command to subscribe to deal property change events', - mode: 'trigger', - condition: { - field: 'selectedTriggerId', - value: 'hubspot_deal_property_changed', - }, - }, - { - id: 'samplePayload', - title: 'Event Payload Example', - type: 'code', - language: 'json', - defaultValue: JSON.stringify( - [ - { - eventId: 3181526827, - subscriptionId: 4629987, - portalId: 244315265, - appId: 23608917, - occurredAt: 1762659213730, - subscriptionType: 'deal.propertyChange', - attemptNumber: 0, - objectId: 316126906060, - propertyName: 'dealstage', - propertyValue: 'closedwon', - changeFlag: 'UPDATED', - changeSource: 'CRM_UI', - sourceId: 'userId:84916424', - }, - ], - null, - 2 - ), - readOnly: true, - collapsible: true, - defaultCollapsed: true, - mode: 'trigger', - condition: { - field: 'selectedTriggerId', - value: 'hubspot_deal_property_changed', - }, - }, - ], - - outputs: buildDealPropertyChangedOutputs(), - - webhook: { - method: 'POST', - headers: { - 'Content-Type': 'application/json', - 'X-HubSpot-Signature': 'sha256=...', - 'X-HubSpot-Request-Id': 'xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx', - 'User-Agent': 'HubSpot Webhooks', - }, - }, -} diff --git a/apps/sim/triggers/hubspot/deal_restored.ts b/apps/sim/triggers/hubspot/deal_restored.ts deleted file mode 100644 index b511c02ccb5..00000000000 --- a/apps/sim/triggers/hubspot/deal_restored.ts +++ /dev/null @@ -1,205 +0,0 @@ -import { HubspotIcon } from '@/components/icons' -import { - buildDealRestoredOutputs, - hubspotDealTriggerOptions, - hubspotSetupInstructions, -} from '@/triggers/hubspot/utils' -import type { TriggerConfig } from '@/triggers/types' - -export const hubspotDealRestoredTrigger: TriggerConfig = { - id: 'hubspot_deal_restored', - name: 'HubSpot Deal Restored', - provider: 'hubspot', - description: 'Trigger workflow when a deleted deal is restored in HubSpot', - version: '1.0.0', - icon: HubspotIcon, - - subBlocks: [ - { - id: 'selectedTriggerId', - title: 'Trigger Type', - type: 'dropdown', - mode: 'trigger', - options: hubspotDealTriggerOptions, - value: () => 'hubspot_deal_restored', - required: true, - }, - { - id: 'clientId', - title: 'Client ID', - type: 'short-input', - placeholder: 'Enter your HubSpot app Client ID', - description: 'Found in your HubSpot app settings under Auth tab', - required: true, - mode: 'trigger', - condition: { - field: 'selectedTriggerId', - value: 'hubspot_deal_restored', - }, - }, - { - id: 'clientSecret', - title: 'Client Secret', - type: 'short-input', - placeholder: 'Enter your HubSpot app Client Secret', - description: 'Found in your HubSpot app settings under Auth tab', - password: true, - required: true, - mode: 'trigger', - condition: { - field: 'selectedTriggerId', - value: 'hubspot_deal_restored', - }, - }, - { - id: 'appId', - title: 'App ID', - type: 'short-input', - placeholder: 'Enter your HubSpot App ID', - description: 'Found in your HubSpot app settings. Used to identify your app.', - required: true, - mode: 'trigger', - condition: { - field: 'selectedTriggerId', - value: 'hubspot_deal_restored', - }, - }, - { - id: 'developerApiKey', - title: 'Developer API Key', - type: 'short-input', - placeholder: 'Enter your HubSpot Developer API Key', - description: 'Used for making API calls to HubSpot. Found in your HubSpot app settings.', - password: true, - required: true, - mode: 'trigger', - condition: { - field: 'selectedTriggerId', - value: 'hubspot_deal_restored', - }, - }, - { - id: 'webhookUrlDisplay', - title: 'Webhook URL', - type: 'short-input', - readOnly: true, - showCopyButton: true, - useWebhookUrl: true, - placeholder: 'Webhook URL will be generated', - description: 'Copy this URL and paste it into your HubSpot app webhook subscription settings', - mode: 'trigger', - condition: { - field: 'selectedTriggerId', - value: 'hubspot_deal_restored', - }, - }, - { - id: 'triggerInstructions', - title: 'Setup Instructions', - type: 'text', - defaultValue: hubspotSetupInstructions( - 'deal.restore', - 'The webhook will trigger whenever a previously deleted deal is restored in your HubSpot account.' - ), - mode: 'trigger', - condition: { - field: 'selectedTriggerId', - value: 'hubspot_deal_restored', - }, - }, - { - id: 'curlSetWebhookUrl', - title: '1. Set Webhook Target URL', - type: 'code', - language: 'javascript', - value: (params: Record) => { - const webhookUrl = params.webhookUrlDisplay || '{YOUR_WEBHOOK_URL_FROM_ABOVE}' - return `curl -X PUT "https://api.hubapi.com/webhooks/v3/{YOUR_APP_ID}/settings?hapikey={YOUR_DEVELOPER_API_KEY}" \\ - -H "Content-Type: application/json" \\ - -d '{ - "targetUrl": "${webhookUrl}", - "throttling": { - "maxConcurrentRequests": 10 - } - }'` - }, - readOnly: true, - collapsible: true, - defaultCollapsed: true, - showCopyButton: true, - description: 'Run this command to set your webhook URL in HubSpot', - mode: 'trigger', - condition: { - field: 'selectedTriggerId', - value: 'hubspot_deal_restored', - }, - }, - { - id: 'curlCreateSubscription', - title: '2. Create Webhook Subscription', - type: 'code', - language: 'javascript', - defaultValue: `curl -X POST "https://api.hubapi.com/webhooks/v3/{YOUR_APP_ID}/subscriptions?hapikey={YOUR_DEVELOPER_API_KEY}" \\ - -H "Content-Type: application/json" \\ - -d '{ - "eventType": "deal.restore", - "active": true - }'`, - readOnly: true, - collapsible: true, - defaultCollapsed: true, - showCopyButton: true, - description: 'Run this command to subscribe to deal restore events', - mode: 'trigger', - condition: { - field: 'selectedTriggerId', - value: 'hubspot_deal_restored', - }, - }, - { - id: 'samplePayload', - title: 'Event Payload Example', - type: 'code', - language: 'json', - defaultValue: JSON.stringify( - [ - { - eventId: 3181526816, - subscriptionId: 4629977, - portalId: 244315265, - appId: 23608917, - occurredAt: 1762659213730, - subscriptionType: 'deal.restore', - attemptNumber: 0, - objectId: 416126906049, - changeFlag: 'RESTORED', - changeSource: 'CRM_UI', - sourceId: 'userId:84916424', - }, - ], - null, - 2 - ), - readOnly: true, - collapsible: true, - defaultCollapsed: true, - mode: 'trigger', - condition: { - field: 'selectedTriggerId', - value: 'hubspot_deal_restored', - }, - }, - ], - - outputs: buildDealRestoredOutputs(), - - webhook: { - method: 'POST', - headers: { - 'Content-Type': 'application/json', - 'X-HubSpot-Signature': 'sha256=...', - 'X-HubSpot-Request-Id': 'xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx', - 'User-Agent': 'HubSpot Webhooks', - }, - }, -} diff --git a/apps/sim/triggers/hubspot/index.ts b/apps/sim/triggers/hubspot/index.ts index 3c9804add64..bf2025a9ce0 100644 --- a/apps/sim/triggers/hubspot/index.ts +++ b/apps/sim/triggers/hubspot/index.ts @@ -1,27 +1 @@ -export { hubspotCompanyCreatedTrigger } from './company_created' -export { hubspotCompanyDeletedTrigger } from './company_deleted' -export { hubspotCompanyMergedTrigger } from './company_merged' -export { hubspotCompanyPropertyChangedTrigger } from './company_property_changed' -export { hubspotCompanyRestoredTrigger } from './company_restored' -export { hubspotContactCreatedTrigger } from './contact_created' -export { hubspotContactDeletedTrigger } from './contact_deleted' -export { hubspotContactMergedTrigger } from './contact_merged' -export { hubspotContactPrivacyDeletedTrigger } from './contact_privacy_deleted' -export { hubspotContactPropertyChangedTrigger } from './contact_property_changed' -export { hubspotContactRestoredTrigger } from './contact_restored' -export { hubspotConversationCreationTrigger } from './conversation_creation' -export { hubspotConversationDeletionTrigger } from './conversation_deletion' -export { hubspotConversationNewMessageTrigger } from './conversation_new_message' -export { hubspotConversationPrivacyDeletionTrigger } from './conversation_privacy_deletion' -export { hubspotConversationPropertyChangedTrigger } from './conversation_property_changed' -export { hubspotDealCreatedTrigger } from './deal_created' -export { hubspotDealDeletedTrigger } from './deal_deleted' -export { hubspotDealMergedTrigger } from './deal_merged' -export { hubspotDealPropertyChangedTrigger } from './deal_property_changed' -export { hubspotDealRestoredTrigger } from './deal_restored' -export { hubspotTicketCreatedTrigger } from './ticket_created' -export { hubspotTicketDeletedTrigger } from './ticket_deleted' -export { hubspotTicketMergedTrigger } from './ticket_merged' -export { hubspotTicketPropertyChangedTrigger } from './ticket_property_changed' -export { hubspotTicketRestoredTrigger } from './ticket_restored' -export { hubspotWebhookTrigger } from './webhook' +export { hubspotPollingTrigger } from './poller' diff --git a/apps/sim/triggers/hubspot/poller.ts b/apps/sim/triggers/hubspot/poller.ts new file mode 100644 index 00000000000..81cad5866a2 --- /dev/null +++ b/apps/sim/triggers/hubspot/poller.ts @@ -0,0 +1,394 @@ +import { createLogger } from '@sim/logger' +import { HubspotIcon } from '@/components/icons' +import { requestJson } from '@/lib/api/client/request' +import { + hubspotListsSelectorContract, + hubspotOwnersSelectorContract, + hubspotPipelinesSelectorContract, + hubspotPropertiesSelectorContract, +} from '@/lib/api/contracts/selectors/hubspot' +import { getScopesForService } from '@/lib/oauth/utils' +import { isCredentialSetValue } from '@/executor/constants' +import { useSubBlockStore } from '@/stores/workflows/subblock/store' +import type { TriggerConfig } from '@/triggers/types' + +const logger = createLogger('HubSpotPollingTrigger') + +async function fetchHubSpotProperties(blockId: string, objectType: string) { + const credentialId = useSubBlockStore.getState().getValue(blockId, 'triggerCredentials') as + | string + | null + if (!credentialId) throw new Error('No HubSpot credential selected') + if (isCredentialSetValue(credentialId)) return [] + const data = await requestJson(hubspotPropertiesSelectorContract, { + query: { credentialId, objectType }, + }) + return data.properties.map((p) => ({ id: p.id, label: p.name })) +} + +export const hubspotPollingTrigger: TriggerConfig = { + id: 'hubspot_poller', + name: 'HubSpot CRM Trigger', + provider: 'hubspot', + description: + 'Triggers when HubSpot CRM records (contacts, companies, deals, tickets, custom objects) are created or updated, or when contacts join a list', + version: '1.0.0', + icon: HubspotIcon, + polling: true, + + subBlocks: [ + { + id: 'triggerCredentials', + title: 'HubSpot Account', + type: 'oauth-input', + description: 'Connect a HubSpot account so Sim can poll your CRM on your behalf.', + serviceId: 'hubspot', + requiredScopes: getScopesForService('hubspot'), + required: true, + mode: 'trigger', + supportsCredentialSets: true, + }, + { + id: 'objectType', + title: 'Object Type', + type: 'dropdown', + description: 'What you want to watch.', + options: [ + { label: 'Contact', id: 'contact' }, + { label: 'Company', id: 'company' }, + { label: 'Deal', id: 'deal' }, + { label: 'Ticket', id: 'ticket' }, + { label: 'Custom Object', id: 'custom' }, + { label: 'List Membership', id: 'list_membership' }, + ], + defaultValue: 'contact', + required: true, + mode: 'trigger', + }, + { + id: 'customObjectTypeId', + title: 'Custom Object Type ID', + type: 'short-input', + description: + 'HubSpot custom object type ID (e.g. "2-12345"). Find it in HubSpot Settings → Objects → Custom Objects.', + placeholder: '2-12345', + required: { field: 'objectType', value: 'custom' }, + mode: 'trigger', + condition: { field: 'objectType', value: 'custom' }, + }, + { + id: 'listId', + title: 'List', + type: 'dropdown', + description: 'The HubSpot list to watch for new members.', + placeholder: 'Select a list', + options: [], + fetchOptions: async (blockId: string) => { + const credentialId = useSubBlockStore.getState().getValue(blockId, 'triggerCredentials') as + | string + | null + if (!credentialId) throw new Error('No HubSpot credential selected') + if (isCredentialSetValue(credentialId)) return [] + try { + const data = await requestJson(hubspotListsSelectorContract, { + query: { credentialId }, + }) + return data.lists.map((l) => ({ id: l.id, label: l.name })) + } catch (error) { + logger.error('Error fetching HubSpot lists:', error) + throw error + } + }, + dependsOn: ['triggerCredentials'], + required: { field: 'objectType', value: 'list_membership' }, + mode: 'trigger', + condition: { field: 'objectType', value: 'list_membership' }, + }, + { + id: 'eventType', + title: 'Event', + type: 'dropdown', + description: + 'Created fires once per new record. Updated fires on any modification. Property Changed fires only when the chosen property changes value.', + options: [ + { label: 'Created', id: 'created' }, + { label: 'Updated (any change)', id: 'updated' }, + { label: 'Property Changed', id: 'property_changed' }, + ], + defaultValue: 'created', + required: { field: 'objectType', value: 'list_membership', not: true }, + mode: 'trigger', + condition: { field: 'objectType', value: 'list_membership', not: true }, + }, + { + id: 'targetPropertyName', + title: 'Property to Watch', + type: 'dropdown', + description: 'Fires only when this specific property changes value on a record.', + placeholder: 'Select a property', + options: [], + fetchOptions: async (blockId: string) => { + const objectType = useSubBlockStore.getState().getValue(blockId, 'objectType') as + | string + | null + const customId = useSubBlockStore.getState().getValue(blockId, 'customObjectTypeId') as + | string + | null + const resolved = objectType === 'custom' ? customId : objectType + if (!resolved) throw new Error('Select an object type first') + try { + return await fetchHubSpotProperties(blockId, resolved) + } catch (error) { + logger.error('Error fetching HubSpot properties:', error) + throw error + } + }, + dependsOn: ['triggerCredentials', 'objectType', 'customObjectTypeId'], + required: { field: 'eventType', value: 'property_changed' }, + mode: 'trigger', + condition: { + field: 'eventType', + value: 'property_changed', + and: { field: 'objectType', value: 'list_membership', not: true }, + }, + }, + { + id: 'properties', + title: 'Properties to Fetch', + type: 'dropdown', + multiSelect: true, + description: + 'Properties to include on each record. Leave empty to use sensible defaults. Sim always includes the timestamps it needs internally.', + placeholder: 'Select properties (optional)', + options: [], + fetchOptions: async (blockId: string) => { + const objectType = useSubBlockStore.getState().getValue(blockId, 'objectType') as + | string + | null + const customId = useSubBlockStore.getState().getValue(blockId, 'customObjectTypeId') as + | string + | null + const resolved = objectType === 'custom' ? customId : objectType + if (!resolved) return [] + try { + return await fetchHubSpotProperties(blockId, resolved) + } catch (error) { + logger.error('Error fetching HubSpot properties:', error) + throw error + } + }, + dependsOn: ['triggerCredentials', 'objectType', 'customObjectTypeId'], + required: false, + mode: 'trigger', + condition: { field: 'objectType', value: 'list_membership', not: true }, + }, + { + id: 'pipelineId', + title: 'Pipeline (optional)', + type: 'dropdown', + description: 'Restrict to a single pipeline.', + placeholder: 'All pipelines', + options: [], + fetchOptions: async (blockId: string) => { + const credentialId = useSubBlockStore.getState().getValue(blockId, 'triggerCredentials') as + | string + | null + const objectType = useSubBlockStore.getState().getValue(blockId, 'objectType') as + | string + | null + if (!credentialId || !objectType) return [] + if (isCredentialSetValue(credentialId)) return [] + try { + const data = await requestJson(hubspotPipelinesSelectorContract, { + query: { credentialId, objectType }, + }) + return data.pipelines.map((p) => ({ id: p.id, label: p.name })) + } catch (error) { + logger.error('Error fetching HubSpot pipelines:', error) + throw error + } + }, + dependsOn: ['triggerCredentials', 'objectType'], + required: false, + mode: 'trigger', + condition: { field: 'objectType', value: ['deal', 'ticket'] }, + }, + { + id: 'stageId', + title: 'Stage (optional)', + type: 'dropdown', + description: 'Restrict to a single stage within the selected pipeline.', + placeholder: 'All stages', + options: [], + fetchOptions: async (blockId: string) => { + const credentialId = useSubBlockStore.getState().getValue(blockId, 'triggerCredentials') as + | string + | null + const objectType = useSubBlockStore.getState().getValue(blockId, 'objectType') as + | string + | null + const pipelineId = useSubBlockStore.getState().getValue(blockId, 'pipelineId') as + | string + | null + if (!credentialId || !objectType || !pipelineId) return [] + if (isCredentialSetValue(credentialId)) return [] + try { + const data = await requestJson(hubspotPipelinesSelectorContract, { + query: { credentialId, objectType }, + }) + const pipeline = data.pipelines.find((p) => p.id === pipelineId) + return (pipeline?.stages ?? []).map((s) => ({ id: s.id, label: s.label })) + } catch (error) { + logger.error('Error fetching HubSpot stages:', error) + throw error + } + }, + dependsOn: ['triggerCredentials', 'objectType', 'pipelineId'], + required: false, + mode: 'trigger', + condition: { field: 'pipelineId', value: '', not: true }, + }, + { + id: 'ownerId', + title: 'Owner (optional)', + type: 'dropdown', + description: 'Restrict to records owned by a specific HubSpot user.', + placeholder: 'Any owner', + options: [], + fetchOptions: async (blockId: string) => { + const credentialId = useSubBlockStore.getState().getValue(blockId, 'triggerCredentials') as + | string + | null + if (!credentialId) return [] + if (isCredentialSetValue(credentialId)) return [] + try { + const data = await requestJson(hubspotOwnersSelectorContract, { + query: { credentialId }, + }) + return data.owners.map((o) => ({ id: o.id, label: o.name })) + } catch (error) { + logger.error('Error fetching HubSpot owners:', error) + throw error + } + }, + dependsOn: ['triggerCredentials'], + required: false, + mode: 'trigger', + condition: { field: 'objectType', value: 'list_membership', not: true }, + }, + { + id: 'filters', + title: 'Advanced Filters (optional)', + type: 'long-input', + description: + 'JSON array of HubSpot search filters, AND-combined. Each item: {"propertyName":"...","operator":"EQ","value":"..."}. Operators: EQ, NEQ, CONTAINS_TOKEN, NOT_CONTAINS_TOKEN, GT, GTE, LT, LTE, BETWEEN, IN, NOT_IN, HAS_PROPERTY, NOT_HAS_PROPERTY.', + placeholder: + '[{"propertyName":"lifecyclestage","operator":"EQ","value":"customer"},{"propertyName":"amount","operator":"GT","value":"10000"}]', + required: false, + mode: 'trigger', + condition: { field: 'objectType', value: 'list_membership', not: true }, + wandConfig: { + enabled: true, + maintainHistory: true, + prompt: `You are an expert HubSpot CRM developer. Generate a JSON array of HubSpot search filters based on the user's request. + +Each filter is { propertyName, operator, value }. Filters are AND-combined. The available operators are: EQ, NEQ, CONTAINS_TOKEN, NOT_CONTAINS_TOKEN, GT, GTE, LT, LTE, BETWEEN, IN, NOT_IN, HAS_PROPERTY, NOT_HAS_PROPERTY. + +Dates use millisecond epoch values as strings. Strings are exact (case-sensitive) for EQ/NEQ. + +User context: +{context} + +Return ONLY the JSON array — no explanations, no markdown, no code fences.`, + placeholder: 'Describe the records you want…', + generationType: 'json-object', + }, + }, + { + id: 'maxRecordsPerPoll', + title: 'Max Records Per Poll', + type: 'short-input', + description: + 'Soft cap on records emitted per poll (default 50, max 1000). Excess rolls over to the next poll.', + placeholder: '50', + required: false, + mode: 'trigger', + }, + { + id: 'triggerInstructions', + title: 'How it works', + hideFromPreview: true, + type: 'text', + defaultValue: [ + 'Connect your HubSpot account above.', + 'Pick the object type and event you want to watch.', + '(Optional) Restrict by pipeline, stage, owner, or advanced filters.', + 'Sim polls HubSpot every minute and fires this workflow for each new or updated record.', + 'The first poll establishes a baseline — only records changed after activation will fire the workflow.', + ] + .map( + (instruction, index) => + `
${index + 1}. ${instruction}
` + ) + .join(''), + mode: 'trigger', + }, + ], + + outputs: { + objectType: { + type: 'string', + description: + 'HubSpot object type (contact, company, deal, ticket, custom object id, or list_membership)', + }, + eventType: { + type: 'string', + description: 'Event type (created, updated, property_changed, or joined)', + }, + objectId: { + type: 'string', + description: 'HubSpot ID of the affected record (or contact id for list memberships)', + }, + occurredAt: { + type: 'string', + description: 'ISO timestamp of when the change happened in HubSpot', + }, + properties: { + type: 'json', + description: + 'HubSpot properties on the record as a key-value object (property internal name → value). Default keys per object type (override via "Properties to Fetch"): Contact → firstname, lastname, email, phone, company, lifecyclestage, hs_lead_status, hubspot_owner_id, createdate, lastmodifieddate. Company → name, domain, industry, lifecyclestage, hubspot_owner_id, createdate, hs_lastmodifieddate. Deal → dealname, amount, dealstage, pipeline, closedate, hubspot_owner_id, createdate, hs_lastmodifieddate. Ticket → subject, content, hs_pipeline, hs_pipeline_stage, hs_ticket_priority, hubspot_owner_id, createdate, hs_lastmodifieddate. Custom and user-requested properties appear keyed by their HubSpot internal name.', + }, + createdAt: { + type: 'string', + description: 'ISO timestamp when the record was created in HubSpot', + }, + updatedAt: { + type: 'string', + description: 'ISO timestamp when the record was last updated in HubSpot', + }, + archived: { + type: 'boolean', + description: 'Whether the record is archived', + }, + propertyName: { + type: 'string', + description: 'Name of the property that changed (property_changed events only)', + }, + propertyValue: { + type: 'string', + description: 'New value of the changed property (property_changed events only)', + }, + previousValue: { + type: 'string', + description: 'Previous value before the change (property_changed events only)', + }, + listId: { + type: 'string', + description: 'HubSpot list ID (list_membership events only)', + }, + timestamp: { + type: 'string', + description: 'ISO timestamp when Sim emitted the event', + }, + }, +} diff --git a/apps/sim/triggers/hubspot/ticket_created.ts b/apps/sim/triggers/hubspot/ticket_created.ts deleted file mode 100644 index 70201fcd2a5..00000000000 --- a/apps/sim/triggers/hubspot/ticket_created.ts +++ /dev/null @@ -1,205 +0,0 @@ -import { HubspotIcon } from '@/components/icons' -import { - buildTicketCreatedOutputs, - hubspotSetupInstructions, - hubspotTicketTriggerOptions, -} from '@/triggers/hubspot/utils' -import type { TriggerConfig } from '@/triggers/types' - -export const hubspotTicketCreatedTrigger: TriggerConfig = { - id: 'hubspot_ticket_created', - name: 'HubSpot Ticket Created', - provider: 'hubspot', - description: 'Trigger workflow when a new ticket is created in HubSpot', - version: '1.0.0', - icon: HubspotIcon, - - subBlocks: [ - { - id: 'selectedTriggerId', - title: 'Trigger Type', - type: 'dropdown', - mode: 'trigger', - options: hubspotTicketTriggerOptions, - value: () => 'hubspot_ticket_created', - required: true, - }, - { - id: 'clientId', - title: 'Client ID', - type: 'short-input', - placeholder: 'Enter your HubSpot app Client ID', - description: 'Found in your HubSpot app settings under Auth tab', - required: true, - mode: 'trigger', - condition: { - field: 'selectedTriggerId', - value: 'hubspot_ticket_created', - }, - }, - { - id: 'clientSecret', - title: 'Client Secret', - type: 'short-input', - placeholder: 'Enter your HubSpot app Client Secret', - description: 'Found in your HubSpot app settings under Auth tab', - password: true, - required: true, - mode: 'trigger', - condition: { - field: 'selectedTriggerId', - value: 'hubspot_ticket_created', - }, - }, - { - id: 'appId', - title: 'App ID', - type: 'short-input', - placeholder: 'Enter your HubSpot App ID', - description: 'Found in your HubSpot app settings. Used to identify your app.', - required: true, - mode: 'trigger', - condition: { - field: 'selectedTriggerId', - value: 'hubspot_ticket_created', - }, - }, - { - id: 'developerApiKey', - title: 'Developer API Key', - type: 'short-input', - placeholder: 'Enter your HubSpot Developer API Key', - description: 'Used for making API calls to HubSpot. Found in your HubSpot app settings.', - password: true, - required: true, - mode: 'trigger', - condition: { - field: 'selectedTriggerId', - value: 'hubspot_ticket_created', - }, - }, - { - id: 'webhookUrlDisplay', - title: 'Webhook URL', - type: 'short-input', - readOnly: true, - showCopyButton: true, - useWebhookUrl: true, - placeholder: 'Webhook URL will be generated', - description: 'Copy this URL and paste it into your HubSpot app webhook subscription settings', - mode: 'trigger', - condition: { - field: 'selectedTriggerId', - value: 'hubspot_ticket_created', - }, - }, - { - id: 'triggerInstructions', - title: 'Setup Instructions', - type: 'text', - defaultValue: hubspotSetupInstructions( - 'ticket.creation', - 'The webhook will trigger whenever a new ticket is created in your HubSpot account, regardless of the source (manual entry, form submission, API, import, etc.).' - ), - mode: 'trigger', - condition: { - field: 'selectedTriggerId', - value: 'hubspot_ticket_created', - }, - }, - { - id: 'curlSetWebhookUrl', - title: '1. Set Webhook Target URL', - type: 'code', - language: 'javascript', - value: (params: Record) => { - const webhookUrl = params.webhookUrlDisplay || '{YOUR_WEBHOOK_URL_FROM_ABOVE}' - return `curl -X PUT "https://api.hubapi.com/webhooks/v3/{YOUR_APP_ID}/settings?hapikey={YOUR_DEVELOPER_API_KEY}" \\ - -H "Content-Type: application/json" \\ - -d '{ - "targetUrl": "${webhookUrl}", - "throttling": { - "maxConcurrentRequests": 10 - } - }'` - }, - readOnly: true, - collapsible: true, - defaultCollapsed: true, - showCopyButton: true, - description: 'Run this command to set your webhook URL in HubSpot', - mode: 'trigger', - condition: { - field: 'selectedTriggerId', - value: 'hubspot_ticket_created', - }, - }, - { - id: 'curlCreateSubscription', - title: '2. Create Webhook Subscription', - type: 'code', - language: 'javascript', - defaultValue: `curl -X POST "https://api.hubapi.com/webhooks/v3/{YOUR_APP_ID}/subscriptions?hapikey={YOUR_DEVELOPER_API_KEY}" \\ - -H "Content-Type: application/json" \\ - -d '{ - "eventType": "ticket.creation", - "active": true - }'`, - readOnly: true, - collapsible: true, - defaultCollapsed: true, - showCopyButton: true, - description: 'Run this command to subscribe to ticket creation events', - mode: 'trigger', - condition: { - field: 'selectedTriggerId', - value: 'hubspot_ticket_created', - }, - }, - { - id: 'samplePayload', - title: 'Event Payload Example', - type: 'code', - language: 'json', - defaultValue: JSON.stringify( - [ - { - eventId: 3181526830, - subscriptionId: 4629990, - portalId: 244315265, - appId: 23608917, - occurredAt: 1762659213730, - subscriptionType: 'ticket.creation', - attemptNumber: 0, - objectId: 316126906070, - changeFlag: 'CREATED', - changeSource: 'CRM_UI', - sourceId: 'userId:84916424', - }, - ], - null, - 2 - ), - readOnly: true, - collapsible: true, - defaultCollapsed: true, - mode: 'trigger', - condition: { - field: 'selectedTriggerId', - value: 'hubspot_ticket_created', - }, - }, - ], - - outputs: buildTicketCreatedOutputs(), - - webhook: { - method: 'POST', - headers: { - 'Content-Type': 'application/json', - 'X-HubSpot-Signature': 'sha256=...', - 'X-HubSpot-Request-Id': 'xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx', - 'User-Agent': 'HubSpot Webhooks', - }, - }, -} diff --git a/apps/sim/triggers/hubspot/ticket_deleted.ts b/apps/sim/triggers/hubspot/ticket_deleted.ts deleted file mode 100644 index d1152c32e61..00000000000 --- a/apps/sim/triggers/hubspot/ticket_deleted.ts +++ /dev/null @@ -1,205 +0,0 @@ -import { HubspotIcon } from '@/components/icons' -import { - buildTicketDeletedOutputs, - hubspotSetupInstructions, - hubspotTicketTriggerOptions, -} from '@/triggers/hubspot/utils' -import type { TriggerConfig } from '@/triggers/types' - -export const hubspotTicketDeletedTrigger: TriggerConfig = { - id: 'hubspot_ticket_deleted', - name: 'HubSpot Ticket Deleted', - provider: 'hubspot', - description: 'Trigger workflow when a ticket is deleted in HubSpot', - version: '1.0.0', - icon: HubspotIcon, - - subBlocks: [ - { - id: 'selectedTriggerId', - title: 'Trigger Type', - type: 'dropdown', - mode: 'trigger', - options: hubspotTicketTriggerOptions, - value: () => 'hubspot_ticket_deleted', - required: true, - }, - { - id: 'clientId', - title: 'Client ID', - type: 'short-input', - placeholder: 'Enter your HubSpot app Client ID', - description: 'Found in your HubSpot app settings under Auth tab', - required: true, - mode: 'trigger', - condition: { - field: 'selectedTriggerId', - value: 'hubspot_ticket_deleted', - }, - }, - { - id: 'clientSecret', - title: 'Client Secret', - type: 'short-input', - placeholder: 'Enter your HubSpot app Client Secret', - description: 'Found in your HubSpot app settings under Auth tab', - password: true, - required: true, - mode: 'trigger', - condition: { - field: 'selectedTriggerId', - value: 'hubspot_ticket_deleted', - }, - }, - { - id: 'appId', - title: 'App ID', - type: 'short-input', - placeholder: 'Enter your HubSpot App ID', - description: 'Found in your HubSpot app settings. Used to identify your app.', - required: true, - mode: 'trigger', - condition: { - field: 'selectedTriggerId', - value: 'hubspot_ticket_deleted', - }, - }, - { - id: 'developerApiKey', - title: 'Developer API Key', - type: 'short-input', - placeholder: 'Enter your HubSpot Developer API Key', - description: 'Used for making API calls to HubSpot. Found in your HubSpot app settings.', - password: true, - required: true, - mode: 'trigger', - condition: { - field: 'selectedTriggerId', - value: 'hubspot_ticket_deleted', - }, - }, - { - id: 'webhookUrlDisplay', - title: 'Webhook URL', - type: 'short-input', - readOnly: true, - showCopyButton: true, - useWebhookUrl: true, - placeholder: 'Webhook URL will be generated', - description: 'Copy this URL and paste it into your HubSpot app webhook subscription settings', - mode: 'trigger', - condition: { - field: 'selectedTriggerId', - value: 'hubspot_ticket_deleted', - }, - }, - { - id: 'triggerInstructions', - title: 'Setup Instructions', - type: 'text', - defaultValue: hubspotSetupInstructions( - 'ticket.deletion', - 'The webhook will trigger whenever a ticket is deleted from your HubSpot account.' - ), - mode: 'trigger', - condition: { - field: 'selectedTriggerId', - value: 'hubspot_ticket_deleted', - }, - }, - { - id: 'curlSetWebhookUrl', - title: '1. Set Webhook Target URL', - type: 'code', - language: 'javascript', - value: (params: Record) => { - const webhookUrl = params.webhookUrlDisplay || '{YOUR_WEBHOOK_URL_FROM_ABOVE}' - return `curl -X PUT "https://api.hubapi.com/webhooks/v3/{YOUR_APP_ID}/settings?hapikey={YOUR_DEVELOPER_API_KEY}" \\ - -H "Content-Type: application/json" \\ - -d '{ - "targetUrl": "${webhookUrl}", - "throttling": { - "maxConcurrentRequests": 10 - } - }'` - }, - readOnly: true, - collapsible: true, - defaultCollapsed: true, - showCopyButton: true, - description: 'Run this command to set your webhook URL in HubSpot', - mode: 'trigger', - condition: { - field: 'selectedTriggerId', - value: 'hubspot_ticket_deleted', - }, - }, - { - id: 'curlCreateSubscription', - title: '2. Create Webhook Subscription', - type: 'code', - language: 'javascript', - defaultValue: `curl -X POST "https://api.hubapi.com/webhooks/v3/{YOUR_APP_ID}/subscriptions?hapikey={YOUR_DEVELOPER_API_KEY}" \\ - -H "Content-Type: application/json" \\ - -d '{ - "eventType": "ticket.deletion", - "active": true - }'`, - readOnly: true, - collapsible: true, - defaultCollapsed: true, - showCopyButton: true, - description: 'Run this command to subscribe to ticket deletion events', - mode: 'trigger', - condition: { - field: 'selectedTriggerId', - value: 'hubspot_ticket_deleted', - }, - }, - { - id: 'samplePayload', - title: 'Event Payload Example', - type: 'code', - language: 'json', - defaultValue: JSON.stringify( - [ - { - eventId: 3181526831, - subscriptionId: 4629991, - portalId: 244315265, - appId: 23608917, - occurredAt: 1762659213730, - subscriptionType: 'ticket.deletion', - attemptNumber: 0, - objectId: 316126906070, - changeFlag: 'DELETED', - changeSource: 'CRM_UI', - sourceId: 'userId:84916424', - }, - ], - null, - 2 - ), - readOnly: true, - collapsible: true, - defaultCollapsed: true, - mode: 'trigger', - condition: { - field: 'selectedTriggerId', - value: 'hubspot_ticket_deleted', - }, - }, - ], - - outputs: buildTicketDeletedOutputs(), - - webhook: { - method: 'POST', - headers: { - 'Content-Type': 'application/json', - 'X-HubSpot-Signature': 'sha256=...', - 'X-HubSpot-Request-Id': 'xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx', - 'User-Agent': 'HubSpot Webhooks', - }, - }, -} diff --git a/apps/sim/triggers/hubspot/ticket_merged.ts b/apps/sim/triggers/hubspot/ticket_merged.ts deleted file mode 100644 index 737f3c81ef6..00000000000 --- a/apps/sim/triggers/hubspot/ticket_merged.ts +++ /dev/null @@ -1,206 +0,0 @@ -import { HubspotIcon } from '@/components/icons' -import { - buildTicketMergedOutputs, - hubspotSetupInstructions, - hubspotTicketTriggerOptions, -} from '@/triggers/hubspot/utils' -import type { TriggerConfig } from '@/triggers/types' - -export const hubspotTicketMergedTrigger: TriggerConfig = { - id: 'hubspot_ticket_merged', - name: 'HubSpot Ticket Merged', - provider: 'hubspot', - description: 'Trigger workflow when tickets are merged in HubSpot', - version: '1.0.0', - icon: HubspotIcon, - - subBlocks: [ - { - id: 'selectedTriggerId', - title: 'Trigger Type', - type: 'dropdown', - mode: 'trigger', - options: hubspotTicketTriggerOptions, - value: () => 'hubspot_ticket_merged', - required: true, - }, - { - id: 'clientId', - title: 'Client ID', - type: 'short-input', - placeholder: 'Enter your HubSpot app Client ID', - description: 'Found in your HubSpot app settings under Auth tab', - required: true, - mode: 'trigger', - condition: { - field: 'selectedTriggerId', - value: 'hubspot_ticket_merged', - }, - }, - { - id: 'clientSecret', - title: 'Client Secret', - type: 'short-input', - placeholder: 'Enter your HubSpot app Client Secret', - description: 'Found in your HubSpot app settings under Auth tab', - password: true, - required: true, - mode: 'trigger', - condition: { - field: 'selectedTriggerId', - value: 'hubspot_ticket_merged', - }, - }, - { - id: 'appId', - title: 'App ID', - type: 'short-input', - placeholder: 'Enter your HubSpot App ID', - description: 'Found in your HubSpot app settings. Used to identify your app.', - required: true, - mode: 'trigger', - condition: { - field: 'selectedTriggerId', - value: 'hubspot_ticket_merged', - }, - }, - { - id: 'developerApiKey', - title: 'Developer API Key', - type: 'short-input', - placeholder: 'Enter your HubSpot Developer API Key', - description: 'Used for making API calls to HubSpot. Found in your HubSpot app settings.', - password: true, - required: true, - mode: 'trigger', - condition: { - field: 'selectedTriggerId', - value: 'hubspot_ticket_merged', - }, - }, - { - id: 'webhookUrlDisplay', - title: 'Webhook URL', - type: 'short-input', - readOnly: true, - showCopyButton: true, - useWebhookUrl: true, - placeholder: 'Webhook URL will be generated', - description: 'Copy this URL and paste it into your HubSpot app webhook subscription settings', - mode: 'trigger', - condition: { - field: 'selectedTriggerId', - value: 'hubspot_ticket_merged', - }, - }, - { - id: 'triggerInstructions', - title: 'Setup Instructions', - type: 'text', - defaultValue: hubspotSetupInstructions( - 'ticket.merge', - 'The webhook will trigger whenever two tickets are merged in your HubSpot account. The objectId will be the winning (primary) ticket ID.' - ), - mode: 'trigger', - condition: { - field: 'selectedTriggerId', - value: 'hubspot_ticket_merged', - }, - }, - { - id: 'curlSetWebhookUrl', - title: '1. Set Webhook Target URL', - type: 'code', - language: 'javascript', - value: (params: Record) => { - const webhookUrl = params.webhookUrlDisplay || '{YOUR_WEBHOOK_URL_FROM_ABOVE}' - return `curl -X PUT "https://api.hubapi.com/webhooks/v3/{YOUR_APP_ID}/settings?hapikey={YOUR_DEVELOPER_API_KEY}" \\ - -H "Content-Type: application/json" \\ - -d '{ - "targetUrl": "${webhookUrl}", - "throttling": { - "maxConcurrentRequests": 10 - } - }'` - }, - readOnly: true, - collapsible: true, - defaultCollapsed: true, - showCopyButton: true, - description: 'Run this command to set your webhook URL in HubSpot', - mode: 'trigger', - condition: { - field: 'selectedTriggerId', - value: 'hubspot_ticket_merged', - }, - }, - { - id: 'curlCreateSubscription', - title: '2. Create Webhook Subscription', - type: 'code', - language: 'javascript', - defaultValue: `curl -X POST "https://api.hubapi.com/webhooks/v3/{YOUR_APP_ID}/subscriptions?hapikey={YOUR_DEVELOPER_API_KEY}" \\ - -H "Content-Type: application/json" \\ - -d '{ - "eventType": "ticket.merge", - "active": true - }'`, - readOnly: true, - collapsible: true, - defaultCollapsed: true, - showCopyButton: true, - description: 'Run this command to subscribe to ticket merge events', - mode: 'trigger', - condition: { - field: 'selectedTriggerId', - value: 'hubspot_ticket_merged', - }, - }, - { - id: 'samplePayload', - title: 'Event Payload Example', - type: 'code', - language: 'json', - defaultValue: JSON.stringify( - [ - { - eventId: 3181526817, - subscriptionId: 4629978, - portalId: 244315265, - appId: 23608917, - occurredAt: 1762659213730, - subscriptionType: 'ticket.merge', - attemptNumber: 0, - objectId: 516126906049, - changeFlag: 'MERGED', - changeSource: 'CRM_UI', - sourceId: 'userId:84916424', - mergedObjectIds: [516126906050], - }, - ], - null, - 2 - ), - readOnly: true, - collapsible: true, - defaultCollapsed: true, - mode: 'trigger', - condition: { - field: 'selectedTriggerId', - value: 'hubspot_ticket_merged', - }, - }, - ], - - outputs: buildTicketMergedOutputs(), - - webhook: { - method: 'POST', - headers: { - 'Content-Type': 'application/json', - 'X-HubSpot-Signature': 'sha256=...', - 'X-HubSpot-Request-Id': 'xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx', - 'User-Agent': 'HubSpot Webhooks', - }, - }, -} diff --git a/apps/sim/triggers/hubspot/ticket_property_changed.ts b/apps/sim/triggers/hubspot/ticket_property_changed.ts deleted file mode 100644 index 104a77b5524..00000000000 --- a/apps/sim/triggers/hubspot/ticket_property_changed.ts +++ /dev/null @@ -1,221 +0,0 @@ -import { HubspotIcon } from '@/components/icons' -import { - buildTicketPropertyChangedOutputs, - hubspotSetupInstructions, - hubspotTicketTriggerOptions, -} from '@/triggers/hubspot/utils' -import type { TriggerConfig } from '@/triggers/types' - -export const hubspotTicketPropertyChangedTrigger: TriggerConfig = { - id: 'hubspot_ticket_property_changed', - name: 'HubSpot Ticket Property Changed', - provider: 'hubspot', - description: 'Trigger workflow when any property of a ticket is updated in HubSpot', - version: '1.0.0', - icon: HubspotIcon, - - subBlocks: [ - { - id: 'selectedTriggerId', - title: 'Trigger Type', - type: 'dropdown', - mode: 'trigger', - options: hubspotTicketTriggerOptions, - value: () => 'hubspot_ticket_property_changed', - required: true, - }, - { - id: 'clientId', - title: 'Client ID', - type: 'short-input', - placeholder: 'Enter your HubSpot app Client ID', - description: 'Found in your HubSpot app settings under Auth tab', - required: true, - mode: 'trigger', - condition: { - field: 'selectedTriggerId', - value: 'hubspot_ticket_property_changed', - }, - }, - { - id: 'clientSecret', - title: 'Client Secret', - type: 'short-input', - placeholder: 'Enter your HubSpot app Client Secret', - description: 'Found in your HubSpot app settings under Auth tab', - password: true, - required: true, - mode: 'trigger', - condition: { - field: 'selectedTriggerId', - value: 'hubspot_ticket_property_changed', - }, - }, - { - id: 'appId', - title: 'App ID', - type: 'short-input', - placeholder: 'Enter your HubSpot App ID', - description: 'Found in your HubSpot app settings. Used to identify your app.', - required: true, - mode: 'trigger', - condition: { - field: 'selectedTriggerId', - value: 'hubspot_ticket_property_changed', - }, - }, - { - id: 'developerApiKey', - title: 'Developer API Key', - type: 'short-input', - placeholder: 'Enter your HubSpot Developer API Key', - description: 'Used for making API calls to HubSpot. Found in your HubSpot app settings.', - password: true, - required: true, - mode: 'trigger', - condition: { - field: 'selectedTriggerId', - value: 'hubspot_ticket_property_changed', - }, - }, - { - id: 'webhookUrlDisplay', - title: 'Webhook URL', - type: 'short-input', - readOnly: true, - showCopyButton: true, - useWebhookUrl: true, - placeholder: 'Webhook URL will be generated', - description: 'Copy this URL and paste it into your HubSpot app webhook subscription settings', - mode: 'trigger', - condition: { - field: 'selectedTriggerId', - value: 'hubspot_ticket_property_changed', - }, - }, - { - id: 'propertyName', - title: 'Property Name (Optional)', - type: 'short-input', - placeholder: 'e.g., hs_pipeline_stage, hs_ticket_priority', - description: - 'Optional: Filter to only trigger when a specific property changes. Leave empty to trigger on any property change.', - required: false, - mode: 'trigger', - condition: { - field: 'selectedTriggerId', - value: 'hubspot_ticket_property_changed', - }, - }, - { - id: 'triggerInstructions', - title: 'Setup Instructions', - type: 'text', - defaultValue: hubspotSetupInstructions( - 'ticket.propertyChange', - 'The webhook will trigger whenever any property of a ticket is updated. You can optionally filter by a specific property name to only receive events for that property. The webhook provides both the property name and new value in the payload.' - ), - mode: 'trigger', - condition: { - field: 'selectedTriggerId', - value: 'hubspot_ticket_property_changed', - }, - }, - { - id: 'curlSetWebhookUrl', - title: '1. Set Webhook Target URL', - type: 'code', - language: 'javascript', - value: (params: Record) => { - const webhookUrl = params.webhookUrlDisplay || '{YOUR_WEBHOOK_URL_FROM_ABOVE}' - return `curl -X PUT "https://api.hubapi.com/webhooks/v3/{YOUR_APP_ID}/settings?hapikey={YOUR_DEVELOPER_API_KEY}" \\ - -H "Content-Type: application/json" \\ - -d '{ - "targetUrl": "${webhookUrl}", - "throttling": { - "maxConcurrentRequests": 10 - } - }'` - }, - readOnly: true, - collapsible: true, - defaultCollapsed: true, - showCopyButton: true, - description: 'Run this command to set your webhook URL in HubSpot', - mode: 'trigger', - condition: { - field: 'selectedTriggerId', - value: 'hubspot_ticket_property_changed', - }, - }, - { - id: 'curlCreateSubscription', - title: '2. Create Webhook Subscription', - type: 'code', - language: 'javascript', - defaultValue: `curl -X POST "https://api.hubapi.com/webhooks/v3/{YOUR_APP_ID}/subscriptions?hapikey={YOUR_DEVELOPER_API_KEY}" \\ - -H "Content-Type: application/json" \\ - -d '{ - "eventType": "ticket.propertyChange", - "active": true - }'`, - readOnly: true, - collapsible: true, - defaultCollapsed: true, - showCopyButton: true, - description: 'Run this command to subscribe to ticket property change events', - mode: 'trigger', - condition: { - field: 'selectedTriggerId', - value: 'hubspot_ticket_property_changed', - }, - }, - { - id: 'samplePayload', - title: 'Event Payload Example', - type: 'code', - language: 'json', - defaultValue: JSON.stringify( - [ - { - eventId: 3181526832, - subscriptionId: 4629992, - portalId: 244315265, - appId: 23608917, - occurredAt: 1762659213730, - subscriptionType: 'ticket.propertyChange', - attemptNumber: 0, - objectId: 316126906070, - propertyName: 'hs_pipeline_stage', - propertyValue: 'closed', - changeFlag: 'UPDATED', - changeSource: 'CRM_UI', - sourceId: 'userId:84916424', - }, - ], - null, - 2 - ), - readOnly: true, - collapsible: true, - defaultCollapsed: true, - mode: 'trigger', - condition: { - field: 'selectedTriggerId', - value: 'hubspot_ticket_property_changed', - }, - }, - ], - - outputs: buildTicketPropertyChangedOutputs(), - - webhook: { - method: 'POST', - headers: { - 'Content-Type': 'application/json', - 'X-HubSpot-Signature': 'sha256=...', - 'X-HubSpot-Request-Id': 'xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx', - 'User-Agent': 'HubSpot Webhooks', - }, - }, -} diff --git a/apps/sim/triggers/hubspot/ticket_restored.ts b/apps/sim/triggers/hubspot/ticket_restored.ts deleted file mode 100644 index 18e8cded6bb..00000000000 --- a/apps/sim/triggers/hubspot/ticket_restored.ts +++ /dev/null @@ -1,205 +0,0 @@ -import { HubspotIcon } from '@/components/icons' -import { - buildTicketRestoredOutputs, - hubspotSetupInstructions, - hubspotTicketTriggerOptions, -} from '@/triggers/hubspot/utils' -import type { TriggerConfig } from '@/triggers/types' - -export const hubspotTicketRestoredTrigger: TriggerConfig = { - id: 'hubspot_ticket_restored', - name: 'HubSpot Ticket Restored', - provider: 'hubspot', - description: 'Trigger workflow when a deleted ticket is restored in HubSpot', - version: '1.0.0', - icon: HubspotIcon, - - subBlocks: [ - { - id: 'selectedTriggerId', - title: 'Trigger Type', - type: 'dropdown', - mode: 'trigger', - options: hubspotTicketTriggerOptions, - value: () => 'hubspot_ticket_restored', - required: true, - }, - { - id: 'clientId', - title: 'Client ID', - type: 'short-input', - placeholder: 'Enter your HubSpot app Client ID', - description: 'Found in your HubSpot app settings under Auth tab', - required: true, - mode: 'trigger', - condition: { - field: 'selectedTriggerId', - value: 'hubspot_ticket_restored', - }, - }, - { - id: 'clientSecret', - title: 'Client Secret', - type: 'short-input', - placeholder: 'Enter your HubSpot app Client Secret', - description: 'Found in your HubSpot app settings under Auth tab', - password: true, - required: true, - mode: 'trigger', - condition: { - field: 'selectedTriggerId', - value: 'hubspot_ticket_restored', - }, - }, - { - id: 'appId', - title: 'App ID', - type: 'short-input', - placeholder: 'Enter your HubSpot App ID', - description: 'Found in your HubSpot app settings. Used to identify your app.', - required: true, - mode: 'trigger', - condition: { - field: 'selectedTriggerId', - value: 'hubspot_ticket_restored', - }, - }, - { - id: 'developerApiKey', - title: 'Developer API Key', - type: 'short-input', - placeholder: 'Enter your HubSpot Developer API Key', - description: 'Used for making API calls to HubSpot. Found in your HubSpot app settings.', - password: true, - required: true, - mode: 'trigger', - condition: { - field: 'selectedTriggerId', - value: 'hubspot_ticket_restored', - }, - }, - { - id: 'webhookUrlDisplay', - title: 'Webhook URL', - type: 'short-input', - readOnly: true, - showCopyButton: true, - useWebhookUrl: true, - placeholder: 'Webhook URL will be generated', - description: 'Copy this URL and paste it into your HubSpot app webhook subscription settings', - mode: 'trigger', - condition: { - field: 'selectedTriggerId', - value: 'hubspot_ticket_restored', - }, - }, - { - id: 'triggerInstructions', - title: 'Setup Instructions', - type: 'text', - defaultValue: hubspotSetupInstructions( - 'ticket.restore', - 'The webhook will trigger whenever a previously deleted ticket is restored in your HubSpot account.' - ), - mode: 'trigger', - condition: { - field: 'selectedTriggerId', - value: 'hubspot_ticket_restored', - }, - }, - { - id: 'curlSetWebhookUrl', - title: '1. Set Webhook Target URL', - type: 'code', - language: 'javascript', - value: (params: Record) => { - const webhookUrl = params.webhookUrlDisplay || '{YOUR_WEBHOOK_URL_FROM_ABOVE}' - return `curl -X PUT "https://api.hubapi.com/webhooks/v3/{YOUR_APP_ID}/settings?hapikey={YOUR_DEVELOPER_API_KEY}" \\ - -H "Content-Type: application/json" \\ - -d '{ - "targetUrl": "${webhookUrl}", - "throttling": { - "maxConcurrentRequests": 10 - } - }'` - }, - readOnly: true, - collapsible: true, - defaultCollapsed: true, - showCopyButton: true, - description: 'Run this command to set your webhook URL in HubSpot', - mode: 'trigger', - condition: { - field: 'selectedTriggerId', - value: 'hubspot_ticket_restored', - }, - }, - { - id: 'curlCreateSubscription', - title: '2. Create Webhook Subscription', - type: 'code', - language: 'javascript', - defaultValue: `curl -X POST "https://api.hubapi.com/webhooks/v3/{YOUR_APP_ID}/subscriptions?hapikey={YOUR_DEVELOPER_API_KEY}" \\ - -H "Content-Type: application/json" \\ - -d '{ - "eventType": "ticket.restore", - "active": true - }'`, - readOnly: true, - collapsible: true, - defaultCollapsed: true, - showCopyButton: true, - description: 'Run this command to subscribe to ticket restore events', - mode: 'trigger', - condition: { - field: 'selectedTriggerId', - value: 'hubspot_ticket_restored', - }, - }, - { - id: 'samplePayload', - title: 'Event Payload Example', - type: 'code', - language: 'json', - defaultValue: JSON.stringify( - [ - { - eventId: 3181526818, - subscriptionId: 4629979, - portalId: 244315265, - appId: 23608917, - occurredAt: 1762659213730, - subscriptionType: 'ticket.restore', - attemptNumber: 0, - objectId: 516126906049, - changeFlag: 'RESTORED', - changeSource: 'CRM_UI', - sourceId: 'userId:84916424', - }, - ], - null, - 2 - ), - readOnly: true, - collapsible: true, - defaultCollapsed: true, - mode: 'trigger', - condition: { - field: 'selectedTriggerId', - value: 'hubspot_ticket_restored', - }, - }, - ], - - outputs: buildTicketRestoredOutputs(), - - webhook: { - method: 'POST', - headers: { - 'Content-Type': 'application/json', - 'X-HubSpot-Signature': 'sha256=...', - 'X-HubSpot-Request-Id': 'xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx', - 'User-Agent': 'HubSpot Webhooks', - }, - }, -} diff --git a/apps/sim/triggers/hubspot/utils.ts b/apps/sim/triggers/hubspot/utils.ts deleted file mode 100644 index fa601b5980a..00000000000 --- a/apps/sim/triggers/hubspot/utils.ts +++ /dev/null @@ -1,503 +0,0 @@ -import type { TriggerOutput } from '@/triggers/types' - -/** - * Combined trigger dropdown options for all HubSpot triggers (for block config) - */ -export const hubspotAllTriggerOptions = [ - { label: 'Contact Created', id: 'hubspot_contact_created' }, - { label: 'Contact Deleted', id: 'hubspot_contact_deleted' }, - { label: 'Contact Merged', id: 'hubspot_contact_merged' }, - { label: 'Contact Privacy Deleted', id: 'hubspot_contact_privacy_deleted' }, - { label: 'Contact Property Changed', id: 'hubspot_contact_property_changed' }, - { label: 'Contact Restored', id: 'hubspot_contact_restored' }, - { label: 'Company Created', id: 'hubspot_company_created' }, - { label: 'Company Deleted', id: 'hubspot_company_deleted' }, - { label: 'Company Merged', id: 'hubspot_company_merged' }, - { label: 'Company Property Changed', id: 'hubspot_company_property_changed' }, - { label: 'Company Restored', id: 'hubspot_company_restored' }, - { label: 'Conversation Creation', id: 'hubspot_conversation_creation' }, - { label: 'Conversation Deletion', id: 'hubspot_conversation_deletion' }, - { label: 'Conversation New Message', id: 'hubspot_conversation_new_message' }, - { label: 'Conversation Privacy Deletion', id: 'hubspot_conversation_privacy_deletion' }, - { label: 'Conversation Property Changed', id: 'hubspot_conversation_property_changed' }, - { label: 'Deal Created', id: 'hubspot_deal_created' }, - { label: 'Deal Deleted', id: 'hubspot_deal_deleted' }, - { label: 'Deal Merged', id: 'hubspot_deal_merged' }, - { label: 'Deal Property Changed', id: 'hubspot_deal_property_changed' }, - { label: 'Deal Restored', id: 'hubspot_deal_restored' }, - { label: 'Ticket Created', id: 'hubspot_ticket_created' }, - { label: 'Ticket Deleted', id: 'hubspot_ticket_deleted' }, - { label: 'Ticket Merged', id: 'hubspot_ticket_merged' }, - { label: 'Ticket Property Changed', id: 'hubspot_ticket_property_changed' }, - { label: 'Ticket Restored', id: 'hubspot_ticket_restored' }, - { label: 'Generic Webhook (All Events)', id: 'hubspot_webhook' }, -] - -/** - * Shared trigger dropdown options for all HubSpot contact triggers - */ -export const hubspotContactTriggerOptions = [ - { label: 'Contact Created', id: 'hubspot_contact_created' }, - { label: 'Contact Deleted', id: 'hubspot_contact_deleted' }, - { label: 'Contact Merged', id: 'hubspot_contact_merged' }, - { label: 'Contact Privacy Deleted', id: 'hubspot_contact_privacy_deleted' }, - { label: 'Contact Property Changed', id: 'hubspot_contact_property_changed' }, - { label: 'Contact Restored', id: 'hubspot_contact_restored' }, -] - -/** - * Shared trigger dropdown options for all HubSpot company triggers - */ -export const hubspotCompanyTriggerOptions = [ - { label: 'Company Created', id: 'hubspot_company_created' }, - { label: 'Company Deleted', id: 'hubspot_company_deleted' }, - { label: 'Company Merged', id: 'hubspot_company_merged' }, - { label: 'Company Property Changed', id: 'hubspot_company_property_changed' }, - { label: 'Company Restored', id: 'hubspot_company_restored' }, -] - -/** - * Shared trigger dropdown options for all HubSpot conversation triggers - */ -export const hubspotConversationTriggerOptions = [ - { label: 'Conversation Creation', id: 'hubspot_conversation_creation' }, - { label: 'Conversation Deletion', id: 'hubspot_conversation_deletion' }, - { label: 'Conversation New Message', id: 'hubspot_conversation_new_message' }, - { label: 'Conversation Privacy Deletion', id: 'hubspot_conversation_privacy_deletion' }, - { label: 'Conversation Property Changed', id: 'hubspot_conversation_property_changed' }, -] - -/** - * Shared trigger dropdown options for all HubSpot deal triggers - */ -export const hubspotDealTriggerOptions = [ - { label: 'Deal Created', id: 'hubspot_deal_created' }, - { label: 'Deal Deleted', id: 'hubspot_deal_deleted' }, - { label: 'Deal Merged', id: 'hubspot_deal_merged' }, - { label: 'Deal Property Changed', id: 'hubspot_deal_property_changed' }, - { label: 'Deal Restored', id: 'hubspot_deal_restored' }, -] - -/** - * Shared trigger dropdown options for all HubSpot ticket triggers - */ -export const hubspotTicketTriggerOptions = [ - { label: 'Ticket Created', id: 'hubspot_ticket_created' }, - { label: 'Ticket Deleted', id: 'hubspot_ticket_deleted' }, - { label: 'Ticket Merged', id: 'hubspot_ticket_merged' }, - { label: 'Ticket Property Changed', id: 'hubspot_ticket_property_changed' }, - { label: 'Ticket Restored', id: 'hubspot_ticket_restored' }, -] - -/** - * Derives the required OAuth scope from a HubSpot event type - */ -function getScopeForEventType(eventType: string): string { - if (eventType.startsWith('company')) return 'crm.objects.companies.read' - if (eventType.startsWith('deal')) return 'crm.objects.deals.read' - if (eventType.startsWith('ticket')) return 'tickets' - if (eventType === 'All Events') - return 'crm.objects.contacts.read, crm.objects.companies.read, crm.objects.deals.read, tickets' - return 'crm.objects.contacts.read' -} - -/** - * Generate setup instructions for a specific HubSpot event type - */ -export function hubspotSetupInstructions(eventType: string, additionalNotes?: string): string { - const scope = getScopeForEventType(eventType) - const instructions = [ - 'Step 1: Create a HubSpot Developer Account
Sign up for a free developer account at developers.hubspot.com if you don\'t have one.', - 'Step 2: Create a Public App via CLI
Note: HubSpot has deprecated the web UI for creating apps. You must use the HubSpot CLI to create and manage apps. Install the CLI with npm install -g @hubspot/cli and run hs project create to create a new app. See HubSpot\'s documentation for details.', - 'Step 3: Configure OAuth Settings
After creating your app via CLI, configure it to add the OAuth Redirect URL: https://www.sim.ai/api/auth/oauth2/callback/hubspot. Then retrieve your Client ID and Client Secret from your app configuration and enter them in the fields above.', - "Step 4: Get App ID and Developer API Key
In your HubSpot developer account, find your App ID (shown below your app name) and your Developer API Key (in app settings). You'll need both for the next steps.", - `Step 5: Set Required Scopes
Configure your app to include the required OAuth scope(s): ${scope}`, - 'Step 6: Configure Webhook in HubSpot via API
After saving above, copy the Webhook URL and run the two curl commands below (replace {YOUR_APP_ID}, {YOUR_DEVELOPER_API_KEY}, and {YOUR_WEBHOOK_URL_FROM_ABOVE} with your actual values).', - "Step 7: Test Your Webhook
Create or modify a contact in HubSpot to trigger the webhook. Check your workflow execution logs in Sim to verify it's working.", - ] - - if (additionalNotes) { - instructions.push(`Additional Info: ${additionalNotes}`) - } - - return instructions.map((instruction, index) => `
${instruction}
`).join('') -} - -/** - * Base webhook outputs that are common to all HubSpot triggers - * Clean structure with payload, provider, and providerConfig at root level - */ -function buildBaseHubSpotOutputs(): Record { - return { - payload: { - type: 'array', - description: 'Full webhook payload array from HubSpot containing event details', - items: { - type: 'object', - properties: { - objectId: { type: 'number', description: 'HubSpot object ID' }, - subscriptionType: { type: 'string', description: 'Type of subscription event' }, - portalId: { type: 'number', description: 'HubSpot portal ID' }, - occurredAt: { type: 'number', description: 'Timestamp when event occurred (ms)' }, - attemptNumber: { type: 'number', description: 'Webhook delivery attempt number' }, - eventId: { type: 'number', description: 'Event ID' }, - changeSource: { type: 'string', description: 'Source of the change' }, - propertyName: { - type: 'string', - description: 'Property name (for propertyChange events)', - }, - propertyValue: { - type: 'string', - description: 'New property value (for propertyChange events)', - }, - }, - }, - }, - provider: { - type: 'string', - description: 'Provider name (hubspot)', - }, - providerConfig: { - type: 'object', - description: 'Provider configuration', - properties: { - appId: { - type: 'string', - description: 'HubSpot App ID', - }, - clientId: { - type: 'string', - description: 'HubSpot Client ID', - }, - triggerId: { - type: 'string', - description: 'Trigger ID (e.g., hubspot_company_created)', - }, - clientSecret: { - type: 'string', - description: 'HubSpot Client Secret', - }, - developerApiKey: { - type: 'string', - description: 'HubSpot Developer API Key', - }, - curlSetWebhookUrl: { - type: 'string', - description: 'curl command to set webhook URL', - }, - curlCreateSubscription: { - type: 'string', - description: 'curl command to create subscription', - }, - webhookUrlDisplay: { - type: 'string', - description: 'Webhook URL display value', - }, - propertyName: { - type: 'string', - description: 'Optional property name filter (for property change triggers)', - }, - }, - }, - } as any -} - -/** - * Merge-specific webhook outputs that include mergedObjectIds - */ -function buildMergeHubSpotOutputs(): Record { - return { - payload: { - type: 'array', - description: 'Full webhook payload array from HubSpot containing merge event details', - items: { - type: 'object', - properties: { - objectId: { type: 'number', description: 'HubSpot object ID (winning/primary record)' }, - subscriptionType: { type: 'string', description: 'Type of subscription event' }, - portalId: { type: 'number', description: 'HubSpot portal ID' }, - occurredAt: { type: 'number', description: 'Timestamp when event occurred (ms)' }, - attemptNumber: { type: 'number', description: 'Webhook delivery attempt number' }, - eventId: { type: 'number', description: 'Event ID' }, - changeSource: { type: 'string', description: 'Source of the change' }, - mergedObjectIds: { - type: 'array', - description: 'IDs of the objects that were merged into the primary record', - }, - }, - }, - }, - provider: { - type: 'string', - description: 'Provider name (hubspot)', - }, - providerConfig: { - type: 'object', - description: 'Provider configuration', - properties: { - appId: { - type: 'string', - description: 'HubSpot App ID', - }, - clientId: { - type: 'string', - description: 'HubSpot Client ID', - }, - triggerId: { - type: 'string', - description: 'Trigger ID (e.g., hubspot_contact_merged)', - }, - clientSecret: { - type: 'string', - description: 'HubSpot Client Secret', - }, - developerApiKey: { - type: 'string', - description: 'HubSpot Developer API Key', - }, - curlSetWebhookUrl: { - type: 'string', - description: 'curl command to set webhook URL', - }, - curlCreateSubscription: { - type: 'string', - description: 'curl command to create subscription', - }, - webhookUrlDisplay: { - type: 'string', - description: 'Webhook URL display value', - }, - }, - }, - } as any -} - -/** - * Build output schema for contact creation events - */ -export function buildContactCreatedOutputs(): Record { - return buildBaseHubSpotOutputs() -} - -/** - * Build output schema for contact deletion events - */ -export function buildContactDeletedOutputs(): Record { - return buildBaseHubSpotOutputs() -} - -/** - * Build output schema for contact privacy deletion events - */ -export function buildContactPrivacyDeletedOutputs(): Record { - return buildBaseHubSpotOutputs() -} - -/** - * Build output schema for contact property change events - */ -export function buildContactPropertyChangedOutputs(): Record { - return buildBaseHubSpotOutputs() -} - -/** - * Build output schema for contact merge events - */ -export function buildContactMergedOutputs(): Record { - return buildMergeHubSpotOutputs() -} - -/** - * Build output schema for contact restore events - */ -export function buildContactRestoredOutputs(): Record { - return buildBaseHubSpotOutputs() -} - -/** - * Build output schema for company creation events - */ -export function buildCompanyCreatedOutputs(): Record { - return buildBaseHubSpotOutputs() -} - -/** - * Build output schema for company deletion events - */ -export function buildCompanyDeletedOutputs(): Record { - return buildBaseHubSpotOutputs() -} - -/** - * Build output schema for company property change events - */ -export function buildCompanyPropertyChangedOutputs(): Record { - return buildBaseHubSpotOutputs() -} - -/** - * Build output schema for company merge events - */ -export function buildCompanyMergedOutputs(): Record { - return buildMergeHubSpotOutputs() -} - -/** - * Build output schema for company restore events - */ -export function buildCompanyRestoredOutputs(): Record { - return buildBaseHubSpotOutputs() -} - -/** - * Build output schema for conversation creation events - */ -export function buildConversationCreationOutputs(): Record { - return buildBaseHubSpotOutputs() -} - -/** - * Build output schema for conversation deletion events - */ -export function buildConversationDeletionOutputs(): Record { - return buildBaseHubSpotOutputs() -} - -/** - * Build output schema for conversation new message events - */ -export function buildConversationNewMessageOutputs(): Record { - return buildBaseHubSpotOutputs() -} - -/** - * Build output schema for conversation privacy deletion events - */ -export function buildConversationPrivacyDeletionOutputs(): Record { - return buildBaseHubSpotOutputs() -} - -/** - * Build output schema for conversation property change events - */ -export function buildConversationPropertyChangedOutputs(): Record { - return buildBaseHubSpotOutputs() -} - -/** - * Build output schema for deal creation events - */ -export function buildDealCreatedOutputs(): Record { - return buildBaseHubSpotOutputs() -} - -/** - * Build output schema for deal deletion events - */ -export function buildDealDeletedOutputs(): Record { - return buildBaseHubSpotOutputs() -} - -/** - * Build output schema for deal property change events - */ -export function buildDealPropertyChangedOutputs(): Record { - return buildBaseHubSpotOutputs() -} - -/** - * Build output schema for deal merge events - */ -export function buildDealMergedOutputs(): Record { - return buildMergeHubSpotOutputs() -} - -/** - * Build output schema for deal restore events - */ -export function buildDealRestoredOutputs(): Record { - return buildBaseHubSpotOutputs() -} - -/** - * Build output schema for ticket creation events - */ -export function buildTicketCreatedOutputs(): Record { - return buildBaseHubSpotOutputs() -} - -/** - * Build output schema for ticket deletion events - */ -export function buildTicketDeletedOutputs(): Record { - return buildBaseHubSpotOutputs() -} - -/** - * Build output schema for ticket property change events - */ -export function buildTicketPropertyChangedOutputs(): Record { - return buildBaseHubSpotOutputs() -} - -/** - * Build output schema for ticket merge events - */ -export function buildTicketMergedOutputs(): Record { - return buildMergeHubSpotOutputs() -} - -/** - * Build output schema for ticket restore events - */ -export function buildTicketRestoredOutputs(): Record { - return buildBaseHubSpotOutputs() -} - -/** - * Build output schema for generic webhook events - */ -export function buildWebhookOutputs(): Record { - return buildBaseHubSpotOutputs() -} - -/** - * Check if a HubSpot event matches the expected trigger configuration - */ -export function isHubSpotContactEventMatch(triggerId: string, eventType: string): boolean { - const eventMap: Record = { - hubspot_contact_created: 'contact.creation', - hubspot_contact_deleted: 'contact.deletion', - hubspot_contact_merged: 'contact.merge', - hubspot_contact_privacy_deleted: 'contact.privacyDeletion', - hubspot_contact_property_changed: 'contact.propertyChange', - hubspot_contact_restored: 'contact.restore', - hubspot_company_created: 'company.creation', - hubspot_company_deleted: 'company.deletion', - hubspot_company_merged: 'company.merge', - hubspot_company_property_changed: 'company.propertyChange', - hubspot_company_restored: 'company.restore', - hubspot_conversation_creation: 'conversation.creation', - hubspot_conversation_deletion: 'conversation.deletion', - hubspot_conversation_new_message: 'conversation.newMessage', - hubspot_conversation_privacy_deletion: 'conversation.privacyDeletion', - hubspot_conversation_property_changed: 'conversation.propertyChange', - hubspot_deal_created: 'deal.creation', - hubspot_deal_deleted: 'deal.deletion', - hubspot_deal_merged: 'deal.merge', - hubspot_deal_property_changed: 'deal.propertyChange', - hubspot_deal_restored: 'deal.restore', - hubspot_ticket_created: 'ticket.creation', - hubspot_ticket_deleted: 'ticket.deletion', - hubspot_ticket_merged: 'ticket.merge', - hubspot_ticket_property_changed: 'ticket.propertyChange', - hubspot_ticket_restored: 'ticket.restore', - } - - const expectedEventType = eventMap[triggerId] - if (!expectedEventType) { - return true // Unknown trigger, allow through - } - - return expectedEventType === eventType -} diff --git a/apps/sim/triggers/hubspot/webhook.ts b/apps/sim/triggers/hubspot/webhook.ts deleted file mode 100644 index aeb303ff051..00000000000 --- a/apps/sim/triggers/hubspot/webhook.ts +++ /dev/null @@ -1,212 +0,0 @@ -import { HubspotIcon } from '@/components/icons' -import { - buildWebhookOutputs, - hubspotAllTriggerOptions, - hubspotSetupInstructions, -} from '@/triggers/hubspot/utils' -import type { TriggerConfig } from '@/triggers/types' - -export const hubspotWebhookTrigger: TriggerConfig = { - id: 'hubspot_webhook', - name: 'HubSpot Webhook (All Events)', - provider: 'hubspot', - description: 'Trigger workflow on any HubSpot webhook event', - version: '1.0.0', - icon: HubspotIcon, - - subBlocks: [ - { - id: 'selectedTriggerId', - title: 'Trigger Type', - type: 'dropdown', - mode: 'trigger', - options: hubspotAllTriggerOptions, - value: () => 'hubspot_webhook', - required: true, - }, - { - id: 'clientId', - title: 'Client ID', - type: 'short-input', - placeholder: 'Enter your HubSpot app Client ID', - description: 'Found in your HubSpot app settings under Auth tab', - required: true, - mode: 'trigger', - condition: { - field: 'selectedTriggerId', - value: 'hubspot_webhook', - }, - }, - { - id: 'clientSecret', - title: 'Client Secret', - type: 'short-input', - placeholder: 'Enter your HubSpot app Client Secret', - description: 'Found in your HubSpot app settings under Auth tab', - password: true, - required: true, - mode: 'trigger', - condition: { - field: 'selectedTriggerId', - value: 'hubspot_webhook', - }, - }, - { - id: 'appId', - title: 'App ID', - type: 'short-input', - placeholder: 'Enter your HubSpot App ID', - description: 'Found in your HubSpot app settings. Used to identify your app.', - required: true, - mode: 'trigger', - condition: { - field: 'selectedTriggerId', - value: 'hubspot_webhook', - }, - }, - { - id: 'developerApiKey', - title: 'Developer API Key', - type: 'short-input', - placeholder: 'Enter your HubSpot Developer API Key', - description: 'Used for making API calls to HubSpot. Found in your HubSpot app settings.', - password: true, - required: true, - mode: 'trigger', - condition: { - field: 'selectedTriggerId', - value: 'hubspot_webhook', - }, - }, - { - id: 'webhookUrlDisplay', - title: 'Webhook URL', - type: 'short-input', - readOnly: true, - showCopyButton: true, - useWebhookUrl: true, - placeholder: 'Webhook URL will be generated', - description: 'Copy this URL and paste it into your HubSpot app webhook subscription settings', - mode: 'trigger', - condition: { - field: 'selectedTriggerId', - value: 'hubspot_webhook', - }, - }, - { - id: 'triggerInstructions', - title: 'Setup Instructions', - type: 'text', - defaultValue: hubspotSetupInstructions( - 'All Events', - 'This generic webhook trigger will accept all HubSpot webhook events. Create subscriptions for each event type you want to receive using the curl command below (changing the eventType parameter).' - ), - mode: 'trigger', - condition: { - field: 'selectedTriggerId', - value: 'hubspot_webhook', - }, - }, - { - id: 'curlSetWebhookUrl', - title: '1. Set Webhook Target URL', - type: 'code', - language: 'javascript', - value: (params: Record) => { - const webhookUrl = params.webhookUrlDisplay || '{YOUR_WEBHOOK_URL_FROM_ABOVE}' - return `curl -X PUT "https://api.hubapi.com/webhooks/v3/{YOUR_APP_ID}/settings?hapikey={YOUR_DEVELOPER_API_KEY}" \\ - -H "Content-Type: application/json" \\ - -d '{ - "targetUrl": "${webhookUrl}", - "throttling": { - "maxConcurrentRequests": 10 - } - }'` - }, - readOnly: true, - collapsible: true, - defaultCollapsed: true, - showCopyButton: true, - description: 'Run this command to set your webhook URL in HubSpot', - mode: 'trigger', - condition: { - field: 'selectedTriggerId', - value: 'hubspot_webhook', - }, - }, - { - id: 'curlCreateSubscription', - title: '2. Create Webhook Subscription', - type: 'code', - language: 'javascript', - defaultValue: `# Create subscriptions for each event type you want to receive. -# Replace {eventType} with: contact.creation, contact.deletion, contact.propertyChange, -# contact.merge, contact.restore, company.creation, company.deletion, company.propertyChange, -# company.merge, company.restore, deal.creation, deal.deletion, deal.propertyChange, -# deal.merge, deal.restore, ticket.creation, ticket.deletion, ticket.propertyChange, -# ticket.merge, ticket.restore, etc. - -curl -X POST "https://api.hubapi.com/webhooks/v3/{YOUR_APP_ID}/subscriptions?hapikey={YOUR_DEVELOPER_API_KEY}" \\ - -H "Content-Type: application/json" \\ - -d '{ - "eventType": "{eventType}", - "active": true - }'`, - readOnly: true, - collapsible: true, - defaultCollapsed: true, - showCopyButton: true, - description: 'Run this command for each event type you want to subscribe to', - mode: 'trigger', - condition: { - field: 'selectedTriggerId', - value: 'hubspot_webhook', - }, - }, - { - id: 'samplePayload', - title: 'Event Payload Example', - type: 'code', - language: 'json', - defaultValue: JSON.stringify( - [ - { - eventId: 3181526809, - subscriptionId: 4629970, - portalId: 244315265, - appId: 23608917, - occurredAt: 1762659213730, - subscriptionType: 'contact.creation', - attemptNumber: 0, - objectId: 316126906049, - changeFlag: 'CREATED', - changeSource: 'CRM_UI', - sourceId: 'userId:84916424', - }, - ], - null, - 2 - ), - readOnly: true, - collapsible: true, - defaultCollapsed: true, - mode: 'trigger', - condition: { - field: 'selectedTriggerId', - value: 'hubspot_webhook', - }, - }, - ], - - outputs: buildWebhookOutputs(), - - webhook: { - method: 'POST', - headers: { - 'Content-Type': 'application/json', - 'X-HubSpot-Signature': 'sha256=...', - 'X-HubSpot-Request-Id': 'xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx', - 'User-Agent': 'HubSpot Webhooks', - }, - }, -} diff --git a/apps/sim/triggers/registry.ts b/apps/sim/triggers/registry.ts index bb4d252d751..43a5af5dedf 100644 --- a/apps/sim/triggers/registry.ts +++ b/apps/sim/triggers/registry.ts @@ -145,35 +145,7 @@ import { greenhouseOfferCreatedTrigger, greenhouseWebhookTrigger, } from '@/triggers/greenhouse' -import { - hubspotCompanyCreatedTrigger, - hubspotCompanyDeletedTrigger, - hubspotCompanyMergedTrigger, - hubspotCompanyPropertyChangedTrigger, - hubspotCompanyRestoredTrigger, - hubspotContactCreatedTrigger, - hubspotContactDeletedTrigger, - hubspotContactMergedTrigger, - hubspotContactPrivacyDeletedTrigger, - hubspotContactPropertyChangedTrigger, - hubspotContactRestoredTrigger, - hubspotConversationCreationTrigger, - hubspotConversationDeletionTrigger, - hubspotConversationNewMessageTrigger, - hubspotConversationPrivacyDeletionTrigger, - hubspotConversationPropertyChangedTrigger, - hubspotDealCreatedTrigger, - hubspotDealDeletedTrigger, - hubspotDealMergedTrigger, - hubspotDealPropertyChangedTrigger, - hubspotDealRestoredTrigger, - hubspotTicketCreatedTrigger, - hubspotTicketDeletedTrigger, - hubspotTicketMergedTrigger, - hubspotTicketPropertyChangedTrigger, - hubspotTicketRestoredTrigger, - hubspotWebhookTrigger, -} from '@/triggers/hubspot' +import { hubspotPollingTrigger } from '@/triggers/hubspot' import { imapPollingTrigger } from '@/triggers/imap' import { intercomContactCreatedTrigger, @@ -583,33 +555,7 @@ export const TRIGGER_REGISTRY: TriggerRegistry = { webflow_collection_item_changed: webflowCollectionItemChangedTrigger, webflow_collection_item_deleted: webflowCollectionItemDeletedTrigger, webflow_form_submission: webflowFormSubmissionTrigger, - hubspot_contact_created: hubspotContactCreatedTrigger, - hubspot_contact_deleted: hubspotContactDeletedTrigger, - hubspot_contact_merged: hubspotContactMergedTrigger, - hubspot_contact_privacy_deleted: hubspotContactPrivacyDeletedTrigger, - hubspot_contact_property_changed: hubspotContactPropertyChangedTrigger, - hubspot_contact_restored: hubspotContactRestoredTrigger, - hubspot_company_created: hubspotCompanyCreatedTrigger, - hubspot_company_deleted: hubspotCompanyDeletedTrigger, - hubspot_company_merged: hubspotCompanyMergedTrigger, - hubspot_company_property_changed: hubspotCompanyPropertyChangedTrigger, - hubspot_company_restored: hubspotCompanyRestoredTrigger, - hubspot_conversation_creation: hubspotConversationCreationTrigger, - hubspot_conversation_deletion: hubspotConversationDeletionTrigger, - hubspot_conversation_new_message: hubspotConversationNewMessageTrigger, - hubspot_conversation_privacy_deletion: hubspotConversationPrivacyDeletionTrigger, - hubspot_conversation_property_changed: hubspotConversationPropertyChangedTrigger, - hubspot_deal_created: hubspotDealCreatedTrigger, - hubspot_deal_deleted: hubspotDealDeletedTrigger, - hubspot_deal_merged: hubspotDealMergedTrigger, - hubspot_deal_property_changed: hubspotDealPropertyChangedTrigger, - hubspot_deal_restored: hubspotDealRestoredTrigger, - hubspot_ticket_created: hubspotTicketCreatedTrigger, - hubspot_ticket_deleted: hubspotTicketDeletedTrigger, - hubspot_ticket_merged: hubspotTicketMergedTrigger, - hubspot_ticket_property_changed: hubspotTicketPropertyChangedTrigger, - hubspot_ticket_restored: hubspotTicketRestoredTrigger, - hubspot_webhook: hubspotWebhookTrigger, + hubspot_poller: hubspotPollingTrigger, imap_poller: imapPollingTrigger, intercom_conversation_created: intercomConversationCreatedTrigger, intercom_conversation_reply: intercomConversationReplyTrigger, diff --git a/helm/sim/values.yaml b/helm/sim/values.yaml index e253f1a0af8..1305d363768 100644 --- a/helm/sim/values.yaml +++ b/helm/sim/values.yaml @@ -1150,6 +1150,15 @@ cronjobs: successfulJobsHistoryLimit: 3 failedJobsHistoryLimit: 1 + hubspotWebhookPoll: + enabled: true + name: hubspot-webhook-poll + schedule: "*/1 * * * *" + path: "/api/webhooks/poll/hubspot" + concurrencyPolicy: Forbid + successfulJobsHistoryLimit: 3 + failedJobsHistoryLimit: 1 + renewSubscriptions: enabled: true name: renew-subscriptions diff --git a/scripts/check-api-validation-contracts.ts b/scripts/check-api-validation-contracts.ts index 0ab7c97be19..0fbe9d4077a 100644 --- a/scripts/check-api-validation-contracts.ts +++ b/scripts/check-api-validation-contracts.ts @@ -9,8 +9,8 @@ const QUERY_HOOKS_DIR = path.join(ROOT, 'apps/sim/hooks/queries') const SELECTOR_HOOKS_DIR = path.join(ROOT, 'apps/sim/hooks/selectors') const BASELINE = { - totalRoutes: 751, - zodRoutes: 751, + totalRoutes: 755, + zodRoutes: 755, nonZodRoutes: 0, } as const