AutomationFlowsEmail & Gmail › Send Nse Stock Watchlist Alerts with Google Sheets and Gmail

Send Nse Stock Watchlist Alerts with Google Sheets and Gmail

ByWeblineIndia @weblineindia on n8n.io

This workflow polls a Google Sheets stock watchlist every five minutes during weekday market hours, fetches live quotes from an NSE quotes HTTP API, and sends Gmail alerts when prices cross buy-below or sell-above thresholds while logging each triggered alert back to Google…

Cron / scheduled trigger★★★★☆ complexity20 nodesGoogle SheetsGmailHTTP Request
Email & Gmail Trigger: Cron / scheduled Nodes: 20 Complexity: ★★★★☆ Added:

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

This workflow follows the Gmail → Google Sheets 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
{
  "id": "5UieRWkGPv2XT9W1",
  "name": "DIY Stock Watchlist Alert",
  "tags": [],
  "nodes": [
    {
      "id": "d7861ef9-0f89-4c62-95b3-33aec6a30256",
      "name": "Market Hours Polling Trigger",
      "type": "n8n-nodes-base.scheduleTrigger",
      "position": [
        720,
        464
      ],
      "parameters": {
        "rule": {
          "interval": [
            {
              "field": "cronExpression",
              "expression": "*/5 9-15 * * 1-5"
            }
          ]
        }
      },
      "typeVersion": 1.3
    },
    {
      "id": "c22fcd32-029f-46c2-bd08-f7693ed96226",
      "name": "Load Stock Watchlist",
      "type": "n8n-nodes-base.googleSheets",
      "position": [
        944,
        464
      ],
      "parameters": {
        "options": {},
        "sheetName": {
          "__rl": true,
          "mode": "list",
          "value": 955947842,
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/1fwvOWtXwLzgx1FF_v1FaxTMDEiIN0qPF_zE1uFJj1Q8/edit#gid=955947842",
          "cachedResultName": "Stock Watchlist"
        },
        "documentId": {
          "__rl": true,
          "mode": "list",
          "value": "1fwvOWtXwLzgx1FF_v1FaxTMDEiIN0qPF_zE1uFJj1Q8",
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/1fwvOWtXwLzgx1FF_v1FaxTMDEiIN0qPF_zE1uFJj1Q8/edit?usp=drivesdk",
          "cachedResultName": "N8N - PRACTICE"
        }
      },
      "typeVersion": 4.7
    },
    {
      "id": "3c2458b6-7208-46f1-b36c-690b5f98e17a",
      "name": "Filter Active Stocks",
      "type": "n8n-nodes-base.code",
      "position": [
        1184,
        464
      ],
      "parameters": {
        "jsCode": "const rows = $input.all();\nconst symbols = rows\n  .filter(r => r.json.active === true || r.json.active === 'TRUE')\n  .map(r => r.json.symbol.trim().toUpperCase());\n\n// Pass both the symbols array AND the full row data downstream\nreturn [{ json: { symbols, rows: rows.map(r => r.json) } }];"
      },
      "typeVersion": 2
    },
    {
      "id": "9129b871-78a6-4b4e-90ab-86d3ed500381",
      "name": "Prepare NSE Quote Request",
      "type": "n8n-nodes-base.set",
      "position": [
        1408,
        464
      ],
      "parameters": {
        "options": {},
        "assignments": {
          "assignments": [
            {
              "id": "a96ea1f2-9ace-4425-92f8-eaed55e07ace",
              "name": "apiBody",
              "type": "array",
              "value": "={{ $json.rows.map((item)=>{\n  return item.Name\n}) }}"
            },
            {
              "id": "f0b763f0-27a4-4b0e-8dff-dda7a127b061",
              "name": "watchlistRows",
              "type": "array",
              "value": "={{ $json.rows }}"
            }
          ]
        }
      },
      "typeVersion": 3.4
    },
    {
      "id": "222136a6-6d6c-4977-9742-3409122c0abe",
      "name": "Check Alert Availability",
      "type": "n8n-nodes-base.if",
      "position": [
        2128,
        464
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 3,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "c2694ac3-dc08-405c-9067-6f5a42f44386",
              "operator": {
                "type": "object",
                "operation": "notEmpty",
                "singleValue": true
              },
              "leftValue": "={{ $json }}",
              "rightValue": ""
            }
          ]
        }
      },
      "typeVersion": 2.3
    },
    {
      "id": "eab5277e-5add-4759-90dc-9b8760a51c03",
      "name": "No Alerts Exit",
      "type": "n8n-nodes-base.noOp",
      "position": [
        2432,
        544
      ],
      "parameters": {},
      "typeVersion": 1
    },
    {
      "id": "a942de46-4d02-438e-a22c-f14b822c75d0",
      "name": "Route Alert Type",
      "type": "n8n-nodes-base.switch",
      "position": [
        2432,
        320
      ],
      "parameters": {
        "rules": {
          "values": [
            {
              "conditions": {
                "options": {
                  "version": 3,
                  "leftValue": "",
                  "caseSensitive": true,
                  "typeValidation": "strict"
                },
                "combinator": "and",
                "conditions": [
                  {
                    "id": "24b3bbf9-f7f5-4c2d-88b1-8b28002b4d43",
                    "operator": {
                      "name": "filter.operator.equals",
                      "type": "string",
                      "operation": "equals"
                    },
                    "leftValue": "above",
                    "rightValue": "={{ $json.direction }}"
                  }
                ]
              }
            },
            {
              "conditions": {
                "options": {
                  "version": 3,
                  "leftValue": "",
                  "caseSensitive": true,
                  "typeValidation": "strict"
                },
                "combinator": "and",
                "conditions": [
                  {
                    "id": "b25e96dc-c762-499e-870a-517f4235541a",
                    "operator": {
                      "name": "filter.operator.equals",
                      "type": "string",
                      "operation": "equals"
                    },
                    "leftValue": "below",
                    "rightValue": "={{ $json.direction }}"
                  }
                ]
              }
            }
          ]
        },
        "options": {}
      },
      "typeVersion": 3.4
    },
    {
      "id": "dbb643c5-eb7b-4dd4-bc40-fd1dab7e6fe5",
      "name": "Build Sell Alert Message",
      "type": "n8n-nodes-base.set",
      "position": [
        2656,
        272
      ],
      "parameters": {
        "options": {},
        "assignments": {
          "assignments": [
            {
              "id": "4ef295fb-b364-46d1-a064-4893dc47b6b9",
              "name": "alertMessage",
              "type": "string",
              "value": "=SELL ALERT: {{ $json.symbol }} hit \u20b9{{ $json.price }} (above \u20b9{{ $json.threshold }})"
            },
            {
              "id": "71b6d672-ff68-4869-863e-675cc93b0a7b",
              "name": "subject",
              "type": "string",
              "value": "=SELL Signal \u2014 {{ $json.symbol }}"
            },
            {
              "id": "8ea5e083-571a-4a71-9d91-cab2cc3c2827",
              "name": "symbol",
              "type": "string",
              "value": "={{ $json.symbol }}"
            },
            {
              "id": "571184ac-ae99-42ec-a566-502896525427",
              "name": "price",
              "type": "number",
              "value": "={{ $json.price }}"
            },
            {
              "id": "e8d8fa20-7e7b-46a6-8bcb-4c7949f1e119",
              "name": "threshold",
              "type": "number",
              "value": "={{ $json.threshold }}"
            },
            {
              "id": "975d1de5-75fe-450b-9854-966739c4473e",
              "name": "direction",
              "type": "string",
              "value": "={{ $json.direction }}"
            }
          ]
        }
      },
      "typeVersion": 3.4
    },
    {
      "id": "6f335a72-763f-4b29-bd52-800ad9bf30a0",
      "name": "Build Buy Alert Message",
      "type": "n8n-nodes-base.set",
      "position": [
        2656,
        464
      ],
      "parameters": {
        "options": {},
        "assignments": {
          "assignments": [
            {
              "id": "8def4666-46f9-4955-a956-a2e879a81d41",
              "name": "alertMessage",
              "type": "string",
              "value": "=BUY ALERT: {{ $json.symbol }} dropped to \u20b9{{ $json.price }} (below \u20b9{{ $json.threshold }})"
            },
            {
              "id": "08a2fb59-0368-40ca-92a5-5d02505d2d97",
              "name": "subject",
              "type": "string",
              "value": "=BUY Signal \u2014 {{ $json.symbol }}"
            },
            {
              "id": "bea7e5ef-7e53-49ec-acd7-9bbd8cbbc393",
              "name": "symbol",
              "type": "string",
              "value": "={{ $json.symbol }}"
            },
            {
              "id": "ce39dfc7-3c14-4f69-afca-ad8647c23b48",
              "name": "price",
              "type": "number",
              "value": "={{ $json.price }}"
            },
            {
              "id": "8eec8d5a-518c-4dad-ac38-f9ffbf18199e",
              "name": "threshold",
              "type": "number",
              "value": "={{ $json.threshold }}"
            },
            {
              "id": "3f1b2293-69e2-4e5d-ac6d-dfc7cb4af1e5",
              "name": "direction",
              "type": "string",
              "value": "={{ $json.direction }}"
            }
          ]
        }
      },
      "typeVersion": 3.4
    },
    {
      "id": "8a26a0c1-898d-4000-8d98-621d3d3b630d",
      "name": "Combine Alert Streams",
      "type": "n8n-nodes-base.merge",
      "position": [
        2880,
        368
      ],
      "parameters": {},
      "typeVersion": 3.2
    },
    {
      "id": "24db3c2a-38bd-4613-a774-ceff7055533f",
      "name": "Send Email Alert",
      "type": "n8n-nodes-base.gmail",
      "position": [
        3216,
        336
      ],
      "parameters": {
        "message": "={{ $json.alertMessage }}",
        "options": {
          "appendAttribution": false
        },
        "subject": "={{ $json.subject }}",
        "emailType": "text"
      },
      "typeVersion": 2.2
    },
    {
      "id": "9c71b201-6087-42ce-9182-3243d668d5c5",
      "name": "Log Alert History",
      "type": "n8n-nodes-base.googleSheets",
      "position": [
        3216,
        512
      ],
      "parameters": {
        "columns": {
          "value": {
            "price": "={{ $json.price }}",
            "symbol": "={{ $json.symbol }}",
            "direction": "={{ $json.direction }}",
            "threshold": "={{ $json.threshold }}",
            "timestamp": "={{ new Date().toISOString() }}"
          },
          "schema": [
            {
              "id": "timestamp",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "timestamp",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "symbol",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "symbol",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "price",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "price",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "direction",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "direction",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "threshold",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "threshold",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            }
          ],
          "mappingMode": "defineBelow",
          "matchingColumns": [],
          "attemptToConvertTypes": false,
          "convertFieldsToString": false
        },
        "options": {},
        "operation": "append",
        "sheetName": {
          "__rl": true,
          "mode": "list",
          "value": 1545314164,
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/1fwvOWtXwLzgx1FF_v1FaxTMDEiIN0qPF_zE1uFJj1Q8/edit#gid=1545314164",
          "cachedResultName": "AlertLog"
        },
        "documentId": {
          "__rl": true,
          "mode": "list",
          "value": "1fwvOWtXwLzgx1FF_v1FaxTMDEiIN0qPF_zE1uFJj1Q8",
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/1fwvOWtXwLzgx1FF_v1FaxTMDEiIN0qPF_zE1uFJj1Q8/edit?usp=drivesdk",
          "cachedResultName": "N8N - PRACTICE"
        }
      },
      "typeVersion": 4.7
    },
    {
      "id": "e5baf996-9fba-4311-a90a-006933dee0db",
      "name": "Sticky Note",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        0,
        -176
      ],
      "parameters": {
        "width": 608,
        "height": 864,
        "content": "## Stock Watchlist Monitoring & Alert Automation\nThis workflow continuously monitors stock prices from a Google Sheets watchlist and automatically generates BUY or SELL alerts when configured thresholds are reached.\n\n\n### How it works:\nThe workflow runs every 5 minutes during market hours using a schedule trigger.\nActive stocks are loaded from the Stock Watchlist sheet.\nOnly enabled rows are processed and converted into a request payload.\nLatest market prices are fetched from the NSE quotes API.\nCurrent prices are compared against the configured buy_below and sell_above values.\nMatching conditions generate alert records with stock symbol, current price, threshold, and signal type.\nAlerts are split into BUY and SELL paths to create appropriate messages.\nNotifications are emailed and every alert is stored in the AlertLog sheet for tracking.\n\n### Setup steps:\nConfigure Google Sheets credentials.\nCreate Stock Watchlist and AlertLog sheets.\nEnsure watchlist contains symbol, active, buy_below, and sell_above columns.\nConfigure Gmail credentials for notifications.\nVerify NSE quote API availability.\nAdjust market schedule timing if needed."
      },
      "typeVersion": 1
    },
    {
      "id": "24708b4c-5619-4ebb-b654-46f42104a644",
      "name": "Sticky Note1",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        656,
        192
      ],
      "parameters": {
        "color": 2,
        "width": 432,
        "height": 496,
        "content": "### Trigger & Watchlist Loading\n\nLoads stock tracking configuration from Google Sheets.\n\nRuns every 5 minutes during market sessions and retrieves watchlist rows."
      },
      "typeVersion": 1
    },
    {
      "id": "94336ac1-0d5e-49c2-8bd1-2286ecae996d",
      "name": "Sticky Note2",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1136,
        192
      ],
      "parameters": {
        "color": 2,
        "width": 640,
        "height": 496,
        "content": "### Data Preparation & Market Fetch\n\nPrepares symbols and requests latest market quotes.\n\nBuilds API payload and retrieves live stock prices."
      },
      "typeVersion": 1
    },
    {
      "id": "32752f12-19ff-4eed-9bc7-87954dbf6742",
      "name": "Sticky Note3",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1824,
        192
      ],
      "parameters": {
        "color": 2,
        "width": 480,
        "height": 496,
        "content": "### Alert Detection Engine\n\nCompares market prices against configured thresholds.\n\nStops execution when no conditions are matched."
      },
      "typeVersion": 1
    },
    {
      "id": "b0779753-9428-4eeb-b8cb-5916de08a243",
      "name": "Sticky Note4",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        2384,
        128
      ],
      "parameters": {
        "color": 2,
        "width": 640,
        "height": 560,
        "content": "### Alert Routing & Message Creation\n\nSeparates BUY and SELL events and creates notification messages.\n\nProduces standardized alert outputs."
      },
      "typeVersion": 1
    },
    {
      "id": "a1d92315-0cb3-4b95-b31f-1debcde2058b",
      "name": "Sticky Note5",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        3056,
        128
      ],
      "parameters": {
        "color": 2,
        "width": 416,
        "height": 560,
        "content": "### Notification & Logging\n\nFinal delivery and audit layer.\n\nSends notifications and stores alerts in Google Sheets history."
      },
      "typeVersion": 1
    },
    {
      "id": "ac814d2d-5a79-4aed-8a6c-6dc9c33031d3",
      "name": "Detect Buy Sell Signals",
      "type": "n8n-nodes-base.code",
      "position": [
        1904,
        464
      ],
      "parameters": {
        "jsCode": "let apiResponse = []; // array of quotes\nfor (const key in $input.first().json.prices) {\n  if (Object.prototype.hasOwnProperty.call($input.first().json.prices, key)) {\n    const element = $input.first().json.prices[key];\n    apiResponse.push(element);\n  }\n}\n\nconst watchlistRows = $('Prepare NSE Quote Request').first().json.watchlistRows;\nconsole.log(watchlistRows)\n\n\n// Build a price map\nconst priceMap = {};\napiResponse.forEach(q => { priceMap[q.symbol] = q.last_price; });\n\nconst alerts = [];\nwatchlistRows.forEach(row => {\n  const price = priceMap[row.Name];\n  if (!price) return;\n\n  const above = row.sell_above && price >= parseFloat(row.sell_above);\n  const below = row.buy_below  && price <= parseFloat(row.buy_below);\n\n  if (above || below) {\n    alerts.push({\n      symbol:    row.Name,\n      price,\n      threshold: above ? row.sell_above : row.buy_below,\n      direction: above ? 'above' : 'below',\n    });\n  }\n});\n\nreturn alerts.map(a => ({ json: a }));"
      },
      "typeVersion": 2
    },
    {
      "id": "f66ffbb2-6981-4869-b9c9-1c0e5ddb692f",
      "name": "Fetch NSE Market Quotes",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        1632,
        464
      ],
      "parameters": {
        "url": "https://memic-nse-quotes-api.hf.space/quotes",
        "method": "POST",
        "options": {
          "timeout": 10000
        },
        "jsonBody": "={{ {\n\"symbols\": $json.apiBody\n} }}",
        "sendBody": true,
        "specifyBody": "json"
      },
      "typeVersion": 4.4
    }
  ],
  "active": false,
  "settings": {
    "binaryMode": "separate",
    "availableInMCP": false,
    "executionOrder": "v1"
  },
  "versionId": "ba2f4722-a1d5-4a91-b632-916506e2dfe4",
  "nodeGroups": [],
  "connections": {
    "Route Alert Type": {
      "main": [
        [
          {
            "node": "Build Sell Alert Message",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Build Buy Alert Message",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Filter Active Stocks": {
      "main": [
        [
          {
            "node": "Prepare NSE Quote Request",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Load Stock Watchlist": {
      "main": [
        [
          {
            "node": "Filter Active Stocks",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Combine Alert Streams": {
      "main": [
        [
          {
            "node": "Send Email Alert",
            "type": "main",
            "index": 0
          },
          {
            "node": "Log Alert History",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Build Buy Alert Message": {
      "main": [
        [
          {
            "node": "Combine Alert Streams",
            "type": "main",
            "index": 1
          }
        ]
      ]
    },
    "Detect Buy Sell Signals": {
      "main": [
        [
          {
            "node": "Check Alert Availability",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Fetch NSE Market Quotes": {
      "main": [
        [
          {
            "node": "Detect Buy Sell Signals",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Build Sell Alert Message": {
      "main": [
        [
          {
            "node": "Combine Alert Streams",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Check Alert Availability": {
      "main": [
        [
          {
            "node": "Route Alert Type",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "No Alerts Exit",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Prepare NSE Quote Request": {
      "main": [
        [
          {
            "node": "Fetch NSE Market Quotes",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Market Hours Polling Trigger": {
      "main": [
        [
          {
            "node": "Load Stock Watchlist",
            "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 polls a Google Sheets stock watchlist every five minutes during weekday market hours, fetches live quotes from an NSE quotes HTTP API, and sends Gmail alerts when prices cross buy-below or sell-above thresholds while logging each triggered alert back to Google…

Source: https://n8n.io/workflows/17799/ — 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

YOUR_ID 4. Uses gmail, googleDrive, googleSheets, httpRequest. Scheduled trigger; 53 nodes.

Gmail, Google Drive, Google Sheets +1
Email & Gmail

Looking for a way to track GitHub bounty issues automatically and get notified in real time? This GitHub Bounty Tracker workflow monitors repositories for issues labeled 💎 Bounty, logs them in Google

Google Sheets, HTTP Request, WhatsApp +1
Email & Gmail

This workflow automatically sends a beautifully designed HTML newsletter every Sunday at 8 AM, featuring products currently on sale from your Algolia-powered e-commerce store.

Google Sheets, HTTP Request, Gmail
Email & Gmail

This n8n template demonstrates how to build a Auto Lead Gen & Outreach System for Local Businesses specifically designed to help businesses that don’t have a website yet.

Google Sheets, HTTP Request, Google Drive +1
Email & Gmail

I created this workflow with care for marketing professionals and agencies who manage multiple Meta Ads (Facebook) accounts and want to track ad account balances automatically — no more logging in eve

HTTP Request, Google Sheets, Gmail