Mijn Afvalwijzer + Todoist + n8n: Never Forget about Trash Collection

Written by

Jannick

Published on

BlogUncategorized

Recently, I started using Todoist for keeping my life organized. And then I thought: why not use it to manage trash pickup dates too? In the Netherlands, we have the handy Mijn Afvalwijzer website and API to access local waste collection schedules. By combining it with n8n, we can automatically add pickup reminders directly to Todoist.

Building the Workflow

Here’s how I built the n8n workflow to automatically add tasks for each upcoming trash pickup date:

Before you begin

  • Edit the HTTP Request node:
    • Replace [POSTAL CODE] and [HOUSE NUMBER] in the URL with your own information.
  • Set up Todoist credentials:
    • Ensure you have your Todoist account connected to your n8n instance.

Workflow Breakdown

  1. HTTP Request: This node fetches your local waste collection schedule from the Mijn Afvalwijzer API using your postal code and house number.
  2. Code node: This node processes the retrieved data, filters for upcoming pickup dates, seperates the upcoming pickup dates and formats the information for Todoist.
  3. Loop Over Items: This node loops over the items coming from the Code node.
  4. Todoist node: For each upcoming pickup date, this node creates a Todoist task with the type of waste and the collection date and time (set for 7:00 AM Amsterdam time, adjusted for daylight saving).

Here’s the n8n workflow code you can copy and paste:


{
  "meta": {
    "templateCredsSetupCompleted": true,
    "instanceId": "878af04124d283f36dc61c972e912acbfdba7f204bcdb86318e97038a57cbe46"
  },
  "nodes": [
    {
      "parameters": {
        "url": "https://api.mijnafvalwijzer.nl/webservices/appsinput/?apikey=5ef443e778f41c4f75c69459eea6e6ae0c2d92de729aa0fc61653815fbd6a8ca&method=postcodecheck&postcode=[POSTAL CODE]&street=&huisnummer=[HOUSE NUMBER]&toevoeging=&app_name=afvalwijzer&platform=web&afvaldata=2024-01-01&langs=nl&",
        "options": {
          "response": {
            "response": {
              "responseFormat": "json"
            }
          }
        }
      },
      "id": "395aaf09-b426-489d-9420-d600dd206074",
      "name": "HTTP Request",
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.2,
      "position": [
        1380,
        860
      ]
    },
    {
      "parameters": {
        "jsCode": "const today = new Date();\n\n// Function to check for daylight saving time\nconst isDaylightSavingTime = (date) => {\n  const year = date.getFullYear();\n  const dstStart = new Date(year, 2, 31);\n  const dstEnd = new Date(year, 9, 31);\n  \n  // Adjust start and end dates to the last Sunday of March and October\n  dstStart.setDate(dstStart.getDate() - dstStart.getDay());\n  dstEnd.setDate(dstEnd.getDate() - dstEnd.getDay());\n  \n  return date >= dstStart && date < dstEnd;\n};\n\nlet trashData;\ntry {\n  trashData = items[0].json.ophaaldagen.data;\n} catch (error) {\n  return [{ json: { message: 'Error in accessing data. Check path.' } }];\n}\n\nif (!trashData) {\n  return [{ json: { message: 'Data is missing or path is incorrect.' } }];\n}\n\n// Filter for upcoming trash collection dates\nconst upcomingTrash = trashData.filter(trash => {\n  const trashDate = new Date(trash.date);\n  return trashDate >= today;\n});\n\n// Create items for each upcoming collection\nreturn upcomingTrash.map(trash => {\n  const trashDate = new Date(trash.date);\n  \n  // Set time to 7:00 AM Amsterdam time\n  trashDate.setHours(7, 0, 0, 0);\n  \n  // Adjust for daylight saving time\n  const amsterdamOffsetMinutes = isDaylightSavingTime(trashDate) ? +120 : +60;\n  trashDate.setMinutes(trashDate.getMinutes() - amsterdamOffsetMinutes);\n  \n  const trashDateRFC3339 = trashDate.toISOString();\n  \n  return {\n    json: {\n      trashType: trash.type.charAt(0).toUpperCase() + trash.type.slice(1),\n      collectionDateRFC3339: trashDateRFC3339\n    }\n  };\n});"
      },
      "id": "fc84485b-cd7f-41b4-a7de-605bec4aa610",
      "name": "Code1",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        1620,
        1200
      ]
    },
    {
      "parameters": {
        "options": {}
      },
      "id": "4a7c4ccc-f877-429c-be14-13fe00f7c8f7",
      "name": "Loop Over Items",
      "type": "n8n-nodes-base.splitInBatches",
      "typeVersion": 3,
      "position": [
        1840,
        1200
      ]
    },
    {
      "parameters": {
        "authentication": "oAuth2",
        "project": {
          "__rl": true,
          "value": "2332022907",
          "mode": "list",
          "cachedResultName": "Privé 🏡"
        },
        "content": "={{ $json.trashType }} bij de weg zetten ",
        "options": {
          "dueDateTime": "={{ $json.collectionDateRFC3339 }}",
          "section": "154195286"
        }
      },
      "id": "7fd2a5a9-be3b-42fe-a977-21005781cf89",
      "name": "Todoist1",
      "type": "n8n-nodes-base.todoist",
      "typeVersion": 2,
      "position": [
        2100,
        1260
      ],
      "credentials": {
        "todoistOAuth2Api": {
          "id": "jN4JGEBQmDkXjXWr",
          "name": "Todoist"
        }
      }
    },
    {
      "parameters": {},
      "id": "ff0eb3ce-4165-435c-a58d-12c5b08070c3",
      "name": "When clicking \"Test workflow\"",
      "type": "n8n-nodes-base.manualTrigger",
      "typeVersion": 1,
      "position": [
        1180,
        860
      ]
    }
  ],
  "connections": {
    "HTTP Request": {
      "main": [
        [
          {
            "node": "Code1",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Code1": {
      "main": [
        [
          {
            "node": "Loop Over Items",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Loop Over Items": {
      "main": [
        null,
        [
          {
            "node": "Todoist1",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Todoist1": {
      "main": [
        [
          {
            "node": "Loop Over Items",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "When clicking \"Test workflow\"": {
      "main": [
        [
          {
            "node": "HTTP Request",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  },
  "pinData": {}
}