This workflow corresponds to n8n.io template #15873 — we link there as the canonical source.
This workflow follows the Gmail → Google Sheets recipe pattern — see all workflows that pair these two integrations.
The workflow JSON
Copy or download the full n8n JSON below. Paste it into a new n8n workflow, add your credentials, activate. Full import guide →
{
"meta": {
"templateCredsSetupCompleted": true
},
"nodes": [
{
"id": "0a154269-8c8f-432b-a7b5-35f868301a70",
"name": "Parse & Enrich Payment Data",
"type": "n8n-nodes-base.code",
"position": [
960,
416
],
"parameters": {
"jsCode": "// \u2500\u2500\u2500 Parse & Enrich Stripe Failed Payment Event \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\nconst body = $input.item.json.body ?? $input.item.json;\n\n// Validate event type\nconst ALLOWED = [\n 'payment_intent.payment_failed',\n 'invoice.payment_failed',\n 'charge.failed'\n];\nif (!ALLOWED.includes(body.type)) {\n throw new Error('[StripeRecovery] Unexpected event: ' + body.type);\n}\n\nconst o = body.data?.object ?? {};\n\n// Normalise across event types (payment_intent vs invoice)\nconst amountCents = o.amount ?? o.amount_due ?? 0;\nconst amountDollars = (amountCents / 100).toFixed(2);\nconst currency = (o.currency ?? 'usd').toUpperCase();\nconst customerId = o.customer ?? '';\nconst customerEmail = o.receipt_email ?? o.customer_email ?? o.metadata?.customer_email ?? '';\nconst customerName = o.metadata?.customer_name ?? o.customer_name ?? 'Unknown Customer';\nconst plan = o.metadata?.plan ?? o.metadata?.product_name ?? 'N/A';\nconst paymentId = o.id ?? '';\nconst invoiceId = o.invoice ?? o.id ?? '';\nconst subscriptionId = o.subscription ?? o.metadata?.subscription_id ?? null;\nconst attemptCount = Number(\n o.attempt_count ?? // real field on invoice events\n o.metadata?.attempt_count ?? // your custom metadata override\n 1\n);\nconst failureCode = o.last_payment_error?.code ?? o.failure_code ?? 'unknown';\nconst failureMessage = o.last_payment_error?.message ?? o.failure_message ?? 'Payment failed';\nconst failureType = o.last_payment_error?.type ?? 'unknown';\nconst declineCode = o.last_payment_error?.decline_code ?? null;\nconst nextRetryAt = o.next_payment_attempt\n ? new Date(o.next_payment_attempt * 1000).toUTCString()\n : 'None scheduled';\nconst createdAt = new Date((o.created ?? Date.now() / 1000) * 1000).toISOString();\nconst processedAt = new Date().toISOString();\n\n// Severity tiers\nlet severity = 'LOW';\nif (amountCents >= 100000) severity = 'CRITICAL'; // >= $1,000\nelse if (amountCents >= 10000) severity = 'HIGH'; // >= $100\nelse if (amountCents >= 1000) severity = 'MEDIUM'; // >= $10\n\n// ClickUp priority: 1=urgent 2=high 3=normal 4=low\nconst priorityMap = { CRITICAL: 1, HIGH: 2, MEDIUM: 3, LOW: 4 };\nconst clickupPriority = priorityMap[severity];\n\n// Due date: 24h critical, 48h otherwise\nconst dueDateMs = severity === 'CRITICAL'\n ? Date.now() + 24 * 3600 * 1000\n : Date.now() + 48 * 3600 * 1000;\n\nreturn [{ json: {\n // Identifiers\n stripeEventId: body.id,\n eventType: body.type,\n paymentId,\n invoiceId,\n subscriptionId,\n customerId,\n // Customer\n customerEmail,\n customerName,\n plan,\n // Payment\n amountCents,\n amountDollars,\n currency,\n // Failure\n attemptCount,\n failureCode,\n failureMessage,\n failureType,\n declineCode,\n // Routing\n severity,\n clickupPriority,\n dueDateMs,\n isHighValue: amountCents >= 100000,\n isRepeatedFailure: attemptCount > 2,\n // Timing\n nextRetryAt,\n createdAt,\n processedAt,\n // Deep links\n stripePaymentUrl: 'https://dashboard.stripe.com/payments/' + paymentId,\n stripeCustomerUrl: 'https://dashboard.stripe.com/customers/' + customerId\n}}];"
},
"typeVersion": 2
},
{
"id": "632bc0b3-da1c-411a-8114-edc4137bfbcc",
"name": "High Value Check",
"type": "n8n-nodes-base.if",
"position": [
1392,
416
],
"parameters": {
"options": {},
"conditions": {
"options": {
"version": 1,
"leftValue": "",
"caseSensitive": true,
"typeValidation": "strict"
},
"combinator": "and",
"conditions": [
{
"id": "cond-highvalue",
"operator": {
"type": "boolean",
"operation": "equals"
},
"leftValue": "={{ $json.isHighValue }}",
"rightValue": true
}
]
}
},
"typeVersion": 2
},
{
"id": "812d5980-a3d9-4e0a-aefc-ea85d4ee3503",
"name": "Slack \u2014 Critical Alert",
"type": "n8n-nodes-base.slack",
"position": [
1760,
256
],
"parameters": {
"text": "=:rotating_light: *CRITICAL PAYMENT FAILURE* :rotating_light:\n\n*Customer:* {{ $('Parse & Enrich Payment Data').item.json.customerName }}\n*Email:* {{ $('Parse & Enrich Payment Data').item.json.customerEmail }}\n*Plan:* {{ $('Parse & Enrich Payment Data').item.json.plan }}\n*Amount:* {{ $('Parse & Enrich Payment Data').item.json.amountDollars }} {{ $('Parse & Enrich Payment Data').item.json.currency }}\n*Severity:* `{{ $('Parse & Enrich Payment Data').item.json.severity }}`\n*Failure Code:* `{{ $('Parse & Enrich Payment Data').item.json.failureCode }}`\n*Failure Message:* {{ $('Parse & Enrich Payment Data').item.json.failureMessage }}\n*Attempt #:* {{ $('Parse & Enrich Payment Data').item.json.attemptCount }}\n*Next Retry:* {{ $('Parse & Enrich Payment Data').item.json.nextRetryAt }}\n\n:link: <{{ $('Parse & Enrich Payment Data').item.json.stripePaymentUrl }}|View Payment> | <{{ $('Parse & Enrich Payment Data').item.json.stripeCustomerUrl }}|View Customer>\n\n_Event: `{{ $('Parse & Enrich Payment Data').item.json.stripeEventId }}` \u2014 {{ $('Parse & Enrich Payment Data').item.json.processedAt }}_",
"otherOptions": {
"mrkdwn": true
},
"authentication": "oAuth2"
},
"typeVersion": 2.2
},
{
"id": "90647890-ea8e-4de0-abca-23a2a2c09d4a",
"name": "Slack \u2014 Standard Alert",
"type": "n8n-nodes-base.slack",
"position": [
1760,
528
],
"parameters": {
"text": "=:credit_card: *Payment Failed*\n\n*Customer:* {{ $json.customerName }}\n*Email:* {{ $json.customerEmail }}\n*Plan:* {{ $json.plan }}\n*Amount:* ${{ $json.amountDollars }} {{ $json.currency }}\n*Severity:* `{{ $json.severity }}`\n*Failure:* {{ $json.failureMessage }} (`{{ $json.failureCode }}`)\n*Attempt #:* {{ $json.attemptCount }}\n*Next Retry:* {{ $json.nextRetryAt }}\n\n:link: <{{ $json.stripePaymentUrl }}|View Payment> | <{{ $json.stripeCustomerUrl }}|View Customer>\n\n_Event: `{{ $json.stripeEventId }}` \u2014 {{ $json.processedAt }}_",
"otherOptions": {
"mrkdwn": true
},
"authentication": "oAuth2"
},
"typeVersion": 2.2
},
{
"id": "4b05f0a7-8473-45df-ab5b-04c6b6c8ce77",
"name": "ClickUp \u2014 Create Recovery Task",
"type": "n8n-nodes-base.clickUp",
"position": [
2112,
416
],
"parameters": {
"name": "=\ud83d\udcb3 Payment Recovery: {{ $('High Value Check').item.json.customerName }}\u2014 {{ $('High Value Check').item.json.amountDollars }} {{ $('High Value Check').item.json.currency }}",
"folderless": true,
"additionalFields": {
"dueDate": "={{ $('Parse & Enrich Payment Data').item.json.dueDateMs }}",
"priority": "={{ $('Parse & Enrich Payment Data').item.json.clickupPriority }}"
}
},
"typeVersion": 1
},
{
"id": "42920d01-c232-4e46-9cf1-7d3de4d79755",
"name": "Retry Count Check",
"type": "n8n-nodes-base.if",
"position": [
2416,
416
],
"parameters": {
"options": {},
"conditions": {
"options": {
"version": 1,
"leftValue": "",
"caseSensitive": true,
"typeValidation": "strict"
},
"combinator": "and",
"conditions": [
{
"id": "cond-retry",
"operator": {
"type": "boolean",
"operation": "equals"
},
"leftValue": "={{ $('High Value Check').item.json.isRepeatedFailure }}",
"rightValue": true
}
]
}
},
"typeVersion": 2
},
{
"id": "b8bdb28d-b48f-4b33-bd84-8c14d96469ae",
"name": "Slack \u2014 Escalation Alert",
"type": "n8n-nodes-base.slack",
"position": [
2768,
288
],
"parameters": {
"text": "=:sos: *ESCALATION \u2014 Repeated Payment Failure (Attempt #{{ $('High Value Check').item.json.attemptCount }}*\n\nA customer has now failed payment *{{ $('High Value Check').item.json.attemptCount }} times*. Manual intervention required.\n\n*Customer:* {{ $('High Value Check').item.json.customerName }} ({{ $('High Value Check').item.json.customerEmail }})\n*Plan:* {{ $('High Value Check').item.json.plan }}\n*Amount:* {{ $('High Value Check').item.json.amountDollars }} {{ $('High Value Check').item.json.currency }}\n*Last Failure:* {{ $('High Value Check').item.json.failureMessage }} (`{{ $('High Value Check').item.json.failureCode }}`)\n*Subscription ID:* {{ $('High Value Check').item.json.subscriptionId || 'N/A' }}\n\n:link: <{{ $('High Value Check').item.json.stripeCustomerUrl }}|View Customer in Stripe>\n\n{{ $vars.SLACK_ESCALATION_MENTION || '@billing-manager' }} \u2014 please review and take action.\n\n_Event: `{{ $('High Value Check').item.json.stripeEventId }}` | Severity: {{ $('High Value Check').item.json.severity }}_",
"otherOptions": {
"mrkdwn": true
},
"authentication": "oAuth2"
},
"typeVersion": 2.2
},
{
"id": "1cda8f9a-f994-4715-a85f-8536080a000d",
"name": "Log to Google Sheets",
"type": "n8n-nodes-base.googleSheets",
"position": [
3344,
432
],
"parameters": {
"operation": "append",
"sheetName": {
"__rl": true,
"mode": "",
"value": "",
"cachedResultUrl": "",
"cachedResultName": ""
},
"documentId": {
"__rl": true,
"mode": "",
"value": "",
"cachedResultUrl": "",
"cachedResultName": ""
}
},
"typeVersion": 4.4
},
{
"id": "1bf9ac9b-b5a7-4242-ae6f-b06327314b74",
"name": "Send a message",
"type": "n8n-nodes-base.gmail",
"position": [
3136,
432
],
"parameters": {
"message": "=<p>Dear {{ $('High Value Check').item.json.customerName }},</p> <p>We were unable to process your payment of <strong>{{ $('High Value Check').item.json.amountDollars }} {{ $('High Value Check').item.json.currency }}</strong> for your <strong>{{ $('High Value Check').item.json.plan }}</strong> subscription.</p> <table style=\"background:#fff3f3;border-left:4px solid #c53030;padding:12px 16px;width:100%\"> <tr><td> <strong>Reason:</strong> {{ $('High Value Check').item.json.failureMessage }}<br> <strong>Failure Code:</strong> {{ $('High Value Check').item.json.failureCode }}<br> <strong>Attempt #:</strong> {{ $('High Value Check').item.json.attemptCount }} </td></tr> </table> <p>If you need help, reply to this email.</p> <p>Best regards,<br>The Billing Team</p> <p style=\"font-size:11px;color:#999\">Next retry scheduled: {{ $('High Value Check').item.json.nextRetryAt }}</p>",
"options": {},
"subject": "=Action Required: Payment of ${{ $('High Value Check').item.json.amountDollars }} Failed \u2014 {{ $('High Value Check').item.json.plan }} Plan"
},
"typeVersion": 2.2
},
{
"id": "7f3bf805-965b-436c-8983-ad02a26ad5f2",
"name": "Stripe Trigger",
"type": "n8n-nodes-base.stripeTrigger",
"position": [
544,
416
],
"parameters": {
"events": [
"charge.failed",
"invoice.payment_failed",
"payment_intent.payment_failed"
]
},
"typeVersion": 1
},
{
"id": "976316b0-f216-4e1b-b51f-5c07e97c3a17",
"name": "Create or update a contact",
"type": "n8n-nodes-base.hubspot",
"position": [
3536,
432
],
"parameters": {
"options": {},
"authentication": "appToken",
"additionalFields": {
"lastName": "={{ $('High Value Check').item.json.customerName.split(' ')[1] ?? '' }}",
"firstName": "={{ $('High Value Check').item.json.customerName.split(' ')[0] }}",
"companyName": "={{ $('High Value Check').item.json.plan }}"
}
},
"typeVersion": 2.2
},
{
"id": "10ecee41-157a-4d21-b4a4-49a92b60ae7f",
"name": "Sticky Note",
"type": "n8n-nodes-base.stickyNote",
"position": [
-128,
96
],
"parameters": {
"width": 480,
"height": 576,
"content": "## Automated Payment Failure Handling System \nThis workflow helps you handle failed payments automatically. Whenever a payment fails, the system collects all details about it. It then informs your team and creates a task to fix the issue. If the problem happens many times, it sends a stronger alert. It also saves all data for future tracking.\n\n### How it works\n\n\t\u2022\tIt detects when a payment fails.\n\t\u2022\tIt collects all important details like amount, customer, and reason.\n\t\u2022\tIt checks if the payment amount is big or small.\n\t\u2022\tIt sends a message to your team about the failure.\n\t\u2022\tIt creates a task so someone can take action.\n\t\u2022\tIt checks if the payment failed many times.\n\t\u2022\tIt sends a warning and email if the issue is serious and saves the data.\n\n### Setup Steps\n\n\t1.\tConnect your payment system.\n\t2.\tConnect your team messaging app.\n\t3.\tConnect your task management tool.\n\t4.\tConnect email and data storage (like sheets).\n\t5.\tTurn on the workflow."
},
"typeVersion": 1
},
{
"id": "b2eed5fb-6ee8-44cf-9eb6-ad904a68e011",
"name": "Sticky Note1",
"type": "n8n-nodes-base.stickyNote",
"position": [
384,
96
],
"parameters": {
"color": 7,
"width": 400,
"height": 576,
"content": "## Step 1: Detect Payment Failure\nThis step watches for any failed payment. Whenever a payment does not go through, it immediately catches that event. It acts like a trigger to start the whole process."
},
"typeVersion": 1
},
{
"id": "c641b97e-a2cf-4927-9480-d28007c0eec0",
"name": "Sticky Note2",
"type": "n8n-nodes-base.stickyNote",
"position": [
816,
96
],
"parameters": {
"color": 7,
"width": 400,
"height": 576,
"content": "## Step 2: Collect and Prepare Data\nThis step gathers all details about the failed payment. It collects customer name, email, amount, and reason for failure. It also prepares the data so it can be used easily in later steps."
},
"typeVersion": 1
},
{
"id": "59b9ac60-dae4-4ed4-98b6-bc57911c8c98",
"name": "Sticky Note3",
"type": "n8n-nodes-base.stickyNote",
"position": [
1248,
96
],
"parameters": {
"color": 7,
"width": 400,
"height": 576,
"content": "## Step 3: Check Payment Importance\nThis step checks how big the payment is. If the amount is large, it marks it as important. Based on this, it decides how serious the alert should be."
},
"typeVersion": 1
},
{
"id": "831eed20-6e9d-4d5e-a524-20529b1a2217",
"name": "Sticky Note4",
"type": "n8n-nodes-base.stickyNote",
"position": [
1680,
96
],
"parameters": {
"color": 7,
"width": 560,
"height": 576,
"content": "## Step 4: Send Alert and Create Task\nThis step sends a message to your team about the failure. If the issue is serious, it sends a stronger alert. It also creates a task so someone can fix the problem quickly."
},
"typeVersion": 1
},
{
"id": "764f0953-ba63-4c49-9ff5-1ed36f5bcee8",
"name": "Sticky Note5",
"type": "n8n-nodes-base.stickyNote",
"position": [
2272,
96
],
"parameters": {
"color": 7,
"width": 416,
"height": 576,
"content": "## Step 5: Check Repeated Failures\nThis step checks if the same payment has failed multiple times. If it happens again and again, it becomes more serious. It helps identify customers who need urgent attention."
},
"typeVersion": 1
},
{
"id": "27125c41-a024-4ec9-9477-604277a7f3d2",
"name": "Sticky Note6",
"type": "n8n-nodes-base.stickyNote",
"position": [
2720,
96
],
"parameters": {
"color": 7,
"width": 1024,
"height": 576,
"content": "## Step 6: Escalate, Inform Customer, and Save Data\nThis step sends a warning to the team for repeated failures. It also sends an email to the customer about the issue. Finally, it saves all details in a sheet for future tracking and updates customer records."
},
"typeVersion": 1
}
],
"connections": {
"Send a message": {
"main": [
[
{
"node": "Log to Google Sheets",
"type": "main",
"index": 0
}
]
]
},
"Stripe Trigger": {
"main": [
[
{
"node": "Parse & Enrich Payment Data",
"type": "main",
"index": 0
}
]
]
},
"High Value Check": {
"main": [
[
{
"node": "Slack \u2014 Critical Alert",
"type": "main",
"index": 0
}
],
[
{
"node": "Slack \u2014 Standard Alert",
"type": "main",
"index": 0
}
]
]
},
"Retry Count Check": {
"main": [
[
{
"node": "Slack \u2014 Escalation Alert",
"type": "main",
"index": 0
}
],
[
{
"node": "Send a message",
"type": "main",
"index": 0
}
]
]
},
"Log to Google Sheets": {
"main": [
[
{
"node": "Create or update a contact",
"type": "main",
"index": 0
}
]
]
},
"Slack \u2014 Critical Alert": {
"main": [
[
{
"node": "ClickUp \u2014 Create Recovery Task",
"type": "main",
"index": 0
}
]
]
},
"Slack \u2014 Standard Alert": {
"main": [
[
{
"node": "ClickUp \u2014 Create Recovery Task",
"type": "main",
"index": 0
}
]
]
},
"Slack \u2014 Escalation Alert": {
"main": [
[
{
"node": "Send a message",
"type": "main",
"index": 0
}
]
]
},
"Parse & Enrich Payment Data": {
"main": [
[
{
"node": "High Value Check",
"type": "main",
"index": 0
}
]
]
},
"ClickUp \u2014 Create Recovery Task": {
"main": [
[
{
"node": "Retry Count Check",
"type": "main",
"index": 0
}
]
]
}
}
}
For the full experience including quality scoring and batch install features for each workflow upgrade to Pro
About this workflow
This workflow automatically handles every failed Stripe payment by collecting all details, assessing severity, and taking immediate action — alerting your team, creating recovery tasks, escalating repeat failures, notifying the customer, and logging everything — without any…
Source: https://n8n.io/workflows/15873/ — original creator credit. Request a take-down →
Related workflows
Workflows that share integrations, category, or trigger type with this one. All free to copy and import.
This workflow automatically handles every resolved Jira bug by verifying the fix, notifying the customer, updating HubSpot, commenting on the Jira issue, alerting the team on Slack, and logging everyt
This workflow triggers when a new deal is created in HubSpot, sends a two-step follow-up sequence via Gmail, checks HubSpot for a recent email reply, then updates the deal stage, alerts a Slack channe
📘 Description
This workflow automates the tracking and follow-up process for pending payments. It pulls lead payment data from Google Sheets, checks whether the status is “Open,” and then routes actions accordingly
Categories: Payments, Project Operations, Client Onboarding