Python Todoist
I absolutely love Todoist. But one of the things that really bothers me is the “View All” view. I especially wish I could adjust the view to show everything segmented / separated by project.
Well if you’re willing to do a bit of technical stuff 🤓, I can show you how to accomplish this. You only have to set it up one time.
But first let me explain how it works.
Todoist has revolutionized the way we run our small business by helping us simplify projects and coordinate tons of details. Todoist gave us the focus to scale our company from 2 to 75 employees, $12M in VC financing, and 350+ happy enterprise customers. To-do list app in Python. Inspired by the diary app in the Databases in Python course of Kenneth Love, I've made a to-do list app. It lets you add and delete entries, modify them, as well as flag them 'DONE'. CHAPTER 1 Modules 1.1pytodoist.todoist This module introduces abstractions over Todoist entities such as Users, Tasks and Projects. It’s purpose is to hide the.
If you want to separate your tasks by project manually, the only way to accomplish this is to create a Filter that specifically lists out each project separated by commas. Basically this is like connecting a bunch of filter queries together with commas.
So you’re writing a query that includes every project you want included ##Project 1, ##Project 2, etc.
Then you’ll get a nice view of all the tasks separated by project in the order you wrote your filter query.
So obviously this would suck to maintain manually since every time you add a new project, change it’s name, remove a project, etc., your filter would break and you would need to manually update it.
Well let me introduce you to the power of APIs. I jumped into Todoist’s API documentation and figured out how to automatically grab all my projects and update a filter with a query that will show me all my tasks from all my projects, separated by project.
Don’t worry, you don’t need to know how to code. I’m going to show you how to upload a special bit of code into Google Cloud and have it run and update automatically for you… for free!
Basically every hour (or whatever you want to set the interval to) something called a Google Cloud Function will run a piece of code that grabs all your projects and all their tasks and updates a custom “View All” filter in Todoist.

Filter ID
Ok the first thing you’re going to need is to pick a filter (or create a new one) that you want to be your special “View All” view. I made one called ⛏️ View All
. I like to use emojis on everything I use frequently since the human brain can find and parse information visually much faster than reading text. But call yours whatever you want.
You’ll need to do this next part in a web browser (todoist.com/app). Once you have a filter you want to use you need to click on it. In the address bar you should notice the URL will say something like todoist.com/app/#filter%2F2290740
. Copy the number that appears after #filter%2F
and save it somewhere for later. This is your filter ID. In my case my filter ID is 2290740
.
Todoist API Key
Now you need to get your Todoist API key. This is a special key that allows programs to make changes to your Todoist account via the Todoist API. Don’t share this with anyone.
To find yours go to todoist.com/prefs/integrations from a browser or you can get to it by clicking on:
- The gear icon in the upper-right corner
- Settings
- Integrations
Scroll down and you’ll find your API key. It should look something like b0imfnc8mwsae3aaw6465jr50qtlx
. Copy and save it somewhere. We’ll need it later.
Create a Google Cloud Function
Head over to console.cloud.google.com and make sure you’re logged in. If you don’t already have a Google Cloud account just follow my guide on how to create and setup a free Google Cloud Platform account.
Once you’re there click the menu and under the “Compute” section click on “Cloud Functions.” Then click “Create Function.”
Give your function a good descriptive name like todoist-filter-view-all
.
Now under Trigger and Authentication choose Allow unauthenticated invocations
. This means that anything or anyone with the URL for this trigger will be able to invoke it. This can be useful if you want to use a service like IFTTT or Zapier to trigger your Cloud Function. You can set it to Require Authentication
if you don’t plan on using an external service to trigger it.
Now click “Save”
Click the “Variables, Networking and Advanced Settings” dropdown and set the “Memory allocated” dropdown to 128 MiB
. This is optional but since this is a very simple cloud function you might as well lower it down to 128MiB to be more efficient.
Click “Next”!
Configure Your Cloud Function
Next is the fun part where all the action happens. We’re going to write the code that this Cloud Function will execute every time it is called. This code is what will update your Todoist filter with all that “view all” goodness and segment it by project. Yay! 🥳
In the “Runtime” dropdown select Python 3.7
. At the time of this writing the only Python options are 3.7 and 3.8 and 3.8 didn’t work for me. It’s possible you may have higher versions. If so, just use whatever is available to you and hopefully it will work for you! 🤞😬 If not hit me up on the Twitters and I’ll see what I can do.
Now change the value under “Entry point” to update
.
Add the Todoist Python Library
The good folks at Doist created a library that makes our job really easy. In order to add it click on requirements.txt
and add a new line todoist-python
.
Write the Codes

