heybmoDocsOpen HeyBMO

API reference

Notes

Notes, folders, tags, files and search, including text inside pictures.

Base URL https://app.heybmo.comFor agents: llms.txt · OpenAPI

Operations

WritePOST /api/ops/notes.create

Create a note

Create a note: a title and a Markdown body, optionally in a folder, with tags and a colour.

MCP tool notes_createCLI heybmo notes createLimit writeInput
titlerequiredtextUp to 200 characters.
bodytextMarkdown, up to 100 KB. Default "".
folderIdidA folder id (from notes.folders).
tagslist of textLabels, e.g. ["work", "home"]. Stored lower-case. Up to 50 items.
pinnedtrue or falseKeep it at the top of lists.
colorlavender | sky | apricot | limeA colour that makes the note stand out on the board.
curl https://app.heybmo.com/api/ops/notes.create \
  -H "Authorization: Bearer $HEYBMO_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"input":{"title":"Groceries","body":"- milk\n- eggs","tags":["shopping"]}}'
200 response
{
  "output": {
    "id": "01a19279-e9c3-7c73-9705-94f082fa3a65",
    "title": "…",
    "folderId": "01a19279-e9c3-7c73-9705-94f082fa3a65",
    "tags": [
      "…"
    ],
    "pinned": false,
    "archived": false,
    "color": "lavender",
    "revision": 0,
    "createdAt": "2026-11-09T09:00:00.000Z",
    "updatedAt": "2026-11-09T09:00:00.000Z",
    "body": "…",
    "attachments": [
      {
        "id": "01a19279-e9c3-7c73-9705-94f082fa3a65",
        "name": "…",
        "contentType": "…",
        "size": 0,
        "status": "pending",
        "searchable": "pending",
        "url": "…"
      }
    ]
  }
}
ReadPOST /api/ops/notes.get

Read a note

Read one note in full: body (Markdown), tags, folder, revision, attachments (with short-lived links to view them).

MCP tool notes_getCLI heybmo notes getLimit readSafe to retryInput
noteIdrequiredidThe note id (from notes.list, notes.search or notes.create).
curl https://app.heybmo.com/api/ops/notes.get \
  -H "Authorization: Bearer $HEYBMO_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"input":{"noteId":"01a19279-eb99-775d-bebf-12c59f611dfb"}}'
200 response
{
  "output": {
    "id": "01a19279-e9c3-7c73-9705-94f082fa3a65",
    "title": "…",
    "folderId": "01a19279-e9c3-7c73-9705-94f082fa3a65",
    "tags": [
      "…"
    ],
    "pinned": false,
    "archived": false,
    "color": "lavender",
    "revision": 0,
    "createdAt": "2026-11-09T09:00:00.000Z",
    "updatedAt": "2026-11-09T09:00:00.000Z",
    "body": "…",
    "attachments": [
      {
        "id": "01a19279-e9c3-7c73-9705-94f082fa3a65",
        "name": "…",
        "contentType": "…",
        "size": 0,
        "status": "pending",
        "searchable": "pending",
        "url": "…"
      }
    ]
  }
}
ReadPOST /api/ops/notes.list

List notes

List notes, pinned first, then most recently changed (order changed: most recently changed first, pinned or not), with a short preview of each and how many match. Filter by folder, tag, pinned or archived. Archived notes are left out unless archived is true. Pass nextCursor back as cursor for the next page.

MCP tool notes_listCLI heybmo notes listLimit readSafe to retryInput
folderIdid or nullOnly notes in this folder; null for notes at the top level.
tagtextOnly notes with this tag. Up to 100 characters.
pinnedtrue or falseOnly pinned (true) or only unpinned (false) notes.
archivedtrue or falsetrue lists the archive instead. Default false.
orderpinnedFirst | changedpinnedFirst (default), or changed: most recently changed first. Default "pinnedFirst".
limitnumberDefault 30.
cursortextUp to 300 characters.
curl https://app.heybmo.com/api/ops/notes.list \
  -H "Authorization: Bearer $HEYBMO_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"input":{"tag":"shopping","limit":10}}'
