SupportHost italian

Domains

Register, transfer, renew and restore domains, paid from the account credit, and read a domain’s state by name.

Every money-moving call accepts an Idempotency-Key header: a retry with the same key returns the original response (with Idempotent-Replayed: true) and never charges twice.

Get a domain by name #

GET /reseller/domains/{name}

Returns the current state of one of your domains: status, dates, auto-renew and whether a transfer is pending or failed. The id in the response is the one the Domain management calls are addressed by.

Use it to poll an operation that answered 202. It reads the state stored on this server and never contacts the registry, so it is cheap to call.

Parameters

Path

  • name string required

Responses

  • 200

    The domain.

    Response body application/json
    • data object
      8 properties
      • id integer
      • name string
      • status string
        Allowed values pending pending_registration pending_transfer active expired grace redemption pending_delete transferring_away transferred_away transfer_failed cancelled fraud
      • registration_date string | null
      • expiration_date string | null
      • next_due_date string | null
      • auto_renew boolean
      • transfer object
        2 properties
        • pending boolean
        • failed 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 not_reseller credit_disabled ApiError
  • 404 client_not_found not_found ApiError
  • 429 rate_limited ApiError

cURL

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

PHP

<?php

$ch = curl_init('https://portal.supporthost.com/api/v1/reseller/domains/{name}');
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/reseller/domains/{name}', {
  headers: {
    Authorization: `Bearer ${process.env.API_TOKEN}`,
    Accept: 'application/json',
  },
});

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

Response

200

{
  "data": {
    "id": 1042,
    "name": "example.com",
    "status": "active",
    "registration_date": "2026-09-15",
    "expiration_date": "2027-09-15",
    "next_due_date": "2027-09-15",
    "auto_renew": false,
    "transfer": {
      "pending": false,
      "failed": false
    }
  }
}

Error responses share one format: see Errors.

Get the contacts of a domain #

GET /reseller/domains/{name}/contacts

Every contact the domain uses at its registry, keyed by role. Which roles exist depends on the registry: required_types lists them (registrant always; admin, tech, billing where the registry uses them), and contacts carries exactly those.

Read live from the registry (source: "live"). A registry this server cannot read contacts back from answers what was stored at registration (source: "stored"): the registrant, the other roles empty.

extra_fields are the registrant’s registry-specific fields. For an EXISTING domain this is the authoritative set: the keys the contacts update validates against, which can differ from GET /reseller/tlds/{tld}/extra-fields — that one describes what a NEW registration of the extension needs with its default registry connection.

read_only names the roles the registry does not let you edit on this domain, with the reason (for example, an .it natural person’s admin contact is the registrant). A read-only registrant is still sent to the registry by the update, which then answers with the procedure it needs.

Parameters

Path

  • name string required

Responses

  • 200

    The contacts.

    Response body application/json
    • data object
      5 properties
      • required_types array of string
        The roles the domain uses at its registry, in the order a form shows them. registrant is always there; admin, tech and billing depend on the registry (an .eu domain has the registrant only, an .it one registrant, admin and tech).
      • contacts map of map of string
        One contact per role of required_types: first_name, last_name, organization, street1, street2, city, state_province, postal_code, country_code, phone (+CC.NUMBER), email, empty strings when unset. A role the registry has no contact for yet is {}.
      • extra_fields map of string
        Every registry-specific field of the registrant, with its current value ("" when none is on file): the keys the contacts update validates against for THIS domain. Authoritative for an existing domain; GET /reseller/tlds/{tld}/extra-fields describes what a new registration of the extension needs and can differ.
      • read_only map of string
        Roles the registry does not let you edit on this domain, role => reason (e.g. the admin contact of an .it natural person, which must be the registrant). Sending such a role with different data answers 422 invalid_contact. Empty object when every role is editable.
      • source string
        live: read from the registry now. stored: this domain’s registry cannot be read back, so the contacts are what was stored at registration (the registrant only).
        Allowed values live stored
  • 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 not_reseller credit_disabled ApiError
  • 404 client_not_found not_found ApiError
  • 429 rate_limited ApiError
  • 503 contacts_unavailable ApiError

cURL

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

PHP

<?php

$ch = curl_init('https://portal.supporthost.com/api/v1/reseller/domains/{name}/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/reseller/domains/{name}/contacts', {
  headers: {
    Authorization: `Bearer ${process.env.API_TOKEN}`,
    Accept: 'application/json',
  },
});

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

Response

200

{
  "data": {
    "required_types": [
      "registrant",
      "admin",
      "tech"
    ],
    "contacts": {
      "registrant": {
        "street2": "",
        "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"
      },
      "admin": {
        "first_name": "Laura",
        "last_name": "Bianchi",
        "organization": "Example Srl",
        "email": "hostmaster@example.com",
        "phone": "+39.0212345679",
        "street1": "Via Roma 1",
        "street2": "",
        "city": "Milano",
        "state_province": "MI",
        "postal_code": "20121",
        "country_code": "IT"
      },
      "tech": {
        "first_name": "Laura",
        "last_name": "Bianchi",
        "organization": "Example Srl",
        "email": "hostmaster@example.com",
        "phone": "+39.0212345679",
        "street1": "Via Roma 1",
        "street2": "",
        "city": "Milano",
        "state_province": "MI",
        "postal_code": "20121",
        "country_code": "IT"
      }
    },
    "extra_fields": {
      "entity_type": "2",
      "partita_iva": "01234567890",
      "consent_publishing": "1",
      "accept_terms": "1"
    },
    "read_only": [],
    "source": "live"
  }
}

Error responses share one format: see Errors.

Update the contacts of a domain #

PUT /reseller/domains/{name}/contacts

Changes the roles you send, each as a full contact (the registrant shape of POST /reseller/domains/register); roles you leave out stay as they are. extra_fields (and source) belong to the registrant and are accepted only with contacts.registrant; registry fields you do not send keep the value on file. Free of charge.

Every role is validated before anything is written: a failure is invalid_contact with fields keyed per role (contacts.admin.email, extra_fields.codice_fiscale). A role you send whose content equals the registry’s is not re-sent (unchanged).

Roles are applied one at a time — admin, tech, billing, then the registrant — and the run stops at the first failure. results reports each role sent: updated, pending (accepted, applied later: a registrant confirming by email, say), unchanged, failed or not_attempted. On a failure the error carries the same results, so you know which roles were already applied.

A registrant change the registry accepts only through a change-of-holder procedure is refused with registrant_change_requires_trade (or registrant_change_requires_postal_procedure): nothing is sent for the registrant and nothing is charged.

200 with state: "completed" when every role sent is done; 202 with state: "pending" when at least one is waiting on the registry.

Parameters

Path

  • name string required

