Domain Basics
The nine endpoints behind a domain's nameservers, transfer lock, ownership details and recovery.
Overview
These nine endpoints run a domain's basics. Where it points, whether it can be moved, who it appears to belong to, and whether it survives expiry.
All of them make a real call to the registry. So they can be slow, they can hit the registry's own rules, and a module may not support an operation at all. Every endpoint shares the same four preconditions. The service must exist, be a domain, have a registrar module attached, and that module must support the operation.
Reference
Setting the Nameservers
Writes which nameservers the domain points at.
curl -X PUT 'https://panel.example.com/api/v1/admin/services/520/domain/nameservers' \
-H "Authorization: Bearer $API_KEY" \
-H 'Content-Type: application/json' \
-d '{"ns1":"ns1.example.com","ns2":"ns2.example.com"}'const res = await fetch('https://panel.example.com/api/v1/admin/services/520/domain/nameservers', {
method: 'PUT',
headers: {
Authorization: `Bearer ${apiKey}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
ns1: 'ns1.example.com',
ns2: 'ns2.example.com',
}),
});
const body = await res.json();$ch = curl_init('https://panel.example.com/api/v1/admin/services/520/domain/nameservers');
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_CUSTOMREQUEST => 'PUT',
CURLOPT_HTTPHEADER => [
'Authorization: Bearer ' . $apiKey,
'Content-Type: application/json',
],
CURLOPT_POSTFIELDS => json_encode([
'ns1' => 'ns1.example.com',
'ns2' => 'ns2.example.com',
]),
]);
$body = json_decode(curl_exec($ch), true);
curl_close($ch);// The list is written WHOLE: leave ns3 and ns4 out and any existing ones are cleared.
$response = Api::Services()->SetDomainNameservers([
'id' => 520,
'ns1' => 'ns1.example.com',
'ns2' => 'ns2.example.com',
]);Reading the Transfer Lock
Returns whether the domain is locked against being moved to another registrar.
curl 'https://panel.example.com/api/v1/admin/services/520/domain/transfer-lock' \
-H "Authorization: Bearer $API_KEY"const res = await fetch('https://panel.example.com/api/v1/admin/services/520/domain/transfer-lock', {
headers: { Authorization: `Bearer ${apiKey}` },
});
const body = await res.json();$ch = curl_init('https://panel.example.com/api/v1/admin/services/520/domain/transfer-lock');
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . $apiKey],
]);
$body = json_decode(curl_exec($ch), true);
curl_close($ch);// Reading returns a RAW value while writing returns 'enabled'/'disabled': not the same vocabulary.
$response = Api::Services()->GetDomainTransferLock(['id' => 520]);Changing the Transfer Lock
Locks the domain against being moved, or unlocks it.
enable locks it, disable unlocks it.enable nor disable.curl -X PUT 'https://panel.example.com/api/v1/admin/services/520/domain/transfer-lock' \
-H "Authorization: Bearer $API_KEY" \
-H 'Content-Type: application/json' \
-d '{"status":"enable"}'const res = await fetch('https://panel.example.com/api/v1/admin/services/520/domain/transfer-lock', {
method: 'PUT',
headers: {
Authorization: `Bearer ${apiKey}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({ status: 'enable' }),
});
const body = await res.json();$ch = curl_init('https://panel.example.com/api/v1/admin/services/520/domain/transfer-lock');
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_CUSTOMREQUEST => 'PUT',
CURLOPT_HTTPHEADER => [
'Authorization: Bearer ' . $apiKey,
'Content-Type: application/json',
],
CURLOPT_POSTFIELDS => json_encode(['status' => 'enable']),
]);
$body = json_decode(curl_exec($ch), true);
curl_close($ch);// While the lock is ON the domain cannot move: unlock it before the client leaves for another registrar.
Api::Services()->SetDomainTransferLock(['id' => 520, 'status' => 'disable']);
$code = Api::Services()->GetDomainAuthCode(['id' => 520]);Getting the Authorisation Code
Asks for the code needed to move the domain to another registrar.
curl 'https://panel.example.com/api/v1/admin/services/520/domain/auth-code' \
-H "Authorization: Bearer $API_KEY"const res = await fetch('https://panel.example.com/api/v1/admin/services/520/domain/auth-code', {
headers: { Authorization: `Bearer ${apiKey}` },
});
const body = await res.json();
if (body.data.sent) {
// it went by e-mail, the code is not here
}$ch = curl_init('https://panel.example.com/api/v1/admin/services/520/domain/auth-code');
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . $apiKey],
]);
$body = json_decode(curl_exec($ch), true);
curl_close($ch);// There are two response shapes; do NOT assume the code arrived.
$response = Api::Services()->GetDomainAuthCode(['id' => 520])['data'];
$code = $response['auth_code'] ?? null;
$mailed = $response['sent'] ?? false;{
"data": {
"auth_code": "EXAMPLE-AUTH-CODE"
}
}{
"data": {
"sent": true
}
}Restoring the Domain
Recovers an expired domain. It only works while the recovery window is open.
curl -X POST 'https://panel.example.com/api/v1/admin/services/520/domain/restore' \
-H "Authorization: Bearer $API_KEY"const res = await fetch('https://panel.example.com/api/v1/admin/services/520/domain/restore', {
method: 'POST',
headers: { Authorization: `Bearer ${apiKey}` },
});
const body = await res.json();$ch = curl_init('https://panel.example.com/api/v1/admin/services/520/domain/restore');
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_POST => true,
CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . $apiKey],
]);
$body = json_decode(curl_exec($ch), true);
curl_close($ch);// Recovery costs a FEE at the registry, and it has to be called before the window closes.
$response = Api::Services()->RestoreDomain(['id' => 520]);Checking a Transfer
Asks the registry where a domain transfer in progress has got to.
curl -X POST 'https://panel.example.com/api/v1/admin/services/520/domain/check-transfer' \
-H "Authorization: Bearer $API_KEY"const res = await fetch('https://panel.example.com/api/v1/admin/services/520/domain/check-transfer', {
method: 'POST',
headers: { Authorization: `Bearer ${apiKey}` },
});
const body = await res.json();$ch = curl_init('https://panel.example.com/api/v1/admin/services/520/domain/check-transfer');
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_POST => true,
CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . $apiKey],
]);
$body = json_decode(curl_exec($ch), true);
curl_close($ch);// The error state comes back inside a 200, not as an HTTP error: read the status before assuming success.
$check = Api::Services()->CheckDomainTransfer(['id' => 520])['data'];
$stuck = $check['transfer_status'] === 'error';Reading the WHOIS Contacts
Fetches the domain's contact details from the registry.
curl 'https://panel.example.com/api/v1/admin/services/520/domain/whois' \
-H "Authorization: Bearer $API_KEY"const res = await fetch('https://panel.example.com/api/v1/admin/services/520/domain/whois', {
headers: { Authorization: `Bearer ${apiKey}` },
});
const body = await res.json();$ch = curl_init('https://panel.example.com/api/v1/admin/services/520/domain/whois');
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . $apiKey],
]);
$body = json_decode(curl_exec($ch), true);
curl_close($ch);// The read goes to the registry and refreshes the local copy too, so it can be slow.
$whois = Api::Services()->GetDomainWhois(['id' => 520])['data'];
$owner = $whois['registrant'];{
"data": {
"registrant": {
"first_name": "John",
"last_name": "Doe",
"company": "",
"email": "[email protected]",
"phone": "5550100",
"phone_cc": "+1",
"fax": "",
"fax_cc": "",
"address_line1": "123 Market Street",
"address_line2": "",
"city": "San Francisco",
"state": "California",
"zipcode": "94105",
"country": "US"
},
"administrative": { "first_name": "John", "last_name": "Doe", "email": "[email protected]" },
"technical": { "first_name": "John", "last_name": "Doe", "email": "[email protected]" },
"billing": { "first_name": "John", "last_name": "Doe", "email": "[email protected]" }
}
}Writing the WHOIS Contacts
Writes the contact details to the registry.
curl -X PUT 'https://panel.example.com/api/v1/admin/services/520/domain/whois' \
-H "Authorization: Bearer $API_KEY" \
-H 'Content-Type: application/json' \
-d '{"registrant":{"first_name":"John","last_name":"Doe","email":"[email protected]","phone":"5550100","phone_cc":"+1","address_line1":"123 Market Street","city":"San Francisco","state":"California","zipcode":"94105","country":"US"}}'const res = await fetch('https://panel.example.com/api/v1/admin/services/520/domain/whois', {
method: 'PUT',
headers: {
Authorization: `Bearer ${apiKey}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
registrant: {
first_name: 'John',
last_name: 'Doe',
email: '[email protected]',
phone: '5550100',
phone_cc: '+1',
address_line1: '123 Market Street',
city: 'San Francisco',
state: 'California',
zipcode: '94105',
country: 'US',
},
}),
});
const body = await res.json();$ch = curl_init('https://panel.example.com/api/v1/admin/services/520/domain/whois');
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_CUSTOMREQUEST => 'PUT',
CURLOPT_HTTPHEADER => [
'Authorization: Bearer ' . $apiKey,
'Content-Type: application/json',
],
CURLOPT_POSTFIELDS => json_encode([
'registrant' => [
'first_name' => 'John',
'last_name' => 'Doe',
'email' => '[email protected]',
'address_line1' => '123 Market Street',
'city' => 'San Francisco',
'country' => 'US',
],
]),
]);
$body = json_decode(curl_exec($ch), true);
curl_close($ch);// Read first and write on top: fields left out can end up empty at the registry.
$whois = Api::Services()->GetDomainWhois(['id' => 520])['data'];
$whois['registrant']['email'] = '[email protected]';
Api::Services()->SetDomainWhois(['id' => 520] + $whois);Changing WHOIS Privacy
Turns on or off the hiding of contact details in public lookups.
enable hides them, disable reveals them.enabled or disabled.enable nor disable.curl -X PUT 'https://panel.example.com/api/v1/admin/services/520/domain/whois-privacy' \
-H "Authorization: Bearer $API_KEY" \
-H 'Content-Type: application/json' \
-d '{"status":"enable"}'const res = await fetch('https://panel.example.com/api/v1/admin/services/520/domain/whois-privacy', {
method: 'PUT',
headers: {
Authorization: `Bearer ${apiKey}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({ status: 'enable' }),
});
const body = await res.json();$ch = curl_init('https://panel.example.com/api/v1/admin/services/520/domain/whois-privacy');
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_CUSTOMREQUEST => 'PUT',
CURLOPT_HTTPHEADER => [
'Authorization: Bearer ' . $apiKey,
'Content-Type: application/json',
],
CURLOPT_POSTFIELDS => json_encode(['status' => 'enable']),
]);
$body = json_decode(curl_exec($ch), true);
curl_close($ch);// On most extensions privacy is a PAID add-on, so turning it on can raise an invoice.
$response = Api::Services()->SetDomainWhoisPrivacy([
'id' => 520,
'status' => 'enable',
]);Pitfalls
Some registries hand the code over directly while others e-mail it to the registrant. In the second case the response says only that it was sent and carries no code. A client that assumes the code arrived reads an empty value here.
What you send becomes the truth: leave the third and fourth out and any existing ones are cleared. Even to change only the primary, the others have to go with it.
The WHOIS write is more than updating contact details: the registrant field decides who legally holds the domain. On most extensions that change starts an approval process and locks the domain out of transfers for a while. Fields left out can also end up empty at the registry, so read first and write on top.
An expired domain first passes through a period where it can be recovered, then it is released. Once the window closes this endpoint answers not_in_window and there is nothing left to do. Recovery also tends to cost a steep fee at the registry.
A service that is not a transfer, or a transfer that is stuck, shows up in the status field of the response rather than as an HTTP error. A client reading only the status code counts a failed transfer as a success.
Related Articles
Vielen Dank für Ihre Rückmeldung!
Unser Support-Team ist rund um die Uhr für Sie da, wenn Sie oben nicht fündig werden.