Mailboxes
Mailboxes are unique email addresses used by your agents. Creating a mailbox is subject to local-part rules, a server-configured reserved-name list, domain allowlists by plan, and global uniqueness across all MoMail users.
Base path
Section titled “Base path”On the unified app (dashboard + API), routes are served on the same origin as the product, under /v1/api:
https://momail.io/v1/api/mailboxesUse your API key as Authorization: Bearer <api-key>. See Authentication.
List mailboxes
Section titled “List mailboxes”GET /v1/api/mailboxesResponse
Section titled “Response”{ "mailboxes": [ { "mailbox_id": "uuid", "domain": "user.momail.io", "status": "active", "namespace": "user-uuid", "created_at": "2026-01-15T10:30:00.000Z" } ]}Create mailbox
Section titled “Create mailbox”POST /v1/api/mailboxesContent-Type: application/jsonRequest body
Section titled “Request body”| Field | Type | Required | Description |
|---|---|---|---|
domain | string | Yes | Hostname for the address (must be allowed for your account). |
local_part | string | One of local_part or email_address | Mailbox name only (left of @). Recommended. |
email_address | string | One of local_part or email_address | Either the local part only (combined with domain) or a full local@host where host must equal domain. |
Example (recommended):
{ "local_part": "support-agent", "domain": "user.momail.io"}Local-part rules
Section titled “Local-part rules”- Minimum length: 5 characters (after trim), compared case-insensitively for reserved names and uniqueness.
- Allowed characters: letters and digits, plus
.,_,-. Cannot start or end with.or-(see server validation message for exact regex behavior). - Reserved names: The operator sets
DISALLOWED_EMAIL_NAMEin Worker configuration (comma-separated, case-insensitive). Those local parts are rejected on every domain (e.g.admin,info,systemif configured). - Uniqueness: The full address
local@domainmust not exist anywhere in MoMail’s database for any user.
Success response
Section titled “Success response”HTTP 201
{ "success": true, "mailbox": { "mailbox_id": "…", "domain": "user.momail.io", "status": "active", "namespace": "…", "created_at": "2026-01-15T10:30:00.000Z" }}Preflight: check mailbox name
Section titled “Preflight: check mailbox name”Before POST, you can validate the same rules (including uniqueness) without creating the mailbox:
GET /v1/api/mailboxes/check-email?local_part=myagent&domain=user.momail.ioSuccess (name available)
Section titled “Success (name available)”HTTP 200
{ "success": true, "valid": true,}Name not available (still HTTP 200)
Section titled “Name not available (still HTTP 200)”Validation failed or domain not allowed for the account — body explains why:
{ "success": true, "valid": false, "code": "EMAIL_TAKEN", "message": "This email address is already in use. Try a different name.",}Missing domain query parameter returns HTTP 400 with success: false.
Optional query exclude_mailbox_id (Dashboard rename flow): treat that mailbox’s current address as available so you can keep the same name or change only the domain.
Rename mailbox (Dashboard only)
Section titled “Rename mailbox (Dashboard only)”Change a mailbox’s address after creation or domain migration. Keeps mailbox_id and stored emails; updates mailboxes in D1 and inbound routing KV.
PATCH /api/mailboxes/{mailboxId}Content-Type: application/jsonRequires Dashboard session (cookies).
Request body
Section titled “Request body”Same shape as create: local_part + domain (or email_address + domain).
Success
Section titled “Success”{ "success": true, "data": { "mailbox": { "mailbox_id": "…", "domain": "user.momail.io", "status": "active" } }}Delete mailbox
Section titled “Delete mailbox”Soft-delete a mailbox and its associated data. Requires confirming the full email address.
DELETE /v1/api/mailboxes/{mailboxId}Content-Type: application/jsonRequest body
Section titled “Request body”{}| Field | Type | Required | Description |
|---|---|---|---|
confirm_email_address | string | Yes | Must match the mailbox’s full address exactly |
Success
Section titled “Success”HTTP 200
{ "success": true, "data": { "deleted": true }}Errors
Section titled “Errors”| HTTP | error.code | When |
|---|---|---|
| 400 | BAD_REQUEST | Missing JSON body |
| 400 | VALIDATION_ERROR | confirm_email_address missing or wrong |
| 404 | (varies) | Mailbox not found or not owned by user |
Error responses (POST /v1/api/mailboxes)
Section titled “Error responses (POST /v1/api/mailboxes)”Failures use a consistent JSON body:
{ "success": false, "error": { "code": "ERROR_CODE", "message": "Human-readable explanation", "details": {} }}details is omitted when empty. Use HTTP status together with error.code for programmatic handling.
HTTP status and error codes
Section titled “HTTP status and error codes”| HTTP | error.code | When |
|---|---|---|
| 400 | BAD_REQUEST | Invalid JSON, malformed input, or missing local part in email_address. |
| 400 | MISSING_FIELDS | Missing domain or both of local_part / email_address. |
| 400 | VALIDATION_ERROR | (Dashboard JSON schema only) Body shape invalid; see details.field_errors. |
| 403 | MAILBOX_QUOTA | Mailbox count exceeds plan limit; details may include count, limit, plan. |
| 409 | EMAIL_TAKEN | Full email already exists (check before insert, or rare race on unique constraint). |
| 422 | LOCAL_TOO_SHORT | Local part shorter than 5 characters. details: min_length, actual_length. |
| 422 | INVALID_LOCAL | Characters or shape not allowed. details may include local_part. |
| 422 | DISALLOWED_LOCAL | Matches a reserved name from DISALLOWED_EMAIL_NAME. details may include local_part. |
| 422 | DOMAIN_MISMATCH | email_address host does not match domain. details: domain_expected, domain_in_request. |
| 422 | DOMAIN_NOT_ALLOWED | Domain not in shared pool (free) or not verified / not shared (pro). details: domain, plan. |
Example: reserved name (422)
Section titled “Example: reserved name (422)”{ "success": false, "error": { "code": "DISALLOWED_LOCAL", "message": "This mailbox name is reserved. Please choose another.", "details": { "local_part": "admin" } }}Example: address taken (409)
Section titled “Example: address taken (409)”{ "success": false, "error": { "code": "EMAIL_TAKEN", "message": "This email address is already in use. Try a different name.", }}Dashboard session API
Section titled “Dashboard session API”When using browser session cookies (logged-in dashboard), the same rules apply to:
POST /api/mailboxesGET /api/mailboxes/check-email?local_part=…&domain=…
Response shapes mirror the v1 API for creation errors (success, error.code, error.message, error.details).
See also
Section titled “See also”- Emails (raw MIME) — Download
.emlfor a message in a mailbox - Search (MCP) — Semantic search via
search_emails - Error codes — Global HTTP and error conventions
- Domains — Verifying custom domains (Pro)
- Rate limits