Skip to main content

Messages API

The Messages API provides comprehensive access to email messages across all connected accounts. You can list, read, search, update, move, and delete messages programmatically.

Overview

The Messages API allows you to:

  • List messages from any mailbox with filtering and pagination
  • Read message content, headers, and metadata
  • Search messages using advanced query syntax
  • Update message flags (read/unread, flagged, etc.)
  • Move messages between mailboxes
  • Delete messages permanently or move to trash
  • Download attachments and message source

Message Object Structure

{
"id": "AAAABAABNc",
"uid": 12345,
"path": "INBOX",
"emailId": "1234567890abcdef",
"threadId": "thread_abc123",
"date": "2025-01-15T10:30:00.000Z",
"flags": ["\\Seen"],
"unseen": false,
"flagged": 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": "text_id_123",
"encodedSize": 1234
},
"html": ["html_id_456"],
"attachments": [
{
"id": "attachment_789",
"contentType": "application/pdf",
"encodedSize": 52341,
"filename": "document.pdf"
}
]
}

Message IDs Explained

EmailEngine uses several types of IDs:

  • id: EmailEngine's internal message ID (used in API calls)
  • uid: IMAP UID (server-specific, unique within mailbox)
  • emailId: RFC 8474 Email ID (unique across mailboxes)
  • threadId: RFC 8474 Thread ID (groups related messages)
  • messageId: RFC 5322 Message-ID header

Learn more about IDs →

Common Operations

1. List Messages

Retrieve messages from a mailbox with filtering and pagination.

Endpoint: GET /v1/account/:account/messages

Path Parameters:

ParameterDescription
accountAccount identifier

Query Parameters:

ParameterTypeDescription
pathstringMailbox path (required)
pagenumberPage number (0-indexed, default 0). Deprecated; use cursor instead
pageSizenumberMessages per page (default 20, max 1000)
cursorstringPaging cursor from nextPageCursor or prevPageCursor

To filter messages by flags (unseen, flagged, etc.), use the Search endpoint instead.

Examples:

curl "http://localhost:3000/v1/account/user@example.com/messages?path=INBOX&pageSize=50" \
-H "Authorization: Bearer YOUR_ACCESS_TOKEN"

Response:

{
"total": 128,
"page": 0,
"pages": 3,
"messages": [
{
"id": "AAAABAABNc",
"uid": 12345,
"path": "INBOX",
"subject": "Meeting Tomorrow",
"from": {
"name": "John Doe",
"address": "john@example.com"
},
"date": "2025-01-15T10:30:00.000Z",
"unseen": true,
"size": 15234
}
]
}

Use Cases:

  • Display inbox messages in application UI
  • Process unread messages for automation
  • Export messages for archival

Detailed API reference →


2. Get Message Details

Retrieve complete message information including body and attachments.

Endpoint: GET /v1/account/:account/message/:message

Path Parameters:

ParameterDescription
accountAccount identifier
messageMessage ID

Query Parameters:

ParameterTypeDescription
maxBytesnumberMaximum bytes to retrieve for text/html
textTypestringWhich text format to return: 'html', 'plain', or '*' for all. By default text content is not returned

Examples:

curl "http://localhost:3000/v1/account/user@example.com/message/AAAABAABNc" \
-H "Authorization: Bearer YOUR_ACCESS_TOKEN"

Response:

{
"id": "AAAABAABNc",
"uid": 12345,
"path": "INBOX",
"subject": "Meeting Tomorrow",
"from": {
"name": "John Doe",
"address": "john@example.com"
},
"to": [
{
"name": "Jane Smith",
"address": "jane@example.com"
}
],
"date": "2025-01-15T10:30:00.000Z",
"text": {
"plain": "Let's meet tomorrow at 10 AM.",
"html": "<p>Let's meet tomorrow at 10 AM.</p>"
},
"headers": {
"content-type": ["text/plain; charset=utf-8"],
"date": ["Wed, 15 Jan 2025 10:30:00 +0000"]
},
"attachments": []
}

Use Cases:

  • Display full message in email client
  • Extract message content for processing
  • Download attachments

Detailed API reference →


3. Get Message Source

Retrieve raw RFC822 message source.

Endpoint: GET /v1/account/:account/message/:message/source

Examples:

curl "http://localhost:3000/v1/account/user@example.com/message/AAAABAABNc/source" \
-H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
-o message.eml

Use Cases:

  • Export messages in EML format
  • Parse with custom email parser
  • Forensic analysis
  • Message backup

Detailed API reference →


4. Update Message Flags

Change message flags like read/unread, flagged, etc.

Endpoint: PUT /v1/account/:account/message/:message

Request Body:

{
"flags": {
"add": ["\\Seen", "\\Flagged"],
"delete": ["\\Draft"]
}
}

Standard IMAP Flags:

FlagDescription
\\SeenMessage has been read
\\AnsweredMessage has been replied to
\\FlaggedMessage is flagged/starred
\\DeletedMessage is marked for deletion
\\DraftMessage is a draft

Examples:

curl -X PUT "http://localhost:3000/v1/account/user@example.com/message/AAAABAABNc" \
-H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"flags": {
"add": ["\\Seen"]
}
}'

Use Cases:

  • Mark messages as read/unread
  • Star/flag important messages
  • Track replied messages
  • Implement custom workflow flags

Detailed API reference →


5. Move Message

Move a message to a different mailbox.

Endpoint: PUT /v1/account/:account/message/:message/move

Request Body:

{
"path": "Archive"
}

Examples:

curl -X PUT "http://localhost:3000/v1/account/user@example.com/message/AAAABAABNc/move" \
-H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
-H "Content-Type: application/json" \
-d '{"path": "Archive"}'

Response:

{
"path": "Archive",
"id": "AAAABQABNd",
"uid": 12346
}

Note: The id and uid fields are only included if the server provides them. Moving a message may change its ID since it's technically a new message in the destination mailbox.

Use Cases:

  • Archive processed messages
  • Move spam to Spam folder
  • Organize messages into folders
  • Implement auto-filing rules

Detailed API reference →


6. Delete Message

Delete a message permanently or move to trash.

Endpoint: DELETE /v1/account/:account/message/:message

Query Parameters:

ParameterTypeDescription
forcebooleanIf true, delete message even if not in Trash. Not supported for Gmail API accounts

Examples:

# Delete (moves to Trash, or deletes if already in Trash)
curl -X DELETE "http://localhost:3000/v1/account/user@example.com/message/AAAABAABNc" \
-H "Authorization: Bearer YOUR_ACCESS_TOKEN"

# Force delete (delete even if not in Trash)
curl -X DELETE "http://localhost:3000/v1/account/user@example.com/message/AAAABAABNc?force=true" \
-H "Authorization: Bearer YOUR_ACCESS_TOKEN"

Use Cases:

  • Delete spam messages
  • Clean up after processing
  • User-initiated deletion

Detailed API reference →


7. Search Messages

Search messages using advanced query syntax.

Endpoint: POST /v1/account/:account/search

Query Parameters:

ParameterTypeDescription
pathstringMailbox path (default: INBOX)
pagenumberPage number (0-indexed, default 0)
pageSizenumberMessages per page (default 20, max 1000)
cursorstringPaging cursor from nextPageCursor or prevPageCursor

Request Body:

{
"search": {
"from": "sender@example.com",
"subject": "invoice",
"since": "2025-01-01T00:00:00.000Z"
}
}

Search Criteria:

FieldTypeDescription
fromstringFrom address contains
tostringTo address contains
subjectstringSubject contains
bodystringBody text contains
sincedateMessages received after date
beforedateMessages received before date
sentSincedateMessages sent after date
sentBeforedateMessages sent before date
unseenbooleanUnread messages only
flaggedbooleanFlagged messages only
largernumberMessages larger than size in bytes
smallernumberMessages smaller than size in bytes

Examples:

curl -X POST "http://localhost:3000/v1/account/user@example.com/search?path=INBOX" \
-H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"search": {
"subject": "invoice",
"since": "2025-01-01T00:00:00.000Z"
}
}'

Use Cases:

  • Find messages from specific sender
  • Search for messages with attachments
  • Filter by date range
  • Full-text search across messages

Detailed API reference →


Message Object Reference

Complete Field Reference

FieldTypeDescription
idstringEmailEngine message ID
uidnumberIMAP UID
pathstringMailbox path
emailIdstringRFC 8474 Email ID
threadIdstringRFC 8474 Thread ID
datestringISO date string
flagsarrayIMAP flags
unseenbooleanTrue if unread
flaggedbooleanTrue if flagged
answeredbooleanTrue if replied
draftbooleanTrue if draft
sizenumberMessage size in bytes
subjectstringSubject line
fromobjectSender address
toarrayRecipient addresses
ccarrayCC addresses
bccarrayBCC addresses
replyToarrayReply-To addresses
messageIdstringRFC 5322 Message-ID
inReplyTostringMessage-ID being replied to
referencesarrayThread reference IDs
textobjectPlain text content
htmlarrayHTML content parts
attachmentsarrayAttachment metadata

Nested Structures

Address Object:

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

Text Object:

{
"id": "text_id_123",
"encodedSize": 1234,
"plain": "Message text content",
"html": "<p>Message HTML content</p>"
}

Attachment Object:

{
"id": "attachment_789",
"contentType": "application/pdf",
"disposition": "attachment",
"filename": "document.pdf",
"encodedSize": 52341,
"embedded": false,
"inline": false
}

Query Parameters

List Messages Filters:

// Unread messages in INBOX
url = "/v1/account/" + account + "/messages?path=INBOX&unseen=true"

// Flagged messages
url = "/v1/account/" + account + "/messages?flagged=true"

// Specific mailbox
url = "/v1/account/" + account + "/messages?path=Archive"

// Pagination
url = "/v1/account/" + account + "/messages?path=INBOX&page=2&pageSize=100"

Search Syntax

Advanced Search Examples:

// Messages from domain
searchCriteria = {
search: {
from: "@example.com"
}
}

// Date range
searchCriteria = {
search: {
since: "2025-01-01T00:00:00.000Z",
before: "2025-02-01T00:00:00.000Z"
}
}

// Multiple criteria
searchCriteria = {
search: {
from: "client@example.com",
subject: "invoice",
unseen: true,
larger: 100000
}
}

// Body text search
searchCriteria = {
search: {
body: "urgent payment"
}
}

Common Patterns

Pagination

Fetch all messages across pages:

// Pseudo code: Fetch all messages with pagination
function fetchAllMessages(account, path = "INBOX") {
page = 0
allMessages = []
hasMore = true

while (hasMore) {
// Build URL with pagination
url = "http://localhost:3000/v1/account/" + URL_ENCODE(account) +
"/messages?path=" + path + "&page=" + page + "&pageSize=100"

// Make request
response = HTTP_GET(url, {
headers: { "Authorization": "Bearer YOUR_ACCESS_TOKEN" }
})

// Parse response
data = PARSE_JSON(response.body)
allMessages = allMessages + data.messages

// Check if more pages exist
hasMore = (page < data.pages - 1)
page = page + 1
}

return allMessages
}

Real-time Sync with Webhooks

Instead of polling, use webhooks:

// Step 1: Setup webhook for new messages
HTTP_POST("http://localhost:3000/v1/settings", {
headers: {
"Authorization": "Bearer YOUR_ACCESS_TOKEN",
"Content-Type": "application/json"
},
body: {
webhooks: "https://your-app.com/webhook",
webhookEvents: ["messageNew", "messageDeleted"]
}
})

// Step 2: Handle webhook in your application
// This is a webhook endpoint handler (pseudo code for web server)
function handleWebhook(request, response) {
event = PARSE_JSON(request.body)

if (event.event == "messageNew") {
PRINT("New message: " + event.data.subject)
// Process new message
processNewMessage(event.data)
}

if (event.event == "messageDeleted") {
PRINT("Message deleted: " + event.data.id)
// Handle deletion
}

// Respond with success
response.send({ success: true })
}

Bulk Operations

Update multiple messages:

// Pseudo code: Mark all unread messages as read
function markAllAsRead(account, path = "INBOX") {
// Step 1: Get all unread messages
url = "http://localhost:3000/v1/account/" + URL_ENCODE(account) +
"/messages?path=" + path + "&unseen=true"

response = HTTP_GET(url, {
headers: { "Authorization": "Bearer YOUR_ACCESS_TOKEN" }
})

messages = PARSE_JSON(response.body).messages

// Step 2: Update each message
for each msg in messages {
HTTP_PUT(
"http://localhost:3000/v1/account/" + URL_ENCODE(account) + "/message/" + msg.id,
{
headers: {
"Authorization": "Bearer YOUR_ACCESS_TOKEN",
"Content-Type": "application/json"
},
body: {
flags: { add: ["\\Seen"] }
}
}
)
}

PRINT("Marked " + LENGTH(messages) + " messages as read")
}

Attachment Handling

Download all attachments from a message:

// Pseudo code: Download all attachments from a message
function downloadAttachments(account, messageId) {
// Step 1: Get message details
msgUrl = "http://localhost:3000/v1/account/" + URL_ENCODE(account) +
"/message/" + messageId

msgResponse = HTTP_GET(msgUrl, {
headers: { "Authorization": "Bearer YOUR_ACCESS_TOKEN" }
})

message = PARSE_JSON(msgResponse.body)

// Step 2: Download each attachment
for each attachment in message.attachments {
attUrl = "http://localhost:3000/v1/account/" + URL_ENCODE(account) +
"/attachment/" + attachment.id

attResponse = HTTP_GET(attUrl, {
headers: { "Authorization": "Bearer YOUR_ACCESS_TOKEN" }
})

// Save to file or process
fileData = attResponse.body
SAVE_TO_FILE(attachment.filename, fileData)

PRINT("Downloaded: " + attachment.filename)
}
}