Skip to content

HubSpot Trigger

Triggers a workflow when your HubSpot app receives webhook deliveries (contact / deal / company / property changes).

HubSpot webhook target URLs and event subscriptions are configured at the App level in the HubSpot Developer Portal, not via API. HubSpot publishes a single target URL per app and fans events across all portals (HubSpot accounts) that installed the app. Workflow-automation acts as one such target.

Requires a HubSpot connection configured with the Private App Access Token (for outbound API calls) AND the Client Secret (for verifying inbound webhook signatures).

Auth model — important

HubSpot has two authentication models. They serve different purposes:

  • Private app (access token): per-portal, used for outbound API calls from action nodes. Private apps don't expose webhook subscriptions.
  • OAuth (public) app (client secret): webhooks live here. The webhook URL is configured app-level in the Developer Portal; events arrive tagged with the originating portalId.

If your workflow only needs to call HubSpot, the access token is enough. To receive events via the HubSpot Trigger, you also need an OAuth app installed into your portal, and its Client Secret on the connection.

HubSpot is moving away from legacy public apps

In the HubSpot Developer UI these are now listed under "Legacy Apps" (German: Alte Apps) with a banner noting they won't receive future updates. HubSpot's stated long-term path is the newer Developer Projects framework. The webhook integration we describe here works fine against a legacy public app today; if HubSpot deprecates them in the future, the trigger will need to be re-implemented against Projects. We will track the migration when HubSpot announces a date.

Webhook URL is per-connection, not per-workflow

https://<your-deployment>/api/conn-webhook/<connection-webhook-token>

Fetch it from the connection's webhook-info endpoint, or read it from the trigger node's banner in the workflow editor:

bash
curl -H "Authorization: Bearer $TOKEN" \
  https://<your-deployment>/api/connections/<connection-id>/webhook-info \
  | jq '.data.url'

The same URL services every hubspot_trigger workflow built on this connection. The dispatcher fans deliveries to all matching workflows.

Setup — step by step in the HubSpot Developer Portal

The exact menu labels differ by language. The English / German pairs are noted below.

1. Create a Public (OAuth) Legacy App

  1. Open the HubSpot Developer Portal and sign in.
  2. Left sidebar → Legacy Apps (German: Alte Apps). The URL /applications redirects here automatically.
  3. Click Create Legacy App (Alte App erstellen).
  4. Choose Public (Öffentlich — "For many accounts"). Not Private; private apps don't support webhooks.
  5. Set a meaningful app name (e.g. workflow-automation-trigger).

2. Configure Authentication

  1. Switch to the Authentication tab (Authentifizierung).
  2. Under Redirect URLs (Weiterleitungs-URLs), add a URL. localhost is acceptable for dev — HubSpot's UI accepts it without the http:// prefix; the dropdown defaults to http://. A redirect URL is required even if you never run the OAuth flow.
  3. Under Scopes (Bereiche) → + Add new scope (Neuen Bereich hinzufügen). Add at least one scope matching the events you want, e.g. crm.objects.contacts.read for contact events. The default oauth scope is added automatically and required.
  4. Click Create app (App erstellen) at the bottom of the page. The app gets a numeric ID.

3. Copy the Client Secret

Still on the Authentication tab, scroll to App Credentials (App-Anmeldeinformationen):

  • App ID — numeric, used in OAuth install URLs.
  • Client ID — UUID, used for OAuth flow.
  • Client Secret (Client-Geheimnis) — click Show (Anzeigen) to reveal, then Copy (Kopieren). This is what goes into the workflow-automation connection.

