SupportHost italian

Domain management

Nameservers, contacts, EPP code, transfer lock, WHOIS privacy and auto-renew.

These calls belong to the client API and are addressed by the numeric domain id returned by GET /reseller/domains/{name} (field data.id), not by the name. Success bodies are {"data": …}; errors use the same error envelope as every other call.

List your domains #

GET /client/domains

Every domain of the account, paginated, nearest expiration first, with cancelled, transferred-away and pending-delete domains last. Filter by search (part of the name), status, expiring_within_days or auto_renew.

Each item carries the numeric id the other Domain management calls are addressed by. Read-only.

Parameters

Query

  • search string
    Part of a domain name, e.g. example.
  • status string
    Only domains in this status, e.g. active.
  • expiring_within_days integer
    Only domains expiring within this many days (already expired ones included).
  • auto_renew string
    Only domains with auto-renew on or off.
  • per_page integer
    Domains per page, 1–100. Defaults to this server’s page size.
  • page integer
    Page number, from 1.

Responses

  • 200

    A page of your domains.

    Response body application/json
    • data array of object
      16 properties
      • id integer
      • client_id integer
      • sld string
      • tld_extension string | null
      • name string
      • display_name string
      • status string
      • auto_renew boolean
      • registration_date string | null
      • expiration_date string | null
      • registration_period_years integer
      • currency_code string | null
      • last_synced_at string | null
      • registrant_verification object | null
        Owner (registrant) email verification as last read from the registrar, or null when it was never read or the registrar does not report it. status is not_required, pending, verified or suspended; while it is pending or suspended the owner must click the link the registrar emailed to email. This is the state as last read, not a live answer: it is refreshed only for Active domains, so on any other status it may be stale.
        3 properties
        • status string
        • email string
        • deadline string | null
      • tld object
        2 properties
        • id integer | null
        • extension string | null
      • supported_actions array of string | null
    • links object
      4 properties
      • first string | null
      • last string | null
      • prev string | null
      • next string | null
    • meta object
      8 properties
      • current_page integer
      • from integer | null
      • last_page integer
      • links array of object
        3 properties
        • url string | null
        • label string
        • active boolean
      • path string
      • per_page integer
      • to integer | null
      • total integer
  • 401 unauthenticated ApiError
  • 403 client_token_required token_not_api_enabled token_not_client_scoped client_access_revoked client_cancelled ip_not_allowed ip_whitelist_misconfigured forbidden ApiError
  • 404 client_not_found ApiError
  • 429 rate_limited ApiError

cURL

curl 'https://portal.supporthost.com/api/v1/client/domains' \
  -H "Authorization: Bearer $API_TOKEN" \
  -H 'Accept: application/json'

PHP

<?php

$ch = curl_init('https://portal.supporthost.com/api/v1/client/domains');
curl_setopt_array($ch, [
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_HTTPHEADER => [
        'Authorization: Bearer ' . getenv('API_TOKEN'),
        'Accept: application/json',
    ],
]);

$body   = json_decode(curl_exec($ch), true);
$status = curl_getinfo($ch, CURLINFO_RESPONSE_CODE);

if ($status >= 400) {
    // Error envelope: {"error": {"code": "...", "message": "...", "fields": {...}}}
    echo $status . ' ' . ($body['error']['code'] ?? '') . ': ' . ($body['error']['message'] ?? '') . "\n";
} else {
    print_r($body);
}

Node.js

// Save as a .mjs file (ES module, Node 18+): it uses top-level await.
const response = await fetch('https://portal.supporthost.com/api/v1/client/domains', {
  headers: {
    Authorization: `Bearer ${process.env.API_TOKEN}`,
    Accept: 'application/json',
  },
});

console.log(await response.json());

Response

200

{
  "data": [
    {
      "id": 1042,
      "client_id": 318,
      "sld": "example",
      "tld_extension": ".com",
      "name": "example.com",
      "display_name": "example.com",
      "status": "active",
      "auto_renew": false,
      "registration_date": "2026-09-15T00:00:00+02:00",
      "expiration_date": "2027-09-15T00:00:00+02:00",
      "registration_period_years": 1,
      "currency_code": "EUR",
      "last_synced_at": "2026-09-27T06:00:12+02:00",
      "registrant_verification": {
        "status": "pending",
        "email": "owner@example.com",
        "deadline": "2026-10-09T10:00:00+00:00"
      },
      "tld": {
        "id": 3,
        "extension": ".com"
      },
      "supported_actions": [
        "renew",
        "get_epp",
        "lock",
        "unlock",
        "update_nameservers",
        "update_contact",
        "enable_whois_privacy",
        "disable_whois_privacy"
      ]
    }
  ],
  "links": {
    "first": "https://billing.example.com/api/v1/client/domains?page=1",
    "last": "https://billing.example.com/api/v1/client/domains?page=2",
    "prev": null,
    "next": "https://billing.example.com/api/v1/client/domains?page=2"
  },
  "meta": {
    "current_page": 1,
    "from": 1,
    "last_page": 2,
    "links": [
      {
        "url": "https://billing.example.com/api/v1/client/domains?page=1",
        "label": "1",
        "active": true
      }
    ],
    "path": "https://billing.example.com/api/v1/client/domains",
    "per_page": 25,
    "to": 25,
    "total": 38
  }
}

Error responses share one format: see Errors.

Get a domain #

GET /client/domains/{domain}

One of your domains with its dates, status, auto-renew flag and, in supported_actions, the management operations its registry supports in the domain’s current status.

By default the data may be refreshed from the registry when it is stale; pass fresh=1 to force a live refresh first (slower).

Parameters

Path

  • domain integer required
    The domain ID

Query

  • fresh boolean
    Set to 1 to refresh the domain from the registry before answering.

