Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.sendmux.ai/llms.txt

Use this file to discover all available pages before exploring further.

The Sendmux Mailbox API is for mailbox-scoped credentials. Use it when a client should act only as the mailbox tied to its API key, not manage team-wide resources. Team-wide mailbox provisioning stays in the Management API. High-volume provider-routed sending stays in the Sending API.

Base URL

All Mailbox API requests should be made to:
https://app.sendmux.ai/api/v1

Authentication

Authenticate with a mailbox credential from the Sendmux app. Pass it as a Bearer token in the Authorization header.
curl https://app.sendmux.ai/api/v1/mailbox/me \
  -H "Authorization: Bearer smx_mbx_your_key_here"
Mailbox credentials are scoped to one mailbox. Root API keys are rejected on Mailbox API endpoints. The same credential is also accepted as the mailbox password for SMTP submission and IMAP retrieval.

Current endpoints

EndpointPurpose
GET /mailbox/meReturn the mailbox associated with the bearer token.
GET /mailbox/sessionReturn supported capabilities, limits, and current state tokens.
GET /mailbox/identityReturn the mailbox’s default sender identity and signatures.
PATCH /mailbox/identityUpdate the mailbox’s sender name and signatures.
GET /mailbox/identitiesList sender identities available to the mailbox.
GET /mailbox/messagesList messages with filters, sorting, and cursor pagination.
POST /mailbox/messages:batch-getRead exact message IDs with optional raw or clean body output.
POST /mailbox/messages:batch-updateUpdate allowed flags for multiple messages.
POST /mailbox/messages:batch-deleteMove or permanently delete multiple messages.
GET /mailbox/messages/countCount messages matching filters without returning rows.
GET /mailbox/messages/query-changesRead filtered message-list index changes since a prior state.
GET /mailbox/messages/search-snippetsReturn subject and preview snippets for text searches.
GET /mailbox/messages/{message_id}Read a message, including bodies and attachment metadata.
GET /mailbox/messages/{message_id}/bodyRead raw body text, HTML, or both without cleaning.
GET /mailbox/messages/{message_id}/contentRead clean message content with body-cleaning controls.
PATCH /mailbox/messages/{message_id}Update mutable message flags with state-safe conflict handling.
DELETE /mailbox/messages/{message_id}Move or delete a message with state-safe conflict handling.
POST /mailbox/attachments:uploadUpload an attachment for a later send request.
GET /mailbox/messages/{message_id}/attachments/{attachment_id}Download an attachment.
POST /mailbox/messages/sendSend from the authenticated mailbox.
GET /mailbox/threadsList conversation threads with filters and cursor pagination.
GET /mailbox/threads/{thread_id}Read thread metadata, message IDs, participants, and state.
GET /mailbox/threads/{thread_id}/messagesList message summaries for one thread.
GET /mailbox/threads/{thread_id}/contentRead clean message content for one thread with cursor pagination.
GET /mailbox/foldersList folders.
POST /mailbox/foldersCreate a folder.
GET /mailbox/folders/changesRead folder object changes since a prior folder state.
GET /mailbox/folders/query-changesRead folder-list index changes since a prior query state.
GET /mailbox/folders/{folder_id}Read one folder.
PATCH /mailbox/folders/{folder_id}Update a folder with state-safe conflict handling.
DELETE /mailbox/folders/{folder_id}Delete an empty custom folder with state-safe conflict handling.
GET /mailbox/submissionsList send submissions with filters and cursor pagination.
GET /mailbox/submissions/changesRead submission object changes since a prior state.
GET /mailbox/submissions/{submission_id}Read one send submission.
GET /mailbox/quotasList mailbox quota usage and limits.
GET /mailbox/quotas/changesRead quota object changes since a prior quota state.
GET /mailbox/usageRead a compact usage view derived from quota records.
GET /mailbox/changesRead message changes, or a typed resource state map.
GET /mailbox/eventsStream mailbox events with Server-Sent Events.
Import the Mailbox API Postman collection when you want ready-made requests.

Capability discovery

