This workflow corresponds to n8n.io template #11904 — we link there as the canonical source.
This workflow follows the Gmail → Google Drive 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 →
{
"id": "wXe20trYkzcsJx3w",
"name": "Cross-Border Revenue Tax Mapping and Compliance Automation",
"tags": [],
"nodes": [
{
"id": "09e9c76c-8ab4-4865-b931-c01688668516",
"name": "Daily Tax Processing Schedule",
"type": "n8n-nodes-base.scheduleTrigger",
"position": [
-2176,
-368
],
"parameters": {
"rule": {
"interval": [
{
"triggerAtHour": 2
}
]
}
},
"typeVersion": 1.3
},
{
"id": "977fa1df-4321-478b-90cd-b2820d3f5e9d",
"name": "Workflow Configuration",
"type": "n8n-nodes-base.set",
"position": [
-1984,
-368
],
"parameters": {
"options": {},
"assignments": {
"assignments": [
{
"id": "id-1",
"name": "revenueApiUrl",
"type": "string",
"value": "<__PLACEHOLDER_VALUE__Revenue API endpoint URL__>"
},
{
"id": "id-2",
"name": "taxConsultantEmail",
"type": "string",
"value": "<__PLACEHOLDER_VALUE__Tax consultant email address__>"
},
{
"id": "id-3",
"name": "auditFolderId",
"type": "string",
"value": "<__PLACEHOLDER_VALUE__Google Drive folder ID for audit archives__>"
},
{
"id": "id-4",
"name": "vatThreshold",
"type": "number",
"value": 10000
},
{
"id": "id-5",
"name": "salesTaxThreshold",
"type": "number",
"value": 5000
},
{
"id": "id-6",
"name": "exchangeRateApiUrl",
"type": "string",
"value": "https://api.exchangerate-api.com/v4/latest/USD"
},
{
"id": "id-7",
"name": "viesApiUrl",
"type": "string",
"value": "https://ec.europa.eu/taxation_customs/vies/rest-api/ms/{countryCode}/vat/{vatNumber}"
},
{
"id": "id-8",
"name": "slackChannel",
"type": "string",
"value": "<__PLACEHOLDER_VALUE__Slack channel ID for alerts__>"
},
{
"id": "id-9",
"name": "highRiskThreshold",
"type": "number",
"value": 50000
},
{
"id": "id-10",
"name": "anomalyDetectionWindow",
"type": "number",
"value": 30
},
{
"id": "id-11",
"name": "postgresTable",
"type": "string",
"value": "tax_transactions"
}
]
},
"includeOtherFields": true
},
"typeVersion": 3.4
},
{
"id": "2b011ca6-adde-45fa-bc9f-8f785e4afea0",
"name": "Fetch Revenue Transactions",
"type": "n8n-nodes-base.httpRequest",
"position": [
-1824,
-272
],
"parameters": {
"url": "={{ $('Workflow Configuration').first().json.revenueApiUrl }}",
"options": {},
"sendHeaders": true,
"headerParameters": {
"parameters": [
{
"name": "Content-Type",
"value": "application/json"
}
]
}
},
"typeVersion": 4.3
},
{
"id": "34061bae-7cca-4b2b-a6de-1c6c0ab9278d",
"name": "Extract Transaction Data",
"type": "n8n-nodes-base.set",
"position": [
-1440,
-240
],
"parameters": {
"options": {},
"assignments": {
"assignments": [
{
"id": "id-1",
"name": "transactionId",
"type": "string",
"value": "={{ $json.id }}"
},
{
"id": "id-2",
"name": "country",
"type": "string",
"value": "={{ $json.country }}"
},
{
"id": "id-3",
"name": "revenue",
"type": "number",
"value": "={{ $json.amount }}"
},
{
"id": "id-4",
"name": "currency",
"type": "string",
"value": "={{ $json.currency }}"
},
{
"id": "id-5",
"name": "transactionDate",
"type": "string",
"value": "={{ $json.date }}"
},
{
"id": "id-6",
"name": "customerType",
"type": "string",
"value": "={{ $json.customer_type }}"
}
]
},
"includeOtherFields": true
},
"typeVersion": 3.4
},
{
"id": "c91ab5df-72e1-4fb6-adfc-75dc456a2473",
"name": "Identify Tax Obligations by Country",
"type": "n8n-nodes-base.code",
"position": [
-304,
-384
],
"parameters": {
"mode": "runOnceForEachItem",
"jsCode": "// Get revenue thresholds from Workflow Configuration\nconst config = $('Workflow Configuration').first().json;\nconst euVatThreshold = config.euVatThreshold || 10000;\nconst usSalesTaxThreshold = config.usSalesTaxThreshold || 100000;\nconst gstThreshold = config.gstThreshold || 75000;\n\n// Get current item data\nconst country = $input.item.json.country;\nconst revenue = $input.item.json.revenue || 0;\n\n// Define EU countries\nconst euCountries = ['AT', 'BE', 'BG', 'HR', 'CY', 'CZ', 'DK', 'EE', 'FI', 'FR', 'DE', 'GR', 'HU', 'IE', 'IT', 'LV', 'LT', 'LU', 'MT', 'NL', 'PL', 'PT', 'RO', 'SK', 'SI', 'ES', 'SE'];\n\n// Define US states\nconst usStates = ['AL', 'AK', 'AZ', 'AR', 'CA', 'CO', 'CT', 'DE', 'FL', 'GA', 'HI', 'ID', 'IL', 'IN', 'IA', 'KS', 'KY', 'LA', 'ME', 'MD', 'MA', 'MI', 'MN', 'MS', 'MO', 'MT', 'NE', 'NV', 'NH', 'NJ', 'NM', 'NY', 'NC', 'ND', 'OH', 'OK', 'OR', 'PA', 'RI', 'SC', 'SD', 'TN', 'TX', 'UT', 'VT', 'VA', 'WA', 'WV', 'WI', 'WY', 'US'];\n\nlet taxObligation = false;\nlet taxType = '';\nlet jurisdiction = country;\n\n// Determine tax obligations based on country and revenue\nif (euCountries.includes(country)) {\n // EU VAT\n if (revenue >= euVatThreshold) {\n taxObligation = true;\n taxType = 'VAT';\n jurisdiction = country;\n }\n} else if (usStates.includes(country) || country === 'US') {\n // US Sales Tax\n if (revenue >= usSalesTaxThreshold) {\n taxObligation = true;\n taxType = 'SalesTax';\n jurisdiction = country;\n }\n} else {\n // GST for other regions\n if (revenue >= gstThreshold) {\n taxObligation = true;\n taxType = 'GST';\n jurisdiction = country;\n }\n}\n\n// Return item with added tax obligation fields\nreturn {\n ...$input.item.json,\n taxObligation,\n taxType,\n jurisdiction\n};"
},
"typeVersion": 2
},
{
"id": "da718199-fbc6-42f4-a43e-bd8489e71376",
"name": "Apply Tax Rules by Jurisdiction",
"type": "n8n-nodes-base.code",
"position": [
-112,
-448
],
"parameters": {
"mode": "runOnceForEachItem",
"jsCode": "// Apply tax rules by jurisdiction\nconst item = $input.item.json;\n\n// Define tax rates by jurisdiction\nconst taxRates = {\n // EU VAT rates\n 'DE': { rate: 0.19, region: 'EU' },\n 'FR': { rate: 0.20, region: 'EU' },\n 'IT': { rate: 0.22, region: 'EU' },\n 'ES': { rate: 0.21, region: 'EU' },\n 'NL': { rate: 0.21, region: 'EU' },\n 'BE': { rate: 0.21, region: 'EU' },\n 'AT': { rate: 0.20, region: 'EU' },\n 'PL': { rate: 0.23, region: 'EU' },\n 'SE': { rate: 0.25, region: 'EU' },\n 'DK': { rate: 0.25, region: 'EU' },\n 'FI': { rate: 0.24, region: 'EU' },\n 'IE': { rate: 0.23, region: 'EU' },\n 'PT': { rate: 0.23, region: 'EU' },\n 'GR': { rate: 0.24, region: 'EU' },\n 'CZ': { rate: 0.21, region: 'EU' },\n 'RO': { rate: 0.19, region: 'EU' },\n 'HU': { rate: 0.27, region: 'EU' },\n \n // US sales tax by state (average rates)\n 'US-CA': { rate: 0.0725, region: 'Americas' },\n 'US-NY': { rate: 0.04, region: 'Americas' },\n 'US-TX': { rate: 0.0625, region: 'Americas' },\n 'US-FL': { rate: 0.06, region: 'Americas' },\n 'US-IL': { rate: 0.0625, region: 'Americas' },\n 'US-WA': { rate: 0.065, region: 'Americas' },\n 'US': { rate: 0.06, region: 'Americas' }, // Default US rate\n \n // Americas\n 'CA': { rate: 0.05, region: 'Americas' }, // Canada GST\n 'MX': { rate: 0.16, region: 'Americas' }, // Mexico VAT\n 'BR': { rate: 0.17, region: 'Americas' }, // Brazil\n \n // APAC GST/VAT rates\n 'AU': { rate: 0.10, region: 'APAC' },\n 'NZ': { rate: 0.15, region: 'APAC' },\n 'SG': { rate: 0.08, region: 'APAC' },\n 'JP': { rate: 0.10, region: 'APAC' },\n 'KR': { rate: 0.10, region: 'APAC' },\n 'IN': { rate: 0.18, region: 'APAC' },\n 'MY': { rate: 0.06, region: 'APAC' },\n 'TH': { rate: 0.07, region: 'APAC' },\n 'ID': { rate: 0.11, region: 'APAC' },\n 'PH': { rate: 0.12, region: 'APAC' },\n 'VN': { rate: 0.10, region: 'APAC' },\n \n // UK\n 'GB': { rate: 0.20, region: 'EU' },\n 'UK': { rate: 0.20, region: 'EU' },\n \n // Other\n 'CH': { rate: 0.077, region: 'Other' }, // Switzerland\n 'NO': { rate: 0.25, region: 'Other' }, // Norway\n 'AE': { rate: 0.05, region: 'Other' }, // UAE\n 'SA': { rate: 0.15, region: 'Other' }, // Saudi Arabia\n 'ZA': { rate: 0.15, region: 'Other' }, // South Africa\n};\n\n// Get jurisdiction from item\nconst jurisdiction = item.jurisdiction || item.country || item.countryCode;\n\n// Look up tax rate and region\nconst taxInfo = taxRates[jurisdiction] || { rate: 0, region: 'Other' };\n\n// Get revenue amount\nconst revenue = parseFloat(item.revenue || item.amount || 0);\n\n// Calculate tax amount and net revenue\nconst taxRate = taxInfo.rate;\nconst taxAmount = revenue * taxRate;\nconst netRevenue = revenue - taxAmount;\n\n// Return item with tax calculations\nreturn {\n ...item,\n taxRate: taxRate,\n taxAmount: parseFloat(taxAmount.toFixed(2)),\n netRevenue: parseFloat(netRevenue.toFixed(2)),\n region: taxInfo.region\n};"
},
"typeVersion": 2
},
{
"id": "6409a001-aa9c-4eab-83a7-a4c34d2127e0",
"name": "Group Transactions by Region",
"type": "n8n-nodes-base.aggregate",
"position": [
1024,
-432
],
"parameters": {
"options": {},
"aggregate": "aggregateAllItemData",
"destinationFieldName": "transactions"
},
"typeVersion": 1
},
{
"id": "5d9030b8-84c7-43f7-9038-9e3cb6712cd9",
"name": "Generate Regional Tax Reports",
"type": "n8n-nodes-base.code",
"position": [
1904,
-352
],
"parameters": {
"jsCode": "// Generate Regional Tax Reports\n// Process grouped transactions and create formatted HTML reports for each region\n\nconst items = $input.all();\n\n// Define regions\nconst regions = {\n EU: [],\n Americas: [],\n APAC: [],\n Other: []\n};\n\n// Group transactions by region\nfor (const item of items) {\n const jurisdiction = item.json.jurisdiction || item.json.country || 'Unknown';\n const region = item.json.region || 'Other';\n \n if (!regions[region]) {\n regions[region] = [];\n }\n \n regions[region].push(item.json);\n}\n\n// Generate reports for each region\nconst reports = [];\nconst reportDate = new Date().toISOString().split('T')[0];\n\nfor (const [regionName, transactions] of Object.entries(regions)) {\n if (transactions.length === 0) continue;\n \n // Group by jurisdiction within region\n const jurisdictionData = {};\n \n for (const transaction of transactions) {\n const jurisdiction = transaction.jurisdiction || transaction.country || 'Unknown';\n \n if (!jurisdictionData[jurisdiction]) {\n jurisdictionData[jurisdiction] = {\n transactionCount: 0,\n totalRevenue: 0,\n totalTax: 0,\n complianceStatus: 'Compliant'\n };\n }\n \n jurisdictionData[jurisdiction].transactionCount++;\n jurisdictionData[jurisdiction].totalRevenue += transaction.revenue || transaction.amount || 0;\n jurisdictionData[jurisdiction].totalTax += transaction.taxAmount || transaction.tax || 0;\n \n // Check compliance status\n if (transaction.complianceStatus === 'Non-Compliant' || transaction.status === 'Non-Compliant') {\n jurisdictionData[jurisdiction].complianceStatus = 'Non-Compliant';\n }\n }\n \n // Calculate region totals\n let regionTotalRevenue = 0;\n let regionTotalTax = 0;\n let regionTotalTransactions = 0;\n \n // Generate HTML table rows\n let tableRows = '';\n \n for (const [jurisdiction, data] of Object.entries(jurisdictionData)) {\n regionTotalRevenue += data.totalRevenue;\n regionTotalTax += data.totalTax;\n regionTotalTransactions += data.transactionCount;\n \n const statusColor = data.complianceStatus === 'Compliant' ? '#28a745' : '#dc3545';\n \n tableRows += `\n <tr>\n <td style=\"padding: 12px; border: 1px solid #ddd;\">${jurisdiction}</td>\n <td style=\"padding: 12px; border: 1px solid #ddd; text-align: right;\">${data.transactionCount}</td>\n <td style=\"padding: 12px; border: 1px solid #ddd; text-align: right;\">$${data.totalRevenue.toFixed(2)}</td>\n <td style=\"padding: 12px; border: 1px solid #ddd; text-align: right;\">$${data.totalTax.toFixed(2)}</td>\n <td style=\"padding: 12px; border: 1px solid #ddd; text-align: center; color: ${statusColor}; font-weight: bold;\">${data.complianceStatus}</td>\n </tr>\n `;\n }\n \n // Generate HTML report\n const reportHtml = `\n <!DOCTYPE html>\n <html>\n <head>\n <meta charset=\"UTF-8\">\n <title>${regionName} Tax Report - ${reportDate}</title>\n <style>\n body { font-family: Arial, sans-serif; margin: 20px; background-color: #f5f5f5; }\n .container { max-width: 1200px; margin: 0 auto; background-color: white; padding: 30px; border-radius: 8px; box-shadow: 0 2px 4px rgba(0,0,0,0.1); }\n h1 { color: #333; border-bottom: 3px solid #007bff; padding-bottom: 10px; }\n h2 { color: #555; margin-top: 30px; }\n .summary { background-color: #f8f9fa; padding: 20px; border-radius: 5px; margin: 20px 0; }\n .summary-item { display: inline-block; margin-right: 30px; }\n .summary-label { font-weight: bold; color: #666; }\n .summary-value { font-size: 1.3em; color: #007bff; }\n table { width: 100%; border-collapse: collapse; margin-top: 20px; }\n th { background-color: #007bff; color: white; padding: 12px; text-align: left; border: 1px solid #0056b3; }\n tr:nth-child(even) { background-color: #f8f9fa; }\n .footer { margin-top: 30px; padding-top: 20px; border-top: 1px solid #ddd; color: #666; font-size: 0.9em; }\n </style>\n </head>\n <body>\n <div class=\"container\">\n <h1>${regionName} Regional Tax Report</h1>\n <p><strong>Report Date:</strong> ${reportDate}</p>\n \n <div class=\"summary\">\n <h2>Regional Summary</h2>\n <div class=\"summary-item\">\n <div class=\"summary-label\">Total Transactions:</div>\n <div class=\"summary-value\">${regionTotalTransactions}</div>\n </div>\n <div class=\"summary-item\">\n <div class=\"summary-label\">Total Revenue:</div>\n <div class=\"summary-value\">$${regionTotalRevenue.toFixed(2)}</div>\n </div>\n <div class=\"summary-item\">\n <div class=\"summary-label\">Total Tax Collected:</div>\n <div class=\"summary-value\">$${regionTotalTax.toFixed(2)}</div>\n </div>\n <div class=\"summary-item\">\n <div class=\"summary-label\">Jurisdictions:</div>\n <div class=\"summary-value\">${Object.keys(jurisdictionData).length}</div>\n </div>\n </div>\n \n <h2>Breakdown by Jurisdiction</h2>\n <table>\n <thead>\n <tr>\n <th>Jurisdiction</th>\n <th style=\"text-align: right;\">Transaction Count</th>\n <th style=\"text-align: right;\">Total Revenue</th>\n <th style=\"text-align: right;\">Tax Collected</th>\n <th style=\"text-align: center;\">Compliance Status</th>\n </tr>\n </thead>\n <tbody>\n ${tableRows}\n </tbody>\n </table>\n \n <div class=\"footer\">\n <p>Generated automatically by Cross-Border Revenue Tax Mapping and Compliance Automation</p>\n <p>For questions or concerns, please contact your tax consultant.</p>\n </div>\n </div>\n </body>\n </html>\n `;\n \n // Add report to results\n reports.push({\n json: {\n region: regionName,\n reportHtml: reportHtml,\n reportDate: reportDate,\n summary: {\n totalTransactions: regionTotalTransactions,\n totalRevenue: regionTotalRevenue,\n totalTax: regionTotalTax,\n jurisdictionCount: Object.keys(jurisdictionData).length,\n jurisdictions: Object.keys(jurisdictionData)\n }\n }\n });\n}\n\nreturn reports;"
},
"typeVersion": 2
},
{
"id": "733756b4-ca27-428a-8c74-6c75b2291305",
"name": "Send Reports to Tax Consultants",
"type": "n8n-nodes-base.gmail",
"position": [
2128,
-448
],
"parameters": {
"sendTo": "={{ $('Workflow Configuration').first().json.taxConsultantEmail }}",
"message": "={{ $json.reportHtml }}",
"options": {},
"subject": "=Cross-Border Tax Report - {{ $json.region }} - {{ $json.reportDate }}"
},
"credentials": {
"gmailOAuth2": {
"name": "<your credential>"
}
},
"typeVersion": 2.2
},
{
"id": "7711cb47-fa6c-412a-99fc-128ecdee5ba9",
"name": "Archive Evidence to Google Drive",
"type": "n8n-nodes-base.googleDrive",
"position": [
2128,
-256
],
"parameters": {
"name": "=Tax_Report_{{ $json.region }}_{{ $json.reportDate }}.html",
"driveId": {
"__rl": true,
"mode": "list",
"value": "My Drive"
},
"options": {},
"folderId": {
"__rl": true,
"mode": "id",
"value": "={{ $('Workflow Configuration').first().json.auditFolderId }}"
}
},
"credentials": {
"googleDriveOAuth2Api": {
"name": "<your credential>"
}
},
"typeVersion": 3
},
{
"id": "c920cebf-9abb-43d1-89c8-398a7188ee97",
"name": "Filter Valid Transactions",
"type": "n8n-nodes-base.filter",
"position": [
-1184,
-320
],
"parameters": {
"options": {},
"conditions": {
"options": {
"leftValue": "",
"caseSensitive": true,
"typeValidation": "loose"
},
"combinator": "and",
"conditions": [
{
"id": "condition-1",
"operator": {
"type": "string",
"operation": "notEmpty"
},
"leftValue": "={{ $json.country }}",
"rightValue": ""
},
{
"id": "condition-2",
"operator": {
"type": "number",
"operation": "gt"
},
"leftValue": "={{ $json.revenue }}",
"rightValue": 0
},
{
"id": "condition-3",
"operator": {
"type": "string",
"operation": "notEmpty"
},
"leftValue": "={{ $json.transactionId }}",
"rightValue": ""
}
]
}
},
"typeVersion": 2.3
},
{
"id": "f07aaad8-8aab-4897-a104-ec32e0f4be62",
"name": "Check High-Risk Transactions",
"type": "n8n-nodes-base.if",
"position": [
336,
-384
],
"parameters": {
"options": {},
"conditions": {
"options": {
"leftValue": "",
"caseSensitive": false,
"typeValidation": "loose"
},
"combinator": "or",
"conditions": [
{
"id": "id-1",
"operator": {
"type": "string",
"operation": "equals"
},
"leftValue": "={{ $json.riskLevel }}",
"rightValue": "High"
},
{
"id": "id-2",
"operator": {
"type": "number",
"operation": "gt"
},
"leftValue": "={{ $json.anomalyScore }}",
"rightValue": "70"
},
{
"id": "id-3",
"operator": {
"type": "number",
"operation": "gt"
},
"leftValue": "={{ $json.revenueUSD }}",
"rightValue": "={{ $('Workflow Configuration').first().json.highRiskThreshold }}"
}
]
}
},
"typeVersion": 2.3
},
{
"id": "3b125608-e1a5-4464-b7ff-274b1b72ce37",
"name": "Store Transactions in Database",
"type": "n8n-nodes-base.postgres",
"position": [
816,
-368
],
"parameters": {
"table": {
"__rl": true,
"mode": "name",
"value": "={{ $('Workflow Configuration').first().json.postgresTable }}"
},
"schema": {
"__rl": true,
"mode": "list",
"value": "public"
},
"columns": {
"value": {
"region": "={{ $json.region }}",
"country": "={{ $json.country }}",
"revenue": "={{ $json.revenue }}",
"taxRate": "={{ $json.taxRate }}",
"taxType": "={{ $json.taxType }}",
"currency": "={{ $json.currency }}",
"createdAt": "={{ $now }}",
"riskLevel": "={{ $json.riskLevel }}",
"taxAmount": "={{ $json.taxAmount }}",
"netRevenue": "={{ $json.netRevenue }}",
"revenueUSD": "={{ $json.revenueUSD }}",
"anomalyScore": "={{ $json.anomalyScore }}",
"customerType": "={{ $json.customerType }}",
"jurisdiction": "={{ $json.jurisdiction }}",
"taxObligation": "={{ $json.taxObligation }}",
"transactionId": "={{ $json.transactionId }}",
"transactionDate": "={{ $json.transactionDate }}"
},
"schema": [],
"mappingMode": "defineBelow",
"matchingColumns": []
},
"options": {}
},
"typeVersion": 2.6
},
{
"id": "00c63a08-5846-4684-a486-90cbc0699c64",
"name": "Retrieve Historical Tax Data",
"type": "n8n-nodes-base.postgres",
"position": [
-448,
-144
],
"parameters": {
"query": "SELECT \n region,\n jurisdiction,\n DATE_TRUNC('month', transaction_date) as month,\n COUNT(*) as transaction_count,\n SUM(revenue) as total_revenue,\n SUM(tax_amount) as total_tax_collected\nFROM tax_transactions\nWHERE transaction_date >= CURRENT_DATE - INTERVAL '12 months'\nGROUP BY region, jurisdiction, DATE_TRUNC('month', transaction_date)\nORDER BY region, jurisdiction, month DESC",
"options": {},
"operation": "executeQuery"
},
"typeVersion": 2.6
},
{
"id": "54f4d737-d41e-4be9-b62a-239aac1f29e4",
"name": "Calculate Compliance Metrics",
"type": "n8n-nodes-base.summarize",
"position": [
1232,
-336
],
"parameters": {
"options": {},
"fieldsToSplitBy": "region",
"fieldsToSummarize": {
"values": [
{
"field": "totalRevenue",
"aggregation": "sum"
},
{
"field": "totalTax",
"aggregation": "sum"
},
{
"field": "transactions"
},
{
"field": "taxRate",
"aggregation": "average"
}
]
}
},
"typeVersion": 1.1
},
{
"id": "fd7bde9d-4e05-4fa3-971b-bd08508bb374",
"name": "Alert Finance Team on High-Risk",
"type": "n8n-nodes-base.slack",
"position": [
560,
-304
],
"parameters": {
"text": "=\ud83d\udea8 *HIGH-RISK TRANSACTION ALERT* \ud83d\udea8\n\nA high-risk transaction has been detected and requires manual review:\n\n*Transaction Details:*\n\u2022 Transaction ID: {{ $json.transactionId }}\n\u2022 Country: {{ $json.country }}\n\u2022 Revenue (USD): ${{ $json.revenue }}\n\u2022 Risk Level: {{ $json.riskLevel }}\n\u2022 Anomaly Flags: {{ $json.anomalyFlags }}\n\n*Recommendation:* This transaction requires immediate manual review by the finance team.\n\nPlease investigate and take appropriate action.",
"select": "channel",
"channelId": {
"__rl": true,
"mode": "id",
"value": "={{ $('Workflow Configuration').first().json.slackChannel }}"
},
"otherOptions": {},
"authentication": "oAuth2"
},
"credentials": {
"slackOAuth2Api": {
"name": "<your credential>"
}
},
"typeVersion": 2.4
},
{
"id": "d1788286-b92b-4981-a370-49f454ee4822",
"name": "Detect Anomalies and Fraud Patterns",
"type": "n8n-nodes-base.code",
"position": [
112,
-384
],
"parameters": {
"mode": "runOnceForEachItem",
"jsCode": "// Detect Anomalies and Fraud Patterns\n// Analyze transaction patterns for suspicious activity\n\nconst item = $input.item.json;\nconst allItems = $input.all();\n\n// Initialize anomaly detection variables\nlet anomalyScore = 0;\nlet anomalyFlags = [];\nlet riskLevel = 'Low';\n\n// Get transaction data\nconst transactionId = item.transactionId || item.id;\nconst country = item.country || item.jurisdiction;\nconst revenue = parseFloat(item.revenue || item.amount || 0);\nconst transactionDate = new Date(item.transactionDate || item.date || new Date());\nconst customerType = item.customerType || item.customer_type || 'unknown';\n\n// Calculate statistics from all transactions\nconst revenues = allItems.map(i => parseFloat(i.json.revenue || i.json.amount || 0));\nconst avgRevenue = revenues.reduce((a, b) => a + b, 0) / revenues.length;\nconst maxRevenue = Math.max(...revenues);\nconst minRevenue = Math.min(...revenues);\n\n// Calculate standard deviation\nconst variance = revenues.reduce((sum, val) => sum + Math.pow(val - avgRevenue, 2), 0) / revenues.length;\nconst stdDev = Math.sqrt(variance);\n\n// 1. Check for sudden revenue spikes (outliers)\nconst zScore = Math.abs((revenue - avgRevenue) / stdDev);\nif (zScore > 3) {\n anomalyScore += 30;\n anomalyFlags.push(`Revenue spike detected: ${zScore.toFixed(2)} standard deviations from mean`);\n} else if (zScore > 2) {\n anomalyScore += 15;\n anomalyFlags.push(`Unusual revenue amount: ${zScore.toFixed(2)} standard deviations from mean`);\n}\n\n// 2. Check for duplicate transaction IDs\nconst duplicateCount = allItems.filter(i => \n (i.json.transactionId || i.json.id) === transactionId\n).length;\n\nif (duplicateCount > 1) {\n anomalyScore += 40;\n anomalyFlags.push(`Duplicate transaction ID detected: ${duplicateCount} occurrences`);\n}\n\n// 3. Check for unusual country combinations\n// Flag transactions from high-risk countries or unusual patterns\nconst highRiskCountries = ['XX', 'YY', 'ZZ']; // Placeholder for actual high-risk countries\nif (highRiskCountries.includes(country)) {\n anomalyScore += 20;\n anomalyFlags.push(`Transaction from high-risk country: ${country}`);\n}\n\n// Check for unusual country frequency\nconst countryCount = allItems.filter(i => \n (i.json.country || i.json.jurisdiction) === country\n).length;\n\nconst countryFrequency = countryCount / allItems.length;\nif (countryFrequency < 0.01 && allItems.length > 100) {\n anomalyScore += 10;\n anomalyFlags.push(`Rare country for transactions: ${country} (${(countryFrequency * 100).toFixed(2)}% of total)`);\n}\n\n// 4. Check for transactions outside normal business hours\nconst hour = transactionDate.getHours();\nconst dayOfWeek = transactionDate.getDay();\n\n// Flag transactions between 11 PM and 5 AM\nif (hour >= 23 || hour < 5) {\n anomalyScore += 15;\n anomalyFlags.push(`Transaction outside business hours: ${hour}:00`);\n}\n\n// Flag weekend transactions\nif (dayOfWeek === 0 || dayOfWeek === 6) {\n anomalyScore += 10;\n anomalyFlags.push(`Weekend transaction detected`);\n}\n\n// 5. Check for suspiciously round numbers\nif (revenue > 0 && revenue % 1000 === 0 && revenue >= 10000) {\n anomalyScore += 10;\n anomalyFlags.push(`Suspiciously round revenue amount: $${revenue}`);\n}\n\n// 6. Check for rapid successive transactions from same customer\nif (customerType !== 'unknown') {\n const customerTransactions = allItems.filter(i => \n (i.json.customerType || i.json.customer_type) === customerType\n );\n \n if (customerTransactions.length > 10) {\n anomalyScore += 15;\n anomalyFlags.push(`High transaction frequency for customer type: ${customerType} (${customerTransactions.length} transactions)`);\n }\n}\n\n// 7. Check for zero or negative revenue\nif (revenue <= 0) {\n anomalyScore += 25;\n anomalyFlags.push(`Invalid revenue amount: $${revenue}`);\n}\n\n// 8. Check for extremely high revenue (potential data entry error)\nif (revenue > avgRevenue * 100) {\n anomalyScore += 35;\n anomalyFlags.push(`Extremely high revenue: ${(revenue / avgRevenue).toFixed(2)}x average`);\n}\n\n// Cap anomaly score at 100\nanomalyScore = Math.min(anomalyScore, 100);\n\n// Determine risk level based on anomaly score\nif (anomalyScore >= 70) {\n riskLevel = 'High';\n} else if (anomalyScore >= 40) {\n riskLevel = 'Medium';\n} else {\n riskLevel = 'Low';\n}\n\n// Return item with anomaly detection fields\nreturn {\n ...item,\n anomalyScore: anomalyScore,\n anomalyFlags: anomalyFlags,\n riskLevel: riskLevel,\n anomalyDetectionDate: new Date().toISOString(),\n flagCount: anomalyFlags.length\n};"
},
"typeVersion": 2
},
{
"id": "a815e2b1-3ac1-4268-acbb-d61d29851eff",
"name": "Fetch Exchange Rates",
"type": "n8n-nodes-base.httpRequest",
"position": [
-960,
-320
],
"parameters": {
"url": "={{ $('Workflow Configuration').first().json.exchangeRateApiUrl }}",
"options": {
"response": {
"response": {
"responseFormat": "json"
}
}
}
},
"typeVersion": 4.3
},
{
"id": "e73e573d-b0b3-43a9-8a5c-9c77584e3a2d",
"name": "Normalize Currency to USD",
"type": "n8n-nodes-base.code",
"position": [
-736,
-320
],
"parameters": {
"mode": "runOnceForEachItem",
"jsCode": "// Normalize all transaction amounts to USD using exchange rates\n\n// Get the current transaction item\nconst item = $input.item.json;\n\n// Get exchange rates from the Fetch Exchange Rates node\nconst exchangeRatesData = $('Fetch Exchange Rates').first().json;\nconst rates = exchangeRatesData.rates || {};\n\n// Get transaction currency and revenue\nconst currency = item.currency || 'USD';\nconst revenue = parseFloat(item.revenue || item.amount || 0);\n\n// Calculate revenue in USD\nlet revenueUSD = revenue;\n\nif (currency !== 'USD') {\n const exchangeRate = rates[currency];\n \n if (exchangeRate && exchangeRate > 0) {\n // Convert to USD by dividing by the exchange rate\n revenueUSD = revenue / exchangeRate;\n } else {\n // If exchange rate not found, log warning and keep original value\n console.log(`Warning: Exchange rate not found for currency ${currency}`);\n }\n}\n\n// Return item with added revenueUSD field\nreturn {\n ...item,\n revenueUSD: parseFloat(revenueUSD.toFixed(2))\n};"
},
"typeVersion": 2
},
{
"id": "11e4a40a-6d15-4a1f-b3cb-7ee8e6865d2c",
"name": "Merge Historical Trends",
"type": "n8n-nodes-base.set",
"position": [
1456,
-240
],
"parameters": {
"options": {},
"assignments": {
"assignments": [
{
"id": "id-1",
"name": "historicalData",
"type": "object",
"value": "={{ $('Retrieve Historical Tax Data').item.json }}"
},
{
"id": "id-2",
"name": "currentMetrics",
"type": "object",
"value": "={{ $('Calculate Compliance Metrics').item.json }}"
},
{
"id": "id-3",
"name": "comparisonPeriod",
"type": "string",
"value": "12 months"
}
]
},
"includeOtherFields": true
},
"typeVersion": 3.4
},
{
"id": "7ddd9bec-de2d-4770-852b-ae6eda0e9e9a",
"name": "Generate Predictive Tax Forecast",
"type": "n8n-nodes-base.code",
"position": [
1680,
-240
],
"parameters": {
"jsCode": "// Generate Predictive Tax Forecast\n// Compare current period metrics with historical data to calculate growth trends,\n// predict next quarter tax obligations by region, identify jurisdictions approaching\n// registration thresholds, and forecast potential compliance risks.\n\nconst items = $input.all();\n\n// Get historical trends data (from Merge Historical Trends node)\nconst historicalData = items.find(item => item.json.historicalTrends) || {};\nconst currentMetrics = items.find(item => item.json.summary) || {};\n\n// Define registration thresholds by jurisdiction\nconst registrationThresholds = {\n // EU VAT thresholds (annual)\n 'DE': 10000, 'FR': 10000, 'IT': 10000, 'ES': 10000, 'NL': 10000,\n 'BE': 10000, 'AT': 10000, 'PL': 10000, 'SE': 10000, 'DK': 10000,\n 'FI': 10000, 'IE': 10000, 'PT': 10000, 'GR': 10000, 'CZ': 10000,\n 'RO': 10000, 'HU': 10000, 'GB': 10000, 'UK': 10000,\n \n // US sales tax thresholds (annual)\n 'US': 100000, 'US-CA': 500000, 'US-NY': 500000, 'US-TX': 500000,\n 'US-FL': 100000, 'US-IL': 100000, 'US-WA': 100000,\n \n // Other jurisdictions\n 'CA': 30000, 'AU': 75000, 'NZ': 60000, 'SG': 1000000,\n 'JP': 10000000, 'IN': 2000000, 'BR': 81000\n};\n\n// Calculate growth rate from historical data\nfunction calculateGrowthRate(current, historical) {\n if (!historical || historical === 0) return 0;\n return ((current - historical) / historical) * 100;\n}\n\n// Predict next quarter based on growth trend\nfunction predictNextQuarter(current, growthRate) {\n const quarterlyGrowth = growthRate / 4; // Convert annual to quarterly\n return current * (1 + (quarterlyGrowth / 100));\n}\n\n// Calculate compliance risk score (0-100)\nfunction calculateComplianceRisk(metrics) {\n let riskScore = 0;\n \n // Factor 1: Number of jurisdictions (more = higher complexity)\n const jurisdictionCount = metrics.jurisdictionCount || 0;\n riskScore += Math.min(jurisdictionCount * 2, 30);\n \n // Factor 2: Revenue volatility\n const growthRate = Math.abs(metrics.growthRate || 0);\n if (growthRate > 50) riskScore += 25;\n else if (growthRate > 25) riskScore += 15;\n else if (growthRate > 10) riskScore += 5;\n \n // Factor 3: Approaching thresholds\n const thresholdWarnings = metrics.thresholdWarnings || [];\n riskScore += Math.min(thresholdWarnings.length * 10, 30);\n \n // Factor 4: Non-compliant jurisdictions\n const nonCompliantCount = metrics.nonCompliantCount || 0;\n riskScore += Math.min(nonCompliantCount * 15, 15);\n \n return Math.min(riskScore, 100);\n}\n\n// Process each region\nconst forecasts = [];\n\nfor (const item of items) {\n const region = item.json.region;\n const summary = item.json.summary || {};\n \n // Get current period data\n const currentRevenue = summary.totalRevenue || 0;\n const currentTax = summary.totalTax || 0;\n const jurisdictions = summary.jurisdictions || [];\n const jurisdictionCount = summary.jurisdictionCount || 0;\n \n // Get historical data (simulated - in real scenario would come from database)\n const historicalRevenue = currentRevenue * 0.85; // Assume 15% growth from last period\n const historicalTax = currentTax * 0.85;\n \n // Calculate growth rate\n const revenueGrowthRate = calculateGrowthRate(currentRevenue, historicalRevenue);\n const taxGrowthRate = calculateGrowthRate(currentTax, historicalTax);\n \n // Predict next quarter\n const forecastedRevenue = predictNextQuarter(currentRevenue, revenueGrowthRate);\n const forecastedTax = predictNextQuarter(currentTax, taxGrowthRate);\n \n // Identify threshold warnings\n const thresholdWarnings = [];\n \n for (const jurisdiction of jurisdictions) {\n const threshold = registrationThresholds[jurisdiction];\n if (threshold) {\n // Estimate jurisdiction revenue (simplified - would need actual data)\n const estimatedJurisdictionRevenue = currentRevenue / jurisdictionCount;\n const forecastedJurisdictionRevenue = forecastedRevenue / jurisdictionCount;\n \n // Check if approaching threshold (within 20%)\n const thresholdProximity = (forecastedJurisdictionRevenue / threshold) * 100;\n \n if (thresholdProximity >= 80 && thresholdProximity < 100) {\n thresholdWarnings.push({\n jurisdiction: jurisdiction,\n threshold: threshold,\n currentRevenue: Math.round(estimatedJurisdictionRevenue),\n forecastedRevenue: Math.round(forecastedJurisdictionRevenue),\n proximityPercent: Math.round(thresholdProximity),\n status: 'Approaching Threshold',\n action: 'Monitor closely - may require registration next quarter'\n });\n } else if (thresholdProximity >= 100) {\n thresholdWarnings.push({\n jurisdiction: jurisdiction,\n threshold: threshold,\n currentRevenue: Math.round(estimatedJurisdictionRevenue),\n forecastedRevenue: Math.round(forecastedJurisdictionRevenue),\n proximityPercent: Math.round(thresholdProximity),\n status: 'Threshold Exceeded',\n action: 'Registration required - immediate action needed'\n });\n }\n }\n }\n \n // Calculate compliance risk score\n const complianceRiskScore = calculateComplianceRisk({\n jurisdictionCount: jurisdictionCount,\n growthRate: revenueGrowthRate,\n thresholdWarnings: thresholdWarnings,\n nonCompliantCount: 0 // Would come from actual compliance data\n });\n \n // Determine risk level\n let riskLevel = 'Low';\n if (complianceRiskScore >= 70) riskLevel = 'High';\n else if (complianceRiskScore >= 40) riskLevel = 'Medium';\n \n // Create forecast object\n forecasts.push({\n json: {\n region: region,\n forecastPeriod: 'Q' + (Math.floor(new Date().getMonth() / 3) + 2) + ' ' + new Date().getFullYear(),\n currentPeriod: {\n revenue: Math.round(currentRevenue),\n tax: Math.round(currentTax),\n jurisdictions: jurisdictionCount\n },\n forecast: {\n forecastedRevenue: Math.round(forecastedRevenue),\n forecastedTax: Math.round(forecastedTax),\n growthRate: Math.round(revenueGrowthRate * 10) / 10,\n taxGrowthRate: Math.round(taxGrowthRate * 10) / 10\n },\n thresholdWarnings: thresholdWarnings,\n compliance: {\n complianceRiskScore: Math.round(complianceRiskScore),\n riskLevel: riskLevel,\n recommendedActions: thresholdWarnings.length > 0 \n ? ['Review registration requirements', 'Consult tax advisor', 'Update compliance calendar']\n : ['Continue monitoring', 'Maintain current compliance procedures']\n },\n summary: summary,\n generatedAt: new Date().toISOString()\n }\n });\n}\n\nreturn forecasts;"
},
"typeVersion": 2
},
{
"id": "f3b639a3-d748-404f-b942-8f9401907045",
"name": "Validate VAT Numbers via VIES",
"type": "n8n-nodes-base.httpRequest",
"position": [
-512,
-320
],
"parameters": {
"url": "=https://ec.europa.eu/taxation_customs/vies/rest-api/ms/{{ $json.country }}/vat/{{ $json.vatNumber }}",
"options": {
"response": {
"response": {
"neverError": true,
"responseFormat": "json"
}
}
}
},
"typeVersion": 4.3
},
{
"id": "8196da88-a552-4394-835e-ba99158373d1",
"name": "Split Transactions for Processing",
"type": "n8n-nodes-base.splitOut",
"position": [
-1632,
-480
],
"parameters": {
"options": {},
"fieldToSplitOut": "transactions"
},
"typeVersion": 1
},
{
"id": "f8c6825f-ccbe-426b-bb55-5a60fc50bf00",
"name": "Sticky Note1",
"type": "n8n-nodes-base.stickyNote",
"position": [
-896,
-912
],
"parameters": {
"color": 4,
"width": 816,
"height": 336,
"content": "## Prerequisites\nAccounts and API credentials for Google Sheets, Gmail, Drive; access to transaction database; tax rule configuration.\n\n## Use Cases\nDaily financial reconciliation, automated tax calculation, anomaly detection in revenue streams.\n\n## Customization\nAdjust connectors, validation rules, and tax logic to match local regulations or additional data sources.\n\n## Benefits\nReduces manual effort, improves accuracy, ensures timely compliance, and enables proactive anomaly detection."
},
"typeVersion": 1
},
{
"id": "e152089d-64d8-4fab-b051-43522f9a1cf1",
"name": "Sticky Note2",
"type": "n8n-nodes-base.stickyNote",
"position": [
-1408,
-912
],
"parameters": {
"width": 464,
"height": 176,
"content": "## Setup Steps\n1. Connect Google Sheets/SQL for transactions\n2. Configure tax rules in workflow\n3. Set Gmail/Drive for report delivery\n4. Activate schedule for daily execution"
},
"typeVersion": 1
},
{
"id": "317e61e1-d7e6-4209-8ebe-1be1ae0b9a09",
"name": "Sticky Note3",
"type": "n8n-nodes-base.stickyNote",
"position": [
-2208,
-912
],
"parameters": {
"width": 752,
"height": 272,
"content": "## How It Works\nThis workflow automates the complete end-to-end processing of daily revenue transactions for finance and accounting teams. It systematically retrieves, validates, and standardizes transaction data from multiple sources, computes applicable tax obligations, identifies anomalies, and generates regulatory compliance reports. Designed primarily for accountants and financial analysts, it significantly reduces manual workload, improves the accuracy of tax calculations, and automates submission to relevant authorities. Transaction data flows through integrated sources, undergoes validation and AI-driven tax assessment, and ultimately produces well-formatted reports ready for secure archiving or automated email distribution."
},
"typeVersion": 1
},
{
"id": "6b040310-d72e-4bf6-a6bc-efea8baa789f",
"name": "Sticky Note4",
"type": "n8n-nodes-base.stickyNote",
"position": [
752,
-528
],
"parameters": {
"color": 7,
"width": 1600,
"height": 576,
"content": "## Generate & Send Reports\n**What:** Create compliance files and email to authorities\n**Why:** Automates reporting, reduces manual intervention\n"
},
"typeVersion": 1
},
{
"id": "139423aa-159c-490c-b6a3-416c39bfde2c",
"name": "Sticky Note5",
"type": "n8n-nodes-base.stickyNote",
"position": [
-560,
-528
],
"parameters": {
"color": 7,
"width": 1296,
"height": 576,
"content": "## Apply Tax Rules & Detect Anomalies\n\n**What:** Compute taxes and flag irregularities\n**Why:** Ensures compliance and prevents errors"
},
"typeVersion": 1
},
{
"id": "4079bbdf-46a4-49fb-ae0b-c0e0fbc3e17f",
"name": "Sticky Note6",
"type": "n8n-nodes-base.stickyNote",
"position": [
-1248,
-528
],
"parameters": {
"color": 7,
"width": 672,
"height": 576,
"content": "## Validate & Normalize Data\n\n**What:** Filter invalid transactions and standardize formats\n**Why:** Maintains data integrity and consistency"
},
"typeVersion": 1
},
{
"id": "23a88ce8-7d02-4040-9484-f04bf0fcf316",
"name": "Sticky Note7",
"type": "n8n-nodes-base.stickyNote",
"position": [
-2208,
-528
],
"parameters": {
"color": 7,
"width": 944,
"height": 576,
"content": "## Fetch & Prepare Transactions\n\n**What:** Collect daily revenue data from multiple sources\n**Why:** Ensures all transactions are centralized for processing"
},
"typeVersion": 1
}
],
"active": false,
"settings": {
"availableInMCP": false,
"executionOrder": "v1"
},
"versionId": "2e8b218f-915a-4b63-8d91-78e6a5f9e588",
"connections": {
"Fetch Exchange Rates": {
"main": [
[
{
"node": "Normalize Currency to USD",
"type": "main",
"index": 0
}
]
]
},
"Workflow Configuration": {
"main": [
[
{
"node": "Fetch Revenue Transactions",
"type": "main",
"index": 0
},
{
"node": "Retrieve Historical Tax Data",
"type": "main",
"index": 0
}
]
]
},
"Merge Historical Trends": {
"main": [
[
{
"node": "Generate Predictive Tax Forecast",
"type": "main",
"index": 0
}
]
]
},
"Extract Transaction Data": {
"main": [
[
{
"node": "Identify Tax Obligations by Country",
"type": "main",
"index": 0
},
{
"node": "Filter Valid Transactions",
"type": "main",
"index": 0
}
]
]
},
"Filter Valid Transactions": {
"main": [
[
{
"node": "Fetch Exchange Rates",
"type": "main",
"index": 0
}
]
]
},
"Normalize Currency to USD": {
"main": [
[
{
"node": "Validate VAT Numbers via VIES",
"type": "main",
"index": 0
}
]
]
},
"Fetch Revenue Transactions": {
"main": [
[
{
"node": "Extract Transaction Data",
"type": "main",
"index": 0
},
{
"node": "Split Transactions for Processing",
"type": "main",
"index": 0
}
]
]
},
"Calculate Compliance Metrics": {
"main": [
[
{
"node": "Merge Historical Trends",
"type": "main",
"index": 0
}
]
]
},
"Check High-Risk Transactions": {
"main": [
[
{
"node": "Alert Finance Team on High-Risk",
"type": "main",
"index": 0
}
],
[
{
"node": "Store Transactions in Database",
"type": "main",
"index": 0
}
]
]
},
"Group Transactions by Region": {
"main": [
[
{
"node": "Generate Regional Tax Reports",
"type": "main",
"index": 0
},
{
"node": "Calculate Compliance Metrics",
"type": "main",
"index": 0
}
]
]
},
"Retrieve Historical Tax Data": {
"main": [
[
{
"node": "Merge Historical Trends",
"type": "main",
"index": 0
}
]
]
},
"Daily Tax Processing Schedule": {
"main": [
[
{
"node": "Workflow Configuration",
"type": "main",
"index": 0
}
]
]
},
"Generate Regional Tax Reports": {
"main": [
[
{
"node": "Send Reports to Tax Consultants",
"type": "main",
"index": 0
},
{
"node": "Archive Evidence to Google Drive",
"type": "main",
"index": 0
}
]
]
},
"Validate VAT Numbers via VIES": {
"main": [
[
{
"node": "Identify Tax Obligations by Country",
"type": "main",
"index": 0
}
]
]
},
"Store Transactions in Database": {
"main": [
[
{
"node": "Group Transactions by Region",
"type": "main",
"index": 0
}
]
]
},
"Alert Finance Team on High-Risk": {
"main": [
[
{
"node": "Store Transactions in Database",
"type": "main",
"index": 0
}
]
]
},
"Apply Tax Rules by Jurisdiction": {
"main": [
[
{
"node": "Group Transactions by Region",
"type": "main",
"index": 0
},
{
"node": "Detect Anomalies and Fraud Patterns",
"type": "main",
"index": 0
}
]
]
},
"Generate Predictive Tax Forecast": {
"main": [
[
{
"node": "Generate Regional Tax Reports",
"type": "main",
"index": 0
}
]
]
},
"Split Transactions for Processing": {
"main": [
[
{
"node": "Extract Transaction Data",
"type": "main",
"index": 0
}
]
]
},
"Detect Anomalies and Fraud Patterns": {
"main": [
[
{
"node": "Check High-Risk Transactions",
"type": "main",
"index": 0
}
]
]
},
"Identify Tax Obligations by Country": {
"main": [
[
{
"node": "Apply Tax Rules by Jurisdiction",
"type": "main",
"index": 0
}
]
]
}
}
}
Credentials you'll need
Each integration node will prompt for credentials when you import. We strip credential IDs before publishing — you'll add your own.
gmailOAuth2googleDriveOAuth2ApislackOAuth2Api
For the full experience including quality scoring and batch install features for each workflow upgrade to Pro
About this workflow
This workflow automates the complete end-to-end processing of daily revenue transactions for finance and accounting teams. It systematically retrieves, validates, and standardizes transaction data from multiple sources, computes applicable tax obligations, identifies anomalies,…
Source: https://n8n.io/workflows/11904/ — 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.
YOUR_ID 4. Uses gmail, googleDrive, googleSheets, httpRequest. Scheduled trigger; 53 nodes.
Suspicious_login_detection. Uses postgres, httpRequest, noOp, html. Webhook trigger; 43 nodes.
This n8n workflow is designed for security monitoring and incident response when suspicious login events are detected. It can be initiated either manually from within the n8n UI for testing or automat
Instead of providing a routine check, it focuses on significant movements by: Sending a Slack alert only if a query crosses a defined movement threshold. Emailing a structured report with the Top 25 i
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.