OAKENMAIL
Generated

HTTP API

The loopback API: authentication, the Host and Origin rules, every operation route, the event stream and the agent job routes, from the OpenAPI document.

The local API core serves on 127.0.0.1. The CLI and the web UI use it, and the OpenAPI document this page is built from is served at GET /v1/openapi.json. How it is kept safe.

1

Reaching it

The MCP server is not in this document. When [api] mcp = true it is a separate door on the same listener, /mcp, with its own token and limits, and with the swarm on, /mcp/agent for agent tokens. See Connect an AI client.

2

Routes

Method Path Auth What it does
GET /v1/health none Liveness. Needs no token and reveals nothing else.
GET /v1/operations API token The operations this caller may call, with their schemas.
GET /v1/openapi.json API token This document.
GET /v1/events API token Server-Sent Events: what core does, as it happens.
POST /v1/agent/jobs/claim agent token Lease the best runnable job of the agent's kinds, or none.
POST /v1/agent/jobs/{job_id}/heartbeat agent token Extend the lease; says whether the job was cancelled.
POST /v1/agent/jobs/{job_id}/complete agent token Finish the job with a result that matches its kind's schema.
POST /v1/agent/jobs/{job_id}/fail agent token Give the job back with an error; core decides whether to retry.
POST /v1/operations/{name} API token Call one operation. 46 exist.
3

Calling an operation

POST /v1/operations/{name} takes input and answers ``request_id, status, output?.

status is ok when the operation ran, or confirmation_required for a mutation that was not confirmed: nothing has changed, and proposal says what would, with a confirmation_token. A person at the CLI or UI may send confirm: true. An agent calls again with the token. Status codes: 422 input or result does not validate, 403 not permitted, 404 unknown, 409 conflict, 429 quota, 502 a plugin or provider failed.

Operation Permission MCP Route
ask read off until turned on POST /v1/operations/ask
authorization_status read never POST /v1/operations/authorization_status
check_account read never POST /v1/operations/check_account
create_account mutate never POST /v1/operations/create_account
create_agent mutate never POST /v1/operations/create_agent
enrich_message mutate never POST /v1/operations/enrich_message
get_account read never POST /v1/operations/get_account
get_enrichment read on by default POST /v1/operations/get_enrichment
get_message read on by default POST /v1/operations/get_message
get_message_rules read on by default POST /v1/operations/get_message_rules
get_raw read never POST /v1/operations/get_raw
list_accounts read on by default POST /v1/operations/list_accounts
list_agents read never POST /v1/operations/list_agents
list_audit read never POST /v1/operations/list_audit
list_labels read on by default POST /v1/operations/list_labels
list_messages read on by default POST /v1/operations/list_messages
list_operations read never POST /v1/operations/list_operations
list_plugins read on by default POST /v1/operations/list_plugins
list_schedules read on by default POST /v1/operations/list_schedules
mark_read mutate on by default POST /v1/operations/mark_read
mark_unread mutate on by default POST /v1/operations/mark_unread
message_dismissed read never POST /v1/operations/message_dismissed
message_presented mutate never POST /v1/operations/message_presented
pause_schedule mutate never POST /v1/operations/pause_schedule
pipeline_status read on by default POST /v1/operations/pipeline_status
plugin_health read on by default POST /v1/operations/plugin_health
rebuild_index mutate never POST /v1/operations/rebuild_index
remove_schedule mutate never POST /v1/operations/remove_schedule
reprocess mutate never POST /v1/operations/reprocess
resume_schedule mutate never POST /v1/operations/resume_schedule
revoke_agent mutate never POST /v1/operations/revoke_agent
search read on by default POST /v1/operations/search
search_keyword read on by default POST /v1/operations/search_keyword
set_account_config mutate never POST /v1/operations/set_account_config
set_account_password mutate never POST /v1/operations/set_account_password
set_operation_exposure mutate never POST /v1/operations/set_operation_exposure
set_schedule mutate never POST /v1/operations/set_schedule
sieve_check read never POST /v1/operations/sieve_check
sieve_list read never POST /v1/operations/sieve_list
sieve_test read never POST /v1/operations/sieve_test
start_authorization mutate never POST /v1/operations/start_authorization
status read on by default POST /v1/operations/status
summarize_message mutate on by default POST /v1/operations/summarize_message
sync_now mutate on by default POST /v1/operations/sync_now
undo mutate on by default POST /v1/operations/undo
usage_summary read on by default POST /v1/operations/usage_summary

Each operation's input and output are in Reference: Operations, and as JSON Schema in the OpenAPI document and in GET /v1/operations.

4

Events

GET /v1/events is server-sent events. Each frame has an id (a number), an event (the type below) and data (one line of JSON: ids and counts, never message text). Send Last-Event-ID to resume from the in-memory ring. If that id is older than the ring, or from before core restarted, a gap event comes first, meaning fetch state again. A quiet stream sends : heartbeat comments.

Event type Meaning Fields
AttachmentQuarantined Flagged attachments of a message were written to the quarantine folder (never opened). ts, event_id, account_id, message_id, count
IndexRebuildProgress A rebuild of index.db is under way. total is the live messages in scope when it started; done counts the ones looked at (changed or not). finished is the last event. ts, event_id, account_id, done, total, indexed, failed, finished
JobStateChanged Job state changed. ts, event_id, job_id, kind, status, account_id
LargeMessageStored A message was too big for raw.db and went to the LFS folder, whole. oversize is set when it is also past storage.max_message_bytes (worth a warning in a UI). ts, event_id, account_id, message_id, size_bytes, oversize
MessageEmbedded Message embedded. ts, event_id, account_id, message_id, model
MessageEnriched Message enriched. ts, event_id, account_id, message_id, enricher
MessageFiltered Sieve ran on a message and its organization attributes were written. ts, event_id, account_id, message_id, disposition
MessageIndexed Message indexed. ts, event_id, account_id, message_id
MessageParsed Message parsed. ts, event_id, account_id, message_id
MessageReadChanged Message read changed. ts, event_id, account_id, message_id, read, reason, audit_id, local_only, error
MessageStored is_new: first time seen. changed: an existing message got different bytes (or came back after a delete), so anything derived from it is stale. A no-op put publishes nothing. ts, event_id, account_id, message_id, is_new, changed
PluginEvent Base for events a plugin defines itself: subclass it, add plain-data fields, and publish with ctx.publish(...). plugin names the sender (the host fills it in). ts, event_id, plugin
PluginHealthChanged Plugin health changed. ts, event_id, plugin, healthy, detail
SyncFinished Sync finished. ts, event_id, account_id, new_messages, error, quiet, folder
SyncPaused An account's scheduled sync stopped until the user acts (for example, the password was refused). quiet is as on SyncFinished. ts, event_id, account_id, reason, quiet
SyncProgress Sync progress. ts, event_id, account_id, done, total
SyncScheduleChanged A sync schedule was added, edited, paused, resumed or removed (change says which). ts, event_id, account_id, folder, change
SyncStarted Sync started. ts, event_id, account_id
gap That id is no longer available; fetch state again. first_available
5

Agent job routes

Authenticated by an agent token, never by the API token. See the swarm.

POST /v1/agent/jobs/claim

Lease the best runnable job of the agent's kinds, or none.

POST /v1/agent/jobs/{job_id}/heartbeat

Extend the lease; says whether the job was cancelled.

POST /v1/agent/jobs/{job_id}/complete

Finish the job with a result that matches its kind's schema.

POST /v1/agent/jobs/{job_id}/fail

Give the job back with an error; core decides whether to retry.