Cloudflare DNS: keep your domain at Cloudflare, manage it from Tandem
Many teams register domains at Cloudflare and run DNS there. You don’t have to move anything to use Tandem: connect a Cloudflare API token to your organization and Tandem manages records at Cloudflare, through Cloudflare’s API. Nameservers stay where they are, the registration stays where it is, and you can disconnect at any time — nothing Tandem wrote is undone, and nothing is held hostage.
Once a zone is linked, every DNS surface on Tandem works on it exactly as it does for a Tandem-hosted zone:
- the zone editor and its MCP twins (
list/create/update/delete_dns_record,take_over_dns_record,import_dns_zone,scan_public_dns+apply_dns_scan) attach_domain— the A record for a hostname you attach to a service is written to Cloudflare and the domain goes live on its own- email onboarding (
add_email_domain), DMARC policy/reporting (set_dmarc_policy,set_dmarc_reporting) — MX/SPF/DKIM/DMARC records land at Cloudflare - email migrations that cut inbound DNS over to Tandem-hosted mail
1. Create the token at Cloudflare
Cloudflare dashboard → My Profile → API Tokens → Create Token → Create Custom Token. Give it:
| Permission | Why |
|---|---|
| Zone → Zone:Read | list the zones the token may manage |
| Zone → DNS:Edit | write records |
| Account → Domain Registrar:Read (optional) | show expiry / auto-renew / lock for domains registered at Cloudflare Registrar |
| Account → Domain Registrar:Edit (optional) | let set_domain_auto_renew flip auto-renew there |
Scope Zone Resources to the zones you want Tandem to manage (or all zones). Use an API token, not the Global API Key.
2. Connect it
Portal: Domains → Cloudflare → Connect Cloudflare. Over MCP:
{ "name": "connect_cloudflare",
"arguments": { "organizationId": "…", "apiToken": "cf-token…" } }
Tandem validates the token by listing the zones it can see, stores it encrypted (it is never returned), and by default links every visible zone (linkZones: "none" stores the connection only; pass an array of apexes to pick). The response lists one outcome per zone:
| Outcome | Meaning |
|---|---|
linked |
new Cloudflare-managed zone on Tandem, records mirrored |
converted |
your org already had this zone on Tandem’s nameservers, but Cloudflare now serves it — the zone switched to Cloudflare-managed |
already_linked |
idempotent re-link |
hosted_on_tandem |
refused: the zone is still served by Tandem’s nameservers (Cloudflare reports it pending). Point the nameservers at Cloudflare first, or keep it on Tandem |
conflict_other_org / conflict_platform |
another organization has verified this name on Tandem / it is platform infrastructure |
not_in_account |
the token can’t see that zone |
Requires the manage action and an admin (or owner) role on the org — you are storing a third-party credential for the whole organization.
3. What “linked” means
A linked zone is mode=provider_managed in Tandem. Cloudflare is the source of truth; Tandem keeps a mirror of the records so every tool can list and address them by id:
- the mirror refreshes on read when it’s older than 30 seconds, and every 5 minutes from the worker
- writes go to Cloudflare first, so your own edits are visible immediately
- records you (or other tooling) edit directly at Cloudflare show up on the next refresh
- records Tandem creates are unproxied (grey cloud). A proxied (orange-cloud) record hides the origin IP, which would make the attached-domain verification see Cloudflare’s addresses instead of Tandem’s
Zone status follows Cloudflare’s: active = Cloudflare serves it (the registrar delegates to Cloudflare’s nameservers) and attach_domain auto-publishes; awaiting_delegation = the zone exists at Cloudflare but the registrar doesn’t point at it yet — Tandem still writes records, they just aren’t live until you fix the delegation.
list_dns_records / list_domains mark these zones with provider: "cloudflare" and carry the Cloudflare zone status, nameservers, and (with Registrar permission) cloudflare.registrar.expiresAt / autoRenew / locked.
4. Registrar facts
Cloudflare’s API exposes registrar data read-only except for the auto-renew and transfer-lock flags, so for domains registered at Cloudflare Registrar:
- expiry, auto-renew and lock are shown on the zone (portal +
list_cloudflare_zones/list_domains) set_domain_auto_renewwith the hostname flips auto-renew at Cloudflare (billed by Cloudflare, not Tandem)- renewals, purchases and transfers stay in the Cloudflare dashboard — or use
transfer_domainto bring the registration to Tandem
5. Linking, unlinking, disconnecting
{ "name": "list_cloudflare_zones", "arguments": { "organizationId": "…" } }
{ "name": "link_cloudflare_zone", "arguments": { "organizationId": "…", "hostnames": ["example.com"] } }
{ "name": "unlink_cloudflare_zone", "arguments": { "organizationId": "…", "hostname": "example.com" } }
{ "name": "disconnect_cloudflare", "arguments": { "organizationId": "…" } }
Unlinking removes Tandem’s mirror only. Disconnecting deletes the stored token and unlinks every zone it backed. Neither touches anything at Cloudflare — records Tandem wrote keep serving. Attached hostnames and email domains under those zones simply stop being auto-published until DNS is somewhere Tandem can write to again (reconnect, or move the zone to Tandem’s nameservers with add_external_domain).
Troubleshooting
cloudflare_invalid_token— the token was rejected or can see no zones. Check its permissions and zone scope.- Zone shows
errorwith “cloudflare zone status: moved/deleted” — the zone was removed or moved at Cloudflare. Unlink it, or re-create it at Cloudflare and link again. - Attached domain never verifies — the record is proxied at Cloudflare (orange cloud) or the zone is still
pendingat Cloudflare. Un-proxy the record, or fix the registrar’s nameservers. registrarAccess: false— the token lacks Domain Registrar:Read; DNS management is unaffected.