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.

The curl examples below call https://mailbox.molted.email, which fills in your tenantId from your key (the CLI and the MCP server go through it too). On https://api.molted.email every mailbox route needs your tenantId (query string, or the body of a POST/PATCH); a call without it returns 400.

TaskCLIMCP
Listmolted mailboxes listlist_mailboxes
Get onemolted mailboxes get <id>
Createmolted mailboxes create --address <email>
Update, pause, resumemolted mailboxes update <id>
Activate a provisioning mailboxmolted mailboxes verify <id>
Clonemolted mailboxes clone <id> --address <email>
Make defaultmolted mailboxes set-default <id>set_default_mailbox
Statsmolted mailboxes stats <id>mailbox_stats
Delete, restoremolted mailboxes delete <id>, molted mailboxes restore <id>
Resume after a reputation pausemolted mailboxes unpause <mailboxId>

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

Creating a mailbox needs a key with the admin scope.

CLI
molted mailboxes create --address support@example.com --display-name "Support Inbox"
curl
curl -X POST https://mailbox.molted.email/v1/agent/mailboxes \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "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",
  "autonomyLevel": 3,
  "catchAll": false,
  "isSharedDomain": false,
  "isDefault": false,
  "replyDeadlinesEnabled": false,
  "config": {},
  "createdAt": "2026-03-01T12:00:00Z",
  "updatedAt": "2026-03-01T12:00:00Z"
}

A mailbox on the shared domain, or on a custom domain already verified for your account, starts active. On a custom domain that isn't verified yet it starts provisioning (see Mailbox status).

Creating a mailbox in the portal

In the portal, press ⌘K and choose Create mailbox (or type new mailbox). The form asks for:

  • Address: the part before the @, then a domain. The domain list starts with the shared domain, then your verified custom domains; a domain that is still being verified is not offered. The part before the @ is lowercased, can be up to 64 characters of letters, numbers, dots, dashes and underscores, and has to start and end with a letter or number. If you paste a full address, only the part before the @ is kept.
  • Display name (optional), up to 100 characters.

Create mailbox makes the mailbox and opens its page. Every rule on this page applies, including the shared domain rules and the plan limit. When your plan's mailboxes are all in use, the form says so up front with a See plans link instead of failing, and a failed create is explained in a sentence ("That address is already taken. Try another."). Only the workspace owner can create mailboxes, see Owner and member access.

Owner and member access

What you change in the portal runs with your role in the workspace, read from the workspace's member list on every request. The owner can change mailboxes. Any other member can look but not change: the change fails with 403 owner_required ("Only the workspace owner can do this."), and on a mailbox's page the Address, Default mailbox, Safety and Delete mailbox cards say "Only the workspace owner can change this." A person who is not a member of the workspace at all gets 403 not_a_member. API keys are different: an agent's key has its own scopes, and this role check never applies to it.

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 (400 Bad Request, "Domain ... must be verified before this mailbox can be activated").

Once the domain is verified (Domains), activate the mailbox with PATCH .../mailboxes/:id and { "status": "active" }, or:

CLI
molted mailboxes verify MAILBOX_ID

A mailbox that is already active is returned unchanged.

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://mailbox.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.
addressstring (email)NoA new address on a verified custom domain, see Changing the email address. From an agent key, any change is a human decision, see Address and catch-all changes.
statusstringNoSet to active or paused, see Pausing and resuming.
autonomyLevel1, 2 or 3NoThe mailbox's autonomy level. Lowering it is always allowed; raising it from an agent key is a human decision, see Loosening a control. Also molted mailboxes autonomy set <mailboxId> --level <level>.
configobjectNoPer-mailbox configuration (see below).
catchAllbooleanNoEnable or disable catch-all for this domain. Only on a verified, receiving-enabled custom domain, and only one mailbox per domain (409 otherwise). From an agent key, turning it on or off is a human decision, see Address and catch-all changes.
isDefaulttrueNoMake this mailbox the default mailbox. Only true is accepted.

Updating a mailbox needs a key with the admin scope, and manage on the mailbox for a mailbox-scoped key.

replyDeadlinesEnabled is not an update field: it is read-only for API keys, and a PATCH that includes it returns 403 reply_deadlines_human_only. See Reply deadlines.

Mailbox config

