Domain registration and transfers

This page tells how an operator takes out a domain and saves their domain contact, how to change the owner of a domain, and how to transfer a domain in.

Let an operator take out a domain

An operator can move a domain from the registrar account of the hosting provider to a registrar account of their own. A deployment needs a domain, thus this applies only to a domain that no deployment uses: the operator first destroys the deployment that has the domain, or deploys it with a different domain or with no domain. A succeeded destroy or deploy of this kind does not change the renewal of the old domain and does not take out that domain. The domain stays in your account and keeps its renewal until a transfer moves it, or the operator turns off the renewal and the registration expires.

In the panel, the page "Domains" lists the domains of the operator, and offers these calls for a domain that no deployment uses.

These calls name the domain in the body, and the deployment that had the domain in the path. The owner of that deployment can send them, and the status of the domain must be assignable:

  • POST /deployments/domain_take_out/<deployment> gives the auth code of the domain, unlocks the domain, and removes its DNSSEC keys. The operator gives the code to their new registrar. The api does not keep the code, and a new call gives the code again.
  • POST /deployments/domain_take_out_cancel/<deployment> locks the domain and resets its auth code, thus the code that the operator has stops working.
  • PUT /deployments/released_domain_renewal_off/<deployment> turns off the renewal of the domain. The registration then ends at its expiry.
  • PUT /deployments/released_domain_renewal_curated/<deployment> turns on the renewal again. The api refuses this with conflict when the curation of the deployment method of the build that registered the domain does not let the domain renew.

These calls do not start a build. Each call records an audit event with the domain, and the audit event does not record the auth code. domain_list shows a new renewal after the next read of the registrar account.

While the code is out, transfer_pending of domain_list is true, and the api refuses a deploy that registers the domain with conflict. The transfer can move the domain at any time, and that deploy would lose it. After a cancel, a deploy can use the domain again, and that deploy sets the DNSSEC keys again. The api does not cancel a take-out by itself: the domain stays unlocked until the transfer or the cancel. A claim for a different deployment and a migration import also lock the domain and reset the code.

The registry can refuse a transfer soon after a registration. The new registrar sets the contacts of the domain. When the transfer completes, the domain leaves your account, and domain_list gives transferred. The accounting records this as a release.

These calls need the registrar command of the api, which exists for openprovider. Without it, they give runtime_error.

Let an operator save their domain contacts

An operator can save their own contacts in the registrar account. The panel gives a list of them at Domain contacts on the account page, with a form to add, change or erase each contact, and keeps the handle that the call gives. On the page of a deployment, Domain contacts picks the contact of each role. An operator of a different front-end uses the same calls:

  • PUT /domain_contacts/<contact> makes the contact in the account equal to the body, and gives the handle. The call waits for the end of an OpenTofu apply, which can take minutes.
  • GET /domain_contacts/<contact> gives the handle and the contact from the state.
  • DELETE /domain_contacts/<contact> deletes the customer in the account, and then the state of the contact. The call gives conflict while a domain of the account names the contact. The panel has the button "Erase contact" for this on the same page.

The authorization callback decides who can use <contact>. The panel gives each contact of an operator an ID, and refuses the ID of a different operator. This is so also for a superuser.

OpenTofu keeps each contact in a state of its own, in the state backend of the operator lane, with the key <base>-<contact>-domain-contact. The state holds the contact as plain text, so restrict access to the state as you do for the personal data of your operators. A contact does not go into the state of a deployment. These calls need the registrar command of the api, which exists for openprovider. Without it, they give runtime_error.

A change of a name makes a new customer with a new handle. The api deletes the old customer, unless a domain of your account names it. Such a customer stays in your account until you delete it there. A change of a contact does not change the owner of a domain that is registered, see Change the owner of a domain.

When a panel administrator removes the account of an operator, the panel first erases the domain contact of that operator. If a domain of your account names the contact, the contact stays, and the panel writes a warning with the handle to its log. After the domain leaves your account or gets a different owner, delete the customer in your registrar account. If the erasure fails for a different cause, the panel does not remove the account.