Use GET /mailbox/session before planning a mailbox workflow. It returns the mailbox tied to the credential, supported Mailbox API features, current state tokens, request limits, and gated features. A gated feature is intentionally unavailable through the Mailbox API.
curl "https://app.sendmux.ai/api/v1/mailbox/session" \
  -H "Authorization: Bearer smx_mbx_your_key_here"
{
  "ok": true,
  "data": {
    "mailbox": {
      "id": "mbx_clxxxxxxxxxxxxxxxxxxxxxxxxx",
      "email": "agent@example.com",
      "display_name": "Agent"
    },
    "states": {
      "messages": "email_state_token",
      "folders": "folder_state_token",
      "threads": "thread_state_token",
      "submissions": "submission_state_token",
      "identities": "identity_state_token",
      "quotas": "quota_state_token"
    },
    "capabilities": {
      "messages": {
        "list": true,
        "query_changes": true,
        "batch_update": true,
        "keywords": true,
        "update_fields": ["seen", "flagged", "keywords"]
      },
      "identities": {
        "list": true,
        "update": true
      },
      "attachments": {
        "upload": true,
        "download": true,
        "parsing": false
      }
    },
    "limits": {
      "list_limit_max": 100,
      "changes_limit_max": 500,
      "batch_ids_max": 100,
      "body_chars_max": 1000000,
      "inline_attachment_bytes_max": 5000000,
      "attachment_upload_bytes_max": 7500000,
      "outbound_raw_message_bytes_max": 26214400,
      "keywords_per_update_max": 50
    },
    "gated": {
      "identity_mutation": false,
      "quota_mutation": true,
      "filter_script_writes": true,
      "events": false,
      "raw_protocol": true,
      "attachment_parsing": true
    }
  },
  "meta": {
    "request_id": "req_clxxxxxxxxxxxxxxxxxxxxxxxxx"
  }
}
gated fields are true when a feature is intentionally unavailable.

Operational resources

Operational endpoints expose what an agent needs to send safely and monitor mailbox health without adding mutation authority.

Sender identities

Use GET /mailbox/identity to read the mailbox’s default sender name and signatures. Use PATCH /mailbox/identity to update name, text_signature, and html_signature. Mailbox API sends use this sender name by default and append the matching plain text or HTML signature when the send body includes that format.
curl "https://app.sendmux.ai/api/v1/mailbox/identity" \
  -H "Authorization: Bearer smx_mbx_your_key_here"
curl -X PATCH "https://app.sendmux.ai/api/v1/mailbox/identity" \
  -H "Authorization: Bearer smx_mbx_your_key_here" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Support",
    "text_signature": "Regards",
    "html_signature": "<p>Regards</p>"
  }'
GET /mailbox/identities lists all sender identities available to the authenticated mailbox.
curl "https://app.sendmux.ai/api/v1/mailbox/identities" \
  -H "Authorization: Bearer smx_mbx_your_key_here"
{
  "ok": true,
  "data": [
    {
      "id": "id_123",
      "name": "Support",
      "email": "support@example.com",
      "reply_to": [],
      "bcc": [],
      "text_signature": "Regards",
      "html_signature": "<p>Regards</p>",
      "may_delete": false
    }
  ],
  "pagination": {
    "has_more": false
  },
  "meta": {
    "request_id": "req_clxxxxxxxxxxxxxxxxxxxxxxxxx",
    "identity_state": "identity_state_token"
  }
}

Send submissions

Use submissions to inspect queued, sent, failed, or cancelled send lifecycle records separately from the messages/send request that created them.
curl "https://app.sendmux.ai/api/v1/mailbox/submissions?email_ids=msg_123&limit=10" \
  -H "Authorization: Bearer smx_mbx_your_key_here"
Useful filters:
ParameterPurpose
identity_idsComma-separated identity IDs.
email_idsComma-separated message IDs.
thread_idsComma-separated thread IDs.
undo_statusMatch a specific submission undo state.
afterMatch submissions sent at or after this time.
beforeMatch submissions sent before this time.
cursorContinue from a previous page.
limitReturn 1 to 100 submissions.
sort_bySort by send_at, email_id, or thread_id.
sort_directionSort asc or desc.
Read one submission with GET /mailbox/submissions/{submission_id}. Poll GET /mailbox/submissions/changes?since_state=... to sync submission object changes.

Quotas and usage

