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 in the X-API-Key header (or Authorization: Bearer <token> where supported). See Authentication.
List mailboxes
Section titled “List mailboxes”GET /v1/api/mailboxesResponse
Section titled “Response”{ "mailboxes": [ { "mailbox_id": "uuid", "email_address": "myagent@user.momail.io", "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": "…", "email_address": "support-agent@user.momail.io", "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, "email_address": "myagent@user.momail.io"}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.", "details": { "email_address": "myagent@user.momail.io" }}Missing domain query parameter returns HTTP 400 with success: false.
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.", "details": { "email_address": "james.bond@user.momail.io" } }}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”- Error codes — Global HTTP and error conventions
- Domains — Verifying custom domains (Pro)
- Rate limits