Ok now we just need to write the code that will make your shiny new cloud function do cool stuff. Click on main.py
and erase everything in the code editor window to the right of it. We want to start with a clean slate.
Now copy and paste the following code in. But replace the key
value with your own Todoist API key and replace the filter_id
with the filter ID you saved earlier.
If you only want to show tasks that are due today you can change line 13 from query = '#' + name + ', '
to query = '#' + name + ' & today, '
. Just be very careful to maintain the spacing and indentations. These are very important in Python.
Hit that deploy button and you’re off to the races.
Give it some time… like go grab a cup of tea… use the john… deploying takes a few minutes. Once it’s done it’s time to test that bad boy out! Click on the eclipses (3 dots) and click “Test function.”
Then hit “Test the Function” on the next page.
Now run over to Todist and see if it worked!
Make Sure the Filter Works
If your filter view is spitting out tasks that’s a great sign. If it looks like you’re missing some stuff that might be because you have so many projects that you’ve exceeded the 1,024 character limit for filter queries. Right click on your filter and choose “Edit Filter.”
If your filter query is too long it will tell you here.
If this is happening to you, you’ll either need to delete some projects or read ahead and use my advanced script which can filter out certain projects and gives you more granular control.
It’s also possible you may get an error message like this:
If you see this it’s probably because you’re using a character in one of your project names that isn’t supported. For example, you can’t have a project name that includes a comma. If you have a project called Some, Stuff
it’s not going to work. Change the offending project title and go test your Cloud Function again.
If your filter looks good then continue on to the next step.
Get Your Trigger URL
Go to your Cloud Function, click on the “Trigger” tab and copy the Trigger URL. We’re going to need it for the next step.
Your Cloud Function will run and update your Todoist filter any time you (or anyone or anything else) visits this URL! How cool is that?
We’re going to automate running this Cloud Function every hour (or whatever interval you choose) but it’s handy to save this URL in case you ever want to manually run an update on your “View All” filter. I added it as a comment to my “Inbox” project to make it easy to find.
Automate Posting to Your Trigger URL
As cool as it is to run your Cloud Function manually with your Trigger URL, it’s even cooler if we automate triggering it.
There are 3 ways to do this. You can use Zapier or IFTTT if you use those services. Just use the time trigger (you can have it run every hour) and the webhook action. Choose to Post
to your webhook and don’t worry about the other settings.
The third way to do this is free. Use Google Cloud! Go hit the pancakes (menu), scroll all the way to the “Tools” section and hit “Cloud Scheduler.” You can click the “Pin” icon to make it easier to access later if you want.
Click “Create Job”
Give it a good name and description so you can figure out WTF this is in the future.
Enter the frequency you want. I run mine every hour but put whatever you want. The format is tricky so here are a few examples you can copy and paste in:
* * * * *
run every minute.*/5 * * * *
run every 5 minutes*/30 * * * *
run every 30 minutes0 * * * *
run every hour
Enter your country/timezone, choose HTTP
as your target, paste your Cloud Function Trigger URL in “URL”, and choose POST
for your “HTTP Method.” Leave the other settings blank. Click “Create” and you’re done!
Your hard work has paid off. Isn’t she beautiful?
The Advanced Script
I wanted a bit more granular control over my “view all” filter. So I made one that is even better.
This personally fit my life better. I did a couple of things…
Skip Child Projects
I don’t want child projects in my filter query. I’d rather see those tasks listed out under the parent project section. So if a project is inside of another project I don’t include it in the filter query. If this isn’t something you like then just get rid of these lines:
Skip Certain Projects
There are certain projects I want to completely skip. I have a project called “PROJECTS ON ICE” and I put projects that are on hold in there.
If this is something you want to do just add the projects to this line:
if name 'Misc' or name 'PROJECTS ON ICE': #projects I want to completely skip
Replace Misc with a project you want to not show. You can add more by continuing to add or name 'your project name'
e.g. if name 'project 1' or name 'project 2' or name 'project 3':
If this isn’t your jam then just delete these lines:
Don’t Include Tasks Inside of Sub Projects
Last of all I have certain projects where I don’t want to pull in tasks belonging to sub projects (should any exist.)
If any projects match the criteria the code will generate a query like #Project
otherwise it will be ##Project
.
if name '🏋️ A: Health': #I don't want to see sub projects for these projects
sub_projects = '#' #no sub projects
Replace this with projects that apply for you.
If there aren’t any projects that apply you can just erase everything between the quotes:
if name ': #I don't want to see sub projects for these projects
sub_projects = '#' #no sub projects
If you have questions let me know. I hope this is as big a game changer for you as it has been for me!
Actionista Action CLI for Todoist.
Manage your Todoist tasks from the command line, using powerful filters toselect, print, reschedule, and complete tasks in a batch-wise fashion.
Do you have dozens or even hundreds of overdue tasks on your agenda?Clear up your task list in seconds, using the Actionista Action CLI for Todoist.You can now take the rest of the day off with a clear conscience.
This Action CLI for Todoist (todoist-action-cli
), operates sequentially on a list of tasks.You start out with a list of all tasks, and then select tasks using one of the manyfilters available. You can then sort, print, and reschedule the selected tasks.
Actionista Action-Chain CLI for Todoist (actionista-todoist)is inspired by the powerful find
command line tool. It takes the 'chain of actions'approach that find
uses to find and select files on your harddisk,and applies it for managing your Todoist task list.
The successful find
utility works by supplying a sequence of 'actions'(also known as 'expressions' in the find
manual).
Most actions are essentially filters, where you list criteria for the files to find.However, the real usability of find
is that it can not only print the matching files,but also use the matching files for other actions, e.g. deleting the files,or sending them to other command line tools.
The actionista action-chain CLI takes a similar approach.Starting from the full list of tasks, you can apply filters to find exactly those tasks that you need.Together with other actions, you can print
, reschedule
, rename
, mark-complete
, or delete
whatever tasks you need.You can invoke as many actions as you need, both filters and other actions, in any order.The actions are invoked in exactly the order you specify.
So if you want, you can filter tasks by e.g. project name, and print all tasks in a given project,then filter by due date, and print again, then reschedule the tasks that were just printed,then filter by exact name, then mark that (or those) remaining task(s) as complete,and finally commit the changes to the server.This example is mostly just to show what is possible,and I personally wouldn't recommend having such a complex list of actions,but you are basically free to list as many (or as few) actions as you want or need.For the record, doing the described sequence of actions would look something like this:
Python Todo App
Usually, for your own sanity, command line usage would be a little more simple, and have only a single 'purpose'with each invocation:
The generalized command line usage is:
You can also import the package from python:
Note: This package was formerly imported as rsenv.rstodo.todoist_action_cli
,but has now been separated into its own package, imported as: actionista.todoist_action_cli
.
NOTE: This application is not created by, affiliated with, or supported by Doist.It is a third-party command line utility that is making use of the official Todoist API,as documented by https://developer.todoist.com/sync/v8/.
INSTALLATION:
Installation with pipx
:
For regular end-users, I recommend using pipx
to install the Actionista-Todoist command line apps:
If you don't have pipx installed, you can refer to thepipx installation guide.Briefly:
The last step will add ~/.local/bin
to the PATH environment variable.Please make sure to close and restart your terminal/command prompt afterinstalling pipx for the first time.
Known installation errors:
- If you are using
conda
, there is a known issue where you receive an error,'Error: [Errno 2] No such file or directory:', when trying to install packages withpipx
.If you get this error, please update yourconda
python and make sure you are only usingthe 'defaults' channel, not 'conda-forge'.
Installation with pip
:
To install distribution release package from the Python Packaging Index (PyPI):
Alternatively, install the latest git master source by fetching the git repository from githuband install the package in editable mode (development mode):
CONFIGURATION:
Once actionista-todoist
package is installed, you need to obtain a login token from the todoist website:Log into your todoist.com account, go to Settings -> Integrations
, and copy the API token.(You can also go directly to the page: https://todoist.com/prefs/integrations).
Now run:
to set up the login token with your Actionista-Todoist installation.The API token is stored in ~/.todoist_token.txt
.The actionista-todoist-config
command will also create a default config file,~/.todoist_config.yaml
, which you can edit to change default sorting and printing format.
If you re-set your Todoist API token, you can update it either by running:
or by manually editing the file ~/.todoist_token.txt
and place your token in here.
USAGE:
The actionista-todoist
package contains several command line apps (CLIs):
todoist-action-cli
- also available asactionista-todoist
.todoist-cli
.actionista-todoist-config
.
The todoist-action-cli
CLI program uses the 'action chain' approach, where you specify a sequenceof 'actions', which are used to filter/select tasks from Todoist and then sort, print, or reschedulethe selected tasks in a batch-wise fashion.
The todoist-cli
CLI program is used mostly for things that doesn't fit the 'action chain' philosophy.For instance, if you want to add a new task, that doesn't really fit into the todoist-action-cli
workflow.(*) Instead, you can use todoist-cli add-task
command to add a new task to Todoist.The todoist-cli
is also used for other things, e.g. printing a list of your projects, etc.You can run todoist-cli --help
to see all available commands.
Finally, the actionista-todoist-config
CLI program is used to set up Actionista-Todoist,configuring your API login token, and creating a default configuration file.
(*) The todoist-action-cli
can technically be used to add tasks to Todoist, using the-add-task
action command - however, this is not the recommended approach.
todoist-action-cli
usage:
The general command line usage is:
Where action
is one of the following actions:
To see how to use each filter, type:
E.g.:
As you can see, typical usage is:
The filter actions could be e.g. filtering by -name
(same as -content
),project
, due_date_local_iso
, etc.The -sync
action is optional; if you do not specify -sync
, the program will just re-use the old cache,from last time you invoked -sync
. You must invoke -sync
at least once, when you first install this package,and you should always -sync
if you have made any changes (e.g. from your phone) since your last sync.Finally, the -sort
and -print
commands will sort and print the selected tasks.
If you need to refine your filters, just run the command again. The data is cached locally,so if you omit the -sync
action, commands can be executed in rapid succession.
Another example, to reschedule the due date for a bunch of tasks, would look like:

NOTE: I strongly recommend that you -print
the filtered tasks before you-rename
or -reschedule
the tasks. When you invoke -commit
, the changes cannot be undone automatically,so you may easily end up with a bunch of identically-named tasks with the same due date, if you forgot toapply the correct selection filters before renaming or rescheduling the tasks!For this reason, the program will, by default, ask you for confirmation before every -commit
.
Python To Dict
Action arguments:
Each action can be provided a set of arguments which are listed sequentially, separated by space.If one argument contains spaces, e.g. you are filtering by tasks in the project 'Meeting notes',then you need to quote the argument as such:
Here, we provided one argument to the -project
action ('Meeting notes'
),and two arguments to the -sort
action ('project_name,content'
and ascending
).

Some of the actions attempts to be 'clever' when interpreting the arguments given.For instance, when filtering by project, you can do either:
The general signature for the -project
action is:
Here, [operator]
is the name of one of the many registered binary operators.These are used to compare the tasks against a given value.In the example above, if you do not specify any operator, then the 'glob' operator is used.The 'glob' operator allows you to use wild-cards for selecting tasks, the same way you select files on the command line.In our case, we 'glob' against tasks with project name starting with the string 'Wedding*'.We could also have used the 'startswith' operator, and omit the asterisk: startswith Wedding
.
For more info on how to use operators, see:
Ad-hoc CLI:
Python Todoist Api
Installing this project (actionista-todoist
) with pip
will also give you some'ad-hoc' command line interface entry points:
Prior art: Other python-based Todoist projects
Other Todoist CLI packages that I know about:
todoist-cli -A command line interface for batch creating Todoist tasks from a file.Makes manual requests against the web API url (rather than using the official todoist-python package).No updates since January 2016 (except
setup.py
andrequirements.txt
).This probably doesn't work, given that it uses an old, obsolete API endpoint URL.todoicli - A rather new project (as of April 2018).Focuses on pre-defined queries for listing tasks, e.g. 'today and overdue', 'next 7 days', etc.Lots of other functionality, pretty extensive code base.Has integration with the toggl.com time tracking service.Uses the official
todoist-python
package, but still uses the'universal UTC' time format from the old v7 Sync API, and the v7 due-date structure.That means it probably won't work anymore, given that the v7 Sync API has been deprecated,and thetodoist-python
package has switched to Sync API v8.For instance, thelist td
andlist n7
usesitem['due_date_utc']
, which will raiseaKeyError
with the new v8 data structure.The CLI also expectsIDs
(task_id
,label_id
,project_id
), rather than text names,making it rather difficult to use for the end user.pydoist - A basic CLI to add Todoist tasks from the command line.Uses the official
todoist-python
python API from Todoist.Lastest release was November 2016, so may not work with the new v8 Sync API.
Todoist Python Module
Other general python Todoist packages:
Todoist Python Requests
python-todoist - The official python'Todoist' package from Doist (the company behind Todoist).Is currently using the version 8.0 'Sync' API.
pytodoist - An alternative Todoist API package.Also uses the v7 Sync API.A rather different approach to API wrapping, perhaps more object oriented.Focused on modelling individual Users/Projects/Tasks/Notes,where the official todoist-python package has managers as the central unit(ItemsManager, ProjectsManager, NotesManager).
- Last update November 2016 - will be obsolete when the v7 Sync API is removed.