Use quotas for detailed limits and usage for a compact health view.
curl "https://app.sendmux.ai/api/v1/mailbox/usage" \
  -H "Authorization: Bearer smx_mbx_your_key_here"
{
  "ok": true,
  "data": {
    "resources": [
      {
        "quota_id": "quota_123",
        "name": "Mailbox storage",
        "resource_type": "octets",
        "scope": "account",
        "types": ["Mail"],
        "used": 536870912,
        "hard_limit": 1073741824,
        "warn_limit": 858993459,
        "soft_limit": null,
        "percent_used": 50,
        "limit_status": "ok"
      }
    ],
    "states": {
      "quota_state": "quota_state_token"
    }
  },
  "meta": {
    "request_id": "req_clxxxxxxxxxxxxxxxxxxxxxxxxx"
  }
}
Quota filters:
ParameterPurpose
nameMatch quota name text.
scopeMatch account, domain, or global.
resource_typeMatch count or octets.
typeMatch a resource family, such as Mail.
cursorContinue from a previous page.
limitReturn 1 to 100 quotas.
sort_bySort by name or used.
sort_directionSort asc or desc.
Poll GET /mailbox/quotas/changes?since_state=... to sync quota changes.

Thread APIs

Use thread endpoints when you need conversation-level context without fetching every body.

List threads

curl "https://app.sendmux.ai/api/v1/mailbox/threads?q=invoice&participant=sender@example.com&folder_id=inbox&is_unread=true&limit=10" \
  -H "Authorization: Bearer smx_mbx_your_key_here"
{
  "ok": true,
  "data": [
    {
      "id": "thr_123",
      "subject": "Invoice question",
      "message_count": 2,
      "unread_count": 1,
      "has_attachments": true,
      "folder_ids": ["inbox"],
      "participants": [
        { "email": "sender@example.com", "name": "Sender" },
        { "email": "agent@example.com", "name": "Agent" }
      ],
      "last_message": {
        "id": "msg_456",
        "thread_id": "thr_123",
        "subject": "Re: Invoice question",
        "preview": "Thanks, I found it.",
        "has_attachments": false
      },
      "states": {
        "thread_state": "thread_state_token",
        "email_state": "message_state_token"
      }
    }
  ],
  "pagination": {
    "has_more": false
  },
  "meta": {
    "request_id": "req_clxxxxxxxxxxxxxxxxxxxxxxxxx",
    "query_state": "thread_query_state_token"
  }
}
Thread list filters:
ParameterPurpose
qSearch common address, subject, and body text.
participantMatch sender or recipient addresses.
folder_idRestrict results to one folder.
is_unreadMatch unread or read threads.
has_attachmentMatch threads with or without attachment metadata.
afterMatch threads with messages at or after this time.
beforeMatch threads with messages before this time.
cursorContinue from a previous page.
limitReturn 1 to 100 threads.
sort_directionSort by most recent message, desc or asc.

Read a thread

curl https://app.sendmux.ai/api/v1/mailbox/threads/thr_123 \
  -H "Authorization: Bearer smx_mbx_your_key_here"
The response includes the same thread metadata as the list endpoint plus message_ids in chronological order. Use GET /mailbox/threads/{thread_id}/messages for paginated message summaries, or GET /mailbox/threads/{thread_id}/content when you need cleaned bodies.

Retrieval precision APIs

Use exact retrieval and count endpoints when you already know what you need. This keeps client payloads small and avoids fetching message bodies just to answer count or search-preview questions.

Rich message filters

GET /mailbox/messages and GET /mailbox/messages/count support these filters. GET /mailbox/messages/search-snippets and GET /mailbox/messages/query-changes support the same filters except thread_id; pass message_ids when you already know the exact messages to snippet.
ParameterPurpose
folder_idRestrict results to one folder.
thread_idRestrict list/count to one thread. Not supported for snippets.
qSearch common address, subject, and body text.
fromSearch the From header.
toSearch the To header.
ccSearch the Cc header.
bccSearch the Bcc header.
subjectSearch subject text.
bodySearch body text.
header_nameMatch messages with a specific header.
header_valueMatch text inside header_name.
min_size_bytesMatch messages at least this many bytes.
max_size_bytesMatch messages smaller than this many bytes.
keywordMatch messages with a keyword, such as $seen.
not_keywordMatch messages without a keyword.
afterMatch messages received at or after this timestamp.
beforeMatch messages received before this timestamp.
has_attachmentMatch messages with or without attachments.
is_unreadMatch unread or read messages.
thread_id uses the thread’s message order and cannot be combined with other message filters. Use the thread content endpoint when you need cleaned bodies for one conversation.

