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.
| Task | CLI | MCP |
|---|---|---|
| List | molted mailboxes list | list_mailboxes |
| Get one | molted mailboxes get <id> | |
| Create | molted mailboxes create --address <email> | |
| Update, pause, resume | molted mailboxes update <id> | |
| Activate a provisioning mailbox | molted mailboxes verify <id> | |
| Clone | molted mailboxes clone <id> --address <email> | |
| Make default | molted mailboxes set-default <id> | set_default_mailbox |
| Stats | molted mailboxes stats <id> | mailbox_stats |
| Delete, restore | molted mailboxes delete <id>, molted mailboxes restore <id> | |
| Resume after a reputation pause | molted mailboxes unpause <mailboxId> |
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
Creating a mailbox needs a key with the admin scope.
molted mailboxes create --address support@example.com --display-name "Support Inbox"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
{
"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:
{
"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 (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:
molted mailboxes verify MAILBOX_IDA 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:
molted mailboxes update MAILBOX_ID --display-name "New Display Name"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
| 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. |
address | string (email) | No | A 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. |
status | string | No | Set to active or paused, see Pausing and resuming. |
autonomyLevel | 1, 2 or 3 | No | The 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>. |
config | object | No | Per-mailbox configuration (see below). |
catchAll | boolean | No | Enable 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. |
isDefault | true | No | Make 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:
| Field | Type | Description |
|---|---|---|
humanizer | object | This 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.
molted mailboxes update MAILBOX_ID --config '{"humanizer": {"style": "friendly"}}'molted mailboxes update MAILBOX_ID --config '{"humanizer": {"enabled": false}}'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 -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_requiredwithkind: "mailbox-address", the mailbox id, and adecisionUrlto share with a person. Nothing in the request is applied, other fields included.warn: the change applies, with aMolted-Deprecation: human-gateheader.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
idis 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
configobject, 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
molted mailboxes clone MAILBOX_ID --address sales@example.com --display-name "Sales Inbox"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
adminscope. Only API keys with theadminscope can clone mailboxes, and a mailbox-scoped key also needsreadon the source mailbox. - The same address rules as creating apply, including the shared domain rules and the
409 mailbox_archivedfor 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
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 and CLI
molted mailboxes update MAILBOX_ID --status paused
molted mailboxes update MAILBOX_ID --status activecurl -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"
}'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_pausedblock 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.
molted mailboxes reputation MAILBOX_ID
molted mailboxes reputation recalculate MAILBOX_IDcurl "https://mailbox.molted.email/v1/agent/mailboxes/MAILBOX_ID/reputation" \
-H "Authorization: Bearer YOUR_API_KEY"{
"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:
status | When |
|---|---|
healthy | Bounce rate under 5%, and complaints under the limit below. |
warning | Bounce rate of 5% or more. |
paused | Bounce 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, neverpaused: 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/recalculateIt 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 -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:
{
"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.
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. 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 -X POST "https://mailbox.molted.email/v1/agent/mailboxes/MAILBOX_ID/restore" \
-H "Authorization: Bearer YOUR_API_KEY"molted mailboxes restore MAILBOX_ID{
"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
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 (
400). 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 (in the error body, next toerrorandmessage).
Listing mailboxes
molted mailboxes listcurl "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:
molted mailboxes set-default MAILBOX_IDcurl -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": 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. Needs read on the mailbox.
molted mailboxes stats MAILBOX_ID --period 7dMCP: mailbox_stats.
curl "https://mailbox.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 (CLI molted billing status, MCP billing_status):
curl "https://mailbox.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).