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.