Move the domain's nameservers, with the end user's consent
Move the domain's nameservers, with the end user's consent: CustomDomain™ API reference in the nameservers group. Covers parameters, request body and responses.
Starts moving the nameservers of the connection's registrable domain (acme.com, also for shop.acme.com) to the application's DNS host, or resumes the domain's open migration with what the call brings (a key, zone_ready, skip_zone_check). 201 when a migration was created, 200 when one was resumed. The response is the migration as far as it got in this call: with a registrar key and no DNSSEC it is often already propagating or active.
Where the nameservers go is the application's nameserver_migration.target (PATCH /applications/{id}): managed (CustomDomain™ hosts the zone), dns_host (a zone we create in the platform's own DNS host account) or custom (the platform's own nameservers; the zone must already answer for the domain). For managed and dns_host the domain's records are copied first, mail included, so nothing breaks at the switch: the whole zone through the old DNS host's API when we hold a key there, else from public DNS, and then the move waits in needs_review until a person confirms the copy (copy_reviewed). An API key may pass target for managed or custom; dns_host is always the application's own account. A delegated agent token may name only the application's own target and may not send skip_zone_check (403 target_not_allowed): with a registrar account linked, nameservers an agent chose would hand it the whole domain in one call.
Where they change: at the domain's registrar, looked up over RDAP for every move (registrar), never at the DNS host because it hosts the DNS. A key, an account, a cloud browser sign in and the instructions all go to that registrar; when RDAP names none, the detected DNS host is used as a guess and next_step names no company.
How they change (path): api, the registrar's own API with a key the customer created (credential with provider, used once and never stored, or provider_account_id, a connected account; the connection's linked account is used when there is one); agent, the cloud browser, where the end user signs in to their registrar and approves the exact nameservers (start it with POST /connections/{id}/browser:start and purpose: nameservers); manual, the person sets them with the values in next_step. There is no standard a third party can use to ask a registrar for this (Domain Connect edits records only; CDS and CSYNC need the current DNS operator and DNSSEC), so these three are the ways.
A lost answer: a registrar's error is not taken at its word, since a timeout can come after the registrar acted. The registrar (then the registry) is read back: the nameservers asked for mean the change happened; others mean it didn't (registrar_refused); no answer leaves the move in setting with waiting_for: registrar_confirm, still possible to move back, and the next check reads back first.
DNSSEC: when the registry publishes a DS record for the domain, the nameservers do not move until it is gone and its TTL has passed, or the domain would stop resolving. With a connected account (lasting access) whose registrar API removes DS records, we remove it; otherwise the migration waits in needs_dnssec_off for the person (or the cloud browser's remove_dnssec step).
A widget token (the end user) may start a migration only when the application's nameserver_migration.mode is offer or prefer, must send consent (the id and version of the consent text the person agreed to; stored with the time, never their address), and may not send target, credential, provider_account_id, zone_ready or skip_zone_check. A delegated agent token needs domains:connect (the MCP tool also asks the person to confirm first).
Long-lived tenant API key, cd_live_… (production) or cd_test_… (staging, development), stored hashed. Keys created before the switch to cd_ start with sk_live_… / sk_test_… and are still accepted. Scoped to the owning application's tenant.
In: header
Path Parameters
Request Body
application/json
TypeScript Definitions
Use the request body type in TypeScript.
Response Body
application/json
application/json
application/json
application/json
application/json
application/json
application/json
application/json
application/json
curl -X POST "https://example.com/connections/string/nameservers:migrate" \ -H "Content-Type: application/json" \ -d '{}'{ "id": "string", "connection_id": "string", "zone": "string", "state": "pending", "path": "api", "target": "managed", "dns_host": "string", "provider": "string", "registrar": { "name": "string", "provider": "string", "iana_id": 0, "url": "string", "source": "rdap" }, "old_dns_host": "string", "old_nameservers": [ "string" ], "new_nameservers": [ "string" ], "observed_nameservers": [ "string" ], "waiting_for": "zone_ready", "next_step": "string", "failure_code": "zone_copy_failed", "failure_detail": "string", "records_copied": 0, "email_records": 0, "email_kinds": [ "mx" ], "copy_source": "api", "copy_warnings": [ "string" ], "copy_reviewed_at": "2019-08-24T14:15:22Z", "ds_present": true, "ds_removed_at": "2019-08-24T14:15:22Z", "ds_cleared_at": "2019-08-24T14:15:22Z", "can_rollback": true, "rollback_path": "api", "rollback_targets": [ "previous" ], "rollback_default": "previous", "rollback_target": "previous", "rollback_set_at": "2019-08-24T14:15:22Z", "old_dns_serves": true, "consent": { "id": "string", "version": "string", "at": "2019-08-24T14:15:22Z" }, "actor": "end_user", "created_at": "2019-08-24T14:15:22Z", "set_at": "2019-08-24T14:15:22Z", "active_at": "2019-08-24T14:15:22Z", "failed_at": "2019-08-24T14:15:22Z", "rolled_back_at": "2019-08-24T14:15:22Z", "drifted_at": "2019-08-24T14:15:22Z", "checked_at": "2019-08-24T14:15:22Z", "next_check_at": "2019-08-24T14:15:22Z", "updated_at": "2019-08-24T14:15:22Z"}{ "id": "string", "connection_id": "string", "zone": "string", "state": "pending", "path": "api", "target": "managed", "dns_host": "string", "provider": "string", "registrar": { "name": "string", "provider": "string", "iana_id": 0, "url": "string", "source": "rdap" }, "old_dns_host": "string", "old_nameservers": [ "string" ], "new_nameservers": [ "string" ], "observed_nameservers": [ "string" ], "waiting_for": "zone_ready", "next_step": "string", "failure_code": "zone_copy_failed", "failure_detail": "string", "records_copied": 0, "email_records": 0, "email_kinds": [ "mx" ], "copy_source": "api", "copy_warnings": [ "string" ], "copy_reviewed_at": "2019-08-24T14:15:22Z", "ds_present": true, "ds_removed_at": "2019-08-24T14:15:22Z", "ds_cleared_at": "2019-08-24T14:15:22Z", "can_rollback": true, "rollback_path": "api", "rollback_targets": [ "previous" ], "rollback_default": "previous", "rollback_target": "previous", "rollback_set_at": "2019-08-24T14:15:22Z", "old_dns_serves": true, "consent": { "id": "string", "version": "string", "at": "2019-08-24T14:15:22Z" }, "actor": "end_user", "created_at": "2019-08-24T14:15:22Z", "set_at": "2019-08-24T14:15:22Z", "active_at": "2019-08-24T14:15:22Z", "failed_at": "2019-08-24T14:15:22Z", "rolled_back_at": "2019-08-24T14:15:22Z", "drifted_at": "2019-08-24T14:15:22Z", "checked_at": "2019-08-24T14:15:22Z", "next_check_at": "2019-08-24T14:15:22Z", "updated_at": "2019-08-24T14:15:22Z"}{ "code": "string", "title": "string", "details": "string"}{ "code": "string", "title": "string", "details": "string"}{ "code": "workspace_suspended", "title": "This workspace is suspended.", "details": "New domains, connect steps and domain purchases are refused while CustomDomain™ support has this workspace suspended. Contact support to have it resumed."}{ "code": "string", "title": "string", "details": "string"}{ "code": "string", "title": "string", "details": "string"}{ "code": "string", "title": "string", "details": "string"}{ "code": "string", "title": "string", "details": "string"}