Change the owner of a domain

An operator with a domain contact can make that contact the owner of a registered domain, on the page "Domains" of the panel. The form picks one of the contacts of the operator. The panel sends PUT /deployments/domain_owner_change/<deployment>, with the domain in the body. The deployment is the one that has the domain, or that had it when no deployment uses it, and it can be destroyed. The owner of that deployment can send the call, as for the other actions on the domain. The body cannot name a contact: the api uses the handle of the owner of domain_contacts in the answer of the authorization callback, and without a saved contact the api gives conflict. The panel makes the picked contact the owner contact of the deployment.

The call does not start a build, and a next deploy keeps the owner. The administrative, the technical and the billing contact follow the contacts of the deployment at its next deploy. The call needs the registrar command of the api, which exists for openprovider. The registrar must show the domain as active, with a direct change of the owner allowed. The api also refuses while an auth code of the domain is out. The audit event has the action domain_owner_change, and does not record the handle.

When the domain needs domain terms, the call needs the acceptance of their current version by the new owner. The form of the panel asks for this when the deployment did not accept that version yet, and the api stores it on the deployment. The agreement of openprovider makes the agreement of the new owner a condition of the change, and a change without it can void the transfer and revoke the domain. Your domain terms must thus apply to a new owner, and must authorize the registrar as Designated Agent, see Contract templates. This authorization lets the registrar do the change: it does not move liability. A new version of the terms changes API_DOMAIN_TERMS_VERSION, thus an operator accepts the clause before a next change.

The registrar sends a notice to the old and the new owner. The command does not agree to a fee of the registrar for the change. A registry can have rules of its own for a change of the owner, and it can lock the transfer of the domain for some time after the change. The change was tested on .cfd only, so test it on a domain of each extension that you offer, for example .eu.

Transfer a domain in

An operator can move a domain from a different registrar account to the registrar account of the hosting provider. The configuration of a deployment must give the domain, and that deployment must have something deployed. The panel gives a form for this on the domains page.

  1. Get the auth code of the domain from the registrar that has it now, and remove its transfer lock there.
  2. Send the domain and the code with POST /deployments/domain_transfer_in/{deployment_id}. The api writes the code to the KV of the deployment and starts a build. The audit event does not record the code.
  3. That build orders the transfer and fails, as the transfer is not complete. The registry can take some days. While the account shows the domain as REQ or PEN, GET /domains gives transfer_in_progress, and the panel shows that the transfer is not complete.
  4. Deploy again when the transfer is complete. That deploy uses the domain, and deletes the code from the KV. Nothing starts this deploy automatically.

Warning: a transfer is a real, paid order at the registrar. The registrar charges your registrar account, usually the price of a renewal of one year, and a transfer that the registry refuses can cost money too. Thus the api refuses a request that orders a transfer without accept_transfer_cost: true, with a 400 invalid_configuration and details: {"transfer_cost": "not_accepted"}. The panel asks the operator to accept the cost, and sends accept_transfer_cost only after that: in the transfer form of the domains page, in the deploy controls, and in the migration import of a migration string with a domain_transfer. Thus a client of the api must tell the operator about the cost before it accepts it.

The hourly zone sweep does not delete the deSEC zone of a domain that the registrar snapshot (REGISTRAR_SNAPSHOT) shows in the account, also while the transfer is not complete. Thus the DS records that the transfer sets stay valid. If the snapshot is set but cannot be read, the sweep deletes no zone.

The api refuses this with conflict for a domain that the registrar account has or that a different deployment claims. If the registry refuses the transfer, the account shows the domain as FAI, the deployment does not send the transfer again, and GET /domains gives transfer_failed. The same call then sends the transfer again, without a change in the registrar account: give the code again, also if it did not change, after you correct the cause, such as a wrong code or a lock at the other registrar. The sandbox of the registrar cannot prove this call, thus do the first retry on a domain with no users. A domain that no registrar has is registered and not transferred. The domain terms that the deployment accepted apply to the transfer.

These calls need the registrar command of the api, which exists for openprovider. Without it, they give runtime_error.