Send a Slack alert when a HubSpot deal changes stage using n8n

low complexityCost: $0-24/moRecommended

Prerequisites

Prerequisites
  • n8n instance (cloud or self-hosted)
  • HubSpot private app token with crm.objects.deals.read and crm.schemas.deals.read scopes
  • Slack app with Bot Token (chat:write scope)
  • n8n credentials configured for both HubSpot and Slack

Why n8n?

n8n is the best option if you want full control without ongoing costs. Self-hosted n8n is completely free with unlimited executions — you only pay for your own infrastructure. The visual workflow editor makes it easy to see exactly what's happening at each step, and you can modify the logic without touching code.

The HubSpot Trigger node uses webhooks, so alerts arrive in seconds rather than minutes. If you're already running n8n for other automations, adding this workflow takes under 20 minutes. If you're not, the initial setup (Docker or npm install) adds another 15 minutes.

How it works

  • HubSpot Trigger node listens for deal.propertyChange events on the dealstage property via webhook — fires within seconds of a stage change
  • HTTP Request node fetches the full deal record (name, amount, owner) since the trigger only sends the deal ID and changed property
  • HTTP Request node calls the Pipelines API to get stage ID-to-label mappings
  • Code node resolves the internal stage ID (e.g. closedwon) to the display label (e.g. "Closed Won")
  • Slack node posts a Block Kit message with deal details and a direct link to the HubSpot record

Step 1: Add a HubSpot Trigger node

Create a new workflow and add a HubSpot Trigger node:

  • Authentication: Select your HubSpot credential
  • Event: Deal Property Changed
  • Property: dealstage

This fires every time any deal's stage property is updated. HubSpot sends the deal ID and the new stage value via webhook.

Trigger vs. polling

The HubSpot Trigger node uses webhooks for near-instant delivery (1-5 seconds). This is faster than polling, which checks every 1-5 minutes depending on your plan.

Step 2: Fetch full deal details

The trigger only sends the deal ID and changed property. Add an HTTP Request node to get the full deal record:

  • Method: GET
  • URL: https://api.hubapi.com/crm/v3/objects/deals/{{ $json.objectId }}
  • Authentication: Predefined → HubSpot API
  • Query params: properties=dealname,amount,dealstage,pipeline,hubspot_owner_id,closedate

Step 3: Resolve stage name

The dealstage property returns an ID like closedwon, not a label. Add another HTTP Request node:

  • Method: GET
  • URL: https://api.hubapi.com/crm/v3/pipelines/deals

Then add a Code node to map the stage ID to its label:

const pipelines = $('Fetch Pipelines').first().json.results;
const deal = $('Fetch Deal').first().json;
 
let stageName = deal.properties.dealstage;
for (const pipeline of pipelines) {
  const stage = pipeline.stages.find(s => s.id === deal.properties.dealstage);
  if (stage) {
    stageName = stage.label;
    break;
  }
}
 
return [{
  json: {
    dealName: deal.properties.dealname,
    amount: parseFloat(deal.properties.amount || '0'),
    stageName,
    ownerId: deal.properties.hubspot_owner_id,
    dealId: deal.id,
  }
}];

Step 4: Send Slack notification

Add a Slack node:

  • Resource: Message
  • Operation: Send
  • Channel: #sales-pipeline (or your deals channel)
  • Message Type: Block Kit
{
  "blocks": [
    {
      "type": "section",
      "text": {
        "type": "mrkdwn",
        "text": "🔄 *Deal Stage Changed*\n*{{ $json.dealName }}* moved to *{{ $json.stageName }}*\nAmount: ${{ $json.amount.toLocaleString() }}"
      }
    },
    {
      "type": "context",
      "elements": [
        {
          "type": "mrkdwn",
          "text": "<https://app.hubspot.com/contacts/YOUR_PORTAL_ID/deal/{{ $json.dealId }}|View in HubSpot>"
        }
      ]
    }
  ]
}
Block Kit JSON format

n8n's Slack node expects the full {"blocks": [...]} wrapper. If you pass just the array, blocks are silently ignored and only the notification text shows.

Step 5: Filter unwanted transitions (optional)

If you don't want alerts for every stage change, add an IF node before the Slack node:

  • Condition: $json.stageName is one of Negotiation, Closed Won, Closed Lost

This prevents noise from minor stage movements like Qualification → Discovery.

Step 6: Activate

  1. Click Execute Workflow to test with a real deal stage change
  2. Verify the Slack message appears with correct deal info
  3. Toggle the workflow to Active

Troubleshooting

Common questions

Should I use n8n Cloud or self-hosted for this workflow?

For a single workflow like this, self-hosted is free and straightforward — a $5/mo VPS handles it easily. n8n Cloud ($24/mo starter) makes sense if you're running multiple workflows and don't want to manage infrastructure. The workflow itself is identical on both.

How often does the HubSpot Trigger node poll?

The HubSpot Trigger node in n8n uses webhooks, not polling. Events arrive within 1-5 seconds of the stage change in HubSpot. However, if you're using a self-hosted instance behind a firewall without a public URL, webhooks won't work — you'll need to use n8n's tunnel feature for testing or set up a reverse proxy.

Will this hit HubSpot API rate limits?

Unlikely for deal stage alerts. HubSpot allows 100 requests per 10 seconds for private apps. Each stage change triggers 2 API calls (deal details + pipeline stages). You'd need 50 deals changing stage within 10 seconds to hit the limit — that's not a realistic scenario for most teams. If you have very high volume, cache the pipeline stages response in a Set node so you only fetch it once per execution.

Can I use this with multiple pipelines?

Yes. The workflow automatically handles all pipelines — the HubSpot Trigger fires on stage changes across every pipeline, and the Code node resolves stage names from any pipeline. To filter to a specific pipeline, add an IF node after the Fetch Deal step that checks the pipeline property.

Cost

  • n8n Cloud Starter: $24/mo for 2,500 executions. Each deal stage change = 1 execution.
  • Self-hosted: Free. Unlimited executions.

Looking to scale your AI operations?

We build and optimize automation systems for mid-market businesses. Let's discuss the right approach for your team.