This workflow corresponds to n8n.io template #17030 — we link there as the canonical source.
This workflow follows the Datatable → Gmail 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 →
{
"nodes": [
{
"id": "bafa7af3-5983-48e0-9512-e369c727fefb",
"name": "Sticky Note",
"type": "n8n-nodes-base.stickyNote",
"position": [
0,
0
],
"parameters": {
"width": 480,
"height": 896,
"content": "## Send Zillow new-listing alerts to Gmail via ScraperAPI\n\n### How it works\n\n1. Initializes data tables and seeds them with sample data.\n2. Sets up an AI parser for scraping Zillow data.\n3. Triggers daily or manual searches using defined search configurations.\n4. Scrapes listings from Zillow and filters out already seen ones.\n5. Records new listings and generates a daily digest emailed via Gmail.\n\n### Setup steps\n\n- [ ] Ensure database credentials are configured for table operations.\n- [ ] Set up ScraperAPI credentials for the Zillow parser.\n- [ ] Configure Gmail account with necessary permissions for email sending.\n\n### Customization\n\nThe digest email can be customized to include specific details or formatting needed for your requirements."
},
"typeVersion": 1
},
{
"id": "f1f277c2-a681-4c02-b472-2dbac9090628",
"name": "Sticky Note1",
"type": "n8n-nodes-base.stickyNote",
"position": [
1024,
0
],
"parameters": {
"color": 7,
"width": 1184,
"height": 320,
"content": "## Initialize database tables\n\nSet up Searches and Seen tables and seed sample searches."
},
"typeVersion": 1
},
{
"id": "c26271a6-0e61-44c3-87dc-3c4894ff7175",
"name": "Sticky Note2",
"type": "n8n-nodes-base.stickyNote",
"position": [
544,
0
],
"parameters": {
"color": 7,
"width": 416,
"height": 320,
"content": "## Setup parser\n\nCreate and configure a Zillow parser using a manual trigger."
},
"typeVersion": 1
},
{
"id": "25fce400-934c-4de5-a152-a732717107db",
"name": "Sticky Note3",
"type": "n8n-nodes-base.stickyNote",
"position": [
544,
384
],
"parameters": {
"color": 7,
"width": 768,
"height": 416,
"content": "## Schedule monitoring triggers\n\nInitiate daily or manual check for new listings from pre-configured searches."
},
"typeVersion": 1
},
{
"id": "dc8b7723-f1bf-427e-b5bc-b4cd2bd7517a",
"name": "Sticky Note4",
"type": "n8n-nodes-base.stickyNote",
"position": [
1392,
736
],
"parameters": {
"color": 7,
"width": 976,
"height": 320,
"content": "## Parse and filter listings\n\nScrape Zillow using the AI parser and filter listings to identify new entries."
},
"typeVersion": 1
},
{
"id": "2c357b93-a7f4-4436-9e62-5662cfd1745d",
"name": "Sticky Note5",
"type": "n8n-nodes-base.stickyNote",
"position": [
2448,
736
],
"parameters": {
"color": 7,
"width": 416,
"height": 320,
"content": "## Process new listings\n\nLog newly identified listings into Seen table for record keeping."
},
"typeVersion": 1
},
{
"id": "cb9078d7-71aa-4489-b652-6b20289ab787",
"name": "Sticky Note6",
"type": "n8n-nodes-base.stickyNote",
"position": [
1392,
384
],
"parameters": {
"color": 7,
"width": 672,
"height": 288,
"content": "## Generate listing digest\n\nFetch today's new listings, create a digest, and send email via Gmail."
},
"typeVersion": 1
},
{
"id": "setup-trigger",
"name": "When Manually Triggered",
"type": "n8n-nodes-base.manualTrigger",
"position": [
1072,
144
],
"parameters": {},
"typeVersion": 1
},
{
"id": "create-searches-table",
"name": "Init Searches Table",
"type": "n8n-nodes-base.dataTable",
"position": [
1264,
144
],
"parameters": {
"columns": {
"column": [
{
"name": "name",
"type": "string"
},
{
"name": "url",
"type": "string"
},
{
"name": "min_price",
"type": "number"
},
{
"name": "max_price",
"type": "number"
},
{
"name": "min_beds",
"type": "number"
},
{
"name": "min_baths",
"type": "number"
}
]
},
"options": {
"createIfNotExists": true
},
"resource": "table",
"operation": "create",
"tableName": "zillow_searches"
},
"typeVersion": 1.1
},
{
"id": "create-seen-table",
"name": "Init Seen Table",
"type": "n8n-nodes-base.dataTable",
"position": [
1456,
144
],
"parameters": {
"columns": {
"column": [
{
"name": "zpid",
"type": "string"
},
{
"name": "search_name",
"type": "string"
},
{
"name": "first_seen",
"type": "string"
},
{
"name": "address",
"type": "string"
},
{
"name": "price",
"type": "number"
},
{
"name": "beds",
"type": "number"
},
{
"name": "baths",
"type": "number"
},
{
"name": "sqft",
"type": "number"
},
{
"name": "url",
"type": "string"
},
{
"name": "image_url",
"type": "string"
}
]
},
"options": {
"createIfNotExists": true
},
"resource": "table",
"operation": "create",
"tableName": "zillow_seen"
},
"typeVersion": 1.1
},
{
"id": "read-existing-searches",
"name": "Fetch Existing Searches",
"type": "n8n-nodes-base.dataTable",
"position": [
1680,
144
],
"parameters": {
"filters": {
"conditions": []
},
"resource": "row",
"matchType": "anyCondition",
"operation": "get",
"returnAll": true,
"dataTableId": {
"__rl": true,
"mode": "name",
"value": "zillow_searches"
}
},
"typeVersion": 1.1,
"alwaysOutputData": true
},
{
"id": "seed-sample-searches",
"name": "Create Sample Searches",
"type": "n8n-nodes-base.code",
"position": [
1872,
144
],
"parameters": {
"jsCode": "const existing = new Set(\n $input.all()\n .map(i => (i.json && i.json.name ? String(i.json.name).trim().toLowerCase() : ''))\n .filter(Boolean)\n);\n\nconst samples = [\n {\n name: 'Austin TX \u2014 for sale, 3+ beds, under $600k',\n url: 'https://www.zillow.com/austin-tx/houses/3-_beds/0-600000_price/',\n min_price: 0,\n max_price: 600000,\n min_beds: 3,\n min_baths: 2,\n },\n {\n name: 'Denver CO \u2014 for rent, 1+ beds, under $2500',\n url: 'https://www.zillow.com/denver-co/rentals/1-_beds/0-2500_price/',\n min_price: 0,\n max_price: 2500,\n min_beds: 1,\n min_baths: 1,\n },\n];\n\nreturn samples\n .filter(s => !existing.has(s.name.toLowerCase()))\n .map(s => ({ json: s }));\n",
"language": "javaScript"
},
"typeVersion": 2
},
{
"id": "insert-sample-searches",
"name": "Add to Searches Table",
"type": "n8n-nodes-base.dataTable",
"position": [
2064,
144
],
"parameters": {
"columns": {
"value": {
"url": "={{ $json.url }}",
"name": "={{ $json.name }}",
"min_beds": "={{ $json.min_beds }}",
"max_price": "={{ $json.max_price }}",
"min_baths": "={{ $json.min_baths }}",
"min_price": "={{ $json.min_price }}"
},
"mappingMode": "defineBelow"
},
"options": {},
"resource": "row",
"operation": "insert",
"dataTableId": {
"__rl": true,
"mode": "name",
"value": "zillow_searches"
}
},
"typeVersion": 1.1
},
{
"id": "setup-parser-trigger",
"name": "Create Parser (run once)",
"type": "n8n-nodes-base.manualTrigger",
"position": [
1264,
112
],
"parameters": {},
"typeVersion": 1
},
{
"id": "create-ai-parser",
"name": "Create Zillow Parser",
"type": "n8n-nodes-scraperapi-official.scraperApi",
"position": [
704,
144
],
"parameters": {
"resource": "aiparser",
"operation": "aiParserCreate",
"aiParserName": "Zillow Search Listings",
"aiParserUrls": [
"https://www.zillow.com/austin-tx/houses/3-_beds/0-600000_price/",
"https://www.zillow.com/denver-co/rentals/1-_beds/0-2500_price/",
"https://www.zillow.com/seattle-wa/houses/2-_beds/0-800000_price/"
],
"aiParserCreateFields": {
"field": [
{
"name": "listings.zpid",
"type": "string",
"description": "The Zillow property ID (zpid) of the listing"
},
{
"name": "listings.address",
"type": "string",
"description": "The full street address of the listing"
},
{
"name": "listings.price",
"type": "number",
"description": "The listing price in US dollars as a number"
},
{
"name": "listings.beds",
"type": "number",
"description": "Number of bedrooms"
},
{
"name": "listings.baths",
"type": "number",
"description": "Number of bathrooms"
},
{
"name": "listings.sqft",
"type": "number",
"description": "Interior living area in square feet"
},
{
"name": "listings.url",
"type": "string",
"description": "Absolute URL to the listing detail page"
},
{
"name": "listings.image_url",
"type": "string",
"description": "URL of the primary listing photo"
}
]
},
"aiParserScraperParams": {
"render": true,
"premium": true,
"country_code": "us"
}
},
"typeVersion": 1
},
{
"id": "monitor-schedule-trigger",
"name": "When Daily at 9AM",
"type": "n8n-nodes-base.scheduleTrigger",
"position": [
608,
560
],
"parameters": {
"rule": {
"interval": [
{
"field": "cronExpression",
"expression": "0 9 * * *"
}
]
}
},
"typeVersion": 1.2
},
{
"id": "monitor-manual-trigger",
"name": "When Manually Started",
"type": "n8n-nodes-base.manualTrigger",
"position": [
-1136,
864
],
"parameters": {},
"typeVersion": 1
},
{
"id": "fetch-searches",
"name": "Get Search Configs",
"type": "n8n-nodes-base.dataTable",
"position": [
896,
560
],
"parameters": {
"filters": {
"conditions": []
},
"resource": "row",
"matchType": "anyCondition",
"operation": "get",
"returnAll": true,
"dataTableId": {
"__rl": true,
"mode": "name",
"value": "zillow_searches"
}
},
"typeVersion": 1.1
},
{
"id": "iterate-searches",
"name": "Loop Over Search Configs",
"type": "n8n-nodes-base.splitInBatches",
"position": [
1152,
560
],
"parameters": {
"options": {},
"batchSize": 1
},
"typeVersion": 3
},
{
"id": "parse-zillow-aiparser",
"name": "Parse Zillow via AI Parser",
"type": "n8n-nodes-scraperapi-official.scraperApi",
"maxTries": 2,
"position": [
1440,
896
],
"parameters": {
"resource": "aiparser",
"operation": "aiParserParse",
"aiParserId": "REPLACE_WITH_PARSER_ID",
"aiParserUrl": "={{ $json.url }}",
"aiParserVersion": -1,
"aiParserScraperParams": {
"render": true,
"premium": true,
"country_code": "us"
}
},
"retryOnFail": true,
"typeVersion": 1,
"continueOnFail": true,
"waitBetweenTries": 2000
},
{
"id": "filter-listings",
"name": "Filter Listings",
"type": "n8n-nodes-base.code",
"position": [
1680,
896
],
"parameters": {
"jsCode": "// The ScraperAPI AI Parser already scraped Zillow and extracted the\n// listings for us, so there's no HTML parsing left to do here. We just\n// coerce the extracted fields to consistent types and keep the listings\n// that match this search's price / beds / baths thresholds.\n\nconst search = $('Loop Over Search Configs').item.json;\nconst response = ($input.first().json || {}).response || {};\n\n// The AI Parser returns { parser, version, result }. n8n normally hands us\n// `body` already parsed, but guard against a JSON string just in case.\nlet body = response.body;\nif (typeof body === 'string') {\n try { body = JSON.parse(body); } catch (_) { body = {}; }\n}\nconst result = (body && body.result) || {};\nconst rawListings = Array.isArray(result.listings) ? result.listings : [];\n\nconst num = (v) => {\n if (v === null || v === undefined || v === '') return 0;\n const s = typeof v === 'string' ? v.replace(/[^0-9.]/g, '') : v;\n const n = Number(s);\n return Number.isFinite(n) ? n : 0;\n};\n\nconst toUrl = (u) => {\n if (!u) return '';\n const s = String(u);\n if (s.startsWith('http')) return s;\n return 'https://www.zillow.com' + (s.startsWith('/') ? '' : '/') + s;\n};\n\n// Zillow search-results cards don't expose a standalone zpid, so the AI\n// Parser returns zpid: null. The stable id lives in the detail URL as\n// `<...>/<zpid>_zpid/` \u2014 derive it from there, falling back to any\n// zpid the parser did manage to extract.\nconst zpidFrom = (r) => {\n const raw = r.zpid;\n if (raw !== null && raw !== undefined && String(raw).trim() !== '') {\n return String(raw).trim();\n }\n const m = String(r.url || '').match(/(\\d+)_zpid/);\n return m ? m[1] : '';\n};\n\nconst minPrice = num(search.min_price);\nconst maxPrice = num(search.max_price) || Infinity;\nconst minBeds = num(search.min_beds);\nconst minBaths = num(search.min_baths);\n\nconst seenInScrape = new Set();\nconst matching = [];\nfor (const r of rawListings) {\n const l = {\n zpid: zpidFrom(r),\n address: String(r.address || '').trim(),\n price: num(r.price),\n beds: num(r.beds),\n baths: num(r.baths),\n sqft: num(r.sqft),\n url: toUrl(r.url),\n image_url: String(r.image_url || ''),\n };\n if (!l.zpid || seenInScrape.has(l.zpid)) continue;\n if (l.price > 0 && (l.price < minPrice || l.price > maxPrice)) continue;\n if (l.beds > 0 && l.beds < minBeds) continue;\n if (l.baths > 0 && l.baths < minBaths) continue;\n seenInScrape.add(l.zpid);\n matching.push(l);\n}\n\nreturn [{\n json: {\n search_name: search.name,\n search_url: search.url,\n parsed_count: rawListings.length,\n match_count: matching.length,\n listings: matching,\n },\n pairedItem: { item: 0 },\n}];\n",
"language": "javaScript"
},
"typeVersion": 2,
"alwaysOutputData": true
},
{
"id": "lookup-seen",
"name": "Check Seen Listings",
"type": "n8n-nodes-base.dataTable",
"position": [
2000,
896
],
"parameters": {
"filters": {
"conditions": [
{
"keyName": "search_name",
"keyValue": "={{ $('Loop Over Search Configs').item.json.name }}",
"condition": "eq"
}
]
},
"resource": "row",
"matchType": "allConditions",
"operation": "get",
"returnAll": true,
"dataTableId": {
"__rl": true,
"mode": "name",
"value": "zillow_seen"
}
},
"typeVersion": 1.1,
"alwaysOutputData": true
},
{
"id": "identify-new",
"name": "Find New Listings",
"type": "n8n-nodes-base.code",
"position": [
2224,
896
],
"parameters": {
"jsCode": "// Diff the current scrape against ZPIDs already in zillow_seen for this\n// search. Output one summary item; fan out to insert and to the loop\n// continuation in parallel.\n\nconst parse = $('Filter Listings').item.json || {};\nconst listings = Array.isArray(parse.listings) ? parse.listings : [];\n\nconst seenRows = $input.all().map(i => i.json).filter(r => r && r.zpid);\nconst seenIds = new Set(seenRows.map(r => String(r.zpid)));\n\nconst now = new Date().toISOString();\nconst newListings = [];\nfor (const l of listings) {\n if (!l.zpid || seenIds.has(String(l.zpid))) continue;\n newListings.push({\n zpid: String(l.zpid),\n search_name: parse.search_name,\n first_seen: now,\n address: l.address || '',\n price: Number(l.price) || 0,\n beds: Number(l.beds) || 0,\n baths: Number(l.baths) || 0,\n sqft: Number(l.sqft) || 0,\n url: l.url || '',\n image_url: l.image_url || '',\n });\n}\n\nreturn [{\n json: {\n search_name: parse.search_name,\n parsed_count: parse.parsed_count || 0,\n match_count: parse.match_count || 0,\n seen_count: seenIds.size,\n new_count: newListings.length,\n new_listings: newListings,\n },\n}];\n",
"language": "javaScript"
},
"typeVersion": 2,
"alwaysOutputData": true
},
{
"id": "split-new",
"name": "Explode New Listings",
"type": "n8n-nodes-base.splitOut",
"position": [
2496,
896
],
"parameters": {
"include": "noOtherFields",
"options": {},
"fieldToSplitOut": "new_listings"
},
"typeVersion": 1
},
{
"id": "insert-seen",
"name": "Log Seen Listing",
"type": "n8n-nodes-base.dataTable",
"position": [
2720,
896
],
"parameters": {
"columns": {
"value": {
"url": "={{ $json.url }}",
"beds": "={{ $json.beds }}",
"sqft": "={{ $json.sqft }}",
"zpid": "={{ $json.zpid }}",
"baths": "={{ $json.baths }}",
"price": "={{ $json.price }}",
"address": "={{ $json.address }}",
"image_url": "={{ $json.image_url }}",
"first_seen": "={{ $json.first_seen }}",
"search_name": "={{ $json.search_name }}"
},
"mappingMode": "defineBelow"
},
"options": {},
"resource": "row",
"operation": "insert",
"dataTableId": {
"__rl": true,
"mode": "name",
"value": "zillow_seen"
}
},
"typeVersion": 1.1
},
{
"id": "fetch-todays-new",
"name": "Get Today's New Listings",
"type": "n8n-nodes-base.dataTable",
"position": [
1440,
512
],
"parameters": {
"filters": {
"conditions": [
{
"keyName": "first_seen",
"keyValue": "={{ $now.startOf('day').toISO() }}",
"condition": "gte"
}
]
},
"resource": "row",
"matchType": "allConditions",
"operation": "get",
"returnAll": true,
"dataTableId": {
"__rl": true,
"mode": "name",
"value": "zillow_seen"
}
},
"executeOnce": true,
"typeVersion": 1.1,
"alwaysOutputData": true
},
{
"id": "build-digest",
"name": "Create Listing Digest",
"type": "n8n-nodes-base.code",
"position": [
1680,
512
],
"parameters": {
"jsCode": "// Group today's new listings by search and render an HTML digest.\n// Returns [] when nothing turned up \u2014 that short-circuits the Gmail node.\n\nconst rows = $input.all().map(i => i.json).filter(r => r && r.zpid);\nif (rows.length === 0) return [];\n\nconst esc = (s) => String(s == null ? '' : s).replace(/[&<>\"']/g, c => ({'&':'&','<':'<','>':'>','\"':'"',\"'\":'''}[c]));\nconst fmtPrice = (n) => !n ? '\u2014' : '$' + Number(n).toLocaleString();\nconst fmtSqft = (n) => !n ? '\u2014' : Number(n).toLocaleString() + ' sqft';\n\nconst groups = new Map();\nfor (const r of rows) {\n const key = String(r.search_name || 'Unsorted');\n if (!groups.has(key)) groups.set(key, []);\n groups.get(key).push(r);\n}\n\nfor (const list of groups.values()) {\n list.sort((a, b) => (Number(a.price) || 0) - (Number(b.price) || 0));\n}\n\nconst today = new Date().toISOString().slice(0, 10);\nconst total = rows.length;\nconst subject = `Zillow \u2014 ${total} new listing${total === 1 ? '' : 's'} on ${today}`;\n\nconst sections = [];\nfor (const [name, list] of groups) {\n const rowsHtml = list.map(l => `<tr>\n <td>${l.image_url ? `<img src=\"${esc(l.image_url)}\" alt=\"\" width=\"96\" style=\"display:block;border-radius:4px;\" />` : ''}</td>\n <td>\n <div style=\"font-weight:600;\"><a href=\"${esc(l.url)}\" style=\"color:#0a4d8c;text-decoration:none;\">${esc(l.address)}</a></div>\n <div style=\"color:#555;font-size:13px;\">${esc(l.beds)} bd \u00b7 ${esc(l.baths)} ba \u00b7 ${esc(fmtSqft(l.sqft))}</div>\n </td>\n <td style=\"text-align:right;font-weight:600;white-space:nowrap;\">${esc(fmtPrice(l.price))}</td>\n</tr>`).join('');\n\n sections.push(`<h3 style=\"margin:24px 0 8px;\">${esc(name)} <span style=\"color:#888;font-weight:400;\">(${list.length})</span></h3>\n<table cellpadding=\"8\" cellspacing=\"0\" style=\"border-collapse:collapse;width:100%;font-size:14px;\">\n<tbody>${rowsHtml}</tbody>\n</table>`);\n}\n\nconst html = `<div style=\"font-family:-apple-system,Segoe UI,sans-serif;max-width:760px;\">\n <h2 style=\"margin:0 0 12px;\">${esc(subject)}</h2>\n <p style=\"color:#555;margin:0 0 8px;\">Fresh Zillow listings matching your saved searches, gathered automatically by ScraperAPI.</p>\n ${sections.join('\\n')}\n</div>`;\n\nreturn [{ json: { count: total, subject, html } }];\n",
"language": "javaScript"
},
"typeVersion": 2
},
{
"id": "send-gmail",
"name": "Email Digest via Gmail",
"type": "n8n-nodes-base.gmail",
"position": [
1920,
512
],
"parameters": {
"sendTo": "",
"message": "={{ $json.html }}",
"options": {},
"subject": "={{ $json.subject }}",
"resource": "message",
"emailType": "html",
"operation": "send"
},
"typeVersion": 2.2
}
],
"settings": {
"executionOrder": "v1"
},
"connections": {
"Filter Listings": {
"main": [
[
{
"node": "Check Seen Listings",
"type": "main",
"index": 0
}
]
]
},
"Init Seen Table": {
"main": [
[
{
"node": "Fetch Existing Searches",
"type": "main",
"index": 0
}
]
]
},
"Find New Listings": {
"main": [
[
{
"node": "Explode New Listings",
"type": "main",
"index": 0
},
{
"node": "Loop Over Search Configs",
"type": "main",
"index": 0
}
]
]
},
"When Daily at 9AM": {
"main": [
[
{
"node": "Get Search Configs",
"type": "main",
"index": 0
}
]
]
},
"Get Search Configs": {
"main": [
[
{
"node": "Loop Over Search Configs",
"type": "main",
"index": 0
}
]
]
},
"Check Seen Listings": {
"main": [
[
{
"node": "Find New Listings",
"type": "main",
"index": 0
}
]
]
},
"Init Searches Table": {
"main": [
[
{
"node": "Init Seen Table",
"type": "main",
"index": 0
}
]
]
},
"Explode New Listings": {
"main": [
[
{
"node": "Log Seen Listing",
"type": "main",
"index": 0
}
]
]
},
"Create Listing Digest": {
"main": [
[
{
"node": "Email Digest via Gmail",
"type": "main",
"index": 0
}
]
]
},
"When Manually Started": {
"main": [
[
{
"node": "Get Search Configs",
"type": "main",
"index": 0
}
]
]
},
"Create Sample Searches": {
"main": [
[
{
"node": "Add to Searches Table",
"type": "main",
"index": 0
}
]
]
},
"Fetch Existing Searches": {
"main": [
[
{
"node": "Create Sample Searches",
"type": "main",
"index": 0
}
]
]
},
"When Manually Triggered": {
"main": [
[
{
"node": "Init Searches Table",
"type": "main",
"index": 0
}
]
]
},
"Create Parser (run once)": {
"main": [
[
{
"node": "Create Zillow Parser",
"type": "main",
"index": 0
}
]
]
},
"Get Today's New Listings": {
"main": [
[
{
"node": "Create Listing Digest",
"type": "main",
"index": 0
}
]
]
},
"Loop Over Search Configs": {
"main": [
[
{
"node": "Get Today's New Listings",
"type": "main",
"index": 0
}
],
[
{
"node": "Parse Zillow via AI Parser",
"type": "main",
"index": 0
}
]
]
},
"Parse Zillow via AI Parser": {
"main": [
[
{
"node": "Filter Listings",
"type": "main",
"index": 0
}
]
]
}
}
}
For the full experience including quality scoring and batch install features for each workflow upgrade to Pro
About this workflow
This workflow monitors Zillow searches using ScraperAPI’s AI Parser, stores seen listings in n8n Data Tables, and emails a daily HTML digest of newly found listings via Gmail. Runs on a daily 9AM schedule or manually to check for new listings across saved Zillow search URLs.…
Source: https://n8n.io/workflows/17030/ — original creator credit. Request a take-down →
Related workflows
Workflows that share integrations, category, or trigger type with this one. All free to copy and import.
This workflow listens for Stripe payment failures, looks up the customer in HighLevel, logs or updates the failure in an n8n Data Table, and—when not recently automated—creates a Stripe coupon and ema
This workflow accepts a suspected scam URL via an n8n form, enriches it with RDAP, certificate transparency, DNS/IP hosting data, urlscan.io results, and HTML fingerprints, then correlates findings ag
This workflow runs every Monday at 8 AM and automatically monitors your Jira project, measures progress against the active sprint, and delivers a structured report to stakeholders — with zero manual e
2025-12-03 fix JS code in node
Fetches all open sprint tickets daily from your Jira project Analyzes each ticket for overdue days and blocked status Routes to the right escalation level: assignee email → team Google Chat alert → ma