> ## Documentation Index
> Fetch the complete documentation index at: https://docs.politicalcomms.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Sending Domains and DNS

> Adding a domain, the DNS records to publish for email sending, how each one is confirmed, drift detection, and why we never write DNS for you.

Before you can send a single email you have to prove you own the domain you want
to send from. That proof is a set of DNS records you publish in your own zone.
This page is the whole of it: what to add, where, and how to tell when it worked.

## Why DNS is manual

We never write records in your zone, and we never ask for your registrar
credentials. Your DNS is the control plane for your entire online presence:
handing a vendor write access to it so they can add three CNAMEs is a bad trade,
and it is one you cannot easily undo. We generate the exact records; you publish
them.

This is the one part of setup that needs someone with access to your DNS
provider. Everything after it happens in the app.

## Adding a domain

Sending domains are added on **Admin > Domains**, which is the one page for
every domain the platform uses. Click **Add domain** and you type your root
domain **once**:

<Steps>
  <Step title="Enter your root domain">
    `candidate.com`, not a subdomain. This is the organizational domain
    everything else hangs off.
  </Step>

  <Step title="Pick what it is for">
    Tick any combination of the three uses. **Email** is the sending domain.
    **Link tracking** is the host your click and unsubscribe links use.
    **App** is a branded dashboard hostname. Most people adding email want
    email and link tracking together, so the links in your mail carry your
    domain rather than ours.
  </Step>

  <Step title="Accept or edit the subdomains">
    Each use gets a suggested subdomain, prefilled and editable: `mail.` for
    email, `links.` for tracking, `app.` for the dashboard.
  </Step>

  <Step title="Publish the records">
    One table lists every record for every use you picked. Add them at your DNS
    provider and the page tracks them as they land.
  </Step>
</Steps>

Before it generates anything the dialog runs a **pre-flight check** against the
host you are creating. It names your DNS provider, warns about a conflicting SPF
record, and refuses to continue while there is a hard conflict such as a CNAME on
an apex you also need other records at. This is much cheaper to find out now than
after a failed send.

### Use a subdomain

Send from `mail.candidate.com`, not from `candidate.com` itself. A subdomain
keeps campaign sending reputation separate from the domain your staff email
from, so a bad list cannot damage your day-to-day mail. It is the default the
dialog suggests, and it is the right one for almost everyone.

## The records

Publish all of them. There are seven, or eight if we generate a DMARC record for
you.

| Record | Type | Host | Value |
| - | - | - | - |
| DKIM key 1 | `CNAME` | `<token>._domainkey.<sending domain>` | A signing host on our sending infrastructure |
| DKIM key 2 | `CNAME` | `<token>._domainkey.<sending domain>` | A signing host on our sending infrastructure |
| DKIM key 3 | `CNAME` | `<token>._domainkey.<sending domain>` | A signing host on our sending infrastructure |
| Bounce host | `MX` | `bounce.<sending domain>` | Our feedback host, priority `10` |
| Bounce SPF | `TXT` | `bounce.<sending domain>` | An SPF record authorizing our sending infrastructure |
| DMARC | `TXT` | `_dmarc.<root domain>` | `v=DMARC1; p=none; adkim=r; aspf=r` with a reporting address |
| Domain verification | `TXT` | `_sender-verification.<sending domain>` | `sender-verification=` followed by a value unique to your organization |
| Postmaster ownership | `TXT` | `<root domain>` | `google-site-verification=...` |

Six things worth knowing about that table:

* **The domain verification record proves your organization controls the
  domain.** The value is unique to your organization, so it is the part nobody
  else can publish for you. Publish it even if the other records already show
  as verified. The domain stays **Verifying** until we see it.
* **The bounce host is always `bounce.` under your sending domain.** For
  `mail.candidate.com` it is `bounce.mail.candidate.com`. That pair of records
  is what gives you SPF **alignment**: DKIM alone will authenticate your mail,
  but publishing both is what satisfies the bulk-sender requirements at Gmail
  and Yahoo.