Responses

  • 200
    Response body application/json
    • data object
      16 properties
      • id integer
      • client_id integer
      • sld string
      • tld_extension string | null
      • name string
      • display_name string
      • status string
      • auto_renew boolean
      • registration_date string | null
      • expiration_date string | null
      • registration_period_years integer
      • currency_code string | null
      • last_synced_at string | null
      • registrant_verification object | null
        Owner (registrant) email verification as last read from the registrar, or null when it was never read or the registrar does not report it. status is not_required, pending, verified or suspended; while it is pending or suspended the owner must click the link the registrar emailed to email. This is the state as last read, not a live answer: it is refreshed only for Active domains, so on any other status it may be stale.
        3 properties
        • status string
        • email string
        • deadline string | null
      • tld object
        2 properties
        • id integer | null
        • extension string | null
      • supported_actions array of string | null
  • 401 unauthenticated ApiError
  • 403 client_token_required token_not_api_enabled token_not_client_scoped client_access_revoked client_cancelled ip_not_allowed ip_whitelist_misconfigured forbidden ApiError
  • 404 client_not_found not_found ApiError
  • 429 rate_limited ApiError

cURL

curl 'https://portal.supporthost.com/api/v1/client/domains/{domain}' \
  -H "Authorization: Bearer $API_TOKEN" \
  -H 'Accept: application/json'

PHP

<?php

$ch = curl_init('https://portal.supporthost.com/api/v1/client/domains/{domain}');
curl_setopt_array($ch, [
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_HTTPHEADER => [
        'Authorization: Bearer ' . getenv('API_TOKEN'),
        'Accept: application/json',
    ],
]);

$body   = json_decode(curl_exec($ch), true);
$status = curl_getinfo($ch, CURLINFO_RESPONSE_CODE);

if ($status >= 400) {
    // Error envelope: {"error": {"code": "...", "message": "...", "fields": {...}}}
    echo $status . ' ' . ($body['error']['code'] ?? '') . ': ' . ($body['error']['message'] ?? '') . "\n";
} else {
    print_r($body);
}

Node.js

const response = await fetch('https://portal.supporthost.com/api/v1/client/domains/{domain}', {
  headers: {
    Authorization: `Bearer ${process.env.API_TOKEN}`,
    Accept: 'application/json',
  },
});

console.log(await response.json());

Response

200

{
  "data": {
    "id": 1042,
    "client_id": 318,
    "sld": "example",
    "tld_extension": ".com",
    "name": "example.com",
    "display_name": "example.com",
    "status": "active",
    "auto_renew": false,
    "registration_date": "2026-09-15T00:00:00+02:00",
    "expiration_date": "2027-09-15T00:00:00+02:00",
    "registration_period_years": 1,
    "currency_code": "EUR",
    "last_synced_at": "2026-09-27T06:00:12+02:00",
    "registrant_verification": {
      "status": "pending",
      "email": "owner@example.com",
      "deadline": "2026-10-09T10:00:00+00:00"
    },
    "tld": {
      "id": 3,
      "extension": ".com"
    },
    "supported_actions": [
      "renew",
      "get_epp",
      "lock",
      "unlock",
      "update_nameservers",
      "update_contact",
      "enable_whois_privacy",
      "disable_whois_privacy"
    ]
  }
}

Error responses share one format: see Errors.

Get the nameservers #

GET /client/domains/{domain}/nameservers

The nameservers currently set at the registry, read live. Read-only.

Parameters

Path

  • domain integer required
    The domain ID

Responses

  • 200
    Response body application/json
    • data object
      1 property
      • nameservers array of string
  • 401 unauthenticated ApiError
  • 403 client_token_required token_not_api_enabled token_not_client_scoped client_access_revoked client_cancelled ip_not_allowed ip_whitelist_misconfigured forbidden ApiError
  • 404 client_not_found not_found ApiError
  • 422 invalid_request unprocessable ApiError
  • 429 rate_limited ApiError

cURL

curl 'https://portal.supporthost.com/api/v1/client/domains/{domain}/nameservers' \
  -H "Authorization: Bearer $API_TOKEN" \
  -H 'Accept: application/json'

PHP

<?php

$ch = curl_init('https://portal.supporthost.com/api/v1/client/domains/{domain}/nameservers');
curl_setopt_array($ch, [
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_HTTPHEADER => [
        'Authorization: Bearer ' . getenv('API_TOKEN'),
        'Accept: application/json',
    ],
]);

$body   = json_decode(curl_exec($ch), true);
$status = curl_getinfo($ch, CURLINFO_RESPONSE_CODE);

if ($status >= 400) {
    // Error envelope: {"error": {"code": "...", "message": "...", "fields": {...}}}
    echo $status . ' ' . ($body['error']['code'] ?? '') . ': ' . ($body['error']['message'] ?? '') . "\n";
} else {
    print_r($body);
}

Node.js

const response = await fetch('https://portal.supporthost.com/api/v1/client/domains/{domain}/nameservers', {
  headers: {
    Authorization: `Bearer ${process.env.API_TOKEN}`,
    Accept: 'application/json',
  },
});

console.log(await response.json());

Response

200

{
  "data": {
    "nameservers": [
      "ns1.example.net",
      "ns2.example.net"
    ]
  }
}

Error responses share one format: see Errors.

Change the nameservers #

PUT /client/domains/{domain}/nameservers

Replaces the domain’s nameservers at the registry with the list you send (2 to 13 host names). completed: false means the registry accepted the change but applies it later; message explains.

Free of charge. Refused with 403 domain_not_active when the domain’s status does not allow it (e.g. expired).

Parameters

Path

  • domain integer required
    The domain ID

Body application/json required

  • nameservers array of string required
    2 to 13 nameserver host names, all different. The list replaces the current one.
    • Min items 2
    • Max items 13
    • Unique items
    • Pattern ^(?=.{1,253}$)([a-z0-9](?:[a-z0-9\-]{0,61}[a-z0-9])?)(\.[a-z0-9](?:[a-z0-9\-]{0,61}[a-z0-9])?)+$
    • Max length 253

