{"id":7,"name":"YouTube to Raindrop","nodes":[{"name":"On clicking 'execute'","type":"n8n-nodes-base.manualTrigger","position":[-610,160],"parameters":{},"typeVersion":1,"id":"6cd88172-3b77-4ac1-a41b-251fae9fd48b","notes":"This manualTrigger node performs automated tasks as part of the workflow."},{"name":"YouTube","type":"n8n-nodes-base.youTube","position":[-440,240],"parameters":{"part":["snippet"],"options":{},"resource":"playlistItem","operation":"getAll","playlistId":"CHANGE_ME"},"credentials":{"youTubeOAuth2Api":"Google n8n"},"typeVersion":1,"id":"9cccacd5-5aee-422f-8712-0aa5fccb2400","notes":"This youTube node performs automated tasks as part of the workflow."},{"name":"Filter new items","type":"n8n-nodes-base.function","position":[-120,240],"parameters":{"functionCode":"const staticData = getWorkflowStaticData('global');\nconst newIds = items.map(item => item.json[\"resourceId\"][\"videoId\"]);\nconst oldIds = staticData.oldIds; \n\nif (!oldIds) {\n  staticData.oldIds = newIds;\n  return items;\n}\n\n\nconst actualNewIds = newIds.filter((id) => !oldIds.includes(id));\nconst actualNew = items.filter((data) => actualNewIds.includes(data.json[\"resourceId\"][\"videoId\"]));\nstaticData.oldIds = [...actualNewIds, ...oldIds];\n\nreturn actualNew;\n"},"typeVersion":1,"id":"3ffea276-4dc8-46d8-9596-4beb446f1df1","notes":"This function node performs automated tasks as part of the workflow."},{"name":"Flatten JSON","type":"n8n-nodes-base.functionItem","position":[-280,240],"parameters":{"functionCode":"item = item[\"snippet\"]\n\nreturn item;"},"typeVersion":1,"id":"459b921c-d004-413e-b112-8ba76caac1a7","notes":"This functionItem node performs automated tasks as part of the workflow."},{"name":"Raindrop Bookmark","type":"n8n-nodes-base.raindrop","position":[40,240],"parameters":{"link":"={{ $env.WEBHOOK_URL }}{{$json[\"resourceId\"][\"videoId\"]}}","resource":"bookmark","operation":"create","collectionId":0,"additionalFields":{"tags":"youtube","title":"={{$json[\"videoOwnerChannelTitle\"]}} | {{$json[\"title\"]}}"}},"credentials":{"raindropOAuth2Api":"Raindrop"},"typeVersion":1,"id":"61ae5210-2575-47cb-9a18-b308e9706f59","notes":"This raindrop node performs automated tasks as part of the workflow."},{"name":"Every 30 mins","type":"n8n-nodes-base.cron","position":[-610,320],"parameters":{"triggerTimes":{"item":[{"mode":"everyX","unit":"minutes","value":30}]}},"typeVersion":1,"id":"41962cf7-abbe-4d16-82ad-08071c3ba119","notes":"This cron node performs automated tasks as part of the workflow."},{"id":"error-dd3ffb64","name":"Error Handler","type":"n8n-nodes-base.stopAndError","typeVersion":1,"position":[1000,400],"parameters":{"message":"Workflow execution error","options":{}}}],"active":true,"settings":{"executionOrder":"v1","saveManualExecutions":true,"callerPolicy":"workflowsFromSameOwner","errorWorkflow":null,"timezone":"UTC","executionTimeout":3600,"maxExecutions":1000,"retryOnFail":true,"retryCount":3,"retryDelay":1000},"connections":{},"description":"Automated workflow: YouTube to Raindrop. This workflow processes data and performs automated tasks.","meta":{"instanceId":"workflow-fcd2ae00","versionId":"1.0.0","createdAt":"2025-09-29T07:07:45.080777","updatedAt":"2025-09-29T07:07:45.080790","owner":"n8n-user","license":"MIT","category":"automation","status":"active","priority":"high","environment":"production"},"notes":"Excellent quality workflow: YouTube to Raindrop. This workflow has been optimized for production use with comprehensive error handling, security, and documentation."}