The config field is a JSON object stored with the mailbox. The only key Molted reads from it today is humanizer:

FieldTypeDescription
humanizerobjectThis mailbox's own humanizer settings: { enabled, style }. enabled is true (humanize this mailbox's mail, even while the account setting is off), false (never humanize it), or null/unset (follow the account setting, which is where every mailbox starts). style is casual, professional or friendly, or null for the account's style. An explicit off at the mailbox or the agent wins over an on; the agent's own style and a per-send humanizeStyle override this mailbox's style, see Humanizer precedence. A null field clears just that field; humanizer: null clears both. From an agent key, turning it on (given the account setting) or any change to its style is a human decision, see Loosening a control; turning it off always works. A plan without the humanizer can't turn it on (403 humanizer_not_in_plan).

Every response that returns a mailbox (GET /v1/agent/mailboxes/:id, each mailbox in GET /v1/agent/mailboxes, the PATCH, create and clone responses, and the mailbox in a restore's response) also carries humanizer: { "setting": true | false | null, "enabled": boolean, "source": "mailbox" | "tenant" | "default" }. setting is the stored config.humanizer.enabled; enabled is whether a send from this mailbox is humanized when neither the agent nor the send sets it, and source says which setting decided that.

config replaces the whole stored object on write, with one exception: a PATCH that omits humanizer (or gives only part of it) carries the rest of humanizer forward from what's stored. Any other key you stored before and leave out is dropped, so read the mailbox first and send back everything you want to keep. Other keys are stored and returned as given, but nothing acts on them.

CLI - set the mailbox's humanizer style
molted mailboxes update MAILBOX_ID --config '{"humanizer": {"style": "friendly"}}'
CLI - turn the humanizer off for this mailbox
molted mailboxes update MAILBOX_ID --config '{"humanizer": {"enabled": false}}'
curl - update config
curl -X PATCH "https://mailbox.molted.email/v1/agent/mailboxes/MAILBOX_ID" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "config": {
      "humanizer": { "style": "friendly" }
    }
  }'

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://mailbox.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
  • A catch-all mailbox can't move to a different domain; disable catch-all first
  • Changing address affects deliverability since the new address has no sending reputation

Address and catch-all changes

The address and the catch-all decide which email reaches the mailbox. Changing the address stops mail arriving at the old one, turning catch-all on pulls in every unmatched address on the domain, and turning it off stops that mail. So from an agent key, any change to address and turning catchAll on or off is a human decision, gated by your account's human-gate mode like a resume (see Loosening a control):

  • enforce: 403 human_decision_required with kind: "mailbox-address", the mailbox id, and a decisionUrl to share with a person. Nothing in the request is applied, other fields included.
  • warn: the change applies, with a Molted-Deprecation: human-gate header.
  • off: the change applies.

The address is compared on the exact stored value, so a change in case only (Sales@ to sales@) counts as a change. Sending the value the mailbox already has is not a change and is never gated.

Two other requests change which mailbox gets an address's mail, so they get the same answer from an agent key:

  • Creating or cloning onto an address another mailbox's catch-all receives. An exact address beats a catch-all, so the new mailbox would take that address's mail away from the catch-all mailbox. The id is the catch-all mailbox's.
  • Deleting a catch-all mailbox. A deleted mailbox stops being the catch-all at once, and only mail to its own address is held for a restore.

Addresses ignore case within your account: creating, cloning or renaming onto an address a live mailbox already has, in any case (SALES@acme.com next to sales@acme.com), is 409 mailbox_address_taken for everyone, since the two would split that address's mail. Restoring a deleted mailbox whose address a live mailbox now has is refused the same way.

A person makes these changes in the portal, on the mailbox's page under Address (the decisionUrl links there): edit the address, or flip Catch-all. A person is never gated. The catch-all control shows only when the mailbox's domain can have one; GET /v1/agent/mailboxes/:id says so in catchAllAvailable (a verified custom domain with receiving on). An agent holding a portal session sees both settings but can't change them.

Every address or catch-all change made through PATCH, a person's or an agent's, is recorded on the Activity timeline (mailbox.address_changed or mailbox.catch_all_changed, with who made it and the old and new values). Deleting and restoring a mailbox are recorded as mailbox.deleted and mailbox.restored instead; the restore's record says whether the catch-all came back (catchAllRestored).

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, humanizer style, rules, and labels as an existing one.

