curl --request POST \
--url https://www.closient.com/resolver/api/v1/organizations/{organization_id}/custom-hostnames \
--header 'Content-Type: application/json' \
--header 'X-API-Key: <api-key>' \
--data '
{
"hostname": "id.theirco.com"
}
'import requests
url = "https://www.closient.com/resolver/api/v1/organizations/{organization_id}/custom-hostnames"
payload = { "hostname": "id.theirco.com" }
headers = {
"X-API-Key": "<api-key>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {'X-API-Key': '<api-key>', 'Content-Type': 'application/json'},
body: JSON.stringify({hostname: 'id.theirco.com'})
};
fetch('https://www.closient.com/resolver/api/v1/organizations/{organization_id}/custom-hostnames', 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://www.closient.com/resolver/api/v1/organizations/{organization_id}/custom-hostnames",
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([
'hostname' => 'id.theirco.com'
]),
CURLOPT_HTTPHEADER => [
"Content-Type: application/json",
"X-API-Key: <api-key>"
],
]);
$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://www.closient.com/resolver/api/v1/organizations/{organization_id}/custom-hostnames"
payload := strings.NewReader("{\n \"hostname\": \"id.theirco.com\"\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("X-API-Key", "<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://www.closient.com/resolver/api/v1/organizations/{organization_id}/custom-hostnames")
.header("X-API-Key", "<api-key>")
.header("Content-Type", "application/json")
.body("{\n \"hostname\": \"id.theirco.com\"\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://www.closient.com/resolver/api/v1/organizations/{organization_id}/custom-hostnames")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["X-API-Key"] = '<api-key>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"hostname\": \"id.theirco.com\"\n}"
response = http.request(request)
puts response.read_body{
"fallback_mode": "hosted_404",
"fallback_redirect_url": "",
"fallback_utm_campaign": "",
"fallback_utm_content": "",
"fallback_utm_medium": "",
"fallback_utm_source": "",
"fallback_utm_term": "",
"hostname": "id.theirco.com",
"is_qr_ready": true,
"last_checked_at": "2026-07-20T18:04:11Z",
"last_error": "",
"setup": {
"challenge": {
"name": "_closient-challenge.id.theirco.com",
"purpose": "ownership_verification",
"type": "CNAME",
"value": "9f86d081884c.verify.gtin.one"
},
"qr_density_warning": false,
"serving": {
"name": "id.theirco.com",
"purpose": "resolver_routing",
"type": "CNAME",
"value": "gtin.one"
}
},
"status": "VERIFIED",
"tls_status": "ACTIVE",
"verified_at": "2026-07-20T18:04:11Z"
}{
"detail": "The requested resource was not found.",
"error_code": "not_found",
"retryable": false,
"status": 404,
"timestamp": "2026-03-31T12:00:00+00:00",
"title": "Not Found",
"type": "https://closient.com/docs/errors/not_found"
}{
"detail": "The requested resource was not found.",
"error_code": "not_found",
"retryable": false,
"status": 404,
"timestamp": "2026-03-31T12:00:00+00:00",
"title": "Not Found",
"type": "https://closient.com/docs/errors/not_found"
}{
"detail": "The requested resource was not found.",
"error_code": "not_found",
"retryable": false,
"status": 404,
"timestamp": "2026-03-31T12:00:00+00:00",
"title": "Not Found",
"type": "https://closient.com/docs/errors/not_found"
}{
"detail": "The requested resource was not found.",
"error_code": "not_found",
"retryable": false,
"status": 404,
"timestamp": "2026-03-31T12:00:00+00:00",
"title": "Not Found",
"type": "https://closient.com/docs/errors/not_found"
}{
"detail": "The requested resource was not found.",
"error_code": "not_found",
"retryable": false,
"status": 404,
"timestamp": "2026-03-31T12:00:00+00:00",
"title": "Not Found",
"type": "https://closient.com/docs/errors/not_found"
}{
"detail": "The requested resource was not found.",
"error_code": "not_found",
"retryable": false,
"status": 404,
"timestamp": "2026-03-31T12:00:00+00:00",
"title": "Not Found",
"type": "https://closient.com/docs/errors/not_found"
}{
"detail": "The requested resource was not found.",
"error_code": "not_found",
"retryable": false,
"status": 404,
"timestamp": "2026-03-31T12:00:00+00:00",
"title": "Not Found",
"type": "https://closient.com/docs/errors/not_found"
}Register a custom resolver hostname
Register a customer-owned hostname in PENDING state and return the DNS records to publish. Re-requesting a not-yet-verified hostname the org already owns refreshes its challenge token. Returns 422 when the hostname is Closient-owned or already claimed by another organization. Requires CHANGE permission.
curl --request POST \
--url https://www.closient.com/resolver/api/v1/organizations/{organization_id}/custom-hostnames \
--header 'Content-Type: application/json' \
--header 'X-API-Key: <api-key>' \
--data '
{
"hostname": "id.theirco.com"
}
'import requests
url = "https://www.closient.com/resolver/api/v1/organizations/{organization_id}/custom-hostnames"
payload = { "hostname": "id.theirco.com" }
headers = {
"X-API-Key": "<api-key>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {'X-API-Key': '<api-key>', 'Content-Type': 'application/json'},
body: JSON.stringify({hostname: 'id.theirco.com'})
};
fetch('https://www.closient.com/resolver/api/v1/organizations/{organization_id}/custom-hostnames', 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://www.closient.com/resolver/api/v1/organizations/{organization_id}/custom-hostnames",
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([
'hostname' => 'id.theirco.com'
]),
CURLOPT_HTTPHEADER => [
"Content-Type: application/json",
"X-API-Key: <api-key>"
],
]);
$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://www.closient.com/resolver/api/v1/organizations/{organization_id}/custom-hostnames"
payload := strings.NewReader("{\n \"hostname\": \"id.theirco.com\"\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("X-API-Key", "<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://www.closient.com/resolver/api/v1/organizations/{organization_id}/custom-hostnames")
.header("X-API-Key", "<api-key>")
.header("Content-Type", "application/json")
.body("{\n \"hostname\": \"id.theirco.com\"\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://www.closient.com/resolver/api/v1/organizations/{organization_id}/custom-hostnames")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["X-API-Key"] = '<api-key>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"hostname\": \"id.theirco.com\"\n}"
response = http.request(request)
puts response.read_body{
"fallback_mode": "hosted_404",
"fallback_redirect_url": "",
"fallback_utm_campaign": "",
"fallback_utm_content": "",
"fallback_utm_medium": "",
"fallback_utm_source": "",
"fallback_utm_term": "",
"hostname": "id.theirco.com",
"is_qr_ready": true,
"last_checked_at": "2026-07-20T18:04:11Z",
"last_error": "",
"setup": {
"challenge": {
"name": "_closient-challenge.id.theirco.com",
"purpose": "ownership_verification",
"type": "CNAME",
"value": "9f86d081884c.verify.gtin.one"
},
"qr_density_warning": false,
"serving": {
"name": "id.theirco.com",
"purpose": "resolver_routing",
"type": "CNAME",
"value": "gtin.one"
}
},
"status": "VERIFIED",
"tls_status": "ACTIVE",
"verified_at": "2026-07-20T18:04:11Z"
}{
"detail": "The requested resource was not found.",
"error_code": "not_found",
"retryable": false,
"status": 404,
"timestamp": "2026-03-31T12:00:00+00:00",
"title": "Not Found",
"type": "https://closient.com/docs/errors/not_found"
}{
"detail": "The requested resource was not found.",
"error_code": "not_found",
"retryable": false,
"status": 404,
"timestamp": "2026-03-31T12:00:00+00:00",
"title": "Not Found",
"type": "https://closient.com/docs/errors/not_found"
}{
"detail": "The requested resource was not found.",
"error_code": "not_found",
"retryable": false,
"status": 404,
"timestamp": "2026-03-31T12:00:00+00:00",
"title": "Not Found",
"type": "https://closient.com/docs/errors/not_found"
}{
"detail": "The requested resource was not found.",
"error_code": "not_found",
"retryable": false,
"status": 404,
"timestamp": "2026-03-31T12:00:00+00:00",
"title": "Not Found",
"type": "https://closient.com/docs/errors/not_found"
}{
"detail": "The requested resource was not found.",
"error_code": "not_found",
"retryable": false,
"status": 404,
"timestamp": "2026-03-31T12:00:00+00:00",
"title": "Not Found",
"type": "https://closient.com/docs/errors/not_found"
}{
"detail": "The requested resource was not found.",
"error_code": "not_found",
"retryable": false,
"status": 404,
"timestamp": "2026-03-31T12:00:00+00:00",
"title": "Not Found",
"type": "https://closient.com/docs/errors/not_found"
}{
"detail": "The requested resource was not found.",
"error_code": "not_found",
"retryable": false,
"status": 404,
"timestamp": "2026-03-31T12:00:00+00:00",
"title": "Not Found",
"type": "https://closient.com/docs/errors/not_found"
}Authorizations
Path Parameters
Organization UUID.
22^[23456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz]{22}$Body
The customer-owned FQDN to register, e.g. id.theirco.com (no scheme, no port).
Response
Created
The customer-owned hostname, normalized lowercase.
Ownership-verification state.
PENDING, VERIFIED, DISABLED Edge-certificate state (read-only; driven by the cert pipeline).
NOT_REQUESTED, PENDING, ACTIVE, FAILED True when this hostname is VERIFIED and its edge cert is ACTIVE — QRs may print against it.
Unresolved-scan fallback policy (C-4755). hosted_404 (default) or redirect.
hosted_404, redirect DNS records to publish for this hostname.
Show child attributes
Show child attributes
{
"challenge": {
"name": "_closient-challenge.id.theirco.com",
"purpose": "ownership_verification",
"type": "CNAME",
"value": "9f86d081884c.verify.gtin.one"
},
"qr_density_warning": false,
"serving": {
"name": "id.theirco.com",
"purpose": "resolver_routing",
"type": "CNAME",
"value": "gtin.one"
}
}
ISO-8601 timestamp of the last successful verification, or null.
ISO-8601 timestamp of the last verification attempt, or null.
Reason the last verification attempt failed (empty on success).
Reason the last certificate issuance or renewal check failed (empty on success).
ISO-8601 time before which certificate issuance will not be retried, or null when not in cooldown.
ISO-8601 expiry of the certificate seen at the last successful probe, or null.
Redirect-mode destination. Empty unless fallback_mode is redirect.
2048UTM source override for redirect-mode fallback. Empty = platform default.
255UTM medium override for redirect-mode fallback. Empty = platform default.
255UTM campaign override for redirect-mode fallback. Empty = platform default.
255UTM term override for redirect-mode fallback. Empty = platform default.
255UTM content override for redirect-mode fallback. Empty = platform default.
255