200 response
{
  "output": {
    "notes": [
      {
        "id": "01a19279-e9c3-7c73-9705-94f082fa3a65",
        "title": "…",
        "excerpt": "…",
        "folderId": "01a19279-e9c3-7c73-9705-94f082fa3a65",
        "tags": [
          "…"
        ],
        "pinned": false,
        "archived": false,
        "color": "lavender",
        "revision": 0,
        "createdAt": "2026-11-09T09:00:00.000Z",
        "updatedAt": "2026-11-09T09:00:00.000Z",
        "attached": {
          "count": 0,
          "pictures": 0,
          "cover": {},
          "file": {}
        }
      }
    ],
    "total": 0,
    "nextCursor": "…"
  }
}
ReadPOST /api/ops/notes.search

Search notes

Search notes by words in their title, body and attachments (text in PDFs and in pictures, read automatically). Typos in titles are forgiven. Supports "exact phrases", -excluded words and OR. Best matches first.

MCP tool notes_searchCLI heybmo notes searchLimit readSafe to retryInput
queryrequiredtextUp to 200 characters.
folderIdid or nullOnly notes in this folder; null for notes at the top level.
tagtextOnly notes with this tag. Up to 100 characters.
includeArchivedtrue or falseDefault true.
limitnumberDefault 20.
curl https://app.heybmo.com/api/ops/notes.search \
  -H "Authorization: Bearer $HEYBMO_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"input":{"query":"electricity bill"}}'
200 response
{
  "output": {
    "results": [
      {
        "id": "01a19279-e9c3-7c73-9705-94f082fa3a65",
        "title": "…",
        "excerpt": "…",
        "folderId": "01a19279-e9c3-7c73-9705-94f082fa3a65",
        "tags": [
          "…"
        ],
        "pinned": false,
        "archived": false,
        "color": "lavender",
        "revision": 0,
        "createdAt": "2026-11-09T09:00:00.000Z",
        "updatedAt": "2026-11-09T09:00:00.000Z",
        "attached": {
          "count": 0,
          "pictures": 0,
          "cover": {},
          "file": {}
        },
        "foundIn": [
          "…"
        ]
      }
    ]
  }
}
WritePOST /api/ops/notes.update

Change a note

Change one or more fields of a note: title, whole body, folder (null for the top level), tags (replaces them), pinned, archived or colour (null for none). To add text or fix one passage, notes.append and notes.replaceText are safer than rewriting the body.

MCP tool notes_updateCLI heybmo notes updateLimit writeInput
noteIdrequiredidThe note id (from notes.list, notes.search or notes.create).
revisionnumberThe revision you last read. If the note changed since, the edit is refused so nothing is overwritten. Recommended for AI apps.
titletextUp to 200 characters.
bodytextThe whole new body (Markdown).
folderIdid or null
tagslist of textLabels, e.g. ["work", "home"]. Stored lower-case. Up to 50 items.
pinnedtrue or false
archivedtrue or falseArchived notes leave the normal list but stay searchable.
colorlavender | sky | apricot | lime or null
curl https://app.heybmo.com/api/ops/notes.update \
  -H "Authorization: Bearer $HEYBMO_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"input":{"noteId":"01a19279-eb99-775d-bebf-12c59f611dfb","title":"Groceries for Saturday","revision":3}}'
200 response
{
  "output": {
    "id": "01a19279-e9c3-7c73-9705-94f082fa3a65",
    "title": "…",
    "folderId": "01a19279-e9c3-7c73-9705-94f082fa3a65",
    "tags": [
      "…"
    ],
    "pinned": false,
    "archived": false,
    "color": "lavender",
    "revision": 0,
    "createdAt": "2026-11-09T09:00:00.000Z",
    "updatedAt": "2026-11-09T09:00:00.000Z",
    "body": "…",
    "attachments": [
      {
        "id": "01a19279-e9c3-7c73-9705-94f082fa3a65",
        "name": "…",
        "contentType": "…",
        "size": 0,
        "status": "pending",
        "searchable": "pending",
        "url": "…"
      }
    ]
  }
}
WritePOST /api/ops/notes.append