Count messages

Use the count endpoint when you only need the number of matches.
curl "https://app.sendmux.ai/api/v1/mailbox/messages/count?body=invoice&after=2026-05-01T00:00:00Z" \
  -H "Authorization: Bearer smx_mbx_your_key_here"
{
  "ok": true,
  "data": {
    "total": 12,
    "sync_state": "state_token"
  },
  "meta": {
    "request_id": "req_clxxxxxxxxxxxxxxxxxxxxxxxxx"
  }
}

Search snippets

Use snippets to decide which matching messages deserve a full fetch. Snippets may include <mark> tags around matched terms.
curl "https://app.sendmux.ai/api/v1/mailbox/messages/search-snippets?q=invoice&limit=5" \
  -H "Authorization: Bearer smx_mbx_your_key_here"
{
  "ok": true,
  "data": {
    "snippets": [
      {
        "message_id": "msg_123",
        "subject": "Question about <mark>invoice</mark>",
        "preview": "Can you resend the <mark>invoice</mark> for April?"
      }
    ],
    "not_found": [],
    "sync_state": "state_token"
  },
  "meta": {
    "request_id": "req_clxxxxxxxxxxxxxxxxxxxxxxxxx"
  }
}
Pass message_ids as a comma-separated list when you already have exact messages:
curl "https://app.sendmux.ai/api/v1/mailbox/messages/search-snippets?q=invoice&message_ids=msg_123,msg_456" \
  -H "Authorization: Bearer smx_mbx_your_key_here"

Batch get messages

Use batch get when you have exact IDs and want one request instead of one call per message.
curl https://app.sendmux.ai/api/v1/mailbox/messages:batch-get \
  -H "Authorization: Bearer smx_mbx_your_key_here" \
  -H "Content-Type: application/json" \
  -d '{
    "ids": ["msg_123", "msg_456"],
    "body_mode": "clean_json",
    "part": "text",
    "max_body_chars": 50000,
    "strip_signature": true,
    "strip_quotes": true,
    "include_links": true,
    "include_html": false,
    "include_headers": "selected",
    "include_attachments": "metadata"
  }'
{
  "ok": true,
  "data": {
    "messages": [
      {
        "message": {
          "id": "msg_123",
          "thread_id": "thr_123",
          "subject": "Invoice question",
          "preview": "Can you resend the invoice?",
          "has_attachments": true
        },
        "raw_body": null,
        "content": {
          "id": "msg_123",
          "thread_id": "thr_123",
          "subject": "Invoice question",
          "body": {
            "format": "text",
            "text": "Can you resend the invoice?",
            "html": null,
            "is_truncated": false,
            "truncated_at_chars": null,
            "signature_stripped": false,
            "quotes_stripped": false,
            "extracted_links": []
          },
          "attachments": [
            {
              "id": "att_123",
              "filename": "invoice.pdf",
              "content_type": "application/pdf",
              "size_bytes": 12345,
              "disposition": "attachment",
              "content_id": null,
              "download_url": "/api/v1/mailbox/messages/msg_123/attachments/att_123"
            }
          ]
        }
      }
    ],
    "not_found": [],
    "states": {
      "email_state": "state_token"
    }
  },
  "meta": {
    "request_id": "req_clxxxxxxxxxxxxxxxxxxxxxxxxx"
  }
}
Batch body modes:
body_modeOutput
noneMessage summaries only.
rawMessage summaries plus raw_body. Supports part=text, html, or both.
clean_jsonMessage summaries plus content. Supports the clean controls below.

Batch update messages

