{
  "name": "Daily n8n Workflow Backup (Google Drive)",
  "tags": [],
  "nodes": [
    {
      "id": "sticky-main",
      "name": "Main Description",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -920,
        500
      ],
      "parameters": {
        "color": 2,
        "width": 380,
        "height": 460,
        "content": "## Daily n8n Workflow Backup\nAutomatically backs up all workflows to Google Drive daily.\n\n### How it works\n1. Creates a timestamped folder in Google Drive\n2. Fetches all workflows from n8n\n3. Converts workflows to JSON and uploads them\n4. Deletes backups older than 7 days\n\n### Setup steps\n1. Configure n8n API credentials\n2. Connect Google Drive OAuth2 account\n3. **Important:** Open the 'Cleanup Old Backups' node and paste your Parent Folder ID into the code.\n4. Adjust the Schedule Trigger (default: 11 PM daily)"
      },
      "typeVersion": 1
    },
    {
      "id": "sticky-section-1",
      "name": "Section 1",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -460,
        500
      ],
      "parameters": {
        "color": 7,
        "width": 680,
        "height": 500,
        "content": "## 1. Initialization\nStarts the schedule and creates the daily backup folder."
      },
      "typeVersion": 1
    },
    {
      "id": "sticky-section-2",
      "name": "Section 2",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        260,
        500
      ],
      "parameters": {
        "color": 7,
        "width": 860,
        "height": 500,
        "content": "## 2. Process & Upload\nLoops through workflows, converts to JSON, and saves to Drive."
      },
      "typeVersion": 1
    },
    {
      "id": "sticky-section-3",
      "name": "Section 3",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1160,
        500
      ],
      "parameters": {
        "color": 7,
        "width": 400,
        "height": 500,
        "content": "## 3. Maintenance\nDeletes backup folders older than 7 days."
      },
      "typeVersion": 1
    },
    {
      "id": "convert-json",
      "name": "Convert to JSON",
      "type": "n8n-nodes-base.convertToFile",
      "position": [
        560,
        640
      ],
      "parameters": {
        "options": {
          "fileName": "={{ $json.name }}.json"
        },
        "operation": "toJson"
      },
      "typeVersion": 1.1
    },
    {
      "id": "manual-trigger",
      "name": "When clicking \u2018Execute workflow\u2019",
      "type": "n8n-nodes-base.manualTrigger",
      "position": [
        -400,
        580
      ],
      "parameters": {},
      "typeVersion": 1
    },
    {
      "id": "create-folder",
      "name": "Create Backup Folder",
      "type": "n8n-nodes-base.googleDrive",
      "position": [
        -160,
        640
      ],
      "parameters": {
        "name": "=Workflow Backups {{ $now.format('yyyy-MM-dd') }}",
        "driveId": {
          "__rl": true,
          "mode": "list",
          "value": "My Drive"
        },
        "options": {},
        "folderId": {
          "__rl": true,
          "mode": "list",
          "value": "",
          "cachedResultUrl": "",
          "cachedResultName": "Select Folder in Drive Node"
        },
        "resource": "folder"
      },
      "credentials": {
        "googleDriveOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 3
    },
    {
      "id": "schedule-trigger",
      "name": "Schedule Trigger",
      "type": "n8n-nodes-base.scheduleTrigger",
      "position": [
        -400,
        720
      ],
      "parameters": {
        "rule": {
          "interval": [
            {
              "triggerAtHour": 23
            }
          ]
        }
      },
      "typeVersion": 1.2
    },
    {
      "id": "fetch-workflows",
      "name": "Fetch Workflows",
      "type": "n8n-nodes-base.n8n",
      "position": [
        40,
        640
      ],
      "parameters": {
        "filters": {},
        "requestOptions": {}
      },
      "credentials": {
        "n8nApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "loop-workflows",
      "name": "Loop Workflows",
      "type": "n8n-nodes-base.splitInBatches",
      "position": [
        320,
        640
      ],
      "parameters": {
        "options": {}
      },
      "typeVersion": 3
    },
    {
      "id": "upload-drive",
      "name": "Upload to Drive",
      "type": "n8n-nodes-base.googleDrive",
      "position": [
        820,
        700
      ],
      "parameters": {
        "name": "={{ $json.fileName }}",
        "driveId": {
          "__rl": true,
          "mode": "list",
          "value": "My Drive"
        },
        "options": {},
        "folderId": {
          "__rl": true,
          "mode": "id",
          "value": "={{ $('Create Backup Folder').item.json.id }}"
        }
      },
      "credentials": {
        "googleDriveOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 3
    },
    {
      "id": "cleanup-code",
      "name": "Cleanup Old Backups",
      "type": "n8n-nodes-base.code",
      "position": [
        1220,
        640
      ],
      "parameters": {
        "jsCode": "// CONFIGURATION: \n// 1. Paste the Folder ID where you want backups to live below.\n// 2. Ensure this ID matches the parent folder used in the 'Create Backup Folder' node.\n\nconst parentFolderId = 'PASTE_YOUR_GOOGLE_DRIVE_FOLDER_ID_HERE';\nconst daysToKeep = 7;\n\n// ----------------------------------------\n\ntry {\n  // List all folders in the backup directory\n  const options = {\n    qs: {\n      q: `'${parentFolderId}' in parents and mimeType='application/vnd.google-apps.folder' and name contains 'Workflow Backups'`,\n      fields: 'files(id,name,createdTime)'\n    }\n  };\n  \n  const response = await this.helpers.httpRequestWithAuthentication.call(\n    this,\n    'googleDriveOAuth2Api',\n    options\n  );\n  \n  const folders = response.files || [];\n  const cutoffDate = new Date();\n  cutoffDate.setDate(cutoffDate.getDate() - daysToKeep);\n  \n  const foldersToDelete = folders.filter(folder => {\n    const folderDate = new Date(folder.createdTime);\n    return folderDate < cutoffDate;\n  });\n  \n  console.log(`Found ${folders.length} backup folders, deleting ${foldersToDelete.length} old ones`);\n  \n  // Delete old folders\n  for (const folder of foldersToDelete) {\n    try {\n      await this.helpers.httpRequestWithAuthentication.call(\n        this,\n        'googleDriveOAuth2Api',\n        {\n          method: 'DELETE',\n          url: `https://www.googleapis.com/drive/v3/files/${folder.id}`\n        }\n      );\n      console.log(`Deleted folder: ${folder.name} (${folder.id})`);\n    } catch (error) {\n      console.error(`Failed to delete folder ${folder.id}:`, error.message);\n    }\n  }\n  \n  return [{ json: { deleted: foldersToDelete.length, remaining: folders.length - foldersToDelete.length } }];\n  \n} catch (error) {\n  console.error('Cleanup failed:', error.message);\n  return [{ json: { error: error.message, status: 'cleanup_failed' } }];\n}"
      },
      "credentials": {
        "googleDriveOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 2
    }
  ],
  "active": false,
  "settings": {
    "callerPolicy": "workflowsFromSameOwner",
    "executionOrder": "v1"
  },
  "connections": {
    "Loop Workflows": {
      "main": [
        [
          {
            "node": "Cleanup Old Backups",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Convert to JSON",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Convert to JSON": {
      "main": [
        [
          {
            "node": "Upload to Drive",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Fetch Workflows": {
      "main": [
        [
          {
            "node": "Loop Workflows",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Upload to Drive": {
      "main": [
        [
          {
            "node": "Loop Workflows",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Schedule Trigger": {
      "main": [
        [
          {
            "node": "Create Backup Folder",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Create Backup Folder": {
      "main": [
        [
          {
            "node": "Fetch Workflows",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "When clicking \u2018Execute workflow\u2019": {
      "main": [
        [
          {
            "node": "Create Backup Folder",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  }
}