Skip to content

Emails API

All endpoints require a bearer token (a login JWT or an API key).

INFO

Email hosting is offered on request - contact us before using these endpoints.

Mailboxes live on a domain you have already verified. If the domain's ownership is not verified yet, creating a mailbox returns 400 asking you to publish the verify-domain TXT record first. See the Domains API.

The email object

json
{
  "uuid": "mbx_abc123",
  "email": "hello@example.com",
  "domainName": "example.com",
  "storageSize": 5,
  "status": "ACTIVE",
  "alias": "",
  "catchAll": 0,
  "diskUsage": 20971520,
  "serverId": "srv_mail_1",
  "createdAt": "2026-07-01T12:00:00Z",
  "updatedAt": null
}
FieldMeaning
emailThe full address.
storageSizeMailbox quota in GB (1 to 50).
statusACTIVE or DISABLED (you set these). SUSPENDED is set by us and locks the mailbox.
aliasForwarding target. Empty string means no forwarding.
catchAll1 if this mailbox receives all mail sent to unknown addresses on the domain, else 0.
diskUsageCurrent usage in bytes.

List mailboxes

http
GET /api/emails?domain=example.com&page=1&limit=20

Paginated. The domain filter is optional.

Mailbox counts per domain

http
GET /api/emails/domains

Returns [{ "domainName": "example.com", "count": 3 }] for each domain that has at least one mailbox.

Create a mailbox

http
POST /api/emails/:domainName
json
{
  "email": "hello@example.com",
  "password": "Sup3rSecret",
  "storageSize": 5,
  "serverId": "srv_mail_1"
}
FieldTypeNotes
emailstringThe full address. Its domain part must equal :domainName or you get 400.
passwordstring8+ characters with an uppercase letter, a lowercase letter, and a digit.
storageSizenumberQuota in GB, 1 to 50.
serverIdstringOnly required the first time you create a mailbox on the domain (it picks the email server). Omit it afterwards.

Email addresses are globally unique, so a duplicate returns 400 "Email is already taken.".

Describe a mailbox

http
GET /api/emails/:domainName/:uuid

Update a mailbox

http
PUT /api/emails/:domainName/:uuid

Every field is optional - send only what you want to change:

json
{
  "password": "N3wPassword",
  "alias": "team@example.com",
  "catchAll": true,
  "status": "DISABLED",
  "storageSize": 10
}
FieldTypeNotes
passwordstringNew password (same rules as create).
aliasstringForward a copy of incoming mail here. Send "" to clear it. Cannot equal the mailbox's own address.
catchAllbooleanMake this the catch-all for the domain.
statusstringACTIVE or DISABLED only.
storageSizenumberNew quota in GB, 1 to 50.

Suspended mailboxes

A SUSPENDED mailbox rejects all edits (400 "Cannot update a suspended email"), and you cannot set SUSPENDED yourself - it is an account-level state we manage.

Delete a mailbox

http
DELETE /api/emails/:domainName/:uuid

Returns 204. Irreversible.

Mailbox stats

http
GET /api/emails/:domainName/:uuid/mailbox-stats
json
{ "messageCount": 214, "lastSent": "2026-07-16T09:12:00Z", "lastReceived": "2026-07-17T06:44:00Z" }

Set up email on a domain

http
POST /api/emails/:domainName/email-setup
json
{ "emailServerId": "srv_mail_1" }

Turns on email for the domain and generates the DNS records you need to publish (all with TTL 300):

RecordHostPurposeRequired
MX@Where mail is deliveredYes
SPF@Authorises our servers to send for youYes
DKIM<id>._domainkeySigns your outbound mailYes
DMARC_dmarcReporting and policyRecommended
SRV_imaps._tcpIMAP autodiscovery (993)Recommended
SRV_submission._tcpSMTP submission autodiscovery (587)Recommended

Revalidate DNS

http
POST /api/emails/:domainName/revalidate-dns

Re-checks the published records on demand and updates each record's status. This is what the console's Recheck DNS button calls.

Regenerate DNS

http
POST /api/emails/:domainName/regenerate-dns

Wipes and rebuilds the domain's email DNS records. This is what the console's Regenerate Records button calls.

Update your CNAME after regenerating

Regenerating rotates the DKIM key and also rotates the SSL validation delegation label, so the _acme-challenge CNAME record changes. Update that CNAME at your DNS provider after regenerating, or the next certificate renewal will fail.

Remove email setup

http
DELETE /api/emails/:domainName/email-setup

Strips the email records and unassigns the email server. Ownership and SSL records are left alone. Returns 204.

Metrics

Sent / received / bounced counts at three scopes. Add ?from= and ?to= (RFC3339 or YYYY-MM-DD) to pick a window - the default is the last 7 days and the max range is 90 days.

EndpointScope
GET /api/emails/:domainName/:uuid/metricsMailbox total
GET /api/emails/:domainName/:uuid/metrics/dailyMailbox, daily
GET /api/emails/:domainName/metricsDomain total
GET /api/emails/:domainName/metrics/dailyDomain, daily
GET /api/emails/metrics/accountAccount total
GET /api/emails/metrics/account/dailyAccount, daily

Totals return { "sent": 0, "received": 0, "bounced": 0 }. Daily variants return an array with a date on each row.

Unsubscribes

Every message you send carries a one-click unsubscribe link. When a recipient uses it, their address is added to your domain's suppression list and you stop sending to it.

http
GET /api/unsubscribes/:domainId?page=1&limit=20

Paginated list of unsubscribed addresses on the domain. Each entry: { "id", "email", "domain", "domainId", "createdAt" }.

http
DELETE /api/unsubscribes/:domainId/:email

Removes an address from the list, which re-enables sending to it. Returns 204. An invalid domain id returns 400 "Invalid domain ID".

curl example

Create a mailbox on example.com:

bash
curl -X POST https://cloud-api.microapps.io/api/emails/example.com \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "email": "hello@example.com",
    "password": "Sup3rSecret",
    "storageSize": 5,
    "serverId": "srv_mail_1"
  }'

Built for the long tail.