# DNSHE Domain API Reference
English · 简体中文 · 繁體中文 · 日本語 · Русский · Bahasa Indonesia · Deutsch · Français · 한국어 · العربية
[Back to introduction](../README.md) Register domains, manage DNS, update dynamic IPs and automate account workflows. Examples use the DNSHE API host and placeholder credentials; replace example names and IDs with resources you own. ## Contents - [Getting started](#getting-started) - [Authentication and request conventions](#authentication-and-request-conventions) - [Domain management](#domain-management) - [DNS record management](#dns-record-management) - [Dynamic DNS (DDNS)](#dynamic-dns-ddns) - [API key management](#api-key-management) - [Domain gifts](#domain-gifts) - [Quota](#quota) - [WHOIS](#whois) - [Errors and rate limits](#errors-and-rate-limits) - [Client examples](#client-examples) - [Security and FAQ](#security-and-faq) - [Support](#support) ## Getting started ```text https://api005.dnshe.com/index.php?m=domain_hub ``` The base URL already contains `m=domain_hub`; append route parameters with `&`. Requests and responses use JSON, except GET query parameters. General authenticated access defaults to 60 requests/minute and can be configured by the operator. Function availability depends on your account and deployment settings. The shell examples use Bash/sh; configure these environment variables first. ```bash export DNSHE_API_KEY='replace-with-your-api-key' export DNSHE_API_SECRET='replace-with-your-api-secret' export DNSHE_DDNS_TOKEN='replace-with-your-ddns-token' ``` ## Authentication and request conventions Create your first API key in the client area → [Manage domains](https://my.dnshe.com/index.php?m=domain_hub) → API Management. Send `X-API-Key` and `X-API-Secret` headers on authenticated requests. Credentials in URL queries or request bodies are disabled. Send GET parameters in the query string; send write parameters as JSON with `Content-Type: application/json`. `endpoint` selects the resource; `action` selects the operation. `quota` and `whois` do not need `action`. DDNS uses a separate token, described below. ## Domain management ### 1.1 List domains `GET` · `endpoint=subdomains` · `action=list` #### Parameters - `page` — `integer`; optional; default / range: `1`. - `cursor_id` — `integer`; optional. - `per_page` — `integer`; optional; default / range: `200; 1–500`. - `include_total` — `boolean`; optional; default / range: `false`. - `search` — `string`; optional. - `rootdomain` — `string`; optional. - `status` — `string`; optional; default / range: `active | suspended | expired`. - `created_from / created_to` — `string`; optional; default / range: `YYYY-MM-DD`. - `sort_by` — `string`; optional; default / range: `id`. - `sort_dir` — `string`; optional; default / range: `desc; asc | desc`. - `fields` — `string`; optional; default / range: `all`. `page` is a 1-based compatibility page number. For large collections, start with `cursor_id=0`, then send `pagination.next_cursor_id` while `pagination.has_more=true`; stop when false. Cursor mode uses ID ordering without OFFSET. `per_page` defaults to 200 and is capped at 500; 50–100 is a useful starting point. `include_total=1` requests a potentially expensive total count. `search` matches the prefix or root domain; `rootdomain`, `status`, `created_from` and `created_to` filter results. Dates use YYYY-MM-DD. `sort_by` accepts `id`, `created_at`, `updated_at`, `expires_at` or `subdomain`; `sort_dir` accepts `asc` or `desc`. `fields` is a comma-separated selection or `all`: `id`, `subdomain`, `rootdomain`, `full_domain`, `status`, `created_at`, `updated_at`, `expires_at`, `never_expires`, `cloudflare_zone_id`, `provider_account_id`. A custom selection always includes `id`. `count` describes the returned collection, not necessarily all matching domains; use pagination rather than assuming a global total. #### Request examples ```bash curl --fail-with-body --silent --show-error --max-time 30 -X GET "https://api005.dnshe.com/index.php?m=domain_hub&endpoint=subdomains&action=list" \ -H "X-API-Key: ${DNSHE_API_KEY}" \ -H "X-API-Secret: ${DNSHE_API_SECRET}" ``` ```bash curl --fail-with-body --silent --show-error --max-time 30 -X GET "https://api005.dnshe.com/index.php?m=domain_hub&endpoint=subdomains&action=list&cursor_id=0&per_page=100&fields=id,subdomain,rootdomain,status" \ -H "X-API-Key: ${DNSHE_API_KEY}" \ -H "X-API-Secret: ${DNSHE_API_SECRET}" ``` ```bash curl --fail-with-body --silent --show-error --max-time 30 -X GET "https://api005.dnshe.com/index.php?m=domain_hub&endpoint=subdomains&action=list&search=test&rootdomain=de5.net&status=active&sort_by=expires_at&sort_dir=asc&per_page=50" \ -H "X-API-Key: ${DNSHE_API_KEY}" \ -H "X-API-Secret: ${DNSHE_API_SECRET}" ``` #### Response examples ```json { "success": true, "count": 2, "subdomains": [ { "id": 1, "subdomain": "test", "rootdomain": "de5.net", "full_domain": "test.de5.net", "status": "active", "created_at": "2025-10-19 10:00:00", "updated_at": "2025-10-19 10:00:00" }, { "id": 2, "subdomain": "api", "rootdomain": "de5.net", "full_domain": "api.de5.net", "status": "active", "created_at": "2025-10-19 11:00:00", "updated_at": "2025-10-19 11:00:00" } ] } ``` ```json { "success": true, "count": 1, "subdomains": [ { "id": 901, "subdomain": "test", "rootdomain": "de5.net", "full_domain": "test.de5.net", "status": "active" } ], "pagination": { "mode": "cursor", "page": 1, "per_page": 100, "has_more": true, "cursor_id": 0, "next_cursor_id": 901 } } ``` ### 1.2 Register a domain `POST` · `endpoint=subdomains` · `action=create` #### Parameters - `subdomain` — `string`; required. - `domain` — `string`; required. `subdomain` is the prefix (for example `myapp`); `domain` is an available root suffix (for example `de5.net`). Registration uses `action=create` and the request field `domain`. The response field `rootdomain` and list filter of that name are not registration fields. Availability and account quotas still apply. #### Request examples ```bash curl --fail-with-body --silent --show-error --max-time 30 -X POST "https://api005.dnshe.com/index.php?m=domain_hub&endpoint=subdomains&action=create" \ -H "X-API-Key: ${DNSHE_API_KEY}" \ -H "X-API-Secret: ${DNSHE_API_SECRET}" \ -H "Content-Type: application/json" \ -d '{ "subdomain": "myapp", "domain": "de5.net" }' ``` #### Response examples ```json { "success": true, "message": "Subdomain registered successfully", "subdomain_id": 3, "full_domain": "myapp.de5.net" } ``` ### 1.3 Get domain details `GET` · `endpoint=subdomains` · `action=get` #### Parameters - `subdomain_id` — `integer`; required. Use a domain ID owned by the authenticated account. The response includes the domain object, its `dns_records` and `dns_count`. #### Request examples ```bash curl --fail-with-body --silent --show-error --max-time 30 -X GET "https://api005.dnshe.com/index.php?m=domain_hub&endpoint=subdomains&action=get&subdomain_id=1" \ -H "X-API-Key: ${DNSHE_API_KEY}" \ -H "X-API-Secret: ${DNSHE_API_SECRET}" ``` #### Response examples ```json { "success": true, "subdomain": { "id": 1, "subdomain": "test", "rootdomain": "de5.net", "full_domain": "test.de5.net", "status": "active", "created_at": "2025-10-19 10:00:00", "updated_at": "2025-10-19 10:00:00" }, "dns_records": [ { "id": 1, "name": "test.de5.net", "type": "A", "content": "203.0.113.10", "ttl": 600, "priority": null, "status": "active", "created_at": "2025-10-19 10:05:00" } ], "dns_count": 1 } ``` ### 1.4 Delete a domain `POST / DELETE` · `endpoint=subdomains` · `action=delete` #### Parameters - `subdomain_id` — `integer`; required. Deletes the owned domain and its associated DNS records. The response reports `dns_records_deleted`. Confirm the target ID before sending this write operation. #### Request examples ```bash curl --fail-with-body --silent --show-error --max-time 30 -X POST "https://api005.dnshe.com/index.php?m=domain_hub&endpoint=subdomains&action=delete" \ -H "X-API-Key: ${DNSHE_API_KEY}" \ -H "X-API-Secret: ${DNSHE_API_SECRET}" \ -H "Content-Type: application/json" \ -d '{ "subdomain_id": 1 }' ``` #### Response examples ```json { "success": true, "message": "Subdomain deleted successfully", "subdomain_id": 1, "full_domain": "test.de5.net", "dns_records_deleted": 4 } ``` ### 1.5 Renew a domain `POST / PUT` · `endpoint=subdomains` · `action=renew` #### Parameters - `subdomain_id` — `integer`; required. Normal DNSHE free renewal remains free; the example has `charged_amount=0`. The generic plugin can configure paid redemption handling, so inspect the domain state and current console policy before a redemption renewal. Read `previous_expires_at`, `new_expires_at`, `never_expires`, `remaining_days` and `charged_amount` from the response rather than assuming the result. Renewal failures in the reference include: HTTP 403 `renewal disabled`, `redemption period requires administrator` or `renewal window expired`; HTTP 422 with `error_code=renewal_not_yet_available`; HTTP 402 `insufficient balance for redemption renewal`; HTTP 404 for a missing or unowned domain. Check the renewal window or contact support; do not retry these conditions in a tight loop. #### Request examples ```bash curl --fail-with-body --silent --show-error --max-time 30 -X POST "https://api005.dnshe.com/index.php?m=domain_hub&endpoint=subdomains&action=renew" \ -H "X-API-Key: ${DNSHE_API_KEY}" \ -H "X-API-Secret: ${DNSHE_API_SECRET}" \ -H "Content-Type: application/json" \ -d '{ "subdomain_id": 3 }' ``` #### Response examples ```json { "success": true, "message": "Subdomain renewed successfully", "subdomain_id": 3, "subdomain": "myapp", "previous_expires_at": "2027-05-01 00:00:00", "new_expires_at": "2028-05-01 00:00:00", "renewed_at": "2027-04-30 00:00:00", "never_expires": 0, "status": "active", "remaining_days": 367, "charged_amount": 0 } ``` ## DNS record management ### 2.1 List DNS records `GET` · `endpoint=dns_records` · `action=list` #### Parameters - `subdomain_id` — `integer`; required. Prefer the module's `id` returned by list/create, which is a 15-digit public ID for newly exposed records. `record_id` is the DNS provider's record identifier. Modify/delete require at least one; if both are supplied they must identify the same record, otherwise `dns_record_identifier_mismatch` is returned. Legacy internal IDs remain compatible. Numeric `record_id` compatibility is documented through at least 2027-06-12; new clients should put module IDs in `id`. #### Request examples ```bash curl --fail-with-body --silent --show-error --max-time 30 -X GET "https://api005.dnshe.com/index.php?m=domain_hub&endpoint=dns_records&action=list&subdomain_id=1" \ -H "X-API-Key: ${DNSHE_API_KEY}" \ -H "X-API-Secret: ${DNSHE_API_SECRET}" ``` #### Response examples ```json { "success": true, "count": 2, "records": [ { "id": 1, "record_id": "5a0ce6c4d1d4c71bc5e60a2a2a0e4997", "name": "test.de5.net", "type": "A", "content": "203.0.113.10", "ttl": 600, "priority": null, "line": null, "proxied": false, "status": "active", "created_at": "2025-10-19 10:05:00", "updated_at": "2025-10-19 10:05:00" }, { "id": 2, "name": "www.test.de5.net", "type": "CNAME", "content": "test.de5.net", "ttl": 600, "priority": null, "proxied": false, "status": "active", "created_at": "2025-10-19 10:10:00" } ] } ``` ### 2.2 Create a DNS record `POST` · `endpoint=dns_records` · `action=create` #### Parameters - `subdomain_id` — `integer`; required. - `type` — `string`; required. - `name` — `string`; optional; default / range: `@`. - `content` — `string`; optional. - `ttl` — `integer`; optional; default / range: `600`. - `priority` — `integer`; optional; default / range: `MX: 10; SRV: 0`. - `line` — `string`; optional. - `record_weight / weight` — `integer`; optional. - `record_port / port` — `integer`; optional; default / range: `1–65535`. - `record_target / target` — `string`; optional. - `caa_flag` — `integer`; optional; default / range: `0; 0–255`. - `caa_tag` — `string`; optional; default / range: `issue; 1–15 [A-Za-z0-9]`. - `caa_value` — `string`; optional. `type` supports A, AAAA, CNAME, MX, TXT, NS, SRV and CAA. `name` is relative to the registered domain: omitted, empty or `@` means the domain itself; a full domain name is not accepted. A wildcard `*` may appear only as the leftmost label. `content` is required unless structured SRV/CAA inputs construct it. `ttl` defaults to 600 seconds. `priority` defaults to 10 for MX and 0 for SRV. For SRV, `record_weight`/`weight`, `record_port`/`port` and `record_target`/`target` supply weight, port (1–65535) and target; target `.` means the service is unavailable. For CAA, use `caa_flag` (0–255, default 0), `caa_tag` (1–15 alphanumeric characters, default `issue`) and `caa_value`. `line` is an AliDNS-only routing option; other providers reject a non-empty value. NS writes may be disabled by `disable_ns_management`. Once a domain is delegated to external nameservers, creating/modifying non-NS records is rejected with `external_dns_delegated`. Deleting old records, reconciliation and expiration cleanup are not blocked by this restriction. #### Request examples ```bash curl --fail-with-body --silent --show-error --max-time 30 -X POST "https://api005.dnshe.com/index.php?m=domain_hub&endpoint=dns_records&action=create" \ -H "X-API-Key: ${DNSHE_API_KEY}" \ -H "X-API-Secret: ${DNSHE_API_SECRET}" \ -H "Content-Type: application/json" \ -d '{ "subdomain_id": 1, "type": "A", "content": "203.0.113.10", "ttl": 600 }' ``` #### Response examples ```json { "success": true, "message": "DNS record created successfully", "id": 738492016583241, "record_id": "5a0ce6c4d1d4c71bc5e60a2a2a0e4997" } ``` ### 2.3 Modify a DNS record `POST / PUT / PATCH` · `endpoint=dns_records` · `action=modify` #### Parameters - `id` — `integer`; optional. - `record_id` — `string`; optional. - `type / name / content` — `string`; optional. - `ttl / priority` — `integer`; optional. - `line` — `string`; optional. - `record_weight / weight` — `integer`; optional. - `record_port / port` — `integer`; optional. - `record_target / target` — `string`; optional. - `caa_flag` — `integer`; optional. - `caa_tag / caa_value` — `string`; optional. Send `id` or `record_id` plus the fields to change. The same naming rules and SRV/CAA options as creation apply. If both identifiers are provided, they must refer to the same record. The response returns both the module ID and provider record ID. Prefer the module's `id` returned by list/create, which is a 15-digit public ID for newly exposed records. `record_id` is the DNS provider's record identifier. Modify/delete require at least one; if both are supplied they must identify the same record, otherwise `dns_record_identifier_mismatch` is returned. Legacy internal IDs remain compatible. Numeric `record_id` compatibility is documented through at least 2027-06-12; new clients should put module IDs in `id`. NS writes may be disabled by `disable_ns_management`. Once a domain is delegated to external nameservers, creating/modifying non-NS records is rejected with `external_dns_delegated`. Deleting old records, reconciliation and expiration cleanup are not blocked by this restriction. #### Request examples ```bash curl --fail-with-body --silent --show-error --max-time 30 -X POST "https://api005.dnshe.com/index.php?m=domain_hub&endpoint=dns_records&action=modify" \ -H "X-API-Key: ${DNSHE_API_KEY}" \ -H "X-API-Secret: ${DNSHE_API_SECRET}" \ -H "Content-Type: application/json" \ -d '{ "id": 738492016583241, "type": "A", "content": "203.0.113.20", "ttl": 600 }' ``` #### Response examples ```json { "success": true, "message": "DNS record updated successfully", "id": 738492016583241, "record_id": "5a0ce6c4d1d4c71bc5e60a2a2a0e4997" } ``` ### 2.4 Delete a DNS record `POST / DELETE` · `endpoint=dns_records` · `action=delete` #### Parameters - `id` — `integer`; optional. - `record_id` — `string`; optional. Prefer the module's `id` returned by list/create, which is a 15-digit public ID for newly exposed records. `record_id` is the DNS provider's record identifier. Modify/delete require at least one; if both are supplied they must identify the same record, otherwise `dns_record_identifier_mismatch` is returned. Legacy internal IDs remain compatible. Numeric `record_id` compatibility is documented through at least 2027-06-12; new clients should put module IDs in `id`. #### Request examples ```bash curl --fail-with-body --silent --show-error --max-time 30 -X POST "https://api005.dnshe.com/index.php?m=domain_hub&endpoint=dns_records&action=delete" \ -H "X-API-Key: ${DNSHE_API_KEY}" \ -H "X-API-Secret: ${DNSHE_API_SECRET}" \ -H "Content-Type: application/json" \ -d '{ "id": 1 }' ``` ```bash curl --fail-with-body --silent --show-error --max-time 30 -X POST "https://api005.dnshe.com/index.php?m=domain_hub&endpoint=dns_records&action=delete" \ -H "X-API-Key: ${DNSHE_API_KEY}" \ -H "X-API-Secret: ${DNSHE_API_SECRET}" \ -H "Content-Type: application/json" \ -d '{ "record_id": "5a0ce6c4d1d4c71bc5e60a2a2a0e4997" }' ``` #### Response examples ```json { "success": true, "message": "DNS record deleted successfully" } ``` ## Dynamic DNS (DDNS) `GET / POST / PUT` · `endpoint=ddns` · `action=update` Create a dedicated token for a specific A/AAAA record in Domain Management → DDNS. Send `Authorization: Bearer