4. Configure Webhooks

  1. Left sidebar inside the app → Webhooks.
  2. Under Target URL (Ziel-URL), paste the webhook URL from the connection. The URL field has an https:// prefix baked in — paste only the host + path (e.g. wf-dev.ruvix.io/api/conn-webhook/01KR…).
  3. Click Save (Speichern) at the bottom of the page. You must save before creating subscriptions — HubSpot tooltips you if you try.
  4. Click Create subscription (Abonnement erstellen) — top right.
  5. Pick the Object type (Objekttyp) you want (Contact, Deal, Company, …). Each subscription is one object × one event type.
  6. Pick the Event type (Welche Events beobachten?) — typical choices: Created (Erstellt), Deleted (Gelöscht), Property changed (Eigenschaft geändert), Merged, Restored.
  7. Leave "Use extended object support" (Beta) off unless you specifically need it.
  8. Click Subscribe (Abonnieren). The subscription appears in the table.
  9. Activate the subscription — this is critical. New subscriptions are created in Pausiert (Paused) state by default and fire nothing. Click into the row, select the subscription's checkbox, then click ▶ Aktivieren (Activate) in the row of bulk actions that appears. The status dot should turn green and read Aktiv. Without this step the table shows Gesamtanzahl: 0 forever and HubSpot's Monitoring → Webhooks tab will also show zero deliveries.

5. Install the app in a portal

The OAuth app does nothing until at least one HubSpot portal installs it. Without an install there's no portal context for HubSpot to fan events from.

  1. On the Authentication tab, copy the Sample Installation URL (OAuth) (Beispiel-Installations-URL) — looks like https://app-eu1.hubspot.com/oauth/authorize?client_id=…&redirect_uri=…&scope=….

  2. Open that URL in a browser session logged into the HubSpot portal you want to test from (often the dev portal itself, which doubles as a CRM).

  3. Pick the account → consent → if the app is unverified, type Ich akzeptiere das Risiko / I accept the risk in the confirmation box → Verknüpfen (Connect).

  4. You must complete the OAuth token exchange to commit the install. HubSpot redirects to your configured redirect_uri with a one-time ?code=…. If that redirect target doesn't run server-side code that POSTs the code to /oauth/v1/token, the install remains in a pending state and webhooks never fire — even though the consent screen makes it look done.

    For local dev where redirect_uri=http://localhost (no server running), grab the code from the failed browser address bar and exchange it manually:

    bash
    curl -X POST https://api.hubapi.com/oauth/v1/token \
      -d grant_type=authorization_code \
      -d client_id=<CLIENT_ID> \
      -d client_secret=<CLIENT_SECRET> \
      -d redirect_uri=http://localhost \
      -d code=<CODE_FROM_REDIRECT>

    A successful response includes access_token, refresh_token, hub_id, scopes. That commits the install permanently.

6. Paste the Client Secret into the workflow-automation connection

  1. In the workflow-automation UI → Connections → open the HubSpot connection.
  2. Paste the Client Secret you copied in step 3 into the Client Secret field. Leave the Private App Access Token alone.
  3. Save. The connection's webhook_status flips from error to pending_manual_setup (no error, just the standard state for any manually-configured webhook).

7. Build a workflow

Trigger node = HubSpot Trigger, Connection set to the connection above, events filter set to the matching subscription type (e.g. contact.creation) or ["*"]. Publish.

Output

HubSpot delivers an array of events per POST (batched). The trigger output reflects that — your downstream nodes should iterate or filter.

FieldDescription
bodyArray of subscription events
body[].subscriptionTypeEvent type (e.g., contact.creation, deal.propertyChange)
body[].objectIdThe HubSpot object's ID
body[].portalIdWhich HubSpot portal fired the event (relevant for multi-tenant apps)
headers.X-HubSpot-Signature-v3Signature (already verified before the workflow runs)
headers.X-HubSpot-Request-TimestampUsed as part of the signature payload

The trigger's dispatch-side events filter matches against the first event's subscriptionType — workable for batches that share a type. Use ["*"] if you want every batch regardless and filter downstream.

How it works

  • Every POST is verified with HubSpot's v3 signature scheme: signature = base64(HMAC-SHA256(client_secret, method + full_url + raw_body + timestamp)) compared to the X-HubSpot-Signature-v3 header.
  • Deliveries older than 5 minutes are rejected as replay attempts (timestamps are in milliseconds).

Client Secret required

The HubSpot Trigger refuses to publish if the connection is missing its Client Secret. Deliveries cannot be authenticated without it.

HubSpot doesn't expose a registration API

Target URLs and event subscriptions live in the OAuth app's configuration. HubSpot doesn't allow programmatic mutation of app settings — the Developer Portal is the only path.