Body application/json required

  • contacts object required
    The roles to change, keyed registrant, admin, tech, billing. Send only roles the domain uses (required_types of GET /reseller/domains/{name}/contacts); any other key answers 422 invalid_contact naming contacts.<role>. Roles you leave out stay as they are.
    4 properties
    • registrant object
      The owner contact, as a full contact (the registrant of POST /reseller/domains/register).
      11 properties
      • first_name string required
        • Max length 100
      • last_name string required
        • Max length 100
      • organization string | null
        Company name. Some TLDs require it and some refuse it: either case answers 422 invalid_contact.
        • 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 registrant.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
        Allowed values AF AL DZ AD AO AI AQ AG SA AR
        240 more values AM AW AU AT AZ BS BH BD BB BE BZ BJ BM BT BY BO BA BW BR BN BG BF BI KH CM CA CV BQ CZ TD CL CN CY VA CO KM CD CG KP KR CR CI HR CU CW DK DM EC EG SV AE ER EE SZ ET FJ PH FI FR GA GM GE GS DE GH JM JP GI DJ JO GR GD GL GP GU GT GG GN GQ GW GY GF HT HN IN ID IR IQ IE IS BV CX NF IM KY CC CK FK FO HM MP MH UM PN SB TC VI VG AX IL IT JE KZ KE KG KI XK KW LA LS LV LB LR LY LI LT LU MK MG MW MY MV ML MT MA MQ MR MU YT MX FM MD MC MN ME MS MZ MM NA NR NP NI NE NG NU NO NC NZ OM NL PK PW PA PG PY PE PF PL PT PR QA HK MO GB CF DO RE RO RW RU EH KN LC MF VC BL PM WS AS SM SH SN RS SC SL SG SX SY SK SI SO ES LK US SS ZA SD SR SJ SE CH ST TJ TW TZ TF PS IO TH TL TG TK TO TT TN TR TM TV UA UG HU UY UZ VU VE VN WF YE ZM ZW
    • admin object
      The administrative contact, as a full contact (same fields as the registrant). Organization is always optional here.
      11 properties
      • first_name string required
        • Max length 100
      • last_name string required
        • Max length 100
      • organization string | null
        • Max length 200
      • email string required
        • Format email
        • Max length 200
      • phone string required
        • 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
        • Min length 2
        • Max length 2
        Allowed values AF AL DZ AD AO AI AQ AG SA AR
        240 more values AM AW AU AT AZ BS BH BD BB BE BZ BJ BM BT BY BO BA BW BR BN BG BF BI KH CM CA CV BQ CZ TD CL CN CY VA CO KM CD CG KP KR CR CI HR CU CW DK DM EC EG SV AE ER EE SZ ET FJ PH FI FR GA GM GE GS DE GH JM JP GI DJ JO GR GD GL GP GU GT GG GN GQ GW GY GF HT HN IN ID IR IQ IE IS BV CX NF IM KY CC CK FK FO HM MP MH UM PN SB TC VI VG AX IL IT JE KZ KE KG KI XK KW LA LS LV LB LR LY LI LT LU MK MG MW MY MV ML MT MA MQ MR MU YT MX FM MD MC MN ME MS MZ MM NA NR NP NI NE NG NU NO NC NZ OM NL PK PW PA PG PY PE PF PL PT PR QA HK MO GB CF DO RE RO RW RU EH KN LC MF VC BL PM WS AS SM SH SN RS SC SL SG SX SY SK SI SO ES LK US SS ZA SD SR SJ SE CH ST TJ TW TZ TF PS IO TH TL TG TK TO TT TN TR TM TV UA UG HU UY UZ VU VE VN WF YE ZM ZW
    • tech object
      The technical contact, as a full contact.
      11 properties
      • first_name string required
        • Max length 100
      • last_name string required
        • Max length 100
      • organization string | null
        • Max length 200
      • email string required
        • Format email
        • Max length 200
      • phone string required
        • 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
        • Min length 2
        • Max length 2
        Allowed values AF AL DZ AD AO AI AQ AG SA AR
        240 more values AM AW AU AT AZ BS BH BD BB BE BZ BJ BM BT BY BO BA BW BR BN BG BF BI KH CM CA CV BQ CZ TD CL CN CY VA CO KM CD CG KP KR CR CI HR CU CW DK DM EC EG SV AE ER EE SZ ET FJ PH FI FR GA GM GE GS DE GH JM JP GI DJ JO GR GD GL GP GU GT GG GN GQ GW GY GF HT HN IN ID IR IQ IE IS BV CX NF IM KY CC CK FK FO HM MP MH UM PN SB TC VI VG AX IL IT JE KZ KE KG KI XK KW LA LS LV LB LR LY LI LT LU MK MG MW MY MV ML MT MA MQ MR MU YT MX FM MD MC MN ME MS MZ MM NA NR NP NI NE NG NU NO NC NZ OM NL PK PW PA PG PY PE PF PL PT PR QA HK MO GB CF DO RE RO RW RU EH KN LC MF VC BL PM WS AS SM SH SN RS SC SL SG SX SY SK SI SO ES LK US SS ZA SD SR SJ SE CH ST TJ TW TZ TF PS IO TH TL TG TK TO TT TN TR TM TV UA UG HU UY UZ VU VE VN WF YE ZM ZW
    • billing object
      The billing contact, as a full contact.
      11 properties
      • first_name string required
        • Max length 100
      • last_name string required
        • Max length 100
      • organization string | null
        • Max length 200
      • email string required
        • Format email
        • Max length 200
      • phone string required
        • 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
        • Min length 2
        • Max length 2
        Allowed values AF AL DZ AD AO AI AQ AG SA AR
        240 more values AM AW AU AT AZ BS BH BD BB BE BZ BJ BM BT BY BO BA BW BR BN BG BF BI KH CM CA CV BQ CZ TD CL CN CY VA CO KM CD CG KP KR CR CI HR CU CW DK DM EC EG SV AE ER EE SZ ET FJ PH FI FR GA GM GE GS DE GH JM JP GI DJ JO GR GD GL GP GU GT GG GN GQ GW GY GF HT HN IN ID IR IQ IE IS BV CX NF IM KY CC CK FK FO HM MP MH UM PN SB TC VI VG AX IL IT JE KZ KE KG KI XK KW LA LS LV LB LR LY LI LT LU MK MG MW MY MV ML MT MA MQ MR MU YT MX FM MD MC MN ME MS MZ MM NA NR NP NI NE NG NU NO NC NZ OM NL PK PW PA PG PY PE PF PL PT PR QA HK MO GB CF DO RE RO RW RU EH KN LC MF VC BL PM WS AS SM SH SN RS SC SL SG SX SY SK SI SO ES LK US SS ZA SD SR SJ SE CH ST TJ TW TZ TF PS IO TH TL TG TK TO TT TN TR TM TV UA UG HU UY UZ VU VE VN WF YE ZM ZW
  • extra_fields map of string
    The registrant’s registry-specific fields: the keys GET /reseller/domains/{name}/contacts returns in extra_fields, which is the authoritative set for an existing domain (it can differ from GET /reseller/tlds/{tld}/extra-fields, which describes a new registration). Only together with contacts.registrant. Fields you do not send keep the value on file. Values are strings: send a checkbox as "1". A missing or invalid field answers 422 invalid_contact naming extra_fields.<key>.
  • source object
    Optional, only together with contacts.registrant. The additional domain fields of your own platform, for this server to translate into extra_fields (see POST /reseller/domains/register).
    5 properties
    • platform string
      Your platform, lower case: whmcs, hostbill.
      • Pattern ^[a-z][a-z0-9-]*$
      • Max length 32
    • version string | null
      Your platform’s own version, e.g. 8.13.1: field names differ between versions.
      • Max length 50
    • module_version string | null
      Version of the registrar module sending the request.
      • Max length 50
    • fields map of string
      The platform’s additional fields, name => value, exactly as the platform holds them (e.g. "Legal Type": "Companies/one man companies"). At most 50, values up to 255 characters.
    • translated array of string
      The extra_fields keys your module translated itself from source.fields. This server’s own translation wins over them; keys not listed here are yours and win over it.
      • Max items 100
      • Max length 64