* **The DMARC record is omitted entirely if your root domain already publishes
  one.** We will not ask you to add a second `_dmarc` record, because two of
  them is a permanent error that breaks the policy you already have. Your
  existing policy is inherited and satisfies alignment on its own. See
  [DMARC progression](/help/email/campaigns-and-deliverability#dmarc) for moving
  an existing policy forward.
* **The DMARC record includes a reporting address.** Mailbox providers send
  their aggregate reports there, and the reports are what fill the DMARC page
  and let the policy move forward. If you set up your domain before the record
  carried one, add the reporting address shown in the domain's DMARC panel to your
  DMARC record as a `rua=mailto:` tag; reports start arriving once it is
  published.
* **DMARC and Postmaster records go on the ROOT domain**, not the sending
  subdomain. Everything else goes on the sending subdomain. This is the single
  most common place to get it wrong.
* **The Postmaster record has no value at first.** It stays blank until Google
  issues a token, usually within minutes. Publish it once the value appears. It
  is optional: nothing about your sending depends on it, and it only unlocks
  reporting. See [Google Postmaster Tools](/help/email/google-postmaster-tools).

## How each record is confirmed

A record is not done because we saw it once. Seeing a record in DNS proves it
resolves; it does not prove the service that needs it has accepted it. So every
record has a **confirming signal** beyond our own lookup, and the capability it
belongs to turns on only when that signal fires:

| Record | Confirmed by |
| - | - |
| The three DKIM CNAMEs | Our sending infrastructure reporting DKIM as verified |
| The bounce MX and SPF pair | Our sending infrastructure reporting the bounce domain as verified |
| DMARC | Our own DNS lookup, since nothing else consumes it |
| Domain verification | Our own DNS lookup, since the value is specific to your organization |
| Postmaster ownership | Google confirming the token |

The practical effect: a DKIM record that resolves perfectly but has not yet been
accepted upstream shows as **Verifying**, not Active. That is not a bug, and the
usual fix is to wait a few minutes.

### Per-record status

Each row in the table carries its own state, so you can see exactly which record
is holding things up rather than staring at one domain-level "pending":

| State | Meaning |
| - | - |
| **Not started** | Nothing seen yet. |
| **Pending** | We are looking and have not found it. |
| **Verifying** | Found in DNS, waiting on the confirming signal. |
| **Active** | Confirmed. Done. |
| **Changed** | Was working, and no longer matches. See drift below. |
| **Failed** | Verification was abandoned. |

### Verify now

**Verify now** on the domain's row re-checks immediately rather than waiting for
the next scheduled poll. It works in **every** state, which is the useful part:
on a pending domain it pushes verification forward, and on an active domain it
re-checks a record that may have been removed, so a broken record surfaces on
demand instead of silently breaking your links.

Use it after publishing records rather than refreshing the page repeatedly. If
you hit it many times in a few minutes you may be rate limited; wait a moment and
try again.

## Drift detection

DNS records get deleted. A zone gets migrated, a provider gets changed, someone
tidying up removes a CNAME they did not recognize. Without detection, the first
you would hear of it is a campaign that stopped authenticating.

Active domains are re-checked on a schedule, and a record that no longer matches
is flagged as **Changed**, with its capability downgraded until it is fixed.
Drift is declared in two cases, deliberately not one:

* **Immediately**, when your zone is serving a **different value**. Someone
  edited the record, which is not ambiguous.
* **On the second consecutive miss**, when the record is simply not found. A
  single lookup failure is usually a resolver hiccup or mid-propagation, not a
  deleted record, and flapping a healthy domain to broken and back helps nobody.

The counter resets the moment the record is seen again.

## When verification stalls

In rough order of how often each one turns out to be the cause:

1. **The record went in the wrong zone.** Added at the root when it belonged on
   the sending subdomain, or the reverse. DMARC and Postmaster go on the root;
   DKIM and the bounce pair go on the sending subdomain.
2. **The registrar appended the domain to an already-complete host name**,
   producing `x._domainkey.mail.candidate.com.candidate.com`. Many DNS UIs add
   the zone for you. If yours does, enter only the part before your domain.
3. **A proxy is on.** A record set to "proxied" rather than "DNS only" is
   rewritten in the answer, so what we see is not what you published.
4. **It has not propagated yet.** Usually minutes, occasionally longer if the
   old record had a long TTL.

## Domain statuses

| Status | Meaning |
| - | - |
| **Pending records** | Records generated; publish them. |
| **Verifying** | Records found, waiting on confirming signals. |
| **Active** | Confirmed. The domain can carry sender identities and send. |
| **Failed** | Verification was abandoned. Delete the domain and re-add it to start over. |
| **Suspended** | Sending has been stopped on this domain. Contact support. |

## Using a domain that already has email

You can send from your main domain or from a subdomain, including a domain that
already has mailboxes (Google Workspace, Microsoft 365) or is already set up for
sending somewhere else.

* **Your existing email is not affected.** Nothing on this page changes where
  the domain's own mail is delivered, and none of it changes the SPF record you
  already publish. Every record we ask for sits on a subdomain of your sending
  domain (`bounce.`, `_sender-verification.`, and the DKIM hosts), apart from
  the optional DMARC and Postmaster records on the root.
* **A subdomain is still the usual recommendation.** `mail.candidate.com` keeps
  campaign sending reputation separate from the domain your staff email from.
* **An existing bounce record is recognized.** If the bounce record already
  exists and already authorizes this platform, it is reported as already in
  place and you have nothing to change.

## Sharing a domain

More than one organization can send from the same domain, for example an agency
and its client. Each organization publishes its own domain verification record
at the same host, and a domain can hold several of them side by side. Your
organization can send only once its own record is seen, so one organization
verifying a domain never verifies it for another.

## Deleting a domain

A domain with live sender identities on it cannot be deleted; the request
returns `409 CONFLICT`. Remove or move the identities first. This is deliberate:
deleting the domain out from under an active identity would break sending
mid-campaign rather than at the moment you asked for it.

Removing a domain stops your organization's campaigns from using it. It never
changes your DNS or your mailboxes, and it never removes sending setup that
another organization on the same domain still relies on. Your domain
verification record can be deleted once the domain is removed. Leave the DKIM
and bounce records in place if anyone else sends from this domain: they are
shared, and deleting them stops that sending too.

## Over the API

Domains are read-only on the API: you add one in the dashboard under
**Admin > Domains**, which shows the DNS records to publish. Publish them, then
poll the domain until `status` is `active`.

```bash theme={null}
curl https://api.politicalcomms.com/v1/email/domains/{id} \
  -H "X-API-Key: pc_live_..."
```

The response carries `dns_records` and `status`. Full response shapes are in
the [API reference](/api-reference/introduction).

## What comes next

Once the domain is active, create a
[sender identity](/help/email/campaigns-and-deliverability#sender-identities) on
it. A domain by itself cannot send; the identity is the From address, and it
carries the physical address and disclaimer that go in every footer.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.