Domain migration
Domain migration
Migration is how Most takes over the management lifecycle of a domain
that already exists on your registrar account. The domain itself stays
where it is — what changes is who manages it inside Most: the
ICANN WHOIS contacts get rebound to a Most Client, and (on Webnic)
the domain is relocated into a managed registrant tenant so subsequent
API calls route through the credentials Most holds.
Migration ≠ transfer-in
Migration is a re-ownership flow inside Most. It does not trigger an ICANN registry transfer-in — there's no AuthInfo / EPP code exchange and no registry hand-off. If you want to actually move a domain between registrars, use the auth-info endpoint on Most and submit the resulting code to your target registrar's transfer flow yourself.
When to use it
- You already own the domain at a registrar Most supports (Webnic, Dynadot, Spaceship, NICENIC, GName).
- You registered the domain outside Most — partner panel, CLI, resale — and need to reflect that in our DB so Most can drive the WHOIS / NS / renewal lifecycle.
- You're consolidating multiple Clients' domains onto one registrar account and want them assigned to the right local Client rows.
Don't use migration for fresh registrations — call POST /domains/orders instead.
Pipeline
A migration is async. Submit it via POST /domains/migrate and poll
GET /domains/migrations/{id}
to watch it walk these steps:
| Step | What's happening |
|---|---|
QUEUED | Migration row created; worker hasn't picked it up yet. |
ENSURING_PROFILE | Worker is creating/ensuring the four ICANN contacts (registrant / admin / tech / billing) on the registrar account — one createContact call per role unless a binding already exists from an earlier migration. |
FETCHING_DOMAIN | Pulling current state from the registrar (getDomainInfo) — which contacts and tenant the domain currently lives under. |
REPLACING_CONTACTS | Rebinding the four ICANN roles to our newly-created contact ids. Skipped if everything already matches. Per-registrar shapes: Webnic has a native bulk endpoint, Dynadot/Spaceship/NICENIC/GName loop a per-domain call. |
RELOCATING_REGISTRANT | Webnic only. Moves the domain into the registrant tenant we created for this Client. No-op elsewhere. |
FINALIZING | Re-reads the authoritative state from the registrar and writes it onto the local ClientDomain row — expiry, registered-at, nameservers. |
DONE | Pipeline finished; ClientDomain.status is now ACTIVE. |
Failure at any step leaves the migration in FAILED with a verbatim
errorMessage. Once you've fixed the cause, POST /domains/migrations/{id}/retry
resumes from the last successful step — contact creation that already
succeeded isn't repeated.
Per-registrar notes
- Webnic — fully supported including registrant-tenant relocation
(one tenant per Client × Provider, auto-created during
ENSURING_PROFILEwith the Client's login as the username hint). The contact bulk-replace is queue-backed registry-side, so the worker pollsdomain.infountil the swap is observable (typically 30–120 s, occasionally longer when the registry queue is busy). - Dynadot / Spaceship / NICENIC — no tenant concept; the
pipeline stops after
REPLACING_CONTACTS. WHOIS is rebound but the registrar's internal owner record (where applicable) isn't touched. Migration usually completes in 5–30 s end-to-end. - GName — single template per domain (one WHOIS shared across all
four roles); the worker creates a fresh template from the Client's
REGISTRANT contact and rebinds via
/api/domain/contact— async by spec, the worker polls (1–5 min typical).
Auto-detect the registrar
registrarId is optional. When you omit it, Most asks each of
your connected, active provider accounts (in parallel, concurrency
capped at 4) whether they own the domain, and queues the migration
against the first account that says yes. The response carries
autoDetected: true and echoes the resolved registrarId so you can
reconcile against your records.
When the scan finds nothing, the item goes into the response's
failures[] rather than spawning a doomed migration:
Code
If a provider hit a per-endpoint rate limit (see GName's notes in
Registrar peculiarities), the affected
account shows up in failures[].scanErrors[] — handy for telling
"domain isn't on any account" apart from "the scan was throttled and
that's why the answer is empty".
If you just want to run the lookup without queueing anything, use
POST /domains/find-provider —
same scan, returns the matching account (or null) with no side
effects.
Example flow
Code
For a step-by-step UI version of the same flow, see the panel under
Domains → Migrate — it issues exactly the same /v1/domains/migrate
call under the hood.