{
  "name": "Spotify to YouTube playlist synchronization",
  "nodes": [
    {
      "id": "c9e46f43-b159-42ca-945d-7aa8546e5fa2",
      "name": "Get playlist snapshot",
      "type": "n8n-nodes-base.spotify",
      "position": [
        380,
        1580
      ]
    },
    {
      "id": "73c2303e-24c2-4026-95f6-825e5d08baa4",
      "name": "Get playlist snapshot1",
      "type": "n8n-nodes-base.spotify",
      "position": [
        720,
        1580
      ]
    },
    {
      "id": "bb71003b-0945-4333-91d3-662290dfb42d",
      "name": "If different snapshot",
      "type": "n8n-nodes-base.if",
      "position": [
        900,
        1580
      ]
    },
    {
      "id": "4894d2a7-dda9-430f-849a-d2368daa0aab",
      "name": "Get all musics",
      "type": "n8n-nodes-base.supabase",
      "position": [
        1220,
        1600
      ]
    },
    {
      "id": "e854147b-a5fa-400d-8440-bda25a0226b2",
      "name": "Update to_delete to true",
      "type": "n8n-nodes-base.supabase",
      "position": [
        1700,
        1620
      ]
    },
    {
      "id": "2425db39-487b-4b61-9b61-9ae00067bbca",
      "name": "Add music",
      "type": "n8n-nodes-base.supabase",
      "position": [
        1700,
        1400
      ]
    },
    {
      "id": "1c28ae15-9049-4ac7-9a7f-dcd094a60ace",
      "name": "Compare Datasets",
      "type": "n8n-nodes-base.compareDatasets",
      "position": [
        1460,
        1540
      ]
    },
    {
      "id": "af89d454-1071-42c1-9455-d64e02ae14b7",
      "name": "Spotify",
      "type": "n8n-nodes-base.spotify",
      "position": [
        1220,
        1440
      ]
    },
    {
      "id": "b924ad92-b1f2-41d5-b662-1e64ad0cc6dc",
      "name": "No Operation, do nothing",
      "type": "n8n-nodes-base.noOp",
      "position": [
        1220,
        1800
      ]
    },
    {
      "id": "2665982e-68ac-4a83-988d-78d07a0d6c75",
      "name": "Get all musics not in youtube playlist",
      "type": "n8n-nodes-base.supabase",
      "position": [
        400,
        960
      ]
    },
    {
      "id": "6ea4ae11-9889-4ae2-904f-614ca4118b8a",
      "name": "Every day at noon",
      "type": "n8n-nodes-base.scheduleTrigger",
      "position": [
        20,
        1220
      ]
    },
    {
      "id": "8e4b14f4-a7ec-45dd-9b24-8c86889fd135",
      "name": "Every day at noon + 1mn",
      "type": "n8n-nodes-base.scheduleTrigger",
      "position": [
        20,
        960
      ]
    },
    {
      "id": "16242250-5f3f-49f9-b6cb-7302bc11765a",
      "name": "Every hour",
      "type": "n8n-nodes-base.scheduleTrigger",
      "position": [
        20,
        1580
      ]
    },
    {
      "id": "6b6784ce-e236-40ca-b85c-1b0f0abdd7a5",
      "name": "Wait 1 hour",
      "type": "n8n-nodes-base.wait",
      "position": [
        560,
        1580
      ]
    },
    {
      "id": "746e7e33-00ba-4e92-a877-3619e14fa718",
      "name": "variables",
      "type": "n8n-nodes-base.set",
      "position": [
        200,
        1580
      ]
    },
    {
      "id": "0006e12a-fea6-408d-bcf5-6d0a726322b1",
      "name": "Search video",
      "type": "n8n-nodes-base.youTube",
      "position": [
        2500,
        1420
      ]
    },
    {
      "id": "24f5a360-fa93-4942-baea-baf134dd40a3",
      "name": "Get video duration",
      "type": "n8n-nodes-base.youTube",
      "position": [
        3020,
        1420
      ]
    },
    {
      "id": "2027d659-01d6-4dd0-bfdc-c92f65b021bc",
      "name": "Loop Over Items",
      "type": "n8n-nodes-base.splitInBatches",
      "position": [
        2840,
        1420
      ]
    },
    {
      "id": "3e843f70-bc17-4749-86ba-11f5a0e98e7d",
      "name": "If video duration ~= music duration",
      "type": "n8n-nodes-base.if",
      "position": [
        3240,
        1420
      ]
    },
    {
      "id": "a21e462c-72c9-4e77-99dc-1046acbaa998",
      "name": "Add music to playlist",
      "type": "n8n-nodes-base.youTube",
      "position": [
        3460,
        1400
      ]
    },
    {
      "id": "68fc1180-ce51-496a-909f-a652bb43febc",
      "name": "Add youtube id to row",
      "type": "n8n-nodes-base.supabase",
      "position": [
        3640,
        1400
      ]
    },
    {
      "id": "3611f50e-3000-46e9-b145-109251c3a12d",
      "name": "Discord",
      "type": "n8n-nodes-base.discord",
      "position": [
        4040,
        1400
      ]
    },
    {
      "id": "bd6438b2-8628-4bb9-be34-03785458f194",
      "name": "Discord1",
      "type": "n8n-nodes-base.discord",
      "position": [
        4040,
        1020
      ]
    },
    {
      "id": "97ea9e76-96a5-48de-afe3-f81dbe7e431b",
      "name": "Set youtube id to NOTFOUND if no matching",
      "type": "n8n-nodes-base.supabase",
      "position": [
        3320,
        1020
      ]
    },
    {
      "id": "acb1e31e-5f17-4092-b357-b0b255a4d15f",
      "name": "Aggregate",
      "type": "n8n-nodes-base.aggregate",
      "position": [
        3060,
        1220
      ]
    },
    {
      "id": "2db8c163-bf26-445f-9339-9e387cf22286",
      "name": "If no result",
      "type": "n8n-nodes-base.if",
      "position": [
        2660,
        1420
      ]
    },
    {
      "id": "5eea12d7-c313-4176-b85a-54f631e3a98f",
      "name": "data",
      "type": "n8n-nodes-base.set",
      "position": [
        1900,
        1340
      ]
    },
    {
      "id": "73055f49-c804-4b54-a16f-c795f1295069",
      "name": "variables2",
      "type": "n8n-nodes-base.set",
      "position": [
        560,
        1220
      ]
    },
    {
      "id": "4f7da7fb-5b18-4b44-9aad-d24c2e1409cc",
      "name": "variables1",
      "type": "n8n-nodes-base.set",
      "position": [
        200,
        960
      ]
    },
    {
      "id": "a814763e-d073-4984-986f-7c627bbe2269",
      "name": "Loop Over Items1",
      "type": "n8n-nodes-base.splitInBatches",
      "position": [
        2120,
        1400
      ]
    },
    {
      "id": "5329c838-56bd-4d85-a789-7ded3a128d87",
      "name": "data1",
      "type": "n8n-nodes-base.set",
      "position": [
        2320,
        1420
      ]
    },
    {
      "id": "01039cab-f822-4cfc-996f-0e88923f9c14",
      "name": "Get playlist items",
      "type": "n8n-nodes-base.youTube",
      "position": [
        540,
        2600
      ]
    },
    {
      "id": "c12fb59f-ad15-4456-b827-f749a22f2f0c",
      "name": "Playlist items to be deleted",
      "type": "n8n-nodes-base.compareDatasets",
      "position": [
        840,
        2700
      ]
    },
    {
      "id": "57172162-a766-4c51-8249-e6e0632d1312",
      "name": "Get all musics that should be in playlist",
      "type": "n8n-nodes-base.supabase",
      "position": [
        540,
        2400
      ]
    },
    {
      "id": "88f01cff-33a2-4184-af92-80cf7dd6d28b",
      "name": "Remove Duplicates",
      "type": "n8n-nodes-base.removeDuplicates",
      "position": [
        1080,
        2700
      ]
    },
    {
      "id": "e25d78cd-d3a9-4b24-8663-84344b6f0b68",
      "name": "Remove video from playlist",
      "type": "n8n-nodes-base.youTube",
      "position": [
        1240,
        2700
      ]
    },
    {
      "id": "1420795b-fac4-47ac-8449-96ae39541c22",
      "name": "Check for deleted videos",
      "type": "n8n-nodes-base.compareDatasets",
      "position": [
        820,
        2480
      ]
    },
    {
      "id": "fc2e2908-c491-4d45-87e4-a572a2f3e72a",
      "name": "Set youtube_video_id to null",
      "type": "n8n-nodes-base.supabase",
      "position": [
        1080,
        2440
      ]
    },
    {
      "id": "52523569-4347-477f-abe3-718b0177324a",
      "name": "Get all musics to be deleted",
      "type": "n8n-nodes-base.supabase",
      "position": [
        540,
        2820
      ]
    },
    {
      "id": "c1306c1e-07aa-46f9-970c-3e9ecb01638a",
      "name": "Delete music",
      "type": "n8n-nodes-base.supabase",
      "position": [
        1400,
        2700
      ]
    },
    {
      "id": "770083fa-6ac1-4dd9-929e-e30e933bbd95",
      "name": "Every day at midnight",
      "type": "n8n-nodes-base.scheduleTrigger",
      "position": [
        40,
        2620
      ]
    },
    {
      "id": "92e5e851-0c66-476e-bec8-a46fc96915ab",
      "name": "variables3",
      "type": "n8n-nodes-base.set",
      "position": [
        240,
        2620
      ]
    },
    {
      "id": "acde16fc-3fe3-453b-bffe-ead681e97046",
      "name": "Reset NOTFOUND id to NULL",
      "type": "n8n-nodes-base.supabase",
      "position": [
        420,
        3280
      ]
    },
    {
      "id": "62053829-3253-4a7c-b70f-ba6075df034b",
      "name": "variables4",
      "type": "n8n-nodes-base.set",
      "position": [
        220,
        3280
      ]
    },
    {
      "id": "9a205a87-f32a-49c1-8282-469777c83c9c",
      "name": "Every month",
      "type": "n8n-nodes-base.scheduleTrigger",
      "position": [
        40,
        3280
      ]
    },
    {
      "id": "a40fa87c-71ae-4045-8285-91235f0cf1f0",
      "name": "Sticky Note",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        2040,
        780
      ],
      "parameters": {
        "width": 1780,
        "height": 980,
        "content": "# Match Spotify Tracks to YouTube Videos  \n\n## This part finds the best YouTube video for a Spotify track using the YouTube Data API v3. It searches with the track title and artist, retrieves the top "
      }
    },
    {
      "id": "b850a168-7fa4-417c-980c-da8fcf558cfb",
      "name": "Sticky Note1",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -20,
        1440
      ],
      "parameters": {
        "width": 1100,
        "height": 420,
        "content": "## Check for any modification in the spotify playlist with snapshot_id\n### If you want to change the checking interval, make sure to change the trigger AND the wait node\n"
      }
    },
    {
      "id": "fe2aaa9f-e4de-4000-b535-3e351a643d01",
      "name": "Sticky Note2",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -1360,
        1120
      ],
      "parameters": {
        "width": 960,
        "height": 1340,
        "content": "# Spotify to YouTube Playlist Synchronization\n## A workflow that maintains a YouTube playlist in sync with a Spotify playlist, featuring smart video matching and persistent synchronization.\n\n## Key Fe"
      }
    },
    {
      "id": "a86748bf-e52a-4d14-b940-d66a62de802e",
      "name": "Sticky Note3",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1100,
        700
      ],
      "parameters": {
        "width": 920,
        "height": 1260,
        "content": "# Spotify-Database Synchronization\n\n## Operation:\n- ## Compares Spotify playlist tracks against database entries\n- ## Adds missing tracks to database\n- ## Marks database entries for deletion when remo"
      }
    },
    {
      "id": "c58d3233-7059-4095-bae7-c0b451748c2f",
      "name": "Sticky Note4",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -20,
        620
      ],
      "parameters": {
        "width": 800,
        "height": 800,
        "content": "# Daily Force Check\n\n## Forces daily comparison between Spotify playlist and database state, bypassing playlist modification checks. Essential for:\n- ## Initial setup of large playlists (manages YouTu"
      }
    },
    {
      "id": "cfea38bb-d8b2-48aa-9718-e5d2d36f52c7",
      "name": "Sticky Note5",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        3840,
        780
      ],
      "parameters": {
        "width": 460,
        "height": 980,
        "content": "## Optional notifications (you can use the chat of your choice)\n"
      }
    },
    {
      "id": "fb6fa7af-a434-463a-a2d7-e78d0328033c",
      "name": "Sticky Note7",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -40,
        120
      ],
      "parameters": {
        "width": 4400,
        "height": 1880,
        "content": "# Workflow 1: Main Sync Process\n# 1. **Change Detection**\n   - ## Monitors Spotify playlist for changes\n   - ## Compares database state with current playlist\n\n# 2. **Video Matching**\n   - ## Searches "
      }
    },
    {
      "id": "03e20125-37c8-4e40-98fd-9b4617eaab70",
      "name": "Sticky Note8",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -40,
        2200
      ],
      "parameters": {
        "width": 1740,
        "height": 800,
        "content": "# Workflow 2: YouTube Maintenance\n- ## Monitors YouTube playlist for removed videos\n- ## Flags removed videos for re-search\n- ## Handles deletion of marked videos\n"
      }
    },
    {
      "id": "031c2984-96b1-4c60-9e24-a125619b204a",
      "name": "Sticky Note6",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -40,
        3080
      ],
      "parameters": {
        "width": 760,
        "height": 360,
        "content": "# Workflow 3: Recovery Process\n- ## Clears \"NOTFOUND\" flags periodically to re-search previously unmatched tracks"
      }
    }
  ],
  "connections": {
    "data": {
      "main": [
        [
          {
            "node": "Loop Over Items1",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "data1": {
      "main": [
        [
          {
            "node": "Search video",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Spotify": {
      "main": [
        [
          {
            "node": "Compare Datasets",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Add music": {
      "main": [
        [
          {
            "node": "data",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Aggregate": {
      "main": [
        [
          {
            "node": "Set youtube id to NOTFOUND if no matching",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "variables": {
      "main": [
        [
          {
            "node": "Get playlist snapshot",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Every hour": {
      "main": [
        [
          {
            "node": "variables",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "variables1": {
      "main": [
        [
          {
            "node": "Get all musics not in youtube playlist",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "variables2": {
      "main": [
        [
          {
            "node": "Spotify",
            "type": "main",
            "index": 0
          },
          {
            "node": "Get all musics",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "variables3": {
      "main": [
        [
          {
            "node": "Get all musics that should be in playlist",
            "type": "main",
            "index": 0
          },
          {
            "node": "Get playlist items",
            "type": "main",
            "index": 0
          },
          {
            "node": "Get all musics to be deleted",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "variables4": {
      "main": [
        [
          {
            "node": "Reset NOTFOUND id to NULL",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Every month": {
      "main": [
        [
          {
            "node": "variables4",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Wait 1 hour": {
      "main": [
        [
          {
            "node": "Get playlist snapshot1",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "If no result": {
      "main": [
        [
          {
            "node": "Aggregate",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Loop Over Items",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Search video": {
      "main": [
        [
          {
            "node": "If no result",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Get all musics": {
      "main": [
        [
          {
            "node": "Compare Datasets",
            "type": "main",
            "index": 1
          }
        ]
      ]
    },
    "Loop Over Items": {
      "main": [
        [
          {
            "node": "Aggregate",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Get video duration",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Compare Datasets": {
      "main": [
        [
          {
            "node": "Add music",
            "type": "main",
            "index": 0
          }
        ],
        [],
        [],
        [
          {
            "node": "Update to_delete to true",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Loop Over Items1": {
      "main": [
        [],
        [
          {
            "node": "data1",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Every day at noon": {
      "main": [
        [
          {
            "node": "variables2",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Remove Duplicates": {
      "main": [
        [
          {
            "node": "Remove video from playlist",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Get playlist items": {
      "main": [
        [
          {
            "node": "Playlist items to be deleted",
            "type": "main",
            "index": 0
          },
          {
            "node": "Check for deleted videos",
            "type": "main",
            "index": 1
          }
        ]
      ]
    },
    "Get video duration": {
      "main": [
        [
          {
            "node": "If video duration ~= music duration",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Add music to playlist": {
      "main": [
        [
          {
            "node": "Add youtube id to row",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Add youtube id to row": {
      "main": [
        [
          {
            "node": "Loop Over Items1",
            "type": "main",
            "index": 0
          },
          {
            "node": "Discord",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Every day at midnight": {
      "main": [
        [
          {
            "node": "variables3",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Get playlist snapshot": {
      "main": [
        [
          {
            "node": "Wait 1 hour",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "If different snapshot": {
      "main": [
        [
          {
            "node": "Spotify",
            "type": "main",
            "index": 0
          },
          {
            "node": "Get all musics",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "No Operation, do nothing",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Get playlist snapshot1": {
      "main": [
        [
          {
            "node": "If different snapshot",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Every day at noon + 1mn": {
      "main": [
        [
          {
            "node": "variables1",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Check for deleted videos": {
      "main": [
        [
          {
            "node": "Set youtube_video_id to null",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Remove video from playlist": {
      "main": [
        [
          {
            "node": "Delete music",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Get all musics to be deleted": {
      "main": [
        [
          {
            "node": "Playlist items to be deleted",
            "type": "main",
            "index": 1
          }
        ]
      ]
    },
    "Playlist items to be deleted": {
      "main": [
        [],
        [],
        [
          {
            "node": "Remove Duplicates",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "If video duration ~= music duration": {
      "main": [
        [
          {
            "node": "Add music to playlist",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Loop Over Items",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Get all musics not in youtube playlist": {
      "main": [
        [
          {
            "node": "data",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Get all musics that should be in playlist": {
      "main": [
        [
          {
            "node": "Check for deleted videos",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Set youtube id to NOTFOUND if no matching": {
      "main": [
        [
          {
            "node": "Loop Over Items1",
            "type": "main",
            "index": 0
          },
          {
            "node": "Discord1",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  }
}