How to change Todoist task project when task is updated using Flow

5 min read

Requirement

You need to make automation so when you’ll set a date for any Todoist task it will be moved to special project called “Planned”.

Sounds like piece a cake so you decide to achieve it quick and simple using workflow software like Zapier, IFTTT or Microsoft Flow.

But if something looks easy it means that it will be not, right?

Problems

Actually there are 3 of them.

  1. There is no trigger “Todoist – when a task is updated”. Neither in Zapier, IFTTT or MS Flow.
  2. If you want to check if JSON contains some property (i.e. Date field) and/or JSON property is not empty there is no easy to use function in Zapier or IFTTT
  3. There is no action (block) that allows you to change todoist task project. Neither in Zapier, IFTTT or MS Flow.

Solution

In order to provide full solution we need to resolve all of above issues.

How to make flow “on Todoist task updated”

This won’t be big problem since we can gather HTTP requests/Catch Webhooks in any of mentioned automation framework. 

Webhook in Zapier requires JSON to provide
Webhook in IFTTT requires only Name. URL is shown in webhook settings…which are very hidden. Try this link if you have similar problem as I do. Cool thing – no JSON scheme is required!
Webhook in Flow need JSON as well as Zapier does.

Pick the one that fits you most. I’ve chosen Flow since this is only automation tool that will handle next issue. 

Oh, and if pick Zapier or Flow you will need JSON schema. There is example JSON in Todoist documentation for webhooks so the only thing left is to get schema out of it (manually if you’re masochist OR use any of free tools available on web OR “use sample payload to generate schema” available in Flow). I put mine below so you can also use it. 

{
    "type": "object",
    "properties": {
        "event_name": {
            "type": "string"
        },
        "user_id": {
            "type": "number"
        },
        "event_data": {
            "type": "object",
            "properties": {
                "day_order": {
                    "type": "number"
                },
                "assigned_by_uid": {
                    "type": "number"
                },
                "is_archived": {
                    "type": "number"
                },
                "labels": {
                    "type": "array"
                },
                "sync_id": {
                    "type": "object"
                },
                "in_history": {
                    "type": "number"
                },
                "has_notifications": {
                    "type": "number"
                },
                "indent": {
                    "type": "number"
                },
                "checked": {
                    "type": "number"
                },
                "date_added": {
                    "type": "string"
                },
                "id": {
                    "type": "number"
                },
                "content": {
                    "type": "string"
                },
                "user_id": {
                    "type": "number"
                },
                "due_date_utc": {
                    "type": "object"
                },
                "children": {
                    "type": "object"
                },
                "priority": {
                    "type": "number"
                },
                "item_order": {
                    "type": "number"
                },
                "is_deleted": {
                    "type": "number"
                },
                "responsible_uid": {
                    "type": "object"
                },
                "project_id": {
                    "type": "number"
                },
                "collapsed": {
                    "type": "number"
                },
                "date_string": {
                    "type": "string"
                }
            }
        }
    }
}

Once you configure it don’t forget about registering your webhook listener in Todoist App Manager.

How to check if JSON property exists 

Ok, if you setup everything properly you should be able to receive events from todoist. Now you’ll need to parse received JSON to check:

  • if JSON contains date_string property
  • if date_string property is not empty 

I cannot achieve it using Zapier/IFTTT. Also in Microsoft Flow it’s not something you can do using few clicks. But unlike the competition MS Flow has something called Workflow Definition Language. WDL is a language that you can use to make functional operations like comparing, merging, checking etc. without regarding of the data type. Pretty cool, huh? For our purpose I did below simple line

@empty(triggerBody()?['event_data']?['date_string'])

The code should be read as that:

  • @ opens any new WDL command
  • empty() returns true if object in parenthesis is empty
  • triggerBody() return body of the JSON
  • ? the question mark operator lets you reference null properties of an object without a runtime error
  • [‘event_data’] returns value of property called “event_data”

So, simple line, lot of operations. Love it.

Exercise: how the WDL code would look like if you want to get “true” value if property exists but IS NOT empty?

How to change project id for Todoist task in Flow?

Since we’ve been aware of Todoist documentation we can once again check it to see if we can update task projectId by simple HTTP call. Of course yes 🙂

Here is a section that shows what call need to be made in order to update an item in Todoist.

TL;DR you need to do below call:

  • Method: POST
  • Uri: https://todoist.com/API/v7/sync
  • Headers:
    • Accept: */*
    • Content-Type: application/x-www-form-urlencoded
  • Body:
["all"]=&token=<yourToken>&commands=[{"type":"item_move","args":{"project_items":{"<current_project_id>":[<task_id>]},"to_project":<destinationProjectId>},"uuid":"<yourGuid>"}]

In the body all information should be easy to understand except UUID (your guid) – where to get it from? Answer is easy – generate it for yourself. It has only to uniquely identify your operations. 

How to assemble everything together?

I recommend you to do it manually – it’s the best way to learn. You will also check if I describe everything properly + if it’s easy enough to follow. 

I’ll give you small hint 😉

 

I hope that you will take it from there. If not – feel free to ask me in a comments below.

I’d love to hear what do you think about above solution – Do you like it? Or maybe you found something better? Share it! 🙂

P.S.
[2017-10-01] I’ve submitted my template to MS Flow team – we’ll see if it will be accepted 🙂