Todoist
Extend the Todoist platform with our powerful APIs.
Todoist Sync API v2 makes it easy to retrieve and sync data. It's great if you want to implement a client that stores all of the data locally.

Our Sync API has only three entry points:

Older versions

A deprecated version 1 can be seen here here. Don't use this as it will be discontinued in the future.

Recommended workflow with the API

This is the recommend way to work with the API.

Creating and updating the full model (on login or relaunch of your app):

Updating changes and getting updated data (iterative sync):

/TodoistSync/v2/get

Used to retrieve data (both all and only updated). Do note that at this time only Projects, Labels, Filters, DayOrders supports partially fetching, this is because only these will grow a lot, the other data is small and does not change that much.
Optional parameters:
project_timestamps:
A JSON object containing a mapping from project ids to their last_updated timestamps. last_updated is a property of a project, it's an unix timestamp of when the project was last updated (name changed, tasks added, etc.)
If you omit project_timestamps then all the projects will be fetched! If you specify project_timestamps then only updated projects will be fetched (i.e. new projects or projects where last_updated is different).
                    { "121214": "1325774561.4", "132424": "1325888134.8", ... }
                    
labels_timestamp:
The /get and /syncAndGetUpdated requests return LabelsTimestamp that specifies when the labels were last updated. If you omit labels_timestamp then all the labels will be fetched by /get request and none of then will be fetched by /syncAndGetUpdated request. If you specify labels_timestamp then labels will be returned if your timestamp is different from the servers.
If you send labels_timestamp and the labels have not been updated then the server won't return the Labels entry at all.
filters_timestamp:
The /get and /syncAndGetUpdated requests return FiltersTimestamp that specifies when the custom filters were last updated. If you omit filters_timestamp then all the filters will be fetched by /get request and none of then will be fetched by /syncAndGetUpdated request. If you specify filters_timestamp then filters will be returned if your timestamp is different from the servers.
If you send filters_timestamp and the filters have not been updated then the server won't return the Filters entry at all.
day_orders_timestamp:
The /get and /syncAndGetUpdated requests return DayOrdersTimestamp that specifies when the day orders were last updated. If you omit day_orders_timestamp then all the day orders will be fetched by /get request and none of then will be fetched by /syncAndGetUpdated request. If you specify day_orders_timestamp then day orders will be returned if your timestamp is different from the servers.
If you send day_orders_timestamp and the day orders have not been updated then the server won't return the DayOrders entry at all.
reminders_timestamp:
The /get and /syncAndGetUpdated requests return RemindersTimestamp that specifies when reminders were last updated. If you omit reminders_timestamp then all the reminders will be fetched by /get request and none of then will be fetched by /syncAndGetUpdated request. If you specify reminders_timestamp then reminders will be returned if your timestamp is different from the servers.
If you send reminders_timestamp and reminders have not been updated then the server won't return the Reminders entry at all.
api_token:
User's API token (returned on successful login from /API/Users/login). Else the session cookie is used.
Curl example:
                    curl -X POST -d "api_token=..." https://api.todoist.com/TodoistSync/v2/get
                    curl -X POST -d 'api_token=...&project_timestamps={"15":"1325774561.4"}' https://api.todoist.com/TodoistSync/v2/get
                    
Successful return:
HTTP 200 OK with a JSON object of the data:
                    {
                        "FetchedAllData": true/false,
                        "Projects": [ ... ],
                        "ActiveProjectIds": [ ... ],
                        "ActiveProjectTimestamps": { ... },

                        "Labels":   [ ... ],
                        "LabelsTimestamp":   "1344642992.1",

                        "Filters":   [ ... ],
                        "FiltersTimestamp":   "1363335992.1",

                        "DayOrders":   { ... },
                        "DayOrdersTimestamp":   "1322399993.1",

                        "Reminders":   { ... },
                        "RemindersTimestamp":   "1322399993.1",

                        "Settings": { ... },
                        "User": {...},
                        "UserId":   User's id
                    }
                    
