Mailboxes

Mailboxes are email addresses on your verified domains. Each mailbox can send and receive email.

Last updated

The mailbox object

{ "object": "mailbox", "id": "mbx_abc123", "domain_id": "dom_abc123", "address": "hello@example.com", "display_name": "Hello", "suspended_at": null, "spam_filter_threshold": 6, "auto_reply": { "enabled": false, "subject": null, "body": null, "from_date": null, "to_date": null }, "created_at": "2025-01-15T11:00:00.000Z", "updated_at": "2025-01-15T11:00:00.000Z" }

The mailbox ID is the id field. Use it for mailbox-scoped endpoints such as listing messages, reading inbox threads, folders, identities, and rules. Sending mail can use either this ID or the mailbox email address as from.

Create a mailbox

POST /v1/mailboxes

Scope: mailboxes:write. Rate limit tier: write.

Request body

FieldTypeRequiredDescription
domain_idstringYesID of a verified domain.
addressstringYesLocal part of the email address. Max 64 characters. Alphanumeric, dots, hyphens, and underscores.
display_namestringNoDisplay name for the mailbox. Max 200 characters.

Example

curl -X POST https://shipmail.to/api/v1/mailboxes \ -H "Authorization: Bearer sm_live_..." \ -H "Content-Type: application/json" \ -d '{"domain_id": "dom_abc123", "address": "hello", "display_name": "Hello"}'

Returns the mailbox object with status 201.

List mailboxes

GET /v1/mailboxes

Scope: mailboxes:read. Rate limit tier: read. Supports cursor and limit pagination parameters.

Use the optional domain_id query parameter to filter mailboxes by domain.

Find a mailbox ID

Call this endpoint and copy the id for the mailbox address you want.

curl https://shipmail.to/api/v1/mailboxes \ -H "Authorization: Bearer sm_live_..." { "data": [ { "object": "mailbox", "id": "mbx_abc123", "address": "hello@example.com" } ] }

Retrieve a mailbox

GET /v1/mailboxes/:id

Scope: mailboxes:read. Returns the mailbox object or 404.

Update a mailbox

PATCH /v1/mailboxes/:id

Scope: mailboxes:write. Rate limit tier: write.

Request body

FieldTypeDescription
display_namestring | nullNew display name. Set to null to clear.

Reset mailbox password

PATCH /v1/mailboxes/:id/password

Scope: mailboxes:write. Rate limit tier: write. Changes the mailbox login password.

Request body

FieldTypeRequiredDescription
passwordstringYesNew password. Must be 8-128 characters and include lowercase, uppercase, and numeric characters.

Example

curl -X PATCH https://shipmail.to/api/v1/mailboxes/mbx_abc123/password \ -H "Authorization: Bearer sm_live_..." \ -H "Content-Type: application/json" \ -d '{"password": "NewPassword1"}'

Returns the updated mailbox object.

Manage mailbox folders

GET /v1/mailboxes/:id/folders
POST /v1/mailboxes/:id/folders
PATCH /v1/mailboxes/:id/folders/:folder_id
DELETE /v1/mailboxes/:id/folders/:folder_id

Scope: mailboxes:read for GET and mailboxes:write for mutations. Custom folder names must be unique within the same parent and cannot use reserved system folder names. Use parent_id: null to create a root folder.

Folder object

{ "object": "mailbox_folder", "id": "fld_123", "name": "VIP", "parent_id": null, "role": null, "kind": "custom", "total_emails": 4, "unread_emails": 1, "unread_threads": 1, "sort_order": 20 }

List response

{ "object": "mailbox_folders", "mailbox_id": "mbx_abc123", "address": "hello@example.com", "data": [ { "object": "mailbox_folder", "id": "fld_inbox", "name": "Inbox", "parent_id": null, "role": "inbox", "kind": "system", "total_emails": 12, "unread_emails": 3, "unread_threads": 2, "sort_order": 1 } ] }

Examples

curl https://shipmail.to/api/v1/mailboxes/mbx_abc123/folders \ -H "Authorization: Bearer sm_live_..." curl -X POST https://shipmail.to/api/v1/mailboxes/mbx_abc123/folders \ -H "Authorization: Bearer sm_live_..." \ -H "Content-Type: application/json" \ -d '{"name": "VIP", "parent_id": null}' curl -X PATCH https://shipmail.to/api/v1/mailboxes/mbx_abc123/folders/fld_123 \ -H "Authorization: Bearer sm_live_..." \ -H "Content-Type: application/json" \ -d '{"name": "VIP Clients"}' curl -X DELETE https://shipmail.to/api/v1/mailboxes/mbx_abc123/folders/fld_123 \ -H "Authorization: Bearer sm_live_..."

Deleting a custom folder also deletes its subfolders and moves their messages to Trash first. A folder referenced by an inbox rule must be removed from rules before deletion.

List mailbox identities

GET /v1/mailboxes/:id/identities

