API
A small REST API for the things you'd automate: list your domains, manage addresses, and send mail. Scoped bearer tokens, predictable errors, documented limits.
Base URL & authentication
Every endpoint lives under https://app.mailhow.com/api/v1 and authenticates with a bearer token. Create one in Settings → API tokens, choosing only the scopes it needs. The token is shown once — store it somewhere safe.
curl https://app.mailhow.com/api/v1/domains \
-H "Authorization: Bearer mh_your_token_here"A missing or invalid token returns 401. A token without the scope an endpoint requires returns 403.
Scopes
| Scope | Grants |
|---|---|
| domains:read | List your connected domains. |
| addresses:read | List addresses and aliases. |
| addresses:write | Create and delete aliases. |
| messages:send | Send mail from your addresses. |
Rate limits
60 requests per minute, per token. Exceeding it returns 429 with a Retry-After: 60 header.
Sending is additionally capped per account — the same hourly limit that applies in the web app (100 messages/hour by default). Hitting it returns 429. This protects the shared sending reputation that keeps your mail landing in inboxes; see limits & fair use.
Errors
Errors are always JSON with a single human-readable field:
{ "error": "Token is missing the \"addresses:write\" scope." }400 bad request · 401 bad token · 403 missing scope or not yours · 404 not found · 409 conflict · 429 rate limited.
Endpoints
Your connected domains and their verification state.
{
"domains": [
{
"id": "…",
"domain": "example.com",
"state": "verified",
"verifiedAt": "2026-07-01T10:00:00.000Z",
"strictDmarc": true,
"createdAt": "2026-06-20T09:00:00.000Z"
}
]
}Every address on the account: the primary one, plus each alias. masked aliases carry a lifecycle status; managed addresses are operator-controlled and read-only.
{
"addresses": [
{ "email": "you@example.com", "primary": true, "managed": false, "masked": false, "label": null, "status": null },
{ "email": "hello@example.com", "primary": false, "managed": false, "masked": false, "label": null, "status": null }
]
}Add an alias on one of your connected domains. Returns 409 if it already exists, 403if the domain isn’t yours.
curl -X POST https://app.mailhow.com/api/v1/addresses \
-H "Authorization: Bearer mh_…" \
-H "Content-Type: application/json" \
-d '{"address":"hello@example.com"}'
→ 201 { "address": "hello@example.com" }Remove an alias. URL-encode the address. The primary address, masked aliases and operator-managed addresses are refused with 409.
curl -X DELETE https://app.mailhow.com/api/v1/addresses/hello%40example.com \
-H "Authorization: Bearer mh_…"
→ 200 { "ok": true }Send a message. from must be an address you own. Sending requires a paid plan (402 otherwise) and is subject to the hourly cap above.
curl -X POST https://app.mailhow.com/api/v1/messages \
-H "Authorization: Bearer mh_…" \
-H "Content-Type: application/json" \
-d '{
"from": "you@example.com",
"to": ["someone@elsewhere.com"],
"subject": "Hello",
"text": "Sent via the MailHow API."
}'
→ 201 { "id": "…" }Optional fields: cc (array), html (string).
Versioning
This is v1. Breaking changes ship under a new version prefix — we won’t change v1 responses out from under you. Webhooks are on the roadmap.