{
  "name": "Send weekly payment reminders for overdue invoices with Gmail and Google Sheets",
  "nodes": [
    {
      "id": "9209c319-41a0-4b50-a40c-6a728f665afb",
      "name": "\ud83d\udccb Overview",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -500,
        -440
      ],
      "parameters": {
        "color": 7,
        "width": 420,
        "height": 660,
        "content": "## Send Weekly Invoice Payment Reminders\n\nAutomate your accounts receivable follow-up. Every Monday morning, this workflow reads your Google Sheets invoice tracker, identifies unpaid invoices overdue by more than 7 days, sends a personalized HTML payment reminder via Gmail to each client, and marks the invoice as chased \u2014 hands-free.\n\n### How it works\n\n1. **Every Monday 08:00** fires the workflow on a weekly schedule.\n2. **Configure** holds all user-facing settings (sheet URL, overdue threshold).\n3. **Read Invoice Sheet** fetches all rows from your invoice tracker.\n4. **Capture Row Index** assigns each row a unique index for the final update.\n5. **Filter Unpaid Invoices** keeps only entries with Status = Unpaid and no prior chase date.\n6. **Calculate Days Overdue** computes how many days have passed since the invoice date.\n7. **Filter Overdue 7+ Days** passes only invoices past the configured threshold.\n8. **Send Reminder Email** sends a formatted HTML payment reminder to the client's email.\n9. **Update Invoice Status** marks the row as Chased and sets today's chase date.\n\n### Setup\n\n1. Connect your **Google Sheets OAuth2** credential.\n2. Connect your **Gmail OAuth2** credential.\n3. In the **Configure** node, replace the `sheetUrl` value with your own Google Sheets URL.\n4. Ensure your sheet has columns: Client, Email, Amount, Invoice_Date, Status, Chase_Date.\n5. Activate the workflow.\n\n### Customization\n\n- Change the overdue threshold: update `overdueThreshold` in the **Configure** node.\n- Adjust the trigger day and time in the **Every Monday 08:00** node.\n- Edit the reminder email body in the **Send Reminder Email** node."
      },
      "typeVersion": 1
    },
    {
      "id": "d523135e-eb66-4893-a55c-a0a322b8274e",
      "name": "Trigger & Configure",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -60,
        -180
      ],
      "parameters": {
        "color": 1,
        "width": 460,
        "height": 480,
        "content": "## Trigger & Configure\n\nFires every Monday at 08:00. The Configure node holds all user-facing settings \u2014 update `sheetUrl` and `overdueThreshold` before activating."
      },
      "typeVersion": 1
    },
    {
      "id": "5dfdd87b-c662-485a-b491-8d3894068d3c",
      "name": "Read Data",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        428,
        -180
      ],
      "parameters": {
        "color": 1,
        "width": 420,
        "height": 480,
        "content": "## Read Data\n\nFetches all invoice rows from Google Sheets. Assigns each row a unique index for the final status update."
      },
      "typeVersion": 1
    },
    {
      "id": "62f6a266-c5dc-4bba-b2ce-e25c8b2291f0",
      "name": "Filter Overdue",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        876,
        -180
      ],
      "parameters": {
        "color": 1,
        "width": 660,
        "height": 480,
        "content": "## Filter Overdue\n\nKeeps only unpaid invoices not yet chased. Computes days overdue and passes entries past the configured threshold."
      },
      "typeVersion": 1
    },
    {
      "id": "69ee17f8-29ac-4478-b390-702faba05c7a",
      "name": "Notify & Update",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1548,
        -180
      ],
      "parameters": {
        "color": 1,
        "width": 660,
        "height": 480,
        "content": "## Notify & Update\n\nSends a personalized HTML payment reminder via Gmail to the client's email address. Updates the row in Google Sheets: Status to Chased, chase date to today."
      },
      "typeVersion": 1
    },
    {
      "id": "5f99d986-89a8-4bc9-b12f-2189093b646a",
      "name": "Every Monday 08:00",
      "type": "n8n-nodes-base.scheduleTrigger",
      "position": [
        0,
        0
      ],
      "parameters": {
        "rule": {
          "interval": [
            {
              "field": "cronExpression",
              "expression": "0 8 * * 1"
            }
          ]
        }
      },
      "typeVersion": 1.3
    },
    {
      "id": "51aada92-f2f9-44f0-b8b6-4dd17ec7a0f4",
      "name": "Configure",
      "type": "n8n-nodes-base.set",
      "position": [
        224,
        0
      ],
      "parameters": {
        "mode": "manual",
        "options": {},
        "assignments": {
          "assignments": [
            {
              "id": "cfg-sheet-url",
              "name": "sheetUrl",
              "type": "string",
              "value": "https://docs.google.com/spreadsheets/d/YOUR_SHEET_ID_HERE/edit"
            },
            {
              "id": "cfg-threshold",
              "name": "overdueThreshold",
              "type": "number",
              "value": 7
            }
          ]
        },
        "includeOtherFields": false
      },
      "typeVersion": 3.4
    },
    {
      "id": "fbbdb8cc-1c5c-4a6e-a148-30b4408dc8dd",
      "name": "Read Invoice Sheet",
      "type": "n8n-nodes-base.googleSheets",
      "position": [
        448,
        0
      ],
      "parameters": {
        "options": {},
        "resource": "sheet",
        "operation": "read",
        "sheetName": {
          "__rl": true,
          "mode": "id",
          "value": 0
        },
        "documentId": {
          "__rl": true,
          "mode": "url",
          "value": "={{ $('Configure').first().json.sheetUrl }}"
        }
      },
      "typeVersion": 4.7
    },
    {
      "id": "f2ae0213-5964-4f48-a14e-74181ea80347",
      "name": "Capture Row Index",
      "type": "n8n-nodes-base.set",
      "position": [
        672,
        0
      ],
      "parameters": {
        "mode": "manual",
        "options": {},
        "assignments": {
          "assignments": [
            {
              "id": "assign-row-number",
              "name": "row_number",
              "type": "number",
              "value": "={{ $itemIndex + 2 }}"
            }
          ]
        },
        "includeOtherFields": true
      },
      "typeVersion": 3.4
    },
    {
      "id": "e09a5ea4-35f8-4c13-a15f-47f22ca1f8a6",
      "name": "Filter Unpaid Invoices",
      "type": "n8n-nodes-base.filter",
      "position": [
        896,
        0
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 3,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "cond-statut",
              "operator": {
                "type": "string",
                "operation": "equals"
              },
              "leftValue": "={{ $json.Status }}",
              "rightValue": "Unpaid"
            },
            {
              "id": "cond-relance",
              "operator": {
                "type": "string",
                "operation": "empty",
                "singleValue": true
              },
              "leftValue": "={{ $json['Chase_Date'] }}",
              "rightValue": ""
            }
          ]
        }
      },
      "typeVersion": 2.3
    },
    {
      "id": "2f232b6d-a960-45d3-8e87-e22e3db9a654",
      "name": "Calculate Days Overdue",
      "type": "n8n-nodes-base.set",
      "position": [
        1120,
        0
      ],
      "parameters": {
        "mode": "manual",
        "options": {},
        "assignments": {
          "assignments": [
            {
              "id": "assign-retard",
              "name": "joursRetard",
              "type": "number",
              "value": "={{ Math.floor($now.diff(DateTime.fromFormat($json.Invoice_Date, 'dd/MM/yyyy'), 'days').days) }}"
            }
          ]
        },
        "includeOtherFields": true
      },
      "typeVersion": 3.4
    },
    {
      "id": "b9ca502e-0745-4071-bc9c-7e8986e414d3",
      "name": "Filter Overdue 7+ Days",
      "type": "n8n-nodes-base.filter",
      "position": [
        1344,
        0
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 3,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "loose"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "cond-retard",
              "operator": {
                "type": "number",
                "operation": "gt"
              },
              "leftValue": "={{ $json.joursRetard }}",
              "rightValue": "={{ $('Configure').first().json.overdueThreshold }}"
            }
          ]
        }
      },
      "typeVersion": 2.3
    },
    {
      "id": "6de52584-3429-4489-a78c-2baa389fe72d",
      "name": "Send Reminder Email",
      "type": "n8n-nodes-base.gmail",
      "position": [
        1568,
        0
      ],
      "parameters": {
        "sendTo": "={{ $json.Email }}",
        "message": "={{ \"<html><body style=\\\"font-family:Arial,sans-serif\\\"><p>Dear <strong>\" + $json.Client + \"</strong>,</p><p>This is a friendly reminder that the following invoice remains outstanding.</p><table border=\\\"1\\\" cellpadding=\\\"8\\\"><tr><td>Invoice date</td><td>\" + $json.Invoice_Date + \"</td></tr><tr><td>Amount due</td><td>\" + $json.Amount + \"</td></tr><tr><td>Days overdue</td><td>\" + $json.joursRetard + \" days</td></tr></table><p>Please arrange payment at your earliest convenience.</p><p>Best regards</p></body></html>\" }}",
        "options": {
          "appendAttribution": false
        },
        "subject": "={{ \"Payment reminder \u2014 Invoice dated \" + $json.Invoice_Date }}",
        "resource": "message",
        "emailType": "html",
        "operation": "send"
      },
      "typeVersion": 2.2
    },
    {
      "id": "29bf23cc-0c96-43f4-ae31-81b8459d0acd",
      "name": "Prepare Row Update",
      "type": "n8n-nodes-base.set",
      "position": [
        1792,
        0
      ],
      "parameters": {
        "mode": "manual",
        "options": {},
        "assignments": {
          "assignments": [
            {
              "id": "restore-row",
              "name": "row_number",
              "type": "number",
              "value": "={{ $('Filter Overdue 7+ Days').item.json.row_number }}"
            },
            {
              "id": "restore-client",
              "name": "Client",
              "type": "string",
              "value": "={{ $('Filter Overdue 7+ Days').item.json.Client }}"
            }
          ]
        }
      },
      "typeVersion": 3.4
    },
    {
      "id": "efe3881b-edd9-42fe-8168-e981ed3193ea",
      "name": "Update Invoice Status",
      "type": "n8n-nodes-base.googleSheets",
      "position": [
        2016,
        0
      ],
      "parameters": {
        "columns": {
          "value": {
            "Status": "Chased",
            "Chase_Date": "={{ $now.toFormat('dd/MM/yyyy') }}",
            "row_number": "={{ $json.row_number }}"
          },
          "mappingMode": "defineBelow",
          "matchingColumns": [
            "row_number"
          ]
        },
        "options": {},
        "resource": "sheet",
        "operation": "update",
        "sheetName": {
          "__rl": true,
          "mode": "id",
          "value": 0
        },
        "documentId": {
          "__rl": true,
          "mode": "url",
          "value": "={{ $('Configure').first().json.sheetUrl }}"
        }
      },
      "typeVersion": 4.7
    }
  ],
  "active": false,
  "settings": {
    "executionOrder": "v1"
  },
  "connections": {
    "Configure": {
      "main": [
        [
          {
            "node": "Read Invoice Sheet",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Capture Row Index": {
      "main": [
        [
          {
            "node": "Filter Unpaid Invoices",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Every Monday 08:00": {
      "main": [
        [
          {
            "node": "Configure",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Prepare Row Update": {
      "main": [
        [
          {
            "node": "Update Invoice Status",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Read Invoice Sheet": {
      "main": [
        [
          {
            "node": "Capture Row Index",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Send Reminder Email": {
      "main": [
        [
          {
            "node": "Prepare Row Update",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Calculate Days Overdue": {
      "main": [
        [
          {
            "node": "Filter Overdue 7+ Days",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Filter Overdue 7+ Days": {
      "main": [
        [
          {
            "node": "Send Reminder Email",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Filter Unpaid Invoices": {
      "main": [
        [
          {
            "node": "Calculate Days Overdue",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  },
  "description": "Every Monday, reads your Google Sheets invoice tracker, identifies clients with unpaid invoices past the configured overdue threshold, sends a personalized HTML payment reminder via Gmail, and marks the invoice as chased \u2014 fully hands-free."
}