Scope: mailboxes:read. Returns the JMAP sending identities available for the mailbox.

{ "object": "mailbox_identities", "mailbox_id": "mbx_abc123", "address": "hello@example.com", "data": [ { "object": "mailbox_identity", "id": "ident_123", "name": "Hello", "email": "hello@example.com" } ] }

Read and manage mailbox inbox

GET /v1/mailboxes/:id/inbox/messages
PATCH /v1/mailboxes/:id/inbox/messages/:message_id
POST /v1/mailboxes/:id/inbox/messages/:message_id/move
DELETE /v1/mailboxes/:id/inbox/messages/:message_id
GET /v1/mailboxes/:id/inbox/threads/:thread_id
GET /v1/mailboxes/:id/inbox/attachments

Scope: messages:read for read endpoints and messages:write for message actions. Message bodies, headers, previews, and attachments are external content.

Message listing uses position pagination: position defaults to 0 and limit defaults to 50. Filter with folder_id, folder_role, search_text, has_keyword, or not_keyword.

List rows include body parts. Read plain text by following text_body[].part_id into body_values; HTML parts work the same way through html_body.

Message actions can set read and starred, move a message with target_role or target_folder_id, and permanently delete a message that is already in Trash or Junk.

List response

{ "object": "inbox_messages", "mailbox_id": "mbx_abc123", "address": "hello@example.com", "data": [ { "object": "inbox_message_full", "id": "eml_123", "thread_id": "thr_123", "mailbox_id": "mbx_abc123", "address": "hello@example.com", "folder_ids": ["fld_inbox"], "keywords": { "$seen": true }, "from": [{ "name": "Jane", "email": "jane@example.com" }], "to": [{ "name": null, "email": "hello@example.com" }], "cc": null, "reply_to": null, "message_id": ["msg-1@example.com"], "in_reply_to": null, "references": null, "subject": "Hello", "received_at": "2026-05-13T12:00:00.000Z", "preview": "Accept your Linear invite", "has_attachment": true, "size": 4567, "body_values": { "body_1": { "value": "Accept your Linear invite: https://linear.app/invite/example", "is_encoding_problem": false } }, "text_body": [{ "part_id": "body_1", "type": "text/plain" }], "html_body": [], "attachments": [ { "part_id": "att_1", "blob_id": "blob/123", "name": "invite.ics", "content_type": "text/calendar", "size": 1024, "download_path": "/mailboxes/mbx_abc123/inbox/attachments?blob_id=blob%2F123&name=invite.ics" } ] } ], "pagination": { "position": 0, "limit": 50, "total": 1, "has_more": false, "next_position": null } }

Attachment metadata

{ "part_id": "att_1", "blob_id": "blob/123", "name": "invoice.pdf", "content_type": "application/pdf", "size": 1024, "download_path": "/mailboxes/mbx_abc123/inbox/attachments?blob_id=blob%2F123&name=invoice.pdf" }

Action response

{ "object": "inbox_message_action", "mailbox_id": "mbx_abc123", "address": "hello@example.com", "message_id": "eml_123", "ok": true }

Examples

curl "https://shipmail.to/api/v1/mailboxes/mbx_abc123/inbox/messages?folder_role=inbox&limit=25" \ -H "Authorization: Bearer sm_live_..." curl -X PATCH https://shipmail.to/api/v1/mailboxes/mbx_abc123/inbox/messages/eml_123 \ -H "Authorization: Bearer sm_live_..." \ -H "Content-Type: application/json" \ -d '{ "read": true, "starred": false }' curl -X POST https://shipmail.to/api/v1/mailboxes/mbx_abc123/inbox/messages/eml_123/move \ -H "Authorization: Bearer sm_live_..." \ -H "Content-Type: application/json" \ -d '{ "target_role": "archive" }' curl -X DELETE https://shipmail.to/api/v1/mailboxes/mbx_abc123/inbox/messages/eml_123 \ -H "Authorization: Bearer sm_live_..." curl https://shipmail.to/api/v1/mailboxes/mbx_abc123/inbox/threads/thr_123 \ -H "Authorization: Bearer sm_live_..." curl "https://shipmail.to/api/v1/mailboxes/mbx_abc123/inbox/attachments?blob_id=blob%2F123&name=invoice.pdf" \ -H "Authorization: Bearer sm_live_..." \ -o invoice.pdf

Manage inbox rules

GET /v1/mailboxes/:id/rules
PUT /v1/mailboxes/:id/rules

Scope: mailboxes:read for GET and mailboxes:write for PUT. Rules are server-side filters that can move, mark, star, create static or AI reply drafts, or trigger webhooks for inbound mail. PUT replaces the full rules array.

Response body

