Predict deal close dates and update Salesforce with Groq and Google Sheets
Pull contacts, verify each address with BillionVerify, and continue to Close β only deliverable addresses get through.
Why verify before the send
Sending to invalid, risky, catch-all, or disposable addresses spikes your bounce rate and erodes sender reputation. A verification gate before the Close step removes that risk automatically β only deliverable addresses continue, the rest are flagged.
The workflow
BillionVerify β verification sits right before the send.
Node by node
- 1InsightsSourceΒ· n8n
Provides or transforms the contact data flowing through the workflow.
- 2Run ScheduleTriggerΒ· n8n
Starts the workflow β on a schedule, a webhook, or manually while you test.
- 3Set Lookback TimeframeSourceΒ· n8n
Provides or transforms the contact data flowing through the workflow.
- 4Fetch Historical Won DealsSourceΒ· n8n
Provides or transforms the contact data flowing through the workflow.
- 5Fetch Recent Active DealsSourceΒ· n8n
Provides or transforms the contact data flowing through the workflow.
- 6Process OpportunitiesSourceΒ· n8n
Provides or transforms the contact data flowing through the workflow.
- 7Fetch Deal DetailsSourceΒ· n8n
Provides or transforms the contact data flowing through the workflow.
- 8Deal Task HistorySourceΒ· n8n
Provides or transforms the contact data flowing through the workflow.
- 9Is Deal Valid & Active?LogicΒ· n8n
Branches on the verification result: only deliverable addresses continue to the send; the rest are skipped and flagged.
- 10Calculate Deal Risk & VelocitySourceΒ· n8n
Provides or transforms the contact data flowing through the workflow.
- 11AI Deal Timeline PredictorSourceΒ· n8n
Provides or transforms the contact data flowing through the workflow.
- 12Parse AI OutputSourceΒ· n8n
Provides or transforms the contact data flowing through the workflow.
- 13check confidence scoreLogicΒ· n8n
Branches on the verification result: only deliverable addresses continue to the send; the rest are skipped and flagged.
- 14Update Close DateSourceΒ· n8n
Provides or transforms the contact data flowing through the workflow.
- 15Verify Email (BillionVerify)VerifyΒ· billionverify
The BillionVerify node verifies the address β status (valid / invalid / risky / catch-all / role / disposable), is_deliverable, and a confidence score β before anything is sent.
- 16Log Auto-Update SuccessSourceΒ· n8n
Provides or transforms the contact data flowing through the workflow.
- 17IF deliverableLogicΒ· n8n
Branches on the verification result: only deliverable addresses continue to the send; the rest are skipped and flagged.
- 18alert for Manual reviewSendΒ· n8n
Sends only to verified, deliverable addresses. Swap in your own provider node if you send elsewhere.
- 19Log Pending ReviewSourceΒ· n8n
Provides or transforms the contact data flowing through the workflow.
Workflow JSON
Copy or download this workflow, then import it in n8n (Workflows β Import from File / Paste). Install the BillionVerify community node first, then add your API key credential.
{
"name": "Predict deal close dates and update Salesforce with Groq and Google Sheets + BillionVerify",
"nodes": [
{
"id": "2d2c59b6-1d23-4124-95c3-caba52218f0b",
"name": "AI Deal Timeline Predictor",
"type": "@n8n/n8n-nodes-langchain.agent",
"position": [
16,
-960
],
"parameters": {
"text": "=Analyze this opportunity and predict the most realistic close timeline.\n\nOpportunity Details:\nName: {{ $json.Name }}\nStage: {{ $json.StageName }}\nAmount: {{ $json.Amount }}\nCurrent Probability: {{ $json.Probability }}\nCurrent Close Date: {{ $json.CloseDate }}\nLead Source: {{ $json.LeadSource }}\n\nHistorical Intelligence:\nTotal Historical Deals: {{ $json.totalHistoricalDeals }}\nWon Historical Deals: {{ $json.wonHistoricalDeals }}\nHistorical Win Rate: {{ $json.historicalWinRate }}\nAverage Historical Amount: {{ $json.avgHistoricalAmount }}\nAmount Deviation: {{ $json.amountDeviation }}\n\nFeature Engineered Signals:\nDays Open: {{ $json.daysOpen }}\nDeal Velocity: {{ $json.dealVelocity }}\nActivity Score: {{ $json.activityScore }}\nEngagement Level: {{ $json.engagementLevel }}\nStage Weight: {{ $json.stageWeight }}\nTime Pressure (days remaining): {{ $json.timePressure }}\n\nRisk Assessment:\nRisk Score: {{ $json.riskScore }}\nRisk Label: {{ $json.riskLabel }}\n\nInstructions:\n- Prioritize engagement level and activity score to assess deal momentum\n- Use historical win rate and amount deviation to benchmark deal quality\n- Use days open and time pressure to adjust realism of timeline\n- Use stage and probability to estimate conversion likelihood\n\nGenerate the prediction in valid JSON only.",
"options": {
"systemMessage": "You are an enterprise-grade sales intelligence AI specializing in B2B opportunity forecasting.\n\nYour role is to predict realistic deal closure timelines and win probabilities using a combination of:\n- current opportunity stage and probability\n- historical performance benchmarks\n- feature-engineered signals (engagement, velocity, time pressure)\n- calculated risk score\n\nDecision Guidelines:\n- High engagement and activity increase win probability\n- Low activity or low engagement significantly reduces confidence\n- Large negative amount deviation indicates higher risk\n- Older deals (high daysOpen) tend to have lower success probability\n- High time pressure (few days left) requires realistic or extended timelines\n- Strong historical win rate should positively influence prediction\n\nAlways respond ONLY in valid JSON.\n\nDo not include markdown, explanations or extra text.\n\nUse this exact response schema:\n\n{\n \"predicted_close_date\": \"YYYY-MM-DD\",\n \"predicted_win_probability\": number,\n \"confidence_score\": number,\n \"reasoning\": \"short explanation\",\n \"next_best_action\": \"recommended sales action\"\n}\n\nRules:\n- confidence_score must be between 0 and 100\n- predicted_win_probability must be between 0 and 100\n- predicted_close_date must reflect realistic deal progression\n- reasoning must clearly reference risk, engagement and historical trends\n- next_best_action must be actionable and aligned with deal stage"
},
"promptType": "define"
},
"executeOnce": false,
"typeVersion": 3.1
},
{
"id": "cde3525a-1560-4ed9-ba32-12617ae2acc2",
"name": "Parse AI Output",
"type": "n8n-nodes-base.code",
"position": [
368,
-960
],
"parameters": {
"jsCode": "let rawOutput = $input.first().json.output;\n// Strip markdown formatting if the LLM adds it\nrawOutput = rawOutput.replace(/```json\\n?/g, '').replace(/```/g, '').trim();\n\nlet parsed;\ntry {\n parsed = JSON.parse(rawOutput);\n} catch (error) {\n throw new Error(`Invalid JSON returned from AI: ${rawOutput}`);\n}\n\nreturn [{ json: parsed }];"
},
"typeVersion": 2
},
{
"id": "161857c4-0c4a-4334-999a-aac22fd0b5d6",
"name": "Process Opportunities",
"type": "n8n-nodes-base.splitInBatches",
"position": [
-1040,
-672
],
"parameters": {
"options": {}
},
"typeVersion": 3
},
{
"id": "168d4921-36c5-4018-a36d-b0d0e035faa0",
"name": "Insights",
"type": "@n8n/n8n-nodes-langchain.lmChatGroq",
"position": [
16,
-752
],
"parameters": {
"model": "llama-3.3-70b-versatile",
"options": {}
},
"credentials": {
"groqApi": {
"id": "ZYz2lsdEbgg9Owa1",
"name": "Groq account 2"
}
},
"typeVersion": 1
},
{
"id": "cb63203a-1655-4d54-a1ab-343961255177",
"name": "check confidence score",
"type": "n8n-nodes-base.if",
"position": [
592,
-960
],
"parameters": {
"options": {},
"conditions": {
"options": {
"version": 3,
"leftValue": "",
"caseSensitive": true,
"typeValidation": "strict"
},
"combinator": "and",
"conditions": [
{
"id": "5bd2c425-fc48-4235-965d-ae61248f9350",
"operator": {
"type": "number",
"operation": "gte"
},
"leftValue": "={{ $json.confidence_score }}",
"rightValue": 70
}
]
}
},
"typeVersion": 2.3
},
{
"id": "8c09cb03-c5ac-4339-91dc-523124946294",
"name": "alert for Manual review",
"type": "n8n-nodes-base.gmail",
"position": [
816,
-864
],
"webhookId": "a397efc9-f93b-41bb-ba77-f1b4bf53d62c",
"parameters": {
"message": "=AI prediction confidence below threshold.\n\nOpportunity requires sales manager review.\n\nPredicted Close Date: {{ $json.predicted_close_date }}\nConfidence: {{ $json.confidence_score }}\nRecommended Action: {{ $json.next_best_action }}",
"options": {
"appendAttribution": false
},
"subject": "Manual review alert",
"emailType": "text"
},
"credentials": {
"gmailOAuth2": {
"id": "fAXxeaXx4aurF9lx",
"name": "Gmail account"
}
},
"typeVersion": 2.2
},
{
"id": "ea977f2f-3b00-4fb1-bdcc-b704aa05a00b",
"name": "Sticky Note",
"type": "n8n-nodes-base.stickyNote",
"position": [
-2816,
-1200
],
"parameters": {
"width": 832,
"height": 784,
"content": "\n# AI-Based Deal Timeline Predictor\n\nThis workflow provides an **end-to-end automation pipeline** that continuously evaluates **active Salesforce opportunities** to optimize your sales forecasting. It intelligently engineers **custom momentum features** and leverages a powerful **LLM agent** to accurately predict realistic **close dates** and **win probabilities**. By dynamically routing actions based on **AI confidence scores**, it ensures that routine updates are handled instantly while flagging high-risk deals for **human-in-the-loop review**.\n\n\n## How it Works:\n1. Runs on a rolling schedule, fetching recently modified open deals alongside historical closed/won data for benchmarking.\n2. Iterates through each deal using a rate-controlled batching queue.\n3. Pulls granular task/activity data for each specific deal to assess engagement.\n4. Calculates an intelligent **Risk Score** and **Velocity** metric using custom JS before sending the payload to a Groq Llama-3 LangChain agent.\n5. Evaluates the AI's **Confidence Score**:\n - **High Confidence:** Auto-updates Salesforce Close Date.\n - **Low Confidence:** Alerts management via Gmail for manual review.\n - *Both paths log comprehensive audit trails to Google Sheets.*\n\n## Setup Steps:\n* **Salesforce Configuration:** Authenticate your account to enable querying of open opportunities, historical deals and related task activities.\n* **LLM Integration:** Provide your Groq API key to power the Llama-3 LangChain intelligence engine.\n* **Email Alerts:** Connect your Gmail account to properly route low-confidence predictions to management.\n* **Audit Logging:** Link a target Google Sheet to maintain a comprehensive record of all automated updates and manual review requests.\n* **Trigger Scheduling:** Set your desired interval on the schedule trigger to dictate how often the batch process runs.\n\n"
},
"typeVersion": 1
},
{
"id": "9dbb5905-0903-48bc-9ce7-dbcbb9c140e2",
"name": "Sticky Note1",
"type": "n8n-nodes-base.stickyNote",
"position": [
-1840,
-1056
],
"parameters": {
"color": 7,
"width": 688,
"height": 752,
"content": "### Data Ingestion & Initialization\n\nThis phase triggers the workflow on a set schedule and establishes the lookback time window for recent updates. It queries Salesforce to simultaneously retrieve recently modified active opportunities and a static batch of historical closed-won deals. Fetching this data upfront ensures the AI has both the current deal context and the historical baselines required for accurate forecasting before entering the processing loop."
},
"typeVersion": 1
},
{
"id": "6cc0b5e4-d15d-499f-aad1-34a57b68a9ff",
"name": "Sticky Note2",
"type": "n8n-nodes-base.stickyNote",
"position": [
-1120,
-1152
],
"parameters": {
"color": 7,
"width": 848,
"height": 816,
"content": "### Opportunity Enrichment & Validation\n\nThis section isolates each deal using a **rate-controlled batching queue** to prevent API limit exhaustion. For each deal, it fetches granular **Salesforce task activities** to accurately measure recent engagement. Finally, it uses an IF node to **filter out invalid or closed deals**, ensuring that only active, high-quality opportunities are allowed to consume LLM tokens."
},
"typeVersion": 1
},
{
"id": "78d13f8e-5f9b-4cc5-b501-281196ec20e7",
"name": "Sticky Note3",
"type": "n8n-nodes-base.stickyNote",
"position": [
-256,
-1136
],
"parameters": {
"color": 7,
"width": 768,
"height": 512,
"content": "### AI Intelligence & Feature Engineering\n\nFirst, a custom JavaScript node calculates **Deal Velocity**, **Days Open** and a dynamic **Risk Score** based on stage stagnation. These engineered signals are then processed by a **Groq-powered LangChain Agent**, which acts as a sales strategist to predict the **close date and win probability**. The raw LLM response is strictly parsed into a structured **JSON object** for reliable downstream routing."
},
"typeVersion": 1
},
{
"id": "a4c36447-7dbe-4e76-9d99-e2a70043414c",
"name": "Sticky Note4",
"type": "n8n-nodes-base.stickyNote",
"position": [
544,
-1264
],
"parameters": {
"color": 7,
"width": 672,
"height": 960,
"content": "## 4. Conditional Execution & Logging\n\nThis routing logic dictates action based on the AI's predicted **Confidence Score** using a strict threshold of 70. High-confidence predictions automatically **update the close date in Salesforce**, while low-confidence predictions trigger a **Gmail alert for manual manager review**. Both distinct outcomes maintain a comprehensive audit trail by logging success or pending statuses to **Google Sheets**."
},
"typeVersion": 1
},
{
"id": "8eeba1bb-780b-4de4-8b22-a3f15810e617",
"name": "Run Schedule",
"type": "n8n-nodes-base.scheduleTrigger",
"position": [
-1792,
-768
],
"parameters": {
"rule": {
"interval": [
{}
]
}
},
"typeVersion": 1.3
},
{
"id": "80443cf9-00d8-4fbf-a4ea-539dfa722d7a",
"name": "Set Lookback Timeframe",
"type": "n8n-nodes-base.set",
"position": [
-1616,
-768
],
"parameters": {
"options": {},
"assignments": {
"assignments": [
{
"id": "ef71ac17-4837-4a63-ad26-f41fa320670d",
"name": "lastruntime",
"type": "string",
"value": "={{new Date(Date.now() - 5 * 60 * 1000).toISOString()}}"
}
]
}
},
"executeOnce": true,
"typeVersion": 3.4
},
{
"id": "d56ac1b6-ed5d-4a00-853e-28372ed14158",
"name": "Fetch Historical Won Deals",
"type": "n8n-nodes-base.salesforce",
"position": [
-1376,
-864
],
"parameters": {
"query": "SELECT Id, Name, StageName, Amount, Probability, CloseDate, IsWon, IsClosed, LeadSource, CreatedDate\nFROM Opportunity\nWHERE IsClosed = true\nORDER BY CloseDate DESC\nLIMIT 10",
"resource": "search"
},
"credentials": {
"salesforceOAuth2Api": {
"id": "4cOnMMVTeqyQiqUU",
"name": "Salesforce account"
}
},
"executeOnce": true,
"typeVersion": 1
},
{
"id": "3d134bf8-b1fb-4209-ac36-a1f143b0b95f",
"name": "Fetch Recent Active Deals",
"type": "n8n-nodes-base.salesforce",
"position": [
-1376,
-672
],
"parameters": {
"query": "=SELECT Id, Name, StageName, Amount, Probability, CloseDate, LastModifiedDate\nFROM Opportunity\nWHERE \n LastModifiedDate > {{ $json.lastruntime }}\n AND IsClosed = false\n AND Amount > 0\nORDER BY LastModifiedDate DESC\nLIMIT 20",
"resource": "search"
},
"credentials": {
"salesforceOAuth2Api": {
"id": "4cOnMMVTeqyQiqUU",
"name": "Salesforce account"
}
},
"typeVersion": 1
},
{
"id": "34b3a0f8-0fd6-407a-8ad5-c13ebd14b01d",
"name": "Fetch Deal Details",
"type": "n8n-nodes-base.salesforce",
"position": [
-896,
-960
],
"parameters": {
"resource": "opportunity",
"operation": "get",
"opportunityId": "={{ $json.Id }}"
},
"credentials": {
"salesforceOAuth2Api": {
"id": "4cOnMMVTeqyQiqUU",
"name": "Salesforce account"
}
},
"typeVersion": 1
},
{
"id": "cdb0595f-a3b3-490e-98ea-1bc1ccd743d3",
"name": "Deal Task History",
"type": "n8n-nodes-base.salesforce",
"position": [
-688,
-960
],
"parameters": {
"query": "=SELECT ActivityDate, Subject, Status\nFROM Task\nWHERE WhatId = '{{ $json.Id }}'\nORDER BY ActivityDate DESC\nLIMIT 20",
"resource": "search"
},
"credentials": {
"salesforceOAuth2Api": {
"id": "4cOnMMVTeqyQiqUU",
"name": "Salesforce account"
}
},
"typeVersion": 1,
"alwaysOutputData": true
},
{
"id": "9e4e51d7-6779-4e3c-ad75-dba23181c511",
"name": "Is Deal Valid & Active?",
"type": "n8n-nodes-base.if",
"position": [
-480,
-960
],
"parameters": {
"options": {},
"conditions": {
"options": {
"version": 3,
"leftValue": "",
"caseSensitive": true,
"typeValidation": "loose"
},
"combinator": "and",
"conditions": [
{
"id": "a92fed93-bea0-47cc-9b85-fd46b46887e3",
"operator": {
"type": "number",
"operation": "gt"
},
"leftValue": "={{ $('Fetch Deal Details').item.json.Amount }}",
"rightValue": 0
},
{
"id": "dc750fbc-f2b2-4a8e-b7c3-3c1a3371ad6b",
"operator": {
"type": "string",
"operation": "equals"
},
"leftValue": "={{ $('Fetch Deal Details').item.json.IsClosed }}",
"rightValue": "false"
},
{
"id": "35e30051-70b9-4744-8b7a-532f08b06359",
"operator": {
"type": "number",
"operation": "gt"
},
"leftValue": "={{ $('Fetch Deal Details').item.json.Probability }}",
"rightValue": 0
}
]
},
"looseTypeValidation": true
},
"typeVersion": 2.3
},
{
"id": "643493d0-5f35-47f9-aba3-33e02ebc897d",
"name": "Calculate Deal Risk & Velocity",
"type": "n8n-nodes-base.code",
"position": [
-208,
-960
],
"parameters": {
"jsCode": "// Current deal\nconst currentDeal = $(\"Fetch Deal Details\").first().json;\n\n// Historical deals\nconst historicalDeals = $(\"Fetch Historical Won Deals\").all().map(item => item.json);\n\n// Activities\nconst activities = $(\"Deal Task History\").all().map(item => item.json);\n\n// --------------------\n// Feature Engineering\n// --------------------\n\n// Days open \nconst createdDate = new Date(currentDeal.CreatedDate);\nconst today = new Date();\n\nconst daysOpen = Math.max(\n 1,\n Math.ceil((today - createdDate) / (1000 * 60 * 60 * 24))\n);\n\n// Deal velocity\nconst dealVelocity = (currentDeal.Amount || 0) / daysOpen;\n\n// Activity score\nconst activityScore = activities.length;\n\n// Engagement level\nlet engagementLevel = \"Low\";\nif (activityScore > 10) engagementLevel = \"High\";\nelse if (activityScore > 5) engagementLevel = \"Medium\";\n\n// Stage weight (ML-style encoding)\nconst stageWeights = {\n \"Prospecting\": 1,\n \"Qualification\": 2,\n \"Proposal/Price Quote\": 3,\n \"Negotiation/Review\": 4,\n \"Closed Won\": 5\n};\n\nconst stageWeight = stageWeights[currentDeal.StageName] || 1;\n\n// Time pressure (days left)\nlet timePressure = 0;\nif (currentDeal.CloseDate) {\n const closeDate = new Date(currentDeal.CloseDate);\n timePressure = Math.floor((closeDate - today) / (1000 * 60 * 60 * 24));\n}\n\n// --------------------\n// Historical calculations\n// --------------------\nconst totalDeals = historicalDeals.length;\n\nconst wonDeals = historicalDeals.filter(d => d.IsWon === true).length;\n\nconst totalAmount = historicalDeals.reduce((sum, d) => {\n return sum + (d.Amount || 0);\n}, 0);\n\nconst avgHistoricalAmount =\n totalDeals > 0 ? totalAmount / totalDeals : 0;\n\nconst historicalWinRate =\n totalDeals > 0 ? (wonDeals / totalDeals) * 100 : 0;\n\nconst amountDeviation =\n (currentDeal.Amount || 0) - avgHistoricalAmount;\n\n// --------------------\n// Risk scoring (IMPROVED)\n// --------------------\nlet riskScore = 0;\n\n// Probability-based risk\nif ((currentDeal.Probability || 0) < 50) riskScore += 30;\nelse if ((currentDeal.Probability || 0) < 70) riskScore += 15;\n\n// Amount deviation risk\nif (amountDeviation < -50000) riskScore += 20;\n\n// Stage risk\nif (currentDeal.StageName === \"Prospecting\") riskScore += 25;\nif (currentDeal.StageName === \"Qualification\") riskScore += 15;\nif (currentDeal.StageName === \"Negotiation/Review\") riskScore += 10;\n\n// Historical win-rate risk\nif (historicalWinRate < 70) riskScore += 20;\n\n// Activity-based risk \nif (activityScore === 0) riskScore += 30;\nelse if (activityScore < 3) riskScore += 20;\nelse if (activityScore < 6) riskScore += 10;\n\n// Time pressure risk\nif (timePressure < 5) riskScore += 10;\n\n// Deal aging risk (\nif (daysOpen > 30) riskScore += 10;\n\n// Cap at 100\nriskScore = Math.min(riskScore, 100);\n\n// Risk label\nlet riskLabel = \"Low\";\nif (riskScore >= 70) riskLabel = \"High\";\nelse if (riskScore >= 40) riskLabel = \"Medium\";\n\n// --------------------\n// Final output\n// --------------------\nreturn [\n {\n json: {\n ...currentDeal,\n\n // Historical\n totalHistoricalDeals: totalDeals,\n wonHistoricalDeals: wonDeals,\n avgHistoricalAmount,\n historicalWinRate,\n amountDeviation,\n\n // Feature Engineering\n daysOpen,\n dealVelocity,\n activityScore,\n engagementLevel,\n stageWeight,\n timePressure,\n\n // Risk\n riskScore,\n riskLabel\n }\n }\n];"
},
"executeOnce": true,
"typeVersion": 2
},
{
"id": "72d6c973-506c-49e7-83ab-96d3cc678704",
"name": "Update Close Date",
"type": "n8n-nodes-base.salesforce",
"position": [
816,
-1056
],
"parameters": {
"resource": "opportunity",
"operation": "update",
"updateFields": {
"closeDate": "={{ $json.predicted_close_date }}"
},
"opportunityId": "={{ $('Fetch Deal Details').item.json.Id }}"
},
"credentials": {
"salesforceOAuth2Api": {
"id": "4cOnMMVTeqyQiqUU",
"name": "Salesforce account"
}
},
"typeVersion": 1
},
{
"id": "d1a3ac62-9dd6-4053-96b6-60ca176e2048",
"name": "Log Auto-Update Success",
"type": "n8n-nodes-base.googleSheets",
"position": [
1040,
-720
],
"parameters": {
"columns": {
"value": {
"status": "SUCCESS",
"reasoning": "={{ $(\"Parse AI Output\").first().json.reasoning }}",
"timestamp": "={{ $now }}",
"risk_label": "={{ $(\"Calculate Deal Risk & Velocity\").first().json.riskLabel }}",
"risk_score": "={{ $(\"Calculate Deal Risk & Velocity\").first().json.riskScore }}",
"stage_name": "={{ $(\"Fetch Deal Details\").first().json.StageName }}",
"action_taken": "AUTO_UPDATED",
"current_amount": "={{ $(\"Fetch Deal Details\").first().json.Amount }}",
"opportunity_id": "={{ $(\"Fetch Deal Details\").first().json.Id }}",
"confidence_score": "={{ $(\"Parse AI Output\").first().json.confidence_score }}",
"next_best_action": "={{ $(\"Parse AI Output\").first().json.next_best_action }}",
"opportunity_name": "={{ $(\"Fetch Deal Details\").first().json.Name }}",
"predicted_close_date": "={{ $(\"Parse AI Output\").first().json.predicted_close_date }}",
"predicted_win_probability": "={{ $(\"Parse AI Output\").first().json.predicted_win_probability }}"
},
"schema": [
{
"id": "timestamp",
"type": "string",
"display": true,
"required": false,
"displayName": "timestamp",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "opportunity_id",
"type": "string",
"display": true,
"required": false,
"displayName": "opportunity_id",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "opportunity_name",
"type": "string",
"display": true,
"required": false,
"displayName": "opportunity_name",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "stage_name",
"type": "string",
"display": true,
"removed": false,
"required": false,
"displayName": "stage_name",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "current_amount",
"type": "string",
"display": true,
"removed": false,
"required": false,
"displayName": "current_amount",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "risk_score",
"type": "string",
"display": true,
"required": false,
"displayName": "risk_score",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "risk_label",
"type": "string",
"display": true,
"required": false,
"displayName": "risk_label",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "predicted_close_date",
"type": "string",
"display": true,
"required": false,
"displayName": "predicted_close_date",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "predicted_win_probability",
"type": "string",
"display": true,
"required": false,
"displayName": "predicted_win_probability",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "confidence_score",
"type": "string",
"display": true,
"required": false,
"displayName": "confidence_score",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "action_taken",
"type": "string",
"display": true,
"removed": false,
"required": false,
"displayName": "action_taken",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "status",
"type": "string",
"display": true,
"required": false,
"displayName": "status",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "reasoning",
"type": "string",
"display": true,
"removed": false,
"required": false,
"displayName": "reasoning",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "next_best_action",
"type": "string",
"display": true,
"removed": false,
"required": false,
"displayName": "next_best_action",
"defaultMatch": false,
"canBeUsedToMatch": true
}
],
"mappingMode": "defineBelow",
"matchingColumns": [],
"attemptToConvertTypes": false,
"convertFieldsToString": false
},
"options": {},
"operation": "append",
"sheetName": {
"__rl": true,
"mode": "list",
"value": "gid=0",
"cachedResultUrl": "https://docs.google.com/spreadsheets/d/1xZ3AqllVeBEXx9N2LF6Sp6l2iIUS6-2TwQ2MINPE44c/edit#gid=0",
"cachedResultName": "Sheet1"
},
"documentId": {
"__rl": true,
"mode": "list",
"value": "1xZ3AqllVeBEXx9N2LF6Sp6l2iIUS6-2TwQ2MINPE44c",
"cachedResultUrl": "https://docs.google.com/spreadsheets/d/1xZ3AqllVeBEXx9N2LF6Sp6l2iIUS6-2TwQ2MINPE44c/edit?usp=drivesdk",
"cachedResultName": "update prediction crm"
}
},
"credentials": {
"googleSheetsOAuth2Api": {
"id": "m0H33sXFyEfCABEN",
"name": "Google Sheets account"
}
},
"typeVersion": 4.7
},
{
"id": "0af294ed-0993-4baf-9b74-afa12d141c85",
"name": "Log Pending Review",
"type": "n8n-nodes-base.googleSheets",
"position": [
1040,
-544
],
"parameters": {
"columns": {
"value": {
"status": "PENDING_MANAGER_REVIEW",
"reasoning": "={{ $(\"Parse AI Output\").first().json.reasoning }}",
"timestamp": "={{ $now }}",
"risk_label": "={{ $(\"Calculate Deal Risk & Velocity\").first().json.riskLabel }}",
"risk_score": "={{ $(\"Calculate Deal Risk & Velocity\").first().json.riskScore }}",
"stage_name": "={{ $(\"Fetch Deal Details\").first().json.StageName }}",
"action_taken": "MANUAL_REVIEW",
"current_amount": "={{ $(\"Fetch Deal Details\").first().json.Amount }}",
"opportunity_id": "={{ $(\"Fetch Deal Details\").first().json.Id }}",
"confidence_score": "={{ $(\"Parse AI Output\").first().json.confidence_score }}",
"next_best_action": "={{ $(\"Parse AI Output\").first().json.next_best_action }}",
"opportunity_name": "={{ $(\"Fetch Deal Details\").first().json.Name }}",
"predicted_close_date": "={{ $(\"Parse AI Output\").first().json.predicted_close_date }}",
"predicted_win_probability": "={{ $(\"Parse AI Output\").first().json.predicted_win_probability }}"
},
"schema": [
{
"id": "timestamp",
"type": "string",
"display": true,
"required": false,
"displayName": "timestamp",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "opportunity_id",
"type": "string",
"display": true,
"required": false,
"displayName": "opportunity_id",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "opportunity_name",
"type": "string",
"display": true,
"required": false,
"displayName": "opportunity_name",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "stage_name",
"type": "string",
"display": true,
"removed": false,
"required": false,
"displayName": "stage_name",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "current_amount",
"type": "string",
"display": true,
"removed": false,
"required": false,
"displayName": "current_amount",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "risk_score",
"type": "string",
"display": true,
"required": false,
"displayName": "risk_score",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "risk_label",
"type": "string",
"display": true,
"required": false,
"displayName": "risk_label",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "predicted_close_date",
"type": "string",
"display": true,
"required": false,
"displayName": "predicted_close_date",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "predicted_win_probability",
"type": "string",
"display": true,
"required": false,
"displayName": "predicted_win_probability",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "confidence_score",
"type": "string",
"display": true,
"required": false,
"displayName": "confidence_score",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "action_taken",
"type": "string",
"display": true,
"removed": false,
"required": false,
"displayName": "action_taken",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "status",
"type": "string",
"display": true,
"required": false,
"displayName": "status",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "reasoning",
"type": "string",
"display": true,
"removed": false,
"required": false,
"displayName": "reasoning",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "next_best_action",
"type": "string",
"display": true,
"removed": false,
"required": false,
"displayName": "next_best_action",
"defaultMatch": false,
"canBeUsedToMatch": true
}
],
"mappingMode": "defineBelow",
"matchingColumns": [],
"attemptToConvertTypes": false,
"convertFieldsToString": false
},
"options": {},
"operation": "append",
"sheetName": {
"__rl": true,
"mode": "list",
"value": "gid=0",
"cachedResultUrl": "https://docs.google.com/spreadsheets/d/1xZ3AqllVeBEXx9N2LF6Sp6l2iIUS6-2TwQ2MINPE44c/edit#gid=0",
"cachedResultName": "Sheet1"
},
"documentId": {
"__rl": true,
"mode": "list",
"value": "1xZ3AqllVeBEXx9N2LF6Sp6l2iIUS6-2TwQ2MINPE44c",
"cachedResultUrl": "https://docs.google.com/spreadsheets/d/1xZ3AqllVeBEXx9N2LF6Sp6l2iIUS6-2TwQ2MINPE44c/edit?usp=drivesdk",
"cachedResultName": "update prediction crm"
}
},
"credentials": {
"googleSheetsOAuth2Api": {
"id": "m0H33sXFyEfCABEN",
"name": "Google Sheets account"
}
},
"typeVersion": 4.7
},
{
"parameters": {
"operation": "verify",
"email": "={{ $json.email || $json.Email }}",
"additionalOptions": {}
},
"type": "n8n-nodes-billionverify.billionVerify",
"typeVersion": 1,
"position": [
456,
-864
],
"name": "Verify Email (BillionVerify)",
"credentials": {
"billionVerifyApi": {
"id": "",
"name": "BillionVerify account"
}
}
},
{
"parameters": {
"conditions": {
"options": {
"caseSensitive": true,
"leftValue": "",
"typeValidation": "loose"
},
"combinator": "and",
"conditions": [
{
"id": "is-deliverable",
"leftValue": "={{ $json.is_deliverable }}",
"rightValue": "",
"operator": {
"type": "boolean",
"operation": "true",
"singleValue": true
}
}
]
}
},
"type": "n8n-nodes-base.if",
"typeVersion": 2,
"position": [
636,
-864
],
"name": "IF deliverable"
}
],
"connections": {
"Insights": {
"ai_languageModel": [
[
{
"node": "AI Deal Timeline Predictor",
"type": "ai_languageModel",
"index": 0
}
]
]
},
"Run Schedule": {
"main": [
[
{
"node": "Set Lookback Timeframe",
"type": "main",
"index": 0
}
]
]
},
"Parse AI Output": {
"main": [
[
{
"node": "check confidence score",
"type": "main",
"index": 0
}
]
]
},
"Deal Task History": {
"main": [
[
{
"node": "Is Deal Valid & Active?",
"type": "main",
"index": 0
}
]
]
},
"Update Close Date": {
"main": [
[
{
"node": "Log Auto-Update Success",
"type": "main",
"index": 0
}
]
]
},
"Fetch Deal Details": {
"main": [
[
{
"node": "Deal Task History",
"type": "main",
"index": 0
}
]
]
},
"Log Pending Review": {
"main": [
[
{
"node": "Process Opportunities",
"type": "main",
"index": 0
}
]
]
},
"Process Opportunities": {
"main": [
[],
[
{
"node": "Fetch Deal Details",
"type": "main",
"index": 0
}
]
]
},
"Set Lookback Timeframe": {
"main": [
[
{
"node": "Fetch Historical Won Deals",
"type": "main",
"index": 0
},
{
"node": "Fetch Recent Active Deals",
"type": "main",
"index": 0
}
]
]
},
"check confidence score": {
"main": [
[
{
"node": "Update Close Date",
"type": "main",
"index": 0
}
],
[
{
"node": "Verify Email (BillionVerify)",
"type": "main",
"index": 0
}
]
]
},
"Is Deal Valid & Active?": {
"main": [
[
{
"node": "Calculate Deal Risk & Velocity",
"type": "main",
"index": 0
}
]
]
},
"Log Auto-Update Success": {
"main": [
[
{
"node": "Process Opportunities",
"type": "main",
"index": 0
}
]
]
},
"alert for Manual review": {
"main": [
[
{
"node": "Log Pending Review",
"type": "main",
"index": 0
}
]
]
},
"Fetch Recent Active Deals": {
"main": [
[
{
"node": "Process Opportunities",
"type": "main",
"index": 0
}
]
]
},
"AI Deal Timeline Predictor": {
"main": [
[
{
"node": "Parse AI Output",
"type": "main",
"index": 0
}
]
]
},
"Fetch Historical Won Deals": {
"main": [
[]
]
},
"Calculate Deal Risk & Velocity": {
"main": [
[
{
"node": "AI Deal Timeline Predictor",
"type": "main",
"index": 0
}
]
]
},
"Verify Email (BillionVerify)": {
"main": [
[
{
"node": "IF deliverable",
"type": "main",
"index": 0
}
]
]
},
"IF deliverable": {
"main": [
[
{
"node": "alert for Manual review",
"type": "main",
"index": 0
}
],
[]
]
}
},
"settings": {
"binaryMode": "separate",
"executionOrder": "v1"
}
}When to use this
- Cleaning a list before a Close send or sync.
- Protecting Close deliverability and sender reputation.
- Keeping bounce rates low so your sending is never throttled.
FAQ
Why verify before sending in Close?
Verifying first keeps your bounce rate low, which protects your sender reputation and your results.
How do I import this workflow?
Download the JSON, then in n8n go to Workflows β Import from File (or paste it). Install the BillionVerify community node and add your API key credential.
What happens to risky or catch-all addresses?
They are routed to the false branch and excluded from the send. You decide whether to retry, review, or drop them.
Add verification to your workflow
Create a free account, grab your API key, and stop bounces before they happen.
Get started free