AgentPost
Guides

Custom Domains

Send email from your own domain with full DNS verification

Custom domains let you send and receive email from addresses like support@yourdomain.com instead of the shared @shared.agent-post.dev domain. This guide covers the complete setup process: adding a domain, configuring DNS records, verifying, and managing ongoing domain health.

Why use a custom domain?

BenefitDescription
Professional appearanceEmails come from your brand, not a shared domain
Better deliverabilityBuild your own sending reputation
Catch-all supportRoute all email for your domain to an inbox
Full DNS controlConfigure SPF, DKIM, and DMARC to your specifications

Step 1: Add the domain

import AgentPost from 'agentpost';

const client = new AgentPost({ apiKey: 'ap_sk_...' });

const domain = await client.domains.create({
  domain: 'acmeco.com',
});

console.log(`Domain added: ${domain.domain}`);
console.log(`Status: ${domain.verification_status}`); // "pending"
console.log(`DKIM tokens: ${domain.dkim_tokens}`);
from agentpost import AgentPost

client = AgentPost(api_key="ap_sk_...")

domain = client.domains.create(domain="acmeco.com")

print(f"Domain added: {domain.domain}")
print(f"Status: {domain.verification_status}")  # "pending"
print(f"DKIM tokens: {domain.dkim_tokens}")
curl -X POST https://api.agent-post.dev/api/v1/domains \
  -H "Authorization: Bearer $AGENTPOST_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"domain": "acmeco.com"}'

Step 2: Configure DNS records

After adding the domain, you need to create several DNS records. AgentPost provides the exact values.

MX record

Route incoming email for your domain to AgentPost:

acmeco.com.    MX    10    inbound-smtp.us-east-1.amazonaws.com.

SPF record

Authorize AgentPost (via SES) to send email on behalf of your domain:

acmeco.com.    TXT    "v=spf1 include:amazonses.com ~all"

DKIM records

Add the three DKIM CNAME records provided by AgentPost. These are unique to your domain:

token1._domainkey.acmeco.com.    CNAME    token1.dkim.amazonses.com.
token2._domainkey.acmeco.com.    CNAME    token2.dkim.amazonses.com.
token3._domainkey.acmeco.com.    CNAME    token3.dkim.amazonses.com.

DMARC record

Set up a DMARC policy for monitoring or enforcement:

_dmarc.acmeco.com.    TXT    "v=DMARC1; p=none; rua=mailto:dmarc@acmeco.com"

Start with p=none (monitoring only) and move to p=quarantine or p=reject once you verify alignment.

MAIL FROM record (optional)

Configure a custom MAIL FROM domain for better deliverability:

mail.acmeco.com.    MX     10    feedback-smtp.us-east-1.amazonaws.com.
mail.acmeco.com.    TXT    "v=spf1 include:amazonses.com ~all"

Step 3: Download BIND zone file

For convenience, download a complete BIND-format zone file with all required records:

const zoneFile = await client.domains.getZoneFile(domain.id);
console.log(zoneFile);
// Contains all DNS records in BIND format, ready to paste into your DNS provider
zone_file = client.domains.get_zone_file(domain.id)
print(zone_file)
curl "https://api.agent-post.dev/api/v1/domains/$DOMAIN_ID/zone-file" \
  -H "Authorization: Bearer $AGENTPOST_API_KEY"

Step 4: Verify the domain

After configuring DNS records, trigger verification:

const result = await client.domains.verify(domain.id);
console.log(`Verification status: ${result.verification_status}`);
// "verified" if all DNS records are correctly configured
// "pending" if DNS changes have not propagated yet
result = client.domains.verify(domain.id)
print(f"Verification status: {result.verification_status}")
curl -X POST "https://api.agent-post.dev/api/v1/domains/$DOMAIN_ID/verify" \
  -H "Authorization: Bearer $AGENTPOST_API_KEY"

DNS propagation

DNS changes can take up to 48 hours to propagate, though most changes are visible within 15 minutes. If verification fails, wait and try again.

Step 5: Create inboxes on your domain

Once verified, create inboxes using your custom domain:

const inbox = await client.inboxes.create({
  username: 'support',
  display_name: 'AcmeCo Support',
  domain_id: domain.id,
});

console.log(`Inbox: ${inbox.email}`);
// => support@acmeco.com
inbox = client.inboxes.create(
    username="support",
    display_name="AcmeCo Support",
    domain_id=domain.id,
)

print(f"Inbox: {inbox.email}")
# => support@acmeco.com
curl -X POST https://api.agent-post.dev/api/v1/inboxes \
  -H "Authorization: Bearer $AGENTPOST_API_KEY" \
  -H "Content-Type: application/json" \
  -d "{\"username\": \"support\", \"display_name\": \"AcmeCo Support\", \"domain_id\": \"$DOMAIN_ID\"}"

Catch-all inboxes

Enable catch-all to route any email sent to your domain (even non-existent addresses) to a specific inbox:

await client.domains.setCatchAll(domain.id, {
  inbox_id: 'inb_abc123',
});

// Now emails to anything@acmeco.com will be delivered to inb_abc123
client.domains.set_catch_all(
    domain_id=domain.id,
    inbox_id="inb_abc123",
)
curl -X PUT "https://api.agent-post.dev/api/v1/domains/$DOMAIN_ID/catch-all" \
  -H "Authorization: Bearer $AGENTPOST_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"inbox_id": "inb_abc123"}'

Catch-all is only available on verified custom domains (not the shared domain).

Verification flow

Added (pending) --> DNS configured --> Verify triggered
    |                                       |
    |                               +-------+-------+
    |                               |               |
    |                           Verified        Still pending
    |                               |               |
    |                               v               v
    |                           Active          Retry later
    |                               |
    +-- Re-verification every 4h ---+
    |                               |
    v                               v
Suspended (48h failures)        Still verified

If a domain fails re-verification for 48 consecutive hours, it is suspended and sending is paused on all associated inboxes.

Monitoring domain health

const domain = await client.domains.get('dom_abc123');

console.log(`Domain: ${domain.domain}`);
console.log(`Status: ${domain.verification_status}`);
console.log(`Last verified: ${domain.last_verified_at}`);
domain = client.domains.get("dom_abc123")

print(f"Domain: {domain.domain}")
print(f"Status: {domain.verification_status}")
print(f"Last verified: {domain.last_verified_at}")
curl "https://api.agent-post.dev/api/v1/domains/$DOMAIN_ID" \
  -H "Authorization: Bearer $AGENTPOST_API_KEY"

Tips

  • Inboxes can be created on unverified custom domains, but sending and receiving are blocked until the domain is verified
  • Always start with a p=none DMARC policy and monitor before enforcing
  • The BIND zone file download includes all required records in copy-paste format
  • Re-verification runs automatically every 4 hours to ensure DNS records remain valid
  • Domain verification events (verified, suspended, deleted) are available via webhooks
  • For production domains, configure MAIL FROM for better deliverability scores

On this page