DomaineeDocs
Domains

Get connect instructions

GET /v1/domains/{id}/instructions — one-click Domain Connect where available, provider-specific manual steps everywhere else.

GET /v1/domains/{id}/instructions

Returns setup steps written for the DNS provider actually serving the customer's domain, instead of a generic "add a CNAME".

Most custom-domain connections die at the last mile: the end user opens a registrar panel they have never seen and has to guess which of three name fields to use, whether their provider can even hold a CNAME-like record at a root domain, and which provider-specific toggle silently breaks everything. This endpoint answers all three.

Domainee fingerprints the provider from the zone's public NS records, so there is nothing to configure and no credentials involved.

Request

curl https://api.domainee.dev/v1/domains/$DOMAIN_ID/instructions \
  -H "Authorization: Bearer $DOMAINEE_API_KEY"

Query parameters

ParamNotes
redirect_uriWhere the customer lands after approving a Domain Connect flow at their provider. Use it to bring them back into your app.
stateOpaque value round-tripped through that redirect. Use it for CSRF protection and to identify the domain on return.

Response — 200 OK

{
  "instructions": {
    "hostname": "acme.com",
    "provider": { "id": "cloudflare", "name": "Cloudflare", "detected": true },
    "apex": true,
    "method": "a",
    "methodReason": "At a root domain the A records route each visitor to the nearest region, which ALIAS or CNAME flattening cannot do.",
    "records": [
      { "type": "A", "name": "@", "value": "75.2.52.197", "ttl": 300 },
      { "type": "A", "name": "@", "value": "3.33.255.144", "ttl": 300 }
    ],
    "steps": [
      "Sign in to Cloudflare at https://dash.cloudflare.com.",
      "Open the DNS record editor: Select your domain > DNS > Records > Add record.",
      "Add 2 A records with the name @, one for each address below. Add all 2: one alone works but leaves you with no redundancy.",
      "Delete any existing A, AAAA or CNAME record with the name @, or it will answer alongside the new ones.",
      "Save. We re-check every 5 minutes and issue the TLS certificate on the first request, so there is nothing else to do."
    ],
    "quirks": [
      "Set Proxy status to DNS only (the grey cloud). Leaving it proxied (orange) makes Cloudflare terminate TLS itself, and the certificate will never be issued."
    ],
    "dashboardUrl": "https://dash.cloudflare.com"
  }
}

Fields

FieldNotes
provider.idStable slug, e.g. cloudflare, route53, godaddy. unknown when nothing matched.
provider.detectedfalse means the steps are generic. The record values are still correct.
apextrue when the hostname is its own zone root.
methoda or cname. Which one is right depends on both the position and the provider.
methodReasonWhy this method, in words you can show the end user.
recordsExactly what to publish. name is already written the way this provider's form wants it.
stepsOrdered, plain-language instructions. Safe to render as-is.
quirksProvider-specific gotchas. Show these; they are the difference between a connection that works and one that silently doesn't.

The name field is the point

Providers disagree about how to write a record name, and this is the single most common way a correct record ends up in the wrong place. A user who types the full hostname into a form that already appends the zone gets blog.acme.com.acme.com and no error message.

ProviderApexSubdomain blog.acme.com
Cloudflare, GoDaddy, Namecheap@blog
Route 53leave the record name blankblog
Google Cloud DNS, Akamaiacme.comblog.acme.com
Porkbun, Name.com, Dynadotleave the host field blankblog

records[].name is already correct for the detected provider, so you can put it straight into your UI without a lookup table of your own.

Why a separate endpoint

This does a live NS lookup, so it is not a field on the Domain object. Listing 500 domains must not fan out 500 DNS queries. Call it when you are about to show someone setup steps.

Errors

CodeStatusWhen
not_found404Domain doesn't exist in this workspace.

Detection itself never fails. If the NS lookup returns nothing or the nameservers match no known provider, provider.detected is false and you get correct generic steps.

One-click setup with Domain Connect

Every response also carries a domainConnect object. When the customer's DNS provider supports Domain Connect and has adopted Domainee's template, they can approve a single screen at their own provider instead of editing records by hand.

Status: not live yet. Domain Connect providers apply templates they sync from the shared Domain-Connect/Templates repository, and Domainee's are still awaiting review there. Until they are merged and synced, supported is false with reason: "template_not_adopted" at every provider. The field is documented now so you can build against its final shape; wire up steps today and applyUrl will start appearing on its own, with no change on your side.

{
  "domainConnect": {
    "supported": true,
    "providerId": "cloudflare.com",
    "providerName": "Cloudflare",
    "applyUrl": "https://dash.cloudflare.com/domainconnect/v2/domainTemplates/providers/domainee.dev/services/edge-apex/apply?domain=acme.com&ip1=...&redirect_uri=...",
    "width": 750,
    "height": 750
  }
}

Send the customer to applyUrl, in a popup sized width × height or as a full redirect. Their provider writes the records and returns them to your redirect_uri with your state. No credentials reach Domainee and there is nothing for the customer to revoke afterwards.

When it is unavailable you get a reason instead:

{ "domainConnect": { "supported": false, "reason": "no_discovery_record" } }
reasonMeaning
no_discovery_recordThe zone has no _domainconnect TXT record, so the provider doesn't support the protocol.
settings_unavailableDiscovery record present but the provider's settings endpoint didn't answer.
no_sync_supportThe provider supports Domain Connect but not the synchronous flow.
template_not_adoptedThe provider supports the protocol but hasn't adopted Domainee's template yet.
lookup_failedThe DNS lookup itself failed. Retry.

Always render steps regardless. Domain Connect coverage is roughly 40-50% of end customers at best, supported is false far more often than it is true, and the manual steps are the path most of your customers will actually take. Treat applyUrl as a shortcut you offer when it exists, never as the only route.

MCP

The same thing is available to AI agents as the get_connect_instructions tool, so an agent that just created a domain can walk the customer through pointing it. See the MCP guide.

On this page