Documentation

Email deliverability

Configure your sender domain — provider registration, SPF, DKIM, DMARC — so your messages land in the inbox.

Two things stop email from reaching the inbox: misconfigured authentication and bad sender reputation. The Broadcast module addresses both — it provisions DNS through whatever email provider the org has connected (SES, SendGrid, Mailgun, Resend) and tracks reputation per sender account so you know when to slow down.

Step 1: connect a provider

Email goes through whatever provider your org has connected via Upstream. One of:

  • AWS SES — high deliverability, low cost, requires production-mode access for non-trivial volume
  • SendGrid — easiest setup, mature event webhooks
  • Mailgun — strong EU presence, mailing-list features
  • Resend — newest, simplest API

Connect via POST /upstream/save-integration with the provider type. See Twilio integration for the same flow applied to a different vendor.

Step 2: register the domain

POST/broadcast/domains/registerJWT
{ "domain": "acme.com" }

Returns the DNS records the provider wants you to publish (SPF, DKIM, sometimes a return-path CNAME). The provider also creates an internal "domain" or "identity" record on its side.

{
  "success": true,
  "domain": "acme.com",
  "domainId": "...",
  "verified": false,
  "dkimStatus": "Pending",
  "records": [
    { "purpose": "DKIM", "type": "CNAME", "name": "abc123._domainkey.acme.com", "value": "abc123.dkim.amazonses.com" },
    { "purpose": "DKIM", "type": "CNAME", "name": "def456._domainkey.acme.com", "value": "def456.dkim.amazonses.com" },
    { "purpose": "DKIM", "type": "CNAME", "name": "ghi789._domainkey.acme.com", "value": "ghi789.dkim.amazonses.com" }
  ]
}

Step 3: publish DNS records

Add the records to your DNS — through your registrar, Cloudflare, Route 53, whatever you use.

You'll typically need three categories:

  • SPF — TXT on the apex domain. Authorizes your provider's MTAs to send for you.
  • DKIM — three CNAMEs (or one TXT, depending on provider). Cryptographic signature.
  • DMARC — TXT on _dmarc.<domain>. Policy that tells receivers what to do with unauthenticated mail.

A reasonable starting DMARC: v=DMARC1; p=quarantine; rua=mailto:[email protected]. Move to p=reject once SPF and DKIM are passing for all your sending sources.

Step 4: verify

GET/broadcast/domains/status/{domain}JWT

This endpoint does three things:

  1. Asks the provider whether it has verified the domain (DKIM tokens visible, SPF aligned).
  2. Performs a live DNS lookup of SPF, DKIM, and DMARC.
  3. Compares them and returns per-record status: verified | invalid | missing.
{
  "domain": "acme.com",
  "registeredWithProvider": true,
  "providerVerified": true,
  "isOurDomain": false,
  "allVerified": true,
  "records": [
    { "purpose": "SPF",  "status": "verified", "type": "TXT", ... },
    { "purpose": "DKIM", "status": "verified", "type": "CNAME", ... },
    { "purpose": "DMARC","status": "verified", "type": "TXT", ... }
  ],
  "currentDNS": { "a": [...], "cname": [...], "mx": [...] }
}

DNS propagation can take 5-60 minutes. Poll this endpoint every 30 seconds in the UI until allVerified: true.

Auto-configure (registered through AppMint)

If you bought the domain through AppMint (ResellerClub, Cloudflare, or internal registrar), AppEngine can write the DNS records for you:

POST/broadcast/domains/auto-configureJWT
{ "domain": "acme.com" }

The endpoint:

  1. Calls /broadcast/domains/status/{domain} to know what's needed.
  2. Talks to the registrar API to add SPF, DKIM, DMARC, and any return-path records.
  3. Re-checks status and returns the result.

Only works for domains where purchasedThroughUs: true and the registrar is resellerclub, cloudflare, or internal. External domains stay manual.

Single-email verification (no domain)

For one-off senders without their own domain (e.g., [email protected]), some providers let you verify a single email address:

POST/broadcast/domains/register-emailJWT
{ "email": "[email protected]" }

Returns immediately; the provider sends a verification link to the inbox. Click it, then check status:

GET/broadcast/domains/email-status/{email}JWT

This is fine for transactional sends from a personal mailbox but not for bulk — domain auth is required for any meaningful volume.

Live DNS validators (no provider needed)

GET/broadcast/validate/domain/{domain}No auth
GET/broadcast/validate/email/{email}No auth

Pure DNS lookups — SPF, DKIM, DMARC, MX, CNAME. Useful as a sanity check before kicking off provider registration, or to debug an existing setup that's failing in the wild.

Sender reputation

Each email_account (the sending identity, e.g., [email protected]) has a daily health check that records:

  • Reputation score (0-100)
  • Bounce rate
  • Spam-complaint rate
  • DNS verified state
GET/broadcast/healthJWT
POST/broadcast/health/{accountId}/checkJWT

The dashboard view shows summary counters across the org. Per-account history is held in email_health records (one daily snapshot for at least 30 days).

When bounceRate > 3%, health.status flips to flagged. The send pipeline then prefers other accounts in the same broadcast's rotation set, gradually warming the flagged account back up.

Multi-account warmup

A new domain shouldn't start at 100k emails/day. Configure several email_account records ([email protected][email protected]) all on the same domain, set autoRotate: true, and choose a rotation strategy on each broadcast:

  • healthiest — pick the account with the best score for each batch
  • round_robin — even distribution
  • random — random pick
  • priority_based — use accounts with higher priority first

Combined with low daily caps in early weeks, this gives the domain a reputation ramp.

Don't skip DMARC

Major mailbox providers (Gmail, Yahoo) increasingly drop unauthenticated mail. SPF + DKIM alone is no longer enough; publish a DMARC record (p=quarantine is fine to start) on day one.