Responses

  • 200
    Response body application/json
    • data object
      2 properties
      • completed boolean
      • message string
  • 401 unauthenticated ApiError
  • 403 client_token_required token_not_api_enabled token_not_client_scoped client_access_revoked client_cancelled ip_not_allowed ip_whitelist_misconfigured forbidden domain_not_active ApiError
  • 404 client_not_found not_found ApiError
  • 422 invalid_request unprocessable ApiError
  • 429 rate_limited ApiError

cURL

curl -X PUT 'https://portal.supporthost.com/api/v1/client/domains/{domain}/nameservers' \
  -H "Authorization: Bearer $API_TOKEN" \
  -H 'Accept: application/json' \
  -H 'Content-Type: application/json' \
  -d '{
  "nameservers": [
    "ns1.example.net",
    "ns2.example.net",
    "ns3.example.net"
  ]
}'

PHP

<?php

$ch = curl_init('https://portal.supporthost.com/api/v1/client/domains/{domain}/nameservers');
curl_setopt_array($ch, [
    CURLOPT_CUSTOMREQUEST => 'PUT',
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_HTTPHEADER => [
        'Authorization: Bearer ' . getenv('API_TOKEN'),
        'Accept: application/json',
        'Content-Type: application/json',
    ],
    CURLOPT_POSTFIELDS => json_encode([
        'nameservers' => [
            'ns1.example.net',
            'ns2.example.net',
            'ns3.example.net',
        ],
    ]),
]);

$body   = json_decode(curl_exec($ch), true);
$status = curl_getinfo($ch, CURLINFO_RESPONSE_CODE);

if ($status >= 400) {
    // Error envelope: {"error": {"code": "...", "message": "...", "fields": {...}}}
    echo $status . ' ' . ($body['error']['code'] ?? '') . ': ' . ($body['error']['message'] ?? '') . "\n";
} else {
    print_r($body);
}

Node.js

const response = await fetch('https://portal.supporthost.com/api/v1/client/domains/{domain}/nameservers', {
  method: 'PUT',
  headers: {
    Authorization: `Bearer ${process.env.API_TOKEN}`,
    Accept: 'application/json',
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
    "nameservers": [
      "ns1.example.net",
      "ns2.example.net",
      "ns3.example.net"
    ]
  }),
});

console.log(await response.json());

Response

200

{
  "data": {
    "completed": true,
    "message": "Nameservers updated."
  }
}

Error responses share one format: see Errors.

Get a contact #

GET /client/domains/{domain}/contacts

One contact of the domain, read live from the registry: the registrant by default, or the role named by type. The response is keyed by that role and also lists, in required_types, the roles this domain uses.

Parameters

Path

  • domain integer required
    The domain ID

Query

  • type string
    The contact role: registrant (default), admin, tech or billing. Must be one of the roles this domain uses.

Responses

  • 200
    Response body application/json
    • data object
      1 property
      • required_types array
  • 401 unauthenticated ApiError
  • 403 client_token_required token_not_api_enabled token_not_client_scoped client_access_revoked client_cancelled ip_not_allowed ip_whitelist_misconfigured forbidden ApiError
  • 404 client_not_found not_found ApiError
  • 422 invalid_request unprocessable ApiError
  • 429 rate_limited ApiError

cURL

curl 'https://portal.supporthost.com/api/v1/client/domains/{domain}/contacts' \
  -H "Authorization: Bearer $API_TOKEN" \
  -H 'Accept: application/json'

PHP

<?php

$ch = curl_init('https://portal.supporthost.com/api/v1/client/domains/{domain}/contacts');
curl_setopt_array($ch, [
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_HTTPHEADER => [
        'Authorization: Bearer ' . getenv('API_TOKEN'),
        'Accept: application/json',
    ],
]);

$body   = json_decode(curl_exec($ch), true);
$status = curl_getinfo($ch, CURLINFO_RESPONSE_CODE);

if ($status >= 400) {
    // Error envelope: {"error": {"code": "...", "message": "...", "fields": {...}}}
    echo $status . ' ' . ($body['error']['code'] ?? '') . ': ' . ($body['error']['message'] ?? '') . "\n";
} else {
    print_r($body);
}

Node.js

const response = await fetch('https://portal.supporthost.com/api/v1/client/domains/{domain}/contacts', {
  headers: {
    Authorization: `Bearer ${process.env.API_TOKEN}`,
    Accept: 'application/json',
  },
});

console.log(await response.json());

Response

200

{
  "data": {
    "required_types": [
      "registrant",
      "admin",
      "tech"
    ]
  }
}

Error responses share one format: see Errors.

Update a contact #

PUT /client/domains/{domain}/contacts

Updates one contact of the domain at the registry: the registrant by default, or the role named by type. Send the full contact, not only the fields that change.

For the registrant, the registry-specific fields some TLDs require are sent at the top level, next to first_name; which keys are required depends on the TLD and on this server’s configuration, and a missing one answers 422 naming it.

Free of charge. completed: false means the registry accepted the change but applies it later; message explains.

Parameters

Path

  • domain integer required
    The domain ID

Body application/json required

  • type string
    The contact to update: registrant (the default), admin, tech or billing. Only the roles this domain’s registry uses are accepted; GET /client/domains/{domain}/contacts lists them in required_types.
    Allowed values registrant admin tech billing
  • first_name string required
    • Max length 100
  • last_name string required
    • Max length 100
  • organization string | null
    Company name. For the registrant, some TLDs require it and some refuse it.
    • Max length 200
  • email string required
    • Format email
    • Max length 200
  • phone string required
    International format +CC.NUMBER, e.g. +39.0212345678. You may instead send a local number here together with phone_country_code (ISO country, e.g. IT).
    • Pattern ^\+[0-9]{1,3}\.[0-9]{1,14}$
    • Max length 30
  • street1 string required
    • Max length 200
  • street2 string | null
    • Max length 200
  • city string required
    • Max length 100
  • state_province string | null
    • Max length 100
  • postal_code string required
    • Max length 20
  • country_code string required
    ISO 3166-1 alpha-2 country code, e.g. IT.
    • Min length 2
    • Max length 2

