Using it with AI agents
POST /api/mcp is a Model Context Protocol
server: the same keys and the same permissions as the API, and a set of tools a
model can call. It is what "put that on my to-do list" means when the thing
being asked is an assistant rather than the app.
The examples below use https://app.ontoplano.com. Your own instance answers at
https://your-host/api/mcp — the address you type into the browser, with
/api/mcp after it.
Connecting without a key
Paste your instance's address into an assistant that speaks MCP — Claude, ChatGPT, or anything else with a connector screen — and it will do the rest:
https://app.ontoplano.com/api/mcp
The assistant discovers that the address is protected, registers itself, and sends you here. You see a screen on your own instance saying which assistant is asking and what it would be able to do, you press Connect it, and you are handed back. No key is typed, pasted or stored by anybody.
What it would be able to do is a list of tick boxes, gathered by what they are
about — your week, money, the diary, the house — and everything the assistant
asked for is ticked. Untick a line, or a whole heading, and the key it walks
away with cannot reach that at all: a tool whose permission was not granted is
not offered to the assistant, so one that may not read your diary does not know
write_entry exists.
What it gets is an ordinary key, made for it and named after it, so it stands in the list under Settings → AI & Integrations → Integrations with a revoke button beside it like every other. Deleting is a box of its own on that screen and it starts unticked — the connection reads and writes, and takes nothing away unless you said it may.
Two details for anyone implementing against it: the flow is the authorization
code grant with PKCE (S256 only — there is no plain, and no implicit
grant), and the discovery documents are at
/.well-known/oauth-protected-resource and
/.well-known/oauth-authorization-server. The token that comes out does not
expire, so there is no refresh token to hold; revoking is what ends it.
Make a key
Settings → AI & Integrations → AI → Create a key. It is shown once, so keep the tab open while you set the assistant up.
Every permission the tools use is ticked to begin with, reading and writing
both. Untick what you would rather it did not see — a tool whose permission was
not granted is not offered to the assistant at all, so a read-only key does not
know that add_task exists.
Deleting is a box of its own below that table, and the one thing that starts unticked. Without it an assistant can add and change but never remove, and the tools that delete are not offered to it either; tick it if you want them.
The Integrations tab beside it has the wider form — every permission, the ones an assistant has no use for included, and an expiry date — for a key meant to run a script rather than an assistant. Keys are revoked there too, and a revoked key stops working on the next request.
Connect it
Just tell it
Any assistant with a terminal can set itself up. Paste this, with your key in place of the last line:
I use ontoplano — a life management app my assistant can connect to.
Please connect to it and use it whenever I ask you about my week, my to-do
list, my diary, my notebooks, my shopping list or my recipes.
Address: https://app.ontoplano.com/api/mcp
Protocol: MCP, over streamable HTTP (stateless — no session, no GET)
Key: send it as an "Authorization: Bearer" header
Once you are connected, tell me what is on my plan today. Do not change
anything in my account until I ask you to.
Key: onto_YOUR_KEY_HERE
It names what the app is for, so the assistant reaches for it instead of asking you to repeat yourself, and it says not to write anything yet.
Claude
The plugin. Two lines inside Claude Code, and the shortest route:
/plugin marketplace add ontoplano/claude-plugin
/plugin install ontoplano@ontoplano
It asks for the address of your ontoplano and a key when it installs, and keeps
the key in the system keychain rather than in a file. It also brings /today,
/week and /capture, and the standing instructions an assistant otherwise
needs told every conversation: read before writing, say what you changed.
The command line. One command, and it writes the configuration:
claude mcp add --scope user --transport http ontoplano https://app.ontoplano.com/api/mcp \
--header "Authorization: Bearer onto_YOUR_KEY_HERE"
--scope user is what makes it permanent everywhere. Without it the server is
written into whichever project you were standing in.
Claude Desktop. Its connector screen speaks OAuth, so the address on its
own is the whole setup — see Connecting without a key
above. mcp-remote is still there for a key you would rather hand over
yourself:
{
"mcpServers": {
"ontoplano": {
"command": "npx",
"args": [
"-y",
"mcp-remote",
"https://app.ontoplano.com/api/mcp",
"--header",
"Authorization:Bearer onto_YOUR_KEY_HERE"
]
}
}
}
No space after that colon: Desktop does not escape spaces inside an argument, and the header arrives cut in half if you leave one.
Codex
~/.codex/config.toml. It reads the key out of the environment rather than out
of the file:
[mcp_servers.ontoplano]
url = "https://app.ontoplano.com/api/mcp"
bearer_token_env_var = "ONTOPLANO_KEY"
An export lasts as long as the shell it was typed into, so put it in the file your shell starts from:
echo 'export ONTOPLANO_KEY=onto_YOUR_KEY_HERE' >> ~/.bashrc # zsh: ~/.zshrc
codex mcp list says whether it connected.
Cursor
~/.cursor/mcp.json, where the header is written out in full:
{
"mcpServers": {
"ontoplano": {
"url": "https://app.ontoplano.com/api/mcp",
"headers": { "Authorization": "Bearer onto_YOUR_KEY_HERE" }
}
}
}
Restart the client after editing its file. If it lists ontoplano's tools, it worked.
Blocks and to-dos are different things
A to-do is something to do with no hour attached; a block is an hour.
"Ring the dentist" is a to-do, "deep work from 9 to 11" is a block. An assistant
that only has add_task answers the second by writing the time into the title,
and your day still looks empty.
With schedule:write it puts a real block on the day and can answer for the
ones already there. finish_block takes both answers, and skipped is a real
answer — a week that can only be told about the parts that went well starts
lying by the second one.
change_block moves and renames; cancel_block takes something off a day.
Cancelled is not skipped: skipped means you meant to do it and did not, and
the weekly review asks about it; cancelled means the plan was wrong. An
assistant with only one of them uses the wrong one when it moves something.
All of it is that day only. Moving this Thursday's gym never moves gym, which is what alt-dragging it in the app does too.
The pictures and recordings in what it reads
A note, a task and an idea can all hold a picture or a recording, and what a
tool hands back is the markdown that refers to it: ,
[said](/media/audio/44). The media tool turns that link into the file
itself — hand it the link exactly as the writing writes it, and the picture
comes back as a picture:
{ "name": "media", "arguments": { "path": "/media/31" } }
/media/audio/44 for a recording. The same file is also an ordinary HTTP
request, for a script that holds the key itself rather than speaking the
protocol:
curl -H "Authorization: Bearer $ONTOPLANO_KEY" \
https://your-instance/media/31 --output picture.png
Both doors ask the same question, and the answer is the permission that reads the thing the file is in.
A picture in a note wants notes:read, one on a task tasks:read, a face
people:read, a recipe photograph kitchen:read. There is no separate media
grant — a file answers to whatever refers to it, and one that nothing refers
to answers to nobody. A key tied to one notebook reaches the files inside that
notebook and no others.
Anything the key may not reach is a 404, the same as an id that never existed, so there is nothing to learn by walking the numbers.
How it behaves
- It offers only what the key holds.
tools/listis filtered by permission, and the permission is checked again on every call. - Nothing in it is new behaviour. Every tool calls the same function the web page calls, so the same limits, validation and ownership checks apply.
- It is stateless. No session and no event stream: every request carries its
own key, and a
GETanswers 405. - A refusal is an answer. "That is not a date" comes back as tool content the
model can read and act on, not as a protocol error. Its
structuredContentcarries acodesoftware can branch on — the same words the JSON API answers with:not_found,validation_error,conflict,plan_limit,forbidden,rate_limited— beside the sentence, anddetailswhere the refusal knows more. - Deleting is its own permission. Tools that remove a row for good need the
destructivegrant, and without it they are not offered at all. - Every write answers with what it replaced —
beforeandafter, and for a delete the whole removed row — so a bad call can be put back from the conversation itself. Two exceptions say so in their own description:tag_taskanswers with the labels and nothing else, because two copies of a task to report one label is most of what marking a list costs, and the person's own copy of the change is in the log under Settings → Integrations either way. - A listing answers with a line. A task comes back as what it is, where it
stands and its labels; a note as its name, its labels and an opening.
verbose: truegives the whole row, andfields: "title,notes"gives exactly those. This is a budget, not a limit: a model reading a list to find one thing pays for forty rows it will not use, three times over — on the way in, on the way out, and again next turn. - A line says what the row is about, and names the pictures it refers to.
A task's line carries an opening of its notes and the links in them; a note's
line the same.
mediafetches one when it turns out to matter — a list is rarely read for its pictures, and always read to find something. - A list can be asked for narrowly.
status,tags,withoutTagsandtaggedSinceon the task list;tagsandtaggedSinceon notes.tagstakes as many labels as you like and answers with anything carrying any one of them, so a queue spread overu5,e2andi5is one call rather than three. The date read is the label's own — it does not move when the thing is edited — so "what went into review since this morning" is one call. up_nextanswers what to do next, by the ratings on the tasks themselves: most urgent first, then the easiest, then the one most wanted. All three run the same way — five is the most of what the word says. A rating nobody set is not a zero: it counts as 2.5, the middle of the scale, so a task marked 3 beats an unrated one and 0–2 are the tiers that mean "later".- A change names only what changes. Every
change_*andedit_*tool takes an id and the fields being changed; a field left out keeps what it had. Where a field can be emptied, its description says how —nullfor a rating, an empty string for notes,{}for attributes. An argument that holds a whole set, such astagsonchange_task, replaces it;tag_taskadds and removes one label at a time. - A change can refuse to overwrite somebody else's. A
change_*oredit_*tool on a thing that keeps anupdatedAttakesifUpdatedAt: pass the stamp you read, and if the thing has changed since, nothing is written and the refusal's code isconflict, with the currentupdatedAtin its details. Every change on those tools answers with its newupdatedAt. - A create can be sent again. Tools that make or count something — every
add_*,write_entry,log_*,record_*,tick_habit,set_alarm— take arequestIdyou choose. Sent again with the same arguments within a day, the call answers with the first answer, markedreplayed: true, and nothing is made twice; so an assistant that lost an answer can retry without asking whether the first one landed. The same id with different arguments is refused as aconflict. - A list comes a page at a time. A tool marked "answers a page" takes
limitandoffset, and answers withcount(what is in this answer) andtotal(what matched). While more is left the answer also carriesremainingandnextOffset; passnextOffsetasoffsetto read on. NonextOffsetmeans nothing is left. - A wrong argument is refused before anything runs. An argument the tool
does not take, a string where it wants a number, a value outside its enum or
its bounds: the answer is a JSON-RPC error
-32602naming the argument, withcode: "validation_error"in itsdata, and nothing is written.
Common requests
What somebody asks, the call an assistant makes for it, and the part of the answer worth reading. They run in this order against a fresh account in the test suite, which checks each answer holds what is printed here.
“Start a notebook for the kitchen, under Home.”
{
"name": "add_notebook",
"arguments": { "title": "Kitchen", "folder": "Home" }
}
The answer holds, among the rest:
{ "id": 1 }
“Add ‘descale the kettle’ to the kitchen notebook.”
{
"name": "add_task",
"arguments": { "title": "Descale the kettle", "notebookId": 1 }
}
The answer holds, among the rest:
{ "id": 1, "before": null, "after": { "id": 1, "title": "Descale the kettle" } }
“And ‘fix the cupboard hinge’.”
{
"name": "add_task",
"arguments": { "title": "Fix the cupboard hinge", "notebookId": 1 }
}
The answer holds, among the rest:
{ "id": 2 }
“The hinge is urgent.”
{ "name": "change_task", "arguments": { "id": 2, "urgency": 5 } }
The answer holds, among the rest:
{ "after": { "id": 2, "ratings": { "urgency": 5 } } }
Only id and the field being changed are sent; everything left out keeps what it had.
“What should I do next?”
{ "name": "up_next", "arguments": {} }
The answer holds, among the rest:
{
"items": [{ "id": 2, "title": "Fix the cupboard hinge" }],
"count": 1,
"total": 2,
"remaining": 1,
"nextOffset": 1
}
One task by default. remaining and nextOffset are there because more is left: passing offset: 1 reads the next one.
“Actually, the hinge can wait — forget the urgency.”
{ "name": "change_task", "arguments": { "id": 2, "urgency": null } }
The answer holds, among the rest:
{
"before": { "ratings": { "urgency": 5 } },
"after": { "ratings": { "urgency": null } }
}
null clears a rating; leaving urgency out would have kept it.
“I descaled the kettle.”
{ "name": "finish_task", "arguments": { "id": 1 } }
The answer holds, among the rest:
{ "ok": true, "after": { "id": 1, "status": "done" } }
“Which kitchen tasks are still open?”
{
"name": "tasks",
"arguments": { "notebookId": 1, "status": "open", "fields": "title,status" }
}
The answer holds, among the rest:
{
"items": [{ "id": 2, "title": "Fix the cupboard hinge", "status": "todo" }],
"count": 1,
"total": 1
}
No nextOffset in the answer means there is nothing more to read.
“Note down that the oven runs hot.”
{
"name": "write_entry",
"arguments": {
"content": "The oven runs about 20° hot — set it lower than the recipe says."
}
}
The answer holds, among the rest:
{ "id": 1 }
“File that note under the kitchen notebook.”
{ "name": "move_notes", "arguments": { "ids": [1], "notebookId": 1 } }
The answer holds, among the rest:
{ "ok": true, "moved": 1 }
“What is labelled kitchen?”
{ "name": "tasks", "arguments": { "tag": "kitchen" } }
The answer holds, among the rest:
{
"count": 0,
"total": 0,
"warning": "`tag` is deprecated and will be removed in 0.185.0. …"
}
tag is the old spelling of tags. It still works until the release named, and the answer says so.
“Make the hinge a 3 for urgency.”
{ "name": "change_task", "arguments": { "id": 2, "urgncy": 3 } }
Refused before the tool runs, as a JSON-RPC error -32602 with the message “urgncy is not an argument this tool takes.”
A misspelt argument is named back, and nothing is written.
“Put ‘buy light bulbs’ on the list.”
{
"name": "add_task",
"arguments": { "title": "Buy light bulbs", "requestId": "5f1c-bulbs" }
}
The answer holds, among the rest:
{ "id": 3 }
requestId is any string the assistant picks for this one call.
“(No answer came back, so the assistant sends the same call again.)”
{
"name": "add_task",
"arguments": { "title": "Buy light bulbs", "requestId": "5f1c-bulbs" }
}
The answer holds, among the rest:
{ "id": 3, "replayed": true }
Same requestId and arguments within a day: the first answer comes back, marked replayed, and there is still one task.
What an assistant can do, room by room
The common verbs for each kind of thing, and the tools that do them over MCP
beside what the app itself offers. A blank is a verb neither has; app only
is a gap an assistant cannot fill yet; app only, on purpose is a decision,
said below — mostly deletions kept for the person. Generated from src/lib/server/mcp/capabilities.json,
which a test holds to the tools the server serves and the actions the app has.
| Room | create | read | change | archive | unarchive | delete | reorder |
|---|---|---|---|---|---|---|---|
| Tasks | add_task, note_to_tasks |
tasks, up_next |
change_task, tag_task, finish_task, reopen_task, schedule_task, unschedule_task |
archive_task |
unarchive_task |
drop_task |
reorder_tasks |
| Blocks | add_block, add_repeating_block |
upcoming, past, repeating_week |
change_block, finish_block, change_repeating_block |
change_repeating_block |
change_repeating_block |
cancel_block, remove_repeating_block |
|
| Notes and diary entries | write_entry |
diary, notebook_notes |
edit_entry, pin_note, unpin_note, move_notes |
archive_note |
unarchive_note |
app only, on purpose | |
| Ideas | add_idea |
ideas |
change_idea, apply_idea, favorite_idea |
remove_idea |
|||
| Goals | add_goal, add_goal_area, add_goal_target |
goals, goal_areas |
change_goal, log_goal_progress, link_to_goal, unlink_from_goal, remove_goal_target, change_goal_area |
close_goal |
reopen_goal |
app only, on purpose | move_goal_area |
| Habits | add_habit |
habits, all_habits |
change_habit, tick_habit, set_habit_count |
archive_habit |
unarchive_habit |
app only, on purpose | |
| Inventory | add_inventory_item, add_inventory_category |
shopping_list, inventory_categories, inventory_attributes |
file_inventory_item, record_price, set_item_attributes, change_inventory_attribute, change_inventory_category, move_inventory_category, change_inventory_item |
archive_item |
unarchive_item |
remove_inventory_item, remove_inventory_category, remove_inventory_attribute |
|
| Places | add_location |
locations, where_is |
change_location, put_item |
remove_location |
|||
| Shopping list | add_inventory_item |
shopping_list |
tick_bought, untick_bought, record_price, change_inventory_item |
archive_item |
unarchive_item |
remove_inventory_item |
|
| Recipes | add_recipe |
recipes |
change_recipe, cooked_recipe |
archive_recipe |
archive_recipe |
app only, on purpose | |
| Workouts | add_workout, add_workout_category, log_workout |
workouts, workout_sessions, workout_history, workout_activities, workout_categories |
change_workout, set_workout_measures, change_workout_session, workout_done, change_workout_category |
archive_workout |
archive_workout |
remove_workout_session, remove_workout_category |
|
| Bills | add_bill |
bills, bill_payments, bill_history, month_bills, bills_due |
change_bill, pay_bill, change_bill_payment, unpay_bill, skip_bill, unskip_bill |
archive_bill |
archive_bill |
app only, on purpose | |
| Accounts and movements | add_ledger, record_movement, record_balance_check |
ledgers, movements, statement_months, spending_by_category, balance_checks, summary |
change_ledger, change_movement, classify_movements, link_movement, link_transfer, unlink_transfer, split_movement, unsplit_movement |
change_ledger |
change_ledger |
remove_movement, delete_balance_check |
change_ledger |
| Commitments | add_commitment, record_commitment_entry |
commitments, commitment_entries |
change_commitment, close_commitment, settle_commitment, consume_reserve |
archive_commitment |
archive_commitment |
delete_commitment_entry |
|
| Budgets | add_budget, copy_budgets |
budgets, personal_spending |
change_budget |
delete_budget |
|||
| Sorting rules | add_sort_rule |
sort_rules |
change_sort_rule |
delete_sort_rule |
change_sort_rule |
||
| People | add_person |
people, upcoming_birthdays |
change_person |
app only, on purpose | |||
| Reminders | set_alarm, remind_before_block, remind_task |
reminders |
change_reminder, dismiss_reminder |
cancel_alarm |
|||
| Activities | add_activity |
activities, categories |
change_activity |
change_activity |
change_activity |
remove_activity |
|
| Notebooks | add_notebook |
notebooks |
change_notebook, rename_notebook_folder, favourite_notebook, share_notebook |
change_notebook |
change_notebook |
remove_notebook |
|
| Labels | app only, on purpose | tags, notebook_tags |
describe_tag, rename_tag, recolor_tag, untag_notebook |
remove_tag |
|||
| Recordings | app only, on purpose | recordings, media |
change_recording |
app only, on purpose |
Not there yet — what the app does and an assistant cannot:
Left out on purpose:
- Notes and diary entries, delete. Writing is precious: an assistant archives, and the person deletes in the app.
- Goals, delete. A goal stands for a commitment: closed or abandoned by a tool, deleted only in the app.
- Habits, delete. A habit carries its kept days: deleted only in the app.
- Recipes, delete. A recipe is archived by a tool; deleting one is done in the app.
- Workouts, delete. An exercise carries its sessions: archived by a tool, deleted in the app. Sessions and categories can be removed.
- Bills, delete. A bill carries its payment history: archived by a tool, deleted in the app where that history is in front of the person.
- Accounts and movements, delete. A ledger takes every line in it when deleted: archived by a tool, deleted in the app. A single line can be removed.
- Commitments, delete. A commitment carries financial history: assistants archive it; permanent deletion is only in the archived app view. Mistaken entries can be reversed and restored through the assistant log.
- People, delete. A person's page stands for somebody: deleted only in the app.
- Labels, create. A label comes into being by being used —
tagson a task, a note or an idea — so there is nothing to make first. - Recordings, create. A recording is made by a microphone in the app; there is nothing for a tool to say into.
- Recordings, delete. A recording is the one copy of something said: deleted only in the app.
Old spellings
The surface is additive within a major version: a tool or a parameter is not
removed, a parameter does not become required, an enum does not lose a value,
a bound does not tighten, a default does not move and a tool does not start
needing another grant — at any depth, fields inside a list included — without
a release in between that marks the old shape deprecated. That is enforced by
src/lib/server/mcp/manifest.json and a test that refuses any change breaking
an existing caller.
A deprecated argument keeps working until the release named below. A call
that uses one is translated, and its answer carries a warning naming the
replacement and the release.
| Old spelling | Use instead | Removed in | Tools that take it |
|---|---|---|---|
energy |
ease |
0.190.0 | add_block, change_task, add_repeating_block |
meta |
attributes |
0.190.0 | add_block, change_block, add_task, change_task, add_repeating_block, change_repeating_block |
tag |
tags |
0.185.0 | tasks, up_next, diary, notebook_notes |
withoutTag |
withoutTags |
0.185.0 | tasks, up_next, diary, notebook_notes |
ingredients |
addIngredients |
0.190.0 | change_recipe |
The tools
Every tool the server offers, with the exact description a model is handed — published from the same array that serves them, so the two cannot drift. A key is only offered the tools its permissions reach. The permissions themselves are on the permissions page.
Under each description: the permissions the key must hold, whether the tool
writes, and what its answer carries. Parameters inside a list of objects are
named with [] — measures[].unit is the unit of each line in measures.
today — Today's plan
What is on today: the blocks planned for it and the tasks pulled onto it. This is the answer to 'what am I meant to be doing', and the first thing to reach for before adding anything. Habits are not here — they are their own permission, and their own tool.
Needs today:read; read-only.
Takes no parameters.
habits — Habits due today
The habits scheduled for today, each with its streak and whether it has been kept yet. Separate from the day's plan on purpose: whether somebody kept their habits is a more personal thing than what is on their calendar, so it is granted separately.
Needs habits:read; read-only.
Takes no parameters.
tick_habit — Tick a habit
Tick a habit for a day: for something being built, the tick means it was done; for something being avoided, it means it happened. Name it or give the id habits gave; a name that matches two habits is refused rather than guessed. Ticking twice is not an error; the second call takes it back, which is how the app’s own tick behaves.
Needs habits:write; writes; answers with before and after.
| Parameter | Type | Required | What it is |
|---|---|---|---|
id |
integer | — | The habit’s id, as habits gave it. |
name |
string | — | The habit by name, when the id is not to hand — "stretching". |
notebookId |
integer | — | Look the name up only among the habits filed in this notebook, as notebooks gives its id. Left out, every habit is searched. |
date |
string | — | The day, as YYYY-MM-DD. Today if left out. |
requestId |
string | — | An id you choose for this call, such as a UUID, so it can be sent again safely: the same requestId with the same arguments within a day answers with the first answer, marked replayed, and nothing is made twice. Reused for a different call, it is refused with the code conflict. |
set_habit_count — Set a habit’s count for a day
Set how many times a habit was logged on a day — the number itself, not a step, so sending it twice changes nothing. 0 clears the day. For a habit kept more than once a day ("three glasses of water"); for once-a-day ones tick_habit is the ordinary call. Name it or give the id habits gave; a name that matches two habits is refused rather than guessed. The answer’s before is the count it replaced, which is how to put it back.
Needs habits:write; writes; answers with before and after.
| Parameter | Type | Required | What it is |
|---|---|---|---|
id |
integer | — | The habit’s id, as habits gave it. |
name |
string | — | The habit by name, when the id is not to hand — "drink water". |
notebookId |
integer | — | Look the name up only among the habits filed in this notebook, as notebooks gives its id. Left out, every habit is searched. |
date |
string | — | The day, as YYYY-MM-DD. Today if left out. |
count |
integer | yes | How many times it happened that day, 0 to …. From 0 to 99. |
requestId |
string | — | An id you choose for this call, such as a UUID, so it can be sent again safely: the same requestId with the same arguments within a day answers with the first answer, marked replayed, and nothing is made twice. Reused for a different call, it is refused with the code conflict. |
finish_block — Mark a block done or skipped
Answer for one block on the day: it happened, or it did not. Takes the id today gives for that block. Skipping is a real answer — say skipped when the person says they did not do it. It is NOT a way to clear something off the day: a skip goes into the week’s record and the review asks about it. To move a block use change_block; to take one off because it was never happening use cancel_block. todo takes an answer back, for one ticked by mistake.
Needs schedule:write; writes; answers with before and after.
| Parameter | Type | Required | What it is |
|---|---|---|---|
id |
string | yes | The block’s id, exactly as today gave it — it looks like slot:42. |
status |
string | yes | What actually happened. One of: done, skipped, todo. |
add_block — Put a task block on a day
Add a one-off block to one day: a title, a start time and how long it runs. This is for "deep work from 9 to 11 today" — a thing with an hour. Use add_task instead when there is no time attached, and change_block to move or rename something already on the day rather than adding a second copy of it. It does not touch the repeating week; this is that day only.
Needs schedule:write; writes; answers with before and after.
| Parameter | Type | Required | What it is |
|---|---|---|---|
date |
string | yes | The day, as YYYY-MM-DD. |
title |
string | yes | What it is — shown on the block. |
start_time |
string | yes | When it starts, as HH:MM on a 24-hour clock. |
minutes |
integer | — | How long it runs, in minutes. Default 60. |
category |
string | — | Which part of life it belongs to, by name — categories lists them. A name that matches nothing is refused, never guessed. The first category is used only when this is left out entirely. |
notebookId |
integer | — | The notebook it belongs to, as notebooks gives its id — the subject it is part of. 0 takes it out of the one it is in. |
urgency |
integer | — | How soon it has to happen, 0–5. On a change, null clears it. |
interest |
integer | — | How much they want to do it, 0–5. On a change, null clears it. |
ease |
integer | — | How easy it is, 0–5, five being easiest. On a change, null clears it. Replaces energy, which asked the opposite question on a scale that began at one. |
energy |
integer | — | Deprecated — use ease, which is this turned round: an energy of 5 is an ease of 1. Still accepted so an assistant written against the old shape keeps working, and removed in 0.190.0. Deprecated — removed in 0.190.0. |
attributes |
object | — | Its attributes: key/value pairs such as { "url": "https://…", "room": "B12" }, read by plugins and shown on the task. Keys are lowercase letters, digits and underscores. This replaces the whole set: send every pair to keep, an empty value removes one, and {} removes them all. Left out, they are untouched. Any key, each holding a string. |
meta |
object | — | Deprecated — use attributes, which is the same thing under the name the app uses. Still accepted so an assistant written against the old shape keeps working, and removed in 0.190.0. Any key, each holding a string. Deprecated — removed in 0.190.0. |
requestId |
string | — | An id you choose for this call, such as a UUID, so it can be sent again safely: the same requestId with the same arguments within a day answers with the first answer, marked replayed, and nothing is made twice. Reused for a different call, it is refused with the code conflict. |
change_block — Move or rename a task block
Change one task block on one day: its time, its day, how long it runs, or what it is called — and, for a one-off, the notebook it is filed under and its attributes. This is "push the study block to four", "make it two hours", "that was actually client work". Takes the id today or upcoming gives. Only the fields you pass change, and nothing is written unless all of them are valid; notebookId of 0 unfiles it and attributes of {} empties them. It affects that day only — moving this Thursday’s gym does not move gym — and it never edits the repeating week. Renaming keeps which part of life it belongs to and stops it being the named activity it was, because that is what saying it was something else means.
Needs schedule:write; writes; answers with before and after.
| Parameter | Type | Required | What it is |
|---|---|---|---|
id |
string | yes | The block’s id, exactly as the day gave it — like slot:42. |
date |
string | — | Move it to this day, as YYYY-MM-DD. Leave out to keep the day it is on. |
start_time |
string | — | The new start, as HH:MM on a 24-hour clock. |
minutes |
integer | — | How long it should run, in minutes. |
title |
string | — | What it should be called instead. |
category |
string | — | Refile it under this part of life, by name — categories lists them. Affects that day only, like everything here. |
notebookId |
integer | — | The notebook it belongs to, as notebooks gives its id — the subject it is part of. 0 takes it out of the one it is in. |
attributes |
object | — | Its attributes: key/value pairs such as { "url": "https://…", "room": "B12" }, read by plugins and shown on the task. Keys are lowercase letters, digits and underscores. This replaces the whole set: send every pair to keep, an empty value removes one, and {} removes them all. Left out, they are untouched. Any key, each holding a string. |
meta |
object | — | Deprecated — use attributes, which is the same thing under the name the app uses. Still accepted so an assistant written against the old shape keeps working, and removed in 0.190.0. Any key, each holding a string. Deprecated — removed in 0.190.0. |
cancel_block — Take a block off the day
Remove a block from a day because it is not happening — the meeting moved, the class was called off, it was put on the wrong day. This is NOT the same as marking it skipped: skipped means it was meant to happen and did not, which is a fact the weekly review asks about, and cancelled means it was never going to. Use finish_block with "skipped" for the first and this for the second. A repeating block is only removed from that one day.
Needs schedule:write and destructive; deletes; answers with before and after.
| Parameter | Type | Required | What it is |
|---|---|---|---|
id |
string | yes | The block’s id, exactly as the day gave it — like slot:42. |
upcoming — The days ahead
Everything planned from today onwards — the blocks of the week, in order. Use it to answer questions about a day that is not today.
Needs schedule:read; read-only.
| Parameter | Type | Required | What it is |
|---|---|---|---|
days |
integer | — | How many days from today, up to 31. Default 7. |
past — The days behind
What was on the days that have already happened, with what each one was answered — done, skipped, or nothing yet. Use it before correcting a week: it gives the ids finish_block needs. Ask for a week back with days: 7, or name the day it starts on.
Needs schedule:read; read-only.
| Parameter | Type | Required | What it is |
|---|---|---|---|
days |
integer | — | How many days to look back over, up to 31. Default 7. |
startingOn |
string | — | The first day to include, as YYYY-MM-DD. Left out, it is that many days before today. |
search — Search everything written
One search over diary entries, notebooks, notes, ideas, goals, people, recipes and todos. Prefer this to guessing which room a thing is in.
Needs search:read; read-only.
| Parameter | Type | Required | What it is |
|---|---|---|---|
query |
string | yes | What to look for. |
media — A picture or a recording
The bytes of a file this key may see, given the link as it appears in the writing — /media/12 for a picture, /media/audio/12 for a recording. A file answers to whatever refers to it, so the grant that lets you read the note lets you see the picture in it; one nothing refers to is reachable by nobody.
Needs any of ideas:read, kitchen:read, notes:read, people:read, tasks:read; read-only.
| Parameter | Type | Required | What it is |
|---|---|---|---|
path |
string | yes | The link, exactly as the text writes it: /media/12, or /media/audio/12 for a recording. The number alone is taken as a picture. |
recordings — Recordings
The audio recordings, newest first: name, notes, length in seconds and when it was made. link is what media takes to fetch the sound itself.
Needs audio:read; read-only; answers a page.
| Parameter | Type | Required | What it is |
|---|---|---|---|
limit |
integer | — | How many. Default 50. |
offset |
integer | — | Skip this many before counting, so the rest of the recordings can be read a page at a time. nextOffset on the answer is what to pass here next. Default 0. |
change_recording — Rename a recording, or write its notes
Change a recording’s name, its notes, or both — a transcript, a summary, what it was about. A field left out is untouched; notes replace what was there, and an empty string clears them.
Needs audio:write; writes; answers with before and after.
| Parameter | Type | Required | What it is |
|---|---|---|---|
id |
integer | yes | The recording’s id, as recordings gives it. |
name |
string | — | The new name. |
notes |
string | — | The new notes, as Markdown. An empty string clears them. |
tasks — The todo list
The to-do list: every task, including the ones already put on a day unless scheduled: "undated" asks for only the dateless ones. Answers with a line per task; verbose or fields for more. Narrow it rather than reading it whole — notebookId for one subject, status: "open", query for words, tags, withoutTags, taggedSince, dates and ratings — and sort to read it in another order. up_next is this list in priority order.
Needs tasks:read; read-only; answers a page.
| Parameter | Type | Required | What it is |
|---|---|---|---|
limit |
integer | — | How many to return. Default 50. |
offset |
integer | — | Skip this many before counting, so the rest of the list can be read a page at a time. nextOffset on the answer is what to pass here next. Default 0. |
ids |
integer[] | — | Only these tasks, by id. |
query |
string | — | Only tasks whose title or notes contain these words, as written, ignoring case. |
notebookId |
integer | — | Only the tasks filed under this notebook, as notebooks gives its id. 0 is the ones filed under nothing. |
scheduled |
string | — | any (the default) is every task; undated only the ones with no day yet, which is the to-do list proper; dated only the ones put on a day. One of: any, undated, dated. |
scheduledFrom |
string | — | Only tasks put on this day or later, as YYYY-MM-DD. |
scheduledTo |
string | — | Only tasks put on this day or earlier, as YYYY-MM-DD. |
createdSince |
string | — | Only tasks written at or after this moment — 2026-09-21 or a full ISO timestamp. |
updatedSince |
string | — | Only tasks changed at or after this moment. |
completedSince |
string | — | Only tasks finished at or after this moment. |
minUrgency |
number | — | Only tasks whose urgency is at least this, 0 to 5. An unrated one counts as 2.5. From 0 to 5. |
maxUrgency |
number | — | Only tasks whose urgency is at most this, 0 to 5. An unrated one counts as 2.5. From 0 to 5. |
minEase |
number | — | Only tasks whose ease is at least this, 0 to 5. An unrated one counts as 2.5. From 0 to 5. |
maxEase |
number | — | Only tasks whose ease is at most this, 0 to 5. An unrated one counts as 2.5. From 0 to 5. |
minInterest |
number | — | Only tasks whose interest is at least this, 0 to 5. An unrated one counts as 2.5. From 0 to 5. |
maxInterest |
number | — | Only tasks whose interest is at most this, 0 to 5. An unrated one counts as 2.5. From 0 to 5. |
tags |
string[] | — | Only the ones carrying at least one of these labels, so naming several reads several queues in one call — ["u5", "e2", "i5"]. Lower case, no #. Several assistants on one list mark their own work this way — a1, done — so this is how to read back only yours. A single string of them, separated by commas or spaces, is understood too. |
tagMode |
string | — | How tags combine. any (the default) keeps what carries at least one of them; all keeps only what carries every one. withoutTags drops the same either way. One of: all, any. |
withoutTags |
string[] | — | Leave out the ones carrying any of these labels. The mirror of tags, written the same way; both may be given. |
tag |
string | — | Deprecated — use tags, which asks the same thing of any number of labels at once. Still accepted so an assistant written against the old shape keeps working, and removed in 0.185.0. Deprecated — removed in 0.185.0. |
withoutTag |
string | — | Deprecated — use withoutTags, which drops anything carrying any of the labels named. Still accepted so an assistant written against the old shape keeps working, and removed in 0.185.0. Deprecated — removed in 0.185.0. |
taggedSince |
string | — | Only the ones labelled at or after this moment — 2026-09-21 or a full ISO timestamp. With tags, it is the date of whichever of those labels the thing carries; without, any label’s. A label put on before dates were kept does not answer this. |
status |
string | — | Only the tasks in this state. open is everything not finished and not skipped, which is what a list is usually read for. One of: todo, doing, done, skipped, open, closed. |
archived |
string | — | The tasks that have been put away: exclude (the default, which is what putting away means), include, or only. One of: exclude, include, only. |
includeArchived |
boolean | — | The same as archived: "include". |
sort |
string | — | The order. manual (the default) is the order the board is dragged into; priority is the order up_next answers in; the rest sort by that one field. Ties always fall to the id, so paging never repeats or skips a task. One of: manual, priority, created, updated, completed, scheduled, title. |
direction |
string | — | Which way sort runs. By default the way it is usually read: priority best first, dates newest first, manual, scheduled and title ascending. Tasks with no date sort last either way. One of: asc, desc. |
verbose |
boolean | — | Send the whole of each row rather than a line. Off by default: a list is usually read to find something, and the thing found is then asked about by id. |
fields |
string | — | Only these parts of each row, comma-separated — title,status,tags. id always comes back. Unknown names are refused rather than ignored. |
up_next — What to do next
The task to do next, by the ratings on it: most urgent first, then the easiest, then the one most wanted. All three run the same way — five is the most of what the word says. An unrated one is not a zero: it counts as the middle of the scale, 2.5, so anything marked 4 or 5 beats it and 1 or 2 falls below it as the postpone tiers. Open, unarchived tasks only; tasks already put on a day are included unless scheduled: "undated". Answers with one line by default; limit for a short list to choose between, offset for the next page, and the same filters tasks takes — tags to ask it of one queue or of several at once.
Needs tasks:read; read-only; answers a page.
| Parameter | Type | Required | What it is |
|---|---|---|---|
limit |
integer | — | How many to return. One is the usual question. Default 1. |
offset |
integer | — | Skip this many before counting, so the rest of the queue can be read a page at a time. nextOffset on the answer is what to pass here next. Default 0. |
ids |
integer[] | — | Only these tasks, by id. |
query |
string | — | Only tasks whose title or notes contain these words, as written, ignoring case. |
notebookId |
integer | — | Only the tasks filed under this notebook, as notebooks gives its id. 0 is the ones filed under nothing. |
scheduled |
string | — | any (the default) is every task; undated only the ones with no day yet, which is the to-do list proper; dated only the ones put on a day. One of: any, undated, dated. |
scheduledFrom |
string | — | Only tasks put on this day or later, as YYYY-MM-DD. |
scheduledTo |
string | — | Only tasks put on this day or earlier, as YYYY-MM-DD. |
createdSince |
string | — | Only tasks written at or after this moment — 2026-09-21 or a full ISO timestamp. |
updatedSince |
string | — | Only tasks changed at or after this moment. |
completedSince |
string | — | Only tasks finished at or after this moment. |
minUrgency |
number | — | Only tasks whose urgency is at least this, 0 to 5. An unrated one counts as 2.5. From 0 to 5. |
maxUrgency |
number | — | Only tasks whose urgency is at most this, 0 to 5. An unrated one counts as 2.5. From 0 to 5. |
minEase |
number | — | Only tasks whose ease is at least this, 0 to 5. An unrated one counts as 2.5. From 0 to 5. |
maxEase |
number | — | Only tasks whose ease is at most this, 0 to 5. An unrated one counts as 2.5. From 0 to 5. |
minInterest |
number | — | Only tasks whose interest is at least this, 0 to 5. An unrated one counts as 2.5. From 0 to 5. |
maxInterest |
number | — | Only tasks whose interest is at most this, 0 to 5. An unrated one counts as 2.5. From 0 to 5. |
tags |
string[] | — | Only the ones carrying at least one of these labels, so naming several reads several queues in one call — ["u5", "e2", "i5"]. Lower case, no #. Several assistants on one list mark their own work this way — a1, done — so this is how to read back only yours. A single string of them, separated by commas or spaces, is understood too. |
tagMode |
string | — | How tags combine. any (the default) keeps what carries at least one of them; all keeps only what carries every one. withoutTags drops the same either way. One of: all, any. |
withoutTags |
string[] | — | Leave out the ones carrying any of these labels. The mirror of tags, written the same way; both may be given. |
tag |
string | — | Deprecated — use tags, which asks the same thing of any number of labels at once. Still accepted so an assistant written against the old shape keeps working, and removed in 0.185.0. Deprecated — removed in 0.185.0. |
withoutTag |
string | — | Deprecated — use withoutTags, which drops anything carrying any of the labels named. Still accepted so an assistant written against the old shape keeps working, and removed in 0.185.0. Deprecated — removed in 0.185.0. |
taggedSince |
string | — | Only the ones labelled at or after this moment — 2026-09-21 or a full ISO timestamp. With tags, it is the date of whichever of those labels the thing carries; without, any label’s. A label put on before dates were kept does not answer this. |
verbose |
boolean | — | Send the whole of each row rather than a line. Off by default: a list is usually read to find something, and the thing found is then asked about by id. |
fields |
string | — | Only these parts of each row, comma-separated — title,status,tags. id always comes back. Unknown names are refused rather than ignored. |
add_task — Add a todo
Put a task on the todo list. Leave the date off unless the person said when — a todo with no date is the normal case here, not an unfinished one.
Needs tasks:write; writes; answers with before and after, after being the new todo.
| Parameter | Type | Required | What it is |
|---|---|---|---|
title |
string | yes | What the task is, in the person’s own words. |
notes |
string | — | Anything else about it. |
scheduledDate |
string | — | The day to put it on, as YYYY-MM-DD. Usually omitted. |
notebookId |
integer | — | The notebook this task belongs to, as notebooks gives its id. A subject somebody is working through — a renovation, a project — keeps its tasks together, and the app shows them on the notebook itself. The task takes the notebook’s category, when it has one. |
goalId |
integer | — | A goal to count this towards, as goals gives its id. Breaking a goal into tasks is the ordinary reason to make several at once, and a task linked here moves that goal’s progress when it is finished. |
tags |
string | — | Labels, comma or space separated — "a1, done". The account’s one vocabulary, the same words a diary entry or an idea is tagged with. Mark your own work with a label of your own where several assistants share a list. |
attributes |
object | — | Its attributes: key/value pairs such as { "url": "https://…", "room": "B12" }, read by plugins and shown on the task. Keys are lowercase letters, digits and underscores. This replaces the whole set: send every pair to keep, an empty value removes one, and {} removes them all. Left out, they are untouched. Any key, each holding a string. |
meta |
object | — | Deprecated — use attributes, which is the same thing under the name the app uses. Still accepted so an assistant written against the old shape keeps working, and removed in 0.190.0. Any key, each holding a string. Deprecated — removed in 0.190.0. |
requestId |
string | — | An id you choose for this call, such as a UUID, so it can be sent again safely: the same requestId with the same arguments within a day answers with the first answer, marked replayed, and nothing is made twice. Reused for a different call, it is refused with the code conflict. |
finish_task — Finish a todo
Mark a todo done, which is what "I did that" means here — it is not deleted, it moves to done and stays in the record. Ask tasks first for the id.
Needs tasks:write; writes; answers with before and after.
| Parameter | Type | Required | What it is |
|---|---|---|---|
id |
integer | yes | The todo’s id. |
drop_task — Delete a todo
Remove a todo entirely, because it is not going to happen and is not worth a record — "bin that one", "forget it". Different from finish_task, which keeps it as something that was done. Gone for good; prefer finishing it when it actually happened.
Needs tasks:write and destructive; deletes; answers with before and after.
| Parameter | Type | Required | What it is |
|---|---|---|---|
id |
integer | yes | The todo’s id. |
reopen_task — Put a todo back on the list
Undo a finish or a drop: the todo goes back to not-done. Use it when something was ticked by mistake, or when a dropped thing turns out to matter after all. It keeps its notes, its day and everything linked to it.
Needs tasks:write; writes; answers with before and after.
| Parameter | Type | Required | What it is |
|---|---|---|---|
id |
integer | yes | The todo’s id. |
archive_task — Put a todo away for now
Put a todo out of the way without finishing it or dropping it — for something that matters but not this month. It keeps its notes, its notebook and its state, and comes back with unarchive_task. Prefer this to dropping when somebody says "not now" rather than "not going to".
Needs tasks:write; writes; answers with before and after.
| Parameter | Type | Required | What it is |
|---|---|---|---|
id |
integer | yes | The todo’s id. |
unarchive_task — Bring a todo back
Bring back a todo that was put away, so it shows on the list again. It returns in whatever state it left in. tasks says which ones are archived.
Needs tasks:write; writes; answers with before and after.
| Parameter | Type | Required | What it is |
|---|---|---|---|
id |
integer | yes | The todo’s id. |
tag_task — Label a todo
Put labels on a todo or take them off, leaving its other labels alone — this is the one to use for marking a task, and change_task is for replacing every label at once. Several assistants sharing a list mark their own work this way; tasks takes a tag to read back only the ones you marked. Answers with the labels it has afterwards.
Needs tasks:write; writes; answers without before and after.
| Parameter | Type | Required | What it is |
|---|---|---|---|
id |
integer | yes | The todo’s id, as tasks gives it. |
add |
string | — | Labels to put on it, comma or space separated — "done-by-ai". Lower case, no #; the account’s one vocabulary, the same words a diary entry or an idea is tagged with. |
remove |
string | — | Labels to take off it, comma or space separated. Ones it does not have are ignored. |
change_task — Change a todo
Rewrite a todo’s title, notes or state. Only id is needed: a field left out is untouched. Everything is checked before anything is written, and the change lands whole or not at all. Moving it on or off a day is schedule_task; finish_task and reopen_task are the shorthands for the two ends of status.
Needs tasks:write; writes; answers with before and after.
| Parameter | Type | Required | What it is |
|---|---|---|---|
id |
integer | yes | The todo’s id, as tasks gives it. |
title |
string | — | The new title, in the person’s own words. It cannot be emptied. |
notes |
string | — | The new notes. An empty string clears them. |
status |
string | — | What state it is in: todo waiting, doing started, done finished, skipped given up on. Left out, it is untouched. One of: todo, doing, done, skipped. |
notebookId |
integer | — | The notebook to file it under, as notebooks gives its id. 0 takes it out of whichever one it is in. add_task can file a task at birth; this is how one already made moves. |
tags |
string | — | The labels it should carry from now on, comma or space separated — this replaces whatever it had, so include the ones to keep. An empty string takes them all off. Left out, the labels are untouched. |
urgency |
integer | — | How soon it has to happen, 0–5. On a change, null clears it. |
interest |
integer | — | How much they want to do it, 0–5. On a change, null clears it. |
ease |
integer | — | How easy it is, 0–5, five being easiest. On a change, null clears it. Replaces energy, which asked the opposite question on a scale that began at one. |
energy |
integer | — | Deprecated — use ease, which is this turned round: an energy of 5 is an ease of 1. Still accepted so an assistant written against the old shape keeps working, and removed in 0.190.0. Deprecated — removed in 0.190.0. |
attributes |
object | — | Its attributes: key/value pairs such as { "url": "https://…", "room": "B12" }, read by plugins and shown on the task. Keys are lowercase letters, digits and underscores. This replaces the whole set: send every pair to keep, an empty value removes one, and {} removes them all. Left out, they are untouched. Any key, each holding a string. |
meta |
object | — | Deprecated — use attributes, which is the same thing under the name the app uses. Still accepted so an assistant written against the old shape keeps working, and removed in 0.190.0. Any key, each holding a string. Deprecated — removed in 0.190.0. |
ifUpdatedAt |
string | — | Only change it if nothing has changed it since: the updatedAt a read or an earlier change answered with. If something has, nothing is written and the call is refused with the code conflict, the current updatedAt in its details. |
reorder_tasks — Put tasks in order on the board
Set the order tasks sit in on the board, the way dragging them does: the ids given, first to last. Tasks not named keep their places. tasks answers in this order unless asked for another. It is not a priority — up_next orders by the ratings.
Needs tasks:write; writes; answers with before and after.
| Parameter | Type | Required | What it is |
|---|---|---|---|
ids |
integer[] | yes | The tasks’ ids, as tasks gives them, in the order they should sit. |
schedule_task — Put a todo on a day
Give a todo a date, which moves it onto that day’s board. This is what "do it on Thursday" means here.
Needs tasks:write; writes; answers with before and after.
| Parameter | Type | Required | What it is |
|---|---|---|---|
id |
integer | yes | The todo’s id. |
date |
string | yes | The day, as YYYY-MM-DD. |
unschedule_task — Take a todo off its day
Take the date off a todo, which moves it back to the list of things with no time yet. This is "not today after all" — the todo is kept, it just stops being on a day.
Needs tasks:write; writes; answers with before and after.
| Parameter | Type | Required | What it is |
|---|---|---|---|
id |
integer | yes | The todo’s id. |
goals — Goals
What the person is working towards, by horizon, with the work counted against each. add_goal transcribes one they just said; close_goal says how one ended.
Needs tasks:read; read-only.
| Parameter | Type | Required | What it is |
|---|---|---|---|
includeClosed |
boolean | — | Default false. |
close_goal — Say how a goal ended
Close a goal: achieved, missed, or abandoned. Missed and abandoned are different — missed is a deadline that passed, abandoned is a decision to stop — and both are worth recording honestly rather than being rounded to one. Takes the id goals gives. There is no tool that opens a goal; that is the person’s to make.
Needs tasks:write; writes; answers with before and after.
| Parameter | Type | Required | What it is |
|---|---|---|---|
id |
integer | yes | The goal’s id. |
status |
string | yes | How it ended. One of: achieved, missed, abandoned. |
note |
string | — | A line about how it went, if they said one. |
link_to_goal — Count work towards a goal
Attach todos or repeating blocks to a goal, so finishing them moves its progress. Adds to what is already linked; nothing is replaced. goals gives the goal id and what it already has on it.
Needs tasks:write; writes; answers with before and after.
| Parameter | Type | Required | What it is |
|---|---|---|---|
goalId |
integer | yes | The goal’s id, as goals gave it. |
todoIds |
integer[] | — | Todo ids, as tasks gives them. |
slotIds |
integer[] | — | Ids of repeating blocks, for a goal met by doing something weekly. |
unlink_from_goal — Take work off a goal
Detach todos or blocks from a goal. Only the ones named; everything else it counts stays.
Needs tasks:write; writes; answers with before and after.
| Parameter | Type | Required | What it is |
|---|---|---|---|
goalId |
integer | yes | The goal’s id. |
todoIds |
integer[] | — | Todo ids. |
slotIds |
integer[] | — | Ids of repeating blocks. |
reopen_goal — Reopen a goal
Put a closed goal back to open. Its outcome note is cleared and the date it was closed on goes with it, so a reopened goal does not read as having been finished at some point in the past.
Needs tasks:write; writes; answers with before and after.
| Parameter | Type | Required | What it is |
|---|---|---|---|
id |
integer | yes | The goal’s id. |
change_goal — Change a goal
Rename a goal, or change its notes, horizon, start date, or what it is measured by. Only id is needed: a field left out is untouched, and nothing is written unless all of it is valid. targets replaces every measure at once, so read goals first. Adding one without disturbing the rest is add_goal_target. Saying how it ended is close_goal, not this.
Needs tasks:write; writes; answers with before and after.
| Parameter | Type | Required | What it is |
|---|---|---|---|
id |
integer | yes | The goal’s id, as goals gives it. |
title |
string | — | The new name, in the person’s own words. It cannot be emptied. |
notes |
string | — | The new notes. An empty string clears them. |
horizon |
string | — | week, month, quarter, semester or year. |
startDate |
string | — | The day its period starts from, as YYYY-MM-DD. |
targets |
object[] | — | Everything the goal is measured by, replacing what it has: [{ "value": 3, "unit": "gigs" }, { "value": 5, "unit": "songs" }]. A goal met by doing one thing can say targetValue and unit instead. |
targets[].value |
number | yes | How much of it. |
targets[].unit |
string | — | What is being counted — gigs, songs, km. |
targets[].measure |
string | — | A workout measure this counts, in the word the sessions use — "ran", "deadlifted". Set it and the number is the sum of what the register holds for that activity inside the goal’s period, read rather than typed; workout_sessions and workouts show what has been measured. Leave it off for a number the person keeps themselves. |
targetValue |
number | — | The number it is aiming at, for a goal that counts one thing. |
unit |
string | — | What that number counts — pages, km, sessions. Sent alone, it renames the measure of a goal that counts one thing. |
ifUpdatedAt |
string | — | Only change it if nothing has changed it since: the updatedAt a read or an earlier change answered with. If something has, nothing is written and the call is refused with the code conflict, the current updatedAt in its details. |
diary — Recent diary entries
What has been written lately, newest first. An entry can belong to a notebook or to no notebook at all. Answers with a line and an opening per entry; verbose for the writing itself.
Needs notes:read; read-only; answers a page.
| Parameter | Type | Required | What it is |
|---|---|---|---|
limit |
integer | — | How many entries. Default 20. |
offset |
integer | — | Skip this many before counting, so the rest of the diary can be read a page at a time. nextOffset on the answer is what to pass here next. Default 0. |
tags |
string[] | — | Only the ones carrying at least one of these labels, so naming several reads several queues in one call — ["u5", "e2", "i5"]. Lower case, no #. Several assistants on one list mark their own work this way — a1, done — so this is how to read back only yours. A single string of them, separated by commas or spaces, is understood too. |
tagMode |
string | — | How tags combine. any (the default) keeps what carries at least one of them; all keeps only what carries every one. withoutTags drops the same either way. One of: all, any. |
withoutTags |
string[] | — | Leave out the ones carrying any of these labels. The mirror of tags, written the same way; both may be given. |
tag |
string | — | Deprecated — use tags, which asks the same thing of any number of labels at once. Still accepted so an assistant written against the old shape keeps working, and removed in 0.185.0. Deprecated — removed in 0.185.0. |
withoutTag |
string | — | Deprecated — use withoutTags, which drops anything carrying any of the labels named. Still accepted so an assistant written against the old shape keeps working, and removed in 0.185.0. Deprecated — removed in 0.185.0. |
taggedSince |
string | — | Only the ones labelled at or after this moment — 2026-09-21 or a full ISO timestamp. With tags, it is the date of whichever of those labels the thing carries; without, any label’s. A label put on before dates were kept does not answer this. |
verbose |
boolean | — | Send the whole of each row rather than a line. Off by default: a list is usually read to find something, and the thing found is then asked about by id. |
fields |
string | — | Only these parts of each row, comma-separated — title,status,tags. id always comes back. Unknown names are refused rather than ignored. |
write_entry — Write a diary entry
Add an entry. Markdown. Writing one when asked is the point of this tool — keep their words and their voice where you have them, and do not invent an entry nobody asked for. Put it in a notebook when it is about one subject; leave the notebook off for an ordinary day.
Needs notes:write; writes; answers with before and after, after being the new note.
| Parameter | Type | Required | What it is |
|---|---|---|---|
content |
string | yes | The entry, as Markdown. |
title |
string | — | What to call it. Optional: a note without one is listed by its first line, which is right for an ordinary day and wrong for anything somebody will come back looking for. |
tags |
string | — | Comma-separated tags. |
notebookId |
integer | — | The notebook it belongs to, if any. |
color |
string | — | The colour the note is drawn in, as #rrggbb; the text on it is worked out to stay readable. Left out, it is the plain note. |
requestId |
string | — | An id you choose for this call, such as a UUID, so it can be sent again safely: the same requestId with the same arguments within a day answers with the first answer, marked replayed, and nothing is made twice. Reused for a different call, it is refused with the code conflict. |
notebook_notes — The notes in a notebook
What has been written against one subject, newest first, with the id of each note. diary deliberately shows only entries outside a notebook, so this is the way to read one — and the way to find the id archive_note wants. Answers with a line and an opening per note; verbose for the writing itself, tags and taggedSince to narrow.
Needs notes:read; read-only; answers a page.
| Parameter | Type | Required | What it is |
|---|---|---|---|
id |
integer | yes | The notebook’s id, as notebooks gives it. |
includeArchived |
boolean | — | Include the notes that have been put away. Off by default, as on the page. |
limit |
integer | — | How many to return. Default 50. |
offset |
integer | — | Skip this many before counting, so the rest of the notebook can be read a page at a time. nextOffset on the answer is what to pass here next. Default 0. |
tags |
string[] | — | Only the ones carrying at least one of these labels, so naming several reads several queues in one call — ["u5", "e2", "i5"]. Lower case, no #. Several assistants on one list mark their own work this way — a1, done — so this is how to read back only yours. A single string of them, separated by commas or spaces, is understood too. |
tagMode |
string | — | How tags combine. any (the default) keeps what carries at least one of them; all keeps only what carries every one. withoutTags drops the same either way. One of: all, any. |
withoutTags |
string[] | — | Leave out the ones carrying any of these labels. The mirror of tags, written the same way; both may be given. |
tag |
string | — | Deprecated — use tags, which asks the same thing of any number of labels at once. Still accepted so an assistant written against the old shape keeps working, and removed in 0.185.0. Deprecated — removed in 0.185.0. |
withoutTag |
string | — | Deprecated — use withoutTags, which drops anything carrying any of the labels named. Still accepted so an assistant written against the old shape keeps working, and removed in 0.185.0. Deprecated — removed in 0.185.0. |
taggedSince |
string | — | Only the ones labelled at or after this moment — 2026-09-21 or a full ISO timestamp. With tags, it is the date of whichever of those labels the thing carries; without, any label’s. A label put on before dates were kept does not answer this. |
verbose |
boolean | — | Send the whole of each row rather than a line. Off by default: a list is usually read to find something, and the thing found is then asked about by id. |
fields |
string | — | Only these parts of each row, comma-separated — title,status,tags. id always comes back. Unknown names are refused rather than ignored. |
pin_note — Keep a note at the top
Hold a note at the top of its notebook — the measurements, the account number, the thing the notebook is actually for. As many as the person likes; the most recently pinned leads. unpin_note lets one go.
Needs notes:write; writes; answers with before and after.
| Parameter | Type | Required | What it is |
|---|---|---|---|
id |
integer | yes | The note’s id, as notebook_notes gives it. |
unpin_note — Stop keeping a note at the top
Let a pinned note fall back into its notebook’s own order, where it is read with the rest.
Needs notes:write; writes; answers with before and after.
| Parameter | Type | Required | What it is |
|---|---|---|---|
id |
integer | yes | The note’s id, as notebook_notes gives it. |
edit_entry — Change what a note says
Rewrite a note or a diary entry — its words, its title, its tags, its colour. Only the fields given change; the rest of it, and the notebook it lives in, are left alone. notebook_notes gives the id. To put one out of the way instead, archive_note.
Needs notes:write; writes; answers with before and after.
| Parameter | Type | Required | What it is |
|---|---|---|---|
id |
integer | yes | The note’s id, as notebook_notes gives it. |
content |
string | — | The new words, as Markdown. Left out, the writing is untouched. |
title |
string | — | What to call it. Left out, the name is untouched; an empty string takes the name off, which is what an ordinary day’s diary entry has. |
tags |
string | — | The tags it should carry from now on, comma or space separated — this replaces the ones it has. Left out, they are untouched. |
color |
string | — | The colour the note is drawn in, as #rrggbb; the text on it is worked out to stay readable. Left out, the colour is untouched; an empty string takes it off. |
ifUpdatedAt |
string | — | Only change it if nothing has changed it since: the updatedAt a read or an earlier change answered with. If something has, nothing is written and the call is refused with the code conflict, the current updatedAt in its details. |
note_to_tasks — Make todos out of a checklist note
Turn a note that is really a checklist into the tasks it describes. Every - [ ] line becomes a task, with whatever is written under it as that task’s notes; a - [x] line comes across already done. Each is filed under the note’s own notebook, and each box is replaced by a reference to the task it became — TASK:#4 — so the note keeps its words and stops being a second copy of the list.
Needs tasks:write and notes:read; writes; answers with before and after.
| Parameter | Type | Required | What it is |
|---|---|---|---|
id |
integer | yes | The note’s id, as notebook_notes gives it. |
only |
integer[] | — | Which checkboxes to take, counting from 0 down the note. Left out, all of them. |
requestId |
string | — | An id you choose for this call, such as a UUID, so it can be sent again safely: the same requestId with the same arguments within a day answers with the first answer, marked replayed, and nothing is made twice. Reused for a different call, it is refused with the code conflict. |
archive_note — Put a note away
Hide a note without deleting it — for one that has stopped being current and is not something to throw out: the trip is over, the flat is rented. It stays in its notebook and comes back with unarchive_note. Notes are never deleted through a tool.
Needs notes:write; writes; answers with before and after.
| Parameter | Type | Required | What it is |
|---|---|---|---|
id |
integer | yes | The note’s id, as notebook_notes gives it. |
unarchive_note — Bring a note back
Bring back a note that was put away, so it shows in its notebook again. notebook_notes with includeArchived says which ones are away.
Needs notes:write; writes; answers with before and after.
| Parameter | Type | Required | What it is |
|---|---|---|---|
id |
integer | yes | The note’s id. |
move_notes — Move notes to another notebook
File one or more notes or diary entries under a notebook, or with notebookId 0 into the diary. All of them move or none do, and each takes the next number free where it lands. notebook_notes and diary give the ids.
Needs notes:write; writes; answers with before and after.
| Parameter | Type | Required | What it is |
|---|---|---|---|
ids |
integer[] | yes | The notes’ ids. |
notebookId |
integer | yes | Where they go: a notebook’s id, or 0 for the diary. |
notebooks — Notebooks
The subjects being written against — a trip, a renovation, a book — with the id every other tool means by notebookId. Ask for these before writing an entry into one. A key tied to one notebook is answered with that one. modules is what each one holds: the tabs it shows, which is also what it will accept being filed under it. favourite is whether the person has starred it; favourites come first.
Needs notes:read; read-only.
| Parameter | Type | Required | What it is |
|---|---|---|---|
id |
integer | — | Only this one, by its id. Usually left off; a confined key is pinned to its own. |
add_notebook — Make a notebook
Make a notebook — a subject written against with no deadline: a book, a trip, a renovation. write_entry files notes into it by name.
Needs notes:write; writes; answers with before and after, after being the new notebook.
| Parameter | Type | Required | What it is |
|---|---|---|---|
title |
string | yes | What it is about. |
folder |
string | — | Where it sits on the shelf, a slash-separated path such as Home/Kitchen. A folder only groups notebooks; it holds nothing itself. Left out, it goes at the top. |
description |
string | — | A line under the title, shown on its page. |
defaultTags |
string | — | Labels a new note in it starts with, comma or space separated — the ones writing about this subject always carries, so nobody types them on every note. The person can still take them off a note as they write it. |
category |
string | — | The category a new task in it starts with, by name as categories gives them. Left out, none. |
modules |
string | — | What it holds, comma separated — notes, tasks, goals, ideas, inventory, ledgers, bills, habits, workouts, recipes. Notes and tasks unless this says otherwise, and notes are always in it. Only name what the subject actually accumulates: nine tabs on a reading list is the app deciding what somebody’s subject is about. |
requestId |
string | — | An id you choose for this call, such as a UUID, so it can be sent again safely: the same requestId with the same arguments within a day answers with the first answer, marked replayed, and nothing is made twice. Reused for a different call, it is refused with the code conflict. |
change_notebook — Change a notebook
Rename a notebook, move it to another folder, rewrite the line under its title, set the labels a new note in it starts with or the category a new task in it starts with, change what it holds, or close and reopen it. Only id is needed: a field left out is untouched, and nothing is written unless all of it is valid.
Needs notes:write; writes; answers with before and after.
| Parameter | Type | Required | What it is |
|---|---|---|---|
id |
integer | yes | The notebook’s id, as notebooks gives it. |
title |
string | — | What it is about. It cannot be emptied; left out, the name is untouched. |
folder |
string | — | The folder it sits in, a slash-separated path such as Home/Kitchen; an empty string puts it at the top. Left out, it stays where it is. |
description |
string | — | A line under the title, shown on its page. An empty string clears it; left out, it is untouched. |
defaultTags |
string | — | Labels a new note in it starts with, comma or space separated. An empty string clears them; left out, they are untouched. |
category |
string | — | The category a new task in it starts with, by name as categories gives them. An empty string clears it; left out, it is untouched. |
modules |
string | — | What it holds, comma separated — notes, tasks, goals, ideas, inventory, ledgers, bills, habits, workouts, recipes. The whole list, not an addition. Notes are always in it. Switching one off keeps whatever is already filed under it; it stops being a tab, and stays in its own room. Left out, it is untouched. |
closed |
boolean | — | true closes it — a finished subject, off the shelf and out of the pickers, with everything in it kept. false reopens it. |
ifUpdatedAt |
string | — | Only change it if nothing has changed it since: the updatedAt a read or an earlier change answered with. If something has, nothing is written and the call is refused with the code conflict, the current updatedAt in its details. |
rename_notebook_folder — Rename a notebook folder
Rename or move a folder of notebooks: every notebook in it, and in the folders inside it, has that part of its path rewritten. notebooks gives each notebook its folder. Moving a folder into its own parent removes it; nothing is deleted.
Needs notes:write; writes; answers with before and after.
| Parameter | Type | Required | What it is |
|---|---|---|---|
from |
string | yes | The folder as it is now, e.g. Home/Kitchen. |
to |
string | yes | What it becomes, e.g. Home/Cooking or Flat/Kitchen. An empty string moves what was in it to the top of the shelf. |
remove_notebook — Remove an empty notebook
Delete a notebook that holds nothing — no notes, no tasks, nothing filed under it at all. One with anything in it is refused with what it holds: somebody’s writing is deleted by them in the app, never through a tool. For a notebook made by mistake.
Needs notes:write and destructive; deletes; answers with before and after.
| Parameter | Type | Required | What it is |
|---|---|---|---|
id |
integer | yes | The notebook’s id, as notebooks gives it. |
favourite_notebook — Star a notebook
Keep a notebook at the front of the shelf and at the top of every notebook picker, or take the star off with favourite: false. The star is the person’s own, so a notebook shared with them can carry one too. notebooks says which have one.
Needs notes:write; writes; answers with before and after.
| Parameter | Type | Required | What it is |
|---|---|---|---|
id |
integer | yes | The notebook’s id, as notebooks gives it. |
favourite |
boolean | — | False takes the star off. True if left out. |
share_notebook — Share a notebook with the family
Share one of the person’s notebooks with everybody on their family plan — they read it and write their own entries into it — or stop sharing with shared: false. Only its owner’s to flip, and only when they asked.
Needs notes:write; writes; answers with before and after.
| Parameter | Type | Required | What it is |
|---|---|---|---|
id |
integer | yes | The notebook’s id, as notebooks gives it. |
shared |
boolean | — | False stops the sharing. True if left out. |
ideas — Ideas
Things caught before they evaporated, newest first. An idea is not a task: nobody has committed to doing it, which is what makes it cheap to write down.
Needs ideas:read; read-only; answers a page.
| Parameter | Type | Required | What it is |
|---|---|---|---|
limit |
integer | — | How many. Default 50. |
offset |
integer | — | Skip this many before counting, so the rest of the ideas can be read a page at a time. nextOffset on the answer is what to pass here next. Default 0. |
notebookId |
integer | — | Only what is filed in this notebook, as notebooks gives its id. Left out, all of it. |
add_idea — Catch an idea
Write an idea down without deciding where it belongs. The lowest-friction thing here; prefer it to a todo when the person has not said they will do it.
Needs ideas:write; writes; answers with before and after, after being the new idea.
| Parameter | Type | Required | What it is |
|---|---|---|---|
content |
string | yes | The idea. |
tags |
string | — | Comma-separated tags. |
notebookId |
integer | — | The notebook this belongs to, as notebooks gives its id — a subject somebody is working through, like a renovation. Only when they said so. A notebook whose modules list does not hold this refuses it. |
requestId |
string | — | An id you choose for this call, such as a UUID, so it can be sent again safely: the same requestId with the same arguments within a day answers with the first answer, marked replayed, and nothing is made twice. Reused for a different call, it is refused with the code conflict. |
remove_idea — Delete an idea
Delete an idea — for one added by mistake, or one that has been dealt with. It is gone, not archived, so prefer leaving it alone unless the person asked.
Needs ideas:write and destructive; deletes; answers with before and after.
| Parameter | Type | Required | What it is |
|---|---|---|---|
id |
integer | yes | The idea’s id. |
change_idea — Change an idea
Rewrite an idea, or retag it — for a misheard word or a better tag, not for turning it into something else. Only id is needed: a field left out is untouched.
Needs ideas:write; writes; answers with before and after.
| Parameter | Type | Required | What it is |
|---|---|---|---|
id |
integer | yes | The idea’s id, as ideas gives it. |
content |
string | — | The idea, rewritten. It cannot be emptied. |
tags |
string | — | Comma-separated tags, replacing the old ones. An empty string takes them all off; left out, they are untouched. |
ifUpdatedAt |
string | — | Only change it if nothing has changed it since: the updatedAt a read or an earlier change answered with. If something has, nothing is written and the call is refused with the code conflict, the current updatedAt in its details. |
tags — The labels
Every label the account uses, alphabetically, with the colour it wears and how many things carry it. One vocabulary for the whole app — the same word on a task, a note, an idea, a block and a picture.
Needs tags:read; read-only.
Takes no parameters.
notebook_tags — The labels in one notebook
The labels on what is filed under one subject, with how much of it carries each — and what kind: notes, tasks, ideas. Narrower than tags, which counts a word across the whole account, and the one to ask before labelling something the way this notebook labels things. A label the notebook suggests by default is listed at nought.
Needs tags:read and notes:read; read-only.
| Parameter | Type | Required | What it is |
|---|---|---|---|
notebookId |
integer | yes | The notebook, as notebooks gives its id. |
describe_tag — Say what a label means
Write down what a word means in this account — #short on the shopping is low on something, #short on a book is the book. One line; an empty one takes the meaning off again. The label itself is not changed: rename_tag is for that.
Needs tags:write; writes; answers with before and after.
| Parameter | Type | Required | What it is |
|---|---|---|---|
id |
integer | yes | The label’s id, as tags gives it. |
description |
string | — | What the word means here. Empty takes it off again. |
rename_tag — Rename a label
Rename a label everywhere at once — for a typo, or for two words that turned out to mean one thing. Renaming onto a name the account already uses merges the two: everything that carried the old label carries the surviving one, and the old label stops existing. Answers with the label that survived.
Needs tags:write; writes; answers with before and after.
| Parameter | Type | Required | What it is |
|---|---|---|---|
id |
integer | yes | The label’s id, as tags gives it. |
name |
string | yes | The new name — one word, lower case, no #. A name the account already uses merges the two labels. |
recolor_tag — Colour a label
Give a label a colour, so it is drawn in it wherever a chip for it appears. An empty string takes the colour off again, which is the plain chip every label starts as.
Needs tags:write; writes; answers with before and after.
| Parameter | Type | Required | What it is |
|---|---|---|---|
id |
integer | yes | The label’s id, as tags gives it. |
color |
string | yes | The colour as #rrggbb — #0f766e. An empty string takes it off. |
remove_tag — Delete a label
Take a label out of the vocabulary and off everything that carried it — the tasks, notes, ideas, blocks and pictures keep everything else about them. Nothing is archived; the label is gone. To fold it into another label instead, rename_tag onto that one.
Needs tags:write and destructive; deletes; answers with before and after.
| Parameter | Type | Required | What it is |
|---|---|---|---|
id |
integer | yes | The label’s id, as tags gives it. |
untag_notebook — Take a label off one notebook
Take a label off everything filed in one notebook — its notes, tasks and ideas — and off nothing outside it. The label stays in the vocabulary while anything else carries it. Answers with how many things lost it. To remove a label everywhere, remove_tag.
Needs tags:write; writes; answers with before and after.
| Parameter | Type | Required | What it is |
|---|---|---|---|
notebookId |
integer | yes | The notebook, as notebooks gives its id. |
id |
integer | yes | The label’s id, as tags gives it. |
shopping_list — The shopping list
What is to buy and what is already in the cupboard. An item is a thing, not a line: ticking it bought puts it back in the cupboard rather than deleting it. Each carries how many there are and how many are kept, so "what am I short of" is qty below idealQty — short: true asks for exactly those.
Needs inventory:read; read-only.
| Parameter | Type | Required | What it is |
|---|---|---|---|
short |
boolean | — | Only the things there are fewer of than are kept — what an actual shopping trip is for. |
notebookId |
integer | — | Only what is filed in this notebook, as notebooks gives its id. Left out, all of it. |
add_inventory_item — Add to the shopping list
Put something on the list. If the cupboard already has it, this says so rather than adding a second one.
Needs inventory:write; writes; answers with before and after, after being the new item.
| Parameter | Type | Required | What it is |
|---|---|---|---|
name |
string | yes | What to buy. |
type |
string | — | replenish is something the cupboard runs out of and wants again; someday is a wishlist item. Default replenish. One of: replenish, someday. Default replenish. |
notes |
string | — | Anything else about it. |
section |
string | — | The section to file it under, by name — inventory_categories lists them. |
notebookId |
integer | — | The notebook this belongs to, as notebooks gives its id — a subject somebody is working through, like a renovation. Only when they said so. A notebook whose modules list does not hold this refuses it. |
requestId |
string | — | An id you choose for this call, such as a UUID, so it can be sent again safely: the same requestId with the same arguments within a day answers with the first answer, marked replayed, and nothing is made twice. Reused for a different call, it is refused with the code conflict. |
tick_bought — Tick something bought
Mark an item bought, which moves it out of "to buy" and into the cupboard. The row stays: the same thing is bought again the next time it runs out.
Needs inventory:write; writes; answers with before and after.
| Parameter | Type | Required | What it is |
|---|---|---|---|
id |
integer | yes | The item’s id. |
untick_bought — Put something back on the list
Undo a tick: the item comes out of the cupboard and back onto "to buy". Use it when something was marked bought by mistake, or when it has run out again. Nothing is lost either way — the row, its category and its price history are the same row.
Needs inventory:write; writes; answers with before and after.
| Parameter | Type | Required | What it is |
|---|---|---|---|
id |
integer | yes | The item’s id. |
archive_item — Put something aside for now
Put an item away without deleting it — for something not wanted this week. It keeps everything about itself and comes back with unarchive_item. Prefer this to removing when somebody says "not now" rather than "never".
Needs inventory:write; writes; answers with before and after.
| Parameter | Type | Required | What it is |
|---|---|---|---|
id |
integer | yes | The item’s id. |
unarchive_item — Bring something back to the list
Bring back an item that was put away, so it shows on the list again. shopping_list says which items are archived.
Needs inventory:write; writes; answers with before and after.
| Parameter | Type | Required | What it is |
|---|---|---|---|
id |
integer | yes | The item’s id. |
remove_inventory_item — Take something off the shopping list
Remove an item because it is not wanted — "take milk off", "we already have that". Not the same as tick_bought, which records that it was bought and keeps it in the history and the price record. Takes the id shopping_list gives.
Needs inventory:write and destructive; deletes; answers with before and after.
| Parameter | Type | Required | What it is |
|---|---|---|---|
id |
integer | yes | The item’s id. |
recipes — Recipes
Every recipe, with its ingredients. An ingredient here is a shopping item with an amount, which is what lets a meal on a day fill the shopping list.
Needs kitchen:read; read-only.
| Parameter | Type | Required | What it is |
|---|---|---|---|
id |
integer | — | One recipe, in full. |
notebookId |
integer | — | Only the recipes filed in this notebook, as notebooks gives its id. Left out, every recipe. |
add_recipe — Add a recipe
Write a recipe down. Ingredients are one per line — "200 g flour", "2 eggs" — and each becomes a shopping item, so the list knows about them the day the meal is planned.
Needs kitchen:write; writes; answers with before and after, after being the new recipe.
| Parameter | Type | Required | What it is |
|---|---|---|---|
title |
string | yes | What it is called. |
ingredients |
string | — | One per line, quantity first. |
method |
string | — | How to make it, as Markdown. |
servings |
integer | — | How many it feeds. |
minutes |
integer | — | How long it takes. |
source |
string | — | Where it came from. |
notebookId |
integer | — | The notebook this belongs to, as notebooks gives its id — a subject somebody is working through, like a renovation. Only when they said so. A notebook whose modules list does not hold this refuses it. |
requestId |
string | — | An id you choose for this call, such as a UUID, so it can be sent again safely: the same requestId with the same arguments within a day answers with the first answer, marked replayed, and nothing is made twice. Reused for a different call, it is refused with the code conflict. |
change_recipe — Change a recipe
Change a recipe’s title, method, servings, time, source or notebook, and its ingredients: addIngredients adds lines (one per line, quantity first), removeIngredients takes lines out by the ingredient ids recipes gives. Only id is needed: a field left out is untouched, and ingredients not named stay. An empty string clears a text field, 0 or null clears servings or time. The recipe and its ingredients land together or not at all.
Needs kitchen:write; writes; answers with before and after.
| Parameter | Type | Required | What it is |
|---|---|---|---|
id |
integer | yes | The recipe’s id, as recipes gives it. |
title |
string | — | The new name. |
method |
string | — | How to make it, as Markdown. |
addIngredients |
string | — | Ingredients to add, one per line, quantity first. |
removeIngredients |
integer[] | — | Ingredient ids to take out of this recipe, as its ingredient list in recipes gives them (itemId). The shopping item itself stays. Only this recipe’s own ingredients; any other id refuses the whole call. |
ingredients |
string | — | Deprecated — use addIngredients, which does the same: it adds these lines and keeps the ones already there. Removed in 0.190.0. Deprecated — removed in 0.190.0. |
servings |
integer | — | How many it feeds. |
minutes |
integer | — | How long it takes. |
source |
string | — | Where it came from. |
notebookId |
integer | — | The notebook it belongs to, as notebooks gives its id; 0 takes it out of its notebook. |
ifUpdatedAt |
string | — | Only change it if nothing has changed it since: the updatedAt a read or an earlier change answered with. If something has, nothing is written and the call is refused with the code conflict, the current updatedAt in its details. |
cooked_recipe — Say a recipe was cooked
Record that a meal was made — recipes shows when each was last cooked, and this is what sets it. Name the ingredient ids that ran out and they land back on the shopping list, which is the loop the kitchen exists to close.
Needs kitchen:write; writes; answers with before and after.
| Parameter | Type | Required | What it is |
|---|---|---|---|
id |
integer | yes | The recipe’s id, as recipes gives it. |
ranOutOf |
integer[] | — | Ingredient item ids that were used up, as the recipe’s ingredient list gives them. Only this recipe’s own ingredients; any other id refuses the whole call. |
archive_recipe — Put a recipe away
Archive a recipe — out of the everyday list, not deleted — or bring one back with archived: false. For the dish nobody makes any more that somebody may yet ask for.
Needs kitchen:write; writes; answers with before and after.
| Parameter | Type | Required | What it is |
|---|---|---|---|
id |
integer | yes | The recipe’s id. |
archived |
boolean | — | False brings it back. True if left out. Default true. |
file_inventory_item — File an item into a section
Move a shopping item into a section — "put the milk under Dairy". Takes the item’s id from shopping_list and the section by name from inventory_categories; an empty section name unfiles it. A name matching no section is refused with the ones that exist.
Needs inventory:write; writes; answers with before and after.
| Parameter | Type | Required | What it is |
|---|---|---|---|
id |
integer | yes | The item’s id, as shopping_list gives it. |
section |
string | — | The section, by name. Empty unfiles the item. |
change_inventory_item — Rename a shopping item, or change its notes
Rename an item, change whether it is something to replenish or a someday wish, or rewrite its notes. Takes the id shopping_list gives. Only id is needed: a field left out is untouched. Its section is file_inventory_item, its place put_item, its price record_price.
Needs inventory:write; writes; answers with before and after.
| Parameter | Type | Required | What it is |
|---|---|---|---|
id |
integer | yes | The item’s id, as shopping_list gives it. |
name |
string | — | A new name. |
type |
string | — | replenish is something the cupboard runs out of and wants again; someday is a wishlist item. One of: replenish, someday. |
notes |
string | — | Anything else about it. An empty string clears them. |
ifUpdatedAt |
string | — | Only change it if nothing has changed it since: the updatedAt a read or an earlier change answered with. If something has, nothing is written and the call is refused with the code conflict, the current updatedAt in its details. |
inventory_categories — The shopping list’s sections
How the shopping list is sectioned — produce, cleaning, whatever the person keeps. Read it before filing an item somewhere.
Needs inventory:read; read-only.
Takes no parameters.
add_inventory_category — Add a shopping section
Make a new section for the shopping list — and say whether it holds food, because only food sections can feed recipes as ingredients.
Needs inventory:write; writes; answers with before and after, after being the new inventoryCategory.
| Parameter | Type | Required | What it is |
|---|---|---|---|
name |
string | yes | The section’s name — "Frozen", "Cleaning". |
holdsFood |
boolean | — | Whether what is in it is food. Off if left out. |
requestId |
string | — | An id you choose for this call, such as a UUID, so it can be sent again safely: the same requestId with the same arguments within a day answers with the first answer, marked replayed, and nothing is made twice. Reused for a different call, it is refused with the code conflict. |
change_inventory_category — Rename a shopping section
Rename a section, recolour it, or change whether it holds food. Only id is needed: a field left out is untouched, and the change lands whole or not at all — a refused share leaves the name as it was. The items filed under it stay exactly where they are.
Needs inventory:write; writes; answers with before and after.
| Parameter | Type | Required | What it is |
|---|---|---|---|
id |
integer | yes | The section’s id, as inventory_categories gives it. |
name |
string | — | The new name. |
holdsFood |
boolean | — | Whether what is in it is food. |
shareWithFamily |
boolean | — | Share the section with everybody on the family plan, or stop. Only its owner’s to flip. |
color |
string | — | The colour its cards wear, as #rrggbb. An empty string takes it off, back to the neutral one. |
move_inventory_category — Move a shopping section up or down
Move one of the person’s own sections one place earlier (-1) or later (1) in the order the inventory draws them. Its way back is the opposite move.
Needs inventory:write; writes; answers with before and after.
| Parameter | Type | Required | What it is |
|---|---|---|---|
id |
integer | yes | The section’s id. |
delta |
integer | yes | -1 for earlier, 1 for later. One of: -1, 1. |
remove_inventory_category — Delete a shopping section
Delete a section. Its items are not touched — they stay on the list, just unfiled. A section is a shelf label, and removing the label must not empty the shelf.
Needs inventory:write and destructive; deletes; answers with before and after.
| Parameter | Type | Required | What it is |
|---|---|---|---|
id |
integer | yes | The section’s id. |
record_price — Record what an item cost
Write down what was paid for a shopping item — "milk was 6,50 today". The list keeps a small price history per item, which is how it can notice drift. Takes the id shopping_list gives, and the price as the person said it.
Needs inventory:write; writes; answers with before and after.
| Parameter | Type | Required | What it is |
|---|---|---|---|
id |
integer | yes | The item’s id. |
price |
string | yes | The price, in the account’s own currency — "6,50" or "6.50" both work. |
requestId |
string | — | An id you choose for this call, such as a UUID, so it can be sent again safely: the same requestId with the same arguments within a day answers with the first answer, marked replayed, and nothing is made twice. Reused for a different call, it is refused with the code conflict. |
add_goal — Write down a goal they made
Transcribe a goal the person just committed to, in their own words — "apply to twenty companies this quarter". Never invent one, and never add a goal they did not say: a goal is a commitment, and the commitment is theirs. goal_areas lists the areas one can be filed under.
Needs tasks:write; writes; answers with before and after, after being the new goal.
| Parameter | Type | Required | What it is |
|---|---|---|---|
title |
string | yes | The goal, in the person’s own words. |
horizon |
string | yes | week, month, quarter, semester or year. |
notes |
string | — | Anything else they said about it. |
startDate |
string | — | The day its period starts from, as YYYY-MM-DD. Today if left out. |
area |
string | — | The area to file it under, by name — goal_areas lists them. |
targets |
object[] | — | Everything the goal is measured by, replacing what it has: [{ "value": 3, "unit": "gigs" }, { "value": 5, "unit": "songs" }]. A goal met by doing one thing can say targetValue and unit instead. |
targets[].value |
number | yes | How much of it. |
targets[].unit |
string | — | What is being counted — gigs, songs, km. |
targets[].measure |
string | — | A workout measure this counts, in the word the sessions use — "ran", "deadlifted". Set it and the number is the sum of what the register holds for that activity inside the goal’s period, read rather than typed; workout_sessions and workouts show what has been measured. Leave it off for a number the person keeps themselves. |
targetValue |
number | — | The number it aims at, when it counts one thing. |
unit |
string | — | What that number counts — applications, km, pages. |
notebookId |
integer | — | The notebook it belongs to, as notebooks gives it — a goal that is part of one subject rather than the year in general. |
requestId |
string | — | An id you choose for this call, such as a UUID, so it can be sent again safely: the same requestId with the same arguments within a day answers with the first answer, marked replayed, and nothing is made twice. Reused for a different call, it is refused with the code conflict. |
log_goal_progress — Move a goal’s number
Record progress on a goal that counts something: pass value to set where it stands, or delta to add what just happened — "I sent three more CVs" is delta: 3. Exactly one of the two. A goal measured by several things also needs unit, to say which of them moved; goals shows them and where each stands.
Needs tasks:write; writes; answers with before and after.
| Parameter | Type | Required | What it is |
|---|---|---|---|
id |
integer | yes | The goal’s id. |
value |
number | — | Where it stands now, absolute. |
delta |
number | — | How much just happened, added to where it stands. |
unit |
string | — | Which measure moved, by its unit — only needed when the goal has several. |
requestId |
string | — | An id you choose for this call, such as a UUID, so it can be sent again safely: the same requestId with the same arguments within a day answers with the first answer, marked replayed, and nothing is made twice. Reused for a different call, it is refused with the code conflict. |
add_goal_target — Add something a goal is measured by
Give a goal another measure — "and fifty kilometres run". Leaves the measures already on it alone, and starts at zero. goals shows what it is measured by.
Needs tasks:write; writes; answers with before and after.
| Parameter | Type | Required | What it is |
|---|---|---|---|
goalId |
integer | yes | The goal’s id, as goals gives it. |
value |
number | yes | How much of it. |
unit |
string | — | What is being counted — gigs, songs, km. |
measure |
string | — | A workout measure this counts, in the word the sessions use — "ran", "deadlifted". Set it and the number is the sum of what the register holds for that activity inside the goal’s period, read rather than typed; workout_sessions and workouts show what has been measured. Leave it off for a number the person keeps themselves. |
requestId |
string | — | An id you choose for this call, such as a UUID, so it can be sent again safely: the same requestId with the same arguments within a day answers with the first answer, marked replayed, and nothing is made twice. Reused for a different call, it is refused with the code conflict. |
remove_goal_target — Take a measure off a goal
Drop one of the things a goal is measured by, by its unit. The goal and its other measures stay. For a measure that was a mistake — one that simply did not happen is what close_goal is for.
Needs tasks:write and destructive; deletes; answers with before and after.
| Parameter | Type | Required | What it is |
|---|---|---|---|
goalId |
integer | yes | The goal’s id. |
unit |
string | — | The measure’s unit, as goals gives it. Only needed when there are several. |
goal_areas — The areas goals are filed under
The areas of life a goal can belong to — career, health, whatever the person keeps. Read it before filing a goal; add_goal_area makes a missing one.
Needs tasks:read; read-only.
Takes no parameters.
add_goal_area — Add a goal area
Make a new area to file goals under. Only when the person named one that does not exist — goal_areas says what already does.
Needs tasks:write; writes; answers with before and after.
| Parameter | Type | Required | What it is |
|---|---|---|---|
name |
string | yes | The area’s name. |
color |
string | — | A hex colour like #1d4ed8, if they chose one. |
requestId |
string | — | An id you choose for this call, such as a UUID, so it can be sent again safely: the same requestId with the same arguments within a day answers with the first answer, marked replayed, and nothing is made twice. Reused for a different call, it is refused with the code conflict. |
change_goal_area — Rename or recolour a goal area
Rename an area, or change its colour. Only id is needed: a field left out is untouched. A name another area already has is refused rather than merged. The goals filed under it stay where they are.
Needs tasks:write; writes; answers with before and after.
| Parameter | Type | Required | What it is |
|---|---|---|---|
id |
integer | yes | The area’s id, as goal_areas gives it. |
name |
string | — | The new name. |
color |
string | — | A hex colour like #1d4ed8. |
move_goal_area — Move a goal area up or down
Move an area one place earlier (delta: -1) or later (delta: 1) in the order goal_areas lists them, which is the order the app shows them in. Moving the first one earlier, or the last one later, changes nothing.
Needs tasks:write; writes; answers with before and after.
| Parameter | Type | Required | What it is |
|---|---|---|---|
id |
integer | yes | The area’s id, as goal_areas gives it. |
delta |
integer | yes | -1 for earlier, 1 for later. One of: -1, 1. |
all_habits — Every habit
The full list of habits, due today or not — id, name, type and which days each is scheduled. habits is today’s view with streaks; this is the one to read before adding or changing one. Archived habits are left out unless includeArchived is set; those carry an archivedAt.
Needs habits:read; read-only.
| Parameter | Type | Required | What it is |
|---|---|---|---|
includeArchived |
boolean | — | Default false. |
notebookId |
integer | — | Only what is filed in this notebook, as notebooks gives its id. Left out, all of it. |
add_habit — Add a habit
Start tracking a habit: something to keep doing (good), to avoid (bad), or just to watch (neutral). Scheduled days come in the same shape all_habits shows for existing ones; leave them out for every day.
Needs habits:write; writes; answers with before and after, after being the new habit.
| Parameter | Type | Required | What it is |
|---|---|---|---|
name |
string | yes | The habit, in the person’s own words. |
type |
string | — | good to keep, bad to avoid, neutral to watch. One of: bad, good, neutral. |
description |
string | — | Anything else about it. |
scheduledDays |
string | — | The days it is due, in the shape all_habits shows. Every day if left out. |
notebookId |
integer | — | The notebook this belongs to, as notebooks gives its id — a subject somebody is working through, like a renovation. Only when they said so. A notebook whose modules list does not hold this refuses it. |
requestId |
string | — | An id you choose for this call, such as a UUID, so it can be sent again safely: the same requestId with the same arguments within a day answers with the first answer, marked replayed, and nothing is made twice. Reused for a different call, it is refused with the code conflict. |
change_habit — Change a habit
Rename a habit or change its type, description or days. Only id is needed: a field left out is untouched. An empty description clears it; an empty scheduledDays clears the days. Its history of kept days stays exactly as it was.
Needs habits:write; writes; answers with before and after.
| Parameter | Type | Required | What it is |
|---|---|---|---|
id |
integer | yes | The habit’s id, as all_habits gives it. |
name |
string | — | The new name. |
type |
string | — | good, bad or neutral. One of: bad, good, neutral. |
description |
string | — | The new description. |
scheduledDays |
string | — | The new days, in the shape all_habits shows. |
archive_habit — Put a habit away
Stop tracking a habit without losing it: it leaves today’s list and the room, and every logged day is kept. unarchive_habit brings it back.
Needs habits:write; writes; answers with before and after.
| Parameter | Type | Required | What it is |
|---|---|---|---|
id |
integer | yes | The habit’s id, as all_habits gives it. |
unarchive_habit — Bring a habit back
Start tracking an archived habit again, with its history as it was. all_habits with includeArchived lists the archived ones.
Needs habits:write; writes; answers with before and after.
| Parameter | Type | Required | What it is |
|---|---|---|---|
id |
integer | yes | The habit’s id, as all_habits gives it. |
reminders — What will reach out, and when
Everything set to go off, soonest first: reminders on blocks, alarms about nothing in particular, birthdays, bills that want paying, and a weekly review left open. subjectKind says which. Include the past to see what already fired.
Needs schedule:read; read-only.
| Parameter | Type | Required | What it is |
|---|---|---|---|
includePast |
boolean | — | Default false. |
set_alarm — Set a reminder about nothing else
A time and a sentence, reaching the phone even with the app closed — "take the bread out at ten past", "ring mum at six". Use this when there is nothing to schedule; when the reminder is about something already on the day, remind_before_block hangs it on that block instead, which keeps the two together. cancel_alarm takes it back.
Needs schedule:write; writes; answers with before and after.
| Parameter | Type | Required | What it is |
|---|---|---|---|
at |
string | yes | When, as YYYY-MM-DDTHH:MM in the person’s own timezone. Seconds allowed and honoured. A bare YYYY-MM-DD means the hour their day starts. It has to be ahead of now — check the year, which is the one people leave out. |
message |
string | yes | What it should say, in their words. Markdown, like a todo’s notes: a picture is . |
sound |
boolean | — | Whether it should make a noise as well as showing. Silent unless asked; do not turn this on unless they said so. |
requestId |
string | — | An id you choose for this call, such as a UUID, so it can be sent again safely: the same requestId with the same arguments within a day answers with the first answer, marked replayed, and nothing is made twice. Reused for a different call, it is refused with the code conflict. |
change_reminder — Change a reminder that is already set
Move a reminder, reword it, or change whether it makes a noise — the one set_alarm made, or a nudge before a block. Send only what changes; anything left out stays as it is, and nothing is written unless all of it is valid. sound: null hands the choice back to the default. Takes the id reminders gives.
Needs schedule:write; writes; answers with before and after.
| Parameter | Type | Required | What it is |
|---|---|---|---|
id |
integer | yes | The reminder’s id. |
at |
string | — | A new time, as YYYY-MM-DDTHH:MM in the person’s own timezone. A bare YYYY-MM-DD means the hour their day starts. It has to be ahead of now. |
message |
string | — | What it should say instead, in their words. Markdown, like a todo’s notes. |
sound |
boolean | — | Whether it should make a noise. Leave it out to keep what it does now; do not turn this on unless they said so. |
cancel_alarm — Take a reminder back
Remove a reminder outright — the one set_alarm made, or any other. dismiss_reminder waves one off and leaves the row; this deletes it. Takes the id reminders gives.
Needs schedule:write and destructive; deletes; answers with before and after.
| Parameter | Type | Required | What it is |
|---|---|---|---|
id |
integer | yes | The reminder’s id. |
remind_task — Ring about a todo at a time
A reminder about one todo, at a time, reaching the phone even with the app closed — "remind me at six to send this". Says the todo’s title unless message says otherwise, and pressing it opens the todo list. The todo stays undated; schedule_task is for putting it on a day. change_reminder and cancel_alarm take the answer’s id.
Needs tasks:write; writes; answers with before and after.
| Parameter | Type | Required | What it is |
|---|---|---|---|
id |
integer | yes | The todo’s id, as tasks gives it. |
at |
string | yes | When, as YYYY-MM-DDTHH:MM in the person’s own timezone. A bare YYYY-MM-DD means the hour their day starts. It has to be ahead of now — check the year. |
message |
string | — | What it should say. The todo’s title if left out. |
sound |
boolean | — | Whether it should make a noise. Leave it out for what reminders do by default; do not turn this on unless they said so. |
requestId |
string | — | An id you choose for this call, such as a UUID, so it can be sent again safely: the same requestId with the same arguments within a day answers with the first answer, marked replayed, and nothing is made twice. Reused for a different call, it is refused with the code conflict. |
remind_before_block — Set a reminder on a block
Be told some minutes before a block starts — it reaches the phone even with the app closed. A reminder belongs to a block: for "remind me at three to call the dentist", first add_block the call at three, then set the reminder on it. Takes the id the day gives, like slot:42.
Needs schedule:write; writes; answers with before and after.
| Parameter | Type | Required | What it is |
|---|---|---|---|
id |
string | yes | The block’s id, exactly as the day gave it. |
minutes |
integer | yes | How many minutes before the start. 0 is at the start. |
message |
string | — | What the nudge should say. The block’s own name if left out. |
requestId |
string | — | An id you choose for this call, such as a UUID, so it can be sent again safely: the same requestId with the same arguments within a day answers with the first answer, marked replayed, and nothing is made twice. Reused for a different call, it is refused with the code conflict. |
dismiss_reminder — Dismiss a reminder
Wave one reminder off so it does not fire — for "no need to remind me about that any more". Takes the id reminders gives; the block it sat on is untouched.
Needs schedule:write; writes; answers with before and after.
| Parameter | Type | Required | What it is |
|---|---|---|---|
id |
integer | yes | The reminder’s id. |
repeating_week — The week as it repeats
The blocks that make up every week — each with its weekday, time, length and category. Weekdays are numbered from Monday: 0 is Monday, 6 is Sunday. Not all of them are weekly: repeats says in words how often each one comes back, which can be every N weeks, every N days, or a day of the month. This is the template the days are generated from; today and upcoming show what it produced. Read it before changing Tuesdays rather than a Tuesday.
Needs schedule:read; read-only.
| Parameter | Type | Required | What it is |
|---|---|---|---|
notebookId |
integer | — | Only what is filed in this notebook, as notebooks gives its id. Left out, all of it. |
add_repeating_block — Put a task block on every week
Add a block that comes back — "gym on Tuesdays at seven", "the bins every other Tuesday", "rent on the first". Weekly unless repeats says otherwise. This changes every week from now on; add_block is the one for a single day. Weekdays count from Monday: 0 is Monday, 6 is Sunday. A block can be a bare category rather than a named thing — leave the title out and it shows as the category itself, which is what "put work in those hours" means.
Needs schedule:write; writes; answers with before and after, after being the new repeatingBlock.
| Parameter | Type | Required | What it is |
|---|---|---|---|
weekday |
integer | yes | 0 is Monday, 6 is Sunday — the week starts on Monday here. |
title |
string | — | What it is — shown on the block. Leave it out for a block that is just the category. |
start_time |
string | yes | When it starts, as HH:MM on a 24-hour clock. |
minutes |
integer | — | How long it runs, in minutes. Default 60. |
category |
string | — | Which part of life it belongs to, by name — categories lists them. |
remind_minutes |
integer | — | Minutes before each occurrence to be reminded. No reminder if left out. |
notebookId |
integer | — | The notebook it belongs to, as notebooks gives its id — the subject it is part of. 0 takes it out of the one it is in. |
repeats |
string | — | How often it comes back. Weekly if left out. every_n_weeks and every_n_days need every; monthly needs month_day and ignores the weekday. One of: weekly, every_n_weeks, every_n_days, monthly. |
every |
integer | — | The N in every N weeks or every N days — 2 is "every other". |
month_day |
integer | — | For monthly: which day of the month, 1 to 31. A month too short for it uses its last day. |
urgency |
integer | — | How soon it has to happen, 0–5. On a change, null clears it. |
interest |
integer | — | How much they want to do it, 0–5. On a change, null clears it. |
ease |
integer | — | How easy it is, 0–5, five being easiest. On a change, null clears it. Replaces energy, which asked the opposite question on a scale that began at one. |
energy |
integer | — | Deprecated — use ease, which is this turned round: an energy of 5 is an ease of 1. Still accepted so an assistant written against the old shape keeps working, and removed in 0.190.0. Deprecated — removed in 0.190.0. |
attributes |
object | — | Its attributes: key/value pairs such as { "url": "https://…", "room": "B12" }, read by plugins and shown on the task. Keys are lowercase letters, digits and underscores. This replaces the whole set: send every pair to keep, an empty value removes one, and {} removes them all. Left out, they are untouched. Any key, each holding a string. |
meta |
object | — | Deprecated — use attributes, which is the same thing under the name the app uses. Still accepted so an assistant written against the old shape keeps working, and removed in 0.190.0. Any key, each holding a string. Deprecated — removed in 0.190.0. |
requestId |
string | — | An id you choose for this call, such as a UUID, so it can be sent again safely: the same requestId with the same arguments within a day answers with the first answer, marked replayed, and nothing is made twice. Reused for a different call, it is refused with the code conflict. |
change_repeating_block — Change a repeating task block
Change every future occurrence of a repeating block: its weekday, time, length, how often it comes back, the text on it, its category, its reminder, its notebook or its attributes — or pause and resume it. This is "move gym to Wednesdays" or "make it every other week"; change_block is "move this Wednesday’s gym". Only id is needed: a field left out is untouched, and nothing is written unless all of it is valid. An empty title takes the text off. Takes the id repeating_week gives.
Needs schedule:write; writes; answers with before and after.
| Parameter | Type | Required | What it is |
|---|---|---|---|
id |
integer | yes | The repeating block’s id, as repeating_week gives it. |
weekday |
integer | — | The new weekday. 0 is Monday, 6 is Sunday. |
start_time |
string | — | The new start, as HH:MM. |
minutes |
integer | — | The new length, in minutes. |
title |
string | — | The text shown on the block. A block that names an activity stays that activity — this only changes what the block says, which is how "add stretching to the morning routine’s text" is done. |
category |
string | — | Refile it under this part of life, by name. |
remind_minutes |
integer | — | The new reminder lead. 0 turns it off. |
paused |
boolean | — | true pauses it: it stops coming back until it is resumed, and its past occurrences stay. false resumes it. |
notebookId |
integer | — | The notebook it belongs to, as notebooks gives its id — the subject it is part of. 0 takes it out of the one it is in. |
repeats |
string | — | How often it comes back. Weekly if left out. every_n_weeks and every_n_days need every; monthly needs month_day and ignores the weekday. One of: weekly, every_n_weeks, every_n_days, monthly. |
every |
integer | — | The N in every N weeks or every N days — 2 is "every other". |
month_day |
integer | — | For monthly: which day of the month, 1 to 31. A month too short for it uses its last day. |
attributes |
object | — | Its attributes: key/value pairs such as { "url": "https://…", "room": "B12" }, read by plugins and shown on the task. Keys are lowercase letters, digits and underscores. This replaces the whole set: send every pair to keep, an empty value removes one, and {} removes them all. Left out, they are untouched. Any key, each holding a string. |
meta |
object | — | Deprecated — use attributes, which is the same thing under the name the app uses. Still accepted so an assistant written against the old shape keeps working, and removed in 0.190.0. Any key, each holding a string. Deprecated — removed in 0.190.0. |
ifUpdatedAt |
string | — | Only change it if nothing has changed it since: the updatedAt a read or an earlier change answered with. If something has, nothing is written and the call is refused with the code conflict, the current updatedAt in its details. |
remove_repeating_block — Take a block out of the week
Remove a repeating block from every week to come. Its past occurrences and their record stay. For one day only, use cancel_block instead — this is the whole pattern.
Needs schedule:write and destructive; deletes; answers with before and after.
| Parameter | Type | Required | What it is |
|---|---|---|---|
id |
integer | yes | The repeating block’s id. |
categories — The parts of a life
The categories blocks are filed under — the areas of this person’s life, each with its colour. Read it before writing a block, so the name is real rather than guessed.
Needs schedule:read; read-only.
Takes no parameters.
activities — The named recurring things
Activities are the named things inside categories — "piano", not just "music". A block can name one instead of a bare category. add_activity and change_activity write them.
Needs schedule:read; read-only.
Takes no parameters.
add_activity — Name a new recurring thing
Add an activity — a named thing inside a category, like "piano" inside "music" — so blocks can name it instead of the bare category.
Needs schedule:write; writes; answers with before and after, after being the new activity.
| Parameter | Type | Required | What it is |
|---|---|---|---|
name |
string | yes | What it is called. |
category |
string | — | The category it belongs to, by name — categories lists them. |
description |
string | — | A line about it, shown where it is edited. |
requestId |
string | — | An id you choose for this call, such as a UUID, so it can be sent again safely: the same requestId with the same arguments within a day answers with the first answer, marked replayed, and nothing is made twice. Reused for a different call, it is refused with the code conflict. |
change_activity — Rename an activity, or say what it is
Change an activity: its name, the line describing it, which category it belongs to, or whether it is switched on. Takes the id activities gives. Only id is needed: a field left out is untouched. Blocks that name it follow the change; nothing on any day is moved.
Needs schedule:write; writes; answers with before and after.
| Parameter | Type | Required | What it is |
|---|---|---|---|
id |
integer | yes | The activity’s id, as activities gave it. |
name |
string | — | A new name. |
description |
string | — | A new line about it. Pass an empty string to clear it. |
category |
string | — | Move it to this category, by name. |
active |
boolean | — | false switches it off: it stops being offered for new blocks, and every block and record that names it stays as it is. true switches it back on. |
ifUpdatedAt |
string | — | Only change it if nothing has changed it since: the updatedAt a read or an earlier change answered with. If something has, nothing is written and the call is refused with the code conflict, the current updatedAt in its details. |
remove_activity — Delete an activity
Delete an activity, used or not. Without moveTo, every block that named it becomes a block of its category labelled with its name, past occurrences keep the name, and goals stop counting it. With moveTo, all of it — blocks, occurrences, goal links — names that activity instead. To keep it as it is, switch it off with change_activity and active: false.
Needs schedule:write and destructive; deletes; answers with before and after.
| Parameter | Type | Required | What it is |
|---|---|---|---|
id |
integer | yes | The activity’s id, as activities gave it. |
moveTo |
integer | — | Another activity to hand everything that named this one to. Left off, it falls back to the category. |
people — The people in their life
Everybody the person keeps a page for — name, relationship, birthday, contact details. These are other people’s facts held in this account, which is why they sit behind their own permission.
Needs people:read; read-only.
Takes no parameters.
upcoming_birthdays — Whose birthday is coming
Birthdays in the days ahead, soonest first — the answer to "whose birthday is coming up". Only people with a birthday written down appear.
Needs people:read; read-only.
| Parameter | Type | Required | What it is |
|---|---|---|---|
days |
integer | — | How many days ahead to look. Default 30. |
add_person — Add a person
Keep a page for somebody — name at minimum; birthday as YYYY-MM-DD, or --MM-DD when the year is unknown. A birthday written down announces itself on the morning, unless told not to.
Needs people:write; writes; answers with before and after, after being the new person.
| Parameter | Type | Required | What it is |
|---|---|---|---|
name |
string | yes | Their name, as the person says it. |
relationship |
string | — | The nearest of these — "sister" is family, "landlord" is professional. One of: family, friend, partner, professional, other. |
birthday |
string | — | YYYY-MM-DD, or --MM-DD without a year. |
remindOnBirthday |
boolean | — | Announce the birthday that morning. On if left out. |
phone |
string | — | A phone number. |
email |
string | — | An email address. |
notes |
string | — | Anything else worth keeping. |
requestId |
string | — | An id you choose for this call, such as a UUID, so it can be sent again safely: the same requestId with the same arguments within a day answers with the first answer, marked replayed, and nothing is made twice. Reused for a different call, it is refused with the code conflict. |
change_person — Change a person’s page
Correct or extend what is recorded about somebody — a birthday learnt, a number changed. Only id is needed: a field left out is untouched, and an empty string clears a birthday, phone, email or notes. Takes the id people gives.
Needs people:write; writes; answers with before and after.
| Parameter | Type | Required | What it is |
|---|---|---|---|
id |
integer | yes | The person’s id. |
name |
string | — | The new name. |
relationship |
string | — | The new relationship, one of these. One of: family, friend, partner, professional, other. |
birthday |
string | — | YYYY-MM-DD, or --MM-DD without a year. |
remindOnBirthday |
boolean | — | Whether the birthday announces itself. |
phone |
string | — | The new phone number. |
email |
string | — | The new email address. |
notes |
string | — | The new notes. |
ifUpdatedAt |
string | — | Only change it if nothing has changed it since: the updatedAt a read or an earlier change answered with. If something has, nothing is written and the call is refused with the code conflict, the current updatedAt in its details. |
daily_wins — Three things that went well
The day’s three wins, as written. A practice, not a log: three lines a day, and blank ones are simply not written yet.
Needs notes:read; read-only.
| Parameter | Type | Required | What it is |
|---|---|---|---|
date |
string | — | The day, as YYYY-MM-DD. Today if left out. |
record_win — Record a win
Write one of the day’s three good things, in the person’s own words, into the first empty line. Refused when all three are written — a day holds three, and the fourth is tomorrow’s first.
Needs notes:write; writes; answers with before and after.
| Parameter | Type | Required | What it is |
|---|---|---|---|
content |
string | yes | The win, exactly as they said it. |
date |
string | — | The day it belongs to, as YYYY-MM-DD. Today if left out. |
requestId |
string | — | An id you choose for this call, such as a UUID, so it can be sent again safely: the same requestId with the same arguments within a day answers with the first answer, marked replayed, and nothing is made twice. Reused for a different call, it is refused with the code conflict. |
weekly_review — How a week actually went
A week read whole: planned against done, by category, with the three lines written about it. The heart of the app — this is what the Monday mail says, and what closing a week means. Defaults to the week now running.
Needs tasks:read; read-only.
| Parameter | Type | Required | What it is |
|---|---|---|---|
weekStart |
string | — | The day the week starts on, as YYYY-MM-DD — the account’s own first day, Monday unless it says otherwise. Any day inside the week works; it snaps. This week if left out. |
write_review_note — Write the week’s note
Replace the note on a week’s review — in the person’s own words, and only when they said them. This is what they will reread in a year; never compose it unasked. It used to be three separate lines and is one piece of writing now, so a note somebody dictates in three sentences is stored as they said it.
Needs tasks:write; writes; answers with before and after.
| Parameter | Type | Required | What it is |
|---|---|---|---|
note |
string | yes | The whole note, replacing what was there. Empty removes it. |
weekStart |
string | — | The day the week starts on — the account’s own first day. Any day inside the week works; it snaps. This week if left out. |
data_streams — The numbers being tracked
The account’s data streams — weight, mood, sleep, anything a plugin or a person logs over time — each with its slug, kind and unit. log_data_point writes into one by its slug.
Needs streams:read; read-only.
Takes no parameters.
log_data_point — Log a reading
Write one point into a data stream — "I weigh 82 today", "slept 6 hours". Takes the stream’s slug as data_streams gives it; a slug that names nothing is refused with the list, never created on the quiet.
Needs streams:write; writes; answers with before and after.
| Parameter | Type | Required | What it is |
|---|---|---|---|
stream |
string | yes | The stream’s slug, as data_streams gives it. |
value |
number | yes | The reading. |
at |
string | — | When it was taken, as an ISO instant. Now if left out. |
text |
string | — | A word beside the number, if they said one. |
requestId |
string | — | An id you choose for this call, such as a UUID, so it can be sent again safely: the same requestId with the same arguments within a day answers with the first answer, marked replayed, and nothing is made twice. Reused for a different call, it is refused with the code conflict. |
apply_idea — Mark an idea applied
Say an idea was acted on, with a note about what came of it — or take that back by calling it again. Applied is not deleted: the idea stays, wearing what happened.
Needs ideas:write; writes; answers with before and after.
| Parameter | Type | Required | What it is |
|---|---|---|---|
id |
integer | yes | The idea’s id, as ideas gives it. |
note |
string | — | What came of it, if they said. |
favorite_idea — Star an idea
Star an idea, or unstar it by calling this again. A star is the person’s to ask for — never decorate their inbox on your own judgement.
Needs ideas:write; writes; answers with before and after.
| Parameter | Type | Required | What it is |
|---|---|---|---|
id |
integer | yes | The idea’s id. |
where_is — Where a thing lives
Find a thing by name and say where it lives — "Living room › White chest › First drawer" — with its fields (a tape’s length, a cable’s plug). The inventory half of the shopping list.
Needs locations:read; read-only.
| Parameter | Type | Required | What it is |
|---|---|---|---|
name |
string | yes | The thing, by name or part of it. |
locations — The locations tree
Every location, nested the way the house is — rooms holding furniture holding drawers — each with how many things sit directly in it.
Needs locations:read; read-only.
Takes no parameters.
add_location — Add a location
Add a location things can live in — a room, a chest, a drawer — optionally inside another location.
Needs locations:write; writes; answers with before and after, after being the new location.
| Parameter | Type | Required | What it is |
|---|---|---|---|
name |
string | yes | What the location is called. |
parent_id |
integer | — | The location it is inside, from locations. |
requestId |
string | — | An id you choose for this call, such as a UUID, so it can be sent again safely: the same requestId with the same arguments within a day answers with the first answer, marked replayed, and nothing is made twice. Reused for a different call, it is refused with the code conflict. |
change_location — Rename or move a location
Rename a location, or move it under a different parent. Only id is needed: a field left out is untouched, its notes included. parent_id of 0 or null moves it to the top level. It refuses to be put inside itself.
Needs locations:write; writes; answers with before and after.
| Parameter | Type | Required | What it is |
|---|---|---|---|
id |
integer | yes | The location’s id. |
name |
string | — | The name, rewritten. |
parent_id |
integer | — | The new parent. 0 or null moves it to the top level; left out, it stays where it is. |
ifUpdatedAt |
string | — | Only change it if nothing has changed it since: the updatedAt a read or an earlier change answered with. If something has, nothing is written and the call is refused with the code conflict, the current updatedAt in its details. |
remove_location — Remove a location
Remove a location. Locations inside it rise to where it was; things in it stay, just without an address.
Needs locations:write and destructive; deletes; answers with before and after.
| Parameter | Type | Required | What it is |
|---|---|---|---|
id |
integer | yes | The location’s id. |
put_item — Say where a thing lives
Put a shopping/inventory item in a location, or take its address away by leaving location_id out. The item itself is untouched.
Needs locations:write; writes; answers with before and after.
| Parameter | Type | Required | What it is |
|---|---|---|---|
id |
integer | yes | The item’s id, as shopping_list gives it. |
location_id |
integer | — | The location, from locations. Leave out to unfile. |
set_item_attributes — Set a thing’s attributes
Replace an item’s attributes wholesale — { "length": "5m", "plug": "USB-C" }. Not every thing shares a shape; these are this thing’s. A name with an empty value is a whole attribute: "cable" says as much as "kind": "cable". Send the full set: removing one is writing the rest.
Needs inventory:write; writes; answers with before and after.
| Parameter | Type | Required | What it is |
|---|---|---|---|
id |
integer | yes | The item’s id. |
attributes |
object | yes | The attributes, string values. An empty value is allowed. Any key, each holding a string. |
inventory_attributes — What the things say about themselves
Every attribute the account’s things carry — "length", "brand" — with how many things carry it, the values it takes, and any colour given to either. Read it before renaming or removing one.
Needs inventory:read; read-only.
Takes no parameters.
change_inventory_attribute — Rename or recolour an attribute
Rename an attribute on every thing that carries it — or merge it into another by renaming onto that name — or, with value, rename or recolour just that value of it. color is #rrggbb; an empty string takes the colour off. Its way back is the opposite rename.
Needs inventory:write; writes; answers with before and after.
| Parameter | Type | Required | What it is |
|---|---|---|---|
key |
string | yes | The attribute, as inventory_attributes spells it. |
value |
string | — | One of its values, to act on that value alone. Left out, the attribute itself. |
rename |
string | — | The new name for the attribute, or for the value when value is given. |
color |
string | — | A colour, #rrggbb, or an empty string for none. |
remove_inventory_attribute — Take an attribute off everything
Take an attribute off every thing that carries it, or with value, only off the things that say that value. The things themselves stay. set_item_attributes puts one back on a thing.
Needs inventory:write and destructive; deletes; answers with before and after.
| Parameter | Type | Required | What it is |
|---|---|---|---|
key |
string | yes | The attribute, as inventory_attributes spells it. |
value |
string | — | One of its values, to take off only the things that say it. |
workouts — Your workouts
The workouts you have written down, under Health. Each has a category and a plan; put one on the week with add_block and its workoutId to have it planned like a meal.
Needs workouts:read; read-only.
| Parameter | Type | Required | What it is |
|---|---|---|---|
include_archived |
boolean | — | Include ones put away. |
notebookId |
integer | — | Only what is filed in this notebook, as notebooks gives its id. Left out, all of it. |
set_workout_measures — Say what a workout measures
Declare what a workout is measured by — a run by kilometres and a pace, a push day by what was benched and for how many reps. Names and units only; no amounts. Replaces the list it has, so send all of them. A session may still measure anything: this decides what its form opens on.
Needs workouts:write; writes; answers with before and after.
| Parameter | Type | Required | What it is |
|---|---|---|---|
id |
integer | yes | The workout, from workouts. |
measures |
object[] | yes | What this workout is measured by, in the order a session should be asked for them. Names and units in the person’s own words; no amounts. |
measures[].activity |
string | yes | What is measured: “ran”, “benched”. |
measures[].unit |
string | — | Of what: “km”, “kg”, “reps”. |
workout_sessions — What was actually done
Sessions, newest first: the day, anything noted, and lines of activity, amount and unit in the person’s own words — ran 5 km, deadlifted 120 kg. Narrow it with workout_id or since rather than reading everything.
Needs workouts:read; read-only; answers a page.
| Parameter | Type | Required | What it is |
|---|---|---|---|
workout_id |
integer | — | Only this workout’s, from workouts. |
since |
string | — | Only sessions on or after this day, as YYYY-MM-DD. |
limit |
integer | — | How many sessions. Default 50. |
offset |
integer | — | Skip this many before counting, so the rest of the register can be read a page at a time. nextOffset on the answer is what to pass here next. Default 0. |
log_workout — Write down a session
Record that a workout happened, and how much of what was done. Everything but the workout is optional: a session with no lines is one that happened. Use the person’s own words and units — "ran" and "km", not a normalised distance — because that is what a chart of it will be grouped by. workout_sessions shows what they have called things before.
Needs workouts:write; writes; answers with before and after, after being the new workoutSession.
| Parameter | Type | Required | What it is |
|---|---|---|---|
workout_id |
integer | yes | Which workout, from workouts. |
done_on |
string | — | The day, as YYYY-MM-DD. Today if left off. |
notes |
string | — | Anything worth saying about it. |
measures |
object[] | — | What was done, a line each. amount and unit may be left off for something that happened without a number attached. |
measures[].activity |
string | yes | What was done: "ran", "deadlifted". |
measures[].amount |
number | — | How much. |
measures[].unit |
string | — | Of what: "km", "kg", "reps". |
requestId |
string | — | An id you choose for this call, such as a UUID, so it can be sent again safely: the same requestId with the same arguments within a day answers with the first answer, marked replayed, and nothing is made twice. Reused for a different call, it is refused with the code conflict. |
change_workout_session — Correct a session
Rewrite a session that was written down wrong. Only id is needed: a field left out is untouched. The lines are replaced by the ones given, so send them all; leaving measures off keeps the ones it has, and [] removes them. An empty notes clears the notes. The session and its lines land together or not at all.
Needs workouts:write; writes; answers with before and after.
| Parameter | Type | Required | What it is |
|---|---|---|---|
id |
integer | yes | The session’s id, from workout_sessions. |
done_on |
string | — | The day it actually happened, as YYYY-MM-DD. |
notes |
string | — | What to say about it instead. |
measures |
object[] | — | The lines, replacing every one it has. |
measures[].activity |
string | yes | What was done: "ran", "deadlifted". |
measures[].amount |
number | — | How much. |
measures[].unit |
string | — | Of what: "km", "kg", "reps". |
ifUpdatedAt |
string | — | Only change it if nothing has changed it since: the updatedAt a read or an earlier change answered with. If something has, nothing is written and the call is refused with the code conflict, the current updatedAt in its details. |
remove_workout_session — Remove a session
Delete a session that was logged by accident. Its lines go with it; the workout itself stays. For correcting one rather than removing it, use change_workout_session.
Needs workouts:write and destructive; deletes; answers with before and after.
| Parameter | Type | Required | What it is |
|---|---|---|---|
id |
integer | yes | The session’s id, from workout_sessions. |
workout_history — One activity over time
Every time one activity was measured, oldest first — the shape to draw or to compare against. workout_activities lists what this account has measured and how often, which is where the name comes from.
Needs workouts:read; read-only.
| Parameter | Type | Required | What it is |
|---|---|---|---|
activity |
string | yes | The activity, exactly as it was written down: "ran". |
since |
string | — | Only from this day on, as YYYY-MM-DD. |
workout_activities — What this account measures
Every activity and unit that has ever been written down, with how many times — the names workout_history takes, and the ones to reuse when logging so a chart groups them together.
Needs workouts:read; read-only.
Takes no parameters.
workout_categories — The categories of workout this account keeps
The categories a workout can be filed under — this account’s own list, not a fixed one. add_workout and change_workout take a category_id from here.
Needs workouts:read; read-only.
Takes no parameters.
add_workout_category — Add a category of workout
Add a category to this account’s list — "Swimming", "Physio". Answering with one that already exists returns it rather than making a second.
Needs workouts:write; writes; answers with before and after, after being the new workoutCategory.
| Parameter | Type | Required | What it is |
|---|---|---|---|
name |
string | yes | What the category is called. |
requestId |
string | — | An id you choose for this call, such as a UUID, so it can be sent again safely: the same requestId with the same arguments within a day answers with the first answer, marked replayed, and nothing is made twice. Reused for a different call, it is refused with the code conflict. |
change_workout_category — Rename a category of workout
Rename one of the account’s workout categories. The workouts filed under it stay filed under it.
Needs workouts:write; writes; answers with before and after.
| Parameter | Type | Required | What it is |
|---|---|---|---|
id |
integer | yes | From workout_categories. |
name |
string | yes | What it is called now. |
remove_workout_category — Remove a category of workout
Take a category off the list. Workouts filed under it keep existing, without one.
Needs workouts:write and destructive; deletes; answers with before and after.
| Parameter | Type | Required | What it is |
|---|---|---|---|
id |
integer | yes | From workout_categories. |
add_workout — Add a workout
Write a workout down: a title, a category (one of the account’s own, from workout_categories), a plan as Markdown, and roughly how long it takes. Scheduling it onto a day is a block with its workoutId, the way a meal is a block with a recipe.
Needs workouts:write; writes; answers with before and after, after being the new workout.
| Parameter | Type | Required | What it is |
|---|---|---|---|
title |
string | yes | What the session is called. |
category_id |
integer | — | Its category, from workout_categories. |
plan |
string | — | What to do, as Markdown. |
minutes |
integer | — | Roughly how long it takes. |
notes |
string | — | Anything else. |
measures |
object[] | — | What this workout is measured by, in the order a session should be asked for them. Names and units in the person’s own words; no amounts. |
measures[].activity |
string | yes | What is measured: “ran”, “benched”. |
measures[].unit |
string | — | Of what: “km”, “kg”, “reps”. |
notebookId |
integer | — | The notebook this belongs to, as notebooks gives its id — a subject somebody is working through, like a renovation. Only when they said so. A notebook whose modules list does not hold this refuses it. |
requestId |
string | — | An id you choose for this call, such as a UUID, so it can be sent again safely: the same requestId with the same arguments within a day answers with the first answer, marked replayed, and nothing is made twice. Reused for a different call, it is refused with the code conflict. |
change_workout — Change a workout
Rewrite a workout — for a misheard word or a better plan, not to turn it into a different session. Only id is needed: a field left out is untouched. An empty string clears the plan or the notes; 0 or null clears minutes or category_id.
Needs workouts:write; writes; answers with before and after.
| Parameter | Type | Required | What it is |
|---|---|---|---|
id |
integer | yes | The workout’s id, as workouts gives it. |
title |
string | — | The title, rewritten. |
category_id |
integer | — | Its category, from workout_categories. |
plan |
string | — | The plan, rewritten. |
minutes |
integer | — | Roughly how long it takes. |
notes |
string | — | Notes, replacing the old ones. |
ifUpdatedAt |
string | — | Only change it if nothing has changed it since: the updatedAt a read or an earlier change answered with. If something has, nothing is written and the call is refused with the code conflict, the current updatedAt in its details. |
archive_workout — Put a workout away, or bring it back
Take a workout out of the working list, or restore it. Nothing is lost either way — its history stays.
Needs workouts:write; writes; answers with before and after.
| Parameter | Type | Required | What it is |
|---|---|---|---|
id |
integer | yes | The workout’s id. |
archived |
boolean | — | true to put away, false to bring back. Defaults to true. |
workout_done — Mark a workout done
Record that a workout happened just now — the gym’s version of marking a recipe cooked. It stamps the last-done time.
Needs workouts:write; writes; answers with before and after.
| Parameter | Type | Required | What it is |
|---|---|---|---|
id |
integer | yes | The workout’s id. |
budgets — Monthly category budgets
Allocated, spent, remaining and separate refund credits for one month in original currencies. Budgets do not move money. Orphaned categories remain visible. Defaults to the account’s current month.
Needs statements:read; read-only; answers a page.
| Parameter | Type | Required | What it is |
|---|---|---|---|
month |
string | — | YYYY-MM. |
currency |
string | — | One original ISO currency. |
limit |
integer | — | Maximum budgets per page. Default 100. |
offset |
integer | — | Skip this many before counting, so the rest of budgets can be read a page at a time. nextOffset on the answer is what to pass here next. Default 0. |
add_budget — Set a monthly category ceiling
Create a ceiling for one category, month and original currency with an owned ledger. Exact nonnegative minor units. No bank movement, stock entry or reserve is created.
Needs statements:write; writes; answers with before and after, after being the new budget.
| Parameter | Type | Required | What it is |
|---|---|---|---|
month |
string | yes | YYYY-MM. |
category |
string | yes | Existing category rule name. |
currency |
string | yes | Original ISO currency. |
amount_minor |
integer | yes | Nonnegative ceiling in original minor units. |
requestId |
string | — | An id you choose for this call, such as a UUID, so it can be sent again safely: the same requestId with the same arguments within a day answers with the first answer, marked replayed, and nothing is made twice. Reused for a different call, it is refused with the code conflict. |
change_budget — Change a budget ceiling
Change only named budget fields. Omitted values stay unchanged. ifUpdatedAt refuses stale edits; no bank or stock record changes.
Needs statements:write; writes; answers with before and after.
| Parameter | Type | Required | What it is |
|---|---|---|---|
id |
integer | yes | Budget id. |
month |
string | — | YYYY-MM. |
category |
string | — | Category name. |
currency |
string | — | Original ISO currency. |
amount_minor |
integer | — | Nonnegative ceiling in original minor units. |
ifUpdatedAt |
string | — | Only change it if nothing has changed it since: the updatedAt a read or an earlier change answered with. If something has, nothing is written and the call is refused with the code conflict, the current updatedAt in its details. |
delete_budget — Remove a budget ceiling
Remove only a monthly ceiling. The before state is retained for recovery; bank history and spending remain unchanged.
Needs statements:write and destructive; deletes; answers with before and after.
| Parameter | Type | Required | What it is |
|---|---|---|---|
id |
integer | yes | Budget id. |
copy_budgets — Copy missing monthly budgets
Copy ceilings between civil months in one transaction. Existing category/currency buckets are never overwritten. Returns added and skipped counts; no money moves.
Needs statements:write; writes; answers with before and after.
| Parameter | Type | Required | What it is |
|---|---|---|---|
from_month |
string | yes | Source YYYY-MM. |
to_month |
string | yes | Target YYYY-MM. |
requestId |
string | — | An id you choose for this call, such as a UUID, so it can be sent again safely: the same requestId with the same arguments within a day answers with the first answer, marked replayed, and nothing is made twice. Reused for a different call, it is refused with the code conflict. |
personal_spending — Personal spending and exclusions
Original-currency groups of gross expenses, refunds, signed net spending, personal income, transfer and cash exclusions, custody shares and unclassified counts. Refunds follow their actual date and parent category, never income. No balance or available-funds claim. Without a window reports the last 12 calendar months.
Needs statements:read; read-only.
| Parameter | Type | Required | What it is |
|---|---|---|---|
month |
string | — | One civil month, YYYY-MM. |
from |
string | — | Inclusive first civil day, YYYY-MM-DD. |
to |
string | — | Inclusive last civil day, YYYY-MM-DD. |
currency |
string | — | One original ISO currency, or unspecified. Omit only for separate currency groups. |
ledger_id |
integer | — | Only this owned ledger. |
summary — The money picture
One answer to the four money questions — what is mine, what is committed, what I spent this month and what is left against my plans — for every original currency separately, never a combined total. Funds, stocks (custody, reserves, payables, receivables), personal spending with its exclusions, and the month’s budgets. Available is funds minus custody minus reserves, never payables or receivables. Gaps such as an account without a declared opening or unclassified lines are named, not hidden in a confident number.
Needs statements:read; read-only.
| Parameter | Type | Required | What it is |
|---|---|---|---|
month |
string | — | The civil month, YYYY-MM. Defaults to this month in the account timezone. |
as_of |
string | — | Inclusive balance date YYYY-MM-DD; defaults to today in the account timezone. |
commitments — What you owe, hold and set aside
Custody, payables, receivables and reserves are stocks, not bank movements or budgets. Each balance is its opening plus entries, in its own currency. Totals stay separate by kind and currency; never subtract payables or add receivables to available bank funds.
Needs statements:read; read-only; answers a page.
| Parameter | Type | Required | What it is |
|---|---|---|---|
include_archived |
boolean | — | Include settled and archived records. |
limit |
integer | — | Maximum records per page. Default 100. |
offset |
integer | — | Skip this many before counting, so the rest of commitments can be read a page at a time. nextOffset on the answer is what to pass here next. Default 0. |
commitment_entries — A commitment’s history
Entries and running balances for one commitment. Positive increases the obligation or earmark; negative reduces it. Linked movements remain in their original ledgers.
Needs statements:read; read-only; answers a page.
| Parameter | Type | Required | What it is |
|---|---|---|---|
commitment_id |
integer | yes | Commitment id from commitments. |
limit |
integer | — | Maximum entries per page. Default 100. |
offset |
integer | — | Skip this many before counting, so the rest of commitment entries can be read a page at a time. nextOffset on the answer is what to pass here next. Default 0. |
add_commitment — Record money owed, held or set aside
Create a stock without moving money: custody is held for someone, payable is owed, receivable is owed to you, reserve is your earmark. Currency is explicit ISO 4217; opening_minor is nonnegative original-currency minor units. No bank line or expense is created.
Needs statements:write; writes; answers with before and after, after being the new commitment.
| Parameter | Type | Required | What it is |
|---|---|---|---|
name |
string | yes | What this stock is called. |
kind |
string | yes | The stock’s meaning. One of: custody, payable, receivable, reserve. |
currency |
string | yes | Original ISO 4217 currency; never inferred. |
opening_minor |
integer | — | Nonnegative opening in original minor units. |
person_id |
integer | — | Optional owner-scoped person id. |
notes |
string | — | Optional notes, at most 2000 characters. |
requestId |
string | — | An id you choose for this call, such as a UUID, so it can be sent again safely: the same requestId with the same arguments within a day answers with the first answer, marked replayed, and nothing is made twice. Reused for a different call, it is refused with the code conflict. |
change_commitment — Correct a commitment
Edit the fields originally recorded. Omitted fields stay untouched; person_id 0 clears the person. Currency, kind and opening changes cannot invalidate retained history. Settlements and adjustments belong in entries, not in an invented bank movement.
Needs statements:write; writes; answers with before and after.
| Parameter | Type | Required | What it is |
|---|---|---|---|
id |
integer | yes | Commitment id. |
name |
string | — | A new name. |
kind |
string | — | A new kind, when history permits. One of: custody, payable, receivable, reserve. |
currency |
string | — | Original ISO currency; no conversion is performed. |
opening_minor |
integer | — | Corrected opening in minor units. |
person_id |
integer | — | Person id; 0 clears it. |
notes |
string | — | Replacement notes; an empty string clears them. |
ifUpdatedAt |
string | — | Only change it if nothing has changed it since: the updatedAt a read or an earlier change answered with. If something has, nothing is written and the call is refused with the code conflict, the current updatedAt in its details. |
archive_commitment — Put a commitment away or reopen it
Archive without losing history. archived false reopens it. No balance or bank line changes.
Needs statements:write; writes; answers with before and after.
| Parameter | Type | Required | What it is |
|---|---|---|---|
id |
integer | yes | Commitment id. |
archived |
boolean | yes | True archives; false reopens. |
close_commitment — Close a settled commitment
Close a zero balance. A nonzero balance is refused unless write_off_note explicitly authorizes and explains an entry removing the residual. No ledger adjustment is made. archive_commitment with archived false reopens the record; undo any write-off separately through its entry.
Needs statements:write; writes; answers with before and after.
| Parameter | Type | Required | What it is |
|---|---|---|---|
id |
integer | yes | Commitment id. |
write_off_note |
string | — | Explicit authorization and reason to write off the residual. |
requestId |
string | — | An id you choose for this call, such as a UUID, so it can be sent again safely: the same requestId with the same arguments within a day answers with the first answer, marked replayed, and nothing is made twice. Reused for a different call, it is refused with the code conflict. |
record_commitment_entry — Record a stock adjustment
One dated adjustment in signed minor units: positive increases, negative reduces. An optional transaction_id links real evidence and must obey its currency, sign and allocation guards; use settle_commitment or consume_reserve for a payment. Nothing moves in the ledger. delete_commitment_entry reverses a mistake.
Needs statements:write; writes; answers with before and after, after being the new commitmentEntry.
| Parameter | Type | Required | What it is |
|---|---|---|---|
commitment_id |
integer | yes | Commitment id. |
occurred_on |
string | yes | Civil date YYYY-MM-DD. |
amount_minor |
integer | yes | Signed original-currency minor units. |
transaction_id |
integer | — | Optional bank movement evidence. |
note |
string | — | Why the stock changed, at most 2000 characters. |
requestId |
string | — | An id you choose for this call, such as a UUID, so it can be sent again safely: the same requestId with the same arguments within a day answers with the first answer, marked replayed, and nothing is made twice. Reused for a different call, it is refused with the code conflict. |
delete_commitment_entry — Reverse a mistaken commitment entry
Remove one mistaken stock entry, restoring its effect on the commitment. Refuses an invalid resulting balance. Movement and allocations stay intact; explicitly unsplit afterward if needed. The owner can Put it back from the assistant log through the same validated entry service.
Needs statements:write and destructive; deletes; answers with before and after.
| Parameter | Type | Required | What it is |
|---|---|---|---|
id |
integer | yes | Entry id from commitment_entries. |
settle_commitment — Offset or settle with an existing payment
Apply one owned, same-currency bank movement to custody, payable or receivable once. Refuses overpayment and duplicate evidence. An owner’s expense becomes custody allocation, not personal spending. This never creates or changes a bank amount. Reverse its entry explicitly, then unsplit the movement.
Needs statements:write; writes; answers with before and after.
| Parameter | Type | Required | What it is |
|---|---|---|---|
commitment_id |
integer | yes | Commitment to reduce. |
transaction_id |
integer | yes | Existing payment movement. |
note |
string | — | Optional settlement evidence. |
requestId |
string | — | An id you choose for this call, such as a UUID, so it can be sent again safely: the same requestId with the same arguments within a day answers with the first answer, marked replayed, and nothing is made twice. Reused for a different call, it is refused with the code conflict. |
consume_reserve — Use a reserve for an existing expense
Reduce a reserve once using a same-currency expense or fee already recorded. The payment stays personal spending exactly once. Refuses overconsumption, duplicate evidence or a custody split. Reverse the entry to undo; ledger truth stays unchanged.
Needs statements:write; writes; answers with before and after.
| Parameter | Type | Required | What it is |
|---|---|---|---|
commitment_id |
integer | yes | Reserve to reduce. |
transaction_id |
integer | yes | Existing personal expense. |
note |
string | — | Optional consumption evidence. |
requestId |
string | — | An id you choose for this call, such as a UUID, so it can be sent again safely: the same requestId with the same arguments within a day answers with the first answer, marked replayed, and nothing is made twice. Reused for a different call, it is refused with the code conflict. |
split_movement — Split personal and third-party money
Partition a movement without altering its amount. Signed allocation amounts must have its sign and add exactly to it. Personal parts may override category. Each custody part requires an owned same-currency custody/payable commitment and atomically records one matching entry. Refuses replacement while linked entries remain.
Needs statements:write; writes; answers with before and after.
| Parameter | Type | Required | What it is |
|---|---|---|---|
id |
integer | yes | Movement id. |
allocations |
object[] | yes | Signed parts which conserve the bank movement exactly. At most 100 items. |
allocations[].kind |
string | yes | Who the money belongs to. One of: personal, custody. |
allocations[].amount_minor |
integer | yes | Signed part in original minor units. |
allocations[].category |
string | — | Optional personal category override. |
allocations[].commitment_id |
integer | — | Required for custody; custody/payable only. |
allocations[].note |
string | — | Optional note for this part. |
requestId |
string | — | An id you choose for this call, such as a UUID, so it can be sent again safely: the same requestId with the same arguments within a day answers with the first answer, marked replayed, and nothing is made twice. Reused for a different call, it is refused with the code conflict. |
unsplit_movement — Make a movement whole again
Remove allocations only after every linked entry is explicitly reversed. The original movement and ledger amount never change.
Needs statements:write; writes; answers with before and after.
| Parameter | Type | Required | What it is |
|---|---|---|---|
id |
integer | yes | Movement id. |
ledgers — Your ledgers
Accounts with original currency, declared opening, as-of supported amount, outside-coverage count and recorded/supported/verified evidence status. No opening means supportedMinor is null. balanceCents is retained only as a legacy recorded subtotal, never a bank balance; use recordedMinor. Unknown currency stays unspecified and is never converted.
Needs statements:read; read-only.
| Parameter | Type | Required | What it is |
|---|---|---|---|
notebookId |
integer | — | Only what is filed in this notebook, as notebooks gives its id. Left out, all of it. |
as_of |
string | — | Inclusive balance date YYYY-MM-DD; defaults to today in the account timezone. |
add_ledger — Add a ledger
A new place money moves through. Declare currency explicitly; omitted currency stays unspecified. opening_minor is signed minor units immediately before the first movement on opening_on. Without opening_on only a recorded subtotal is known.
Needs statements:write; writes; answers with before and after, after being the new ledger.
| Parameter | Type | Required | What it is |
|---|---|---|---|
name |
string | yes | What it is called — "Nubank", "Visa". |
kind |
string | — | bank, card, cash or other. |
default_parser |
string | — | An export key like 'nubank:conta_corrente'. |
currency |
string | — | Original ISO 4217 currency, never inferred from user preferences. |
opening_minor |
integer | — | Signed opening in the currency’s minor units. |
opening_on |
string | — | First covered day YYYY-MM-DD; empty means no declared opening. |
notebookId |
integer | — | The notebook this belongs to, as notebooks gives its id — a subject somebody is working through, like a renovation. Only when they said so. A notebook whose modules list does not hold this refuses it. |
requestId |
string | — | An id you choose for this call, such as a UUID, so it can be sent again safely: the same requestId with the same arguments within a day answers with the first answer, marked replayed, and nothing is made twice. Reused for a different call, it is refused with the code conflict. |
change_ledger — Change a ledger
Rename a ledger, change its kind, its usual export or its notebook, archive it or bring it back, or move it in the order. Only id is needed: a field left out is untouched, and nothing is written unless all of it is valid. Archiving keeps every line in it and its totals.
Needs statements:write; writes; answers with before and after.
| Parameter | Type | Required | What it is |
|---|---|---|---|
id |
integer | yes | The ledger’s id, as ledgers gives it. |
name |
string | — | A new name. |
currency |
string | — | Original ISO 4217 currency. Changes require no movements, declared opening or statement checks. No conversion is performed. |
opening_minor |
integer | — | Signed opening in original minor units; does not alter movements. |
opening_on |
string | — | First covered day YYYY-MM-DD. Empty clears the opening coverage, preserving history. |
kind |
string | — | What sort of place it is. One of: bank, card, cash, other. |
default_parser |
string | — | The export key importing into it preselects, like 'nubank:conta_corrente'. An empty string clears it. |
notebookId |
integer | — | The notebook it belongs to, as notebooks gives its id. 0 takes it out of the one it is in. |
archived |
boolean | — | true puts it away with its lines kept; false brings it back. |
position |
integer | — | Its place in the order ledgers lists them, counting from 0. Past the end is the end. |
ifUpdatedAt |
string | — | Only change it if nothing has changed it since: the updatedAt a read or an earlier change answered with. If something has, nothing is written and the call is refused with the code conflict, the current updatedAt in its details. |
balance_checks — Statement balance observations
Statement closing balances, newest first, with computed amounts, observed-minus-computed differences and matched, different or unverified status. No opening means unverified, not discarded evidence.
Needs statements:read; read-only.
| Parameter | Type | Required | What it is |
|---|---|---|---|
ledger_id |
integer | yes | Ledger id. |
record_balance_check — Record a statement closing balance
Store observed signed minor units at an explicit date, once per ledger and date. Stores evidence even without an opening and never writes an adjustment. Delete an incorrect observation explicitly before replacing it.
Needs statements:write; writes; answers with before and after, after being the new balanceCheck.
| Parameter | Type | Required | What it is |
|---|---|---|---|
ledger_id |
integer | yes | Ledger id. |
as_of |
string | yes | Statement closing date YYYY-MM-DD, inclusive of all movements that day. |
observed_minor |
integer | yes | Statement closing amount in original minor units. |
note |
string | — | Optional evidence note, at most 1000 characters. |
requestId |
string | — | An id you choose for this call, such as a UUID, so it can be sent again safely: the same requestId with the same arguments within a day answers with the first answer, marked replayed, and nothing is made twice. Reused for a different call, it is refused with the code conflict. |
delete_balance_check — Delete an incorrect balance observation
Remove one statement observation explicitly. The opening and every movement remain untouched; ledger status is re-evaluated from remaining evidence.
Needs statements:write and destructive; deletes; answers with before and after.
| Parameter | Type | Required | What it is |
|---|---|---|---|
id |
integer | yes | Observation id from balance_checks. |
record_movement — Put a line in a ledger
One movement, for a plugin that reads a bank the parsers do not, or for a purchase the statement has not published yet. Amounts are signed minor units: negative left the account. Give external_id and re-sending the same movement adds nothing.
Needs statements:write; writes; answers with before and after.
| Parameter | Type | Required | What it is |
|---|---|---|---|
ledger_id |
integer | yes | Which ledger, as ledgers gives it. |
occurred_on |
string | yes | The day it moved, YYYY-MM-DD. |
amount_cents |
integer | yes | Signed minor units — negative when money left. |
description |
string | yes | What the bank would call it. The sorting rules read this. |
external_id |
string | — | The source's own id for it, if it has one. |
requestId |
string | — | An id you choose for this call, such as a UUID, so it can be sent again safely: the same requestId with the same arguments within a day answers with the first answer, marked replayed, and nothing is made twice. Reused for a different call, it is refused with the code conflict. |
change_movement — Correct a statement line
Correct a line in a ledger: what it says, the day, the amount, which ledger it is in, or what it meant. Takes the id movements gives. Only id is needed: a field left out is untouched. Amounts are signed minor units — negative when money left. kind says what the line was — expense, income, transfer, refund, fee or cash — and an empty string takes it back to the sign’s guess. A leg of a transfer cannot be re-kinded: unlink the transfer first.
Needs statements:write; writes; answers with before and after.
| Parameter | Type | Required | What it is |
|---|---|---|---|
id |
integer | yes | The line’s id, as movements gives it. |
description |
string | — | What it says. The sorting rules read this. |
occurred_on |
string | — | The day it moved, YYYY-MM-DD. |
amount_cents |
integer | — | Signed minor units — negative when money left. |
ledger_id |
integer | — | Move it to this ledger, as ledgers gives it. |
kind |
string | — | What the line was. An empty string clears it back to the sign’s guess. One of: ``, cash, expense, fee, income, refund, transfer. |
classify_movements — Say what several lines were
Give several statement lines the same meaning in one write — a hundred imported purchases marked as spending, a month of withdrawals marked as cash. kind is expense, income, transfer, refund, fee or cash; an empty string returns them to the sign’s guess. A leg of a transfer in the selection refuses the whole batch — unlink it first.
Needs statements:write; writes; answers with before and after.
| Parameter | Type | Required | What it is |
|---|---|---|---|
ids |
integer[] | yes | The lines’ ids, as movements gives them. |
kind |
string | yes | What they were. An empty string clears it. One of: ``, cash, expense, fee, income, refund, transfer. |
link_transfer — Link two lines as one transfer
Two lines in different ledgers are one move of my own money: both become transfer legs sharing a group. In one currency they must add up to nothing; in different currencies each keeps its own amount and no total is produced. Two lines in the same ledger are refused. Give one line and its counterpart — the answer names the group, and unlink_transfer undoes it.
Needs statements:write; writes; answers with before and after.
| Parameter | Type | Required | What it is |
|---|---|---|---|
id |
integer | yes | One line, as movements gives it. |
counterpart_id |
integer | yes | The other line, in another ledger. |
unlink_transfer — Unlink a transfer
Undo a transfer pairing: both legs go back to the sign’s guess and the group is cleared. A refund attached to a leg refuses the unlink until the refund is unlinked.
Needs statements:write; writes; answers with before and after.
| Parameter | Type | Required | What it is |
|---|---|---|---|
id |
integer | yes | Either leg, as movements gives it. |
link_movement — Attach a refund or a fee
A refund reverses one expense: it counts against that expense in the month it landed, under the expense’s category. A fee belongs to the payment it was charged on and leaves that payment untouched. relation is refund or fee; parent_id is the line it belongs to. Both must be in the same currency — the ledgers may differ. A line has one parent.
Needs statements:write; writes; answers with before and after.
| Parameter | Type | Required | What it is |
|---|---|---|---|
id |
integer | yes | The refund or fee line, as movements gives it. |
parent_id |
integer | yes | The expense a refund reverses, or the payment a fee belongs to. |
relation |
string | yes | What the line is to its parent. One of: refund, fee. |
remove_movement — Delete a statement line
Delete one line from a ledger — a movement recorded twice, or one that never happened. The answer carries the whole line, so it can be recorded again.
Needs statements:write and destructive; deletes; answers with before and after.
| Parameter | Type | Required | What it is |
|---|---|---|---|
id |
integer | yes | The line’s id, as movements gives it. |
statement_months — Money in and out, by month
What arrived and what left, month by month, across every ledger or one of them. Amounts are in minor units (cents), and out is written positive.
Needs statements:read; read-only.
| Parameter | Type | Required | What it is |
|---|---|---|---|
months |
integer | — | How many months back. 12 by default. |
month |
string | — | One civil month, YYYY-MM. |
from |
string | — | Inclusive first civil day, YYYY-MM-DD. |
to |
string | — | Inclusive last civil day, YYYY-MM-DD. |
currency |
string | — | One original ISO currency, or unspecified. Omit only for separate currency groups. |
ledger_id |
integer | — | Only this owned ledger. |
spending_by_category — Where the money went
Personal spending by category over a window: expenses and fees, net of refunds, with only the personal part of a split line, uncategorized included. Transfers, cash withdrawals and custody shares are left out, so the slices are the whole of personal spending rather than of every outgoing line. For cash flow by month use statement_months.
Needs statements:read; read-only.
| Parameter | Type | Required | What it is |
|---|---|---|---|
month |
string | — | One civil month, YYYY-MM. |
from |
string | — | Inclusive first civil day, YYYY-MM-DD. |
to |
string | — | Inclusive last civil day, YYYY-MM-DD. |
currency |
string | — | One original ISO currency, or unspecified. Omit only for separate currency groups. |
ledger_id |
integer | — | Only this owned ledger. |
change_sort_rule — Change a sorting rule
Rewrite a rule’s name, pattern or colour, or move it to another place in the order. Only id is needed: a field left out is untouched, and a pattern that does not compile is refused before anything is written. The change re-sorts every line at once, past ones included.
Needs statements:write; writes; answers with before and after.
| Parameter | Type | Required | What it is |
|---|---|---|---|
id |
integer | yes | The rule, as sort_rules lists it. |
name |
string | — | The name, rewritten. |
pattern |
string | — | A JavaScript regular expression, matched case-insensitively. |
color |
string | — | A hex colour like #1d4ed8. |
position |
integer | — | Its place among the rules of its kind, counting from 0, in the order sort_rules lists them — for categories, the first that matches wins. Past the end is the end. |
movements — Bank-statement lines
Imported statement lines, newest first, each with the category (at most one — they partition) and tags (any number) your sorting rules give it. Amounts in minor units, negative when money left.
Needs statements:read; read-only.
| Parameter | Type | Required | What it is |
|---|---|---|---|
month |
string | — | Only this month, as 'YYYY-MM'. Everything if left out. |
ledger_id |
integer | — | Only this ledger. |
add_sort_rule — Add a sorting rule
A regular expression that sorts statement lines, applied at read time — past lines included. Categories partition (first match, in position order, wins); tags overlap freely.
Needs statements:write; writes; answers with before and after, after being the new sortRule.
| Parameter | Type | Required | What it is |
|---|---|---|---|
kind |
string | yes | 'category' or 'tag'. |
name |
string | yes | What the category or tag is called. |
pattern |
string | yes | A JavaScript regular expression, matched case-insensitively. |
requestId |
string | — | An id you choose for this call, such as a UUID, so it can be sent again safely: the same requestId with the same arguments within a day answers with the first answer, marked replayed, and nothing is made twice. Reused for a different call, it is refused with the code conflict. |
delete_sort_rule — Delete a sorting rule
The rule goes; the lines it sorted stay, now sorted by the rules that remain.
Needs statements:write and destructive; deletes; answers with before and after.
| Parameter | Type | Required | What it is |
|---|---|---|---|
id |
integer | yes | The rule, as listed by sort_rules. |
sort_rules — The sorting rules
Every sorting rule — categories and tags, with their regular expressions — in the order categories win.
Needs statements:read; read-only.
Takes no parameters.
bills — Your bills
The bills you expect to pay, and what you have actually paid. Amounts are in minor units (cents): 12000 is R$120,00. Marking one paid records the real amount, which can differ from the expected one. An automatic bill pays itself (a subscription, a direct debit): it is never reminded, and its payment is recorded on each due day.
Needs bills:read; read-only.
| Parameter | Type | Required | What it is |
|---|---|---|---|
include_archived |
boolean | — | Include ones put away. |
flow |
string | — | Which direction: 'out' (bills, the default) or 'in' — income, recorded exactly the way bills are. |
notebookId |
integer | — | Only what is filed in this notebook, as notebooks gives its id. Left out, all of it. |
bill_payments — What a bill has cost
Every period a bill has been settled for, with the expected amount and what was actually paid. status is paid or skipped; a skipped period paid nothing. automatic marks a payment the app recorded for an automatic bill. Amounts in minor units (cents).
Needs bills:read; read-only.
| Parameter | Type | Required | What it is |
|---|---|---|---|
id |
integer | yes | The bill’s id. |
bill_history — A bill’s history and average
One bill’s whole history — every period paid or skipped, newest first — with how many were paid and skipped, the total paid, and the average paid per period (per week, month or year, following the bill’s rhythm; null before anything was paid). Amounts in minor units (cents).
Needs bills:read; read-only.
| Parameter | Type | Required | What it is |
|---|---|---|---|
id |
integer | yes | The bill’s id. |
month_bills — A month of bills at a glance
For a month (YYYY-MM), what the monthly bills expected, what has been paid, and the gap. Amounts in minor units (cents).
Needs bills:read; read-only.
| Parameter | Type | Required | What it is |
|---|---|---|---|
month |
string | — | The month as YYYY-MM. This month if left out. |
bills_due — Bills that want paying
The bills falling due between two dates, each on the day it wants paying (the due day less its lead), with whether that one is already paid. This is what the week shows. Automatic bills and skipped periods ask for nothing and are left out.
Needs bills:read; read-only.
| Parameter | Type | Required | What it is |
|---|---|---|---|
from |
string | yes | First day, as 2026-03-14. |
to |
string | yes | Last day, as 2026-03-21. |
add_bill — Add a bill
Write down a bill you expect to pay: a name, the expected amount in minor units (cents), and a rhythm (weekly, monthly, yearly, once). A monthly bill can name the day of the month it falls due.
Needs bills:write; writes; answers with before and after, after being the new bill.
| Parameter | Type | Required | What it is |
|---|---|---|---|
name |
string | yes | What the bill is called. |
amount_expected |
integer | — | The expected amount, in minor units (cents). |
rhythm |
string | — | weekly, monthly, yearly, or once. |
due_day |
integer | — | Day of the month it falls due, 1-28 (monthly) — the last day it can be paid. |
pay_lead_days |
integer | — | Pay it this many days before the due day (0 = on the day). It turns up on the week that day. |
automatic |
boolean | — | It pays itself — a subscription on a card, a direct debit. Never reminded and never on the week; its payment is recorded on each due day from today on. |
currency |
string | — | A currency code like BRL. The account’s default if left out. |
flow |
string | — | 'out' for a bill (the default), 'in' for income. |
notes |
string | — | Anything else. |
notebookId |
integer | — | The notebook this belongs to, as notebooks gives its id — a subject somebody is working through, like a renovation. Only when they said so. A notebook whose modules list does not hold this refuses it. |
requestId |
string | — | An id you choose for this call, such as a UUID, so it can be sent again safely: the same requestId with the same arguments within a day answers with the first answer, marked replayed, and nothing is made twice. Reused for a different call, it is refused with the code conflict. |
change_bill — Change a bill
Rewrite a bill — every field add_bill takes. Only id is needed: a field left out is untouched, and nothing is written unless all of it is valid. 0 or null clears due_day or due_month; an empty string clears the notes, and an empty currency goes back to the account’s default. Editing the amount or the currency does not rewrite what past payments recorded — those are snapshots of the day they were paid.
Needs bills:write; writes; answers with before and after.
| Parameter | Type | Required | What it is |
|---|---|---|---|
id |
integer | yes | The bill’s id, as bills gives it. |
name |
string | — | The name, rewritten. |
amount_expected |
integer | — | The expected amount, in minor units (cents). |
rhythm |
string | — | weekly, monthly, yearly, or once. |
due_day |
integer | — | When it falls due. Monthly: day of the month. Weekly: weekday 1-7 from Monday. Yearly: day of due_month. |
due_month |
integer | — | For a yearly bill, the month, 1-12. |
pay_lead_days |
integer | — | Pay it this many days before the due day (0 = on the day). |
automatic |
boolean | — | true when it pays itself, false when somebody pays it. Left alone if not given. |
currency |
string | — | A currency code like BRL. An empty string or null goes back to the account’s default. Payments already recorded keep the currency they were paid in. |
flow |
string | — | 'out' for a bill, 'in' for income. One of: out, in. |
notebookId |
integer | — | The notebook it belongs to, as notebooks gives its id; 0 takes it out of its notebook. |
notes |
string | — | Notes, replacing the old ones. |
ifUpdatedAt |
string | — | Only change it if nothing has changed it since: the updatedAt a read or an earlier change answered with. If something has, nothing is written and the call is refused with the code conflict, the current updatedAt in its details. |
archive_bill — Put a bill away, or bring it back
Take a bill out of the active list (it stopped being paid), or restore it. Its payment history stays either way.
Needs bills:write; writes; answers with before and after.
| Parameter | Type | Required | What it is |
|---|---|---|---|
id |
integer | yes | The bill’s id. |
archived |
boolean | — | true to put away, false to bring back. Defaults to true. |
pay_bill — Mark a bill paid
Record a bill paid for a period. The amount defaults to the expected one; give amount_paid in minor units (cents) when it differed. The period defaults to the current one for the bill’s rhythm. Paying the same period again corrects it, never doubles it.
Needs bills:write; writes; answers with before and after.
| Parameter | Type | Required | What it is |
|---|---|---|---|
id |
integer | yes | The bill’s id. |
amount_paid |
integer | — | What was actually paid, in minor units (cents). |
period |
string | — | The period: YYYY-Www for weekly, YYYY-MM for monthly, YYYY for yearly. This period if left out. |
notes |
string | — | Anything about this payment. |
change_bill_payment — Correct a bill payment
Correct the paid date and actual amount of an existing payment. Find payment_id with bill_payments. The period and expected amount stay as recorded. Amounts are in minor units (cents).
Needs bills:write; writes; answers with before and after.
| Parameter | Type | Required | What it is |
|---|---|---|---|
id |
integer | yes | The bill’s id. |
payment_id |
integer | yes | The payment’s id. |
paid_date |
string | yes | The local payment date, YYYY-MM-DD. |
amount_paid |
integer | yes | The actual amount paid, in minor units (cents). |
unpay_bill — Undo a bill payment
Remove the payment recorded for a period — it was not actually paid, or was recorded by mistake. The inverse of pay_bill.
Needs bills:write; writes; answers with before and after.
| Parameter | Type | Required | What it is |
|---|---|---|---|
id |
integer | yes | The bill’s id. |
period |
string | yes | The period to undo, e.g. 2026-09. |
skip_bill — Skip a bill for a period
Say nothing was owed for a period — the gym frozen for a month, a week with no cleaner. The period reads as settled without a payment, stops asking to be paid, and counts as skipped in the history. Refused on a period already paid: undo that with unpay_bill first. The period defaults to the current one.
Needs bills:write; writes; answers with before and after.
| Parameter | Type | Required | What it is |
|---|---|---|---|
id |
integer | yes | The bill’s id. |
period |
string | — | The period: YYYY-Www for weekly, YYYY-MM for monthly, YYYY for yearly. This period if left out. |
notes |
string | — | Why it was skipped. |
unskip_bill — Undo a skipped period
Take back a skip, so the period is open and asks to be paid again. The inverse of skip_bill.
Needs bills:write; writes; answers with before and after.
| Parameter | Type | Required | What it is |
|---|---|---|---|
id |
integer | yes | The bill’s id. |
period |
string | yes | The period to reopen, e.g. 2026-09. |