What gets copied

  • Autonomy level (L1/L2/L3)
  • Config (the whole config object, including the humanizer switch and style)
  • Custom rules (with label references remapped to the cloned labels)
  • Labels (formerly folders; copied empty: threads are not copied)
  • Paused state (see Guards)

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)
  • Reply deadlines (a new mailbox starts with them off)

Via API and CLI

CLI
molted mailboxes clone MAILBOX_ID --address sales@example.com --display-name "Sales Inbox"
curl
curl -X POST "https://mailbox.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 (including displayNameWarning when a shared-domain display name was replaced). The portal has no clone action.

Guards

  • Requires admin scope. Only API keys with the admin scope can clone mailboxes, and a mailbox-scoped key also needs read on the source mailbox.
  • The same address rules as creating apply, including the shared domain rules and the 409 mailbox_archived for a deleted mailbox's address.
  • 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 and CLI

CLI
molted mailboxes update MAILBOX_ID --status paused
molted mailboxes update MAILBOX_ID --status active
Pause a mailbox
curl -X PATCH "https://mailbox.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://mailbox.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 (400 Bad Request 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.

Reputation pauses

The reputation monitor can also pause a mailbox when its bounce or complaint rate crosses a threshold, see Reputation. The pause is kept on the mailbox's reputation, and blocks sends with the same mailbox_paused reason. Check it with GET /v1/agent/mailboxes/:id/reputation (molted mailboxes reputation <mailboxId>). Lifting it is POST /v1/agent/mailboxes/:id/unpause (molted mailboxes unpause <mailboxId>), which needs manage on the mailbox, answers 400 when the mailbox isn't reputation-paused, and from an agent key is the same human decision as a resume.

Via portal

In the portal, open the mailbox's page and use Pause this mailbox (or Resume on a paused one) next to its sending status.

What happens when a mailbox is paused

  • Outbound emails are blocked. Any send attempt returns a mailbox_paused block reason.
  • Journey steps and scheduled follow-ups wait. They are retried every 15 minutes while the mailbox is paused, go out once it's resumed, and are cancelled (paused_timeout) after 72 hours paused.
  • Inbound messages continue to be received and stored normally.

Reputation

Every mailbox has a reputation, worked out from what happened to its mail in the last 30 days. It is how a mailbox that starts bouncing or drawing complaints is stopped before it damages your sending domain.

CLI
molted mailboxes reputation MAILBOX_ID
molted mailboxes reputation recalculate MAILBOX_ID
curl
curl "https://mailbox.molted.email/v1/agent/mailboxes/MAILBOX_ID/reputation" \
  -H "Authorization: Bearer YOUR_API_KEY"
Response
{
  "id": "7d2a...",
  "mailboxId": "550e8400-e29b-41d4-a716-446655440000",
  "tenantId": "tenant-abc",
  "score": 85,
  "bounceRate": 0.03,
  "complaintRate": 0,
  "totalSends": 200,
  "totalBounces": 6,
  "totalComplaints": 0,
  "status": "healthy",
  "lastCalculatedAt": "2026-03-31T14:22:00Z",
  "createdAt": "2026-03-01T12:00:00Z",
  "updatedAt": "2026-03-31T14:22:00Z"
}

Reading needs read on the mailbox (MCP: check_reputation). A mailbox with no reputation yet is calculated on the first read.

How it is counted

  • Window. Only sends from the last 30 days count, and only sends that were accepted or sent: blocked, rejected and held sends never reached a provider. After a person resumes a reputation-paused mailbox, only sends since the resume count, so the history that caused the pause cannot pause it again at once.
  • Bounces and complaints are counted per send, so a retried delivery notice does not count twice. Hard and soft bounces both count.
  • Score runs from 0 to 100: 100 - round(bounceRate * 500) - 25 * complaints, never below 0. A 3% bounce rate scores 85, 5% scores 75 and 15% scores 25.
  • Status follows the rates:
statusWhen
healthyBounce rate under 5%, and complaints under the limit below.
warningBounce rate of 5% or more.
pausedBounce rate of 15% or more, or complaints at the limit below.
  • Minimum volume. The bounce rate can only pause a mailbox once it has at least 20 sends in the window. Below that, a rate of 5% or more reads warning, never paused: one bounce out of your first few sends is not yet a signal.
  • Complaints are not gated by volume. A mailbox pauses when its complaints reach 0.3% of its sends in the window, rounded up, and never fewer than 1. So one complaint pauses a mailbox with up to 333 sends in the window, and a bulk sender gets a proportional limit instead.

These are Molted's default thresholds.

What a pause does

When the status turns paused, the mailbox is paused too: its sends are blocked with mailbox_paused, its journey steps and follow-ups wait (see Pausing and resuming), and its pause reason starts with "Reputation:". Only a person resumes it, from the mailbox's page or with molted mailboxes unpause, which resets the counters (see Reputation pauses).

Recalculating

The reputation is recalculated whenever a delivery event arrives for one of the mailbox's sends. To refresh it by hand:

POST https://mailbox.molted.email/v1/agent/mailboxes/:id/reputation/recalculate

It needs manage on the mailbox, and a mailbox recalculated in the last 5 minutes answers 400 ("Reputation was recalculated recently. Try again in a few minutes."). A person in the portal has the same route under /v1/me/mailboxes/:id/reputation/recalculate, and the same cooldown. The portal's mailbox page shows a "Last 7 days" bounce rate rather than this score.

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://mailbox.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",
  "restorableBy": "agent_or_person",
  "message": "Archived support@yourdomain.com: ..."
}

restorableBy is agent_or_person when an agent key deleted it (that agent can restore it too), and person otherwise.

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. Only mail to the mailbox's own address: a deleted catch-all mailbox stops being the catch-all at once, and mail to the other addresses it caught is not held for it. That is why an agent deleting a catch-all mailbox needs a person, see Address and catch-all changes.
  • 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://mailbox.molted.email/v1/agent/mailboxes/MAILBOX_ID/restore" \
  -H "Authorization: Bearer YOUR_API_KEY"
CLI
molted mailboxes restore MAILBOX_ID
Response
{
  "restored": true,
  "mailbox": { "id": "MAILBOX_ID", "address": "support@yourdomain.com", "status": "active" },
  "catchAllRestored": false,
  "releasedMessages": 3
}

mailbox is the full mailbox object. releasedMessages counts the emails that arrived while it was deleted.

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; mail to the other addresses it caught while it was deleted is not among the released emails.

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 (400). 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 (in the error body, next to error and message).

Listing mailboxes

CLI
molted mailboxes list
curl
curl "https://mailbox.molted.email/v1/agent/mailboxes" \
  -H "Authorization: Bearer YOUR_API_KEY"

Each mailbox carries replyDeadlinesEnabled (see Reply deadlines) and 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.

Reply deadlines

Each inbound email normally gets a reply deadline, and an email that is still unanswered when its deadline passes is escalated to you: the conversation moves to Needs you, Activity shows "Reply deadline missed", and a thread.sla_breached event is published. That suits a support or sales mailbox. For a personal mailbox it serves no purpose, so each mailbox has a Reply deadlines switch.

  • On: an email gets a deadline of 60 minutes. Auto-replies, opt-outs and delivery notices get none. A shorter deadline applies to mail the classifier holds for a person because it reads as conflicting or adversarial (15 minutes), or because it was unsure about an auto-reply, delivery notice or opt-out (30 minutes). Mail held as spam or for a safety review is never escalated. See Routing actions for how the deadline follows the email's label.
  • Off: new email in this mailbox gets no deadline, and a deadline that was already pending when you turned the switch off is ignored. Nothing else changes: the same routing, approvals, quarantine and notifications apply.

The switch is on the mailbox's page in the portal, under Reply deadlines. It is on for every mailbox that existed before the switch was introduced and off for mailboxes created after, including the one you sign up with. Only a person can change it: turning deadlines off means nobody is told about an unanswered email, so an API key, the CLI or an agent cannot. Agents can see it: every mailbox you list or fetch carries replyDeadlinesEnabled.

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://mailbox.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. Needs read on the mailbox.

CLI
molted mailboxes stats MAILBOX_ID --period 7d

MCP: mailbox_stats.

curl
curl "https://mailbox.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 (CLI molted billing status, MCP billing_status):

curl
curl "https://mailbox.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).