Explanation of data returned:
User:
A JSON object with a user's information
                        Example:
                        {
                           "start_day":1,
                           "start_page":"7 days, overdue",
                           "date_format":1,
                           "is_premium":true,
                           "sort_order":0,
                           "full_name":"Amir Salihefendic",
                           "mobile_number":"...",
                           "mobile_host":"elsewhere",
                           "timezone":"America\/Santiago",
                           "id":1,
                           "time_format":0,
                           "premium_until":"Mon, 20 Nov 2017 16:02:13 +0000",
                           "completed_count":267,
                           "join_date":null,
                           "default_reminder":"mobile",
                           "email":"amix@amix.dk"
                        }
                        
FetchedAllData:
Is true if all the data has been fetched, otherwise false (indicates that only partial data has been retrieved).
Projects:
A list of JSON objects of projects.
                        Example:
                        [{
                          "user_id": 1,
                          "name": "Babu",
                          "color": 2,
                          "collapsed": 0,
                          "item_order": 1,
                          "cache_count": 13,
                          "indent": 1,
                          "id": 455831,
                          "last_updated": "1325774561.4",
                          "items": [...]
                        }, ...]
                        
Projects[X].items:
A list of items (tasks) for a project.
                        Example:
                        [{
                          "due_date": null,
                          "due_date_utc": null,
                          "user_id": 1,
                          "collapsed": 0,
                          "in_history": 1,
                          "priority": 1,
                          "item_order": 2,
                          "content": "Fluffy ferret",
                          "indent": 1,
                          "project_id": 22073,
                          "id": 210873,
                          "checked": 1,
                          "date_string": ""
                          "notes": [...]
                        }, ...]
                        
Note that each task has notes.
ActiveProjectIds:
A complete list of currently active project ids. Can be used to sync client's local model (e.g. to remove projects from the local model that have been deleted).
                        Example:
                        [ 1212, 114131, 121241, ... ]
                        
ActiveProjectTimestamps:
A object specifying the timestamps of all the active projects. When syncing it's important that the local model's project last_updated fields are updated and this object can be used to ensure that.
                        Example:
                        {
                           ...
                           "ActiveProjectTimestamps":{
                              "1181826":"1342723105.4",
                              "976647":"1342723063.5",
                              "976648":"1342215248.7",
                              "1271768":"1342215248.6",
                              "1271769":"1342215248.6",
                              "1271770":"1342215248.6",
                              "1271391":"1342907605.7",
                              "976612":"1342740016.4",
                              "1199851":"1342215248.6"
                           },
                           ...
                        }
                        
Labels:
A JSON list of objects (including things like color, id etc.)
                        Example:
                        [ { "color":4, "count":0, "uid":1, "id":721, "name":"followup" }, ... ]
                        
If LabelsTimestamp is sent and the labels have not been updated then Labels won't be returned at all!
LabelsTimestamp:
A string specifying when labels where last updated. Use this to not fetch all the labels on every request.
                        Example:
                            "1344642992.1"
                        
Filters:
A JSON list of custom filters
                        Example:
                        [ { "name":"Priority 1", "query":"q1", "id":1212, "user_id":1, "item_order":1 }, ... ]
                        
If FiltersTimestamp is sent and the filters have not been updated then Filters won't be returned at all!
FiltersTimestamp:
A string specifying when filters where last updated. Use this to not fetch all the filters on every request.
                        Example:
                            "1344642994.1"
                        
DayOrders:
An object specifying the order of items in daily agenda.
                        Example:
                        {"12345": 1, "12346": 2, "12347": 2, "12348": -1}
                        
If DayOrdersTimestamp is sent and day orders have not been updated then DayOrders won't be returned at all!
DayOrdersTimestamp:
A string specifying when day orders where last updated. Use this to not fetch day orders on every request.
                        Example:
                            "1344642994.1"
                        
Reminders:
An object containing all reminders for all items in the project. The key contains reminder_id the value contains reminder information.
                        Example:
                        {
                            "12345": {"item_id": 12346, "service": "email", "minute_offset": 30},
                            "6789": {"item_id": 12346, "service": "email", "due_date": "Fri 01 Jan 2100 09:00:00 +0000", "date_string": "2100-01-01 at 9am", "mm_offset": 0},
                            ...
                        }
                        