Use batch update to set allowed flags and keywords on up to 100 messages in one state-safe request. keywords is a map where true sets a keyword and false clears it. Keyword names are normalised to lowercase. Lifecycle keywords such as $draft are read-only.
curl -X POST https://app.sendmux.ai/api/v1/mailbox/messages:batch-update \
  -H "Authorization: Bearer smx_mbx_your_key_here" \
  -H "Content-Type: application/json" \
  -d '{
    "ids": ["msg_123", "msg_456"],
    "seen": true,
    "keywords": {
      "agent_triaged": true,
      "needs_reply": false
    },
    "if_in_state": "message_state_token"
  }'
{
  "ok": true,
  "data": {
    "updated": ["msg_123", "msg_456"],
    "not_found": [],
    "failed": [],
    "states": {
      "old_state": "message_state_token",
      "new_state": "message_state_token_2"
    }
  },
  "meta": {
    "request_id": "req_clxxxxxxxxxxxxxxxxxxxxxxxxx"
  }
}

Batch delete messages

Use batch delete to move up to 100 messages to Trash. Set permanent=true only when the messages should be permanently removed.
curl -X POST https://app.sendmux.ai/api/v1/mailbox/messages:batch-delete \
  -H "Authorization: Bearer smx_mbx_your_key_here" \
  -H "Content-Type: application/json" \
  -d '{
    "ids": ["msg_123", "msg_456"],
    "permanent": false,
    "if_in_state": "message_state_token"
  }'
{
  "ok": true,
  "data": {
    "deleted": ["msg_123", "msg_456"],
    "not_found": [],
    "failed": [],
    "states": {
      "old_state": "message_state_token",
      "new_state": "message_state_token_2"
    }
  },
  "meta": {
    "request_id": "req_clxxxxxxxxxxxxxxxxxxxxxxxxx"
  }
}
Batch update and delete accept if_in_state for stale-write protection. Use the latest message state from message lists, detail reads, batch reads, or change endpoints.

Message body APIs

Use the raw body endpoint when you need the message body exactly as available from the mailbox.
curl "https://app.sendmux.ai/api/v1/mailbox/messages/msg_123/body?part=both&max_body_chars=50000" \
  -H "Authorization: Bearer smx_mbx_your_key_here"
{
  "ok": true,
  "data": {
    "id": "msg_123",
    "thread_id": "thr_123",
    "part": "both",
    "body": {
      "text": "Original body text...",
      "html": "<p>Original body HTML...</p>",
      "is_truncated": false,
      "truncated_at_chars": null
    },
    "states": {
      "email_state": "state_token"
    }
  },
  "meta": {
    "request_id": "req_clxxxxxxxxxxxxxxxxxxxxxxxxx"
  }
}
Use the clean content endpoint when you want deterministic body cleaning and structured metadata.
curl "https://app.sendmux.ai/api/v1/mailbox/messages/msg_123/content?strip_signature=true&strip_quotes=true&include_links=true&include_html=false&include_headers=selected&include_attachments=metadata" \
  -H "Authorization: Bearer smx_mbx_your_key_here"
{
  "ok": true,
  "data": {
    "id": "msg_123",
    "thread_id": "thr_123",
    "subject": "Invoice question",
    "body": {
      "format": "text",
      "text": "Clean body text...",
      "html": null,
      "is_truncated": false,
      "truncated_at_chars": null,
      "signature_stripped": true,
      "quotes_stripped": true,
      "extracted_links": ["https://example.com/invoice"]
    },
    "attachments": [
      {
        "id": "att_123",
        "filename": "invoice.pdf",
        "content_type": "application/pdf",
        "size_bytes": 12345,
        "disposition": "attachment",
        "content_id": null,
        "download_url": "/api/v1/mailbox/messages/msg_123/attachments/att_123"
      }
    ]
  },
  "meta": {
    "request_id": "req_clxxxxxxxxxxxxxxxxxxxxxxxxx"
  }
}
Clean content controls:
ParameterValuesDefaultApplies to
partauto, text, htmlautoMessage content, thread content, batch clean JSON
max_body_chars1 to 1000000100000 for messages, 25000 per thread messageRaw body, message content, thread content, batch
strip_signaturetrue, falsetrueMessage content, thread content, batch clean JSON
strip_quotestrue, falsetrueMessage content, thread content, batch clean JSON
include_linkstrue, falsetrueMessage content, thread content, batch clean JSON
include_htmltrue, falsefalseMessage content, thread content, batch clean JSON
include_headersnone, selected, fullselectedMessage content, thread content, batch clean JSON
include_attachmentsnone, metadatametadataMessage content, thread content, batch clean JSON
cursorOpaque cursornoneThread content
limit1 to 10025Thread content
Body endpoints do not parse attachment contents. Attachments are returned as metadata or downloaded separately. PDF, CSV, Office document, and OCR parsing are not part of these APIs.

