Send a Slack alert when a Salesforce deal changes stage using n8n
Prerequisites
- n8n instance (cloud or self-hosted)
- Salesforce Connected App with OAuth credentials (Client ID and Client Secret)
- Slack app with Bot Token (
chat:writescope) - 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:
- In Salesforce, go to Setup → App Manager → New Connected App
- Fill in the basics (App Name, Contact Email)
- Check Enable OAuth Settings
- Set Callback URL to your n8n OAuth callback (e.g.,
https://your-n8n.com/rest/oauth2-credential/callback) - Add OAuth scopes:
Full access (full)or at minimumAccess and manage your data (api)andPerform requests on your behalf at any time (refresh_token, offline_access) - Save and wait 2–10 minutes for the Connected App to propagate
- 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
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 ofNegotiation/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.
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
- Click Execute Workflow to test with a real Opportunity stage change
- Verify the Slack message appears with correct deal info
- 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.