Panel API
Anything the web UI can do, a script can do too. The manager offers panel API tokens that act like a normal user – including audit, webhooks and multi-server fan-out.
Endpoint base
- Every endpoint starts with
/api/v1. - Responses and bodies are JSON.
- Optional: interactive docs under
/docs, ifDOCS_ENABLED=truein.env.
Authentication
1 · Panel token (recommended for scripts)
As the desired user in the panel: Settings → API & Security → Tokens → New token. The token has prefix dnsmgr_usr_ and is shown once in plain text.
curl -H "Authorization: Bearer dnsmgr_usr_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" \
https://pdns.example.com/api/v1/auth/me 2 · Classic JWT (e.g. after interactive login)
curl -c cookies.txt -X POST "https://pdns.example.com/api/v1/auth/login" \
-F "username=admin" -F "password=secret"
curl -b cookies.txt "https://pdns.example.com/api/v1/auth/me" Cookie name is dns_manager_token, HttpOnly + (with HTTPS) Secure.
3 · ACME token
Restricted to _acme-challenge.* in allowed zones, see ACME docs.
Important endpoints
Servers
# List all registered PowerDNS servers + reachability
GET /api/v1/servers
# Single server detail + statistics
GET /api/v1/servers/master-fra1
GET /api/v1/servers/master-fra1/statistics Zones
# Zones on a server
GET /api/v1/zones/master-fra1
# Detail (incl. rrsets)
GET /api/v1/zones/master-fra1/example.com./detail
# Create
POST /api/v1/zones
{
"name": "example.com",
"kind": "Native",
"nameservers": ["ns1.example.com.", "ns2.example.com."],
"soa_edit_api": "DEFAULT"
}
# Import with diff preview
POST /api/v1/zones/import/preview
POST /api/v1/zones/import
# Trigger NOTIFY
POST /api/v1/zones/master-fra1/example.com./notify Records
# List
GET /api/v1/records/master-fra1/example.com.
# Create / upsert RRSet
POST /api/v1/records/master-fra1/example.com.
{
"name": "www.example.com.",
"type": "A",
"ttl": 300,
"records": [{ "content": "203.0.113.10", "disabled": false }]
}
# Bulk
POST /api/v1/records/master-fra1/example.com./bulk
{
"create": [ ... ],
"delete": [ ... ]
} DNSSEC
GET /api/v1/dnssec/master-fra1/example.com./keys
GET /api/v1/dnssec/master-fra1/example.com./keys/12345
POST /api/v1/dnssec/master-fra1/example.com./enable
POST /api/v1/dnssec/master-fra1/example.com./disable
GET /api/v1/dnssec/master-fra1/example.com./ds Audit
GET /api/v1/audit-log?action=DELETE&resource_type=RECORD&limit=50
GET /api/v1/audit-log/export?max_rows=10000 Settings
GET /api/v1/settings/app-info # Public app info
GET /api/v1/settings/servers
POST /api/v1/settings/servers
PUT /api/v1/settings/servers/{id}
DELETE /api/v1/settings/servers/{id}
POST /api/v1/settings/servers/test
GET /api/v1/settings/servers/{id}/api-key # one-time reveal, audited
GET/PUT /api/v1/settings/smtp
POST /api/v1/settings/smtp/test
POST /api/v1/settings/smtp/test-email
GET/PUT /api/v1/settings/captcha
GET/PUT /api/v1/settings/welcome-email
POST /api/v1/settings/welcome-email/test Example: bulk-create 50 subdomains
for i in $(seq 1 50); do
curl -s -X POST "https://pdns.example.com/api/v1/records/master-fra1/example.com." \
-H "Authorization: Bearer dnsmgr_usr_xxxxx" \
-H "Content-Type: application/json" \
-d "{
\"name\":\"app${i}.example.com.\",
\"type\":\"A\",
\"ttl\":300,
\"records\":[{\"content\":\"203.0.113.${i}\"}]
}"
done Error responses
200 / 201– ok.400– invalid body. Detail indetail.401– missing or wrong token.403– token valid, no permission (e.g. write to a read-only zone).404– zone, record, server or user not found.429– login rate limit (only on/auth/login).500– internal error. Detail stays in the server log; the user gets a friendly message.
Rotate / revoke tokens
In the panel: Settings → API & Security → Tokens – delete button per row. Effective immediately.