Responses

  • 200
    Response body application/json
    • data object
      2 properties
      • completed boolean
      • message string
  • 401 unauthenticated ApiError
  • 403 client_token_required token_not_api_enabled token_not_client_scoped client_access_revoked client_cancelled ip_not_allowed ip_whitelist_misconfigured forbidden domain_not_active ApiError
  • 404 client_not_found not_found ApiError
  • 422 invalid_request unprocessable ApiError
  • 429 rate_limited ApiError

cURL

curl -X PUT 'https://portal.supporthost.com/api/v1/client/domains/{domain}/contacts' \
  -H "Authorization: Bearer $API_TOKEN" \
  -H 'Accept: application/json' \
  -H 'Content-Type: application/json' \
  -d '{
  "type": "registrant",
  "first_name": "Mario",
  "last_name": "Rossi",
  "organization": "Example Srl",
  "email": "mario.rossi@example.com",
  "phone": "+39.0212345678",
  "street1": "Via Roma 1",
  "city": "Milano",
  "state_province": "MI",
  "postal_code": "20121",
  "country_code": "IT"
}'

PHP

<?php

$ch = curl_init('https://portal.supporthost.com/api/v1/client/domains/{domain}/contacts');
curl_setopt_array($ch, [
    CURLOPT_CUSTOMREQUEST => 'PUT',
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_HTTPHEADER => [
        'Authorization: Bearer ' . getenv('API_TOKEN'),
        'Accept: application/json',
        'Content-Type: application/json',
    ],
    CURLOPT_POSTFIELDS => json_encode([
        'type' => 'registrant',
        'first_name' => 'Mario',
        'last_name' => 'Rossi',
        'organization' => 'Example Srl',
        'email' => 'mario.rossi@example.com',
        'phone' => '+39.0212345678',
        'street1' => 'Via Roma 1',
        'city' => 'Milano',
        'state_province' => 'MI',
        'postal_code' => '20121',
        'country_code' => 'IT',
    ]),
]);

$body   = json_decode(curl_exec($ch), true);
$status = curl_getinfo($ch, CURLINFO_RESPONSE_CODE);

if ($status >= 400) {
    // Error envelope: {"error": {"code": "...", "message": "...", "fields": {...}}}
    echo $status . ' ' . ($body['error']['code'] ?? '') . ': ' . ($body['error']['message'] ?? '') . "\n";
} else {
    print_r($body);
}

Node.js

const response = await fetch('https://portal.supporthost.com/api/v1/client/domains/{domain}/contacts', {
  method: 'PUT',
  headers: {
    Authorization: `Bearer ${process.env.API_TOKEN}`,
    Accept: 'application/json',
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
    "type": "registrant",
    "first_name": "Mario",
    "last_name": "Rossi",
    "organization": "Example Srl",
    "email": "mario.rossi@example.com",
    "phone": "+39.0212345678",
    "street1": "Via Roma 1",
    "city": "Milano",
    "state_province": "MI",
    "postal_code": "20121",
    "country_code": "IT"
  }),
});

console.log(await response.json());

Response

200

{
  "data": {
    "completed": true,
    "message": "Contact updated."
  }
}

Error responses share one format: see Errors.

Get the transfer lock state #

GET /client/domains/{domain}/lock-state

Whether the registry transfer lock is on, read live, and in supported which of lock / unlock this domain’s registry allows. Read-only.

Parameters

Path

  • domain integer required
    The domain ID

Responses

  • 200
    Response body application/json
    • data object
      2 properties
      • locked boolean
      • supported array of string
  • 401 unauthenticated ApiError
  • 403 client_token_required token_not_api_enabled token_not_client_scoped client_access_revoked client_cancelled ip_not_allowed ip_whitelist_misconfigured forbidden ApiError
  • 404 client_not_found not_found ApiError
  • 422 invalid_request unprocessable ApiError
  • 429 rate_limited ApiError

cURL

curl 'https://portal.supporthost.com/api/v1/client/domains/{domain}/lock-state' \
  -H "Authorization: Bearer $API_TOKEN" \
  -H 'Accept: application/json'

PHP

<?php

$ch = curl_init('https://portal.supporthost.com/api/v1/client/domains/{domain}/lock-state');
curl_setopt_array($ch, [
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_HTTPHEADER => [
        'Authorization: Bearer ' . getenv('API_TOKEN'),
        'Accept: application/json',
    ],
]);

$body   = json_decode(curl_exec($ch), true);
$status = curl_getinfo($ch, CURLINFO_RESPONSE_CODE);

if ($status >= 400) {
    // Error envelope: {"error": {"code": "...", "message": "...", "fields": {...}}}
    echo $status . ' ' . ($body['error']['code'] ?? '') . ': ' . ($body['error']['message'] ?? '') . "\n";
} else {
    print_r($body);
}

Node.js

const response = await fetch('https://portal.supporthost.com/api/v1/client/domains/{domain}/lock-state', {
  headers: {
    Authorization: `Bearer ${process.env.API_TOKEN}`,
    Accept: 'application/json',
  },
});

console.log(await response.json());

Response

200

{
  "data": {
    "locked": true,
    "supported": [
      "lock",
      "unlock"
    ]
  }
}

Error responses share one format: see Errors.

Get the WHOIS privacy state #

GET /client/domains/{domain}/whois-privacy-state

Whether WHOIS privacy is subscribed on the domain (subscribed), whether the registry reports it active (registrarEnabled, read live), whether enabling it is free or paid (optionPricing) and which of enable / disable the registry supports (supported). Read-only.

Parameters

Path

  • domain integer required
    The domain ID

Responses

  • 200
    Response body application/json
    • data object
      4 properties
      • subscribed boolean
      • registrarEnabled boolean
      • optionPricing string
        Allowed values unknown free paid
      • supported array of string
  • 401 unauthenticated ApiError
  • 403 client_token_required token_not_api_enabled token_not_client_scoped client_access_revoked client_cancelled ip_not_allowed ip_whitelist_misconfigured forbidden ApiError
  • 404 client_not_found not_found ApiError
  • 422 invalid_request unprocessable ApiError
  • 429 rate_limited ApiError