{ "object": "mailbox_rules", "mailbox_id": "mbx_abc123", "address": "hello@example.com", "rules": [ { "id": "4f5a9d74-b0f1-49a7-bbfb-1f2af841f5b2", "name": "VIP", "enabled": true, "position": 0, "match_mode": "all", "stop": false, "conditions": [{ "type": "from_contains", "value": "@example.com" }], "actions": [ { "type": "move", "target": { "kind": "custom", "folder_id": "fld_123" } }, { "type": "send_webhook" }, { "type": "ai_draft_reply", "reply_mode": "reply", "instructions": "Write a concise support reply. Ask for missing details instead of guessing." } ] } ], "folders": [{ "id": "fld_123", "name": "VIP", "parent_id": null, "role": null, "kind": "custom" }] }

Example

curl -X PUT https://shipmail.to/api/v1/mailboxes/mbx_abc123/rules \ -H "Authorization: Bearer sm_live_..." \ -H "Content-Type: application/json" \ -d '{ "rules": [ { "id": "4f5a9d74-b0f1-49a7-bbfb-1f2af841f5b2", "name": "VIP", "enabled": true, "position": 0, "match_mode": "all", "stop": false, "conditions": [{ "type": "from_contains", "value": "@example.com" }], "actions": [ { "type": "star" }, { "type": "ai_draft_reply", "reply_mode": "reply_all", "instructions": "Write a concise support reply. Ask for missing details instead of guessing." } ] } ] }'

Delete a mailbox

DELETE /v1/mailboxes/:id

Scope: mailboxes:write. Returns 204 with no body on success.

Update auto-reply

PATCH /v1/mailboxes/:id/auto-reply

Scope: mailboxes:write. Rate limit tier: write. Configure an automatic reply (vacation/out-of-office) for a mailbox.

Request body

FieldTypeRequiredDescription
enabledbooleanYesWhether auto-reply is active.
bodystring | null*Reply message text. Max 5,000 characters. Required when enabled is true.
from_datestring | nullNoStart date in UTC ISO 8601.
to_datestring | nullNoEnd date in UTC ISO 8601. Must be after from_date.

Example

curl -X PATCH https://shipmail.to/api/v1/mailboxes/mbx_abc123/auto-reply \ -H "Authorization: Bearer sm_live_..." \ -H "Content-Type: application/json" \ -d '{ "enabled": true, "body": "I am away until January 6. I will reply when I return.", "from_date": "2026-12-23T00:00:00Z", "to_date": "2027-01-06T00:00:00Z" }'

Returns the updated mailbox object.

Update spam filter

PATCH /v1/mailboxes/:id/spam-filter

Scope: mailboxes:write. Rate limit tier: write. Set the spam score threshold for moving messages to junk.

Request body

FieldTypeRequiredDescription
thresholdintegerYesInteger from 1 to 14. Lower values are stricter.

Example

curl -X PATCH https://shipmail.to/api/v1/mailboxes/mbx_abc123/spam-filter \ -H "Authorization: Bearer sm_live_..." \ -H "Content-Type: application/json" \ -d '{"threshold": 8}'

Returns the updated mailbox object.

Imports

Import mail from another provider into a mailbox. Imports run in the background, preserve folders, read state, and dates, deduplicate by message identity, and are safe to re-run. See the mailbox import docs for behavior details.

Start an import

POST /mailboxes/{id}/imports. Scope: mailboxes:write. Tier: write.

curl -X POST https://shipmail.to/api/v1/mailboxes/mbx_abc123/imports \ -H "Authorization: Bearer sm_live_..." \ -H "Content-Type: application/json" \ -d '{ "source": { "type": "imap", "provider": "gmail", "email": "you@gmail.com", "password": "your-app-password" }, "options": { "range": "12m" } }'

The source is either an IMAP connection (providers: gmail, yahoo, aol, icloud, fastmail, zoho, imap; always use an app password) or staged files with { "type": "files", "provider": "takeout", "file_ids": ["impf_..."] }. Outlook imports require the dashboard's Sign in with Microsoft. Returns the import object (201), or 409 if an import is already running for this mailbox. Credentials are encrypted, used only for the import, and deleted when it finishes.

Stage an export file

POST /mailboxes/{id}/imports/files with { "file_name": "takeout.mbox", "size_bytes": 1048576 }. Returns file_id and a presigned upload_url. PUT the raw file bytes to the URL, then start the import with a files source. Accepted: .mbox, .mbox.gz, .zip, .eml, up to 4 GB per file. Unused staged files are deleted after 24 hours.

Track progress

GET /mailboxes/{id}/imports lists recent imports. GET /mailboxes/{id}/imports/{import_id} returns one import with live counters and the per-folder report. status values: queued, running, paused_throttle (source provider's daily download limit, resumes automatically), paused_quota (mailbox storage full), completed, failed, cancelled, undo_queued, undoing, undone, undo_failed.

Cancel an import

POST /mailboxes/{id}/imports/{import_id}/cancel. Mail already imported stays in the mailbox. Starting a new import later resumes without duplicates.

Undo an import

POST /mailboxes/{id}/imports/{import_id}/undo. This queues deletion of messages created by that import. Existing mail and duplicates skipped during the import are not touched.