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

low complexityCost: $0-24/moRecommended

Prerequisites

Prerequisites
  • n8n instance (cloud or self-hosted)
  • Salesforce Connected App with OAuth credentials (Client ID and Client Secret)
  • Slack app with Bot Token (chat:write scope)
  • n8n credentials configured for both Salesforce and Slack

Step 1: Create a Salesforce Connected App

Before configuring n8n, you need a Connected App in Salesforce for OAuth:

  1. In Salesforce, go to Setup → App Manager → New Connected App
  2. Fill in the basics (App Name, Contact Email)
  3. Check Enable OAuth Settings
  4. Set Callback URL to your n8n OAuth callback (e.g., https://your-n8n.com/rest/oauth2-credential/callback)
  5. Add OAuth scopes: Full access (full) or at minimum Access and manage your data (api) and Perform requests on your behalf at any time (refresh_token, offline_access)
  6. Save and wait 2–10 minutes for the Connected App to propagate
  7. Copy the Consumer Key (Client ID) and Consumer Secret (Client Secret)

In n8n, go to Credentials → New → Salesforce OAuth2 API and enter the Client ID, Client Secret, and your Salesforce instance URL.

Step 2: Add a Salesforce Trigger node

Create a new workflow and add a Salesforce Trigger node:

  • Authentication: Select your Salesforce OAuth2 credential
  • Resource: Opportunity
  • Event: Updated
n8n polls Salesforce — it does not use webhooks

The Salesforce Trigger node in n8n uses polling, not push webhooks. Set the polling interval to 1 minute for near-real-time alerts. On n8n Cloud, the minimum interval depends on your plan.

Step 3: Add an IF node to filter stage changes

The trigger fires on any Opportunity update. Add an IF node to check if the stage actually changed:

  • Condition: {{ $json.StageName }} is not empty

For more precise filtering, you can check against specific stages:

  • Condition: {{ $json.StageName }} is one of Negotiation/Review, Closed Won, Closed Lost

Step 4: Fetch full Opportunity details

The trigger may not include all fields you need. Add a Salesforce node to query the full record:

  • Resource: Opportunity
  • Operation: Get
  • Opportunity ID: {{ $json.Id }}

Or use a Salesforce node with a custom SOQL query for richer data:

  • Operation: Custom API Call
  • Method: GET
  • Endpoint: /services/data/v59.0/query
  • Query Parameters: q = the SOQL below
SELECT Id, Name, Amount, StageName, Account.Name, Owner.Name,
       LastModifiedDate
FROM Opportunity
WHERE Id = '006XXXXXXXXXXXXXXX'

Replace the hardcoded ID with the expression {{ $json.Id }} in your node configuration.

Step 5: 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.Name }}* moved to *{{ $json.StageName }}*\nAmount: ${{ $json.Amount }}\nAccount: {{ $json.Account.Name }}\nOwner: {{ $json.Owner.Name }}"
      }
    },
    {
      "type": "context",
      "elements": [
        {
          "type": "mrkdwn",
          "text": "<https://YOUR_INSTANCE.my.salesforce.com/{{ $json.Id }}|View in Salesforce>"
        }
      ]
    }
  ]
}

Replace YOUR_INSTANCE with your Salesforce org's subdomain.

Block Kit JSON format

n8n's Slack node expects the full blocks wrapper object. If you pass just the array without the outer object, blocks are silently ignored and only the notification text shows.

Step 6: Activate

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

Cost

  • n8n Cloud Starter: $24/mo for 2,500 executions. Each poll interval = 1 execution (regardless of how many records changed).
  • Self-hosted: Free. Unlimited executions.

Need help implementing this?

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