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

# Auto-configure sending-domain DNS on Cloudflare

> Fix custom sending-domain DNS without leaving the dashboard: the Cloudflare auto-configure creates the provider-required records in your zone with one click, and provider verify forces a re-check after any manual DNS change.

# Auto-configure sending-domain DNS on Cloudflare

Custom sending domains verify on SPF, DKIM, and DMARC records you publish in
your DNS provider. When that DNS lives in a Cloudflare zone, Orbit can create
the missing records for you and poke the email provider (Resend) to re-verify,
all from the deliverability card on the domain row. For domains on other DNS
providers, the same page has a provider-verify button that forces the provider
to re-read the records you publish by hand.

## 1. How auto-configure works

The action reads a Cloudflare API token scoped to the domain's zone, resolves
the zone, pulls the exact record set the provider expects for your domain,
creates whatever is missing, then tells the provider to re-check. It runs
over the same record set the provider shows on the domain row, never the
platform-default domain.

The action is idempotent. Records already present in the zone (exact type,
name, and content match) are left alone; only missing ones are created. You
can rerun it after a partial failure and it picks up only what is still
missing.

Every record is created with Cloudflare proxying turned off (the
orange-cloud toggle). A proxied TXT, MX, or CNAME record is invisible to
mail infrastructure, so the DNS grid would show green while verification
fails. Auto-configure prevents that specific trap.

You can repeat as many times as you need. Cloudflare reports the final plan
record by record: created, already present, or rejected with the provider's
error message.

### What the flow does under the hood

1. **Resolve the zone.** It walks up the domain's labels
   (`mail.acme.com` → `acme.com`) until Cloudflare returns an active zone your
   token can see.
2. **Read the required set.** It asks the provider for the authoritative
   record list — the same records the provider's own dashboard shows, so a
   stale provider cache cannot green-light a missing record.
3. **Diff against the zone.** It plans an exact match on type, name, and
   content per record. TXT records at the same name with different content are
   additive in DNS, so a mismatch schedules a creation — it never overwrites
   one of your unrelated records.
4. **Publish and prove.** It creates each gap with proxying off, pokes the
   provider to re-verify, stores the token only once it has shown it works,
   and reports the provider's live state.

## 2. Set up the token

Create a Cloudflare API token with **Zone → DNS → Edit** on the zone that
serves your sending domain (for `mail.acme.com`, scope the `acme.com` zone).
Paste it into the auto-configure dialog on the domain row. Orbit stores it
encrypted (`settings.email.cloudflare_token`) after the first successful run,
so subsequent reconfigures do not need to paste anything.

<Warning>Give the token the narrowest scope that works — one zone, DNS edit only — and rotate it if you regenerate the Cloudflare credentials. Orbit never logs the token and never returns it in any response.</Warning>

If the stored token stops working, supply a new one on the next run and it
replaces the stored value only after that run succeeds.

## 3. Run it from the dashboard

1. Open **Channels → Email**, find your custom sending domain, and expand
   the deliverability card.
2. Choose **Cloudflare auto-configure**.
3. Paste the token on the first run; leave the field empty on later runs
   to reuse the stored one.
4. Read the result per record. Anything marked `already_present` was
   already there; `error` carries the provider's rejection so you can fix
   the qualifier (for example a name collision) and rerun.

The response also reports the provider state after the re-verify kick:
`sendable` when the provider accepts the DNS, `unverified` while it is
still re-checking, or `unknown` when the provider gave no definitive answer.

## 4. Provider verify — the manual path

If your DNS is managed outside Cloudflare (Registrar DNS, another DNS
provider, or an internal resolver), publish the provider-required records
by hand — the deliverability card shows them all — then choose
**Verify provider**. The action forces the provider to re-read your DNS
right now, without also re-running the live DNS resolve the full refresh
does.

Provider verify also proves a manual fix on a Cloudflare domain if you
prefer to own the zone yourself. It is a no-op on the platform-default
domain, which Orbit manages.

The response tells you whether the provider accepted the kick and shows
the freshly probed provider-verification card, so a refresh loop on the
page picks up the live answer immediately.

Cloudflare deletions and edits publish quickly, but public resolvers can
cache the old answer. If provider verify still shows pending after a
manual change, wait for the TTL you saw on the previous record and verify
again.

## 5. Choose between the two

| Situation                                                                                       | Use                                                                           |
| ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------- |
| DNS is in a Cloudflare zone you can permit Orbit to edit                                        | Cloudflare auto-configure                                                     |
| DNS is managed somewhere else                                                                   | Verify provider (after publishing records by hand)                            |
| Auto-configure returned a `CLOUDFLARE_TOKEN_REQUIRED` error and you prefer not to store a token | Verify provider                                                               |
| You want to keep Cloudflare out of Orbit entirely                                               | Verify provider                                                               |
| RCS/brand or other matrix surfaces read from the same domain row                                | Re-check the matrix after either action — they converge on the provider state |

## 6. Security

* **Token scope.** A Zone → DNS → Edit token on one zone. Nothing else.
* **Encrypted storage.** The token sits next to your other provider
  credentials, encrypted at rest, and is written only after a run proves it.
* **No log exposure.** The token is never logged and never returned.
* **Owner/admins only.** The auto-configure route is gated to owner and
  admin roles, same as other write actions against the sending domain.

## 7. Troubleshooting

* **`CLOUDFLARE_TOKEN_INVALID` (400).** The token was rejected. Recreate it
  with Zone → DNS → Edit on the right zone and retry.
* **`CLOUDFLARE_ZONE_NOT_FOUND` (404).** No active Cloudflare zone matched
  any label of the domain. Check the zone status and the token's zone scope.
* **`CLOUDFLARE_TOKEN_REQUIRED` (400).** No token in the body and none
  stored. Paste one or run provider verify instead.
* **`PROVIDER_DOMAIN_UNAVAILABLE` (502).** The provider has no record set
  for the domain yet. Re-add the sending domain under Channels → Email,
  then rerun.
* **A record marked `error` in the plan.** The provider or Cloudflare
  rejected that specific record. The response carries the message; fix the
  named qualifier and rerun.
* **Mixed provider-matrix outcomes.** Some matrix surfaces read the provider
  state from their own cached probe. They re-resolve on their next poll —
  the deliverability card will catch up within its normal cadence.
* **Record existed but with a trailing dot or case difference.** Both the
  diff and lookup normalize for these, so they register as `already_present`
  rather than a duplicate creation.
