ZoneDeck

API 文件

ZoneDeck 完整 REST API:網域與解析管理、DDNS、ACME DNS-01、自訂 NS。所有操作皆可用 curl 或交給 AI Agent 完成。

快速開始

到「API 權杖」建立一個 API 權杖(權杖值只顯示一次),替換下面示例中的 dcp_… 即可。只要快速配 DDNS,看「DDNS 教學」教學就夠。

curl -s https://dns.us.wr.rs/api/v1/zones \
  -H "Authorization: Bearer dcp_xxxxxxxxxxxxxxxx"

認證與權限

每個請求帶 Authorization: Bearer <權杖> 標頭,請求與回應均為 JSON。權杖的權限由建立時勾選的 scope 決定,權限不夠回傳 403。

隔離規則:權杖只能看到並操作建立它的帳號名下的網域,別人的網域一律回傳 404(等同於不存在)。

權杖值只在建立時顯示一次,請立即保存;洩露請立刻在「API 權杖」頁吊銷。

權限範圍(scope)

所需 scope說明
zones:read列出、檢視自己名下的網域
zones:write新增、刪除網域
records:read讀取解析記錄與自訂 NS 狀態
records:write增刪改解析記錄、DDNS、自訂 NS
dns01ACME DNS-01:發布/清理 _acme-challenge TXT
repair對網域執行同步修復
nodes:write管理解析節點(僅管理員帳號可授予)

回應約定

成功回傳 {"ok":true,…};失敗回傳 {"ok":false,"error":"原因"} 並帶 HTTP 狀態碼:400 參數錯誤、401 未認證、403 越權/需要管理員權杖、404 網域不存在或不屬於你。網域一律小寫;解析寫入類操作全部記入稽核日誌(可在「操作日誌」頁看到)。暫停(paused)的網域記錄唯讀,寫入回傳 403。

端點總覽

方法路徑所需 scope說明
GET/api/v1/health—平台與各節點健康狀態(免驗證)
GET/api/v1/ddns/ip—呼叫方公網 IP(免驗證,DDNS 用戶端取本機出口 IP)
GET/api/v1/zoneszones:read列出自己名下的網域;管理員權杖加 ?all=1 列全平台(含歸屬)
POST/api/v1/zoneszones:write新增網域並歸屬目前帳號(全節點自動同步,需幾分鐘)
GET/api/v1/zones/{zone}zones:read檢視網域健康狀態(主/從、SOA 序號一致性)
POST/api/v1/zones/{zone}/repairrepair同步修復(冪等,可反覆呼叫直到 healthy)
DELETE/api/v1/zones/{zone}zones:write刪除網域(主從節點一併刪除,危險操作)
GET/api/v1/zones/{zone}/recordsrecords:read列出全部解析記錄
POST/api/v1/zones/{zone}/recordsrecords:write新增解析記錄
PUT/api/v1/zones/{zone}/recordsrecords:write修改記錄:body 為 {"old":{…現有記錄…},"new":{…}}
DELETE/api/v1/zones/{zone}/recordsrecords:write刪除記錄:body 為要刪的那條記錄(精確匹配)
GET/api/v1/zones/{zone}/vanityrecords:read檢視自訂 NS 與 glue 狀態
POST/api/v1/zones/{zone}/vanityrecords:write新增自訂 NS(hostnames 陣列;整體生效,任一非法則全部不寫入)
DELETE/api/v1/zones/{zone}/vanityrecords:write移除一個自訂 NS(順帶清理無人引用的 glue)
POST/api/v1/ddnsrecords:writeDDNS upsert:呼叫後該記錄恰好等於請求值,回傳 action=created/updated/unchanged
POST/api/v1/acme/dns01dns01發布 _acme-challenge TXT(TTL 60,冪等;泛網域自動落到主網域)
DELETE/api/v1/acme/dns01dns01清理 _acme-challenge TXT(可按 value 精確清理)
GET/api/v1/auditzones:read+admin稽核日誌(?limit=&user=&action= 過濾)
GET/POST/DELETE/api/v1/nodesnodes:write+admin解析節點管理(列表/新增/刪除;新增時即時探活)

