Agent Mail by Ackuna

Every page here is also markdown — add .md to the URL.

Receiving domains

A custom domain lets your agent send and receive mail on a hostname you control — mail.acmerobotics.com instead of the shared platform domain (agentmail.ackuna.com). It is a self-serve, paid-plan feature: registering one provisions a linked sending identity for that hostname and returns the DNS records you need to publish. Once they verify, Ackuna activates the domain by itself — no manual review — and it can host inboxes.

Why register one. Sending from the shared domain agentmail.ackuna.com (and from existing inboxes on the earlier shared domain agents.ackuna.com) is limited to 100 messages a day per account, both domains together. Mail from inboxes on your own domain is not subject to that limit; your plan's limits, the limits for new workspaces and the workspace's hourly send limit still apply. The domain needs an MX record pointing at our inbound server, and its DKIM records. If your main domain already receives mail elsewhere (Google Workspace, Microsoft 365), register a subdomain such as mail.example.com.

The receiving domain object

{
  "id": "dom_01k2n9v8qf3m7d5b0y6xz4rt3e",
  "object": "receiving_domain",
  "domain": "mail.acmerobotics.com",
  "status": "active",
  "mx_status": "ok",
  "dkim_status": "ok",
  "required_records": [
    {"type": "MX", "name": "mail.acmerobotics.com", "value": "inbound-smtp.us-east-1.amazonaws.com", "priority": 10},
    {"type": "CNAME", "host": "sj4f9k2m1q7r._domainkey", "value": "sj4f9k2m1q7r.dkim.amazonses.com", "status": "verified"},
    {"type": "CNAME", "host": "b8n3x6w0p5t2._domainkey", "value": "b8n3x6w0p5t2.dkim.amazonses.com", "status": "verified"},
    {"type": "CNAME", "host": "h1c7y4v9e2u6._domainkey", "value": "h1c7y4v9e2u6.dkim.amazonses.com", "status": "verified"}
  ],
  "verified_at": "2026-08-20T09:12:00.000Z",
  "activated_at": "2026-08-20T09:14:00.000Z",
  "created_at": "2026-08-20T09:00:00.000Z"
}

status moves through pending (just registered, no DNS confirmed yet) → verifying (MX has been seen; DKIM and the sending identity are still being confirmed) → active (fully verified and usable in POST /v1/inboxes) automatically — there is no manual activation step. A domain that never reaches active within 14 days of registration is marked stale: it stops being probed, and its hostname is freed for your own organization to register again (a different organization registering the same hostname still gets domain_taken).

mx_status reflects the outcome of the most recent automated MX probe (missing, ok, or mismatched). dkim_status reflects the automated check of this domain's linked sending identity's DKIM CNAMEs: pending until every CNAME verifies, then ok. required_records is always the current, complete list of DNS records to publish — one MX record (enables receiving) plus the sending identity's DKIM CNAME records (enable sending, and prove control of the domain). The domain becomes able to send once its linked sending identity finishes verifying, so publish the DKIM records promptly if you plan to send as well as receive. There is no webhook event for activation; poll GET /v1/domains/{domain} and watch status.

List receiving domains

GET /v1/domains?limit=25
Authorization: Bearer ak_...

Requires scope domains:read.

Register a receiving domain

POST /v1/domains
Authorization: Bearer ak_...
Content-Type: application/json
Idempotency-Key: register-mail-domain-1

{"domain": "mail.acmerobotics.com"}
{
  "data": {
    "id": "dom_01k2n9v8qf3m7d5b0y6xz4rt3e",
    "object": "receiving_domain",
    "domain": "mail.acmerobotics.com",
    "status": "pending",
    "mx_status": "missing",
    "dkim_status": "pending",
    "required_records": [
      {"type": "MX", "name": "mail.acmerobotics.com", "value": "inbound-smtp.us-east-1.amazonaws.com", "priority": 10}
    ],
    "verified_at": null,
    "activated_at": null,
    "created_at": "2026-08-20T09:00:00.000Z"
  }
}

Requires scope domains:write and a paid plan with custom-domain capacity remaining (the free tier has none). domain is required — a hostname, lowercased before use, up to 253 characters. Registering provisions a linked sending identity for the hostname in the background, so the three DKIM CNAME records are added to required_records within moments of this response, not necessarily inside it — poll GET /v1/domains/{domain} to pick them up. Publish every record required_records ends up listing at your DNS provider, then keep polling GET /v1/domains/{domain} until status is active. Once active, pass this domain's id as domain on POST /v1/inboxes to host an inbox there.

403 quota_exceeded if the organization has no custom-domain capacity left on its plan (including the free tier, which has none). 422 invalid_request if the hostname fails validation or names the platform's own shared domain (which cannot be registered by any organization); 422 domain_taken if the hostname is already registered.

Fetch a receiving domain

GET /v1/domains/dom_01k2n9v8qf3m7d5b0y6xz4rt3e
Authorization: Bearer ak_...

Requires scope domains:read. Returns the current object — the fastest way to check what requirement is still outstanding while onboarding a domain. 404 not_found for an unknown or cross-organization id.

Delete a receiving domain

DELETE /v1/domains/dom_01k2n9v8qf3m7d5b0y6xz4rt3e
Authorization: Bearer ak_...
Idempotency-Key: delete-mail-domain-1

Requires scope domains:write. Returns {"data": null}. 409 invalid_request if the domain still hosts one or more inboxes — move or delete them first. 404 not_found for an unknown or cross-organization id.

See Errors for the full error-code reference, or Versioning for how this contract changes over time.