{
  "name": "HubSpot Deal Stage Alerts",
  "nodes": [
    {
      "parameters": {
        "content": "## HubSpot Deal Stage Alerts: Celebrate Closed Deals in Slack\n\nGet instant notifications in Slack whenever a deal moves to 'Closed Won' in HubSpot, celebrating wins and keeping the team informed of new revenue.\n\n**Setup time:** 15 minutes  ·  **Level:** Intermediate\n\n**You'll need accounts/credentials for:** HubSpot, Slack\n\n**Replace these before running:**\n- `REPLACE_WITH_CHANNEL`\n\n**Setup steps:**\n1. Connect HubSpot and Slack in their respective nodes.\n2. Replace REPLACE_WITH_CHANNEL with your target Slack channel.\n3. Customize the 'Closed Won' stage identifier in the IF node to match your HubSpot setup.\n4. Test the workflow by manually changing a deal stage in HubSpot.\n5. Adjust polling frequency in the Schedule Trigger if needed.\n\nFree templates and updates: navkhan103.github.io",
        "height": 300,
        "width": 400,
        "color": 4
      },
      "id": "sticky-setup",
      "name": "Setup — read me first",
      "type": "n8n-nodes-base.stickyNote",
      "typeVersion": 1,
      "position": [
        -440,
        -120
      ]
    },
    {
      "parameters": {
        "content": "### How it runs\n\nStarts from **Schedule Trigger**.\n\n1. A Schedule Trigger runs every 15 minutes to poll HubSpot for recent changes.\n2. A HubSpot node searches for deals closed in the last 20 minutes.\n3. An IF node checks if the deal stage changed to 'Closed Won'.\n4. A Slack node posts a celebration message with deal details and owner.\n5. The message includes the deal value, owner, and company for recognition.",
        "height": 300,
        "width": 400,
        "color": 7
      },
      "id": "sticky-how",
      "name": "How it runs",
      "type": "n8n-nodes-base.stickyNote",
      "typeVersion": 1,
      "position": [
        -440,
        220
      ]
    },
    {
      "parameters": {
        "content": "### If something breaks\n\nThe HubSpot read retries 3× automatically (5s apart), which absorbs rate limits and brief timeouts.\n\nNodes that **send or write deliberately do not retry** — a send that reached the far end but lost its response would otherwise fire twice, so you'd get duplicate messages or duplicate rows.\n\nTo be told when one of those fails, build a workflow starting with an **Error Trigger** node that posts to Slack or email, then set it under **three-dot menu > Settings > Error Workflow**. Do it once and point every workflow at it.",
        "height": 380,
        "width": 400,
        "color": 3
      },
      "id": "sticky-fail",
      "name": "If something breaks",
      "type": "n8n-nodes-base.stickyNote",
      "typeVersion": 1,
      "position": [
        -440,
        560
      ]
    },
    {
      "parameters": {
        "rule": {
          "times": [
            {
              "hour": "*",
              "minute": "*/15"
            }
          ],
          "daysOfMonth": "*",
          "months": "*",
          "weekdays": "*"
        }
      },
      "id": "f9a0b1c2-0001-4000-8000-000000000001",
      "name": "Schedule Trigger",
      "type": "n8n-nodes-base.scheduleTrigger",
      "typeVersion": 1.2,
      "position": [
        0,
        0
      ]
    },
    {
      "parameters": {
        "resource": "deal",
        "operation": "search",
        "filters": {
          "propertyFilters": [
            {
              "propertyName": "hs_date_entered_closedwon",
              "operator": "GT",
              "value": "={{ new Date(Date.now() - 20 * 60000).toISOString() }}"
            }
          ]
        },
        "additionalFields": {
          "limit": 10
        }
      },
      "id": "f9a0b1c2-0002-4000-8000-000000000002",
      "name": "Find Recent Deals",
      "type": "n8n-nodes-base.hubspot",
      "typeVersion": 2.1,
      "position": [
        220,
        0
      ],
      "retryOnFail": true,
      "maxTries": 3,
      "waitBetweenTries": 5000
    },
    {
      "parameters": {
        "conditions": {
          "options": {
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "conditions": [
            {
              "id": "c1",
              "leftValue": "={{ $json.properties.dealstage }}",
              "rightValue": "closedwon",
              "operator": {
                "type": "string",
                "operation": "equals"
              }
            }
          ],
          "combinator": "and"
        },
        "options": {}
      },
      "id": "f9a0b1c2-0003-4000-8000-000000000003",
      "name": "Stage is Closed Won?",
      "type": "n8n-nodes-base.if",
      "typeVersion": 2.2,
      "position": [
        440,
        0
      ]
    },
    {
      "parameters": {
        "select": "channel",
        "channelId": {
          "__rl": true,
          "mode": "list",
          "value": "REPLACE_WITH_CHANNEL"
        },
        "text": "=:tada: *New Closed Won Deal!* :tada:\\n*{{ $json.properties.dealname }}* - ${{ Number($json.properties.amount || 0).toLocaleString() }}\\nOwner: {{ $json.properties.ownedby }}\\nCompany: {{ $json.properties.company }}",
        "otherOptions": {}
      },
      "id": "f9a0b1c2-0004-4000-8000-000000000004",
      "name": "Celebrate Win",
      "type": "n8n-nodes-base.slack",
      "typeVersion": 2.3,
      "position": [
        660,
        -80
      ]
    }
  ],
  "connections": {
    "Schedule Trigger": {
      "main": [
        [
          {
            "node": "Find Recent Deals",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Find Recent Deals": {
      "main": [
        [
          {
            "node": "Stage is Closed Won?",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Stage is Closed Won?": {
      "main": [
        [
          {
            "node": "Celebrate Win",
            "type": "main",
            "index": 0
          }
        ],
        []
      ]
    }
  },
  "settings": {
    "executionOrder": "v1"
  }
}