Skip to main content

Messages API

This page is the reference for the message resource: the fields a message carries in a listing and in its details, the endpoints that read and change messages, and the conventions those endpoints share. How to use them, with examples and the differences between IMAP, Gmail API and MS Graph accounts, is on Message Operations; the full search grammar is on Searching Messages; each endpoint's complete schema is on its generated page, linked below.

Endpoints​

OperationEndpointPermission
List messages in a folderGET /v1/account/{account}/messagesread / message
Search for messagesPOST /v1/account/{account}/searchread / message
Get message informationGET /v1/account/{account}/message/{message}read / message
Retrieve message textGET /v1/account/{account}/text/{text}read / message
Download attachmentGET /v1/account/{account}/attachment/{attachment}read / message
Download raw messageGET /v1/account/{account}/message/{message}/sourceread / message
Upload messagePOST /v1/account/{account}/messagewrite / message
Update messagePUT /v1/account/{account}/message/{message}write / message
Move a messagePUT /v1/account/{account}/message/{message}/movewrite / message
Delete messageDELETE /v1/account/{account}/message/{message}destructive / message
Update messagesPUT /v1/account/{account}/messageswrite / message
Move messagesPUT /v1/account/{account}/messages/movewrite / message
Delete messagesPUT /v1/account/{account}/messages/deletedestructive / message

The permission column is the x-ee-action and x-ee-group pair each operation publishes in the OpenAPI document; a token narrowed with a permissions record has to allow both. See Access Tokens. Sending is a separate resource, documented on the Sending API.

The Message Object​

A listing entry and the message details share one shape; the details add the headers, the Sender and Bcc addresses and the bounce fields. Text content is included only when asked for.

{
"id": "AAAABAABNc",
"uid": 12345,
"emailId": "1234567890abcdef",
"threadId": "thread_abc123",
"path": "INBOX",
"date": "2025-01-15T10:30:00.000Z",
"flags": ["\\Seen"],
"unseen": false,
"flagged": false,
"answered": false,
"draft": false,
"size": 15234,
"subject": "Meeting Tomorrow",
"from": {
"name": "John Doe",
"address": "john@example.com"
},
"to": [
{
"name": "Jane Smith",
"address": "jane@example.com"
}
],
"messageId": "<abc123@example.com>",
"inReplyTo": "<xyz789@example.com>",
"text": {
"id": "AAAAAQAACnAWkeM",
"encodedSize": {
"plain": 1013,
"html": 3487
}
},
"attachments": [
{
"id": "AAAAAQAACnAy",
"contentType": "application/pdf",
"encodedSize": 52341,
"embedded": false,
"inline": false,
"filename": "document.pdf"
}
]
}

Fields​

FieldTypeDescription
idstringEmailEngine message ID. On IMAP accounts it encodes the folder and UID, so it changes when the message moves
uidnumberIMAP UID. IMAP accounts only
pathstringMailbox path. In a listing, present when listing \All or another virtual folder; in message details, not returned for Gmail API accounts
emailIdstringRFC 8474 Email ID, when the server supports one (Gmail, MS Graph, IMAP servers with OBJECTID)
threadIdstringRFC 8474 Thread ID, when the server supports one
datestringISO date string
flagsarrayIMAP flags
unseenbooleanTrue if unread
flaggedbooleanTrue if flagged
answeredbooleanTrue if replied to (the \Answered flag). IMAP accounts only
draftbooleanTrue if draft
sizenumberMessage size in bytes. Not returned for MS Graph accounts
subjectstringSubject line
fromobjectSender address
senderobjectThe Sender header, when it differs from From. Message details only
toarrayRecipient addresses
ccarrayCC addresses
bccarrayBCC addresses. Message details only
replyToarrayReply-To addresses
messageIdstringRFC 5322 Message-ID
inReplyTostringMessage-ID being replied to
textobjectText content metadata; text.plain and text.html are included when the textType parameter asks for them
headersobjectEvery header of the message, keyed in lower case, each value an array because a header can repeat. Message details only
labelsarrayGmail labels, on Gmail accounts; Outlook categories, on MS Graph accounts. Absent when there are none
previewstringA short plaintext preview, on Gmail API and MS Graph accounts
categorystringGmail inbox tab (primary, social, promotions, updates, forums). Gmail API accounts only
specialUsestringThe special-use role of the folder the message is in, such as \Sent. Message details on IMAP accounts only
messageSpecialUsestringThe special-use role of the message itself, such as \Sent or \Junk
isAutoReplybooleanTrue when the message looks like an automatic reply, see Tracking Email Replies
isBouncebooleanTrue when the message is a delivery failure report. Decided when the message is fetched, for messages in the Inbox only; a delivery or delay notification does not count. Message details only. Since 2.81.2
relatedMessageIdstringThe Message-ID of the message that bounced. Set together with isBounce
attachmentsarrayAttachment metadata

Releases before 2.81.2 attached a bounces array to messages an IMAP account had sent, listing the bounces EmailEngine had matched to them. The array and the store behind it were removed in 2.81.2; a bounce is reported once, as a messageBounce webhook, and the bounce message itself carries isBounce. Message IDs Explained covers how id, uid, emailId and messageId relate.

Nested Structures​

Address Object:

{
"name": "John Doe",
"address": "john@example.com"
}

Text Object:

{
"id": "AAAAAQAACnAWkeM",
"encodedSize": {
"plain": 1013,
"html": 3487
},
"plain": "Message text content",
"html": "<p>Message HTML content</p>",
"hasMore": false,
"webSafe": false
}

encodedSize reports the size of each MIME part separately, before decoding. plain and html are present only when textType asked for them, hasMore says whether maxBytes truncated the result, and webSafe is set when webSafeHtml was requested and html has been processed for display. text.id is what GET /v1/account/{account}/text/{text} takes to fetch the body on its own.

Attachment Object:

{
"id": "AAAAAQAACnAy",
"contentType": "application/pdf",
"filename": "document.pdf",
"encodedSize": 52341,
"embedded": false,
"inline": false,
"encodedInMessage": false,
"contentId": "<part1.abc@example.com>",
"method": "REQUEST"
}

encodedSize is the size as stored in the message, base64 encoded, so the decoded file is roughly three quarters of it. embedded marks a part of a multipart/related body, inline a part meant to be shown in place rather than listed, encodedInMessage a part that belongs to an attached message/rfc822 rather than to the message itself, and contentId is what a cid: URL in the HTML refers to. method is present on iCalendar attachments and carries the calendar method (REQUEST, REPLY, CANCEL). The attachment endpoint returns the decoded file with its own content type, not a JSON wrapper; see Attachments.

Request and Response Conventions​

GET /v1/account/{account}/messages and POST /v1/account/{account}/search take the folder in the path query parameter, which is required on both. Special-use names such as \Sent resolve to the folder that carries that role, and \All selects every message on Gmail and MS Graph accounts. The listing accepts no other filter; an unknown query parameter answers 400. To select by flag, sender, date or any other criterion, use the search endpoint, whose body is a search object and whose path became required in 2.82.0 when the Document Store, which had allowed an account-wide search, was removed.

Both answer the same shape, newest first:

{
"total": 128,
"page": 0,
"pages": 3,
"nextPageCursor": "eyJhIjoxfQ",
"prevPageCursor": null,
"messages": []
}

Paging takes pageSize (default 20, maximum 1000) and either cursor, from nextPageCursor or prevPageCursor, or a zero-based page. cursor works on every account type and is the only way to page a Gmail API account, which rejects a page above 0 with 400 (InvalidInput); when both are sent the cursor wins. total and pages are exact for IMAP accounts, approximate for Gmail API accounts, and can be missing for MS Graph accounts. On MS Graph, useOutlookSearch=true runs the query through Graph's $search instead of $filter, which reaches more fields but returns at most 1,000 results, in relevance order, with no total.

Message details and text​

GET /v1/account/{account}/message/{message} returns no body unless textType is plain, html or *. maxBytes caps each body and sets text.hasMore; webSafeHtml=true returns the HTML processed for display, which also turns on preProcessHtml and embedAttachedImages unless embedAttachedImages=false is sent explicitly; markAsSeen=true adds the \Seen flag while fetching. GET /v1/account/{account}/text/{text} takes textType, maxBytes and webSafeHtml with the text.id from the message. See Web-Safe HTML.

Flags and labels​

PUT /v1/account/{account}/message/{message} takes flags with add, delete and set; set replaces the whole list and makes add and delete ignored. labels takes the same keys for Gmail labels and Outlook categories, with the values each backend expects described under Working with Gmail Labels and Outlook Categories. An IMAP account answers each operation with true or false, for example {"flags": {"add": true}}; Gmail API and MS Graph accounts echo the requested values and add result, the message's list after the update.

Moves and deletes​

A move takes path, which accepts the aliases \Inbox, \Sent, \Drafts, \Trash and \Junk, and answers the destination path with the message's new id and, on IMAP accounts, its new uid when the server reported them. On a Gmail API account a move is a label change, and source names the label to remove.

A delete moves the message to Trash by default and answers {"deleted": false, "moved": {"destination": ..., "message": ...}} on an IMAP account, or {"deleted": true} once the message is gone for good. Gmail API and MS Graph accounts report deleted: true for a move to Trash as well, so deleted: false is the only reliable signal that a message was moved rather than removed. force=true deletes without the Trash step on IMAP and MS Graph accounts and has no effect on Gmail API accounts. The bulk endpoints answer moved.idMap, pairs of source and destination IDs, on IMAP accounts and moved.emailIds on Gmail API and MS Graph accounts; a Graph bulk delete with force=true lists the removed messages under deletedMessages.emailIds.

Bulk actions​

PUT /v1/account/{account}/messages, .../messages/move and .../messages/delete take the folder in the path query parameter and the same search object as the search endpoint in the body, and apply one change to every match. search is required, but {} is valid and selects the whole folder. On Gmail API and MS Graph accounts search.emailIds acts on the listed emailId values and every other criterion is ignored; IMAP accounts ignore emailIds.

Uploads​

POST /v1/account/{account}/message appends a message to a folder, either from raw (a base64-encoded RFC 822 message) or from the structured fields from, to, cc, bcc, subject, text, html, attachments, messageId and headers. path is required; flags and internalDate set the stored flags and date, and reference turns the upload into a reply or forward of a stored message with the threading headers derived from it. The response carries the new id, path and messageId, plus uid, uidValidity and seq on IMAP accounts, and reference.success when a reference was given. Behavior per backend is on Message Operations.

See Also​