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(等同於不存在)。
權限範圍(scope)
| 所需 scope | 說明 |
|---|---|
zones:read | 列出、檢視自己名下的網域 |
zones:write | 新增、刪除網域 |
records:read | 讀取解析記錄與自訂 NS 狀態 |
records:write | 增刪改解析記錄、DDNS、自訂 NS |
dns01 | ACME 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/zones | zones:read | 列出自己名下的網域;管理員權杖加 ?all=1 列全平台(含歸屬) |
POST | /api/v1/zones | zones:write | 新增網域並歸屬目前帳號(全節點自動同步,需幾分鐘) |
GET | /api/v1/zones/{zone} | zones:read | 檢視網域健康狀態(主/從、SOA 序號一致性) |
POST | /api/v1/zones/{zone}/repair | repair | 同步修復(冪等,可反覆呼叫直到 healthy) |
DELETE | /api/v1/zones/{zone} | zones:write | 刪除網域(主從節點一併刪除,危險操作) |
GET | /api/v1/zones/{zone}/records | records:read | 列出全部解析記錄 |
POST | /api/v1/zones/{zone}/records | records:write | 新增解析記錄 |
PUT | /api/v1/zones/{zone}/records | records:write | 修改記錄:body 為 {"old":{…現有記錄…},"new":{…}} |
DELETE | /api/v1/zones/{zone}/records | records:write | 刪除記錄:body 為要刪的那條記錄(精確匹配) |
GET | /api/v1/zones/{zone}/vanity | records:read | 檢視自訂 NS 與 glue 狀態 |
POST | /api/v1/zones/{zone}/vanity | records:write | 新增自訂 NS(hostnames 陣列;整體生效,任一非法則全部不寫入) |
DELETE | /api/v1/zones/{zone}/vanity | records:write | 移除一個自訂 NS(順帶清理無人引用的 glue) |
POST | /api/v1/ddns | records:write | DDNS upsert:呼叫後該記錄恰好等於請求值,回傳 action=created/updated/unchanged |
POST | /api/v1/acme/dns01 | dns01 | 發布 _acme-challenge TXT(TTL 60,冪等;泛網域自動落到主網域) |
DELETE | /api/v1/acme/dns01 | dns01 | 清理 _acme-challenge TXT(可按 value 精確清理) |
GET | /api/v1/audit | zones:read+admin | 稽核日誌(?limit=&user=&action= 過濾) |
GET/POST/DELETE | /api/v1/nodes | nodes: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"}'
各類型必填欄位
| 類型 | 說明 | 欄位 |
|---|---|---|
A | IPv4 位址 | value |
AAAA | IPv6 位址 | value |
CNAME | 目標主機名(不能與 A 並存) | value |
NS | 目標主機名 | value |
MX | 郵件伺服器主機名 + 優先級 | value + priority |
TXT | 文字內容(直接貼原文,不用自己加引號) | value |
SRV | 目標主機名 + priority/weight/port | value + priority + weight + port |
CAA | 值 + tag(issue/issuewild/iodef)+ flags | value + 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.