Marvin API - amazingmarvin/MarvinAPI GitHub Wiki
Use Marvin's API to access data that doesn't live in your user database, or for simplicity's sake. We will be adding more endpoints soon.
Basic structure
Marvin's API involves GET and POST requests to https://serv.amazingmarvin.com/api/:endpoint
. POST bodies and most responses are encoded as JSON.
Credentials
Include an HTTP header X-API-Token
using the API_TOKEN
found here if the endpoint requires limited access, or the header X-Full-Access-Token
using the FULL_ACCESS_TOKEN
also found here if the endpoint requires full access. The idea behind this system is that you might want to give Zapier the ability to create tasks, but not to read your data. If there's user demand then we'll make a proper OAuth system with permissions.
Rotation
Accidentally exposed an API_TOKEN
? You can get rotate your credentials in the API strategy settings within Marvin.
Endpoints
Test credentials
stable
You can test whether your credentials are correct with a POST:
POST /api/test
X-API-Token: XYZ
=>
"OK"
Create a task
stable, but new document's _id and _rev will be included in the response in the future
You can quickly create a task with a POST request:
Note: send actual JSON. The following has inline documentation.
POST /api/addTask
X-API-Token: XYZ
{
"done": false,
"day": "2020-07-17",
"title": "Work 30m homework #School", // supports some autocompletion (parent, day, dueDate, plannedWeek, plannedMonth, timeEstimate, labels, isStarred). Use header X-Auto-Complete=false to disable autocompletion.
"parentId": "xyz", // ID of parent category/project
"labelIds": ["abc", "def"], // IDs of labels
"firstScheduled": "2020-07-17",
"rank": 999,
"dailySection": "Morning",
"bonusSection": "Essential", // or "Bonus"
"customSection": "a3gnaiN31mz", // ID of custom section (from profile.strategySettings.customStructure)
"timeBlockSection": "b00m3feaMbeaz", // ID of time block
"note": "Problems 1-4",
"dueDate": "2020-07-20",
"timeEstimate": 3600000, // ms
"isReward": false,
"isStarred": 3,
"isFrogged": 2,
"plannedWeek": "2020-07-12",
"plannedMonth": "2020-07",
"rewardPoints": 1.25,
"rewardId": "anbeN3mRneam", // Unique ID of attached Reward
"backburner": true, // Manually put in backburner (can also be backburner from label, start date, etc.)
"reviewDate": "2020-09-09",
"timeEstimate": 300000, // duration estimate in ms
"itemSnoozeTime": 1599577206923, // Date.now() until when it's snoozed
"permaSnoozeTime": "09:00",
// Time offset in minutes
//
// Added to time to fix time zone issues. So if the user is in Pacific time,
// this would be -8*60. If the user added a task with +today at 22:00 local
// time 2019-12-05, then we want to create the task on 2019-12-05 and not
// 2019-12-06 (which is the server date).
"timeZoneOffset": 60,
}
Unless you add an X-Auto-Complete=false
header, the title will be processed similar to autocompletion within Marvin. So if you use "Example task +today", then the task will be scheduled for today and " +today" will be removed from the title. If you put "#Parent Category" or "@label1 @label2" in the title, they will be resolved to their IDs when you open Marvin.
See [Marvin data types]] for documentation about how these fields work. Only the above fields are consumed by this API. If you want to set other fields, [add directly to the couchdb.
Working sample code (just change the API token):
curl -H 'X-API-Token: test' -XPOST -d '{"title": "Example API task +today"}' https://serv.amazingmarvin.com/api/addTask
Mark a task done
experimental
You can mark a task done by POSTing its ID to /api/markDone
.
POST /api/markDone
X-API-Token: XYZ
{
"itemId": "x23n123nk",
"timeZoneOffset": 60
}
Your timezone offset, in minutes, should be included in order to correctly determine the date when the task was marked done.
Many things happen in the Marvin client when you mark a task done. Some of these are implemented, and more will be implemented in the future. If a feature is missing that affects your workflow, please create an issue.
- Handle pinned tasks
- Stop tracking time
- Repeat after X days (echo)
- Repeat after X days - subtasks
- Repeat after X days - due date
- Repeat after X days - end date
- Repeat after X days - plannedWeek/plannedMonth
- Repeat after X days - limit to weekdays
- Give reward points
- Attached rewards
- Kudos
- Update "worked on at"
Won't be implemented:
- smart reward points
Create a project
stable
You can quickly create a project with a POST request:
Note: send actual JSON. The following has inline documentation.
POST /api/addProject
X-API-Token: XYZ
{
"done": false,
"day": "2020-07-17",
"title": "Work 30m homework #School", // supports some autocompletion (parent, dueDate, labels)
"parentId": "xyz", // ID of parent category/project
"labelIds": ["abc", "def"], // IDs of labels
"firstScheduled": "2020-07-17",
"rank": 999,
"dailySection": "Morning",
"bonusSection": "Essential", // or "Bonus"
"customSection": "a3gnaiN31mz", // ID of custom section (from profile.strategySettings.customStructure)
"timeBlockSection": "b00m3feaMbeaz", // ID of time block
"note": "Problems 1-4",
"dueDate": "2020-07-20",
"timeEstimate": 3600000, // ms
"isReward": false,
"priority": "high", // "high", "mid", or "low"
"isFrogged": 2,
"plannedWeek": "2020-07-12",
"plannedMonth": "2020-07",
"rewardPoints": 1.25,
"rewardId": "anbeN3mRneam", // Unique ID of attached Reward
"backburner": true, // Manually put in backburner (can also be backburner from label, start date, etc.)
"reviewDate": "2020-09-09",
"timeEstimate": 300000, // duration estimate in ms
"itemSnoozeTime": 1599577206923, // Date.now() until when it's snoozed
"permaSnoozeTime": "09:00",
// Time offset in minutes
//
// Added to time to fix time zone issues. So if the user is in Pacific time,
// this would be -8*60. If the user added a task with +today at 22:00 local
// time 2019-12-05, then we want to create the task on 2019-12-05 and not
// 2019-12-06 (which is the server date).
"timeZoneOffset": 60,
}
If not scheduled, use day=null
.
Create an event
experimental
You can quickly create an event with a POST request:
Note: send actual JSON. The following has inline documentation.
Note: calendar sync happens on the client. You must have Marvin running on one of your devices in order for this event to be calendar synced!
POST /api/addEvent
X-API-Token: XYZ
{
"title": "Haircut",
"note": "Problems 1-4", // Use markdown
"length": 3600000, // ms
"start": "2021-08-21T14:30:00.000Z", // ISO formatted start time
}
Read any doc
stable
With the fullAccessToken
you can GET any individual document in the couchdb database by ID.
Bug fix / breaking change: in the past this API only worked when reading ProfileItems
since it returned the val
field directly. Now the entire document is returned, even when db="ProfileItems"
.
GET /api/doc?id=strategySettings.labelSettings.groups
X-Full-Access-Token: ABC
=>
{
"_id" : "strategySettings.labelSettings.groups",
"_rev" : "12-8dcc836705e9f1ae98f1525092b82b31",
"createdAt" : 1564154150216,
"db" : "ProfileItems",
"fieldUpdates" : {
"createdAt" : 1568180186429,
"db" : 1568180586429,
"updatedAt" : 1568180536429,
"val" : 1582132559581
},
"updatedAt" : 1582132559548,
"val" : {
"84fYiqsxgZadr" : {
"_id" : "81fYbqsxGZadr",
"createdAt" : 1564159272192,
"icon" : "cxicons8-circled-7",
"isExclusive" : false,
"isMenu" : true,
"rank" : 4,
"title" : "numbers"
}
}
}
Update any doc
experimental
With the fullAccessToken
you can update any doc. It is recommended that you update fieldUpdates.FIELD
in order to get functioning conflict resolution and updatedAt
for correct display within Marvin.
Be careful with this API! Updating a document, especially a setting, and giving it the wrong shape might cause Marvin to crash on startup. You can probably remedy this with /api/doc/delete
or by sending another /api/doc/update
with the correct value, but it won't always be obvious to find out what went wrong. You may have to contact support in order to get a working Marvin again. Read the Marvin data types documentation carefully to avoid creating invalid documents.
POST /api/doc/update
X-Full-Access-Token: ABC
{
"itemId": "xy12n3i123",
"setters": [
{ "key": "done", "val": true },
{ "key": "fieldUpdates.done", "val": 1648122403647 },
{ "key": "updatedAt", "val": 1648122403647 }
]
}
=>
{
"_id": "xy12n3i123",
"_rev": "2-xyz",
"done": true,
"fieldUpdates": {
"done": 1648122403647
},
"updatedAt": 1648122403647,
"title": "Example task",
...
}
Create any doc
experimental
With the fullAccessToken
you can create any doc. It is recommended that you include createdAt
for correct display within Marvin.
Be careful with this API! Creating a document, especially a setting, and giving it the wrong shape might cause Marvin to crash on startup. You can probably remedy this with /api/doc/delete
or by sending a /api/doc/update
with the correct value, but it won't always be obvious to find out what went wrong. You may have to contact support in order to get a working Marvin again. Read the Marvin data types documentation carefully to avoid creating invalid documents.
POST /api/doc/create
X-Full-Access-Token: ABC
{
"_id": "xy12n3i123",
"db": "Tasks",
"title": "Example task",
"done": false,
"createdAt": 1649150426400
}
=>
{
"_id": "xy12n3i123",
"_rev": "1-xyz",
"title": "Example task",
"done": false,
"createdAt": 1649150426400
}
Delete any doc
experimental
With the fullAccessToken
you can delete any doc.
Be careful with this API! Marvin's Trash functionality is client-side only, so you won't be able to recover any documents deleted in this way (unless you implement your own trash functionality). Deleting a document shouldn't cause Marvin to crash on startup.
POST /api/doc/delete
X-Full-Access-Token: ABC
{
"itemId": "xy12n3i123"
}
Get the currently tracked task
stable, but will be extended to include how long tracked
GET /api/trackedItem
X-API-Token: XYZ
=>
{
"_id": "a12345",
"db": "Tasks",
"title": "Work 30m on homework"
}
Get child tasks/projects of a category/project
experimental
Marvin has infinite nesting of tasks/projects with categories/projects. The ID of an item's parent is stored in its parentId
field. You can use the /api/children
endpoint to query the children of a category/project. This returns all items that have parentId
equal to the ID you provide. You will have to do additional queries if you want to retrieve the nested grandchildren, and further descendants. Note: this endpoint previously returned done items but now only returns open items. Please get in touch if you need an endpoint that includes done items.
GET /api/children?parentId=unassigned
X-API-Token: XYZ
X-Parent-Id: unassigned // optional, can be used instead of query parameter
=>
[...]
The response is an array of Projects and Tasks.
Get tasks and projects scheduled today (including rollover/auto-schedule due items if enabled)
stable, but improvements coming
GET /api/todayItems
X-API-Token: XYZ
=>
[...]
Time zone issues are possible here (the server is UTC+0), so it's best to provide a date. This can either be done using a query parameter or the X-Date
header. In both cases, use the date format "YYYY-MM-DD"
.
GET /api/todayItems?date=2021-11-15
X-API-Token: XYZ
=>
[...]
OR
GET /api/todayItems
X-API-Token: XYZ
X-Date: 2021-11-15
=>
[...]
Get open Tasks and Projects that are due today (or earlier)
stable, but improvements coming
GET /api/dueItems
X-API-Token: XYZ
=>
[...]
You can also choose a date other than today by setting the by
query param. This is a good idea in any case since you may or may not be in the same time zone as the server.
GET /api/dueItems?by=2022-09-11
X-API-Token: XYZ
=>
[...]
Get a list of today's time blocks
experimental
GET /api/todayTimeBlocks?date=2023-02-28
X-API-Token: XYZ
X-Date: 2023-02-28 // Can be sent instead of query parameter
=>
[...]
The response is an array of Time Blocks.
Get a list of all categories
stable
You can access a list of all your categories with a GET request. See Categories for documentation of the data format.
GET /api/categories
X-API-Token: XYZ
=>
[{ "_id": "a4123412", "title": "Work", "parentId": "root", "color": "#4184a0", ... }, ...]
Get a list of all labels
stable
Get a list of all labels, in their sort order (used in sort by label).
GET /api/labels
X-API-Token: XYZ
=>
[{ "_id": "abcdefg1234", "title": "quick", "color": "#f0a0a0", "icon": "tag", "groupId": "5421fabcdae" }, ...]
The label groups can be found by reading the sync database document profile.strategySettings.labelSettings.groups
.
See documentation for labels and label groups
Start/stop time tracking
You can use the /api/track
endpoint to start or stop time tracking a task by its ID
POST /api/track
POST /api/time # alias you can use if "track" is in a browser extension blacklist
X-API-TOKEN: XYZ
{
taskId: "abc",
action: "START"
}
=>
{
startId: "abc",
startTimes: [1595791080814],
stopId: "xyz", // or null
stopTimes: [1595791066096, 1595791080814],
issues: ["Wanted to..."],
}
Valid actions are "START"
and "STOP"
.
NOTE: you are responsible for updating the stopped task's duration and times! Otherwise Marvin's UI will be missing data in some places. How to update? Updating documents
See Marvin data types#Tasks for documentation about duration and times.
See Marvin data types#Time Tracking for more documentation about how time tracking times are stored.
Getting time track info
Marvin caches time track data in task.times
and task.duration
. But if you use the API to do time tracking and don't update the task, or if something went wrong with sync, then this info might be missing. You can get the source of truth about time track data using the /api/tracks
endpoint.
You can request the time track data for up to 100 tasks at once. This API will then return an array of time track data with taskId
and a times
array. See Marvin data types#Tasks for documentation about times.
POST /api/tracks
POST /api/times # alias you can use if "track" is in a browser extension blacklist
X-API-TOKEN: XYZ
{
"taskIds": ["nfieamewpemnfiqe"],
}
=>
[
{ "taskId": "nfieamewpemnfiqe", "times": [1625985037144, 1625985043470, 1625985049000, 1625985054374] }
]
Claiming reward points
Completed a task or celebrating something? Claim some reward points.
POST /api/claimRewardPoints
X-API-TOKEN: XYZ
{
"points": 1.5,
"itemId": "an2m1n213ml", // Task ID or "MANUAL" for manual point reward
"date": "2020-09-08", // Used to track points today
"op": "CLAIM",
}
=> user profile
Unclaiming reward points
User error? Task marked incomplete? Unclaim the reward points.
POST /api/unclaimRewardPoints
X-API-TOKEN: XYZ
{
"itemId": "an2m1n213ml", // Which itemId to undo (determines how many points)
"date": "2020-09-08", // Used to track points today
"op": "UNCLAIM",
}
=> user profile
Spending reward points
POST /api/spendRewardPoints
X-API-TOKEN: XYZ
{
"points": 2.5,
"date": "2020-09-08", // Used to track points spent today
"op": "SPEND",
}
=> user profile
Reset reward points
Permanently deletes earn/spend history and resets reward points to 0.
POST /api/resetRewardPoints
X-FULL-ACCESS-TOKEN: XYZ
=> user profile
Get Marvin Kudos info
GET /api/kudos
X-API-TOKEN: XYZ
=>
{
"kudos": 0,
"level": 1,
"kudosRemaining": 350
}
Me
Retrieve some information about your account.
GET /api/me
X-API-Token: XYZ
=>
{
"email": "[email protected]",
...
}
See Marvin Data Types#Profile for documentation on which fields are available and what they mean.
Reminders
Reminders are attached to Tasks for display in Marvin (see documentation for Tasks). But they must also be set on the server in order to get push notification on your mobile device. Use the following Reminder APIs to list, set, and delete Reminders on the server. Note: if you have cloud sync disabled and don't want to share task titles with Marvin's servers, then don't use these APIs! These APIs are not used within Marvin when your cloud sync is disabled in order to avoid leaking Task data.
Get a list of all reminders
Sending a GET to the /api/reminders
endpoint will return an array of all reminders that are currently scheduled. See documentation for Reminders.
GET /api/reminders
X-Full-Access-Token: ABC
=>
Reminder[]
Set reminders
You can set one or more reminders using the /api/reminder/set
endpoint. POST an array of Reminders to set them. See documentation for Reminders. Reminders are currently only pushed to mobile phones, so make sure that you have installed the Amazing Marvin mobile app and logged in. If the Reminders you create correspond to scheduled tasks, be sure to update the reminder info in the task in order to keep the Marvin user interface accurate.
POST /api/reminder/set
X-API-Token: XYZ
{
"reminders": [{
"time": 1678098457794,
"offset": 5,
"reminderId": "AA64AC0A-42BD-4EC7-A9F9-8E27BDFA3665",
"type": "M",
"title": "Example reminder",
"snooze": 9,
"autoSnooze": true,
"canTrack": false
}]
}
=>
"OK"
}
Delete one or more Reminders
Be sure to also delete the reminder info in the corresponding Tasks in order to keep the Marvin user interface accurate.
POST /api/reminder/delete
X-API-Token: XYZ
{
reminderIds: String[], // IDs of Reminders to delete
}
=>
"OK"
Delete all Reminders
Be sure to also delete the reminder info in the corresponding Tasks in order to keep the Marvin user interface accurate.
POST /api/reminder/deleteAll
X-Full-Access-Token: ABC
=>
"OK"
Get Goals
stable
See Goals for documentation of the data format.
GET /api/goals
X-API-Token: XYZ
=>
[{ _id: "123", title: "Example Goal", ... }]
Habits
The /api/updateHabit
endpoint is used to record, undo record, and rewrite the history of habits. By default the endpoints only affect the backend database (which is the source of truth). You should either update the Habit stored in cloudant yourself (See Database Access), or set updateDB=true
to have the server do it for you.
Record a habit
experimental
POST /api/updateHabit
X-API-Token: XYZ
{
"habitId": "1n2ifni0qnf31",
"time": 1678378323530,
"value": 4
"updateDB": true
}
=>
New Habit Value
Undo last habit recording
experimental
POST /api/updateHabit
X-API-Token: XYZ
{
"habitId": "1n2ifni0qnf31",
"undo": true,
"updateDB": true
}
=>
New Habit Value
Rewrite habit history
experimental
POST /api/updateHabit
X-API-Token: XYZ
{
"habitId": "1n2ifni0qnf31",
"history": [1646092800000, 2, 1678378323530, 4],
"updateDB": true
}
=>
New Habit Value
Get a Habit
experimental
You can retrieve a Habit, including its full history, using the /api/habit
endpoint. This retrieves a Habit.
GET /api/habit?id=abc
X-API-Token: XYZ
=>
{...}
List Habits
experimental
You can retrieve a list of all your Habits, with full history, using the /api/habits
endpoint. This retrieves an array of Habits.
GET /api/habits
X-API-Token: XYZ
=>
[...]
If you include ?raw=1
, then the entire habit objects will be returned, rather than just history information. You will need to send the full access token in this case.