Responses

  • 200

    Every role sent is done.

    Response body application/json
    • data object
      3 properties
      • state string
        completed (200): every role sent is done. pending (202): at least one role was accepted by the registry but applies later — typically a registrant confirming the change by email.
        Allowed values completed pending
      • results map of string
        One entry per role sent, in the order they were applied: updated, pending, or unchanged (the registry already held exactly this data, so nothing was sent). The same map, with failed and not_attempted, rides on a contact_update_failed or registrant_change_requires_* error so you know which roles were already applied.
      • domain map of any
  • 202 Accepted — completes later

    Accepted; at least one role is waiting on the registry.

    Response body application/json
    • data object
      3 properties
      • state string
        completed (200): every role sent is done. pending (202): at least one role was accepted by the registry but applies later — typically a registrant confirming the change by email.
        Allowed values completed pending
      • results map of string
        One entry per role sent, in the order they were applied: updated, pending, or unchanged (the registry already held exactly this data, so nothing was sent). The same map, with failed and not_attempted, rides on a contact_update_failed or registrant_change_requires_* error so you know which roles were already applied.
      • domain map of any
  • 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 not_reseller credit_disabled domain_not_active ApiError
  • 404 client_not_found not_found ApiError
  • 409 registrant_change_requires_trade registrant_change_requires_postal_procedure ApiError
  • 422 invalid_request invalid_contact contact_update_failed contact_update_not_supported ApiError
  • 429 rate_limited ApiError
  • 503 contacts_unavailable ApiError

cURL

curl -X PUT 'https://portal.supporthost.com/api/v1/reseller/domains/{name}/contacts' \
  -H "Authorization: Bearer $API_TOKEN" \
  -H 'Accept: application/json' \
  -H 'Content-Type: application/json' \
  -d '{
  "contacts": {
    "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"
    },
    "admin": {
      "first_name": "Laura",
      "last_name": "Bianchi",
      "organization": "Example Srl",
      "email": "hostmaster@example.com",
      "phone": "+39.0212345679",
      "street1": "Via Roma 1",
      "street2": "",
      "city": "Milano",
      "state_province": "MI",
      "postal_code": "20121",
      "country_code": "IT"
    },
    "tech": {
      "first_name": "Laura",
      "last_name": "Bianchi",
      "organization": "Example Srl",
      "email": "hostmaster@example.com",
      "phone": "+39.0212345679",
      "street1": "Via Roma 1",
      "street2": "",
      "city": "Milano",
      "state_province": "MI",
      "postal_code": "20121",
      "country_code": "IT"
    }
  },
  "extra_fields": {
    "entity_type": "2",
    "partita_iva": "01234567890",
    "consent_publishing": "1",
    "accept_terms": "1"
  }
}'

PHP

<?php

$ch = curl_init('https://portal.supporthost.com/api/v1/reseller/domains/{name}/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([
        'contacts' => [
            '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',
            ],
            'admin' => [
                'first_name' => 'Laura',
                'last_name' => 'Bianchi',
                'organization' => 'Example Srl',
                'email' => 'hostmaster@example.com',
                'phone' => '+39.0212345679',
                'street1' => 'Via Roma 1',
                'street2' => '',
                'city' => 'Milano',
                'state_province' => 'MI',
                'postal_code' => '20121',
                'country_code' => 'IT',
            ],
            'tech' => [
                'first_name' => 'Laura',
                'last_name' => 'Bianchi',
                'organization' => 'Example Srl',
                'email' => 'hostmaster@example.com',
                'phone' => '+39.0212345679',
                'street1' => 'Via Roma 1',
                'street2' => '',
                'city' => 'Milano',
                'state_province' => 'MI',
                'postal_code' => '20121',
                'country_code' => 'IT',
            ],
        ],
        'extra_fields' => [
            'entity_type' => '2',
            'partita_iva' => '01234567890',
            'consent_publishing' => '1',
            'accept_terms' => '1',
        ],
    ]),
]);

$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/reseller/domains/{name}/contacts', {
  method: 'PUT',
  headers: {
    Authorization: `Bearer ${process.env.API_TOKEN}`,
    Accept: 'application/json',
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
    "contacts": {
      "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"
      },
      "admin": {
        "first_name": "Laura",
        "last_name": "Bianchi",
        "organization": "Example Srl",
        "email": "hostmaster@example.com",
        "phone": "+39.0212345679",
        "street1": "Via Roma 1",
        "street2": "",
        "city": "Milano",
        "state_province": "MI",
        "postal_code": "20121",
        "country_code": "IT"
      },
      "tech": {
        "first_name": "Laura",
        "last_name": "Bianchi",
        "organization": "Example Srl",
        "email": "hostmaster@example.com",
        "phone": "+39.0212345679",
        "street1": "Via Roma 1",
        "street2": "",
        "city": "Milano",
        "state_province": "MI",
        "postal_code": "20121",
        "country_code": "IT"
      }
    },
    "extra_fields": {
      "entity_type": "2",
      "partita_iva": "01234567890",
      "consent_publishing": "1",
      "accept_terms": "1"
    }
  }),
});

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

Response

200

{
  "data": {
    "state": "completed",
    "results": {
      "admin": "updated",
      "tech": "unchanged",
      "registrant": "updated"
    },
    "domain": {
      "id": 1042,
      "name": "example.com",
      "status": "active",
      "registration_date": "2026-09-15",
      "expiration_date": "2027-09-15",
      "next_due_date": "2027-09-15",
      "auto_renew": false,
      "transfer": {
        "pending": false,
        "failed": false
      }
    }
  }
}

202

{
  "data": {
    "state": "pending",
    "results": {
      "admin": "updated",
      "registrant": "pending"
    },
    "domain": {
      "id": 1042,
      "name": "example.com",
      "status": "active",
      "registration_date": "2026-09-15",
      "expiration_date": "2027-09-15",
      "next_due_date": "2027-09-15",
      "auto_renew": false,
      "transfer": {
        "pending": false,
        "failed": false
      }
    }
  }
}

Error responses share one format: see Errors.

Register a domain #

POST /reseller/domains/register

Registers an available name, paid from your credit at your net price. Check availability and price first with GET /reseller/domains/check.

  • years defaults to the TLD’s minimum term; GET /reseller/pricing lists the terms you can buy.
  • nameservers (2–5 host names) is optional: omitted, the default nameservers configured on this server are used.
  • registrant is the owner contact. The phone is +CC.NNNN (e.g. +39.0212345678), or a local number plus phone_country_code (ISO country, e.g. IT).
  • extra_fields is an object of string values for the registry-specific data some TLDs require (entity type, tax codes, language…). Which keys are required depends on the TLD and on this server’s configuration, and some are only required depending on another field’s answer. Send a checkbox as "1". Keys the TLD does not declare are ignored. A missing or invalid field answers 422 invalid_contact, whose fields map names every field to fix.
  • source is optional: your platform’s own additional fields, as your platform holds them, for this server to translate into extra_fields. A key you send in extra_fields wins over a translated one.