Add text to a note

Add text at the end of a note (on a new line). Safer than rewriting the whole body.

MCP tool notes_appendCLI heybmo notes appendLimit writeInput
noteIdrequiredidThe note id (from notes.list, notes.search or notes.create).
textrequiredtextMarkdown to add.
revisionnumberThe revision you last read. If the note changed since, the edit is refused so nothing is overwritten. Recommended for AI apps.
curl https://app.heybmo.com/api/ops/notes.append \
  -H "Authorization: Bearer $HEYBMO_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"input":{"noteId":"01a19279-eb99-775d-bebf-12c59f611dfb","text":"- oat milk"}}'
200 response
{
  "output": {
    "id": "01a19279-e9c3-7c73-9705-94f082fa3a65",
    "title": "…",
    "folderId": "01a19279-e9c3-7c73-9705-94f082fa3a65",
    "tags": [
      "…"
    ],
    "pinned": false,
    "archived": false,
    "color": "lavender",
    "revision": 0,
    "createdAt": "2026-11-09T09:00:00.000Z",
    "updatedAt": "2026-11-09T09:00:00.000Z",
    "body": "…",
    "attachments": [
      {
        "id": "01a19279-e9c3-7c73-9705-94f082fa3a65",
        "name": "…",
        "contentType": "…",
        "size": 0,
        "status": "pending",
        "searchable": "pending",
        "url": "…"
      }
    ]
  }
}
WritePOST /api/ops/notes.replaceText

Replace text in a note

Replace one exact passage of a note with new text (empty to remove it). The passage must appear exactly once: copy it from the note, with enough surrounding text to be unique.

MCP tool notes_replaceTextCLI heybmo notes replaceTextLimit writeInput
noteIdrequiredidThe note id (from notes.list, notes.search or notes.create).
findrequiredtextThe exact text to replace.
replacerequiredtextThe new text.
revisionnumberThe revision you last read. If the note changed since, the edit is refused so nothing is overwritten. Recommended for AI apps.
curl https://app.heybmo.com/api/ops/notes.replaceText \
  -H "Authorization: Bearer $HEYBMO_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"input":{"noteId":"01a19279-eb99-775d-bebf-12c59f611dfb","find":"- eggs","replace":"- 12 eggs"}}'
200 response
{
  "output": {
    "id": "01a19279-e9c3-7c73-9705-94f082fa3a65",
    "title": "…",
    "folderId": "01a19279-e9c3-7c73-9705-94f082fa3a65",
    "tags": [
      "…"
    ],
    "pinned": false,
    "archived": false,
    "color": "lavender",
    "revision": 0,
    "createdAt": "2026-11-09T09:00:00.000Z",
    "updatedAt": "2026-11-09T09:00:00.000Z",
    "body": "…",
    "attachments": [
      {
        "id": "01a19279-e9c3-7c73-9705-94f082fa3a65",
        "name": "…",
        "contentType": "…",
        "size": 0,
        "status": "pending",
        "searchable": "pending",
        "url": "…"
      }
    ]
  }
}
DeletePOST /api/ops/notes.delete

Move a note to the trash

Move a note to the trash. It can be restored with notes.restore for 30 days, then it is deleted for good with its attachments.

Goes to the trash: it can be restored for 30 days.

MCP tool notes_deleteCLI heybmo notes deleteLimit deleteSafe to retryInput
noteIdrequiredidThe note id (from notes.list, notes.search or notes.create).
revisionnumberThe revision you last read. If the note changed since, the edit is refused so nothing is overwritten. Recommended for AI apps.
curl https://app.heybmo.com/api/ops/notes.delete \
  -H "Authorization: Bearer $HEYBMO_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"input":{"noteId":"01a19279-eb99-775d-bebf-12c59f611dfb"}}'