If RemindersTimestamp is sent and reminders have not been updated then Reminders won't be returned at all!
RemindersTimestamp:
A string specifying when day orders where last updated. Use this to not fetch day orders on every request.
                        Example:
                            "1344642994.1"
                        
Settings:
Includes user's settings as a JSON object, including things like start page query and timezone information.
                        Example:
                        { 
                            "START_PAGE":"7 days, overdue",
                            "AMPM":false, "SORT_ORDER":0, "US_DATES":false,
                            "TIMEZONE":"America/Santiago" 
                        }
                        
UserId:
Includes the id of the user we are fetching data from. Do note that other user data is returned on login from /API/Users/login.

/TodoistSync/v2/sync

/TodoistSync/v2/sync takes a list of JSON object commands which specify which changes should be done to the model. These changes could be adding projects, deleting tasks, adding notes etc.

It supports two big features which can make syncing easier:

Required parameters:
items_to_sync:
A list of JSON object commands. These commands are specified later in the documentation.
                    Example:
                    [{
                         "type": "project_add",
                         "temp_id": "$1326467493134",
                         "timestamp": 1326467500523,
                         "args": {
                           "name": "Test",
                           "item_order": 1,
                           "indent": 1,
                           "color": 1
                         }
                      }, 
                      {
                         "type": "project_update",
                         "timestamp": 1326467500573,
                         "args": {
                           "id": "$1326467493134",
                           "name": "Test new",
                           "item_order": 5,
                           "color": 2
                         }
                    }]
                    
api_token:
User's API token (returned on successful login from /API/Users/login). Else the session cookie is used.
Curl example:
                    curl -X POST -d 'api_token=...&items_to_sync=[{ "type": "project_add", "temp_id": "$1326467493134", "timestamp": 1326467500523, "args": { "name": "Test", "item_order": 1, "indent": 1, "color": 1 } }]' https://api.todoist.com/TodoistSync/v2/sync
                    
Successful return:
HTTP 200 OK with a JSON object of temporary id to real id mappings:
                    {
                        "$1326467493134": 232323,
                        ...,
                        "$1326467493152": 2323234
                    }
                    
Error return:
Same as successful return, but with an extra errors mapping that specifies which commands were not processed correctly:
                    {
                        "$1326467493134": 232323,
                        ...,
                        {"errors": ["Could not be processed (ignored!): {'args': {'blah': 'blah'}, 'type': 'item_update'}"]},
                        ...,
                        "$1326467493152": 2323234
                    }
                    

/TodoistSync/v2/syncAndGetUpdated

syncAndGetUpdated is a combined call that syncs updates and fetches the latest data. This is useful because you don't have to do 2 requests.
Required parameters:
api_token:
User's API token (returned on successful login from /API/Users/login). Else the session cookie is used.
Optional parameters:
items_to_sync:
A list of JSON object commands. It's the items_to_sync parameter of /v2/sync call.
project_timestamps:
A JSON object containing a mapping from project ids to their last_updated timestamps. It's the ActiveProjectTimestamps parameter of /v2/get call. Please see that documentation for further details.
labels_timestamp:
A string value specifying when labels where last updated. It's the LabelsTimestamp parameter of /v2/get call. Please see that documentation for further details.
filters_timestamp:
A string value specifying when filters where last updated. It's the FiltersTimestamp parameter of /v2/get call. Please see that documentation for further details.
day_orders_timestamp:
A string value specifying when day_orders where last updated. It's the DayOrdersTimestamp parameter of /v2/get call. Please see that documentation for further details.
reminders_timestamp: A string value specifying when reminders were last updated.
Curl example:
                        curl -X POST -d 'api_token=...&items_to_sync=[{ "type": "project_add", "temp_id": "$1326467493134", "timestamp": 1326467500523, "args": { "name": "Test", "item_order": 1, "indent": 1, "color": 1 } }]' https://api.todoist.com/TodoistSync/v2/syncAndGetUpdated
                    