Side effects: the charge is taken from your credit before the registry is contacted, and refunded automatically if the registry refuses. On 424 registrar_unknown the registry did not confirm the outcome and the charge is NOT refunded while it is reconciled: do not retry with a new Idempotency-Key.

Parameters

Header

  • Idempotency-Key string
    Optional. 1–255 printable ASCII characters, scoped to your account. A retry with the same key and the same request returns the stored response byte for byte (with Idempotent-Replayed: true) and never charges twice. The same key with a different request answers 422 idempotency_key_reused; while the first request is still running, 409 idempotency_in_progress (retry after retry_after seconds). Keys are kept for 30 days. See Idempotency in the introduction.
    • Min length 1
    • Max length 255

    See Rate limits and idempotency.

Body application/json required

  • name string required
    The domain to register, e.g. example.com. A Unicode (IDN) name is accepted only on a TLD that supports it, and is converted to its ASCII form; otherwise 422 invalid_domain.
    • Max length 255
  • years integer
    Registration term. Defaults to the TLD’s minimum; must be one of the register terms GET /reseller/pricing lists for the TLD, otherwise 422 invalid_years (with allowed_years).
    • Minimum 1
  • nameservers array of string
    2 to 5 nameserver host names. Optional: when omitted, the default nameservers configured on this server are used.
    • Min items 2
    • Max items 5
    • Pattern ^[A-Za-z0-9.\-]+$
    • Max length 255
  • registrant object required
    The owner contact of the domain, the only contact these calls take. The registrar fills the other roles the TLD needs (admin, tech, billing) on its own: most copy the registrant, some use contacts of their own. Change any role afterwards with PUT /reseller/domains/{name}/contacts.
    11 properties
    • first_name string required
      • Max length 100
    • last_name string required
      • Max length 100
    • organization string | null
      Company name. Some TLDs require it and some refuse it: either case answers 422 invalid_contact.
      • 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 registrant.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. When the TLD lists registrant_countries in GET /reseller/pricing, it must be one of them, otherwise 422 invalid_contact before any credit is taken.
      • Min length 2
      • Max length 2
      Allowed values AF AL DZ AD AO AI AQ AG SA AR
      240 more values AM AW AU AT AZ BS BH BD BB BE BZ BJ BM BT BY BO BA BW BR BN BG BF BI KH CM CA CV BQ CZ TD CL CN CY VA CO KM CD CG KP KR CR CI HR CU CW DK DM EC EG SV AE ER EE SZ ET FJ PH FI FR GA GM GE GS DE GH JM JP GI DJ JO GR GD GL GP GU GT GG GN GQ GW GY GF HT HN IN ID IR IQ IE IS BV CX NF IM KY CC CK FK FO HM MP MH UM PN SB TC VI VG AX IL IT JE KZ KE KG KI XK KW LA LS LV LB LR LY LI LT LU MK MG MW MY MV ML MT MA MQ MR MU YT MX FM MD MC MN ME MS MZ MM NA NR NP NI NE NG NU NO NC NZ OM NL PK PW PA PG PY PE PF PL PT PR QA HK MO GB CF DO RE RO RW RU EH KN LC MF VC BL PM WS AS SM SH SN RS SC SL SG SX SY SK SI SO ES LK US SS ZA SD SR SJ SE CH ST TJ TW TZ TF PS IO TH TL TG TK TO TT TN TR TM TV UA UG HU UY UZ VU VE VN WF YE ZM ZW
  • extra_fields map of string
    Registry-specific data some TLDs require (e.g. entity type, tax codes, language). Which keys are required depends on the TLD and on this server’s configuration, and some are only required depending on the answer to another field. For a new registration or transfer, GET /reseller/tlds/{tld}/extra-fields lists them, with their conditions; for an existing domain, GET /reseller/domains/{name}/contacts returns the ones it uses. Values are strings: send a checkbox as "1". Keys the TLD does not declare are ignored. A missing or invalid field answers 422 invalid_contact with a fields map naming each field to fix.
  • source object
    Optional. The additional domain fields of your own platform, sent as your platform holds them, for this server to translate into extra_fields. A registrar module generated by this server fills it in: you do not need it when you send extra_fields yourself. A key you send in extra_fields always wins over a translated one.
    5 properties
    • platform string
      Your platform, lower case: whmcs, hostbill.
      • Pattern ^[a-z][a-z0-9-]*$
      • Max length 32
    • version string | null
      Your platform’s own version, e.g. 8.13.1: field names differ between versions.
      • Max length 50
    • module_version string | null
      Version of the registrar module sending the request.
      • Max length 50
    • fields map of string
      The platform’s additional fields, name => value, exactly as the platform holds them (e.g. "Legal Type": "Companies/one man companies"). At most 50, values up to 255 characters.
    • translated array of string
      The extra_fields keys your module translated itself from source.fields. This server’s own translation wins over them; keys not listed here are yours and win over it.
      • Max items 100
      • Max length 64

Responses

  • 200

    Registered.

    Idempotent-Replayed string response header
    true when this response is the replay of an earlier request with the same Idempotency-Key.
    Response body application/json
    • data object
      3 properties
      • state string
        • Value completed
      • domain object
        8 properties
        • id integer
        • name string
        • status string
          Allowed values pending pending_registration pending_transfer active expired grace redemption pending_delete transferring_away transferred_away transfer_failed cancelled fraud
        • registration_date string | null
        • expiration_date string | null
        • next_due_date string | null
        • auto_renew boolean
        • transfer object
          2 properties
          • pending boolean
          • failed boolean
      • charges array of object
        8 properties
        • id integer
        • action string
          Allowed values register transfer renew restore grace_fee redemption_fee
        • years integer
        • currency string
        • net number
        • tax number
        • gross number
        • status string
          Allowed values pending billable invoiced refunded
  • 202 Accepted — completes later

    Accepted but not completed yet: the registry has taken the request and will finish it later. Your credit has already been debited; the charges stay pending until the operation completes (then they are billed on your next monthly invoice) and are refunded automatically if it fails. Poll GET /reseller/domains/{name} until status leaves pending_registration / pending_transfer (a failed transfer shows transfer.failed: true).

    Idempotent-Replayed string response header
    true when this response is the replay of an earlier request with the same Idempotency-Key.
    Response body application/json
    • data object
      3 properties
      • state string
        • Value pending
      • domain object
        8 properties
        • id integer
        • name string
        • status string
          Allowed values pending pending_registration pending_transfer active expired grace redemption pending_delete transferring_away transferred_away transfer_failed cancelled fraud
        • registration_date string | null
        • expiration_date string | null
        • next_due_date string | null
        • auto_renew boolean
        • transfer object
          2 properties
          • pending boolean
          • failed boolean
      • charges array of object
        8 properties
        • id integer
        • action string
          Allowed values register transfer renew restore grace_fee redemption_fee
        • years integer
        • currency string
        • net number
        • tax number
        • gross number
        • status string
          Allowed values pending billable invoiced refunded
  • 401 unauthenticated ApiError
  • 402 insufficient_credit 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 not_reseller credit_disabled ApiError
  • 404 client_not_found ApiError
  • 409 operation_in_progress idempotency_in_progress ApiError
  • 422 invalid_request invalid_contact invalid_domain tld_not_sellable invalid_years domain_unavailable registration_data_missing registrar_error invalid_idempotency_key idempotency_key_reused ApiError
  • 424 registrar_unknown ApiError
  • 429 rate_limited ApiError
  • 500 operation_failed ApiError
  • 503 whois_unavailable ApiError