{zone} 為網域小寫名(如 example.com)。不帶權杖或權杖錯誤回傳 401。

網域管理

網域即區域(zone)。新增後平台自動在主節點建 Primary、在每個從節點建 Secondary 並補齊 NS,等待同步期間 healthy 為 false。

子網域同樣可以接入:create_zone 直接用 dev.example.com 這類名字,平台把它當作獨立區域;之後到父網域的 DNS 裡給它加 NS 記錄委派到平台即可,主網域解析不受影響。

# 添加域名(创建后自动归属本令牌的账号,全节点同步需几分钟)
curl -s -X POST https://dns.us.wr.rs/api/v1/zones \
  -H "Authorization: Bearer dcp_xxxxxxxxxxxxxxxx" \
  -H "Content-Type: application/json" \
  -d '{"name":"example.com"}'

# 查看域名健康状态(主/从节点、SOA 序号是否一致)
curl -s https://dns.us.wr.rs/api/v1/zones/example.com \
  -H "Authorization: Bearer dcp_xxxxxxxxxxxxxxxx"

# 同步修复(幂等,可反复调用直到 healthy)
curl -s -X POST https://dns.us.wr.rs/api/v1/zones/example.com/repair \
  -H "Authorization: Bearer dcp_xxxxxxxxxxxxxxxx"

解析記錄

記錄 name 支援:@(根網域)、短名 www、完整網域 www.example.com、萬用字元 * 或 *.sub。TTL 最小 30。

# 添加 A 记录(name 支持短名 www / 完整域名 / @ / 通配符 *)
curl -s -X POST https://dns.us.wr.rs/api/v1/zones/example.com/records \
  -H "Authorization: Bearer dcp_xxxxxxxxxxxxxxxx" \
  -H "Content-Type: application/json" \
  -d '{"name":"www","type":"A","value":"203.0.113.10","ttl":300}'

# 列出全部记录(name 为 @ 表示根域名)
curl -s https://dns.us.wr.rs/api/v1/zones/example.com/records \
  -H "Authorization: Bearer dcp_xxxxxxxxxxxxxxxx"

# 修改(old 必须与现有记录完全一致,等价删除+重建)
curl -s -X PUT https://dns.us.wr.rs/api/v1/zones/example.com/records \
  -H "Authorization: Bearer dcp_xxxxxxxxxxxxxxxx" \
  -H "Content-Type: application/json" \
  -d '{"old":{"name":"www","type":"A","value":"203.0.113.10"},
       "new":{"name":"www","type":"A","value":"198.51.100.20"}}'

# 删除(按 name+type+值 精确匹配)
curl -s -X DELETE https://dns.us.wr.rs/api/v1/zones/example.com/records \
  -H "Authorization: Bearer dcp_xxxxxxxxxxxxxxxx" \
  -H "Content-Type: application/json" \
  -d '{"name":"www","type":"A","value":"203.0.113.10"}'

# 泛解析(通配符)
curl -s -X POST https://dns.us.wr.rs/api/v1/zones/example.com/records \
  -H "Authorization: Bearer dcp_xxxxxxxxxxxxxxxx" \
  -H "Content-Type: application/json" \
  -d '{"name":"*","type":"A","value":"203.0.113.10"}'

各類型必填欄位

類型說明欄位
AIPv4 位址value
AAAAIPv6 位址value
CNAME目標主機名(不能與 A 並存)value
NS目標主機名value
MX郵件伺服器主機名 + 優先級value + priority
TXT文字內容(直接貼原文,不用自己加引號)value
SRV目標主機名 + priority/weight/portvalue + priority + weight + port
CAA值 + tag(issue/issuewild/iodef)+ flagsvalue + tag + flags

錯誤提示會精確指出哪個欄位不合法(如 A 記錄要求合法 IPv4)。

受保護記錄:SOA 與平台託管的根 NS(ns1.qn.cx / ns2.qn.cx)不可改刪,改動回傳 403 —— 這是多節點同步的骨架。

DDNS 動態解析

給路由器/腳本/AI 用戶端用的「單呼叫對齊」介面:不用先查再刪再建,一次呼叫即讓記錄與請求值一致。完整教學與用戶端腳本見「DDNS 教學」。

