curl --request POST \
--url https://rdp.sh/api/v1/domains \
--header 'Authorization: <api-key>' \
--header 'Content-Type: application/json' \
--data '
{
"domain": "example.com",
"years": 1,
"auto_renew": false,
"nameservers": [
"ns1.example.net"
]
}
'import requests
url = "https://rdp.sh/api/v1/domains"
payload = {
"domain": "example.com",
"years": 1,
"auto_renew": False,
"nameservers": ["ns1.example.net"]
}
headers = {
"Authorization": "<api-key>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {Authorization: '<api-key>', 'Content-Type': 'application/json'},
body: JSON.stringify({
domain: 'example.com',
years: 1,
auto_renew: false,
nameservers: ['ns1.example.net']
})
};
fetch('https://rdp.sh/api/v1/domains', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://rdp.sh/api/v1/domains",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'domain' => 'example.com',
'years' => 1,
'auto_renew' => false,
'nameservers' => [
'ns1.example.net'
]
]),
CURLOPT_HTTPHEADER => [
"Authorization: <api-key>",
"Content-Type: application/json"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://rdp.sh/api/v1/domains"
payload := strings.NewReader("{\n \"domain\": \"example.com\",\n \"years\": 1,\n \"auto_renew\": false,\n \"nameservers\": [\n \"ns1.example.net\"\n ]\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Authorization", "<api-key>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://rdp.sh/api/v1/domains")
.header("Authorization", "<api-key>")
.header("Content-Type", "application/json")
.body("{\n \"domain\": \"example.com\",\n \"years\": 1,\n \"auto_renew\": false,\n \"nameservers\": [\n \"ns1.example.net\"\n ]\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://rdp.sh/api/v1/domains")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = '<api-key>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"domain\": \"example.com\",\n \"years\": 1,\n \"auto_renew\": false,\n \"nameservers\": [\n \"ns1.example.net\"\n ]\n}"
response = http.request(request)
puts response.read_body{
"status": true,
"message": "Domain registered",
"invoice_id": 8231,
"amount_charged": 11.9,
"years": 1,
"domain": {
"id": 1,
"domain_name": "example.com",
"status": "active",
"provider": "internetbs",
"auto_renew": true,
"whois_privacy": true,
"lock_status": true,
"use_rdp_nameservers": true,
"nameservers": "ns1.rdp.sh",
"registration_date": "2025-01-01T00:00:00.000000Z",
"expiry_date": "2027-01-01T00:00:00.000000Z",
"days_until_expiry": 180,
"is_expiring_soon": true,
"dns_records_count": 2,
"created_at": "2025-01-01T00:00:00.000000Z"
},
"warning": "<string>"
}{
"status": false,
"error": "Insufficient balance",
"required": 11.9,
"available": 5
}Register Domain
Register a domain and pay for it from the account balance.
The domain is registered with WHOIS privacy and a registrar transfer
lock, pointed at the RDP.sh nameservers (ns1.rdp.sh, ns2.rdp.rs),
and given a DNS zone with default @ and www A records. Pass
nameservers to point it elsewhere straight away, or call
PUT /domains/{domain}/nameservers later.
Pricing comes from the RDP.sh price list rather than the registrar:
registration_price * years, plus 19% VAT unless the account is VAT
exempt. Call GET /domains/search first for the exact amount.
curl --request POST \
--url https://rdp.sh/api/v1/domains \
--header 'Authorization: <api-key>' \
--header 'Content-Type: application/json' \
--data '
{
"domain": "example.com",
"years": 1,
"auto_renew": false,
"nameservers": [
"ns1.example.net"
]
}
'import requests
url = "https://rdp.sh/api/v1/domains"
payload = {
"domain": "example.com",
"years": 1,
"auto_renew": False,
"nameservers": ["ns1.example.net"]
}
headers = {
"Authorization": "<api-key>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {Authorization: '<api-key>', 'Content-Type': 'application/json'},
body: JSON.stringify({
domain: 'example.com',
years: 1,
auto_renew: false,
nameservers: ['ns1.example.net']
})
};
fetch('https://rdp.sh/api/v1/domains', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://rdp.sh/api/v1/domains",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'domain' => 'example.com',
'years' => 1,
'auto_renew' => false,
'nameservers' => [
'ns1.example.net'
]
]),
CURLOPT_HTTPHEADER => [
"Authorization: <api-key>",
"Content-Type: application/json"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://rdp.sh/api/v1/domains"
payload := strings.NewReader("{\n \"domain\": \"example.com\",\n \"years\": 1,\n \"auto_renew\": false,\n \"nameservers\": [\n \"ns1.example.net\"\n ]\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Authorization", "<api-key>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://rdp.sh/api/v1/domains")
.header("Authorization", "<api-key>")
.header("Content-Type", "application/json")
.body("{\n \"domain\": \"example.com\",\n \"years\": 1,\n \"auto_renew\": false,\n \"nameservers\": [\n \"ns1.example.net\"\n ]\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://rdp.sh/api/v1/domains")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = '<api-key>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"domain\": \"example.com\",\n \"years\": 1,\n \"auto_renew\": false,\n \"nameservers\": [\n \"ns1.example.net\"\n ]\n}"
response = http.request(request)
puts response.read_body{
"status": true,
"message": "Domain registered",
"invoice_id": 8231,
"amount_charged": 11.9,
"years": 1,
"domain": {
"id": 1,
"domain_name": "example.com",
"status": "active",
"provider": "internetbs",
"auto_renew": true,
"whois_privacy": true,
"lock_status": true,
"use_rdp_nameservers": true,
"nameservers": "ns1.rdp.sh",
"registration_date": "2025-01-01T00:00:00.000000Z",
"expiry_date": "2027-01-01T00:00:00.000000Z",
"days_until_expiry": 180,
"is_expiring_soon": true,
"dns_records_count": 2,
"created_at": "2025-01-01T00:00:00.000000Z"
},
"warning": "<string>"
}{
"status": false,
"error": "Insufficient balance",
"required": 11.9,
"available": 5
}Authorizations
Body
Domain to register, as one label plus a top-level extension
-- example.com. Subdomains and second-level extensions
such as .co.uk are not accepted. The extension must be
active in the RDP.sh price list, which
GET /domains/pricing returns.
3 - 253^[a-zA-Z0-9]([a-zA-Z0-9-]*[a-zA-Z0-9])?\.[a-zA-Z]{2,}$"example.com"
Registration term in years.
1 <= x <= 10Renew the domain automatically. Auto-renewals are charged to the account balance in the week before expiry.
Point the domain at your own nameservers instead of the
RDP.sh ones. Omit to keep the RDP.sh nameservers and the
managed DNS zone. If the switch fails the domain is still
registered and the response carries a warning.
2 - 6 elementsResponse
The domain was registered and the account balance was charged. In
rare cases the registration lands but the managed DNS zone does
not; dns_records_count is 0 when that happens and support is
alerted automatically.
true
"Domain registered"
ID of the balance invoice created for this registration.
8231
Gross amount deducted from the account balance, VAT included.
11.9
Registration term that was purchased.
1
Domain object.
Show child attributes
Show child attributes
Present only when the registration succeeded but applying the requested nameservers did not. The domain is registered either way.