{
  "id": "IgdFJTPyiQgcyuZ0",
  "meta": {
    "templateCredsSetupCompleted": true
  },
  "name": "Invoice Reminders Calendar",
  "tags": [],
  "nodes": [
    {
      "id": "12db8aa7-301c-48e9-b2b8-c4d6c4952a97",
      "name": "Workflow Description",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -2400,
        -96
      ],
      "parameters": {
        "width": 389,
        "height": 592,
        "content": "## \ud83d\udccb Stripe Invoice to Google Calendar Automation\n\nThis workflow automatically monitors Stripe invoices and creates Google Calendar reminders for invoices due within the next 7 days.\n\n### Key Features:\n- Daily scheduled execution at 8 AM\n- Fetches draft invoices from Stripe\n- Filters invoices due within 7 days\n- Creates calendar events only for new invoices\n- Prevents duplicate calendar entries\n\n### Prerequisites:\n- Stripe API credentials configured\n- Google Calendar OAuth2 credentials\n- Access to target Google Calendar\n\n### Use Case:\nPerfect for freelancers, agencies, or businesses that need automated invoice due date tracking and reminders."
      },
      "typeVersion": 1
    },
    {
      "id": "c4e5fef2-e9a0-407e-9c33-a7d30025daba",
      "name": "Schedule Setup",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -1872,
        -288
      ],
      "parameters": {
        "width": 300,
        "height": 320,
        "content": "## \u23f0 Daily Schedule Setup\n\nConfigured to run every day at 8:00 AM using cron expression `0 8 * * *`\n\n**Setup Instructions:**\n1. Adjust the cron expression if needed\n2. Consider your timezone settings\n3. Test with a shorter interval during setup\n\n**Cron Format:** `minute hour day month dayofweek`"
      },
      "typeVersion": 1
    },
    {
      "id": "58ec67ec-fb91-4c04-9cb9-da017afe3065",
      "name": "Schedule Trigger",
      "type": "n8n-nodes-base.scheduleTrigger",
      "position": [
        -1664,
        64
      ],
      "parameters": {
        "rule": {
          "interval": [
            {
              "field": "cronExpression",
              "expression": "0 8 * * *"
            }
          ]
        }
      },
      "typeVersion": 1.1
    },
    {
      "id": "8bfcbc60-3af3-4204-b631-d3adce6f7c3f",
      "name": "Stripe Setup Guide",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -2288,
        -592
      ],
      "parameters": {
        "width": 300,
        "height": 424,
        "content": "## \ud83d\udcb3 Stripe API Configuration\n\n**Setup Steps:**\n1. Go to n8n Credentials\n2. Add new Stripe API credential\n3. Enter your Stripe Secret Key\n4. Test the connection\n\n**Query Parameters:**\n- `status=draft`: Only fetch draft invoices\n- `limit=100`: Maximum 100 invoices per request\n"
      },
      "typeVersion": 1
    },
    {
      "id": "72b75afe-0fef-46a3-b999-da3ccf3b1691",
      "name": "Get Stripe Invoices",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        -1472,
        64
      ],
      "parameters": {
        "url": "https://api.stripe.com/v1/invoices",
        "options": {},
        "sendQuery": true,
        "sendHeaders": true,
        "authentication": "predefinedCredentialType",
        "queryParameters": {
          "parameters": [
            {
              "name": "status",
              "value": "draft"
            },
            {
              "name": "limit",
              "value": "100"
            }
          ]
        },
        "headerParameters": {
          "parameters": [
            {
              "name": "Content-Type",
              "value": "application/x-www-form-urlencoded"
            }
          ]
        },
        "nodeCredentialType": "stripeApi"
      },
      "credentials": {
        "stripeApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 4.1
    },
    {
      "id": "f6695758-d333-446e-8379-81096965ad30",
      "name": "Array Processing",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -1536,
        224
      ],
      "parameters": {
        "width": 280,
        "height": 376,
        "content": "## \ud83d\udccb Processing Invoice Array\n\nThe Stripe API returns invoices in a `data` array. This node splits the array so we can process each invoice individually.\n\n**What it does:**\n- Takes the `data` field from Stripe response\n- Creates separate items for each invoice\n- Enables individual processing downstream"
      },
      "typeVersion": 1
    },
    {
      "id": "a6aade30-8cbf-44dc-96b4-ead84be48371",
      "name": "Split Invoices",
      "type": "n8n-nodes-base.itemLists",
      "position": [
        -1248,
        64
      ],
      "parameters": {
        "options": {},
        "fieldToSplitOut": "data"
      },
      "typeVersion": 3
    },
    {
      "id": "0c63a347-c22e-45d3-a85d-8ce9c00a2569",
      "name": "Date Filter Logic",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -1184,
        -384
      ],
      "parameters": {
        "width": 280,
        "height": 416,
        "content": "## \ud83d\udd0d Invoice Due Date Filter\n\nFilters invoices based on due date criteria:\n\n**Conditions (ALL must be true):**\n1. Invoice has a due date\n2. Due within next 7 days\n3. Due date is today or later\n\n**Logic:**\n- Converts dates to Unix timestamps\n- Uses JavaScript expressions for calculations\n- Only passes invoices meeting all criteria"
      },
      "typeVersion": 1
    },
    {
      "id": "007ad07d-634c-4cc1-b8e0-ad6f1c77a6ca",
      "name": "Filter Due Invoices",
      "type": "n8n-nodes-base.if",
      "position": [
        -1040,
        64
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 1,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "has-due-date",
              "operator": {
                "type": "number",
                "operation": "exists",
                "singleValue": true
              },
              "leftValue": "={{ $json.due_date }}",
              "rightValue": ""
            },
            {
              "id": "due-within-7-days",
              "operator": {
                "type": "number",
                "operation": "lte"
              },
              "leftValue": "={{ $json.due_date }}",
              "rightValue": "={{ Math.floor((Date.now() + (7 * 24 * 60 * 60 * 1000)) / 1000) }}"
            },
            {
              "id": "due-after-today",
              "operator": {
                "type": "number",
                "operation": "gte"
              },
              "leftValue": "={{ $json.due_date }}",
              "rightValue": "={{ Math.floor(Date.now() / 1000) }}"
            }
          ]
        }
      },
      "typeVersion": 2
    },
    {
      "id": "3309ccc7-bdd4-4582-a584-6f702ca74f9f",
      "name": "Calendar API Setup",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -880,
        256
      ],
      "parameters": {
        "width": 300,
        "height": 352,
        "content": "## \ud83d\udcc5 Google Calendar Setup\n\n**Configuration Steps:**\n1. Create Google Calendar OAuth2 credentials\n2. Select your target calendar\n3. Set time range (next 30 days)\n\n**Purpose:**\nFetches existing calendar events to check for duplicate invoice reminders.\n\n\u26a0\ufe0f **Note:** Replace the calendar ID with your actual calendar email"
      },
      "typeVersion": 1
    },
    {
      "id": "07d2cba4-0897-4735-8c1d-5a9c9cb11006",
      "name": "Google Calendar Get Events",
      "type": "n8n-nodes-base.googleCalendar",
      "position": [
        -832,
        64
      ],
      "parameters": {
        "end": "={{ Math.floor((Date.now() + (30 * 24 * 60 * 60 * 1000)) / 1000) }}",
        "start": "={{ Math.floor(Date.now() / 1000) }}",
        "calendar": {
          "__rl": true,
          "mode": "list",
          "value": "user@example.com",
          "cachedResultName": "user@example.com"
        },
        "additionalFields": {}
      },
      "credentials": {
        "googleCalendarOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "30f03054-10a8-4683-9db8-158e1959f139",
      "name": "Duplicate Prevention",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -736,
        -368
      ],
      "parameters": {
        "width": 280,
        "height": 384,
        "content": "## \ud83d\udd04 Duplicate Detection\n\n**Logic:**\n1. Extracts invoice IDs from existing calendar events\n2. Looks for pattern `invoice_id:XXXXXX` in event descriptions\n3. Compares current invoice ID with existing ones\n\n**Fields Created:**\n- `existing_invoice_ids`: Array of found invoice IDs\n- `current_invoice_id`: Current invoice being processed"
      },
      "typeVersion": 1
    },
    {
      "id": "8b12c8ec-4252-4490-9a49-cba0c75f5b0d",
      "name": "Check Invoice Exists",
      "type": "n8n-nodes-base.set",
      "position": [
        -624,
        64
      ],
      "parameters": {
        "fields": {
          "values": [
            {
              "name": "existing_invoice_ids",
              "stringValue": "={{ $input.all().map(event => {\n  const description = event.json.description || '';\n  const match = description.match(/invoice_id:([^\\s\\n]+)/);\n  return match ? match[1] : null;\n}).filter(id => id !== null) }}"
            },
            {
              "name": "current_invoice_id",
              "stringValue": "={{ $('Filter Due Invoices').item.json.id }}"
            }
          ]
        },
        "options": {}
      },
      "typeVersion": 3.2
    },
    {
      "id": "c70a542d-d544-469e-8fd3-d29324727a45",
      "name": "New Invoice Check",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -432,
        224
      ],
      "parameters": {
        "width": 280,
        "height": 312,
        "content": "## \u2705 New Invoice Validation\n\n**Conditions (OR logic):**\n1. Invoice ID not found in existing events\n2. Current invoice ID exists and is valid\n\n**Result:**\nOnly new invoices (not already in calendar) will proceed to create calendar events."
      },
      "typeVersion": 1
    },
    {
      "id": "a9703708-0584-4daf-90b3-e23b5b27410a",
      "name": "IF Not Exists",
      "type": "n8n-nodes-base.if",
      "position": [
        -416,
        64
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 1,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "or",
          "conditions": [
            {
              "id": "invoice-not-exists",
              "operator": {
                "type": "boolean",
                "operation": "equal"
              },
              "leftValue": "={{ !$json.existing_invoice_ids.includes($json.current_invoice_id) }}",
              "rightValue": true
            },
            {
              "id": "8a1ef7b4-b24f-47ed-a9c6-bc5c0bd379c5",
              "operator": {
                "type": "string",
                "operation": "exists",
                "singleValue": true
              },
              "leftValue": "={{ $json.current_invoice_id }}",
              "rightValue": ""
            }
          ]
        }
      },
      "typeVersion": 2
    },
    {
      "id": "f7570c80-326a-4248-85ff-6730f80a1168",
      "name": "Calendar Event Setup",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -256,
        -352
      ],
      "parameters": {
        "width": 300,
        "height": 384,
        "content": "## \ud83d\udcc5 Create Calendar Reminder\n\n**Event Details:**\n- **Title:** \"Pending Invoice\"\n- **Start Time:** Invoice due date\n- **Duration:** 1 hour\n- **Description:** Includes invoice ID for tracking\n\n**Customization Ideas:**\n- Add customer name to title\n- Include invoice amount\n- Set custom reminder times\n- Add invoice URL to description"
      },
      "typeVersion": 1
    },
    {
      "id": "f57610fa-52d1-48f5-9a21-ac533ffcb1ac",
      "name": "Google Calendar Create Event",
      "type": "n8n-nodes-base.googleCalendar",
      "position": [
        -208,
        64
      ],
      "parameters": {
        "end": "={{ new Date(($('Filter Due Invoices').item.json.due_date * 1000) + (60 * 60 * 1000)).toISOString() }}",
        "start": "={{ new Date($('Filter Due Invoices').item.json.due_date * 1000).toISOString() }}",
        "calendar": {
          "__rl": true,
          "mode": "list",
          "value": "user@example.com",
          "cachedResultName": "user@example.com"
        },
        "additionalFields": {
          "summary": "Pending Invoice Due",
          "attendees": []
        }
      },
      "credentials": {
        "googleCalendarOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1
    }
  ],
  "active": false,
  "settings": {
    "executionOrder": "v1"
  },
  "versionId": "04d55a9b-fe45-4185-978c-18144d689b01",
  "connections": {
    "IF Not Exists": {
      "main": [
        [
          {
            "node": "Google Calendar Create Event",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Split Invoices": {
      "main": [
        [
          {
            "node": "Filter Due Invoices",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Schedule Trigger": {
      "main": [
        [
          {
            "node": "Get Stripe Invoices",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Filter Due Invoices": {
      "main": [
        [
          {
            "node": "Google Calendar Get Events",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Get Stripe Invoices": {
      "main": [
        [
          {
            "node": "Split Invoices",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Check Invoice Exists": {
      "main": [
        [
          {
            "node": "IF Not Exists",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Google Calendar Get Events": {
      "main": [
        [
          {
            "node": "Check Invoice Exists",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  }
}