# upsert:调用后该 (name,type) 恰好有一条此值记录;返回 action=created/updated/unchanged
curl -s -X POST https://dns.us.wr.rs/api/v1/ddns \
  -H "Authorization: Bearer dcp_xxxxxxxxxxxxxxxx" \
  -H "Content-Type: application/json" \
  -d '{"zone":"example.com","name":"home","type":"A","value":"203.0.113.7","ttl":60}'

# 查询调用方公网 IP(免鉴权,供 DDNS 客户端取本机出口 IP)
curl -s https://dns.us.wr.rs/api/v1/ddns/ip

ACME DNS-01:給泛網域簽憑證

申請 *.example.com 泛網域憑證時的標準流程(certbot manual 模式 + 本 API 發布 TXT,全程不需要面板):

# 1) 用 certbot manual 模式发起签发,拿到 TXT 挑战值
certbot certonly --manual --preferred-challenges dns \
  -d example.com -d "*.example.com"
# certbot 会显示:_acme-challenge.example.com → TXT 值

# 2) 把挑战值发布到 DNS(无需面板登录;泛域名自动落到 _acme-challenge.example.com;重复提交幂等)
curl -s -X POST https://dns.us.wr.rs/api/v1/acme/dns01 \
  -H "Authorization: Bearer dcp_xxxxxxxxxxxxxxxx" \
  -H "Content-Type: application/json" \
  -d '{"domain":"*.example.com","value":"把certbot给的值粘在这里"}'

# 3) 确认已生效(平台 NS 直查,绕过本地缓存)
dig +short _acme-challenge.example.com @ns1.qn.cx

# 4) 回到 certbot 按回车完成验证;签发完成后清理 TXT
curl -s -X DELETE https://dns.us.wr.rs/api/v1/acme/dns01 \
  -H "Authorization: Bearer dcp_xxxxxxxxxxxxxxxx" \
  -H "Content-Type: application/json" \
  -d '{"domain":"*.example.com"}'

權杖只需 dns01 scope。也適用於 acme.sh manual 模式或任何 ACME 用戶端;一條 TXT 可同時給多台機器完成驗證,簽發完記得清理。

自訂 NS(vanity nameservers)

讓網域用你自己的 NS 主機名(如 ns1.example.com)替代平台預設。區內主機名自動建 glue A;區外主機名需先在其所屬 DNS 指向平台節點 IP(或傳 skip_verify:true 跳過校驗)。視覺化操作見「自訂 NS」頁。

# 添加自定义 NS(区内主机名自动建 glue A;整体提交——任一主机名不合法则全部不生效)
curl -s -X POST https://dns.us.wr.rs/api/v1/zones/example.com/vanity \
  -H "Authorization: Bearer dcp_xxxxxxxxxxxxxxxx" \
  -H "Content-Type: application/json" \
  -d '{"hostnames":["ns1.example.com","ns2.example.com"]}'

# 查看当前自定义 NS 与 glue 状态
curl -s https://dns.us.wr.rs/api/v1/zones/example.com/vanity \
  -H "Authorization: Bearer dcp_xxxxxxxxxxxxxxxx"

# 移除一个(顺带清掉无人引用的 glue)
curl -s -X DELETE https://dns.us.wr.rs/api/v1/zones/example.com/vanity \
  -H "Authorization: Bearer dcp_xxxxxxxxxxxxxxxx" \
  -H "Content-Type: application/json" \
  -d '{"hostname":"ns2.example.com"}'

管理端點(管理員權杖)

稽核日誌與節點管理僅限管理員帳號建立的權杖。節點新增後立即探活,可達性隨回應返回。

curl -s "https://dns.us.wr.rs/api/v1/audit?limit=100" -H "Authorization: Bearer dcp_xxxxxxxxxxxxxxxx"

節點:GET 列表(權杖脫敏)、POST 新增(欄位 name、api_url、api_token、role=primary|secondary、ns_name、public_ip)、DELETE /api/v1/nodes/{id} 刪除。

MCP 接入(AI 用戶端原生)