Successful return:
HTTP 200 OK with a JSON object of temporary id to real id mappings:
                    {
                        "TempIdMapping: {
                            "$1326467493134": 232323,
                        },

                        "FetchedAllData": {
                            ... Same data as /v2/get ...
                        },

                        "ActiveProjectIds": {
                            ... Same data as /v2/get ...
                        },

                        "ActiveProjectTimestamps": {
                            ... Same data as /v2/get ...
                        },

                        "Projects": {
                            ... Data of the updated projects, same as  /v2/get ...
                        },

                        "Settings": { 
                            ... Same data as /v2/get ...
                        },

                        "User": {
                            ... Same data as /v2/get ...
                        },

                        "SyncErrors": [
                            ... Only set if some of the updates could not be processed ...
                        ],

                        "LabelsTimestamp":   "1344642992.1",
                        "Labels":   
                            ... Only sent if LabelsTimestamp is sent and your LabelsTimestamp is different from the backends ...
                        ,

                        "FiltersTimestamp":   "1322598231.1",
                        "Filters":   
                            ... Only sent if FiltersTimestamp is sent and your FiltersTimestamp is different from the backends ...
                        ,

                        "DayOrdersTimestamp":   "1833298299.1",
                        "DayOrders":   
                            ... Only sent if DayOrdersTimestamp is sent and your DayOrdersTimestamp is different from the backends ...
                        ,

                        "RemindersTimestamp":   "1833298299.1",
                        "Reminders":
                            ... Only sent if RemindersTimestamp is sent and your RemindersTimestamp is different from the backends ...
                        ,

                        "UserId": ... Same data as /v2/get ...
                    }
                    

Why do I need to supply timestamps?

timestamp should be a unix timestamp of when the command was created. This is used for duplication protection, i.e. we want to ensure that same command isn't executed twice! This check works by keeping track of command types, temporary ids and timestamps. By just supplying timestamps the system does these checks automatically and will ignore duplicated commands!

How does temporary ids work?

Your application will use temporary ids and the Sync API has special support for them. We suggest that you use unix timestamps to generate these ids to give them uniquness (maybe also prefixing them with a special number). An example shows how temporary ids can be used and referenced:

            [{
              "type": "project_add",
              "temp_id": "$1326467493134",
              "args": {
                "name": "Test",
                "item_order": 1,
                "indent": 1,
                "color": 1
              },
              "timestamp": 1326467500523
            }, 
            {
              "type": "project_update",
              "args": {
                "id": "$1326467493134",
                "name": "Test new",
                "color": 2
              },
              "timestamp": 1326467500573
            }]
            

In the above example you can see that project_add command has a temp_id property - - which specifies which temporary id this new project has. project_update command later references this temporary id. The API will automatically resolve these ids.

Additionally /TodoistSync/v2/sync will return the real id of $1326467493134 in the result. Remember to update your local model with these real ids e.g.:

            {"$1326467493134": 21314212}
            

While the system remembers temporary ids and their mappings to real ids, it's important to use real ids when they are available to you (typically after a sync). This is important since the API only remembers the last 500 temporary ids for each user!

JSON object commands

Projects

project_add: Adding a project
                    {
                      "type": "project_add",
                      "temp_id": "$1326467493134",
                      "timestamp": 1326467500523,
                      "args": {
                        "name": "Test",
                        "color": 1,
                        "indent": 1,
                        "item_order": 1
                      }
                    }
                    
project_update: Updating a project
                    {
                      "type": "project_update",
                      "timestamp": 1326467976310,
                      "args": {
                        "name": "New name",
                        "indent": 1,
                        "color": 7,
                        "id": "$1326467493134"
                      }
                    }
                    
project_delete: Deleting projects
                    {
                      "type": "project_delete",
                      "timestamp": 1326468118911,
                      "args": {
                        "ids": [1272425]
                      }
                    }
                    
project_archive: Archive a project
Only available for premium users.
                    {
                      "type": "project_archive",
                      "timestamp": 1326468118912,
                      "args": {
                        "id": 1272426
                      }
                    }
                    
project_unarchive: Unarchive a project
Only available for premium users.
                    {
                    "type": "project_unarchive",
                      "timestamp": 1326468118913,
                      "args": {
                        "id": 1272426
                      }
                    }
                    
