Spending and income, categories, budgets, recurring bills and receipts.
Base URL https://app.heybmo.comFor agents: llms.txt · OpenAPI
Operations
WritePOST /api/ops/expenses.add
Log spending or income
Log up to 100 amounts spent or received in one call (log several at once rather than one call each). Each has an amount, a currency (default: the home currency), a day (default: today), a category by name (default: Other), an optional merchant and note, and a receipt (receiptId) to put on it. Amounts in another currency are converted with that day’s stored rate, or the bank’s rate when given. If the person has no home currency yet, the first currency given becomes it; say so.
entriesrequiredlist of objectUp to 100 items.Each item:
amountrequirednumberHow much, in the currency’s normal units (45.5 means 45.50), always positive.
currencytextA three-letter currency code (ISO 4217), e.g. MAD, USD, EUR, GBP. A currency named without its country is the home currency when the names match; otherwise ask which one.
daydateA day, as YYYY-MM-DD.
kindspending | incomespending (money out, the default) or income (money in). Default "spending".
categorytextA category name (expenses.categories). Up to 60 characters.
merchanttextDefault "". Up to 120 characters.
notetextDefault "". Up to 500 characters.
ratenumberThe rate the bank used: units of the home currency per one unit of this currency. Without it, the stored rate of that day is used.
receiptIdidA receipt (expenses.attachReceipt) to put on it.
addMissingCategoriestrue or falseMake categories that do not exist yet instead of refusing them. Default false.
Change up to 100 entries: amount, currency, day, kind, category, merchant, note, the bank’s rate (null goes back to the day’s stored rate), or add a receipt (receiptId). Only what is given changes.
entriesrequiredlist of objectUp to 100 items.Each item:
entryIdrequiredidAn entry id (from expenses.entries or expenses.add).
revisionnumberThe revision you last read. If it changed since, the change is refused so nothing is overwritten.
amountnumberHow much, in the currency’s normal units (45.5 means 45.50), always positive.
currencytextA three-letter currency code (ISO 4217), e.g. MAD, USD, EUR, GBP. A currency named without its country is the home currency when the names match; otherwise ask which one.
daydateA day, as YYYY-MM-DD.
kindspending | incomespending (money out, the default) or income (money in).
categorytextUp to 60 characters.
merchanttextUp to 120 characters.
notetextUp to 500 characters.
ratenumber or null
receiptIdidA receipt (expenses.attachReceipt) to add to it.
addMissingCategoriestrue or falseMake categories that do not exist yet instead of refusing them. Default false.
Move every entry that matches the filters of expenses.entries (matching) to one category, however many there are. The matching entries must all be spending or all income: add kind to matching when unsure. For a few entries named by id, expenses.update works too.
MCP tool expenses_moveToCategoryCLI heybmo expenses moveToCategoryLimit writeSafe to retryInput
matchingrequiredobjectThe filters of expenses.entries.
categoryrequiredtextThe category to move them to (a name). Up to 60 characters.
addMissingCategoriestrue or falseMake the category when it does not exist yet instead of refusing. Default false.
Entries spent or received, newest day first (or by amount, category or merchant), filtered by days, kind, categories, receipt, currency or words in the merchant and note. total is how many match across every page. For sums use expenses.totals instead of adding up pages.
MCP tool expenses_entriesCLI heybmo expenses entriesLimit readSafe to retryInput
fromdateFirst day, included.
todateLast day, included.
kindspending | incomeOnly spending or only income (default: both).
categorytextOnly this category (a name). Up to 60 characters.
categorieslist of textOnly entries in any of these categories (names). Up to 100 items.
hasReceipttrue or falsetrue: only entries with a receipt; false: only entries without one.
currencytextOnly entries in this currency.
querytextWords in the merchant or note. Up to 200 characters.
checkAmounttrue or falseOnly entries marked to check (true).
sortday | amount | category | whereday, amount (in the home currency), category (its name) or where (merchant). Default "day".
directionasc | descDefault: newest and largest first, names from A.
Totals of spending and income in the home currency, for any days, grouped by category, month or day (or one total), with the same filters as expenses.entries. One call answers “how much did I spend on food in October”; never add up pages of entries instead. With limit, only the largest groups (e.g. the top 3 categories), and groupCount says how many there are.
MCP tool expenses_totalsCLI heybmo expenses totalsLimit readSafe to retryInput
fromdateFirst day, included.
todateLast day, included.
kindspending | incomeOnly spending or only income (default: both).
categorytextOnly this category (a name). Up to 60 characters.
categorieslist of textOnly entries in any of these categories (names). Up to 100 items.
hasReceipttrue or falsetrue: only entries with a receipt; false: only entries without one.
currencytextOnly entries in this currency.
querytextWords in the merchant or note. Up to 200 characters.
checkAmounttrue or falseOnly entries marked to check (true).
groupBycategory | month | day | noneDefault "category".
limitnumberOnly this many groups, the largest spending first (then income); groupCount says how many there are. Without it: every group, in key order.
The categories entries can have, spending ones and income ones. A space starts with Food, Transport, Home, Bills, Health, Fun, Shopping and Other, plus Salary and Other income.
MCP tool expenses_categoriesCLI heybmo expenses categoriesLimit readSafe to retryInput
Rename a category (its entries follow) or archive it: an archived category is no longer offered, but its entries keep it. archived: false brings it back.
MCP tool expenses_updateCategoryCLI heybmo expenses updateCategoryLimit writeSafe to retryInput
categoryIdrequiredidA category id (from expenses.categories).
Each monthly budget with what was spent that month (default: this month), what is left and the share used, in the home currency. The budget for all spending comes first, then the most used (over budget first), then by category; limit keeps the first few, and total says how many there are.
MCP tool expenses_budgetsCLI heybmo expenses budgetsLimit readSafe to retryInput
monthtextA month, as YYYY-MM.
limitnumberHow many budgets to answer, the most relevant first. Default 50.
Set the monthly budget for a spending category, or for all spending when no category is given, in the home currency. Setting it again changes the amount. alertAt is the heads-up share in percent (1 to 100, 80 by default, null for none): the person gets a heads-up in their inbox there and again at 100% (built in, nothing else to set up), and expenses.budgetReached fires at the same moments for automations.
MCP tool expenses_setBudgetCLI heybmo expenses setBudgetLimit writeSafe to retryInput
categorytextA spending category name; none means all. Up to 60 characters.
amountrequirednumberHow much, in the currency’s normal units (45.5 means 45.50), always positive.
alertAtnumber or nullHeads-up share in percent; null for none. Left as it was when not given (80 for a new budget).
Remove a monthly budget for good (entries are not touched). Ask the person first.
Deletes for good. The first call changes nothing and answers CONFIRMATION_REQUIRED with what would be deleted; call again with confirm: true once the person agrees.
MCP tool expenses_removeBudgetCLI heybmo expenses removeBudgetLimit deleteSafe to retryInput
budgetIdrequiredidA budget id (from expenses.budgets).
confirmtrue or falseSet to true once the person agreed. Without it nothing is deleted and you get a description of what would be.
Move entries to the trash: the ones named (entryIds), or every entry that matches the filters of expenses.entries (matching), however many. They no longer count in totals or budgets, and can be restored with expenses.restore for 30 days (everything one call moved at once, with its deletedAt), then they are deleted for good.
Goes to the trash: it can be restored for 30 days.
MCP tool expenses_deleteCLI heybmo expenses deleteLimit deleteSafe to retryInput
entryIdslist of idUp to 100 items.
matchingobjectEvery live entry that matches these filters (as in expenses.entries).
Bring entries back from the trash: the ones named (entryIds), or everything one expenses.delete call moved there (its deletedAt). They count in totals and budgets again.
MCP tool expenses_restoreCLI heybmo expenses restoreLimit writeSafe to retryInput
entryIdslist of idUp to 100 items.
deletedAtdate and timeThe deletedAt of an expenses.delete answer: brings back all it moved.
Entries in the trash, most recently deleted first, with until when each can be restored. total is how many the trash holds; nextCursor reads the next page.
MCP tool expenses_trashCLI heybmo expenses trashLimit readSafe to retryInput
Delete entries that are in the trash for good, with their receipts: the ones named (entryIds), or the whole trash (all: true), however big. It cannot be undone, so ask the person first. Entries not in the trash are refused: expenses.delete moves an entry there.
Deletes for good. The first call changes nothing and answers CONFIRMATION_REQUIRED with what would be deleted; call again with confirm: true once the person agrees.
MCP tool expenses_deleteForeverCLI heybmo expenses deleteForeverLimit deleteSafe to retryInput
entryIdslist of idEntries in the trash to delete for good (from expenses.trash). Up to 100 items.
alltrue or falsetrue: empty the whole trash instead.
confirmtrue or falseSet to true once the person agreed. Without it nothing is deleted and you get a description of what would be.
Store a photo or PDF of a receipt, on an entry or on its own. To log a receipt: attach it without entryId, read it with expenses.readReceipt, then log it with expenses.add and its receiptId (a receipt never logged is deleted after 7 days). Chat apps send small files (up to 5 MB) inline as base64 in data. Otherwise give size and sha256 (the CLI fills them from --file <path>): the answer has an upload link to PUT the bytes to, then call expenses.finishReceipt.
The text read out of a receipt (words in the photo, or the PDF text), plain guesses of its total, day, currency and shop, and a short link to view it. Text is read a few seconds after upload; until then the answer says so. Check the guesses against the text before logging.
MCP tool expenses_readReceiptCLI heybmo expenses readReceiptLimit readSafe to retryInput
receiptIdrequiredidA receipt id (from expenses.attachReceipt or an entry).
Delete a receipt file for good. The entry it was on stays. This cannot be undone.
Deletes for good. The first call changes nothing and answers CONFIRMATION_REQUIRED with what would be deleted; call again with confirm: true once the person agrees.
MCP tool expenses_removeReceiptCLI heybmo expenses removeReceiptLimit deleteSafe to retryInput
receiptIdrequiredidA receipt id (from expenses.attachReceipt or an entry).
confirmtrue or falseSet to true once the person agreed. Without it nothing is deleted and you get a description of what would be.
A bill or income that comes back (rent on the 1st, salary on the 25th, a weekly class). From the next matching day on, its entry is written by itself each time, in the morning of the person’s time zone. For a bill whose amount changes (electricity), set variable: each entry repeats the last amount and is flagged checkAmount so the person can correct it.
noterequiredtextWhat it is, e.g. Rent (written as each entry’s note). Up to 500 characters.
amountrequirednumberHow much, in the currency’s normal units (45.5 means 45.50), always positive.
currencytextA three-letter currency code (ISO 4217), e.g. MAD, USD, EUR, GBP. A currency named without its country is the home currency when the names match; otherwise ask which one.
kindspending | incomespending (money out, the default) or income (money in). Default "spending".
categorytextA category name (default: Other). Up to 60 characters.
merchanttextDefault "". Up to 120 characters.
variabletrue or falseThe amount changes each time. Default false.
repeatweekly | monthly | yearlyweekly, monthly or yearly. Default "monthly".
everynumberEvery N weeks, months or years (default 1). Default 1.
dayOfMonthnumber or "last"Monthly: the day of the month, or last (29-31 fall on the last day of shorter months); default: the day of starts.
weekdaynumberWeekly: 1 = Monday ... 7 = Sunday; default: the weekday of starts.
startsdateThe first day it can happen (default: today).
untildate or nullThe last day it can happen (null: no end).
addMissingCategoriestrue or falseMake the category if it does not exist yet instead of refusing it. Default false.
Change a recurring bill or income: its amount, currency, category, merchant, note, whether the amount varies, how often it comes back, or pause it (paused: true, false to resume). skipDay skips one day only (its nextDay from expenses.recurring, to skip the next one; null cancels). Entries already written stay as they are. Only what is given changes.
recurringIdrequiredidA recurring bill or income id (from expenses.recurring).
revisionnumberThe revision you last read. If it changed since, the change is refused so nothing is overwritten.
notetextUp to 500 characters.
amountnumberHow much, in the currency’s normal units (45.5 means 45.50), always positive.
currencytextA three-letter currency code (ISO 4217), e.g. MAD, USD, EUR, GBP. A currency named without its country is the home currency when the names match; otherwise ask which one.
categorytextUp to 60 characters.
merchanttextUp to 120 characters.
variabletrue or false
pausedtrue or falseStop writing entries (false: start again).
skipDaydate or nullOne day to skip; null cancels it.
repeatweekly | monthly | yearlyweekly, monthly or yearly.
everynumberEvery N weeks, months or years (default 1).
dayOfMonthnumber or "last" or null
weekdaynumber or null
startsdateThe first day it can happen (default: today).
untildate or nullThe last day it can happen (null: no end).
Stop a recurring bill or income for good (to stop it for a while, pause it with expenses.updateRecurring). The entries it already wrote stay. Ask the person first.
Deletes for good. The first call changes nothing and answers CONFIRMATION_REQUIRED with what would be deleted; call again with confirm: true once the person agrees.
MCP tool expenses_removeRecurringCLI heybmo expenses removeRecurringLimit deleteSafe to retryInput
recurringIdrequiredidA recurring bill or income id (from expenses.recurring).
confirmtrue or falseSet to true once the person agreed. Without it nothing is deleted and you get a description of what would be.