# MeshBay HTTP API > **Generated** by `docs/generate_http_api.py` from the routes themselves. Do not > edit this file: change the route's docstring and run the script again. A test > fails when the two disagree. MeshBay has two HTTP APIs: the **hub's**, for accounts, groups and signaling, and the **node's control API**, which only its own machine reaches. Files, the index and chat do not use either: they travel between a client and a node over MNP (`MESHBAY_NODE_PROTOCOL.md`). Why each API is shaped as it is, who may call what and what the hub must never see are in `MESHBAY_DESIGN.md`; this file lists what exists. `examples/` has small Python programs that use both. ## Hub Under the hub's address, `https://meshbay.org` on the reference deployment. The hub also serves the web application at `/` and `/app/`, which are not listed. | Auth | What the request carries | |---|---| | none | No session. Any credential is in the request itself, as the route says | | user | `Authorization: Bearer`, a person's session. A node's token is refused | | user or node | A person's session, or a node daemon's token from `/v1/nodes/auth` | | node | A node daemon's token only | | moderator | A person's session, for an account with the moderator or admin role | | admin | A person's session, for an account with the admin role | | peer hub | Another hub's MHP token. Every route answers 503 unless federation is enabled | ### Instance | Method | Path | Auth | What | |---|---|---|---| | GET | `/v1/hub/info` | none | Versions and the instance policy a client needs before signing in. | | GET | `/v1/hub/pubkey` | none | Hub Ed25519 public key PEM — cached by nodes on first contact. | | GET | `/v1/hub/version` | none | Version check endpoint for clients to detect updates. | ### Accounts | Method | Path | Auth | What | |---|---|---|---| | POST | `/v1/users/register` | none | Create an account. | | POST | `/v1/users/verify-email` | none | Verify a registration email with the code received by mail. | | POST | `/v1/users/me/bundle-pepper` | user | The pepper, for a session that has just been given the passphrase again. | | POST | `/v1/users/login` | none | Sign in with the auth key derived from the passphrase. | | POST | `/v1/users/devices` | user | Register a device's hub authentication key. | | GET | `/v1/users/devices` | user or node | The account's registered devices. | | DELETE | `/v1/users/devices/{device_id}` | user | Retire a device's hub key. | | POST | `/v1/users/auth` | none | Sign in with a registered device key. | | POST | `/v1/users/token/refresh` | none | Exchange a refresh token for a new session. | | GET | `/v1/users/me` | user or node | The signed-in account: id, name, e-mail, role, status. | | PATCH | `/v1/users/me` | user | Update the signed-in account. | | POST | `/v1/users/verify-email-change` | user | Confirm an email change with the code sent to the new address. | | POST | `/v1/users/logout` | none | End this session on the hub, not only in the browser. | | POST | `/v1/users/me/sessions/revoke` | user | Sign out everywhere: no refresh token of this account renews any more. | | POST | `/v1/users/password` | user | Change the passphrase, proving the current one. | | POST | `/v1/users/password/reset-request` | none | Send a reset code by e-mail, when the username and the address match. | | POST | `/v1/users/password/reset` | none | Set a new passphrase with the code received by e-mail. | | GET | `/v1/users/me/preferences` | user or node | The account's stored interface preferences. | | PUT | `/v1/users/me/preferences/{key:path}` | user | Store one interface preference. | | DELETE | `/v1/users/me/preferences/{key:path}` | user | Remove one interface preference. | | PUT | `/v1/users/me/node_key` | user | Link a node daemon's Ed25519 public key to the operator's account. | | DELETE | `/v1/users/me/node_key` | user or node | Remove the linked node key from the operator's account. | | DELETE | `/v1/users/me` | user | Erase your own account. | | GET | `/v1/users/{username}/pubkeys` | user or node | Resolve a username to its account id, and its node's linking key. | ### Nodes | Method | Path | Auth | What | |---|---|---|---| | POST | `/v1/nodes/mnp-token` | user | Mint the short-lived token a member presents to a node in the MNP handshake. | | POST | `/v1/nodes/auth` | none | Authenticate a node daemon via Ed25519 challenge-response. | | POST | `/v1/nodes/announce` | user or node | Register a node record. | | GET | `/v1/nodes/{node_id}` | user or node | A node's public record: owner, key, endpoint hint. | ### Groups | Method | Path | Auth | What | |---|---|---|---| | GET | `/v1/groups/mine` | user or node | List groups the current user belongs to. | | GET | `/v1/groups/invitations` | user or node | Groups somebody added this account to, waiting for it to say yes. | | POST | `/v1/groups/{group_id}/invitation/accept` | user | Accept an invitation: the account becomes a member of the group. | | POST | `/v1/groups/{group_id}/invitation/decline` | user | Decline an invitation to a group. | | POST | `/v1/groups/{group_id}/activity` | user or node | Bump a group's last_activity_at. | | GET | `/v1/groups/{group_id}/nodes` | user or node | Return online nodes that serve a group (for WebRTC connection). | | GET | `/v1/groups` | none | List/search public groups — local and optionally federated. | | GET | `/v1/groups/{group_id}/members` | user or node | A group's members, for its members only. | | POST | `/v1/groups/{group_id}/join` | user | Join an open group. | | POST | `/v1/groups` | user | Create a group, owned by the caller. | | DELETE | `/v1/groups/{group_id}/members/{username}` | user | Remove someone from a group. | | POST | `/v1/groups/{group_id}/leave` | user | Leave a group you are a member of. | | PATCH | `/v1/groups/{group_id}` | user | Change the group's description. | | POST | `/v1/groups/{group_id}/members/{username}` | user or node | Add an account to a group the caller owns. | | POST | `/v1/groups/{group_id}/mute` | user | Turn this group's notifications on or off, for this account. | | DELETE | `/v1/groups/{group_id}` | user | Delete a group. | | POST | `/v1/groups/{group_id}/invite-notify` | user | Send an invitation email to a member who was just invited. | | GET | `/v1/groups/{group_id}/hosts` | user | The nodes that host a group or asked to, for its owner. | | POST | `/v1/groups/{group_id}/hosts/{node_id}` | user | Approve a node that asked to host this group. | | DELETE | `/v1/groups/{group_id}/hosts/{node_id}` | user | Withdraw an approval, or turn a request down. | ### Invitation links | Method | Path | Auth | What | |---|---|---|---| | POST | `/v1/groups/{group_id}/invite-links` | user or node | Mint the ticket for a link whose node half already exists. | | GET | `/v1/groups/{group_id}/invite-links` | user or node | The owner's view: the links nobody has used yet, masked. | | DELETE | `/v1/groups/{group_id}/invite-links/{link_id}` | user or node | Take the ticket back. | | POST | `/v1/invite-links/preview` | user | What the confirmation screen shows before anyone joins anything. | | POST | `/v1/invite-links/redeem` | user | Membership for the first account that asks, once — and the same answer again for that account, because a second tab or a reload is the same person. | ### Revocation and the node socket | Method | Path | Auth | What | |---|---|---|---| | WS | `/v1/nodes/ws` | none | Persistent WebSocket connection for nodes, authenticated by the node's token in the first message. | | POST | `/v1/nodes/{node_id}/incoming` | user or node | Signal a node that a client wants to connect (NAT punch coordination). | | POST | `/v1/admin/revoke` | admin | Revoke a user or group. | ### Moderation | Method | Path | Auth | What | |---|---|---|---| | POST | `/v1/reports` | user | Report a file of a public group, as a member of that group. | | GET | `/v1/blocklist` | node | The content blocklist, a page at a time, for a node hosting a public group. | | GET | `/v1/admin/blocklist` | admin | The content blocklist. | | POST | `/v1/admin/blocklist` | admin | Add a content hash (BLAKE3) to the blocklist. | | DELETE | `/v1/admin/blocklist/{content_hash}` | admin | Remove a content hash from the blocklist. | | GET | `/v1/admin/reports` | moderator | Hashes waiting for a decision, oldest first, with what was said about them. | | POST | `/v1/admin/reports/{content_hash}/block` | admin | Block reported content and close its reports. | | POST | `/v1/admin/reports/{content_hash}/dismiss` | admin | Dismiss the reports on a piece of content. | ### Federation (MHP) | Method | Path | Auth | What | |---|---|---|---| | GET | `/mhp/info` | peer hub | Return this hub's identity for peer registration. | | GET | `/mhp/directory` | peer hub | This hub's public groups, for a peer hub presenting an MHP token. | | POST | `/mhp/directory` | peer hub | A peer hub's public groups, pushed with a single-use MHP token. | | POST | `/mhp/revoke` | peer hub | Act on a revocation from a peer hub. | | POST | `/mhp/peers` | admin | Admin: register a trusted peer hub. | | GET | `/mhp/peers` | admin | Admin: list registered peer hubs. | ### Health | Method | Path | Auth | What | |---|---|---|---| | GET | `/v1/health` | none | Liveness: database reachable, version, connected nodes. | ### Signaling | Method | Path | Auth | What | |---|---|---|---| | POST | `/v1/nodes/{node_id}/webrtc/offer` | user or node | Browser sends WebRTC SDP offer for a node. | ### Administration | Method | Path | Auth | What | |---|---|---|---| | GET | `/v1/admin/settings` | moderator | Instance-wide policy an admin controls from the panel. | | PATCH | `/v1/admin/settings` | admin | Change instance policy. | | GET | `/v1/admin/mail` | moderator | Is the hub still sending, and how much of the hour is left. | | GET | `/v1/admin/stats` | moderator | Account, group and node counts. | | GET | `/v1/admin/users` | moderator | Search and list accounts. | | GET | `/v1/admin/users/{user_id}` | moderator | One account, with its group count. | | PATCH | `/v1/admin/users/{user_id}` | moderator | Change an account's status, or its role (admin only). | | DELETE | `/v1/admin/users/{user_id}` | admin | Erase an account, and every group it owns. | | GET | `/v1/admin/groups` | moderator | List groups with their member counts. | | PATCH | `/v1/admin/groups/{group_id}` | moderator | Change a group's status. | | GET | `/v1/admin/nodes` | moderator | Registered nodes, with the address the hub saw them announce from. | | GET | `/v1/admin/logs` | moderator | The connection log, filtered by account and event. | ### Notifications | Method | Path | Auth | What | |---|---|---|---| | GET | `/v1/notifications` | user or node | The account's notifications, newest first. | | POST | `/v1/notifications/{notification_id}/read` | user or node | Dismiss one. | | DELETE | `/v1/notifications/{notification_id}` | user or node | Dismiss one. | | DELETE | `/v1/notifications` | user or node | Throw them all away. | | POST | `/v1/notifications/read-all` | user or node | Dismiss every one — the same thing as `DELETE ""`, under the name an older client knows it by. | ## Node control API `http://127.0.0.1:`, port 18000 unless `ui_port` in `node.toml` says otherwise, and never on another address. Every request carries the token the daemon writes to `/ui-token` (`~/.local/share/meshbay/ui-token` on Linux), as the `X-MeshBay-Token` header or the `t` query parameter. The daemon draws a new one at each start and deletes the file when it stops. | Method | Path | What | |---|---|---| | GET | `/api/status` | The daemon's state, and what it still needs: a linked key, a group, an operator, a group key. | | DELETE | `/api/unlink` | Unlink the node's key from its hub account. | | GET | `/api/groups` | The groups this node hosts, with live status, and whether an operator is paired. | | POST | `/api/groups/attach` | Host a group that exists on the hub: add it to node.toml with its first folder, then reload. | | POST | `/api/groups/detach` | Stop hosting a group: remove it from node.toml, then reload. | | DELETE | `/api/groups/{group_id}/files/{file_id}` | Delete a file from the group's folder on disk. | | GET | `/api/denylist` | What the node currently refuses. | | POST | `/api/denylist/clear` | Drop denylist entries: all of them, or one identifier. | | GET | `/api/index-cache` | Size of the index cache. | | POST | `/api/index-cache/prune` | Drop index cache rows that no longer match a file on disk. | | POST | `/api/groups/{group_id}/video/rematch` | Forget the automatic matches of the group's videos, so they are looked up again. | | GET | `/api/groups/{group_id}/files` | The group's files, from its index. | | GET | `/api/peers` | The connected peers. | | GET | `/api/audit` | The audit log, filtered by time, account and event. | | POST | `/api/operator/pair` | A one-time code that pairs an application as this node's operator. | | GET | `/api/roster` | The pinned identities, for one group or all. | | POST | `/api/groups/{group_id}/invites` | An invitation code for one account, for this group. | | POST | `/api/groups/{group_id}/invite-links` | A whole invitation link: the node's code, then the hub's ticket. | | DELETE | `/api/groups/{group_id}/invite-links/{invite_id}` | Take an invitation link back, on the node and on the hub. | | GET | `/api/resolve` | Map a username to an account id, through the hub. | | POST | `/api/members/{user_id}/revoke` | Stop serving the group key to a member. | | POST | `/api/members/{user_id}/unpin` | Forget a pinned identity, so the person can pair again with a new key. | | GET | `/api/groups/{group_id}/chat` | What the operator needs to decide anything about the group's chat. | | POST | `/api/groups/{group_id}/chat/epoch` | Open a new chat epoch. | | POST | `/api/groups/{group_id}/chat/encrypt-history` | Re-encrypt the messages written before the group's chat was encrypted. | | POST | `/api/groups/{group_id}/chat/prune` | Delete chat messages older than a number of days. | | POST | `/api/groups/{group_id}/gek` | Generate the group key, or rotate it with ?rotate=true. | | POST | `/api/groups/{group_id}/roots` | Add a folder to a group. | | PATCH | `/api/groups/{group_id}/roots/{root_name}` | Make a folder writable or removable, or not. | | PUT | `/api/groups/{group_id}/roots/{root_name}/eject` | Eject a removable folder so its disk can be unplugged. | | PUT | `/api/groups/{group_id}/roots/{root_name}/plug` | Bring an ejected folder back. | | DELETE | `/api/groups/{group_id}/roots/{root_name}` | Remove a folder from a group. | | GET | `/api/groups/{group_id}/index-status` | One group's indexing progress. | | GET | `/api/index-status` | Every group's indexing progress. | | PUT | `/api/groups/{group_id}/apps` | Which applications members see for the group. | | POST | `/api/reload` | Reload node.toml. | | POST | `/api/shutdown` | Stop the daemon. | | GET | `/api/node-settings` | The node's effective settings. | | PUT | `/api/node-settings` | Change node settings, written to roster.db and node.toml. | | GET | `/api/transfers` | Live transfer leases and queue depth. | | PUT | `/api/groups/{group_id}/transfer-limits` | How many transfers one member may run at once in this group. |