平台內建 MCP 伺服器(Streamable HTTP):Claude Desktop、Claude Code 等用戶端用一段配置即可原生管理解析,工具與 REST API 一一對應,同一個 API 權杖 權杖、同一套帳號隔離與稽核。

# Claude Code —— 一条命令接入
claude mcp add --transport http dns-control https://dns.us.wr.rs/mcp \
  --header "Authorization: Bearer dcp_xxxxxxxxxxxxxxxx"

// Claude Desktop / 任意支持 Streamable HTTP 的 MCP 客户端
{
  "mcpServers": {
    "dns-control": {
      "type": "http",
      "url": "https://dns.us.wr.rs/mcp",
      "headers": { "Authorization": "Bearer dcp_xxxxxxxxxxxxxxxx" }
    }
  }
}

可用工具:list_zones、create_zone(支援任意子網域)、zone_status、delete_zone、list_records、create/update/delete_record、upsert_record(DDNS)、acme_set_txt / acme_clear_txt、get/add/remove_vanity、dns_health、my_ip。

複製給 AI Agent 的提示語

把下面的整段提示語連同你的權杖一起發給任何 AI Agent(Claude、GPT、本地工具鏈…),它就知道怎麼替你管 DNS:

You manage DNS through the ZoneDeck REST API (managed authoritative DNS).
An MCP server with the same tools is available at https://dns.us.wr.rs/mcp (Streamable HTTP,
same token) — prefer it when the client supports MCP.

Base URL: https://dns.us.wr.rs
Auth: every request needs the header `Authorization: Bearer <TOKEN>` — use the
API token the user provides (format dcp_...). All bodies are JSON.
Responses: success `{"ok":true,...}`; failure `{"ok":false,"error":"message"}` with
HTTP 400 (bad input), 401 (bad/missing token), 403 (missing scope or admin-only
endpoint), 404 (zone not found **or not owned by this token's account**).

ZONES
- GET    /api/v1/zones                      list owned zones (name, healthy, sync state)
- POST   /api/v1/zones                      {"name":"example.com"} create + claim (sync takes minutes)
- GET    /api/v1/zones/example.com          zone health/status
- POST   /api/v1/zones/example.com/repair   idempotent sync/repair
- DELETE /api/v1/zones/example.com          delete on all nodes (destructive — confirm first)

RECORDS  (name accepts "@", "www", FQDN, or "*" wildcard)
- GET    /api/v1/zones/example.com/records
- POST   /api/v1/zones/example.com/records   {"name":"www","type":"A","value":"203.0.113.10","ttl":300}
- PUT    /api/v1/zones/example.com/records   {"old":{...exact existing...},"new":{...}}
- DELETE /api/v1/zones/example.com/records   {"name":"www","type":"A","value":"203.0.113.10"}
Types: A (IPv4), AAAA (IPv6), CNAME (hostname), NS (hostname),
MX (value + priority), TXT (raw text, no extra quotes),
SRV (value=target + priority + weight + port), CAA (value + tag + flags).

DDNS (upsert; A/AAAA/CNAME/TXT only)
- POST /api/v1/ddns    {"zone":"example.com","name":"home","type":"A","value":"203.0.113.7","ttl":60}
  -> {"ok":true,"action":"created|updated|unchanged",...}; zone may be omitted (auto-resolved from name)
- GET  /api/v1/ddns/ip -> the caller's public IP (no auth needed)

ACME DNS-01 (wildcard certificates)
- POST   /api/v1/acme/dns01  {"domain":"*.example.com","value":"<challenge>"} publish TXT (TTL 60, idempotent)
- DELETE /api/v1/acme/dns01  {"domain":"*.example.com"} clear it afterwards

CUSTOM NAMESERVERS
- GET  /api/v1/zones/example.com/vanity
- POST /api/v1/zones/example.com/vanity  {"hostnames":["ns1.example.com","ns2.example.com"]}
- DELETE /api/v1/zones/example.com/vanity {"hostname":"ns2.example.com"}

RULES
- The token sees ONLY the zones of the account that created it; other zones answer 404.
- TTL must be >= 30. Platform apex NS records and SOA are protected (403 if you try).
- Never guess zone names — list first. Confirm with the user before deleting
  anything you did not create in this session.