The HTTP bridge runs alongside the daemon when [bridge] enabled = true
in the active config.toml. It exposes the same IPC contract the TUI uses, but over
HTTP — so the web app, mobile clients, agent runners, and your own shell
scripts all talk to the same daemon through one stable surface.
The bridge serves an OpenAPI 3.1 spec at
http://mxr.localhost:42829/api/v1/openapi.json (port and host configurable
in [bridge]). The spec is authenticated like the rest of the bridge API. It
covers most routes and the shared protocol types. Some live routes are missing
from it, and no route carries its parameters or response body, so a generated
client gets the path list and the schemas while payload shapes stay untyped.
That is what the web app runs on: openapi-typescript over the spec, then
openapi-fetch on top. Use the route tables below for request and response
shapes.
Every request except /api/v1/health, /api/v1/auth/local-token, and
/api/v1/i18n needs Authorization: Bearer $MXR_TOKEN. OpenAPI and
Swagger UI are not special-cased. WebSocket clients can also pass the token via the
Sec-WebSocket-Protocol subprotocol or as a ?token= query string.
A plain browser location bar cannot attach an Authorization header. For
generated clients, dump /api/v1/openapi.json with curl first. For normal
browser use, open the first-party web app with mxr web.
The SPA served by mxr web doesn’t ask the user to paste a token.
GET /api/v1/auth/local-token is an unauthenticated endpoint that
returns the bridge token to callers whose TCP peer is a loopback IP.
All mutations accept message_ids: string[] in the JSON body unless
noted. They emit a MutationCompleted event over the WebSocket so
clients can reconcile optimistically.
Method
Path
Purpose
POST
/mail/mutations/archive
Remove from inbox
POST
/mail/mutations/trash
Move to trash
POST
/mail/mutations/spam
Mark as spam
POST
/mail/mutations/star
Star / unstar ({starred: bool})
POST
/mail/mutations/read
Mark read / unread ({read: bool})
POST
/mail/mutations/read-and-archive
Combined
POST
/mail/mutations/labels
Modify labels ({add, remove})
POST
/mail/mutations/move
Move to another label
POST
/mail/mutations/undo
Undo via mutation_id
POST
/mail/sync
Trigger sync
POST
/mail/snoozed/{id}/wake
Force-unsnooze
GET
/mail/actions/snooze/presets
Available snooze presets
POST
/mail/actions/snooze
Snooze messages
POST
/mail/actions/unsubscribe
Unsubscribe from list mail
POST
/mail/actions/invite/reply
Dry-run or send a calendar invite RSVP
POST
/mail/deliveries/scan
Backfill scan ({since_days, dry_run})
POST
/mail/deliveries/{id}/resolve
Mark a delivery delivered/done
POST
/mail/deliveries/{id}/dismiss
Hide a false positive
POST
/mail/messages/{message_id}/flags
Set message flags (bitmask in body)
Terminal window
curl-XPOST-H"Authorization: Bearer $MXR_TOKEN"\
-H"Content-Type: application/json"\
-d'{"message_ids":["..."], "starred":true}'\
"$MXR_BASE/api/v1/mail/mutations/star"
List detected calendar invites:
Terminal window
curl-G-H"Authorization: Bearer $MXR_TOKEN"\
"$MXR_BASE/api/v1/mail/invites"\
--data-urlencode'limit=50'
Dry-run calendar replies before sending the iMIP METHOD:REPLY email:
Per-sender aggregates plus recent messages from that sender
GET
/mail/contacts/autocomplete?q=...&limit=...
Prefix-search known senders (filters by email or display name)
The sender response is SenderProfile { profile }. When present, profile
includes recent_messages: the newest messages from that sender with
message_id, thread_id, subject, snippet, date, direction,
and an attachment-present flag. Clients use this to render “Other
emails from sender” and deep-link directly into the matching thread.
The desktop and any other interactive client open a compose session
that the daemon owns. The state (frontmatter + body + attachments)
lives server-side until you send/save/discard.
Method
Path
Purpose
POST
/mail/compose/session
Open new / reply / forward
POST
/mail/compose/session/refresh
Refetch latest state
POST
/mail/compose/session/restore
Resume saved draft
POST
/mail/compose/session/update
Save current edits locally and to a linked provider draft
POST
/mail/compose/session/send
Send (calls provider)
POST
/mail/compose/session/save
Save locally or create/update a linked provider draft
These are the “platform” features — saved searches, rules, account
management, analytics, LLM status, semantic search. Available even
without an active inbox.
Connect a WebSocket to /api/v1/events and you’ll receive a JSON line
per daemon event. The TypeScript shapes are in
apps/web/src/api/generated.ts under DaemonEvent. Common ones:
MutationCompleted — your last mutation landed (or rolled back)
SyncStarted / SyncFinished
ReminderTriggered — auto-reminder fired
ScheduledSendFlushed — a Send Later draft just went out
IndexBootstrapped — Tantivy completed a startup repair