Guides

Domain Connect — one-click DNS

AdminUpdated Sep 19, 2026

Domain Connect — one-click DNS

The open standard that lets customers set up DNS records with a single click at registrars that implement it — no copy-paste.

Domain Connect is the open spec that lets a SaaS provider hand a customer a button. The customer clicks → their DNS provider authenticates them, shows the exact records that will be added, asks for one confirmation → records appear in their DNS zone. Zero copy-pasting, zero typos.

Chatly implements both halves: the service-provider endpoints a registrar calls, and the discovery that finds the customer's registrar so we can offer the button at all. You don't configure anything — claim a custom domain and Chatly asks DNS whether a one-click flow is available.

Info — Why this exists

DNS setup is one of the highest-friction steps in onboarding any multi-tenant SaaS. Typos, wrong TTLs, "what's a CNAME again?" — Domain Connect eliminates all of that for customers whose DNS lives at a registrar that implements the spec.

Which registrars support it

We do not maintain a list. Whether a customer gets the button is answered by DNS at request time:

GET /v1/domains/{id}/domain-connect — Bearer token

{ "supported": true, "applyUrl": "https://dcc.godaddy.com/…", "providerName": "GoDaddy" }
{ "supported": false }

supported: false is a normal answer, not an error — the dashboard keeps showing the records to copy. The lookup:

  1. Resolve TXT _domainconnect.{registered-domain}. A registrar that implements the spec publishes the hostname of its Domain Connect API there. No record → supported: false.

  2. Fetch https://{that-host}/v2/{registered-domain}/settings (HTTPS only, hostname character-validated, 4-second timeout — the TXT value is DNS the customer controls, so it is untrusted input naming an outbound request).

  3. Read urlSyncUX out of the response and build the apply link:

{urlSyncUX}/v2/domainTemplates/providers/chatly/services/help-center/apply
  ?domain={registered}
  &host={label}
  &verify={token}
  &target={CUSTOM_DOMAIN_CNAME_TARGET}
  &redirect_uri={dashboard}/settings/domains?domain=…&service=help-center

Warning — The domain/host split is not a full public-suffix list

Domain Connect addresses records as (domain, host) — acme.com plus help — so the claimed hostname has to be split. Two labels is assumed, with a hard-coded set of multi-part suffixes (co.uk, org.uk, me.uk, com.au, net.au, org.au, co.nz, co.za, com.br, co.jp, com.mx, co.in) handled as three. An unrecognised shape fails closed to a bare domain and the customer copies the records by hand — offering a link that configures the wrong zone would be worse.

How the flow works

1. Customer claims a hostname in Chatly
       POST /v1/domains  { "hostname": "help.acme.com" }
       ← { id, hostname, kind: "help_center", status: "pending",
           txtRecord: { host: "_chatly.help.acme.com",
                        value: "chatly-domain-verify=…" } }

2. Dashboard asks whether one-click is available
       GET /v1/domains/{id}/domain-connect
       ← { supported: true, applyUrl: "…", providerName: "GoDaddy" }

3. Customer clicks applyUrl → lands at their own registrar

4. Registrar fetches the template from us
       GET /v1/domain-connect/v2/chatly/help-center/template?domain=acme.com&host=help&verify=abc&target=…
       ← { records: [
             { "type": "CNAME", "host": "help",         "pointsTo": "connect.chatlychat.com", "ttl": 3600 },
             { "type": "TXT",   "host": "_chatly.help", "data": "chatly-domain-verify=abc",   "ttl": 300 }
         ] }