project_update_orders_indents: : Updating orders/indents of multiple projects at once
                    {
                       "type":"project_update_orders_indents",
                       "timestamp":1342922613464,
                       "args":{
                          "ids_to_orders_indents":"{\"15\":[22,2],\"1437\":[9,2],\"14681\":[26,2],\"20656\":[6,1],\"20657\":[8,2],\"20658\":[12,2],\"750222\":[10,2],\"1271770\":[23,1],\"1271816\":[27,1],\"1276938\":[21,1],\"1276944\":[25,1],\"1277096\":[24,1],\"1277097\":[2,1],\"1277098\":[3,1],\"1277099\":[1,1]}"
                       }
                    }
                    

Items

item_add: Adding a task
                    {
                      "type": "item_add",
                      "temp_id": "$1326468158202",
                      "timestamp": 1326468806307,
                      "args": {
                        "content": "Test",
                        "project_id": 1272426,
                        "indent": 1,
                        "priority": 1,
                        "date_string": "tom",
                        "due_date_utc": "2012-3-24T20:59",
                        "item_order": 1
                      }
                    }
                    
When passing date_string and due_date_utc they should be formatted as following:
  • date_string: Can be every day @ 10. Look at our reference to see which formats are supported
  • due_date_utc: Should be formatted as 'YYYY-M-DDT00:00', example: '2012-3-24T23:59'. Value of due_date_utc must be in UTC.
  • due_date: Alternative (backward compatible, not recommended) way of providing item due date. Format is the same as for due_date_utc, must be in UTC for due dates containing time fragments, and in the format 'YYYY-M-DDT23:59:59' (hardcoded timestamp) for whole-day entries.
If you want to pass in due dates note that date_string is required, while due_date_utc (due_date) can be omitted. If date_string is provided, it will be parsed as local timestamp, and converted to UTC internally, according to user profile settings.
item_update: Updating a task
None of the properties are requried (i.e. you can only supply some of them). It's much fast to use item_update_orders_indents and item_update_day_orders if you need to do multiple updates of indents, item_orders or day_orders.
                    {
                      "type": "item_update",
                      "timestamp": 1326470294735,
                      "args": {
                        "content": "New task text",
                        "project_id": 1272426,
                        "indent": 1,
                        "priority": 1,
                        "date_string": "",
                        "due_date_utc": null,
                        "item_order": 5,
                        "day_order": 7,
                        "id": "$1326468158202"
                      }
                    }
                    
item_delete: Deleting tasks
                    {
                      "type": "item_delete",
                      "timestamp": 1326470379977,
                      "args": {
                        "ids": [11466961]
                      }
                    }
                    
item_move: Moving a task from one project to another
                    {
                      "type": "item_move",
                      "timestamp": 1326470524258,
                      "args": {
                        "project_items": {
                          "1272426": [11466963]
                        },
                        "to_project": 1272419
                      }
                    }
                    
item_complete: Completing a task
                    {
                      "type": "item_complete",
                      "timestamp": 1326470662137,
                      "args": {
                        "project_id": 1272426,
                        "ids": [11466964],
                        "force_history": 1
                      }
                    }
                    
item_uncomplete: Uncompleting a task
                    {
                      "type": "item_uncomplete",
                      "timestamp": 1326470707104,
                      "args": {
                        "project_id": 1272426,
                        "ids": [11466964],
                        "update_item_orders": 1
                      }
                    }
                    
item_update_date_complete: When completing/uncompleting a recurring task (needs special handling!)
                    {
                       "timestamp":1342920333612,
                       "args":{
                          "id":11482124,
                          "new_date_utc":"2012-7-25T23:59",
                          "date_string":"every day",
                          "is_forward":1
                       },
                       "type":"item_update_date_complete"
                    }
                    
is_forward indicates if it's a complete (1) or uncomplete (0). The reason why this is a special case is because we need to mark a recurring completion (and using item_update won't do this!) Argument new_date is a backward-compatible replacement for new_date_utc. It's treated the same way as due_date in item_update/item_add methods.
item_update_orders_indents: Updating orders/indents of multiple items at once
                    {
                       "type":"item_update_orders_indents",
                       "timestamp":1342920577620,
                       "args":{
                          "ids_to_orders_indents":"{\"11478113\":[2,1],\"11478114\":[1,1],\"11482125\":[4,1],\"11482126\":[3,1],\"11482127\":[5,1]}"
                       }
                    }
                    
