Hey there, fellow developer! Ready to supercharge your productivity with a custom Todoist integration? You're in the right place. We're going to walk through building a Python-based integration with the Todoist API. It's powerful, it's flexible, and by the end of this guide, you'll have it under your belt.
Before we dive in, make sure you've got:
Got all that? Great! Let's get our hands dirty.
First things first, let's set up our project:
mkdir todoist_integration cd todoist_integration python -m venv env source env/bin/activate # On Windows, use `env\Scripts\activate` pip install requests
We're using requests
to handle our HTTP calls. Simple and effective.
Alright, let's get you authenticated:
config.py
file and add:API_TOKEN = "your_token_here"
Now, let's set up our headers:
headers = { "Authorization": f"Bearer {API_TOKEN}" }
Time to make our first API call! Let's fetch your tasks:
import requests from config import API_TOKEN response = requests.get( "https://api.todoist.com/rest/v2/tasks", headers={"Authorization": f"Bearer {API_TOKEN}"} ) if response.status_code == 200: tasks = response.json() for task in tasks: print(f"Task: {task['content']}") else: print(f"Error: {response.status_code}")
Run this, and you should see your tasks printed out. Cool, right?
Let's add a new task:
new_task = { "content": "Buy milk", "due_string": "tomorrow at 12:00", "priority": 4 } response = requests.post( "https://api.todoist.com/rest/v2/tasks", headers=headers, json=new_task ) if response.status_code == 200: print("Task added successfully!") else: print(f"Error: {response.status_code}")
Forgot to buy almond milk instead? No worries, let's update that task:
task_id = "task_id_here" # You'll get this when creating or fetching tasks updated_task = { "content": "Buy almond milk" } response = requests.post( f"https://api.todoist.com/rest/v2/tasks/{task_id}", headers=headers, json=updated_task ) if response.status_code == 204: print("Task updated successfully!") else: print(f"Error: {response.status_code}")
Decided you don't need milk after all? Let's delete that task:
task_id = "task_id_here" response = requests.delete( f"https://api.todoist.com/rest/v2/tasks/{task_id}", headers=headers ) if response.status_code == 204: print("Task deleted successfully!") else: print(f"Error: {response.status_code}")
Let's fetch your projects:
response = requests.get( "https://api.todoist.com/rest/v2/projects", headers=headers ) if response.status_code == 200: projects = response.json() for project in projects: print(f"Project: {project['name']}") else: print(f"Error: {response.status_code}")
Want to get fancy? Let's add a task with a specific due date and label:
new_task = { "content": "Finish Todoist integration", "due_datetime": "2023-06-30T12:00:00Z", "priority": 4, "label_ids": ["label_id_here"] } response = requests.post( "https://api.todoist.com/rest/v2/tasks", headers=headers, json=new_task ) if response.status_code == 200: print("Advanced task added successfully!") else: print(f"Error: {response.status_code}")
Always check those status codes! And remember, Todoist has rate limits. Be kind to their servers:
import time def make_request(url, method="GET", data=None): response = requests.request(method, url, headers=headers, json=data) if response.status_code == 429: # Too Many Requests retry_after = int(response.headers.get('Retry-After', 60)) print(f"Rate limited. Waiting {retry_after} seconds...") time.sleep(retry_after) return make_request(url, method, data) return response
Here's a quick test to make sure everything's working:
def test_integration(): # Create a task response = make_request("https://api.todoist.com/rest/v2/tasks", "POST", {"content": "Test task"}) assert response.status_code == 200 task_id = response.json()['id'] # Fetch the task response = make_request(f"https://api.todoist.com/rest/v2/tasks/{task_id}") assert response.status_code == 200 assert response.json()['content'] == "Test task" # Delete the task response = make_request(f"https://api.todoist.com/rest/v2/tasks/{task_id}", "DELETE") assert response.status_code == 204 print("All tests passed!") test_integration()
And there you have it! You've just built a Todoist API integration in Python. You can now create, read, update, and delete tasks, work with projects, and even handle advanced features. The sky's the limit from here!
Remember, this is just scratching the surface. The Todoist API has so much more to offer. Why not try integrating with labels next? Or maybe sync with a calendar app?
Happy coding, and may your tasks always be organized!