Attachments

Use POST /mailbox/attachments:upload for binary files up to 7.5 MB. Send the raw bytes in the request body, then pass the returned blob_id to POST /mailbox/messages/send. Final outbound messages, including bodies, headers, and encoded attachments, must fit inside the 25 MB raw message limit.
curl -X POST "https://app.sendmux.ai/api/v1/mailbox/attachments:upload?filename=invoice.pdf" \
  -H "Authorization: Bearer smx_mbx_your_key_here" \
  -H "Content-Type: application/pdf" \
  --data-binary "@invoice.pdf"
{
  "ok": true,
  "data": {
    "blob_id": "blob_123",
    "filename": "invoice.pdf",
    "content_type": "application/pdf",
    "size_bytes": 12345
  },
  "meta": {
    "request_id": "req_clxxxxxxxxxxxxxxxxxxxxxxxxx"
  }
}
Then send the uploaded attachment by ID:
curl -X POST https://app.sendmux.ai/api/v1/mailbox/messages/send \
  -H "Authorization: Bearer smx_mbx_your_key_here" \
  -H "Content-Type: application/json" \
  -d '{
    "to": [{ "email": "customer@example.com" }],
    "subject": "Invoice",
    "text_body": "Attached is your invoice.",
    "attachments": [
      {
        "filename": "invoice.pdf",
        "content_type": "application/pdf",
        "blob_id": "blob_123"
      }
    ]
  }'
Small inline base64 attachments are still supported on messages/send, but the upload endpoint avoids large JSON request bodies. Attachment downloads support byte ranges:
curl "https://app.sendmux.ai/api/v1/mailbox/messages/msg_123/attachments/att_123" \
  -H "Authorization: Bearer smx_mbx_your_key_here" \
  -H "Range: bytes=0-1048575" \
  --output invoice.part

Sync APIs

Use sync endpoints to poll for changes with state tokens returned by earlier responses, or open an event stream when a client needs live updates.

Event stream

GET /mailbox/events streams mailbox events as Server-Sent Events. Use it for agents, CLIs, MCP servers, and SDKs that need to react when inbound mail arrives. Use webhooks instead when a backend service should receive signed event POSTs without keeping a live connection open.
curl -N "https://app.sendmux.ai/api/v1/mailbox/events?event_types=message.received,message.received.spam" \
  -H "Authorization: Bearer smx_mbx_your_key_here"
id: evt_clxxxxxxxxxxxxxxxxxxxxxxxxx
event: message.received
data: {"event_type":"message.received","mailbox_id":"mbx_clxxxxxxxxxxxxxxxxxxxxxxxxx","message_id":"msg_123","message":{"id":"msg_123","subject":"New reply","preview":"Thanks for the update.","body":{"text":"Thanks for the update.","html":null,"is_truncated":false,"max_bytes":16384}}}
Each received-message event includes subject, participants, preview, attachment metadata, and a capped body snapshot. Use the message and attachment endpoints when you need full content or attachment bytes. To resume after a disconnect, pass the last SSE id as the Last-Event-ID header or the last_event_id query parameter. If the stream sends sync_required, call GET /mailbox/changes before reopening the stream. Optional query parameters:
ParameterPurpose
event_typesComma-separated list of message.received and message.received.spam.
pingHeartbeat interval in seconds, from 10 to 300.
close_afterClose the stream after 30 to 3600 seconds. Omit for a long-lived stream.
last_event_idReplay events after a prior SSE event ID.

Message query changes

GET /mailbox/messages/query-changes tracks how a filtered message list has changed since a prior query_state. Omit since_query_state to get the current query state for a filter without a change list.
curl "https://app.sendmux.ai/api/v1/mailbox/messages/query-changes?since_query_state=message_query_state_token&q=invoice&limit=100" \
  -H "Authorization: Bearer smx_mbx_your_key_here"
{
  "ok": true,
  "data": {
    "old_query_state": "message_query_state_token",
    "new_query_state": "message_query_state_token_2",
    "has_more": false,
    "removed": ["msg_old"],
    "added": [{ "id": "msg_new", "index": 0 }],
    "total": null
  },
  "meta": {
    "request_id": "req_clxxxxxxxxxxxxxxxxxxxxxxxxx"
  }
}

