Email Services & API for Private Clients

Agents can sign up themselves

Sign up with a username. An email is optional. A username that looks like an email is not a verified email. No mail is sent to it.

A username is 3 to 64 characters: letters, digits, and . _ - + @. It is stored case-insensitively. Reserved names such as admin, root, postmaster, and abuse are refused.

If you pass contactEmail, the 8-digit email code flow is unchanged. If you omit contactEmail, pass username, domain, agentName, and intendedUse. The response includes a TXT record. Publish it at exactly _msn-verify.<domain> (that name only). The token expires in 24 hours and works once. Then call verify_access_request with requestId and method dns. Poll get_request_status with requestId and username about every 20 minutes. The key is returned once, on verify when the account is ready, or on a fresh request_access plus verify_access_request after it becomes ready. get_request_status does not return the key. Then call get_account_status with the key. mailservicenow.com and its subdomains cannot use this DNS check.

Lost the key and have no email: call request_access again with the same username and the account domain, publish the new TXT, and verify with method dns. A new key is returned once.

Approval and autonomous onboarding

Self-service does not mean self-approval. After proof verification, service policy may approve the account; otherwise a Mail Service Now owner/admin must decide. Polling checks that decision and never returns a key. A standard key cannot approve itself or change service approval rules.

After approval, call list_domains, add_domain if needed, get_dns_instructions, and verify_domain. The last two take domainId. Publish DNS records externally with the owner's authorization. Add the hosted address with add_mailbox, then check get_account_status.canSend and mailbox mtaApplied separately. No UID override or cross-account domain access is available through these domain tools.

DNS-bound key recovery revokes all previous customer keys; email recovery adds a key. Save a successful key and do not recover on every ready poll. Approval, domain verification and live mailbox delivery are separate checks. Pricing remains tailored through Contact/Apply. See the full onboarding state machine and error/retry contract.

Domain ownership comes before mailbox access

Every new claim gets a unique account-bound TXT at _msn-domain.<domain>, with the exact msn-domain-verification=… value returned in the DNS instructions. The ownership object exposes required, expiresAt and verifiedAt. Shared mail DNS alone is not ownership proof. The signup _msn-verify challenge is separate.

The initial ownership proof expires after 24 hours. On 409 domain_ownership_expired, call add_domain again, publish the renewed TXT and verify. Before expiry the same call preserves its token. Proven ownership persists for that claim; removal/re-add requires fresh proof. Unproven new claims cannot create mailboxes (403 domain_ownership_required). A concurrent claim change returns 409 domain_claim_changed; reload the current state.

Previously verified domains keep working without migration; unverified legacy domains receive a challenge lazily. Legacy verified ownership still needs a separate operator audit. A domain reserved by another account remains 409 domain_claimed, including abandoned unverified claims. Contact support for review instead of trying to transfer it automatically.

REST

export MSN_API_BASE=https://us-central1-mailservicenow.cloudfunctions.net
curl -sS -X POST "$MSN_API_BASE/requestAccess" \
  -H "Content-Type: application/json" \
  -d '{"username":"agent-one","domain":"example-domain.com","agentName":"ExampleAgent","intendedUse":"Send a notification from an agent"}'
curl -sS -X POST "$MSN_API_BASE/verifyAccessRequest" \
  -H "Content-Type: application/json" \
  -d '{"requestId":"ar_0123456789abcdef01234567","method":"dns"}'
curl -sS -X POST "$MSN_API_BASE/getRequestStatus" \
  -H "Content-Type: application/json" \
  -d '{"requestId":"ar_0123456789abcdef01234567","username":"agent-one"}'

MCP

POST each JSON body to https://us-central1-mailservicenow.cloudfunctions.net/mcp with Content-Type: application/json and no Authorization header.

{"jsonrpc":"2.0","id":1,"method":"tools/call","params":{"name":"request_access","arguments":{"username":"agent-one","domain":"example-domain.com","agentName":"ExampleAgent","intendedUse":"Send a notification from an agent"}}}
{"jsonrpc":"2.0","id":2,"method":"tools/call","params":{"name":"verify_access_request","arguments":{"requestId":"ar_0123456789abcdef01234567","method":"dns"}}}
{"jsonrpc":"2.0","id":3,"method":"tools/call","params":{"name":"get_request_status","arguments":{"requestId":"ar_0123456789abcdef01234567","username":"agent-one"}}}

Longer copy: llms.txt, Markdown guide, Agent API, OpenAPI.