cURL

# Idempotency-Key is optional: a retry with the same key is never processed twice.
curl -X POST 'https://portal.supporthost.com/api/v1/reseller/domains/register' \
  -H "Authorization: Bearer $API_TOKEN" \
  -H 'Accept: application/json' \
  -H 'Content-Type: application/json' \
  -H 'Idempotency-Key: 00000000-0000-4000-8000-000000000000' \
  -d '{
  "name": "example.com",
  "years": 1,
  "nameservers": [
    "ns1.example.net",
    "ns2.example.net"
  ],
  "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/reseller/domains/register');
curl_setopt_array($ch, [
    CURLOPT_CUSTOMREQUEST => 'POST',
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_HTTPHEADER => [
        'Authorization: Bearer ' . getenv('API_TOKEN'),
        'Accept: application/json',
        'Content-Type: application/json',
        // Optional: a retry with the same key is never processed twice.
        'Idempotency-Key: 00000000-0000-4000-8000-000000000000',
    ],
    CURLOPT_POSTFIELDS => json_encode([
        'name' => 'example.com',
        'years' => 1,
        'nameservers' => [
            'ns1.example.net',
            'ns2.example.net',
        ],
        '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/reseller/domains/register', {
  method: 'POST',
  headers: {
    Authorization: `Bearer ${process.env.API_TOKEN}`,
    Accept: 'application/json',
    'Content-Type': 'application/json',
    // Optional: a retry with the same key is never processed twice.
    'Idempotency-Key': '00000000-0000-4000-8000-000000000000',
  },
  body: JSON.stringify({
    "name": "example.com",
    "years": 1,
    "nameservers": [
      "ns1.example.net",
      "ns2.example.net"
    ],
    "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": {
    "state": "completed",
    "domain": {
      "id": 1042,
      "name": "example.com",
      "status": "active",
      "registration_date": "2026-09-15",
      "expiration_date": "2027-09-15",
      "next_due_date": "2027-09-15",
      "auto_renew": false,
      "transfer": {
        "pending": false,
        "failed": false
      }
    },
    "charges": [
      {
        "id": 5310,
        "action": "register",
        "years": 1,
        "currency": "EUR",
        "net": 11.1699999999999999289457264239899814128875732421875,
        "tax": 2.45999999999999996447286321199499070644378662109375,
        "gross": 13.6300000000000007815970093361102044582366943359375,
        "status": "billable"
      }
    ]
  }
}

202

{
  "data": {
    "state": "pending",
    "domain": {
      "id": 1042,
      "name": "example.com",
      "status": "pending_registration",
      "registration_date": "2026-09-15",
      "expiration_date": "2027-09-15",
      "next_due_date": "2027-09-15",
      "auto_renew": false,
      "transfer": {
        "pending": false,
        "failed": false
      }
    },
    "charges": [
      {
        "id": 5310,
        "action": "register",
        "years": 1,
        "currency": "EUR",
        "net": 11.1699999999999999289457264239899814128875732421875,
        "tax": 2.45999999999999996447286321199499070644378662109375,
        "gross": 13.6300000000000007815970093361102044582366943359375,
        "status": "pending"
      }
    ]
  }
}

Error responses share one format: see Errors.

Transfer a domain in #

POST /reseller/domains/transfer

Starts the transfer of a registered name to your account, paid from your credit at your net transfer price. The body is the register body plus auth_code (the EPP code from the current registrar); years is not accepted, a transfer always buys the TLD’s minimum term.

registrant, nameservers and extra_fields follow the same rules as POST /reseller/domains/register, including the per-TLD extra_fields and the 422 invalid_contact answer with its fields map.

Most transfers answer 202: the registry and the losing registrar take from hours to several days to complete one. The charge is refunded automatically if the transfer fails.

Parameters

Header

  • Idempotency-Key string
    Optional. 1–255 printable ASCII characters, scoped to your account. A retry with the same key and the same request returns the stored response byte for byte (with Idempotent-Replayed: true) and never charges twice. The same key with a different request answers 422 idempotency_key_reused; while the first request is still running, 409 idempotency_in_progress (retry after retry_after seconds). Keys are kept for 30 days. See Idempotency in the introduction.
    • Min length 1
    • Max length 255

    See Rate limits and idempotency.

Body application/json required

  • name string required
    The domain to transfer in, e.g. example.org.
    • Max length 255
  • nameservers array of string
    2 to 5 nameserver host names. Optional: when omitted, the default nameservers configured on this server are used.
    • Min items 2
    • Max items 5
    • Pattern ^[A-Za-z0-9.\-]+$
    • Max length 255
  • registrant object required
    The owner contact of the domain, the only contact these calls take. The registrar fills the other roles the TLD needs (admin, tech, billing) on its own: most copy the registrant, some use contacts of their own. Change any role afterwards with PUT /reseller/domains/{name}/contacts.
    11 properties
    • first_name string required
      • Max length 100
    • last_name string required
      • Max length 100
    • organization string | null
      Company name. Some TLDs require it and some refuse it: either case answers 422 invalid_contact.
      • 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 registrant.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. When the TLD lists registrant_countries in GET /reseller/pricing, it must be one of them, otherwise 422 invalid_contact before any credit is taken.
      • Min length 2
      • Max length 2
      Allowed values AF AL DZ AD AO AI AQ AG SA AR
      240 more values AM AW AU AT AZ BS BH BD BB BE BZ BJ BM BT BY BO BA BW BR BN BG BF BI KH CM CA CV BQ CZ TD CL CN CY VA CO KM CD CG KP KR CR CI HR CU CW DK DM EC EG SV AE ER EE SZ ET FJ PH FI FR GA GM GE GS DE GH JM JP GI DJ JO GR GD GL GP GU GT GG GN GQ GW GY GF HT HN IN ID IR IQ IE IS BV CX NF IM KY CC CK FK FO HM MP MH UM PN SB TC VI VG AX IL IT JE KZ KE KG KI XK KW LA LS LV LB LR LY LI LT LU MK MG MW MY MV ML MT MA MQ MR MU YT MX FM MD MC MN ME MS MZ MM NA NR NP NI NE NG NU NO NC NZ OM NL PK PW PA PG PY PE PF PL PT PR QA HK MO GB CF DO RE RO RW RU EH KN LC MF VC BL PM WS AS SM SH SN RS SC SL SG SX SY SK SI SO ES LK US SS ZA SD SR SJ SE CH ST TJ TW TZ TF PS IO TH TL TG TK TO TT TN TR TM TV UA UG HU UY UZ VU VE VN WF YE ZM ZW
  • extra_fields map of string
    Registry-specific data some TLDs require (e.g. entity type, tax codes, language). Which keys are required depends on the TLD and on this server’s configuration, and some are only required depending on the answer to another field. For a new registration or transfer, GET /reseller/tlds/{tld}/extra-fields lists them, with their conditions; for an existing domain, GET /reseller/domains/{name}/contacts returns the ones it uses. Values are strings: send a checkbox as "1". Keys the TLD does not declare are ignored. A missing or invalid field answers 422 invalid_contact with a fields map naming each field to fix.
  • source object
    Optional. The additional domain fields of your own platform, sent as your platform holds them, for this server to translate into extra_fields. A registrar module generated by this server fills it in: you do not need it when you send extra_fields yourself. A key you send in extra_fields always wins over a translated one.
    5 properties
    • platform string
      Your platform, lower case: whmcs, hostbill.
      • Pattern ^[a-z][a-z0-9-]*$
      • Max length 32
    • version string | null
      Your platform’s own version, e.g. 8.13.1: field names differ between versions.
      • Max length 50
    • module_version string | null
      Version of the registrar module sending the request.
      • Max length 50
    • fields map of string
      The platform’s additional fields, name => value, exactly as the platform holds them (e.g. "Legal Type": "Companies/one man companies"). At most 50, values up to 255 characters.
    • translated array of string
      The extra_fields keys your module translated itself from source.fields. This server’s own translation wins over them; keys not listed here are yours and win over it.
      • Max items 100
      • Max length 64
  • auth_code string required
    The transfer authorisation (EPP) code, obtained from the domain’s current registrar. Always required, whatever the TLD: the panel does not know reliably which registries transfer without one, so it never starts a transfer without it.
    • Max length 255

Responses

  • 200

    Transferred.

    Idempotent-Replayed string response header
    true when this response is the replay of an earlier request with the same Idempotency-Key.
    Response body application/json
    • data object
      3 properties
      • state string
        • Value completed
      • domain object
        8 properties
        • id integer
        • name string
        • status string
          Allowed values pending pending_registration pending_transfer active expired grace redemption pending_delete transferring_away transferred_away transfer_failed cancelled fraud
        • registration_date string | null
        • expiration_date string | null
        • next_due_date string | null
        • auto_renew boolean
        • transfer object
          2 properties
          • pending boolean
          • failed boolean
      • charges array of object
        8 properties
        • id integer
        • action string
          Allowed values register transfer renew restore grace_fee redemption_fee
        • years integer
        • currency string
        • net number
        • tax number
        • gross number
        • status string
          Allowed values pending billable invoiced refunded
  • 202 Accepted — completes later

    Accepted but not completed yet: the registry has taken the request and will finish it later. Your credit has already been debited; the charges stay pending until the operation completes (then they are billed on your next monthly invoice) and are refunded automatically if it fails. Poll GET /reseller/domains/{name} until status leaves pending_registration / pending_transfer (a failed transfer shows transfer.failed: true).

    Idempotent-Replayed string response header
    true when this response is the replay of an earlier request with the same Idempotency-Key.
    Response body application/json
    • data object
      3 properties
      • state string
        • Value pending
      • domain object
        8 properties
        • id integer
        • name string
        • status string
          Allowed values pending pending_registration pending_transfer active expired grace redemption pending_delete transferring_away transferred_away transfer_failed cancelled fraud
        • registration_date string | null
        • expiration_date string | null
        • next_due_date string | null
        • auto_renew boolean
        • transfer object
          2 properties
          • pending boolean
          • failed boolean
      • charges array of object
        8 properties
        • id integer
        • action string
          Allowed values register transfer renew restore grace_fee redemption_fee
        • years integer
        • currency string
        • net number
        • tax number
        • gross number
        • status string
          Allowed values pending billable invoiced refunded
  • 401 unauthenticated ApiError
  • 402 insufficient_credit 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 not_reseller credit_disabled ApiError
  • 404 client_not_found ApiError
  • 409 operation_in_progress idempotency_in_progress ApiError
  • 422 invalid_request invalid_contact invalid_domain tld_not_sellable invalid_years domain_unavailable domain_not_registered registration_data_missing registrar_error invalid_idempotency_key idempotency_key_reused ApiError
  • 424 registrar_unknown ApiError
  • 429 rate_limited ApiError
  • 500 operation_failed ApiError
  • 503 whois_unavailable ApiError

cURL

# Idempotency-Key is optional: a retry with the same key is never processed twice.
curl -X POST 'https://portal.supporthost.com/api/v1/reseller/domains/transfer' \
  -H "Authorization: Bearer $API_TOKEN" \
  -H 'Accept: application/json' \
  -H 'Content-Type: application/json' \
  -H 'Idempotency-Key: 00000000-0000-4000-8000-000000000000' \
  -d '{
  "name": "example.org",
  "auth_code": "kX7#p2Qz9w",
  "nameservers": [
    "ns1.example.net",
    "ns2.example.net"
  ],
  "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/reseller/domains/transfer');
curl_setopt_array($ch, [
    CURLOPT_CUSTOMREQUEST => 'POST',
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_HTTPHEADER => [
        'Authorization: Bearer ' . getenv('API_TOKEN'),
        'Accept: application/json',
        'Content-Type: application/json',
        // Optional: a retry with the same key is never processed twice.
        'Idempotency-Key: 00000000-0000-4000-8000-000000000000',
    ],
    CURLOPT_POSTFIELDS => json_encode([
        'name' => 'example.org',
        'auth_code' => 'kX7#p2Qz9w',
        'nameservers' => [
            'ns1.example.net',
            'ns2.example.net',
        ],
        '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/reseller/domains/transfer', {
  method: 'POST',
  headers: {
    Authorization: `Bearer ${process.env.API_TOKEN}`,
    Accept: 'application/json',
    'Content-Type': 'application/json',
    // Optional: a retry with the same key is never processed twice.
    'Idempotency-Key': '00000000-0000-4000-8000-000000000000',
  },
  body: JSON.stringify({
    "name": "example.org",
    "auth_code": "kX7#p2Qz9w",
    "nameservers": [
      "ns1.example.net",
      "ns2.example.net"
    ],
    "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": {
    "state": "completed",
    "domain": {
      "id": 1043,
      "name": "example.org",
      "status": "active",
      "registration_date": "2021-05-03",
      "expiration_date": "2027-05-03",
      "next_due_date": "2027-05-03",
      "auto_renew": false,
      "transfer": {
        "pending": false,
        "failed": false
      }
    },
    "charges": [
      {
        "id": 5312,
        "action": "transfer",
        "years": 1,
        "currency": "EUR",
        "net": 11.1699999999999999289457264239899814128875732421875,
        "tax": 2.45999999999999996447286321199499070644378662109375,
        "gross": 13.6300000000000007815970093361102044582366943359375,
        "status": "billable"
      }
    ]
  }
}

202

{
  "data": {
    "state": "pending",
    "domain": {
      "id": 1043,
      "name": "example.org",
      "status": "pending_transfer",
      "registration_date": null,
      "expiration_date": null,
      "next_due_date": null,
      "auto_renew": false,
      "transfer": {
        "pending": true,
        "failed": false
      }
    },
    "charges": [
      {
        "id": 5312,
        "action": "transfer",
        "years": 1,
        "currency": "EUR",
        "net": 11.1699999999999999289457264239899814128875732421875,
        "tax": 2.45999999999999996447286321199499070644378662109375,
        "gross": 13.6300000000000007815970093361102044582366943359375,
        "status": "pending"
      }
    ]
  }
}

Error responses share one format: see Errors.

Renew a domain #

POST /reseller/domains/{name}/renew

Adds years to an active or grace domain, paid from your credit. A domain in grace also pays the TLD’s grace fee (a separate grace_fee charge). A domain in redemption must be restored first (409 restore_required).

If the domain already has an open renewal invoice for that term, your credit pays that invoice instead of creating a charge: charges is then empty and paid_invoice_id / paid_invoice_covers name the invoice and the domains it renewed (an invoice can cover several of your domains; paid_invoice_covers_truncated: true means the list was cut at 50).

Parameters

Path

  • name string required

Header

  • Idempotency-Key string
    Optional. 1–255 printable ASCII characters, scoped to your account. A retry with the same key and the same request returns the stored response byte for byte (with Idempotent-Replayed: true) and never charges twice. The same key with a different request answers 422 idempotency_key_reused; while the first request is still running, 409 idempotency_in_progress (retry after retry_after seconds). Keys are kept for 30 days. See Idempotency in the introduction.
    • Min length 1
    • Max length 255

    See Rate limits and idempotency.

Body application/json required

  • years integer required
    Years to add. Must be one of the renew terms GET /reseller/pricing lists for the TLD, otherwise 422 invalid_years (with allowed_years).
    • Minimum 1
    • Maximum 999

Responses

  • 200

    Renewed.

    Idempotent-Replayed string response header
    true when this response is the replay of an earlier request with the same Idempotency-Key.
    Response body application/json
    • data object
      6 properties
      • state string
        • Value completed
      • domain object
        8 properties
        • id integer
        • name string
        • status string
          Allowed values pending pending_registration pending_transfer active expired grace redemption pending_delete transferring_away transferred_away transfer_failed cancelled fraud
        • registration_date string | null
        • expiration_date string | null
        • next_due_date string | null
        • auto_renew boolean
        • transfer object
          2 properties
          • pending boolean
          • failed boolean
      • charges array of object
        8 properties
        • id integer
        • action string
          Allowed values register transfer renew restore grace_fee redemption_fee
        • years integer
        • currency string
        • net number
        • tax number
        • gross number
        • status string
          Allowed values pending billable invoiced refunded
      • paid_invoice_id integer
      • paid_invoice_covers array of string
      • paid_invoice_covers_truncated boolean
  • 202 Accepted — completes later

    Accepted but not confirmed yet. pending: the registrar has not confirmed the operation; your credit has already been used, and its charges stay pending until the domain’s dates move, then they are billed (poll GET /reseller/domains/{name} and watch expiration_date / next_due_date). not_settled: your credit was applied to an open renewal invoice that it did not fully pay, so the domain is NOT renewed yet. In neither case is anything refunded automatically: if the operation did not happen, support follows up. Do not retry with a new Idempotency-Key.

    Idempotent-Replayed string response header
    true when this response is the replay of an earlier request with the same Idempotency-Key.
    Response body application/json
    • data object
      6 properties
      • state string
        Allowed values pending not_settled
      • domain object
        8 properties
        • id integer
        • name string
        • status string
          Allowed values pending pending_registration pending_transfer active expired grace redemption pending_delete transferring_away transferred_away transfer_failed cancelled fraud
        • registration_date string | null
        • expiration_date string | null
        • next_due_date string | null
        • auto_renew boolean
        • transfer object
          2 properties
          • pending boolean
          • failed boolean
      • charges array of object
        8 properties
        • id integer
        • action string
          Allowed values register transfer renew restore grace_fee redemption_fee
        • years integer
        • currency string
        • net number
        • tax number
        • gross number
        • status string
          Allowed values pending billable invoiced refunded
      • paid_invoice_id integer
      • paid_invoice_covers array of string
      • paid_invoice_covers_truncated boolean
  • 401 unauthenticated ApiError
  • 402 insufficient_credit 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 not_reseller credit_disabled ApiError
  • 404 client_not_found not_found ApiError
  • 409 restore_required renewal_in_progress operation_in_progress idempotency_in_progress ApiError
  • 422 invalid_request invalid_years domain_not_renewable registrar_error invalid_idempotency_key idempotency_key_reused ApiError
  • 424 registrar_unknown ApiError
  • 429 rate_limited ApiError

cURL

# Idempotency-Key is optional: a retry with the same key is never processed twice.
curl -X POST 'https://portal.supporthost.com/api/v1/reseller/domains/{name}/renew' \
  -H "Authorization: Bearer $API_TOKEN" \
  -H 'Accept: application/json' \
  -H 'Content-Type: application/json' \
  -H 'Idempotency-Key: 00000000-0000-4000-8000-000000000000' \
  -d '{
  "years": 1
}'

PHP

<?php

$ch = curl_init('https://portal.supporthost.com/api/v1/reseller/domains/{name}/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',
        // Optional: a retry with the same key is never processed twice.
        'Idempotency-Key: 00000000-0000-4000-8000-000000000000',
    ],
    CURLOPT_POSTFIELDS => json_encode([
        'years' => 1,
    ]),
]);

$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/reseller/domains/{name}/renew', {
  method: 'POST',
  headers: {
    Authorization: `Bearer ${process.env.API_TOKEN}`,
    Accept: 'application/json',
    'Content-Type': 'application/json',
    // Optional: a retry with the same key is never processed twice.
    'Idempotency-Key': '00000000-0000-4000-8000-000000000000',
  },
  body: JSON.stringify({
    "years": 1
  }),
});

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

Response

200

{
  "data": {
    "state": "completed",
    "domain": {
      "id": 1042,
      "name": "example.com",
      "status": "active",
      "registration_date": "2026-09-15",
      "expiration_date": "2028-09-15",
      "next_due_date": "2028-09-15",
      "auto_renew": false,
      "transfer": {
        "pending": false,
        "failed": false
      }
    },
    "charges": [
      {
        "id": 5311,
        "action": "renew",
        "years": 1,
        "currency": "EUR",
        "net": 11.1699999999999999289457264239899814128875732421875,
        "tax": 2.45999999999999996447286321199499070644378662109375,
        "gross": 13.6300000000000007815970093361102044582366943359375,
        "status": "billable"
      }
    ],
    "paid_invoice_id": 20790,
    "paid_invoice_covers": [
      "example.com",
      "example.net"
    ],
    "paid_invoice_covers_truncated": true
  }
}

202

{
  "data": {
    "state": "pending",
    "domain": {
      "id": 1042,
      "name": "example.com",
      "status": "active",
      "registration_date": "2026-09-15",
      "expiration_date": "2027-09-15",
      "next_due_date": "2027-09-15",
      "auto_renew": false,
      "transfer": {
        "pending": false,
        "failed": false
      }
    },
    "charges": [
      {
        "id": 5311,
        "action": "renew",
        "years": 1,
        "currency": "EUR",
        "net": 11.1699999999999999289457264239899814128875732421875,
        "tax": 2.45999999999999996447286321199499070644378662109375,
        "gross": 13.6300000000000007815970093361102044582366943359375,
        "status": "pending"
      }
    ],
    "paid_invoice_id": 20790,
    "paid_invoice_covers": [
      "example.com",
      "example.net"
    ],
    "paid_invoice_covers_truncated": true
  }
}

Error responses share one format: see Errors.

Restore a domain from redemption #

POST /reseller/domains/{name}/restore

Recovers a domain in redemption and renews it for one year, paid from your credit: a restore charge priced as a one-year renewal, plus the TLD’s redemption fee as a separate redemption_fee charge. No body. Like renew, it pays an open renewal invoice for the domain instead when there is one (paid_invoice_* fields, empty charges).

Parameters

Path

  • name string required

Header

  • Idempotency-Key string
    Optional. 1–255 printable ASCII characters, scoped to your account. A retry with the same key and the same request returns the stored response byte for byte (with Idempotent-Replayed: true) and never charges twice. The same key with a different request answers 422 idempotency_key_reused; while the first request is still running, 409 idempotency_in_progress (retry after retry_after seconds). Keys are kept for 30 days. See Idempotency in the introduction.
    • Min length 1
    • Max length 255

    See Rate limits and idempotency.

Responses

  • 200

    Restored.

    Idempotent-Replayed string response header
    true when this response is the replay of an earlier request with the same Idempotency-Key.
    Response body application/json
    • data object
      6 properties
      • state string
        • Value completed
      • domain object
        8 properties
        • id integer
        • name string
        • status string
          Allowed values pending pending_registration pending_transfer active expired grace redemption pending_delete transferring_away transferred_away transfer_failed cancelled fraud
        • registration_date string | null
        • expiration_date string | null
        • next_due_date string | null
        • auto_renew boolean
        • transfer object
          2 properties
          • pending boolean
          • failed boolean
      • charges array of object
        8 properties
        • id integer
        • action string
          Allowed values register transfer renew restore grace_fee redemption_fee
        • years integer
        • currency string
        • net number
        • tax number
        • gross number
        • status string
          Allowed values pending billable invoiced refunded
      • paid_invoice_id integer
      • paid_invoice_covers array of string
      • paid_invoice_covers_truncated boolean
  • 202 Accepted — completes later

    Accepted but not confirmed yet. pending: the registrar has not confirmed the operation; your credit has already been used, and its charges stay pending until the domain’s dates move, then they are billed (poll GET /reseller/domains/{name} and watch expiration_date / next_due_date). not_settled: your credit was applied to an open renewal invoice that it did not fully pay, so the domain is NOT renewed yet. In neither case is anything refunded automatically: if the operation did not happen, support follows up. Do not retry with a new Idempotency-Key.

    Idempotent-Replayed string response header
    true when this response is the replay of an earlier request with the same Idempotency-Key.
    Response body application/json
    • data object
      6 properties
      • state string
        Allowed values pending not_settled
      • domain object
        8 properties
        • id integer
        • name string
        • status string
          Allowed values pending pending_registration pending_transfer active expired grace redemption pending_delete transferring_away transferred_away transfer_failed cancelled fraud
        • registration_date string | null
        • expiration_date string | null
        • next_due_date string | null
        • auto_renew boolean
        • transfer object
          2 properties
          • pending boolean
          • failed boolean
      • charges array of object
        8 properties
        • id integer
        • action string
          Allowed values register transfer renew restore grace_fee redemption_fee
        • years integer
        • currency string
        • net number
        • tax number
        • gross number
        • status string
          Allowed values pending billable invoiced refunded
      • paid_invoice_id integer
      • paid_invoice_covers array of string
      • paid_invoice_covers_truncated boolean
  • 401 unauthenticated ApiError
  • 402 insufficient_credit 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 not_reseller credit_disabled ApiError
  • 404 client_not_found not_found ApiError
  • 409 renewal_in_progress operation_in_progress idempotency_in_progress ApiError
  • 422 domain_not_restorable registrar_error invalid_idempotency_key idempotency_key_reused ApiError
  • 424 registrar_unknown ApiError
  • 429 rate_limited ApiError

cURL

# Idempotency-Key is optional: a retry with the same key is never processed twice.
curl -X POST 'https://portal.supporthost.com/api/v1/reseller/domains/{name}/restore' \
  -H "Authorization: Bearer $API_TOKEN" \
  -H 'Accept: application/json' \
  -H 'Idempotency-Key: 00000000-0000-4000-8000-000000000000'

PHP

<?php

$ch = curl_init('https://portal.supporthost.com/api/v1/reseller/domains/{name}/restore');
curl_setopt_array($ch, [
    CURLOPT_CUSTOMREQUEST => 'POST',
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_HTTPHEADER => [
        'Authorization: Bearer ' . getenv('API_TOKEN'),
        'Accept: application/json',
        // Optional: a retry with the same key is never processed twice.
        'Idempotency-Key: 00000000-0000-4000-8000-000000000000',
    ],
]);

$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/reseller/domains/{name}/restore', {
  method: 'POST',
  headers: {
    Authorization: `Bearer ${process.env.API_TOKEN}`,
    Accept: 'application/json',
    // Optional: a retry with the same key is never processed twice.
    'Idempotency-Key': '00000000-0000-4000-8000-000000000000',
  },
});

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

Response

200

{
  "data": {
    "state": "completed",
    "domain": {
      "id": 1042,
      "name": "example.com",
      "status": "active",
      "registration_date": "2026-09-15",
      "expiration_date": "2028-09-15",
      "next_due_date": "2028-09-15",
      "auto_renew": false,
      "transfer": {
        "pending": false,
        "failed": false
      }
    },
    "charges": [
      {
        "id": 5313,
        "action": "restore",
        "years": 1,
        "currency": "EUR",
        "net": 11.1699999999999999289457264239899814128875732421875,
        "tax": 2.45999999999999996447286321199499070644378662109375,
        "gross": 13.6300000000000007815970093361102044582366943359375,
        "status": "billable"
      }
    ],
    "paid_invoice_id": 20790,
    "paid_invoice_covers": [
      "example.com",
      "example.net"
    ],
    "paid_invoice_covers_truncated": true
  }
}

202

{
  "data": {
    "state": "pending",
    "domain": {
      "id": 1042,
      "name": "example.com",
      "status": "redemption",
      "registration_date": "2026-09-15",
      "expiration_date": "2027-09-15",
      "next_due_date": "2027-09-15",
      "auto_renew": false,
      "transfer": {
        "pending": false,
        "failed": false
      }
    },
    "charges": [
      {
        "id": 5313,
        "action": "restore",
        "years": 1,
        "currency": "EUR",
        "net": 11.1699999999999999289457264239899814128875732421875,
        "tax": 2.45999999999999996447286321199499070644378662109375,
        "gross": 13.6300000000000007815970093361102044582366943359375,
        "status": "pending"
      }
    ],
    "paid_invoice_id": 20790,
    "paid_invoice_covers": [
      "example.com",
      "example.net"
    ],
    "paid_invoice_covers_truncated": true
  }
}

Error responses share one format: see Errors.