Configure email domains and sender identities from the CLI.
Email Identity
AscendKit email configuration has two layers:
- A verified sending domain
- One or more verified sender identities on that domain
The CLI uses the same backend APIs as the portal. Domain setup, identity management, status refresh, default sender selection, and test sends all map to the /api/email/settings backend routes.
View current email settings
ascendkit email-identity settings
ascendkit email-identity settings --json
By default this prints a compact summary of the configured domain, DNS provider, default sender, and sender identities. Use --json to print the full backend payload.
Set up a custom domain
ascendkit email-identity setup-domain yourapp.com
ascendkit email-identity status
setup-domaincreates the SES domain identity and returns the DNS records you need to add.statuschecks the SES domain status and public DNS records together.
To remove the custom domain and reset the environment back to the AscendKit sender:
ascendkit email-identity remove-domain
Manage sender identities
List identities and refresh their SES verification state:
ascendkit email-identity list
Add a new identity:
ascendkit email-identity add [email protected] --display-name "Your App"
Update the display name for an existing identity:
ascendkit email-identity update [email protected] --display-name "New Name"
Request SES to resend inbox verification:
ascendkit email-identity resend [email protected]
Set the default sender identity:
ascendkit email-identity set-default [email protected] --display-name "Your App"
Remove an identity:
ascendkit email-identity remove [email protected]
Send a test email from a verified identity:
ascendkit email-identity test [email protected] --to [email protected]
DNS provider shortcuts
Detect the DNS provider for the configured domain and print the provider console URL:
ascendkit email-identity open-dns
You can also detect a provider for a specific domain:
ascendkit email-identity open-dns --domain yourapp.com
Email suppressions
email-suppression list shows every address currently excluded from campaign delivery in the active environment. That includes SES-style suppressions (bounce, complaint) and user opt-outs (unsubscribe).
List excluded addresses for the current environment:
ascendkit email-suppression list
ascendkit email-suppression list --reason unsubscribe
ascendkit email-suppression list --skip 0 --limit 50
| Flag | Description |
|---|---|
--reason | Filter to bounce, complaint, or unsubscribe |
--skip | Pagination offset (default 0) |
--limit | Number of rows to return (default 100, max 500) |
Remove a bounce or complaint suppression entry manually:
ascendkit email-suppression remove [email protected]
remove only applies to bounce and complaint suppressions. Unsubscribed users remain excluded until they opt back in through application logic or a future resubscribe flow.
Campaigns automatically exclude all of these addresses from delivery.
Why domain verification decides everything
Transactional email either arrives or it does not, and authentication is the largest single factor. Three DNS records matter:
| Record | Proves | Without it |
|---|---|---|
| DKIM | The message was not altered in transit | Fails authentication at major providers |
| SPF | This server may send for the domain | Higher spam placement, some rejection |
| DMARC | What to do when the other two fail | No visibility, weaker deliverability over time |
AscendKit generates the records and detects your DNS provider, automating the Cloudflare path entirely. What it cannot skip is propagation — verification is not complete until the records are visible, which is why a correct setup can still show as pending for a while.
Reputation, and why the first campaign is the risky one
Deliverability is earned per domain and per volume. A domain that sends 50 messages a day and suddenly sends 5,000 looks, to a receiver, exactly like a compromised account — and delivery degrades even with perfect DNS.
Grow volume gradually rather than launching with your largest send. This is the single most common cause of a first campaign performing far worse than the transactional email that preceded it.
Suppression protects the same reputation. Addresses that hard-bounce or file a spam complaint stop receiving mail automatically, because continuing to send to them is the fastest way to damage a domain. Suppression is separate from an explicit unsubscribe, which is why a recipient can stop receiving email without having opted out.
Troubleshooting
Verification stays pending after adding records
DNS propagation, or records added to the wrong zone — common when an apex and a subdomain are managed separately. Confirm the records resolve with dig before assuming a problem.
Email lands in spam despite passing DKIM and SPF
Authentication is necessary, not sufficient. Content and reputation also count, and a new domain has neither. Keep transactional email short and free of marketing markup — a one-line message with a single button outperforms a designed template for verification and magic-link email.
Sends work from the dashboard but not the app
Sending from your application is server-side and requires the secret key, which is never exposed to the browser. Send from a route handler or server action, never a client component.
Related
- Templates — authoring the content that gets sent
- Campaigns — bulk sending, where reputation matters most
- CLI Setup — confirming which environment you are configuring
Transactional and campaign email share a reputation
They send from the same domain, so a campaign with a high complaint rate degrades delivery of your password resets. This is why the two are separated in AscendKit rather than treated as one stream, and why campaign volume should grow gradually even when transactional volume is already healthy.
If deliverability of authentication email is critical, consider a dedicated subdomain for campaigns so the reputations are scored separately. Verify it the same way, and keep transactional sending on the domain with the longer, cleaner history.