5. Registrar shows the customer the exact records, they confirm
       → Records appear in their zone
       → Registrar sends them to redirect_uri (the dashboard's domains page)

6. The verification sweep resolves the TXT, matches the token,
   flips status to verified, and publishes a Traefik router

7. Traefik issues a Let's Encrypt certificate for help.acme.com

Discovery + endpoints we publish

GET /.well-known/domain-connect — Public

{
  "providerId": "chatly",
  "providerName": "Chatly",
  "providerDisplayName": "Chatly — open customer messaging platform",
  "urlSyncUX": "https://api.chatlychat.com/v1/domain-connect/v2/chatly/_serviceId_/apply",
  "urlAPI": "https://api.chatlychat.com/v1/domain-connect/v2/chatly/_serviceId_/template",
  "width": 750,
  "height": 750
}

providerId is the literal string chatly — it is the path segment in every service URL below, not a hostname.

Then per service:

GET /v1/domain-connect/v2/chatly/{serviceId}/template — Public

GET /v1/domain-connect/v2/chatly/{serviceId}/apply — Public

Both are GET and both are unauthenticated — a registrar calls them with no credential of ours. template requires a domain query parameter and 400s without it. apply answers 302 to the dashboard's /settings/domains?domain=…&service=…; the record write itself is done by the registrar, not by us.

Template query parameters

Name

Type

Description

domain (required)

string

The registered domain, e.g. acme.com.

host

string

The label beneath it — help, or @ for the apex. Default: help.

verify

string

The verification token, without the chatly-domain-verify= prefix. Interpolated into the TXT record's value.

target

string

CNAME target. Defaults to the API's own hostname; the dashboard always passes CUSTOM_DOMAIN_CNAME_TARGET so the one-click and copy-paste paths name the same host.

Templates we publish

Service templates

Name

Type

Description

help-center

template

Points {host}.{domain} at the custom-domain ingress and adds the verification TXT at _chatly.{host}. syncBlock: true — the records are applied as one block.

Warning — One template, because there is one thing a custom domain does

A custom domain serves this workspace's help centre. widget, email, and marketing templates existed alongside it for domain kinds that were never wired to anything and were removed (migration 0384). Any serviceId other than help-center answers 404 unknown domain-connect service.

Templates are built in code, in apps/api/src/modules/domains/domain-connect.controller.ts — there is no JSON template directory.

Trust model

Warning — The DNS provider is the trust anchor here

The registrar checks that the person clicking actually owns the domain (because they're authenticated with the registrar). Chatly never touches the customer's registrar credentials, never sees their auth session.

After the records land, we still require the TXT challenge to be verified — that's how we confirm the records were actually applied to the right zone. Without that step, a misconfigured registrar could apply records to the wrong account and we'd never catch it.

Limitations

Warning — Templates are not signed

Domain Connect 2.0 defines signed templates for synchronous provisioning. Chatly does not implement them: the discovery document advertises no syncPubKey and the template carries no syncPubKeyDomain. Every flow goes through the user-interactive urlSyncUX redirect.

Warning — Apex CNAME records aren't legal in DNS

The template will emit host: "@" if you claim an apex, and a CNAME at the apex is not valid DNS. Claim a subdomain — help.acme.com — which is what the help centre is for anyway.

  • DNSSEC + DS records aren't covered by Domain Connect. If you rotate keys, the customer has to update DS records manually.

  • Wildcard CNAMEs (*.acme.com) aren't supported by the spec — claim each hostname instead.

  • Custom TTLs can't be set through Domain Connect: the registrar applies whatever the template specifies (3600 for the CNAME, 300 for the TXT).

Debugging

There is no per-click activity log. What the dashboard shows instead is a diagnosis on each domain, refreshed by the verification sweep — see Custom domains for the full list. The ones relevant here:

  • awaiting_dns — the sweep has not yet seen the records. Either the customer did not confirm at their registrar, or propagation is still in flight.

  • points_elsewhere — records exist but the CNAME does not resolve to our target. Usually the registrar applied the template to a different zone (subdomain delegation, vanity nameservers). Run dig against the authoritative nameservers.

  • proxied — a proxy sits in front of the hostname, so certificate validation cannot reach us.

If GET /v1/domains/{id}/domain-connect returns supported: false for a registrar you believe supports the spec, check dig TXT _domainconnect.acme.com +short — an empty answer is the whole explanation.

Was this page helpful?
Domain Connect — one-click DNS