cURL

curl 'https://portal.supporthost.com/api/v1/client/domains/{domain}/whois-privacy-state' \
  -H "Authorization: Bearer $API_TOKEN" \
  -H 'Accept: application/json'

PHP

<?php

$ch = curl_init('https://portal.supporthost.com/api/v1/client/domains/{domain}/whois-privacy-state');
curl_setopt_array($ch, [
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_HTTPHEADER => [
        'Authorization: Bearer ' . getenv('API_TOKEN'),
        'Accept: application/json',
    ],
]);

$body   = json_decode(curl_exec($ch), true);
$status = curl_getinfo($ch, CURLINFO_RESPONSE_CODE);

if ($status >= 400) {
    // Error envelope: {"error": {"code": "...", "message": "...", "fields": {...}}}
    echo $status . ' ' . ($body['error']['code'] ?? '') . ': ' . ($body['error']['message'] ?? '') . "\n";
} else {
    print_r($body);
}

Node.js

const response = await fetch('https://portal.supporthost.com/api/v1/client/domains/{domain}/whois-privacy-state', {
  headers: {
    Authorization: `Bearer ${process.env.API_TOKEN}`,
    Accept: 'application/json',
  },
});

console.log(await response.json());

Response

200

{
  "data": {
    "subscribed": true,
    "registrarEnabled": true,
    "optionPricing": "free",
    "supported": [
      "enable_whois_privacy",
      "disable_whois_privacy"
    ]
  }
}

Error responses share one format: see Errors.

Turn auto-renew on or off #

POST /client/domains/{domain}/auto-renew

With auto-renew on, the domain is renewed automatically before it expires. Turning it off also removes the domain from an open renewal invoice, if it had one. It cannot be turned off on a domain included with a hosting service: that domain renews with the service.

Parameters

Path

  • domain integer required
    The domain ID

Body application/json required

  • value string required
    1 to turn auto-renew on, 0 to turn it off.
    Allowed values 0 1

Responses

  • 200
    Response body application/json
    • data object
      1 property
      • auto_renew boolean
  • 401 unauthenticated ApiError
  • 403 client_token_required token_not_api_enabled token_not_client_scoped client_access_revoked client_cancelled ip_not_allowed ip_whitelist_misconfigured forbidden domain_not_active ApiError
  • 404 client_not_found not_found ApiError
  • 422 invalid_request unprocessable ApiError
  • 429 rate_limited ApiError

cURL

curl -X POST 'https://portal.supporthost.com/api/v1/client/domains/{domain}/auto-renew' \
  -H "Authorization: Bearer $API_TOKEN" \
  -H 'Accept: application/json' \
  -H 'Content-Type: application/json' \
  -d '{
  "value": "0"
}'

PHP

<?php

$ch = curl_init('https://portal.supporthost.com/api/v1/client/domains/{domain}/auto-renew');
curl_setopt_array($ch, [
    CURLOPT_CUSTOMREQUEST => 'POST',
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_HTTPHEADER => [
        'Authorization: Bearer ' . getenv('API_TOKEN'),
        'Accept: application/json',
        'Content-Type: application/json',
    ],
    CURLOPT_POSTFIELDS => json_encode([
        'value' => '0',
    ]),
]);

$body   = json_decode(curl_exec($ch), true);
$status = curl_getinfo($ch, CURLINFO_RESPONSE_CODE);

if ($status >= 400) {
    // Error envelope: {"error": {"code": "...", "message": "...", "fields": {...}}}
    echo $status . ' ' . ($body['error']['code'] ?? '') . ': ' . ($body['error']['message'] ?? '') . "\n";
} else {
    print_r($body);
}

Node.js

const response = await fetch('https://portal.supporthost.com/api/v1/client/domains/{domain}/auto-renew', {
  method: 'POST',
  headers: {
    Authorization: `Bearer ${process.env.API_TOKEN}`,
    Accept: 'application/json',
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
    "value": "0"
  }),
});

console.log(await response.json());

Response

200

{
  "data": {
    "auto_renew": false
  }
}

Error responses share one format: see Errors.

Enable the transfer lock #

POST /client/domains/{domain}/lock

Turns on the registry transfer lock, which blocks transfers of the domain to another registrar. Free of charge. completed: false means the registry applies it later.

Parameters

Path

  • domain integer required
    The domain ID

Responses

  • 200
    Response body application/json
    • data object
      2 properties
      • completed boolean
      • message string
  • 401 unauthenticated ApiError
  • 403 client_token_required token_not_api_enabled token_not_client_scoped client_access_revoked client_cancelled ip_not_allowed ip_whitelist_misconfigured forbidden domain_not_active ApiError
  • 404 client_not_found not_found ApiError
  • 422 invalid_request unprocessable ApiError
  • 429 rate_limited ApiError

cURL

curl -X POST 'https://portal.supporthost.com/api/v1/client/domains/{domain}/lock' \
  -H "Authorization: Bearer $API_TOKEN" \
  -H 'Accept: application/json'

PHP

<?php

$ch = curl_init('https://portal.supporthost.com/api/v1/client/domains/{domain}/lock');
curl_setopt_array($ch, [
    CURLOPT_CUSTOMREQUEST => 'POST',
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_HTTPHEADER => [
        'Authorization: Bearer ' . getenv('API_TOKEN'),
        'Accept: application/json',
    ],
]);

$body   = json_decode(curl_exec($ch), true);
$status = curl_getinfo($ch, CURLINFO_RESPONSE_CODE);

if ($status >= 400) {
    // Error envelope: {"error": {"code": "...", "message": "...", "fields": {...}}}
    echo $status . ' ' . ($body['error']['code'] ?? '') . ': ' . ($body['error']['message'] ?? '') . "\n";
} else {
    print_r($body);
}

Node.js

const response = await fetch('https://portal.supporthost.com/api/v1/client/domains/{domain}/lock', {
  method: 'POST',
  headers: {
    Authorization: `Bearer ${process.env.API_TOKEN}`,
    Accept: 'application/json',
  },
});

