MOLTED EMAIL

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:

PlanMax mailboxes
Trial3
Free3
Solo10
Team50
EnterpriseUnlimited

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
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

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:

Error 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 to POST /v1/agent/mailboxes and POST /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>. On POST /v1/agent/mailboxes and POST /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 a displayNameWarning field saying so. On PATCH /v1/agent/mailboxes/:id, a rejected display name is refused outright with 400 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 stored displayName is never changed by this. A custom domain's display name is never screened, at write time or send time.
400 Bad Request — invalid local part
{
  "statusCode": 400,
  "message": "\"support+x\" is not a valid shared-domain local part (lowercase alphanumeric, dots and hyphens only)"
}
201 Created — display name rejected on create, falls back with a warning
{
  "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."
}
400 Bad Request — display name rejected on update
{
  "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."
}
409 Conflict — reserved local part
{
  "statusCode": 409,
  "message": "\"support\" is reserved and cannot be used"
}
409 Conflict — address already in use
{
  "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:

StatusDescription
provisioningMailbox is being set up
activeMailbox is ready to receive email
pausedMailbox is temporarily disabled
errorMailbox 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:

CLI
molted mailboxes update MAILBOX_ID --display-name "New Display Name"
curl
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

FieldTypeRequiredDescription
displayNamestring or nullNoDisplay name for the mailbox. On the shared domain, a changed name is screened for impersonation — see Shared domain rules.
statusstringNoSet to active or paused.
configobjectNoPer-mailbox configuration (see below).
catchAllbooleanNoEnable or disable catch-all for this domain.
isDefaulttrueNoMake 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.

FieldTypeDescription
addressstring (email)The mailbox email address.
displayNamestring or nullDisplay name shown in outbound email.
inboundRateLimitinteger or nullMaximum inbound messages per period. Must be a positive integer. Set to null to disable.
pausedAutoReplystring or nullAuto-reply message sent when the mailbox is paused. Set to null to disable.
humanizerobjectThis 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.
CLI - set inbound rate limit
molted mailboxes update MAILBOX_ID --config '{"inboundRateLimit": 120}'
CLI - set paused auto-reply
molted mailboxes update MAILBOX_ID --config '{"pausedAutoReply": "We are currently unavailable. We will respond shortly."}'
curl - update config
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
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
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 admin scope. Only API keys with the admin scope 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 provisioning instead.

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

Pause a mailbox
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"
  }'
Resume a mailbox
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_paused block 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
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:

Response
{
  "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: ..."
}
CLI
molted mailboxes delete MAILBOX_ID

Via 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.received or inbound.classified events), 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
curl -X POST https://api.molted.email/v1/agent/mailboxes/MAILBOX_ID/restore \
  -H "Authorization: Bearer YOUR_API_KEY"
CLI
molted mailboxes restore MAILBOX_ID

The 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 provisioning instead of its old status, and the response carries "domainNeedsVerification": true plus 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 admin scope (and manage on 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 the mailboxId to restore instead.

Listing mailboxes

CLI
molted mailboxes list
curl
curl 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:

CLI
molted mailboxes set-default MAILBOX_ID
curl
curl -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": false returns 400. 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 isDefault moves 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
curl https://api.molted.email/v1/agent/mailboxes/MAILBOX_ID/stats?period=7d \
  -H "Authorization: Bearer YOUR_API_KEY"

Query parameters

ParameterTypeDefaultDescription
period24h | 7d | 30d7dTime window for metrics

Response

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
curl https://api.molted.email/v1/billing/status \
  -H "Authorization: Bearer YOUR_API_KEY"

The response includes a mailboxes field:

Mailbox usage
{
  "mailboxes": {
    "used": 2,
    "limit": 3
  }
}

A null limit means unlimited mailboxes (Enterprise plan).