{
  "id": "b465308b8c439b39",
  "name": "Recover failed Stripe payments with AI dunning emails in Gmail",
  "tags": [
    {
      "name": "dunning"
    },
    {
      "name": "payment-recovery"
    },
    {
      "name": "stripe"
    },
    {
      "name": "billing"
    },
    {
      "name": "gmail"
    },
    {
      "name": "google-sheets"
    },
    {
      "name": "openai"
    },
    {
      "name": "ai"
    }
  ],
  "nodes": [
    {
      "id": "5075a9f0-88c3-46b9-a9cf-a580d897e394",
      "name": "Sticky Note",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -640,
        -272
      ],
      "parameters": {
        "width": 480,
        "height": 672,
        "content": "## Recover failed Stripe payments with AI dunning emails in Gmail\n\n## How it works\n\n1. Triggers upon a failed Stripe payment event.\n2. Normalizes invoice data for processing.\n3. Uses AI to write a dunning email.\n4. Sends the dunning email via Gmail.\n5. Logs the email transaction to a Google Sheet.\n6. Checks if this is the final attempt to send dunning emails and escalates to the owner if needed.\n\n## Setup steps\n\n- [ ] Configure Stripe account to connect with the Stripe Trigger node.\n- [ ] Set up Gmail credentials for sending emails.\n- [ ] Ensure Google Sheets access for logging purposes.\n- [ ] Configure Slack credentials for message escalation.\n\n## Customization\n\nModify the AI model configuration in the Write Dunning Email node to adjust the tone or language of the emails."
      },
      "typeVersion": 1
    },
    {
      "id": "f53a9b77-f894-4a68-81aa-e134769df7cd",
      "name": "Sticky Note1",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -80,
        -128
      ],
      "parameters": {
        "color": 7,
        "width": 432,
        "height": 304,
        "content": "## Stripe trigger and normalization\n\nHandles the notification of failed payments and prepares data for email crafting."
      },
      "typeVersion": 1
    },
    {
      "id": "24c14d20-5096-4209-b705-7050cd1e6bca",
      "name": "Sticky Note2",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        400,
        -128
      ],
      "parameters": {
        "color": 7,
        "width": 448,
        "height": 496,
        "content": "## Generate and send dunning email\n\nUtilizes AI to draft a dunning email and sends it through Gmail."
      },
      "typeVersion": 1
    },
    {
      "id": "81b4d762-1ff8-455a-8d68-8a61e98041f2",
      "name": "Sticky Note3",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        896,
        -128
      ],
      "parameters": {
        "color": 7,
        "width": 432,
        "height": 304,
        "content": "## Log outcome and determine escalation\n\nLogs email dispatch to Google Sheets and checks if escalation to the owner is needed."
      },
      "typeVersion": 1
    },
    {
      "id": "9ebb929a-71a1-4f9e-9f95-2d8866d5cb5a",
      "name": "Sticky Note4",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1376,
        -272
      ],
      "parameters": {
        "color": 7,
        "width": 240,
        "height": 352,
        "content": "## Slack escalation notification\n\nEscalates the issue to the owner through Slack if needed."
      },
      "typeVersion": 1
    },
    {
      "id": "658e7f55-51ad-45da-8432-1f62e00c86a3",
      "name": "When Payment Fails (Stripe)",
      "type": "n8n-nodes-base.stripeTrigger",
      "position": [
        -40,
        0
      ],
      "parameters": {
        "events": [
          "invoice.payment_failed"
        ]
      },
      "typeVersion": 1
    },
    {
      "id": "dbbb6957-8df2-461c-bb22-4191ab1d1562",
      "name": "Prepare Invoice Data",
      "type": "n8n-nodes-base.set",
      "position": [
        200,
        0
      ],
      "parameters": {
        "options": {},
        "assignments": {
          "assignments": [
            {
              "id": "b739e774-79dc-4b10-a596-03f04dab8d2f",
              "name": "customer_email",
              "type": "string",
              "value": "={{ $json.body.data.object.customer_email }}"
            },
            {
              "id": "4c08c7d4-1b75-4bb4-a92e-4af92c5af01b",
              "name": "customer_name",
              "type": "string",
              "value": "={{ $json.body.data.object.customer_name || 'there' }}"
            },
            {
              "id": "6e07aa44-6e23-444d-b67a-2a9132bba556",
              "name": "amount_due",
              "type": "number",
              "value": "={{ ($json.body.data.object.amount_due || 0) / 100 }}"
            },
            {
              "id": "031f0ada-35c5-4b1d-bd73-9618e2c483da",
              "name": "currency",
              "type": "string",
              "value": "={{ ($json.body.data.object.currency || 'usd').toUpperCase() }}"
            },
            {
              "id": "649e97b4-52b3-4839-9e6b-71b88700c0d7",
              "name": "attempt",
              "type": "number",
              "value": "={{ $json.body.data.object.attempt_count || 1 }}"
            },
            {
              "id": "5cfa9898-1e03-4a98-aa1a-c68db0bec7f4",
              "name": "invoice_url",
              "type": "string",
              "value": "={{ $json.body.data.object.hosted_invoice_url }}"
            }
          ]
        }
      },
      "typeVersion": 3.4
    },
    {
      "id": "ee412f9d-633f-4917-8a6c-ac6286ca26e8",
      "name": "Draft Dunning Email",
      "type": "@n8n/n8n-nodes-langchain.chainLlm",
      "position": [
        440,
        0
      ],
      "parameters": {
        "text": "=You write polite-but-effective dunning (payment-recovery) emails. The tone ESCALATES with the attempt number: 1 = friendly reminder, 2 = firm, 3+ = final notice (mention service interruption, never threatening). Keep under 130 words, state the amount, include the pay link, and a clear CTA.\n\nCustomer: {{ $('Prepare Invoice Data').item.json.customer_name }}\nAmount due: {{ $('Prepare Invoice Data').item.json.amount_due }} {{ $('Prepare Invoice Data').item.json.currency }}\nAttempt #: {{ $('Prepare Invoice Data').item.json.attempt }}\nPay link: {{ $('Prepare Invoice Data').item.json.invoice_url }}",
        "promptType": "define",
        "hasOutputParser": true
      },
      "typeVersion": 1.5
    },
    {
      "id": "d93cc860-cc6b-4eba-a38e-0d6047a7ce15",
      "name": "OpenAI Dunning Model",
      "type": "@n8n/n8n-nodes-langchain.lmChatOpenAi",
      "position": [
        440,
        220
      ],
      "parameters": {
        "model": {
          "__rl": true,
          "mode": "list",
          "value": "gpt-4o-mini",
          "cachedResultName": "gpt-4o-mini"
        },
        "options": {
          "temperature": 0.4
        }
      },
      "typeVersion": 1.2
    },
    {
      "id": "ad5e7d85-44ef-41fc-8857-b21a76a5038a",
      "name": "Configure Dunning Output",
      "type": "@n8n/n8n-nodes-langchain.outputParserStructured",
      "position": [
        660,
        220
      ],
      "parameters": {
        "schemaType": "fromJson",
        "jsonSchemaExample": "{\n  \"subject\": \"Quick reminder: your invoice is past due\",\n  \"body\": \"Hi Alex, we couldn't process your payment of $49 for...\",\n  \"tone\": \"friendly\",\n  \"recommended_action\": \"retry_in_3_days\"\n}"
      },
      "typeVersion": 1.2
    },
    {
      "id": "fe320952-601e-479e-8aef-e6d68876546c",
      "name": "Send Email via Gmail",
      "type": "n8n-nodes-base.gmail",
      "position": [
        700,
        0
      ],
      "parameters": {
        "sendTo": "={{ $('Prepare Invoice Data').item.json.customer_email }}",
        "message": "={{ $json.output.body }}",
        "options": {},
        "subject": "={{ $json.output.subject }}"
      },
      "typeVersion": 2.1
    },
    {
      "id": "ec4ef7b4-df34-4b34-9c06-288b016323f9",
      "name": "Append to Dunning Sheet",
      "type": "n8n-nodes-base.googleSheets",
      "position": [
        940,
        0
      ],
      "parameters": {
        "sheet": {
          "__rl": true,
          "mode": "list",
          "value": "Dunning"
        },
        "columns": {
          "value": {},
          "mappingMode": "autoMapInputData"
        },
        "options": {},
        "operation": "append",
        "documentId": {
          "__rl": true,
          "mode": "url",
          "value": "https://docs.google.com/spreadsheets/d/REPLACE_ID/edit"
        }
      },
      "typeVersion": 4.5
    },
    {
      "id": "2bf97e94-e9b4-4c53-a03a-c30373ca9b80",
      "name": "If Final Attempt Reached",
      "type": "n8n-nodes-base.if",
      "position": [
        1180,
        0
      ],
      "parameters": {
        "conditions": {
          "options": {
            "typeValidation": "loose"
          },
          "combinator": "and",
          "conditions": [
            {
              "operator": {
                "type": "number",
                "operation": "gte"
              },
              "leftValue": "={{ $('Prepare Invoice Data').item.json.attempt }}",
              "rightValue": 3
            }
          ]
        }
      },
      "typeVersion": 2
    },
    {
      "id": "5f621d13-5b50-4ed8-a888-1d3ec094b7bd",
      "name": "Notify Owner on Slack",
      "type": "n8n-nodes-base.slack",
      "position": [
        1420,
        -80
      ],
      "parameters": {
        "text": "=:rotating_light: Final dunning attempt failed \u2014 {{ $('Prepare Invoice Data').item.json.customer_name }} ({{ $('Prepare Invoice Data').item.json.customer_email }}) owes {{ $('Prepare Invoice Data').item.json.amount_due }} {{ $('Prepare Invoice Data').item.json.currency }}. Consider pausing service / manual outreach.",
        "select": "channel",
        "resource": "message",
        "channelId": {
          "__rl": true,
          "mode": "name",
          "value": "#billing"
        },
        "operation": "post",
        "otherOptions": {}
      },
      "typeVersion": 2.2
    }
  ],
  "active": false,
  "settings": {
    "executionOrder": "v1"
  },
  "connections": {
    "Draft Dunning Email": {
      "main": [
        [
          {
            "node": "Send Email via Gmail",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "OpenAI Dunning Model": {
      "ai_languageModel": [
        [
          {
            "node": "Draft Dunning Email",
            "type": "ai_languageModel",
            "index": 0
          }
        ]
      ]
    },
    "Prepare Invoice Data": {
      "main": [
        [
          {
            "node": "Draft Dunning Email",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Send Email via Gmail": {
      "main": [
        [
          {
            "node": "Append to Dunning Sheet",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Append to Dunning Sheet": {
      "main": [
        [
          {
            "node": "If Final Attempt Reached",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Configure Dunning Output": {
      "ai_outputParser": [
        [
          {
            "node": "Draft Dunning Email",
            "type": "ai_outputParser",
            "index": 0
          }
        ]
      ]
    },
    "If Final Attempt Reached": {
      "main": [
        [
          {
            "node": "Notify Owner on Slack",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "When Payment Fails (Stripe)": {
      "main": [
        [
          {
            "node": "Prepare Invoice Data",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  }
}