Domain Extensions
The ten endpoints that manage the domain extensions you sell, their prices and their registration documents.
Overview
These endpoints run the domain extensions you sell: which ones are open, which registrar they are attached to, what they cost, and which documents are asked for at registration.
An extension appears in the path by its own name, not by an id. The price table has three levels: operation type, then year, then currency. The same extension can be priced one way for a five-year registration and another for a one-year renewal.
Reference
Listing the Extensions
Returns the domain extensions the installation offers.
active or inactive.none when there is none, and then registration cannot run automatically.curl -G 'https://panel.example.com/api/v1/admin/products/domain/tlds' \
-H "Authorization: Bearer $API_KEY" \
-d limit=100const url = new URL('https://panel.example.com/api/v1/admin/products/domain/tlds');
url.searchParams.set('limit', '100');
const res = await fetch(url, { headers: { Authorization: `Bearer ${apiKey}` } });
const body = await res.json();$url = 'https://panel.example.com/api/v1/admin/products/domain/tlds?' . http_build_query(['limit' => 100]);
$ch = curl_init($url);
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . $apiKey],
]);
$body = json_decode(curl_exec($ch), true);
curl_close($ch);$response = Api::Products()->GetDomainTlds([], ['limit' => 100]);Extension Detail
Returns one extension with its costs and the whole price table.
active or inactive.amount, status, promotion and promotion_status.curl 'https://panel.example.com/api/v1/admin/products/domain/tlds/com' \
-H "Authorization: Bearer $API_KEY"const res = await fetch('https://panel.example.com/api/v1/admin/products/domain/tlds/com', {
headers: { Authorization: `Bearer ${apiKey}` },
});
const body = await res.json();$ch = curl_init('https://panel.example.com/api/v1/admin/products/domain/tlds/com');
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . $apiKey],
]);
$body = json_decode(curl_exec($ch), true);
curl_close($ch);$response = Api::Products()->GetDomainTld(['tld' => 'com']);
// The price table has three levels: type, year, currency.
$oneYear = $response['data']['pricing']['register']['1']['USD']['amount'] ?? null;{
"data": {
"id": 3,
"extension": "com",
"status": "active",
"module": "Enom",
"auto_pricing": false,
"features": {
"dns_manage": true,
"forwarding": false,
"whois_privacy": true,
"epp_code": true
},
"min_years": 1,
"max_years": 10,
"register_cost": 8.5,
"renewal_cost": 9,
"transfer_cost": 8.5,
"pricing": {
"register": {
"1": {
"USD": {
"amount": 12,
"status": true,
"promotion": 0,
"promotion_status": false
}
}
}
}
}
}Adding an Extension
Adds a new extension. If you like, the starting prices and the logo go in the same request.
active or inactive.{register, transfer, renewal} object. There is no year breakdown here; the detailed table goes in through the pricing endpoint.pricing comes back empty.extension was empty.curl -X POST 'https://panel.example.com/api/v1/admin/products/domain/tlds' \
-H "Authorization: Bearer $API_KEY" \
-H 'Content-Type: application/json' \
-d '{"extension":"com","registrar":"Enom","status":"active","features":{"dns_manage":true,"whois_privacy":true},"pricing":{"USD":{"register":12,"transfer":12,"renewal":14}}}'const res = await fetch('https://panel.example.com/api/v1/admin/products/domain/tlds', {
method: 'POST',
headers: {
Authorization: `Bearer ${apiKey}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
extension: 'com',
registrar: 'Enom',
status: 'active',
features: { dns_manage: true, whois_privacy: true },
pricing: { USD: { register: 12, transfer: 12, renewal: 14 } },
}),
});
const body = await res.json();$ch = curl_init('https://panel.example.com/api/v1/admin/products/domain/tlds');
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_POST => true,
CURLOPT_HTTPHEADER => [
'Authorization: Bearer ' . $apiKey,
'Content-Type: application/json',
],
CURLOPT_POSTFIELDS => json_encode([
'extension' => 'com',
'registrar' => 'Enom',
'status' => 'active',
'features' => ['dns_manage' => true, 'whois_privacy' => true],
'pricing' => ['USD' => ['register' => 12, 'transfer' => 12, 'renewal' => 14]],
]),
]);
$body = json_decode(curl_exec($ch), true);
curl_close($ch);// The price here is a one-year starting point; use the pricing endpoint for the year breakdown.
$response = Api::Products()->CreateDomainTld([
'extension' => 'com',
'registrar' => 'Enom',
'pricing' => ['USD' => ['register' => 12, 'renewal' => 14]],
]);Deleting an Extension
Deletes the extension and its prices.
gate:domain.tld_delete hook vetoed the operation.curl -X DELETE 'https://panel.example.com/api/v1/admin/products/domain/tlds/com' \
-H "Authorization: Bearer $API_KEY"const res = await fetch('https://panel.example.com/api/v1/admin/products/domain/tlds/com', {
method: 'DELETE',
headers: { Authorization: `Bearer ${apiKey}` },
});
const body = await res.json();$ch = curl_init('https://panel.example.com/api/v1/admin/products/domain/tlds/com');
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_CUSTOMREQUEST => 'DELETE',
CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . $apiKey],
]);
$body = json_decode(curl_exec($ch), true);
curl_close($ch);$response = Api::Products()->DeleteDomainTld(['tld' => 'com']);Bulk Action
Switches several extensions on or off, deletes them, or changes their settings.
enable, disable, delete or change.extension and the fields to change: the features, the module, the status, the order. Only on the change action.curl -X POST 'https://panel.example.com/api/v1/admin/products/domain/tlds/bulk' \
-H "Authorization: Bearer $API_KEY" \
-H 'Content-Type: application/json' \
-d '{"action":"disable","extensions":["net","org"]}'const res = await fetch('https://panel.example.com/api/v1/admin/products/domain/tlds/bulk', {
method: 'POST',
headers: {
Authorization: `Bearer ${apiKey}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({ action: 'disable', extensions: ['net', 'org'] }),
});
const body = await res.json();$ch = curl_init('https://panel.example.com/api/v1/admin/products/domain/tlds/bulk');
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_POST => true,
CURLOPT_HTTPHEADER => [
'Authorization: Bearer ' . $apiKey,
'Content-Type: application/json',
],
CURLOPT_POSTFIELDS => json_encode([
'action' => 'disable',
'extensions' => ['net', 'org'],
]),
]);
$body = json_decode(curl_exec($ch), true);
curl_close($ch);// The 'change' action wants a list of changes, not a list of extensions.
$response = Api::Products()->BulkDomainTlds([
'action' => 'change',
'changes' => [
['extension' => 'net', 'whois_privacy' => true],
['extension' => 'org', 'status' => 'inactive'],
],
]);Setting the Pricing
Writes the extension's registration, transfer and renewal prices, broken down by year and currency.
register, transfer, renewal), then year, then currency code. The innermost object carries status, fee, promotion_status and promotion.pricing map rather than assuming the shape you sent survived.curl -X PUT 'https://panel.example.com/api/v1/admin/products/domain/tlds/com/pricing' \
-H "Authorization: Bearer $API_KEY" \
-H 'Content-Type: application/json' \
-d '{"auto_pricing":false,"pricing":{"register":{"1":{"USD":{"status":true,"fee":12,"promotion_status":false,"promotion":0}}}}}'const res = await fetch('https://panel.example.com/api/v1/admin/products/domain/tlds/com/pricing', {
method: 'PUT',
headers: {
Authorization: `Bearer ${apiKey}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
auto_pricing: false,
pricing: {
register: {
1: { USD: { status: true, fee: 12, promotion_status: false, promotion: 0 } },
},
},
}),
});
const body = await res.json();$ch = curl_init('https://panel.example.com/api/v1/admin/products/domain/tlds/com/pricing');
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_CUSTOMREQUEST => 'PUT',
CURLOPT_HTTPHEADER => [
'Authorization: Bearer ' . $apiKey,
'Content-Type: application/json',
],
CURLOPT_POSTFIELDS => json_encode([
'auto_pricing' => false,
'pricing' => [
'register' => [
1 => ['USD' => ['status' => true, 'fee' => 12]],
],
],
]),
]);
$body = json_decode(curl_exec($ch), true);
curl_close($ch);// Reading calls the field 'amount', writing calls it 'fee' - they hold the same value.
$current = Api::Products()->GetDomainTld(['tld' => 'com'])['data']['pricing'];
$amount = $current['register']['1']['USD']['amount'];
Api::Products()->SetDomainTldPricing([
'tld' => 'com',
'pricing' => [
'register' => [1 => ['USD' => ['status' => true, 'fee' => $amount + 1]]],
],
]);Extensions That Ask for Documents
Returns the extensions that ask for documents at registration.
curl 'https://panel.example.com/api/v1/admin/products/domain/docs' \
-H "Authorization: Bearer $API_KEY"const res = await fetch('https://panel.example.com/api/v1/admin/products/domain/docs', {
headers: { Authorization: `Bearer ${apiKey}` },
});
const body = await res.json();$ch = curl_init('https://panel.example.com/api/v1/admin/products/domain/docs');
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . $apiKey],
]);
$body = json_decode(curl_exec($ch), true);
curl_close($ch);$response = Api::Products()->GetDomainDocsList();Reading the Document Set
Returns the documents an extension asks for at registration.
text, file or select.active or inactive.curl 'https://panel.example.com/api/v1/admin/products/domain/tlds/us/docs' \
-H "Authorization: Bearer $API_KEY"const res = await fetch('https://panel.example.com/api/v1/admin/products/domain/tlds/us/docs', {
headers: { Authorization: `Bearer ${apiKey}` },
});
const body = await res.json();$ch = curl_init('https://panel.example.com/api/v1/admin/products/domain/tlds/us/docs');
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . $apiKey],
]);
$body = json_decode(curl_exec($ch), true);
curl_close($ch);$response = Api::Products()->GetDomainTldDocs(['tld' => 'us']);Writing the Document Set
Writes the document set. What you send becomes the truth; a document missing from it is deleted.
curl -X PUT 'https://panel.example.com/api/v1/admin/products/domain/tlds/us/docs' \
-H "Authorization: Bearer $API_KEY" \
-H 'Content-Type: application/json' \
-d '{"description":{"en":"Provide a valid ID."},"docs":{"n1":{"type":"text","name":{"en":"Registrant ID"}}}}'const res = await fetch('https://panel.example.com/api/v1/admin/products/domain/tlds/us/docs', {
method: 'PUT',
headers: {
Authorization: `Bearer ${apiKey}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
description: { en: 'Provide a valid ID.' },
docs: {
n1: { type: 'text', name: { en: 'Registrant ID' } },
},
}),
});
const body = await res.json();$ch = curl_init('https://panel.example.com/api/v1/admin/products/domain/tlds/us/docs');
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_CUSTOMREQUEST => 'PUT',
CURLOPT_HTTPHEADER => [
'Authorization: Bearer ' . $apiKey,
'Content-Type: application/json',
],
CURLOPT_POSTFIELDS => json_encode([
'description' => ['en' => 'Provide a valid ID.'],
'docs' => [
'n1' => ['type' => 'text', 'name' => ['en' => 'Registrant ID']],
],
]),
]);
$body = json_decode(curl_exec($ch), true);
curl_close($ch);// To ADD a document, send the existing set too, or the earlier ones are deleted.
$existing = Api::Products()->GetDomainTldDocs(['tld' => 'us'])['data']['docs'];
$docs = [];
foreach ($existing as $doc) $docs[$doc['id']] = ['type' => $doc['type'], 'name' => $doc['names']];
$docs['n1'] = ['type' => 'file', 'name' => ['en' => 'Passport scan']];
Api::Products()->SetDomainTldDocs(['tld' => 'us', 'docs' => $docs]);Deleting the Document Set
Deletes the extension's whole document set.
curl -X DELETE 'https://panel.example.com/api/v1/admin/products/domain/tlds/us/docs' \
-H "Authorization: Bearer $API_KEY"const res = await fetch('https://panel.example.com/api/v1/admin/products/domain/tlds/us/docs', {
method: 'DELETE',
headers: { Authorization: `Bearer ${apiKey}` },
});
const body = await res.json();$ch = curl_init('https://panel.example.com/api/v1/admin/products/domain/tlds/us/docs');
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_CUSTOMREQUEST => 'DELETE',
CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . $apiKey],
]);
$body = json_decode(curl_exec($ch), true);
curl_close($ch);$response = Api::Products()->DeleteDomainTldDocs(['tld' => 'us']);Pitfalls
In the price table the same value is called amount when you read it and fee when you write it. That means the table you read from the detail cannot go straight back: you have to rename the field first.
The document write does not merge. To add one document you have to send the whole existing set as well, or the earlier ones are deleted and that extension stops asking for anything. Give a new document a key you made up, and use the record's id for an existing one.
Enabling, disabling and deleting want a list of extensions, while changing settings wants a per-extension list of changes. Sending the wrong field quietly leaves the action empty: the returned list comes back empty and no error is raised. Check what was applied from that list.
With no registrar module attached the extension can still be sold, but registration, transfer and renewal do not run automatically; an operator does them by hand. Check the module is attached before opening the extension.
Related Articles
Thanks for your feedback!
Our support team is here around the clock for anything you can't find above.