Domains

Detect where a domain's DNS lives and how it will be set up

Read-only feature detection. Returns the provider, the chosen setup_type, whether automatic setup is possible, whether the OAuth-into-provider and one-click setup rails are available, capability flags (ns_support, wildcard_support, cname_flattening, spf_override_support, caa_support), social-login support, and any record_conflicts observed in public DNS. Unknown providers degrade to setup_type: manual.

Apex pre-flight: apex_supported reports whether the provider can host a CNAME-like record at the zone root, and apex_message is returned when this particular target needs one the provider cannot host, so an apex connection that would be refused at apply time is refused here instead, before any connection is created.

The answer is for one application (where its domains point: target_mode and the apex strategy). A widget JWT checks for its own application. An API key checks for application_id, which must be an application in the key's tenant (404 otherwise), or for the key's own application when it is omitted.

A delegated agent token needs domains:read or domains:connect and checks for its own application; naming another application is a 403.

post/domains:check

Request

  • Base URL: https://api.customdomain.ai/v1
  • URL: https://api.customdomain.ai/v1/domains:check
  • Auth: one of:
    • HTTP bearer
    • HTTP bearer
    • OAuth 2 (authorization code, authorization URL https://api.customdomain.ai/oauth/agent/authorize, token URL https://api.customdomain.ai/oauth/agent/token, scopes: domains:read)
    • OAuth 2 (authorization code, authorization URL https://api.customdomain.ai/oauth/agent/authorize, token URL https://api.customdomain.ai/oauth/agent/token, scopes: domains:connect)

Request body

domainstring required
application_idstring

With an API key, the application to check for (defaults to the key's own). A widget JWT may only omit it or send its own application id (403 otherwise).

Response

Detection result

domainstring required
sandboxboolean

true when the check ran for a test mode application: nothing was looked up, the answer is always the manual rail, and the domain must be a reserved .test name. Omitted on a real check.

subdomainstring

Server's authoritative Public-Suffix-List parse verdict: the subdomain labels of domain, empty string when the domain IS the registrable apex. Clients must adopt this boundary instead of computing their own.

registrable_domainstring

The registrable domain (eTLD+1) of domain per the full PSL.

public_suffixstring

The effective TLD (public suffix) of domain, e.g. com, co.uk, com.ng.

providerstring nullable
setup_type'automatic' | 'manual' | 'async' | 'mcp' required

How a connection reaches live.

supports_automaticboolean
oauth_availableboolean

the OAuth-into-provider rail can be offered

domain_connectboolean

the one-click (Domain Connect sync) rail is offered for this domain. Same predicate as rails.domain_connect.available: the provider answered discovery AND, when a provider allowlist is configured (DC_SYNC_PROVIDERS, the default), the provider is on it, i.e. is measured to serve our template catalog. Providers that speak the protocol but have not onboarded our template (GoDaddy, IONOS, Cloudflare) report false even with DC_SYNC_ENABLED on. A domain reported true will not have its domainconnect:start refused for lack of the rail.

registeredboolean

Whether the domain resolves to a delegated zone. OMITTED (not false) when detection failed for a transient reason; only an NXDOMAIN answer reports false. Do not tell a user their domain is unregistered unless this field is present and false.

detection_error'nxdomain' | 'resolver'

Present only on a degraded check (detection failed): nxdomain means the domain is not delegated (registered is false, blocked_reason is unregistered); resolver means a transient resolver failure; the provider is unknown for now, retry the check.

authoritative_dns_providerstring nullable
wildcard_supportboolean
cname_flatteningboolean
apex_supportedboolean

The provider can serve CNAME-like data at the zone root (ALIAS/ANAME/flattened CNAME). Always agrees with cname_flattening. Reported for every check, apex target or not.

apex_messagestring

Present only when the record set this check ran against needs an apex record the provider cannot host, i.e. exactly when the apply would refuse with apex_not_supported. Gate any warning UI on this field, not on apex_supported: a subdomain connect on a provider with no apex capability reports apex_supported: false and no message, because nothing in that flow breaks.

target_mode'edge' | 'custom'

Where this application's domains point: edge (proxied by the platform) or custom (the application's own connection target, see PUT /applications/{id}/connect-target).

apex_strategy'alias' | 'a_records' | 'unsupported'

How a ROOT domain is pointed for this application on the detected provider: alias (an ALIAS, ANAME or flattened CNAME record to a hostname), a_records (address records to apex_targets), or unsupported (neither is possible; apex_message explains).

apex_record_typestring

The record type to choose in the provider's panel for the root (ALIAS, ANAME, CNAME or A).

apex_targetsstring[]

The addresses a root domain's A records point at when apex_strategy is a_records.

spf_override_supportboolean
caa_supportboolean
supports_social_loginstring

yes | no | n-a

recommended_rail'oauth' | 'domain_connect' | 'cloud_browser' | 'api_key' | 'manual'

The rail the server recommends, by precedence oauth → domain_connect → cloud_browser → api_key → manual (least typing for the end user first). cloud_browser is recommended only when it is available and the API key rail is unavailable or carries a caveat. Absent when blocked_reason is set. The console and the widget follow this field so the surfaces never disagree.

end_user_automaticboolean

True when the recommended rail needs nothing typed by the end user (OAuth or one-click). This is the fact supports_automatic was always misread as. An API-key rail is "automatic" only for someone holding an API key.

blocked_reason'unregistered' | 'platform_subdomain'

Present when no rail can connect this domain. unregistered: no nameserver delegation at all (fix it at the registrar). platform_subdomain: a hosting platform's own subdomain (www.<name>.vercel.app). Its DNS is the platform's; POST /v1/connections refuses it with platform_subdomain.

dashboard_urlstring

Best-effort deep link into the detected provider's DNS panel for this zone, to send the user to when they add records by hand. Absent when unknown.

nameserversstring[]

The nameserver delegation the detector observed (normalized hostnames).

conflict_toleranceinteger

Provider's automated-write conflict threshold (0/absent = no modeled limit).

will_fallback_to_manualboolean

True when current record conflicts exceed the provider's threshold, so an automated flow would silently drop to manual. Have the user clear conflicts first.

Changes

No recorded changes to this operation across all 1 revision of this API.