console.log(await response.json());

Response

200

{
  "data": {
    "completed": true,
    "message": "Transfer lock enabled."
  }
}

Error responses share one format: see Errors.

Disable the transfer lock #

POST /client/domains/{domain}/unlock

Turns off the registry transfer lock so the domain can be transferred away. Free of charge. completed: false means the registry applies it later.

Parameters

Path

  • domain integer required
    The domain ID

Responses

  • 200
    Response body application/json
    • data object
      2 properties
      • completed boolean
      • message string
  • 401 unauthenticated ApiError
  • 403 client_token_required token_not_api_enabled token_not_client_scoped client_access_revoked client_cancelled ip_not_allowed ip_whitelist_misconfigured forbidden domain_not_active ApiError
  • 404 client_not_found not_found ApiError
  • 422 invalid_request unprocessable ApiError
  • 429 rate_limited ApiError

cURL

curl -X POST 'https://portal.supporthost.com/api/v1/client/domains/{domain}/unlock' \
  -H "Authorization: Bearer $API_TOKEN" \
  -H 'Accept: application/json'

PHP

<?php

$ch = curl_init('https://portal.supporthost.com/api/v1/client/domains/{domain}/unlock');
curl_setopt_array($ch, [
    CURLOPT_CUSTOMREQUEST => 'POST',
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_HTTPHEADER => [
        'Authorization: Bearer ' . getenv('API_TOKEN'),
        'Accept: application/json',
    ],
]);

$body   = json_decode(curl_exec($ch), true);
$status = curl_getinfo($ch, CURLINFO_RESPONSE_CODE);

if ($status >= 400) {
    // Error envelope: {"error": {"code": "...", "message": "...", "fields": {...}}}
    echo $status . ' ' . ($body['error']['code'] ?? '') . ': ' . ($body['error']['message'] ?? '') . "\n";
} else {
    print_r($body);
}

Node.js

const response = await fetch('https://portal.supporthost.com/api/v1/client/domains/{domain}/unlock', {
  method: 'POST',
  headers: {
    Authorization: `Bearer ${process.env.API_TOKEN}`,
    Accept: 'application/json',
  },
});

console.log(await response.json());

Response

200

{
  "data": {
    "completed": true,
    "message": "Transfer lock disabled."
  }
}

Error responses share one format: see Errors.

Get the EPP code #

POST /client/domains/{domain}/epp

Retrieves the transfer authorisation (EPP) code. Depending on the registry the code is returned in code (delivered_via: screen) or emailed to the registrant (delivered_via: email, code: null).

A POST because it has side effects: some registries generate a new code on every request.

Parameters

Path

  • domain integer required
    The domain ID

Responses

  • 200
    Response body application/json
    • data object
      3 properties
      • delivered_via string
      • code string | null
      • message string | null
  • 401 unauthenticated ApiError
  • 403 client_token_required token_not_api_enabled token_not_client_scoped client_access_revoked client_cancelled ip_not_allowed ip_whitelist_misconfigured forbidden domain_not_active ApiError
  • 404 client_not_found not_found ApiError
  • 422 invalid_request unprocessable ApiError
  • 429 rate_limited ApiError

cURL

curl -X POST 'https://portal.supporthost.com/api/v1/client/domains/{domain}/epp' \
  -H "Authorization: Bearer $API_TOKEN" \
  -H 'Accept: application/json'

PHP

<?php

$ch = curl_init('https://portal.supporthost.com/api/v1/client/domains/{domain}/epp');
curl_setopt_array($ch, [
    CURLOPT_CUSTOMREQUEST => 'POST',
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_HTTPHEADER => [
        'Authorization: Bearer ' . getenv('API_TOKEN'),
        'Accept: application/json',
    ],
]);

$body   = json_decode(curl_exec($ch), true);
$status = curl_getinfo($ch, CURLINFO_RESPONSE_CODE);

if ($status >= 400) {
    // Error envelope: {"error": {"code": "...", "message": "...", "fields": {...}}}
    echo $status . ' ' . ($body['error']['code'] ?? '') . ': ' . ($body['error']['message'] ?? '') . "\n";
} else {
    print_r($body);
}

Node.js

const response = await fetch('https://portal.supporthost.com/api/v1/client/domains/{domain}/epp', {
  method: 'POST',
  headers: {
    Authorization: `Bearer ${process.env.API_TOKEN}`,
    Accept: 'application/json',
  },
});

console.log(await response.json());

Response

200

{
  "data": {
    "delivered_via": "screen",
    "code": "EXAMPLE-EPP-7Hq2",
    "message": "Give this code to the new registrar to authorise the transfer."
  }
}

Error responses share one format: see Errors.

Release the domain to another registrar #

POST /client/domains/{domain}/release

Hands the domain over to another registrar, identified by its tag. Some registries move a domain this way instead of with a transfer code: .uk domains (including .co.uk, .org.uk and the other .uk extensions) leave by a tag change, often called the IPS tag. Ask the receiving registrar for its tag and send it as tag; letters, digits and hyphens, case is ignored.

Only for a domain whose status is active: any other status answers 403 domain_not_active. A domain whose registry does not release by tag answers 422 domain_release_not_supported: use the EPP code (POST /client/domains/{domain}/epp) to transfer it instead.

Irreversible from our side: once the receiving registrar has the domain, it is no longer managed from this account and cannot be taken back from here. Check the tag before sending it.

  • Authentication: bearer Token
  • Requires permission managedomains
  • Rate limit: 10 req/min per user

Parameters

Path

  • domain integer required
    The domain ID

Body application/json required

  • tag string required
    The tag of the registrar receiving the domain, as that registrar gives it to you: letters, digits and hyphens, up to 32 characters. Case is ignored. The release is irreversible from our side, so check it before sending.
    • Pattern ^[A-Za-z0-9\-]+$
    • Max length 32