200 response
{
  "output": {
    "id": "01a19279-e9c3-7c73-9705-94f082fa3a65",
    "deletedAt": "2026-11-09T09:00:00.000Z",
    "restoreUntil": "2026-11-09T09:00:00.000Z"
  }
}
WritePOST /api/ops/notes.restore

Restore a note from the trash

Bring a note back from the trash, with its attachments.

MCP tool notes_restoreCLI heybmo notes restoreLimit writeInput
noteIdrequiredidThe note id (from notes.list, notes.search or notes.create).
curl https://app.heybmo.com/api/ops/notes.restore \
  -H "Authorization: Bearer $HEYBMO_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"input":{"noteId":"01a19279-eb99-775d-bebf-12c59f611dfb"}}'
200 response
{
  "output": {
    "id": "01a19279-e9c3-7c73-9705-94f082fa3a65",
    "title": "…",
    "folderId": "01a19279-e9c3-7c73-9705-94f082fa3a65",
    "tags": [
      "…"
    ],
    "pinned": false,
    "archived": false,
    "color": "lavender",
    "revision": 0,
    "createdAt": "2026-11-09T09:00:00.000Z",
    "updatedAt": "2026-11-09T09:00:00.000Z",
    "body": "…",
    "attachments": [
      {
        "id": "01a19279-e9c3-7c73-9705-94f082fa3a65",
        "name": "…",
        "contentType": "…",
        "size": 0,
        "status": "pending",
        "searchable": "pending",
        "url": "…"
      }
    ]
  }
}
ReadPOST /api/ops/notes.trash

List notes in the trash

List notes in the trash (most recently deleted first), until when each can be restored, and how many are in it in all. Pass nextCursor back as cursor for the next page.

MCP tool notes_trashCLI heybmo notes trashLimit readSafe to retryInput
limitnumberDefault 50.
cursortextnextCursor from the previous page.
curl https://app.heybmo.com/api/ops/notes.trash \
  -H "Authorization: Bearer $HEYBMO_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"input":{"limit":20}}'
200 response
{
  "output": {
    "notes": [
      {
        "id": "01a19279-e9c3-7c73-9705-94f082fa3a65",
        "title": "…",
        "deletedAt": "2026-11-09T09:00:00.000Z",
        "restoreUntil": "2026-11-09T09:00:00.000Z"
      }
    ],
    "total": 0,
    "nextCursor": "…"
  }
}
DeletePOST /api/ops/notes.deleteForever

Delete notes in the trash for good

