AutomationFlowsEmail & Gmail › Send Contract Renewal Reminders From Hubspot via Gmail and Slack Alerts

Send Contract Renewal Reminders From Hubspot via Gmail and Slack Alerts

ByAvkash Kakdiya @itechnotion on n8n.io

This workflow runs on a schedule to monitor HubSpot deals with upcoming contract expiry dates. It filters deals that are 30, 60, or 90 days away from expiration and processes each one individually. Based on the remaining days, it sends personalized email reminders to contacts…

Cron / scheduled trigger★★★★☆ complexity18 nodesGmailHubSpotHTTP RequestSlackClickUp
Email & Gmail Trigger: Cron / scheduled Nodes: 18 Complexity: ★★★★☆ Added:

This workflow corresponds to n8n.io template #14155 — we link there as the canonical source.

This workflow follows the Gmail → HTTP Request recipe pattern — see all workflows that pair these two integrations.

The workflow JSON

Copy or download the full n8n JSON below. Paste it into a new n8n workflow, add your credentials, activate. Full import guide →

Download .json
{
  "meta": {
    "templateCredsSetupCompleted": true
  },
  "nodes": [
    {
      "id": "babada84-5bb8-4822-900b-5b8d315f35fb",
      "name": "Schedule Trigger",
      "type": "n8n-nodes-base.scheduleTrigger",
      "position": [
        20400,
        5712
      ],
      "parameters": {
        "rule": {
          "interval": [
            {}
          ]
        }
      },
      "typeVersion": 1.3
    },
    {
      "id": "dafebf5d-c8e4-4363-9754-c949900cd864",
      "name": "Switch",
      "type": "n8n-nodes-base.switch",
      "position": [
        21664,
        5520
      ],
      "parameters": {
        "rules": {
          "values": [
            {
              "conditions": {
                "options": {
                  "version": 3,
                  "leftValue": "",
                  "caseSensitive": true,
                  "typeValidation": "loose"
                },
                "combinator": "and",
                "conditions": [
                  {
                    "id": "737e9347-01e4-40ac-ae41-d695781d5978",
                    "operator": {
                      "type": "number",
                      "operation": "equals"
                    },
                    "leftValue": "={{ $('Loop Over Deals').item.json.daysLeft }}",
                    "rightValue": 30
                  }
                ]
              }
            },
            {
              "conditions": {
                "options": {
                  "version": 3,
                  "leftValue": "",
                  "caseSensitive": true,
                  "typeValidation": "loose"
                },
                "combinator": "and",
                "conditions": [
                  {
                    "id": "dbf65d57-ffa0-4599-ab97-1cf49935b4c0",
                    "operator": {
                      "name": "filter.operator.equals",
                      "type": "string",
                      "operation": "equals"
                    },
                    "leftValue": "={{ $('Loop Over Deals').item.json.daysLeft }}",
                    "rightValue": "60"
                  }
                ]
              }
            },
            {
              "conditions": {
                "options": {
                  "version": 3,
                  "leftValue": "",
                  "caseSensitive": true,
                  "typeValidation": "loose"
                },
                "combinator": "and",
                "conditions": [
                  {
                    "id": "ca48b087-ac38-4fe9-bcd3-1a66c9c82a4b",
                    "operator": {
                      "name": "filter.operator.equals",
                      "type": "string",
                      "operation": "equals"
                    },
                    "leftValue": "={{ $('Loop Over Deals').item.json.daysLeft }}",
                    "rightValue": "90"
                  }
                ]
              }
            }
          ]
        },
        "options": {},
        "looseTypeValidation": true
      },
      "typeVersion": 3.4
    },
    {
      "id": "e6351f9d-dfdd-4d22-9c57-c0516e3cc746",
      "name": "Merge",
      "type": "n8n-nodes-base.merge",
      "position": [
        22112,
        5520
      ],
      "parameters": {
        "numberInputs": 3
      },
      "typeVersion": 3.2
    },
    {
      "id": "94742aac-f36c-49d5-82a1-34f15becc486",
      "name": "30 day mail",
      "type": "n8n-nodes-base.gmail",
      "position": [
        21888,
        5344
      ],
      "parameters": {
        "sendTo": "={{ $json[\"identity-profiles\"][0].identities[0].value }}",
        "message": "=<!DOCTYPE html>\n<html>\n<body style=\"font-family: Arial, sans-serif; line-height: 1.6; color: #333;\">\n  <h2 style=\"color: #e74c3c;\">Urgent: Contract Expiring Soon</h2>\n\n  <p>Hi {{ $json.properties.hs_full_name_or_email.value }},</p>\n\n  <p>\n    This is an important reminder that your contract for \n    <strong>{{ $('Loop Over Deals').item.json.dealName }}</strong> is expiring in just \n    <strong>{{ $('Loop Over Deals').item.json.daysLeft }} days</strong>.\n  </p>\n\n  <p>\n    To avoid any disruption in service, we recommend renewing your contract as soon as possible.\n  </p>\n\n  <p>\n    Please let us know a convenient time to discuss or proceed with renewal.\n  </p>\n\n  <br/>\n\n  <p style=\"color: #e74c3c; font-weight: bold;\">\n    Action required: Please respond at your earliest convenience.\n  </p>\n\n  <p>Best regards,<br/>Your Team</p>\n</body>\n</html>",
        "options": {},
        "subject": "Action Required: Contract Expiring in 30 Days"
      },
      "typeVersion": 2.2
    },
    {
      "id": "89ef810b-bbc5-47d0-8a71-3895b4a73f7e",
      "name": "60 day mail",
      "type": "n8n-nodes-base.gmail",
      "position": [
        21888,
        5536
      ],
      "parameters": {
        "sendTo": "={{ $json[\"identity-profiles\"][0].identities[0].value }}",
        "message": "=<!DOCTYPE html>\n<html>\n<body style=\"font-family: Arial, sans-serif; line-height: 1.6; color: #333;\">\n  <h2 style=\"color: #f39c12;\">Contract Renewal Reminder</h2>\n\n  <p>Hi {{ $json.properties.hs_full_name_or_email.value }},</p>\n\n  <p>\n    Just a friendly reminder that your contract for \n    <strong>{{ $('Loop Over Deals').item.json.dealName }}</strong> will expire in \n    <strong>{{ $('Loop Over Deals').item.json.daysLeft }}  days</strong>.\n  </p>\n\n  <p>\n    We recommend starting the renewal process to ensure uninterrupted service.\n  </p>\n\n  <p>\n    Our team would be happy to assist you with renewal options or any queries.\n  </p>\n\n  <br/>\n\n  <p>\n    Looking forward to continuing working with you \ud83e\udd1d\n  </p>\n\n  <p>Best regards,<br/>Your Team</p>\n</body>\n</html>",
        "options": {},
        "subject": "Action Required: Contract Expiring in 60 Days"
      },
      "typeVersion": 2.2
    },
    {
      "id": "f5a63d76-94a0-4d12-9b05-d67389853493",
      "name": "90 day mail",
      "type": "n8n-nodes-base.gmail",
      "position": [
        21888,
        5728
      ],
      "parameters": {
        "sendTo": "={{ $json[\"identity-profiles\"][0].identities[0].value }}",
        "message": "=<!DOCTYPE html>\n<html>\n<body style=\"font-family: Arial, sans-serif; line-height: 1.6; color: #333;\">\n  <h2 style=\"color: #2c3e50;\">Contract Expiry Notice</h2>\n\n  <p>Hi {{ $json.properties.hs_full_name_or_email.value }},</p>\n\n  <p>\n    We hope you're doing well \ud83d\ude0a\n  </p>\n\n  <p>\n    This is a quick heads-up that your contract for \n    <strong>{{ $('Loop Over Deals').first().json.dealName }}</strong> is set to expire in \n    <strong>{{ $('Loop Over Deals').first().json.daysLeft }} days</strong>.\n  </p>\n\n  <p>\n    No action is required right now, but we wanted to keep you informed in advance.\n  </p>\n\n  <p>\n    If you have any questions or would like to discuss renewal options, feel free to reach out.\n  </p>\n\n  <br/>\n\n  <p>Best regards,<br/>Your Team</p>\n</body>\n</html>",
        "options": {},
        "subject": "Action Required: Contract Expiring in 90 Days"
      },
      "typeVersion": 2.2
    },
    {
      "id": "498a2192-44ea-47db-acfe-ccf8a28e3f28",
      "name": "Sticky Note",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        19712,
        5168
      ],
      "parameters": {
        "width": 576,
        "height": 800,
        "content": "# Contract Expiry & Renewal Alert System\n\nThis workflow automates contract renewal management by tracking upcoming expirations and triggering timely actions. It ensures that no contract is missed by proactively notifying clients and internal teams, improving retention and operational efficiency.\n\n### How it works\n\n1. Runs on a schedule to fetch all deals from HubSpot.\n2. Filters contracts expiring in 30, 60, or 90 days.\n3. Loops through each deal and fetches associated contact details.\n4. Routes deals using a Switch node based on days left.\n5. Sends automated email reminders via Gmail.\n6. Notifies account managers in Slack.\n7. Creates follow-up tasks in ClickUp for tracking.\n\n### Setup steps\n\n* Connect your HubSpot account (Deals + Contacts access required).\n* Configure Gmail credentials for sending emails.\n* Add Slack credentials for internal notifications.\n* Connect ClickUp API for task creation.\n* Replace any placeholder API keys (e.g., HubSpot HTTP node).\n* Adjust schedule trigger timing based on your needs."
      },
      "typeVersion": 1
    },
    {
      "id": "8dc837fb-85a5-4dfa-afa2-afa1fba7e5a2",
      "name": "Sticky Note1",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        20320,
        5168
      ],
      "parameters": {
        "color": 7,
        "width": 560,
        "height": 800,
        "content": "## Step 1: Schedule & Filter Contracts\n\nRuns on a schedule, fetches deals from HubSpot, and filters contracts expiring in 30, 60, or 90 days.\n"
      },
      "typeVersion": 1
    },
    {
      "id": "8c1f33c5-c677-4aa7-be1f-9a8d0b9bd6d3",
      "name": "Sticky Note2",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        20912,
        5168
      ],
      "parameters": {
        "color": 7,
        "width": 672,
        "height": 800,
        "content": "## Step 2: Process Deals & Fetch Contacts\n\nLoops through deals, fetches associated contacts, and retrieves email details for communication.\n"
      },
      "typeVersion": 1
    },
    {
      "id": "41da35be-799b-4ead-ade1-cbe5493150f4",
      "name": "Sticky Note3",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        21616,
        5168
      ],
      "parameters": {
        "color": 7,
        "width": 640,
        "height": 800,
        "content": "## Step 3: Email Routing & Sending\n\nUses a Switch node to route deals (30/60/90 days) and sends personalized emails via Gmail.\n"
      },
      "typeVersion": 1
    },
    {
      "id": "a10e08e6-4706-4480-935e-93171af9baca",
      "name": "Sticky Note4",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        22288,
        5168
      ],
      "parameters": {
        "color": 7,
        "width": 448,
        "height": 800,
        "content": "## Step 4: Alerts & Task Creation\n\nSends Slack alerts to account managers and creates ClickUp tasks for follow-up actions.\n"
      },
      "typeVersion": 1
    },
    {
      "id": "d3c6c77f-de19-4e21-bc1d-3ac405288f64",
      "name": "Get all deals",
      "type": "n8n-nodes-base.hubspot",
      "position": [
        20576,
        5712
      ],
      "parameters": {
        "filters": {
          "properties": [
            "contract_expiry_date",
            "dealname"
          ],
          "includeAssociations": false
        },
        "resource": "deal",
        "operation": "getAll",
        "authentication": "appToken"
      },
      "typeVersion": 2.2
    },
    {
      "id": "72fad76e-c127-4b99-b952-f9ec5fb8f553",
      "name": "Filter Deals",
      "type": "n8n-nodes-base.code",
      "position": [
        20752,
        5712
      ],
      "parameters": {
        "jsCode": "const today = new Date();\ntoday.setHours(0, 0, 0, 0);\n\nreturn items\n  .map(item => {\n    const expiryTimestamp = item.json.properties?.contract_expiry_date?.value;\n    if (!expiryTimestamp) return null;\n\n    const expiryDate = new Date(Number(expiryTimestamp));\n    expiryDate.setHours(0, 0, 0, 0);\n\n    const diffDays = Math.round(\n      (expiryDate - today) / (1000 * 60 * 60 * 24)\n    );\n\n    return {\n      json: {\n        dealId: item.json.dealId,\n        dealName: item.json.properties?.dealname?.value || \"No Name\",\n        expiryDate: expiryDate.toISOString().split(\"T\")[0],\n        daysLeft: diffDays\n      }\n    };\n  })\n  .filter(item => item && [30, 60, 90].includes(item.json.daysLeft));"
      },
      "typeVersion": 2
    },
    {
      "id": "ae2b0599-c789-4bb0-bffa-83bb8ce724bb",
      "name": "Loop Over Deals",
      "type": "n8n-nodes-base.splitInBatches",
      "position": [
        20992,
        5712
      ],
      "parameters": {
        "options": {}
      },
      "typeVersion": 3
    },
    {
      "id": "2fa2c3ac-a767-41de-80bb-da51a4e8f938",
      "name": "Fetch Associated Contact With Deal",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        21216,
        5536
      ],
      "parameters": {
        "url": "=https://api.hubapi.com/crm/v3/objects/deals/{{$json[\"dealId\"]}}/associations/contacts",
        "options": {},
        "sendHeaders": true,
        "headerParameters": {
          "parameters": [
            {
              "name": "Authorization",
              "value": "YOUR_HUBSPOT_API_KEY"
            }
          ]
        }
      },
      "typeVersion": 4.3
    },
    {
      "id": "bb461bc3-e283-4fb6-a645-6bf9e051959a",
      "name": "Get Contact Details",
      "type": "n8n-nodes-base.hubspot",
      "position": [
        21440,
        5536
      ],
      "parameters": {
        "contactId": {
          "__rl": true,
          "mode": "id",
          "value": "={{ $json.results[0].id }}"
        },
        "operation": "get",
        "authentication": "appToken",
        "additionalFields": {
          "propertiesCollection": {
            "propertiesValues": {
              "properties": [
                "email"
              ],
              "propertyMode": "valueOnly"
            }
          }
        }
      },
      "typeVersion": 2.2
    },
    {
      "id": "bd3a12f2-ca60-475b-8052-be24296e83cd",
      "name": "Nofity Account Manager",
      "type": "n8n-nodes-base.slack",
      "position": [
        22336,
        5536
      ],
      "parameters": {
        "text": "=\ud83d\udea8 Contract Expiry Alert\n\n\ud83d\udc64 Contact: {{ $('Get Contact Details').item.json.properties.hs_full_name_or_email.value }}\n\ud83d\udcc4 Deal: {{ $('Loop Over Deals').item.json.dealName }}\n\u23f3 Days Left: {{ $('Loop Over Deals').item.json.daysLeft }}\n\nPlease reach out to the client and initiate the renewal process.",
        "user": {
          "__rl": true,
          "mode": "list",
          "value": ""
        },
        "select": "user",
        "otherOptions": {},
        "authentication": "oAuth2"
      },
      "typeVersion": 2.4
    },
    {
      "id": "a85e68e4-e62d-4899-a79c-9578ba5adfd7",
      "name": "Create Follow-up Task",
      "type": "n8n-nodes-base.clickUp",
      "position": [
        22560,
        5712
      ],
      "parameters": {
        "list": "YOUR_CLICKUP_LIST_ID",
        "name": "=Contract Renewal Follow-up: {{ $('Loop Over Deals').item.json.dealName }} ",
        "team": "YOUR_CLICKUP_TEAM_ID",
        "space": "YOUR_CLICKUP_SPACE_ID",
        "folder": "YOUR_CLICKUP_FOLDER_ID",
        "additionalFields": {}
      },
      "typeVersion": 1
    }
  ],
  "connections": {
    "Merge": {
      "main": [
        [
          {
            "node": "Nofity Account Manager",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Switch": {
      "main": [
        [
          {
            "node": "30 day mail",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "60 day mail",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "90 day mail",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "30 day mail": {
      "main": [
        [
          {
            "node": "Merge",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "60 day mail": {
      "main": [
        [
          {
            "node": "Merge",
            "type": "main",
            "index": 1
          }
        ]
      ]
    },
    "90 day mail": {
      "main": [
        [
          {
            "node": "Merge",
            "type": "main",
            "index": 2
          }
        ]
      ]
    },
    "Filter Deals": {
      "main": [
        [
          {
            "node": "Loop Over Deals",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Get all deals": {
      "main": [
        [
          {
            "node": "Filter Deals",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Loop Over Deals": {
      "main": [
        [],
        [
          {
            "node": "Fetch Associated Contact With Deal",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Schedule Trigger": {
      "main": [
        [
          {
            "node": "Get all deals",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Get Contact Details": {
      "main": [
        [
          {
            "node": "Switch",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Create Follow-up Task": {
      "main": [
        [
          {
            "node": "Loop Over Deals",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Nofity Account Manager": {
      "main": [
        [
          {
            "node": "Create Follow-up Task",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Fetch Associated Contact With Deal": {
      "main": [
        [
          {
            "node": "Get Contact Details",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  }
}
Pro

For the full experience including quality scoring and batch install features for each workflow upgrade to Pro

About this workflow

This workflow runs on a schedule to monitor HubSpot deals with upcoming contract expiry dates. It filters deals that are 30, 60, or 90 days away from expiration and processes each one individually. Based on the remaining days, it sends personalized email reminders to contacts…

Source: https://n8n.io/workflows/14155/ — original creator credit. Request a take-down →

More Email & Gmail workflows → · Browse all categories →

Related workflows

Workflows that share integrations, category, or trigger type with this one. All free to copy and import.

Email & Gmail

This workflow identifies HubSpot deals that have gone untouched for 21+ days and automatically updates their status to Closed Lost. It fetches associated contacts, retrieves their details, and sends p

HubSpot, HTTP Request, Gmail +1
Email & Gmail

This workflow is an automated invoice payment tracking and reminder system for the Polish accounting service iFirma.pl. It monitors unpaid and overdue invoices, then automatically sends escalating rem

HTTP Request, Stop And Error, Slack +1
Email & Gmail

📘 Description

HTTP Request, Gmail Trigger, ClickUp +3
Email & Gmail

Following up at the right time is one of the most important parts of sales. This workflow uses Gmail to send outreach emails to Hubspot contacts that have already been contacted only once more than a

Gmail, HubSpot, HTTP Request
Email & Gmail

This workflow automatically monitors solar energy production every 2 hours by fetching data from the Energidataservice API. If the energy output falls below a predefined threshold, it instantly notifi

HTTP Request, Gmail, Google Sheets +1