Statement of purpose
I do solemnly swear (or affirm) that this is an API feature request and not a Marvin feature request.
Three behaviors we ran into while building an MCP server against the API (amazing-marvin-complete-mcp). None of them is necessarily a bug, but all three cost real debugging time and none is currently documented. All verified against the live API on 2026-08-19.
1. Non-raw GET /api/habits reads a lazily-created tracking registry — a never-checked-in habit is invisible
GET /api/habits (without ?raw=1) doesn't read the Habits documents; it reads a server-side tracking registry that is only created on the habit's first check-in. Consequences:
- A habit that has never been recorded is completely absent from the response — it looks like the user has no such habit.
- The entries that do appear carry only
habitId + history, no titles.
- After an undo (
/updateHabit with undo: true), the registry entry remains (with empty history), so the habit stays visible from then on.
Verified sequence: habit invisible before first /updateHabit check-in → visible after → still visible (empty history) after undo. ?raw=1 (Full Access token) returns the actual Habit documents including titles and is the reliable way to enumerate habits. A sentence about this in the habits docs would save integrators a lot of head-scratching.
2. Task reminders are two writes; /api/reminder/set only does one of them
A reminder attached to a task exists in two places: reminder fields on the task document, and a server-side reminder entry. Only the app keeps the two in sync. /api/reminder/set creates just the server-side entry, so an API user who "adds a reminder to a task" this way creates an entry the app's task UI doesn't know about — and deleting a task-linked reminder via /api/reminder/delete leaves stale reminder fields on the task document. Standalone reminders (type M) don't have this problem.
Worth documenting which fields on the task document the app expects to be set alongside the server-side entry — or noting that /reminder/set is only intended for standalone reminders.
3. Reward points claimed with itemId: "MANUAL" can't be reversed
/api/claimRewardPoints accepts itemId: "MANUAL", but the server stores no entry for it, so it can't be undone:
/api/unclaimRewardPoints with itemId: "MANUAL" → 404 No such entry (with or without a points field).
- A negative
claimRewardPoints as a counter-booking → 400.
The app itself never uses MANUAL (checked the web bundle), so this is API-only surface. If irreversibility is intended, a note in the docs would help; the only workaround today is /api/spendRewardPoints as a manual correction.
Happy to provide exact request/response pairs for any of these.
Statement of purpose
I do solemnly swear (or affirm) that this is an API feature request and not a Marvin feature request.
Three behaviors we ran into while building an MCP server against the API (amazing-marvin-complete-mcp). None of them is necessarily a bug, but all three cost real debugging time and none is currently documented. All verified against the live API on 2026-08-19.
1. Non-raw
GET /api/habitsreads a lazily-created tracking registry — a never-checked-in habit is invisibleGET /api/habits(without?raw=1) doesn't read the Habits documents; it reads a server-side tracking registry that is only created on the habit's first check-in. Consequences:habitId+ history, no titles./updateHabitwithundo: true), the registry entry remains (with empty history), so the habit stays visible from then on.Verified sequence: habit invisible before first
/updateHabitcheck-in → visible after → still visible (empty history) after undo.?raw=1(Full Access token) returns the actual Habit documents including titles and is the reliable way to enumerate habits. A sentence about this in the habits docs would save integrators a lot of head-scratching.2. Task reminders are two writes;
/api/reminder/setonly does one of themA reminder attached to a task exists in two places: reminder fields on the task document, and a server-side reminder entry. Only the app keeps the two in sync.
/api/reminder/setcreates just the server-side entry, so an API user who "adds a reminder to a task" this way creates an entry the app's task UI doesn't know about — and deleting a task-linked reminder via/api/reminder/deleteleaves stale reminder fields on the task document. Standalone reminders (typeM) don't have this problem.Worth documenting which fields on the task document the app expects to be set alongside the server-side entry — or noting that
/reminder/setis only intended for standalone reminders.3. Reward points claimed with
itemId: "MANUAL"can't be reversed/api/claimRewardPointsacceptsitemId: "MANUAL", but the server stores no entry for it, so it can't be undone:/api/unclaimRewardPointswithitemId: "MANUAL"→404 No such entry(with or without apointsfield).claimRewardPointsas a counter-booking →400.The app itself never uses
MANUAL(checked the web bundle), so this is API-only surface. If irreversibility is intended, a note in the docs would help; the only workaround today is/api/spendRewardPointsas a manual correction.Happy to provide exact request/response pairs for any of these.