Responses

  • 200
    Response body application/json
    • data object
      2 properties
      • completed boolean
      • message string
  • 401 unauthenticated ApiError
  • 403 client_token_required token_not_api_enabled token_not_client_scoped client_access_revoked client_cancelled ip_not_allowed ip_whitelist_misconfigured forbidden domain_not_active ApiError
  • 404 client_not_found not_found ApiError
  • 422 domain_release_not_supported registrar_error invalid_request unprocessable ApiError
  • 429 rate_limited ApiError

cURL

curl -X POST 'https://portal.supporthost.com/api/v1/client/domains/{domain}/release' \
  -H "Authorization: Bearer $API_TOKEN" \
  -H 'Accept: application/json' \
  -H 'Content-Type: application/json' \
  -d '{
  "tag": "EXAMPLE-REGISTRAR"
}'

PHP

<?php

$ch = curl_init('https://portal.supporthost.com/api/v1/client/domains/{domain}/release');
curl_setopt_array($ch, [
    CURLOPT_CUSTOMREQUEST => 'POST',
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_HTTPHEADER => [
        'Authorization: Bearer ' . getenv('API_TOKEN'),
        'Accept: application/json',
        'Content-Type: application/json',
    ],
    CURLOPT_POSTFIELDS => json_encode([
        'tag' => 'EXAMPLE-REGISTRAR',
    ]),
]);

$body   = json_decode(curl_exec($ch), true);
$status = curl_getinfo($ch, CURLINFO_RESPONSE_CODE);

if ($status >= 400) {
    // Error envelope: {"error": {"code": "...", "message": "...", "fields": {...}}}
    echo $status . ' ' . ($body['error']['code'] ?? '') . ': ' . ($body['error']['message'] ?? '') . "\n";
} else {
    print_r($body);
}

Node.js

const response = await fetch('https://portal.supporthost.com/api/v1/client/domains/{domain}/release', {
  method: 'POST',
  headers: {
    Authorization: `Bearer ${process.env.API_TOKEN}`,
    Accept: 'application/json',
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
    "tag": "EXAMPLE-REGISTRAR"
  }),
});

console.log(await response.json());

Response

200

{
  "data": {
    "completed": true,
    "message": "Your domain has been released to the receiving registrar."
  }
}

Error responses share one format: see Errors.

Enable WHOIS privacy #

POST /client/domains/{domain}/whois-privacy/enable

Hides the owner’s details from public WHOIS. When the service is free it is enabled at once (enabled: true). When it is paid, an invoice is issued and returned (enabled: false, invoice_id, invoice): privacy is enabled once that invoice is paid.

Parameters

Path

  • domain integer required
    The domain ID

Responses

  • 200
    Response body application/json
    • data object
      3 properties
      • enabled boolean
      • invoice_id integer | null
      • invoice object | null
        47 properties
        • id integer
        • client_id integer
        • client object
          4 properties
          • id integer
          • firstname string
          • lastname string
          • company string | null
        • type string
        • related_invoice_id integer | null
        • related_invoice object
          3 properties
          • id integer | null
          • invoice_number string | null
          • display_number string | null
        • invoice_number string | null
        • display_number string
        • status string
        • currency_code string
        • exchange_rate string
        • gateway_id integer | null
        • client_name string | null
        • client_company string | null
        • client_email string | null
        • client_address string | null
        • client_city string | null
        • client_state string | null
        • client_country string | null
        • client_postcode string | null
        • client_vat_number string | null
        • client_tax_exempt boolean
        • client_custom_fields

          Any of

          Option 1 object
          Option 2 map of any
        • business_name string | null
        • business_address string | null
        • business_vat_number string | null
        • subtotal string | number
        • tax1_name string | null
        • tax1_rate string | number
        • tax1_amount string | number
        • tax2_name string | null
        • tax2_rate string | number
        • tax2_amount string | number
        • tax_override boolean
        • total string | number
        • credit_applied string | number
        • balance string | number
        • date string | null
        • due_date string | null
        • paid_date string | null
        • items array of object
          12 properties
          • id integer
          • invoice_id integer
          • description string
          • qty string
          • unit_price string
          • taxable boolean
          • amount string
          • source_type string | null
          • source_id integer | null
          • sort_order integer
          • created_at string
          • updated_at string
        • transactions array of object
          16 properties
          • id integer
          • client_id integer
          • client object
            4 properties
            • id integer
            • firstname string
            • lastname string
            • company string | null
          • invoice_id integer | null
          • related_transaction_id integer | null
          • related_transaction object
            4 properties
            • id integer | null
            • amount string | null
            • type string | null
            • date string | null
          • amount string
          • currency_code string
          • gateway string | null
          • transaction_id string | null
          • exchange_rate string
          • type string
          • description string | null
          • date string
          • created_at string
          • updated_at string
        • collection_held_at string | null
        • collection_hold_reason string | null
        • extensions string
        • created_at string
        • updated_at string
  • 401 unauthenticated ApiError
  • 403 client_token_required token_not_api_enabled token_not_client_scoped client_access_revoked client_cancelled ip_not_allowed ip_whitelist_misconfigured forbidden domain_not_active ApiError
  • 404 client_not_found not_found ApiError
  • 422 invalid_request unprocessable ApiError
  • 429 rate_limited ApiError

cURL

curl -X POST 'https://portal.supporthost.com/api/v1/client/domains/{domain}/whois-privacy/enable' \
  -H "Authorization: Bearer $API_TOKEN" \
  -H 'Accept: application/json'

PHP

<?php

$ch = curl_init('https://portal.supporthost.com/api/v1/client/domains/{domain}/whois-privacy/enable');
curl_setopt_array($ch, [
    CURLOPT_CUSTOMREQUEST => 'POST',
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_HTTPHEADER => [
        'Authorization: Bearer ' . getenv('API_TOKEN'),
        'Accept: application/json',
    ],
]);

$body   = json_decode(curl_exec($ch), true);
$status = curl_getinfo($ch, CURLINFO_RESPONSE_CODE);

