Mailboxes
Create, manage, and delete mailboxes for receiving inbound email, with plan-based limits.
Mailboxes let your tenant receive inbound email at dedicated addresses. Each mailbox is scoped to a single tenant and can be used to receive and process incoming messages.
Plan limits
The number of mailboxes you can create depends on your plan:
| Plan | Max mailboxes |
|---|---|
| Trial | 3 |
| Free | 3 |
| Solo | 10 |
| Team | 50 |
| Enterprise | Unlimited |
When your account is in the expired state, no new mailboxes can be created.
Creating a mailbox
Mailboxes are created via the agentic mailbox API:
curl -X POST https://api.molted.email/v1/agent/mailboxes \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"tenantId": "tenant-abc",
"address": "support@example.com",
"displayName": "Support Inbox"
}'Response
{
"id": "550e8400-e29b-41d4-a716-446655440000",
"tenantId": "tenant-abc",
"address": "support@example.com",
"displayName": "Support Inbox",
"status": "provisioning",
"isDefault": false,
"config": {},
"createdAt": "2026-03-01T12:00:00Z",
"updatedAt": "2026-03-01T12:00:00Z"
}Limit exceeded
If you attempt to create a mailbox beyond your plan's limit, you'll receive a 403 Forbidden response:
{
"statusCode": 403,
"message": "Mailbox limit reached (3). Upgrade your plan to create more mailboxes."
}Shared domain rules
Addresses on the shared domain (agent.molted.email by default) are visible to every tenant, so they're subject to extra checks that a custom domain (which only your tenant can use) is not:
- Reserved local parts are blocked. Role-like names (
admin,support,security,billing,postmaster, and others) cannot be used on the shared domain, to avoid phishing and impersonation. This applies toPOST /v1/agent/mailboxesandPOST /v1/agent/mailboxes/:id/clone. - Addresses must be ASCII, lowercase alphanumeric with dots or hyphens only. Non-ASCII characters and plus-addressing (
support+x@...) are rejected — the local part must look exactly like a plain name, not something that folds or reads differently across systems. - Addresses are unique across all tenants, not just within your own — and unique against every tenant's sender addresses too, not just their mailboxes. Creating or cloning onto a shared-domain address another tenant already holds, as either a mailbox or a sender address, returns
409 Conflict. - Catch-all cannot be enabled on the shared domain -- only a verified, receiving-enabled custom domain can be a catch-all.
- Display names are screened for impersonation. A display name that reads as an organisation, brand, official role or service — role/security words like
support,billing,admin,official,verification,bank,team,noreply, plus a short list of well-known brands — is rejected, matched regardless of letter case or common lookalike substitutions (e.g. a Cyrillic "а" for a Latin "a", or separators inserted between letters). A display name shaped like an email address or a bare domain (support@paypal.com,ceo@bank.com,paypal.com) is rejected too, even when it contains no banned word — this closes a spoof where a mail client shows only the display name, e.g."support@paypal.com" <brave-otter-4821@agent.molted.email>. OnPOST /v1/agent/mailboxesandPOST /v1/agent/mailboxes/:id/clone, a rejected display name isn't an error: it's silently replaced with the address's own local part, and the response includes adisplayNameWarningfield saying so. OnPATCH /v1/agent/mailboxes/:id, a rejected display name is refused outright with400 Bad Request. - The same screening also runs again on every send. A shared-domain mailbox's display name is re-checked at send time, not just when it's set: this catches a name saved before the screening existed. A name that now fails the check is dropped for that send only (the email goes out from the bare address, e.g.
brave-otter-4821@agent.molted.email, with no display name); the mailbox's storeddisplayNameis never changed by this. A custom domain's display name is never screened, at write time or send time.
{
"statusCode": 400,
"message": "\"support+x\" is not a valid shared-domain local part (lowercase alphanumeric, dots and hyphens only)"
}{
"id": "550e8400-e29b-41d4-a716-446655440000",
"tenantId": "tenant-abc",
"address": "brave-otter-4821@agent.molted.email",
"displayName": "brave-otter-4821",
"status": "active",
"config": {},
"createdAt": "2026-03-01T12:00:00Z",
"updatedAt": "2026-03-01T12:00:00Z",
"displayNameWarning": "Display name \"PayPal Support\" is not allowed on the shared domain, so this mailbox uses \"brave-otter-4821\" instead. Custom domains allow any display name."
}{
"statusCode": 400,
"message": "Display name \"Billing Team\" is not allowed on the shared domain: it reads as an organisation, brand, official role, or an email address or domain. Custom domains allow any display name."
}{
"statusCode": 409,
"message": "\"support\" is reserved and cannot be used"
}{
"statusCode": 409,
"message": "\"sales@agent.molted.email\" is already in use on the shared domain"
}None of this applies to a verified custom domain you own: pick any local part and any display name, and only your tenant's own mailboxes compete for it.
Mailbox status
Each mailbox has a status field:
| Status | Description |
|---|---|
provisioning | Mailbox is being set up |
active | Mailbox is ready to receive email |
paused | Mailbox is temporarily disabled |
error | Mailbox encountered a configuration error |
On a custom domain, both creating a mailbox and moving it from provisioning to active require that domain to be verified for your own tenant. Creating a mailbox on a domain another tenant has already verified is rejected outright (409 Conflict); a mailbox that stayed provisioning because the domain wasn't verified yet cannot be activated by PATCH .../mailboxes/:id either, until it is.
Sends are checked too, at send time: a mailbox whose domain is neither the shared domain nor verified for your account is never used as a sender, whatever its status. The send is blocked with reason sender_domain_not_verified. This also covers sends that were already queued or approved. A verified domain that is temporarily failing its DNS checks (temporary_failure) still counts as verified here; pending and failed do not.
Updating a mailbox
Use PATCH /v1/agent/mailboxes/:id to update mailbox properties:
molted mailboxes update MAILBOX_ID --display-name "New Display Name"curl -X PATCH https://api.molted.email/v1/agent/mailboxes/MAILBOX_ID \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"displayName": "New Display Name"
}'Update fields
| Field | Type | Required | Description |
|---|---|---|---|
displayName | string or null | No | Display name for the mailbox. On the shared domain, a changed name is screened for impersonation — see Shared domain rules. |
status | string | No | Set to active or paused. |
config | object | No | Per-mailbox configuration (see below). |
catchAll | boolean | No | Enable or disable catch-all for this domain. |
isDefault | true | No | Make this mailbox the default mailbox. Only true is accepted. |
Mailbox config schema
The config field is a JSON object for per-mailbox settings. All fields are optional on update -- you only need to include the fields you want to change.
| Field | Type | Description |
|---|---|---|
address | string (email) | The mailbox email address. |
displayName | string or null | Display name shown in outbound email. |
inboundRateLimit | integer or null | Maximum inbound messages per period. Must be a positive integer. Set to null to disable. |
pausedAutoReply | string or null | Auto-reply message sent when the mailbox is paused. Set to null to disable. |
humanizer | object | This mailbox's own humanizer setting: { style } (casual, professional, or friendly), style-only -- a mailbox can't turn the humanizer on or off, only pick a style for when it's already on. Overrides the tenant's style for sends from this mailbox; the agent's own setting and a per-send humanizeStyle both override this in turn -- see Humanizer precedence. config replaces the whole object on write, but a PATCH that omits humanizer (or gives only part of it) carries the rest forward from what's stored, so you only need to include the fields you're actually changing; send humanizer: null to clear it back to the account default. Changing the style while one is already stored is a human decision from an agent key -- see Loosening a control. |
molted mailboxes update MAILBOX_ID --config '{"inboundRateLimit": 120}'molted mailboxes update MAILBOX_ID --config '{"pausedAutoReply": "We are currently unavailable. We will respond shortly."}'curl -X PATCH https://api.molted.email/v1/agent/mailboxes/MAILBOX_ID \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"config": {
"inboundRateLimit": 120,
"pausedAutoReply": "We are currently unavailable."
}
}'Changing the email address
You can change a mailbox's email address if it is on a custom domain. Shared domain mailboxes (agent.molted.email) cannot have their address changed.
The new address must be on a verified custom domain owned by the tenant.
curl -X PATCH https://api.molted.email/v1/agent/mailboxes/MAILBOX_ID \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"address": "new-address@yourdomain.com"
}'Restrictions:
- Shared domain mailboxes cannot change their address
- The new address must be on a verified custom domain
- The new address must be unique within the tenant
- Changing address affects deliverability since the new address has no sending reputation
Cloning a mailbox
You can clone an existing mailbox to create a new one with the same settings. This is useful when you want to set up a new mailbox with the same autonomy level, safety mitigations, humanizer configuration, rules, and folders as an existing one.
What gets copied
- Autonomy level (L1/L2/L3)
- Config (safety mitigations, humanizer style, reply-to, signature)
- Custom rules (with folder references remapped to the cloned folders)
- Custom folders (empty - threads are not copied)
What does not get copied
- Threads and sending history
- Catch-all setting (only one mailbox per domain can be catch-all)
- Email address and display name (you provide new ones)
Via API
curl -X POST https://api.molted.email/v1/agent/mailboxes/MAILBOX_ID/clone \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"address": "sales@example.com",
"displayName": "Sales Inbox"
}'The response is the newly created mailbox object, identical to the response from creating a mailbox.
Via portal
In the portal, open the mailbox settings page and find the Duplicate Mailbox section. Click Duplicate, enter the new email address and optional display name, then confirm. You will be redirected to the new mailbox's settings page.
Guards
- Requires
adminscope. Only API keys with theadminscope can clone mailboxes. - Plan limits apply. The clone counts against your mailbox quota just like creating a new mailbox.
- Address must be unique. The new address must not already exist for your tenant.
- A paused mailbox clones paused. Cloning a paused mailbox (paused by hand or by the reputation monitor) creates a paused copy, which only a person can resume. On a custom domain that isn't verified for your account yet, the copy starts
provisioninginstead.
Pausing and resuming
You can pause a mailbox to temporarily stop all outbound sending. This is useful during incidents, migrations, or while investigating deliverability issues.
Via API
curl -X PATCH https://api.molted.email/v1/agent/mailboxes/MAILBOX_ID \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"status": "paused"
}'curl -X PATCH https://api.molted.email/v1/agent/mailboxes/MAILBOX_ID \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"status": "active"
}'Only an active mailbox can be paused: pausing a provisioning mailbox returns 400 Bad Request. A mailbox on a custom domain can only be resumed while that domain is verified for your account (409 Conflict otherwise).
Only a person resumes a paused mailbox, including one that was paused automatically. An agent key can always pause; its resume is a human decision (403 human_decision_required with a decisionUrl, or a Molted-Deprecation: human-gate warning while the account is in warn). See Loosening a control.
Via portal
In the portal, open the mailbox settings page and use the Sending Status toggle at the top. Pausing requires confirmation. Paused mailboxes show a "PAUSED" badge in the sidebar.
What happens when a mailbox is paused
- Outbound emails are blocked. Any send attempt returns a
mailbox_pausedblock reason. - Queued and scheduled messages are held, not dropped. They will be sent once the mailbox is resumed.
- Inbound messages continue to be received and stored normally.
- Paused mailboxes do not count against rate limits.
- Mailboxes can also be auto-paused by the reputation system if bounce or complaint rates exceed thresholds.
Deleting a mailbox
Mailboxes can be deleted via the API, the CLI or the portal, by your agent or by you. A deletion can be undone for 14 days: the mailbox is archived first, and only deleted for good once the 14 days are up.
Via API
curl -X DELETE https://api.molted.email/v1/agent/mailboxes/MAILBOX_ID \
-H "Authorization: Bearer YOUR_API_KEY"A successful deletion returns the date it goes for good:
{
"deleted": true,
"archived": true,
"mailboxId": "MAILBOX_ID",
"address": "support@yourdomain.com",
"archivedAt": "2026-10-01T10:00:00.000Z",
"purgeAfter": "2026-10-15T10:00:00.000Z",
"message": "Archived support@yourdomain.com: ..."
}molted mailboxes delete MAILBOX_IDVia portal
In the portal, open the mailbox's page, click Delete mailbox in the last card and type the mailbox's address to confirm. Only the workspace owner can, and never for the last mailbox. You land on Home with a line confirming it.
What happens when a mailbox is deleted
For the 14 days after a deletion, the mailbox is archived:
- It stops sending at once, and your agents no longer see it: it is gone from mailbox lists, and its threads and messages are hidden from every agent route. Its threads are not moved to trash, so a restore brings them back exactly as they were.
- Its address stays reserved. Nobody, in your workspace or another, can create it again while it can still be restored.
- Mail sent to it is kept. It is stored and held under the mailbox, out of your agents' sight (no
inbound.receivedorinbound.classifiedevents), and comes back with it on a restore. - You get a card on Home when an agent deleted it ("support-bot archived support@yourdomain.com. It's deleted for good on ..."), with Restore and Dismiss.
- It doesn't count against your plan's mailbox limit.
- Its scheduled follow-ups wait. They never go out from another address, and resume if it's restored.
- If it was your default mailbox, it no longer is. Sends without a mailbox go out from your oldest active mailbox, and restoring it does not make it the default again.
After 14 days it is deleted for good: its threads, messages, held mail and attachments, the content of the emails it sent, and its pending follow-ups are removed. Its key scopes, rules, folders and reputation go with it; your send history stays (who, when, delivery), without the content or the mailbox. The address is free again.
A mailbox deleted before this 14-day window existed was given one retroactively: it shows up as a normal archived mailbox with Restore, and a Home card of its own ("support@yourdomain.com was deleted before restore existed. It will be permanently removed on ..."). Its threads, already moved to trash by the old delete, are hidden with the rest of the mailbox while it's archived and come back to Trash on restore -- not pulled back into the open inbox. (One exception: if its address on the shared domain now collides with another account's, it was left exactly as it was, with no restore window at all -- contact support.)
Restoring a deleted mailbox
Within the 14 days, restore it from the portal: Settings lists deleted mailboxes with Restore and the days left, the deleted mailbox's own page has Restore mailbox, and so does the Home card. Your agent can restore a mailbox an agent deleted, with the same access it needs to delete it (a mailbox you deleted can only be restored by a person, from the portal):
curl -X POST https://api.molted.email/v1/agent/mailboxes/MAILBOX_ID/restore \
-H "Authorization: Bearer YOUR_API_KEY"molted mailboxes restore MAILBOX_IDThe mailbox, its threads and settings come back as they were, and each email that arrived meanwhile is released to your agents with an inbound.released event (reason: "mailbox_restored"). A catch-all mailbox gets its catch-all back unless another mailbox took it meanwhile.
If the mailbox is on a custom domain, its ownership is re-checked at restore time, since the 14 days in between is enough for a domain's verification to lapse or for someone else to claim it:
- Domain no longer verified for you: the mailbox comes back as
provisioninginstead of its old status, and the response carries"domainNeedsVerification": trueplus a message saying it needs (re-)verifying before it can send again. (The shared domain and a domain you still own are unaffected.) - Domain now verified by a different account: the restore is refused outright with
409 domain_conflict, rather than handing you back a mailbox on someone else's domain.
On the shared domain, restore also re-checks that nobody else now holds the exact address: refused with 409 address_taken if another account has since taken it, as a mailbox or as a sender address.
Guards
- You cannot delete the last mailbox. Every tenant must have at least one active mailbox. Create another mailbox first if you need to delete the current one.
- Requires
adminscope (andmanageon the mailbox for a mailbox-scoped key), for deleting and restoring alike. - An agent restoring a mailbox a person deleted returns
403 human_archive; restore it from the portal. - Restoring after the 14 days returns
410 archive_expired; the mailbox is being deleted for good. - Restoring at your plan's mailbox limit returns
403 mailbox_limit. Delete another mailbox or upgrade first. - Restoring onto a domain someone else now owns returns
409 domain_conflict. - Restoring onto a shared-domain address someone else now holds returns
409 address_taken. - Creating a deleted mailbox's address again within the 14 days returns
409 mailbox_archived, with themailboxIdto restore instead.
Listing mailboxes
molted mailboxes listcurl https://api.molted.email/v1/agent/mailboxes?tenantId=tenant-abc \
-H "Authorization: Bearer YOUR_API_KEY"Each mailbox carries isDefault: true on the workspace's default mailbox, the one that sends without a mailboxId go out from (see Default mailbox). A key scoped to some mailboxes sees the same flag (it marks the workspace default, which may not be one of its mailboxes, so it may see none flagged), but its own sends without a mailboxId go out from its oldest active scoped mailbox, not the workspace default.
Default mailbox
Every send that names no mailbox (an API or MCP send without mailboxId, a journey step with no mailbox, a follow-up, a reply from the portal to an older thread with no mailbox) goes out from your workspace's default mailbox. The mailbox you sign up with is the default.
Choose another one from the portal (a mailbox's page, Make default), the CLI, MCP (set_default_mailbox) or the API:
molted mailboxes set-default MAILBOX_IDcurl -X PATCH https://api.molted.email/v1/agent/mailboxes/MAILBOX_ID \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{ "isDefault": true }'The response is the mailbox, with "isDefault": true. Every mailbox list and mailbox page then tags it as the default.
- Only an active mailbox can be the default. A paused or provisioning mailbox returns
409 mailbox_not_active. - It needs a key with access to every mailbox (or a person in the portal). A key scoped to some mailboxes returns
403 mailbox_scope_denied, because the default changes where every unattributed send in the workspace goes. "isDefault": falsereturns400. There is always a default; change it by choosing another mailbox.- If the default is paused or deleted, sends without a mailbox fall back to your oldest active mailbox, and
isDefaultmoves to that one. A paused default takes over again once it's resumed. A deleted one does not, even if it's restored. - The change is recorded in the audit log (
mailbox.default_changed).
Mailbox statistics
Get per-mailbox usage statistics including send volume, deliverability metrics, and inbound counts.
curl https://api.molted.email/v1/agent/mailboxes/MAILBOX_ID/stats?period=7d \
-H "Authorization: Bearer YOUR_API_KEY"Query parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
period | 24h | 7d | 30d | 7d | Time window for metrics |
Response
{
"mailboxId": "550e8400-e29b-41d4-a716-446655440000",
"period": "7d",
"sends": {
"total": 1250,
"period": 342
},
"inbound": {
"period": 87
},
"deliverability": {
"delivered": 330,
"bounced": 8,
"complained": 1,
"opened": 210,
"clicked": 45,
"deliveryRate": 0.973,
"bounceRate": 0.024,
"complaintRate": 0.003,
"openRate": 0.614,
"clickRate": 0.132
},
"suppressionCount": 12,
"lastSendAt": "2026-03-31T14:22:00Z",
"dailySends": [
{ "day": "2026-03-25", "count": 48 },
{ "day": "2026-03-26", "count": 52 },
{ "day": "2026-03-27", "count": 41 }
]
}The stats are computed from existing send and delivery data. The dailySends array provides data for charting send volume over the selected period.
Checking your usage
Mailbox usage is included in the billing status endpoint:
curl https://api.molted.email/v1/billing/status \
-H "Authorization: Bearer YOUR_API_KEY"The response includes a mailboxes field:
{
"mailboxes": {
"used": 2,
"limit": 3
}
}A null limit means unlimited mailboxes (Enterprise plan).