Folder changes

GET /mailbox/folders/changes tracks folder object changes. Omit since_state to get the current folder state without a change list.
curl "https://app.sendmux.ai/api/v1/mailbox/folders/changes?since_state=folder_state_token" \
  -H "Authorization: Bearer smx_mbx_your_key_here"

Folder query changes

GET /mailbox/folders/query-changes tracks folder-list ordering changes. Omit since_query_state to get the current folder query state.
curl "https://app.sendmux.ai/api/v1/mailbox/folders/query-changes?since_query_state=folder_query_state_token" \
  -H "Authorization: Bearer smx_mbx_your_key_here"

Typed mailbox changes

GET /mailbox/changes keeps the legacy message-only response when types is omitted. Pass a comma-separated types list to receive a typed state map.
curl "https://app.sendmux.ai/api/v1/mailbox/changes?types=messages,folders,threads,submissions,identities,quotas" \
  -H "Authorization: Bearer smx_mbx_your_key_here"
{
  "ok": true,
  "data": {
    "types": {
      "messages": {
        "old_state": "message_state_token",
        "new_state": "message_state_token_2",
        "has_more": false,
        "created": ["msg_789"],
        "updated": [],
        "destroyed": []
      },
      "folders": {
        "old_state": "folder_state_token",
        "new_state": "folder_state_token_2",
        "has_more": false,
        "created": [],
        "updated": ["inbox"],
        "destroyed": []
      },
      "threads": {
        "old_state": "thread_state_token",
        "new_state": "thread_state_token_2",
        "has_more": false,
        "created": [],
        "updated": ["thr_123"],
        "destroyed": []
      },
      "submissions": {
        "old_state": "submission_state_token",
        "new_state": "submission_state_token_2",
        "has_more": false,
        "created": [],
        "updated": ["sub_123"],
        "destroyed": []
      },
      "identities": {
        "old_state": "identity_state_token",
        "new_state": "identity_state_token_2",
        "has_more": false,
        "created": [],
        "updated": ["id_123"],
        "destroyed": []
      },
      "quotas": {
        "old_state": "quota_state_token",
        "new_state": "quota_state_token_2",
        "has_more": false,
        "created": [],
        "updated": ["quota_123"],
        "destroyed": []
      }
    }
  },
  "meta": {
    "request_id": "req_clxxxxxxxxxxxxxxxxxxxxxxxxx"
  }
}
Supported types values are messages, folders, threads, submissions, identities, and quotas.

Response format

The Mailbox API uses the same envelope as the Management API.

Success

{
  "ok": true,
  "data": {
    "id": "mbx_clxxxxxxxxxxxxxxxxxxxxxxxxx",
    "email": "agent@example.com"
  },
  "meta": {
    "request_id": "req_clxxxxxxxxxxxxxxxxxxxxxxxxx"
  }
}

Error

{
  "ok": false,
  "error": {
    "code": "not_found",
    "message": "Mailbox not found.",
    "doc_url": "https://docs.sendmux.ai/api-reference/errors#not_found",
    "retryable": false
  },
  "meta": {
    "request_id": "req_clxxxxxxxxxxxxxxxxxxxxxxxxx"
  }
}
Every response includes an X-Request-Id header matching meta.request_id. Include that value when contacting support.

Rate limiting

Mailbox API keys are rate-limited to 1800 requests per minute. Rate limit headers are included on responses:
X-RateLimit-Limit: 1800
X-RateLimit-Remaining: 1794
X-RateLimit-Reset: 1679313700
When the limit is exceeded, the API returns 429 rate_limit_exceeded with a Retry-After header.

Conventions

  • snake_case fields in JSON request and response bodies
  • UTC ISO 8601 timestamps in RFC 3339 format: 2026-03-19T10:30:00Z
  • Opaque IDs only for mailbox, message, folder, and attachment resources
  • Cache-Control: no-store on authenticated responses
  • Weak ETag headers on single-resource GETs where supported
  • Header-based idempotency for retriable POST requests where supported

OpenAPI specification

Mailbox API endpoints are included in the app API specification:
https://app.sendmux.ai/api/v1/openapi.json