{ "id": "VLRbAr4OrtnHUU2l", "name": "Todoist Weekly Review Template", "tags": [], "nodes": [ { "id": "45351dbb-6c0c-4442-a350-35d966a26fa1", "name": "When clicking ‘Test workflow’", "type": "n8n-nodes-base.manualTrigger", "position": [ 0, 180 ], "parameters": {}, "typeVersion": 1 }, { "id": "9644a07e-0b97-4b48-846c-821f620128cc", "name": "Get completed tasks via Todoist API", "type": "n8n-nodes-base.httpRequest", "position": [ 220, 0 ], "parameters": { "url": "https://api.todoist.com/sync/v9/completed/get_all", "method": "POST", "options": {}, "sendBody": true, "authentication": "predefinedCredentialType", "bodyParameters": { "parameters": [ { "name": "since", "value": "={{ $now.minus(7, 'days') }}" }, { "name": "until", "value": "={{ $now }}" } ] }, "nodeCredentialType": "todoistApi" }, "credentials": { "todoistApi": {} }, "typeVersion": 4.2 }, { "id": "94f40824-43ff-45ae-adfd-b18a5903cba1", "name": "Optional: Ignore specific projects", "type": "n8n-nodes-base.code", "position": [ 440, 0 ], "parameters": { "jsCode": "// maintain this array with ignored Todoist project_id's\n// empty \"[]\" it when you don't want to ignore any\nconst ignoredProjects = ['2335544024'];\n\n// Remove ignored projects\nconst items = $input.all()[0].json.items;\nvar newItems = [];\nfor(j = 0; j < items.length; j++) {\n if(!ignoredProjects.includes(items[j].project_id)) {\n newItems.push(items[j]);\n }\n}\n\nreturn newItems;" }, "typeVersion": 2 }, { "id": "c50b00d6-4e9c-43e5-b6b8-ee0caac78c68", "name": "Format the email body", "type": "n8n-nodes-base.code", "position": [ 660, 0 ], "parameters": { "jsCode": "const items = $input.all();\n\n// Group items by day\nconst grouped = items.reduce((acc, item) => {\n const date = new Date(item.json.completed_at).toISOString().split('T')[0];\n acc[date] = acc[date] || [];\n acc[date].push(item.json.content);\n return acc;\n}, {});\n\n// Format the grouped data into an HTML string for the email\nlet emailBody = \"