item_update_day_orders: Updating day ordering on today or 7 days views
                    {
                       "type":"item_update_day_orders",
                       "timestamp":1342920577622,
                       "args":{
                          "ids_to_orders":"{\"11477867\":2,\"11478271\":3,\"11478272\":1}"
                       }
                    }
                    

Labels

label_register: Register a label
                    {
                      "type": "label_register",
                      "timestamp": 1326471017745,
                      "temp_id": "$1326470987640",
                      "args": {
                        "name": "home",
                        "color": 5
                      }
                    }
                    
label_delete: Delete a label
                    {
                      "type": "label_delete",
                      "timestamp": 1326471017756,
                      "args": {
                        "id": "$1326470987640"
                      }
                    }
                    
label_update: Updating a label
                    {
                      "type": "label_update",
                      "timestamp": 1326471017757,
                      "args": {
                          "id": "$1326470987640",
                          "name": "New name",
                          "color": 3
                      }
                    }
                    
name and color are optional (i.e. you can just update name or color).

Notes

Only available for premium users.
note_add: Add a note
                    {
                      "type": "note_add",
                      "timestamp": 1326471017748,
                      "temp_id": "$1326470987549",
                      "args": {
                        "item_id": "$1326470987649",
                        "content": "This is a test"
                      }
                    }
                    
note_update: Updating a note
                    {
                      "type": "note_update",
                      "timestamp": 1326471017749,
                      "args": {
                        "note_id": "$1326470987549",
                        "content": "This is a test"
                      }
                    }
                    
note_delete: Deleting a note
                    {
                      "type": "note_delete",
                      "timestamp": 1326471017759,
                      "args": {
                        "note_id": "$1326470987549",
                        "item_id": "$1326470987649"
                      }
                    }
                    

Filters

filter_add: Add a filter
                    {
                      "type": "filter_add",
                      "timestamp": 1426471017750,
                      "temp_id": "$1426470987550",
                      "args": {
                        "name": "Priority 1",
                        "query": "p1",
                        "item_order": 1
                      }
                    }
                    
filter_update: Update a filter
                    {
                      "type": "filter_update",
                      "timestamp": 1426471017751,
                      "args": {
                        "id": "$1426470987551",
                        "name": "Priority 2",
                        "query": "p2",
                      }
                    }
                    
filter_delete: Delete a filter
                    {
                      "type": "filter_delete",
                      "timestamp": 1426471017752,
                      "args": {
                        "id": "$1426470987551",
                      }
                    }
                    

Reminders

Only available for premium users.
reminder_add: Add a reminder
For a reminder with a relative timestamp (calculated as the offset from the item timestamp)
                    {
                      "type": "reminder_add",
                      "timestamp": 1426471017750,
                      "temp_id": "$1426470987550",
                      "args": {
                        "item_id": "$1326470987649",
                        "service": "email",
                        "minute_offset": 30
                      }
                    }
                    
For a reminder with an absolute timestamp. The due date should be converted to UTC timezone.
                    {
                      "type": "reminder_add",
                      "timestamp": 1426471017750,
                      "temp_id": "$1426470987550",
                      "args": {
                        "item_id": "$1326470987649",
                        "service": "email",
                        "due_date_utc": "2013-01-01T14:00",
                        "date_string": "tod @ 6pm"
                      }
                    }
                    
reminder_update: Update a reminder
                    {
                      "type": "reminder_update",
                      "timestamp": 1426471017751,
                      "args": {
                        "id": "$1426470987551",
                        "minute_offset": null,
                        "due_date_utc": "2013-01-01T15:00",
                        "date_string": "tod @ 7pm"
                      }
                    }
                    
reminder_delete: Delete a reminder
                    {
                      "type": "reminder_delete",
                      "timestamp": 1426471017752,
                      "args": {
                        "id": "$1426470987551",
                      }
                    }