Inbox
Read and manage inbound emails received via IMAP.
Requires an IMAP account configured in the dashboard. Messages are polled automatically and made available via API. Supports read/flag toggling, folder management, and attachment downloads.
Endpoints
| Method | Path | Permission |
|---|---|---|
GET | email.inbox_read | |
GET | email.inbox_read | |
PATCH | email.inbox_read | |
PATCH | email.inbox_read | |
PATCH | email.inbox_read | |
GET | email.inbox_read | |
DELETE | email.inbox_reply |
List Inbox Messages
GET /api/v1/inbox
Request
Response
{
"success": true,
"data": [
{
"id": "inbox-uuid-1",
"messageId": "<CAF%3D2026031809%40mail.example.com>",
"fromEmail": "client@example.com",
"fromName": "Marie Dupont",
"replyToEmail": null,
"toEmail": "contact@yourcompany.com",
"subject": "Re: Invoice #2024-001",
"isRead": false,
"imapSeen": false,
"isFlagged": true,
"imapFlagged": true,
"hasAttachments": true,
"folder": "INBOX",
"receivedAt": "2026-03-18T09:45:00.000Z",
"createdAt": "2026-03-18T09:46:02.113Z",
"_count": { "attachments": 2 }
},
{
"id": "inbox-uuid-2",
"messageId": "<renewal-8821%40vendor.com>",
"fromEmail": "support@vendor.com",
"fromName": null,
"replyToEmail": "billing@vendor.com",
"toEmail": "contact@yourcompany.com",
"subject": "Your subscription has been renewed",
"isRead": false,
"imapSeen": true,
"isFlagged": false,
"imapFlagged": false,
"hasAttachments": false,
"folder": "INBOX",
"receivedAt": "2026-03-18T08:30:00.000Z",
"createdAt": "2026-03-18T08:31:44.007Z",
"_count": { "attachments": 0 }
}
],
"meta": { "page": 1, "per_page": 20, "total": 87, "total_pages": 5 }
}Get Inbox Message
GET /api/v1/inbox/:id
Returns the full message, including htmlBody, textBody and attachment metadata. The list endpoint omits all three.
Request
Response
{
"success": true,
"data": {
"id": "inbox-uuid-1",
"messageId": "<CAF%3D2026031809%40mail.example.com>",
"fromEmail": "client@example.com",
"fromName": "Marie Dupont",
"replyToEmail": null,
"toEmail": "contact@yourcompany.com",
"subject": "Re: Invoice #2024-001",
"htmlBody": "<p>Thank you for sending the invoice.</p>",
"textBody": "Thank you for sending the invoice.",
"isRead": false,
"imapSeen": false,
"isFlagged": true,
"imapFlagged": true,
"hasAttachments": true,
"folder": "INBOX",
"receivedAt": "2026-03-18T09:45:00.000Z",
"createdAt": "2026-03-18T09:46:02.113Z",
"attachments": [
{
"id": "attachment-uuid-1",
"filename": "invoice-2024-001.pdf",
"contentType": "application/pdf",
"sizeBytes": 84213
}
]
}
}Mark as Read
PATCH /api/v1/inbox/:id/read
Request
Response
{
"success": true,
"data": {
"id": "inbox-uuid-1",
"isRead": true,
"imapSeen": false
}
}Toggle Flagged Status
PATCH /api/v1/inbox/:id/flag
isFlagged is Sendy's own state and takes effect immediately — the IMAP poller never overwrites it. The matching \Flagged flag is pushed to the mail server in the background, so imapFlagged in the response reflects the server state before that push and may lag by one poll. Same contract as isRead / imapSeen.
Request
Response
{
"success": true,
"data": {
"id": "inbox-uuid-1",
"isFlagged": true,
"imapFlagged": false
}
}Move to Folder
PATCH /api/v1/inbox/:id/move
Moves the message on the IMAP server, then records the new folder. The move assigns a new UID, returned as imapUid. Moving a message to the folder it is already in is a no-op and returns without imapUid.
Request
Response
{
"success": true,
"data": {
"id": "inbox-uuid-1",
"folder": "Archive",
"imapUid": 4212
}
}Download Attachment
GET /api/v1/inbox/:id/attachments/:attachmentId
Returns the raw file, not JSON — Content-Type, Content-Disposition and Content-Length come from the stored attachment. Get the attachment ids from GET /api/v1/inbox/:id. Errors are still JSON.
Request
Response headers
Content-Type: application/pdf
Content-Disposition: attachment; filename="invoice-2024-001.pdf"
Content-Length: 84213Delete Inbox Message
DELETE /api/v1/inbox/:id
The only inbox endpoint requiring email.inbox_reply — every other one needs email.inbox_read. The message is soft-deleted in Sendy and disappears from the list; the deletion is also pushed to the IMAP server in the background, so a mail-server failure leaves the message hidden in Sendy but still present in the mailbox.
Request
Response
{
"success": true,
"data": {
"id": "inbox-uuid-1",
"deleted": true
}
}