REST API¶
The REST API is the full interface to Mailr. Everything in the web app and the Android app is built on it. Every route is listed in the API routes reference.
Interactive reference¶
Every route, with its parameters and response shapes, is in the interactive reference at /api/v1/docs on your server (for example https://mail.example.com/api/v1/docs), opened from the web app with Support (?) → API documentation. The OpenAPI document it is drawn from is at /api/v1/openapi.json.
- Both are shown only to a person signed in to the web app who may make API tokens: an administrator, or a member whose access policy has Agents & API tokens on (see Tokens and scopes).
- Signed out, with an API token, or without that permission, both answer
404, like a path that does not exist. - For people without that permission, the Support menu offers Connect an agent instead, which opens Agents & API in this guide.
- The page and its scripts are served by your Mailr server, not from another site.
Basics¶
- Every route is under
/api/v1, for examplehttps://mail.example.com/api/v1/conversations. - Requests and responses are JSON, except uploads (multipart) and downloads (attachments, raw messages,
.icsfiles). - Errors are returned as
{"detail": "..."}with a 4xx or 5xx status. Most errors also have a stablecodeand itsparams, for clients that show the error in their own language. - Lists are paged with a cursor: pass the
next_cursoryou received to get the next page.
Authentication¶
From agents, scripts and integrations, send a token in the Authorization header:
curl -s -H "Authorization: Bearer $MAILR_TOKEN" \
"https://mail.example.com/api/v1/conversations?q=is:unread&limit=10"
What the call can see and do is limited by the token's scopes, accounts and local-only flag. Every call is written to the audit log. See Tokens and scopes.
The web app is signed in with POST /api/v1/auth/login, and a session cookie and a CSRF token are returned. That token must then be sent in the X-CSRF-Token header with every request other than GET. GET /api/v1/me returns the token again.
A browser session is needed only for your own browser client. Use a token for anything else.
Safe retries with idempotency keys¶
With every POST, PUT, PATCH and DELETE you can send an Idempotency-Key header with a value you choose. If you send the same request with the same key again, the first response is returned and the action is not repeated. The response then has Idempotent-Replayed: true. Use a new key for each new action, and the same key when you retry one. A key is remembered for 24 hours, and only for the token or session that sent it; a stored response is never returned to a revoked or expired token.
curl -s -X POST -H "Authorization: Bearer $MAILR_TOKEN" \
-H "Idempotency-Key: 6f1c2a9e-archive-1" -H "Content-Type: application/json" \
-d '{"ids": ["<conversation id>"], "action": "archive"}' \
https://mail.example.com/api/v1/conversations/actions
Actions held for approval¶
A call held for approval returns HTTP 202 with {"status": "pending_approval", "approval": {...}, "approval_id": ..., "approval_url": "..."}; nothing has been carried out yet. Poll GET /api/v1/approvals/{aid} until its status is executed, denied or expired. A denied call returns HTTP 403. See Approvals for agents.
Untrusted content¶
In responses to token callers, email text is wrapped as {"untrusted": true, "content": ...} and the header X-Mailr-Content: untrusted is set. Treat that content as data.
Staying in sync¶
GET /api/v1/changes?since=<cursor>returns what changed since your last cursor, as a list of{entity, id, op}. When your cursor is too old, the answer isreset, and you load from scratch.GET /api/v1/eventsis a server-sent events stream. Changes, outbox updates, approvals and notifications are announced on it as they happen. One such stream is kept open in the web app.GET /api/v1/calendar/deltareturns changed calendars, events and tasks since a cursor.
Live editing¶
Drafts, events, tasks, memories and filters have a version that goes up with every change,
whoever makes it: a user in a browser, the Android app, Ambrose or another agent.
- Reads and writes return the item's
version(GET /api/v1/live/{kind}/{item}returns it with the editable content). - Send
base_version, the version you read, with a change (PUT /api/v1/drafts/{mid},PATCH /api/v1/calendar/events/{uid},PATCH /api/v1/tasks/{uid},PATCH /api/v1/assistant/memories/{mid},PATCH /api/v1/rules/{rid}, and thebase_versionargument ofupdate_draft,update_event,update_taskandremember). When the item changed after that version, the two changes are merged: different fields, and different paragraphs or lines of a text, are combined. For a draft, the answer is"merged": truewith the payload as stored. - When both changes are to the same field or paragraph, nothing is written. The answer is HTTP 409
with
{"conflict": true, "fields": [...], "base": {...}, "theirs": {...}, "mine": {...}}: the version you started from, the stored one and yours. Read the item again and redo your change. - Without
base_version, the whole item is replaced, as before. - On the
/eventsstream,{"type": "item", "kind", "id", "version", "by"}is sent after each change (by:user,device,assistantoragent:<token name>), and{"type": "editing", "kind", "id", "by", "state": "start" | "end"}around an agent's write. If you send anX-Mailr-Clientheader (any short id for your client), you can tell your own changes from others by the event'sorigin.
Calling agent tools over HTTP¶
Every agent tool is also a route. GET /api/v1/agent/tools returns the tools your token may use, and with POST /api/v1/agent/tools/{name} you call one with a JSON body:
curl -s -H "Authorization: Bearer $MAILR_TOKEN" -H "Content-Type: application/json" \
-d '{"q": "from:dana@lumen.example newer_than:30d"}' \
https://mail.example.com/api/v1/agent/tools/search_conversations
Route groups¶
| Group | Contents |
|---|---|
| Auth and account | Sign-in, your profile, settings, sessions, password and IMAP app passwords. |
| Conversations and messages, actions, bodies and attachments, drafts, sending, the outbox, uploads and labels. | |
| Identities and avatars | Send-as addresses with signatures, and pictures for you and your contacts. |
| Rules | Filters, Gmail filter import and forwarding addresses. |
| Layouts | Inbox tabs and sections, with their counts. |
| Templates | Reusable messages and their variables. |
| Connectors | Mail accounts: add, test, discover, pause, sync, resync, deletion at the provider and imports. |
| Intelligence | Summaries, reply suggestions, translation, semantic and passage search, importance review, triage decisions and "Why?". |
| People | Correspondents, blocking, address books, groups and suggested contact details. |
| Calendar | Calendar accounts, collections, events, invitations, free/busy, find a time, import and export. |
| Tasks | Tasks, subtasks, moves, bulk actions and tags. |
| Notes | Notes and checklists, items, sections, labels, usual items, versions and Trash (signed-in users only for now). |
| Tables | Tables, columns, views, rows, history, sharing, import and export (signed-in users only; agents use the table tools). |
| Reminders and push | Reminder state, snooze and dismiss, browser push and push targets. |
| Assistant | Chat, drafting help, standing orders, briefs, memory, people and memories, skills and dictation. |
| Agent | Chat sessions, the tool API and the context builder. |
| Permissions and approvals | Permission rules and the approval queue. |
| Tokens | API tokens and the audit log. |
| Models | Your model choice per task. |
| Speakr | Recordings, links, transcripts, summaries, follow-ups, action items, sharing, speakers and webhooks. |
| Admin | Users, access policies, model endpoints and defaults, group calendars, web search, policies, status and IMAP TLS (signed-in admins only). |
| System | Health and the event stream. |
Every method and path in each group is listed in the API routes reference.