Delete notes that are in the trash for good, with their pictures and files: the ones named (noteIds), or the whole trash (all: true). It cannot be undone, so ask the person first. Notes not in the trash are refused: notes.delete moves a note 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 notes_deleteForeverCLI heybmo notes deleteForeverLimit deleteSafe to retryInput
noteIdslist of idNotes in the trash to delete for good (from notes.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.
curl https://app.heybmo.com/api/ops/notes.deleteForever \
  -H "Authorization: Bearer $HEYBMO_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"input":{"noteIds":["01a19279-e9c3-7c73-9705-94f082fa3a65"]}}'
200 response
{
  "output": {
    "notes": 0,
    "files": 0
  }
}
WritePOST /api/ops/notes.attach

Attach a file to a note

Attach a picture or file (PDF, document, audio...) to a note. 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 notes.finishAttach. Show a picture in the body with ![caption](attachment:<id>) on a line of its own. To set how it shows, add a title: ![caption](attachment:<id> "width=50 align=center crop=0.1,0.1,0.8,0.8"): width is a percent of the text width (10 to 100; left out, the picture keeps its own size), align is left, center or right, and crop is the part kept as x,y,width,height fractions of the picture. Text in pictures and PDFs becomes searchable.

MCP tool notes_attachCLI heybmo notes attachLimit uploadInput
noteIdrequiredidThe note id (from notes.list, notes.search or notes.create).
namerequiredtextFile name, e.g. receipt.jpg. Up to 255 characters.
contentTyperequiredtexte.g. image/jpeg or application/pdf. Up to 200 characters.
datatextThe whole file as base64 (up to 5 MB): stored in one step. Up to 6990508 characters.
sizenumberBytes, when uploading with the link instead.
sha256textHex SHA-256 of the bytes, when uploading.
curl https://app.heybmo.com/api/ops/notes.attach \
  -H "Authorization: Bearer $HEYBMO_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"input":{"noteId":"01a19279-eb99-775d-bebf-12c59f611dfb","name":"receipt.jpg","contentType":"image/jpeg","data":"/9j/4AAQSkZJRg=="}}'
200 response
{
  "output": {
    "attachment": {
      "id": "01a19279-e9c3-7c73-9705-94f082fa3a65",
      "name": "…",
      "contentType": "…",
      "size": 0,
      "status": "pending",
      "searchable": "pending",
      "url": "…"
    },
    "upload": {
      "url": "…",
      "method": "PUT",
      "headers": {},
      "expiresAt": "2026-11-09T09:00:00.000Z"
    },
    "finish": {
      "operation": "…",
      "input": {}
    }
  }
}
WritePOST /api/ops/notes.finishAttach

Finish attaching a file

Confirm an attachment after its bytes were uploaded with the link from notes.attach.

MCP tool notes_finishAttachCLI heybmo notes finishAttachLimit writeSafe to retryInput
noteIdrequiredidThe note id (from notes.list, notes.search or notes.create).
attachmentIdrequiredidThe attachment id (from notes.get or notes.attach).
curl https://app.heybmo.com/api/ops/notes.finishAttach \
  -H "Authorization: Bearer $HEYBMO_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"input":{"noteId":"01a19279-eb99-775d-bebf-12c59f611dfb","attachmentId":"01a1927a-1071-7a71-994f-4180839c9a39"}}'
200 response
{
  "output": {
    "attachment": {
      "id": "01a19279-e9c3-7c73-9705-94f082fa3a65",
      "name": "…",
      "contentType": "…",
      "size": 0,
      "status": "pending",
      "searchable": "pending",
      "url": "…"
    }
  }
}
DeletePOST /api/ops/notes.detach

Delete an attachment

Remove an attachment from a note and delete the file. This cannot be undone. Remove any ![...](attachment:<id>) from the body too.

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 notes_detachCLI heybmo notes detachLimit deleteSafe to retryInput
noteIdrequiredidThe note id (from notes.list, notes.search or notes.create).
attachmentIdrequiredidThe attachment id (from notes.get or notes.attach).
confirmtrue or falseSet to true once the person agreed. Without it nothing is deleted and you get a description of what would be.
curl https://app.heybmo.com/api/ops/notes.detach \
  -H "Authorization: Bearer $HEYBMO_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"input":{"noteId":"01a19279-eb99-775d-bebf-12c59f611dfb","attachmentId":"01a1927a-1071-7a71-994f-4180839c9a39"}}'
200 response
{
  "output": {
    "id": "01a19279-e9c3-7c73-9705-94f082fa3a65",
    "deleted": false
  }
}
ReadPOST /api/ops/notes.folders

List note folders

List all note folders (a tree: each has its parentId, null at the top level) with how many notes are directly in each.

MCP tool notes_foldersCLI heybmo notes foldersLimit readSafe to retryInput

No input: send an empty object.

curl https://app.heybmo.com/api/ops/notes.folders \
  -H "Authorization: Bearer $HEYBMO_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"input":{}}'
200 response
{
  "output": {
    "folders": [
      {
        "id": "01a19279-e9c3-7c73-9705-94f082fa3a65",
        "name": "…",
        "parentId": "01a19279-e9c3-7c73-9705-94f082fa3a65",
        "notes": 0
      }
    ]
  }
}
WritePOST /api/ops/notes.createFolder

Create a folder

Create a folder for notes, at the top level or inside another folder (5 levels at most).

MCP tool notes_createFolderCLI heybmo notes createFolderLimit writeInput
namerequiredtextUp to 100 characters.
parentIdidPut it inside this folder.
curl https://app.heybmo.com/api/ops/notes.createFolder \
  -H "Authorization: Bearer $HEYBMO_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"input":{"name":"Garden"}}'
200 response
{
  "output": {
    "id": "01a19279-e9c3-7c73-9705-94f082fa3a65",
    "name": "…",
    "parentId": "01a19279-e9c3-7c73-9705-94f082fa3a65",
    "notes": 0
  }
}
WritePOST /api/ops/notes.updateFolder

Rename or move a folder

Rename a folder or move it into another folder (parentId null moves it to the top level). Its notes and subfolders move with it.

MCP tool notes_updateFolderCLI heybmo notes updateFolderLimit writeSafe to retryInput
folderIdrequiredidA folder id (from notes.folders).
nametextUp to 100 characters.
parentIdid or null
curl https://app.heybmo.com/api/ops/notes.updateFolder \
  -H "Authorization: Bearer $HEYBMO_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"input":{"folderId":"01a19279-e9c3-7c73-9705-94f082fa3a65","name":"Cooking"}}'
200 response
{
  "output": {
    "id": "01a19279-e9c3-7c73-9705-94f082fa3a65",
    "name": "…",
    "parentId": "01a19279-e9c3-7c73-9705-94f082fa3a65",
    "notes": 0
  }
}
DeletePOST /api/ops/notes.deleteFolder

Delete a folder

Delete a folder. It must be empty, unless moveContentsUp is true: then its notes and subfolders move to the folder above (or the top level). Notes are never deleted by this.

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 notes_deleteFolderCLI heybmo notes deleteFolderLimit deleteSafe to retryInput
folderIdrequiredidA folder id (from notes.folders).
moveContentsUptrue or falseMove what is inside to the parent folder instead of refusing. Default false.
confirmtrue or falseSet to true once the person agreed. Without it nothing is deleted and you get a description of what would be.
curl https://app.heybmo.com/api/ops/notes.deleteFolder \
  -H "Authorization: Bearer $HEYBMO_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"input":{"folderId":"01a19279-e9c3-7c73-9705-94f082fa3a65"}}'
200 response
{
  "output": {
    "id": "01a19279-e9c3-7c73-9705-94f082fa3a65",
    "movedNotes": 0,
    "movedFolders": 0
  }
}
ReadPOST /api/ops/notes.tags

List tags

List every tag used on notes (not counting the trash), most used first.

MCP tool notes_tagsCLI heybmo notes tagsLimit readSafe to retryInput

No input: send an empty object.

curl https://app.heybmo.com/api/ops/notes.tags \
  -H "Authorization: Bearer $HEYBMO_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"input":{}}'
200 response
{
  "output": {
    "tags": [
      {
        "tag": "…",
        "notes": 0
      }
    ]
  }
}
WritePOST /api/ops/notes.renameTag

Rename a tag everywhere

Rename a tag on every note that has it (merging into the new tag if a note already has both).

MCP tool notes_renameTagCLI heybmo notes renameTagLimit writeSafe to retryInput
fromrequiredtextUp to 100 characters.
torequiredtextUp to 100 characters.
curl https://app.heybmo.com/api/ops/notes.renameTag \
  -H "Authorization: Bearer $HEYBMO_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"input":{"from":"job","to":"work"}}'
200 response
{
  "output": {
    "notesChanged": 0
  }
}
DeletePOST /api/ops/notes.removeTag

Remove a tag everywhere

Remove a tag from every note that has it. The notes themselves stay.

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 notes_removeTagCLI heybmo notes removeTagLimit deleteSafe to retryInput
tagrequiredtextUp to 100 characters.
confirmtrue or falseSet to true once the person agreed. Without it nothing is deleted and you get a description of what would be.
curl https://app.heybmo.com/api/ops/notes.removeTag \
  -H "Authorization: Bearer $HEYBMO_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"input":{"tag":"old"}}'
200 response
{
  "output": {
    "notesChanged": 0
  }
}