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.