if ($status >= 400) {
    // Error envelope: {"error": {"code": "...", "message": "...", "fields": {...}}}
    echo $status . ' ' . ($body['error']['code'] ?? '') . ': ' . ($body['error']['message'] ?? '') . "\n";
} else {
    print_r($body);
}

Node.js

const response = await fetch('https://portal.supporthost.com/api/v1/client/domains/{domain}/whois-privacy/enable', {
  method: 'POST',
  headers: {
    Authorization: `Bearer ${process.env.API_TOKEN}`,
    Accept: 'application/json',
  },
});

console.log(await response.json());

Response

200

{
  "data": {
    "enabled": false,
    "invoice_id": 20871,
    "invoice": {
      "id": 20871,
      "client_id": 318,
      "client": {
        "id": 318,
        "firstname": "Mario",
        "lastname": "Rossi",
        "company": "Example Srl"
      },
      "type": "invoice",
      "related_invoice_id": 20790,
      "related_invoice": {
        "id": 20790,
        "invoice_number": "1498",
        "display_number": "1498"
      },
      "invoice_number": "1532",
      "display_number": "1532",
      "status": "unpaid",
      "currency_code": "EUR",
      "exchange_rate": "1.00000",
      "gateway_id": 1,
      "client_name": "Mario Rossi",
      "client_company": "Example Srl",
      "client_email": "mario.rossi@example.com",
      "client_address": "Via Roma 1",
      "client_city": "Milano",
      "client_state": "MI",
      "client_country": "IT",
      "client_postcode": "20121",
      "client_vat_number": "IT01234567890",
      "client_tax_exempt": false,
      "client_custom_fields": {
        "fiscal_code": "RSSMRA80A01F205X"
      },
      "business_name": "Example Hosting Srl",
      "business_address": "Via Milano 10, 20121 Milano, Italy",
      "business_vat_number": "IT09876543210",
      "subtotal": "4.90",
      "tax1_name": "VAT",
      "tax1_rate": "22.000",
      "tax1_amount": "1.08",
      "tax2_name": null,
      "tax2_rate": "0.000",
      "tax2_amount": "0.00",
      "tax_override": false,
      "total": "5.98",
      "credit_applied": "0.00",
      "balance": "5.98",
      "date": "2026-09-27T00:00:00+02:00",
      "due_date": "2026-10-04T00:00:00+02:00",
      "paid_date": null,
      "items": [
        {
          "id": 48213,
          "invoice_id": 20871,
          "description": "WHOIS privacy - example.com",
          "qty": "1.00",
          "unit_price": "4.90",
          "taxable": true,
          "amount": "4.90",
          "source_type": "domain_option",
          "source_id": 1042,
          "sort_order": 0,
          "created_at": "2026-09-27T10:15:32+02:00",
          "updated_at": "2026-09-27T10:15:32+02:00"
        }
      ],
      "transactions": [
        {
          "id": 7730,
          "client_id": 318,
          "client": {
            "id": 318,
            "firstname": "Mario",
            "lastname": "Rossi",
            "company": "Example Srl"
          },
          "invoice_id": 20871,
          "related_transaction_id": 7729,
          "related_transaction": {
            "id": 7729,
            "amount": "5.98",
            "type": "payment",
            "date": "2026-09-20T09:12:31+02:00"
          },
          "amount": "5.98",
          "currency_code": "EUR",
          "gateway": "bank_transfer",
          "transaction_id": "TRX-20260927-0042",
          "exchange_rate": "1.00000",
          "type": "payment",
          "description": "Payment of invoice 1532",
          "date": "2026-09-27T11:02:44+02:00",
          "created_at": "2026-09-27T11:02:44+02:00",
          "updated_at": "2026-09-27T11:02:44+02:00"
        }
      ],
      "collection_held_at": null,
      "collection_hold_reason": null,
      "extensions": [],
      "created_at": "2026-09-27T10:15:32+02:00",
      "updated_at": "2026-09-27T10:15:32+02:00"
    }
  }
}

Error responses share one format: see Errors.

Disable WHOIS privacy #

POST /client/domains/{domain}/whois-privacy/disable

Shows the owner’s details in public WHOIS again, where the registry allows it.

Parameters

Path

  • domain integer required
    The domain ID

Responses

  • 200
    Response body application/json
    • data object
      1 property
      • enabled boolean
  • 401 unauthenticated ApiError
  • 403 client_token_required token_not_api_enabled token_not_client_scoped client_access_revoked client_cancelled ip_not_allowed ip_whitelist_misconfigured forbidden domain_not_active ApiError
  • 404 client_not_found not_found ApiError
  • 422 invalid_request unprocessable ApiError
  • 429 rate_limited ApiError

cURL

curl -X POST 'https://portal.supporthost.com/api/v1/client/domains/{domain}/whois-privacy/disable' \
  -H "Authorization: Bearer $API_TOKEN" \
  -H 'Accept: application/json'

PHP

<?php

$ch = curl_init('https://portal.supporthost.com/api/v1/client/domains/{domain}/whois-privacy/disable');
curl_setopt_array($ch, [
    CURLOPT_CUSTOMREQUEST => 'POST',
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_HTTPHEADER => [
        'Authorization: Bearer ' . getenv('API_TOKEN'),
        'Accept: application/json',
    ],
]);

$body   = json_decode(curl_exec($ch), true);
$status = curl_getinfo($ch, CURLINFO_RESPONSE_CODE);

if ($status >= 400) {
    // Error envelope: {"error": {"code": "...", "message": "...", "fields": {...}}}
    echo $status . ' ' . ($body['error']['code'] ?? '') . ': ' . ($body['error']['message'] ?? '') . "\n";
} else {
    print_r($body);
}

Node.js

const response = await fetch('https://portal.supporthost.com/api/v1/client/domains/{domain}/whois-privacy/disable', {
  method: 'POST',
  headers: {
    Authorization: `Bearer ${process.env.API_TOKEN}`,
    Accept: 'application/json',
  },
});

console.log(await response.json());

Response

200

{
  "data": {
    "enabled": false
  }
}

Error responses share one format: see Errors.