Aggregate email verification with BillionVerify
Aggregate is a developer-focused data aggregation tool that collects and consolidates information from multiple sources into unified datasets. When email addresses are part of that aggregated data, BillionVerify adds a validation layer so only clean, deliverable contacts make it into your final outputs.
Why verify before the send
Aggregated datasets almost always contain email addresses gathered from varied sources with inconsistent quality controls. Running verification through BillionVerify before these datasets are consumed by downstream applications removes invalid, duplicate-risk, and disposable addresses, preventing bad data from silently degrading the quality of every system that relies on the aggregated output.
Ready-to-use n8n workflow
Import this workflow into n8n — it verifies every address with BillionVerify before Aggregate sends, so only deliverable contacts are emailed. Install the BillionVerify community node first, then add your API key. Adapted from this n8n template
{
"name": "Aggregate & update documentation from Slack, Teams & GitHub with Claude Sonnet 4.5 + BillionVerify",
"nodes": [
{
"id": "a3ea1f47-42f9-4151-a312-57ccb9ce9169",
"name": "Schedule Trigger",
"type": "n8n-nodes-base.scheduleTrigger",
"position": [
-768,
160
],
"parameters": {
"rule": {
"interval": [
{
"field": "hours"
}
]
}
},
"typeVersion": 1.3
},
{
"id": "2903deeb-4ce3-470d-9e53-24ca14c0fa54",
"name": "Workflow Configuration",
"type": "n8n-nodes-base.set",
"position": [
-512,
160
],
"parameters": {
"options": {},
"assignments": {
"assignments": [
{
"id": "id-1",
"name": "slackChannelId",
"type": "string",
"value": "<__PLACEHOLDER_VALUE__Slack channel ID to monitor__>"
},
{
"id": "id-2",
"name": "teamsChannelId",
"type": "string",
"value": "<__PLACEHOLDER_VALUE__Teams channel ID to monitor__>"
},
{
"id": "id-3",
"name": "gmailQuery",
"type": "string",
"value": "<__PLACEHOLDER_VALUE__Gmail search query__>"
},
{
"id": "id-4",
"name": "githubRepo",
"type": "string",
"value": "<__PLACEHOLDER_VALUE__GitHub repository name__>"
},
{
"id": "id-5",
"name": "confluenceSpaceKey",
"type": "string",
"value": "<__PLACEHOLDER_VALUE__Confluence space key__>"
},
{
"id": "id-6",
"name": "notionDatabaseId",
"type": "string",
"value": "<__PLACEHOLDER_VALUE__Notion database ID__>"
},
{
"id": "id-7",
"name": "lookbackHours",
"type": "number",
"value": 1
}
]
},
"includeOtherFields": true
},
"typeVersion": 3.4
},
{
"id": "bdc0bb18-37b1-4754-9174-7f0a4e59678f",
"name": "Get Slack Messages",
"type": "n8n-nodes-base.slack",
"position": [
-288,
16
],
"webhookId": "211149c9-0444-48ce-ab76-b328fbdf2168",
"parameters": {
"limit": 100,
"options": {},
"operation": "search",
"authentication": "oAuth2"
},
"credentials": {
"slackOAuth2Api": {
"id": "credential-id",
"name": "slackOAuth2Api Credential"
}
},
"typeVersion": 2.4
},
{
"id": "ec251066-a4b9-4b10-854f-0f17da1e571d",
"name": "Get Teams Messages",
"type": "n8n-nodes-base.microsoftTeams",
"position": [
-288,
160
],
"webhookId": "57d50607-f032-494a-a441-9aa83d84479d",
"parameters": {
"teamId": {
"__rl": true,
"mode": "id",
"value": "<__PLACEHOLDER_VALUE__Microsoft Teams team ID__>"
},
"resource": "channelMessage",
"channelId": {
"__rl": true,
"mode": "id",
"value": "={{ $('Workflow Configuration').first().json.teamsChannelId }}"
},
"operation": "getAll"
},
"typeVersion": 2
},
{
"id": "b2cd5bf2-c314-467f-9c00-cc997ef76fc4",
"name": "Get Gmail Messages",
"type": "n8n-nodes-base.gmail",
"position": [
-288,
336
],
"webhookId": "594215b2-1319-452e-a9ad-950c97153e43",
"parameters": {
"limit": 100,
"filters": {
"q": "={{ $('Workflow Configuration').first().json.gmailQuery }}"
},
"operation": "getAll"
},
"credentials": {
"gmailOAuth2": {
"id": "credential-id",
"name": "gmailOAuth2 Credential"
}
},
"typeVersion": 2.2
},
{
"id": "3cff8e0c-b1f4-4bae-8f77-e530fd032a11",
"name": "Get GitHub Activity",
"type": "n8n-nodes-base.github",
"position": [
-288,
512
],
"webhookId": "80b36b12-0882-45db-9295-95022a69a197",
"parameters": {
"owner": {
"__rl": true,
"mode": "name",
"value": "<__PLACEHOLDER_VALUE__GitHub repository owner__>"
},
"operation": "get",
"repository": {
"__rl": true,
"mode": "name",
"value": "={{ $('Workflow Configuration').first().json.githubRepo }}"
}
},
"typeVersion": 1.1
},
{
"id": "d07c2808-189c-444f-9676-3a6c701907bc",
"name": "Get Confluence Pages",
"type": "n8n-nodes-base.httpRequest",
"position": [
-288,
672
],
"parameters": {
"url": "<__PLACEHOLDER_VALUE__Confluence API URL for getting pages__>",
"options": {},
"authentication": "genericCredentialType",
"genericAuthType": "httpBasicAuth"
},
"typeVersion": 4.3
},
{
"id": "f26c578a-7c91-4e38-a7fe-5810e18b051f",
"name": "Get Notion Pages",
"type": "n8n-nodes-base.notion",
"position": [
-288,
848
],
"parameters": {
"options": {},
"resource": "databasePage",
"operation": "getAll",
"databaseId": {
"__rl": true,
"mode": "id",
"value": "={{ $('Workflow Configuration').first().json.notionDatabaseId }}"
}
},
"typeVersion": 2.2
},
{
"id": "91972d2b-91d4-48c8-bf16-77b477bdd873",
"name": "Merge All Sources",
"type": "n8n-nodes-base.merge",
"position": [
-64,
64
],
"parameters": {
"mode": "combine",
"options": {},
"combineBy": "combineAll"
},
"typeVersion": 3.2
},
{
"id": "8568cdb5-133c-4e8e-85ec-c4be311aa1b2",
"name": "AI Content Analyzer",
"type": "@n8n/n8n-nodes-langchain.agent",
"position": [
160,
64
],
"parameters": {
"text": "={{ $json.content || $json.text || $json.body || $json.message || JSON.stringify($json) }}",
"options": {
"systemMessage": "You are a knowledge management assistant that analyzes content from multiple platforms (Slack, Teams, email, GitHub, Confluence, Notion).\n\nYour task is to:\n1. Analyze the provided content to determine if it contains valuable information such as:\n - Important decisions and their rationale\n - Design documents or architectural choices\n - Bug reports and their resolutions\n - Requirements or feature specifications\n - Process changes or updates\n\n2. Extract and summarize the key information\n3. Categorize the content type (decision, design, bug, requirement, other)\n4. Identify which documents should be updated based on this information\n5. Assess the priority level (high, medium, low)\n\nReturn structured data with all findings."
},
"promptType": "define",
"hasOutputParser": true
},
"typeVersion": 3
},
{
"id": "88a0455c-ac55-4394-8ecb-ffb09991fd33",
"name": "Anthropic Chat Model",
"type": "@n8n/n8n-nodes-langchain.lmChatAnthropic",
"position": [
144,
288
],
"parameters": {
"model": {
"__rl": true,
"mode": "list",
"value": "claude-sonnet-4-5-20250929",
"cachedResultName": "Claude Sonnet 4.5"
},
"options": {}
},
"credentials": {
"anthropicApi": {
"id": "credential-id",
"name": "anthropicApi Credential"
}
},
"typeVersion": 1.3
},
{
"id": "d5931524-3b77-4953-877f-8f6812843b1b",
"name": "Structured Output Parser",
"type": "@n8n/n8n-nodes-langchain.outputParserStructured",
"position": [
304,
288
],
"parameters": {
"schemaType": "manual"
},
"typeVersion": 1.3
},
{
"id": "fc8b5160-b53c-4678-8bea-3d824f53a0f7",
"name": "Check If Valuable",
"type": "n8n-nodes-base.if",
"position": [
512,
64
],
"parameters": {
"options": {},
"conditions": {
"options": {
"leftValue": "",
"caseSensitive": true,
"typeValidation": "strict"
},
"combinator": "and",
"conditions": [
{
"id": "id-1",
"operator": {
"type": "boolean",
"operation": "true"
},
"leftValue": "={{ $json.isValuable }}"
}
]
}
},
"typeVersion": 2.3
},
{
"id": "6abb055b-1888-40ee-bcab-308098ec379f",
"name": "Update Notion Document",
"type": "n8n-nodes-base.notion",
"position": [
1088,
96
],
"parameters": {
"operation": "update"
},
"typeVersion": 2.2
},
{
"id": "f7890c4d-9d84-4d29-b5db-4c670f1d1f44",
"name": "Update Confluence Page",
"type": "n8n-nodes-base.httpRequest",
"position": [
1088,
352
],
"parameters": {
"url": "<__PLACEHOLDER_VALUE__Confluence API URL for updating page__>",
"method": "PUT",
"options": {},
"jsonBody": "={{ { version: { number: 2 }, title: $json.documentTitle, body: { storage: { value: $json.updateContent, representation: 'storage' } } } }}",
"sendBody": true,
"specifyBody": "json",
"authentication": "genericCredentialType",
"genericAuthType": "httpBasicAuth"
},
"typeVersion": 4.3
},
{
"id": "aac09e42-e72b-43e9-b455-5a9def72bde3",
"name": "Send Review Task to Slack",
"type": "n8n-nodes-base.slack",
"position": [
1280,
144
],
"webhookId": "f3fc62f0-2ec1-4c5e-955a-a574b08c259b",
"parameters": {
"text": "={{ '📝 Document Updated: ' + $json.documentTitle + '\n\nCategory: ' + $json.category + '\nPriority: ' + $json.priority + '\n\nSummary: ' + $json.summary + '\n\nPlease review the updated documentation.' }}",
"select": "channel",
"channelId": {
"__rl": true,
"mode": "list",
"value": "<__PLACEHOLDER_VALUE__Slack channel for review notifications__>"
},
"otherOptions": {},
"authentication": "oAuth2"
},
"credentials": {
"slackOAuth2Api": {
"id": "credential-id",
"name": "slackOAuth2Api Credential"
}
},
"typeVersion": 2.4
},
{
"id": "008628a0-9d33-4087-9e6c-830ca3ea79f3",
"name": "Format Update Data",
"type": "n8n-nodes-base.set",
"position": [
784,
128
],
"parameters": {
"options": {},
"assignments": {
"assignments": [
{
"id": "id-1",
"name": "documentTitle",
"type": "string",
"value": "={{ $json.category + ': ' + $json.summary.substring(0, 50) }}"
},
{
"id": "id-2",
"name": "updateContent",
"type": "string",
"value": "={{ $json.summary }}"
},
{
"id": "id-3",
"name": "metadata",
"type": "object",
"value": "={{ { category: $json.category, priority: $json.priority, source: $json.source, timestamp: new Date().toISOString() } }}"
}
]
},
"includeOtherFields": true
},
"typeVersion": 3.4
},
{
"id": "2851bc83-4252-47ad-a5b2-5b24f51ac516",
"name": "Sticky Note",
"type": "n8n-nodes-base.stickyNote",
"position": [
1040,
-336
],
"parameters": {
"color": 5,
"width": 512,
"height": 208,
"content": "## Customization\nAdd/remove source nodes, adjust Claude prompts for analysis type, modify output destinations \n\n## Benefits\nSaves 6+ hours weekly, eliminates missed content, AI-driven quality assurance "
},
"typeVersion": 1
},
{
"id": "a39eccce-3f94-4179-a547-257a86d21bd3",
"name": "Sticky Note2",
"type": "n8n-nodes-base.stickyNote",
"position": [
256,
-336
],
"parameters": {
"color": 3,
"width": 752,
"height": 208,
"content": "## Prerequisites\nSlack workspace, Teams account, Gmail access, GitHub repository, Confluence space, Anthropic API key, Notion workspace, n8n instance.\n\n## Use Cases\nContent review teams processing feedback, documentation teams aggregating updates, QA teams reviewing communications"
},
"typeVersion": 1
},
{
"id": "afd6d93f-7153-443a-a167-13abfc809ed4",
"name": "Sticky Note3",
"type": "n8n-nodes-base.stickyNote",
"position": [
-240,
-336
],
"parameters": {
"color": 4,
"width": 464,
"height": 192,
"content": "## Setup Steps\n-Connect credentials: Slack API, Teams, Gmail OAuth, GitHub PAT. \n-Confluence API, Anthropic API key, Notion Integration. \n-Configure monitored channels/repositories. \n-Set schedule frequency. \n-Map output destinations (Notion/Confluence). \n-Test merged output before enabling automation.\n"
},
"typeVersion": 1
},
{
"id": "86e2f135-aa21-4bf3-a686-fe4937072da2",
"name": "Sticky Note4",
"type": "n8n-nodes-base.stickyNote",
"position": [
-832,
-384
],
"parameters": {
"width": 576,
"height": 272,
"content": "## How It Works\nAggregates communication data from Slack, Microsoft Teams, Gmail, GitHub, and Confluence into a single, unified AI-powered analysis workflow designed for quality review and automated documentation updates. This solution is specifically aimed at teams managing distributed content and knowledge workflows across multiple platforms. It addresses the challenges of fragmented communication and isolated information silos that often prevent rapid content review and timely decision-making. The workflow begins with a scheduled trigger, followed by multi-source data collection, merging and normalizing inputs, Claude AI-powered analysis, validation and quality checks, formatting, and finally publishing updates to Notion and Confluence, accompanied by Slack notifications to ensure stakeholders are promptly informed."
},
"typeVersion": 1
},
{
"id": "606928b2-a31b-4464-b630-2e6c83080bf4",
"name": "Sticky Note6",
"type": "n8n-nodes-base.stickyNote",
"position": [
496,
-80
],
"parameters": {
"color": 7,
"width": 224,
"height": 1072,
"content": "## 4. Check Validity\n**What:** Validates AI output for completeness and accuracy \n**Why:** Prevents publishing incomplete "
},
"typeVersion": 1
},
{
"id": "0efa9987-75b8-4428-8c08-e8fae71102aa",
"name": "Sticky Note7",
"type": "n8n-nodes-base.stickyNote",
"position": [
80,
-80
],
"parameters": {
"color": 7,
"width": 400,
"height": 1088,
"content": "## 3. AI Content Analyzer (Claude)\n**What:** Processes merged content to extract key themes, insights\n**Why:** Surfaces patterns and intelligence humans would miss in high-volume data"
},
"typeVersion": 1
},
{
"id": "c73824f7-5d97-4301-b0f2-328262f99d39",
"name": "Sticky Note8",
"type": "n8n-nodes-base.stickyNote",
"position": [
736,
-80
],
"parameters": {
"color": 7,
"width": 832,
"height": 1088,
"content": "## 5. Format & Publish\n**What:** Structures data into publish-ready format \n**Why:** Ensures consistent presentation aligned with documentation standards"
},
"typeVersion": 1
},
{
"id": "0f4138ad-6b3e-4201-94f7-403fa429aed3",
"name": "Sticky Note10",
"type": "n8n-nodes-base.stickyNote",
"position": [
-576,
-96
],
"parameters": {
"color": 7,
"width": 640,
"height": 1104,
"content": "## 2. Merge Sources\n**What:** Consolidates data from Slack, Teams, Gmail, GitHub, Confluence into single dataset \n**Why:** Creates unified view across communication silos for comprehensive analysis"
},
"typeVersion": 1
},
{
"id": "0f586839-9b60-4c3c-84d0-515f35a76567",
"name": "Sticky Note11",
"type": "n8n-nodes-base.stickyNote",
"position": [
-832,
-96
],
"parameters": {
"color": 7,
"height": 1104,
"content": "## 1. Schedule Trigger\n**What:** Runs workflow at defined intervals (daily/weekly) \n**Why:** Ensures consistent"
},
"typeVersion": 1
},
{
"parameters": {
"operation": "verify",
"email": "={{ $json.email || $json.Email }}",
"additionalOptions": {}
},
"type": "n8n-nodes-billionverify.billionVerify",
"typeVersion": 1,
"position": [
-648,
336
],
"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": [
-468,
336
],
"name": "IF deliverable"
}
],
"connections": {
"Schedule Trigger": {
"main": [
[
{
"node": "Workflow Configuration",
"type": "main",
"index": 0
}
]
]
},
"Check If Valuable": {
"main": [
[
{
"node": "Format Update Data",
"type": "main",
"index": 0
}
]
]
},
"Merge All Sources": {
"main": [
[
{
"node": "AI Content Analyzer",
"type": "main",
"index": 0
}
]
]
},
"Format Update Data": {
"main": [
[
{
"node": "Update Notion Document",
"type": "main",
"index": 0
},
{
"node": "Update Confluence Page",
"type": "main",
"index": 0
}
]
]
},
"Get Slack Messages": {
"main": [
[
{
"node": "Merge All Sources",
"type": "main",
"index": 0
}
]
]
},
"Get Teams Messages": {
"main": [
[
{
"node": "Merge All Sources",
"type": "main",
"index": 1
}
]
]
},
"AI Content Analyzer": {
"main": [
[
{
"node": "Check If Valuable",
"type": "main",
"index": 0
}
]
]
},
"Anthropic Chat Model": {
"ai_languageModel": [
[
{
"node": "AI Content Analyzer",
"type": "ai_languageModel",
"index": 0
}
]
]
},
"Update Confluence Page": {
"main": [
[
{
"node": "Send Review Task to Slack",
"type": "main",
"index": 0
}
]
]
},
"Update Notion Document": {
"main": [
[
{
"node": "Send Review Task to Slack",
"type": "main",
"index": 0
}
]
]
},
"Workflow Configuration": {
"main": [
[
{
"node": "Get Slack Messages",
"type": "main",
"index": 0
},
{
"node": "Get Teams Messages",
"type": "main",
"index": 0
},
{
"node": "Verify Email (BillionVerify)",
"type": "main",
"index": 0
},
{
"node": "Get GitHub Activity",
"type": "main",
"index": 0
},
{
"node": "Get Confluence Pages",
"type": "main",
"index": 0
},
{
"node": "Get Notion Pages",
"type": "main",
"index": 0
}
]
]
},
"Structured Output Parser": {
"ai_outputParser": [
[
{
"node": "AI Content Analyzer",
"type": "ai_outputParser",
"index": 0
}
]
]
},
"Verify Email (BillionVerify)": {
"main": [
[
{
"node": "IF deliverable",
"type": "main",
"index": 0
}
]
]
},
"IF deliverable": {
"main": [
[
{
"node": "Get Gmail Messages",
"type": "main",
"index": 0
}
],
[]
]
}
},
"settings": {
"executionOrder": "v1"
}
}Workflow templates with Aggregate
Ready-to-use workflows that verify emails before Aggregate sends.
How it works
- 1
Use the BillionVerify n8n community node or REST API to add a verification step in your Aggregate-powered data pipeline.
- 2
After Aggregate consolidates records, pass each email address field to BillionVerify for validation.
- 3
BillionVerify checks format, domain existence, mailbox activity, and flags disposable or role-based addresses.
- 4
Write only verified-valid addresses to your target system, or include the verification status as an enrichment field.
- 5
Schedule periodic re-verification for long-lived datasets to catch addresses that become invalid over time.
When to use this
Clean email fields before dataset delivery
After Aggregate compiles records from multiple APIs or databases, pipe email fields through BillionVerify before the dataset is written to its final destination, ensuring downstream consumers always receive verified addresses.
Enrich aggregated records with verification status
Append BillionVerify's result—valid, invalid, catch-all, disposable—as a metadata field on each aggregated record. Recipients of the dataset can then filter by quality tier without running their own checks.
FAQ
Can BillionVerify handle the volume that Aggregate produces?
Yes. BillionVerify's REST API supports high-throughput bulk verification, making it suitable for large aggregated datasets with thousands or millions of email addresses.
What integration method works best for a data aggregation pipeline?
For developer-built pipelines, the REST API gives the most flexibility. For no-code or low-code setups, the n8n community node or Integrately integration are the fastest paths.
How do I handle catch-all results in an aggregated dataset?
BillionVerify returns catch-all addresses as a distinct category. You can choose to include them with a lower confidence score or exclude them entirely, depending on how the dataset will be used.
Does BillionVerify verify addresses in real time or only in batch mode?
Both. You can verify individual addresses in real time via the API or submit large batches for bulk processing, whichever fits your aggregation workflow best.
Verify emails in Aggregate
Create a free account, grab your API key, and stop bounces before they happen.
Get started free