This document is about PowerDNS 4.X. If you have PowerDNS 3.X, please see the PowerDNS 3.X documentation

PowerDNS API

PowerDNS features a built-in API. For the Authoritative Server, starting with version 3.4, for the Recursor starting with version 3.6.

In 3.x, all of the API was considered experimental and authentication initially used the standard webserver password. On 4.x, a static API key is used (see below).

Try it

Install PowerDNS Authoritative with one of the gsql backends (i.e. MySQL, PostgreSQL or SQLite3).

Then configure as follows:

api=yes
api-key=changeme
# Needed before 4.1.0
webserver=yes

After restarting pdns_server, the following examples should start working:

# List zones
curl -H 'X-API-Key: changeme' http://127.0.0.1:8081/api/v1/servers/localhost/zones | jq .

# Create new zone "example.org" with nameservers ns1.example.org, ns2.example.org
curl -X POST --data '{"name":"example.org.", "kind": "Native", "masters": [], "nameservers": ["ns1.example.org.", "ns2.example.org."]}' -v -H 'X-API-Key: changeme' http://127.0.0.1:8081/api/v1/servers/localhost/zones | jq .

# Show the new zone
curl -H 'X-API-Key: changeme' http://127.0.0.1:8081/api/v1/servers/localhost/zones/example.org. | jq .

# Add a new record to the new zone (would replace any existing test.example.org/A records)
curl -X PATCH --data '{"rrsets": [ {"name": "test.example.org.", "type": "A", "ttl": 86400, "changetype": "REPLACE", "records": [ {"content": "192.0.5.4", "disabled": false } ] } ] }' -H 'X-API-Key: changeme' http://127.0.0.1:8081/api/v1/servers/localhost/zones/example.org. | jq .

# Combined replacement of multiple RRsets
curl -X PATCH --data '{"rrsets": [
  {"name": "test1.example.org.",
   "type": "A",
   "ttl": 86400,
   "changetype": "REPLACE",
   "records": [ {"content": "192.0.2.5", "disabled": false} ]
  },
  {"name": "test2.example.org.",
   "type": "AAAA",
   "ttl": 86400,
   "changetype": "REPLACE",
   "records": [ {"content": "2001:db8::6", "disabled": false} ]
  }
  ] }' -H 'X-API-Key: changeme' http://127.0.0.1:8081/api/v1/servers/localhost/zones/example.org. | jq .

jq is a highly recommended tool for pretty-printing JSON. If you don't have jq, try json_pp or python -mjson.tool instead.

When running multiple instances you might want to specify on which address the web server should run:

# IP Address of web server to listen on
webserver-address=127.0.0.1
# Port of web server to listen on
webserver-port=8081
# Web server access is only allowed from these subnets
webserver-allow-from=0.0.0.0/0,::/0

Try it (Recursor edition)

Install PowerDNS Recursor, configured as follows:

webserver=yes
api-key=changeme
auth-zones=
forward-zones=
forward-zones-recurse=

After restarting pdns_recursor, the following examples should start working:

curl -v -H 'X-API-Key: changeme' http://127.0.0.1:8082/api/v1/servers/localhost | jq .
curl -v -H 'X-API-Key: changeme' http://127.0.0.1:8082/api/v1/servers/localhost/zones | jq .

API Specification

The complete API docs are available in api_spec.md.

Additional help

For additional help, come to the #powerdns IRC channel on irc.oftc.net.

Examples (Authoritative Server)

Show zone information and records

curl -H 'X-API-Key: changeme' \
    http://127.0.0.1:8081/api/v1/servers/localhost/zones/example.org. | jq .

Response:

{
  "id": "example.org.",
  "url": "api/v1/servers/localhost/zones/example.org.",
  "name": "example.org.",
  "kind": "Master",
  "dnssec": false,
  "account": "",
  "masters": [],
  "serial": 2015120401,
  "notified_serial": 0,
  "last_check": 0,
  "soa_edit_api": "",
  "soa_edit": "",
  "rrsets": [
    {
      "comments": [],
      "name": "example.org.",
      "records": [
        {
          "content": "ns2.example.org.",
          "disabled": false
        },
        {
          "content": "ns1.example.org.",
          "disabled": false
        }
      ],
      "ttl": 86400,
      "type": "NS"
    },
    {
      "comments": [],
      "name": "example.org.",
      "type": "SOA",
      "ttl": 86400,
      "records": [
        {
          "disabled": false,
          "content": "ns1.example.org. hostmaster.example.org. 2015120401 10800 15 604800 10800"
        }
      ]
    },
    {
      "comments": [],
      "name": "ns1.example.org.",
      "type": "A",
      "ttl": 86400,
      "records": [
        {
          "content": "192.168.0.1",
          "disabled": false
        }
      ]
    },
    {
      "comments": [],
      "name": "www.example.org.",
      "type": "A",
      "ttl": 86400,
      "records": [
        {
          "disabled": false,
          "content": "192.168.0.2"
        }
      }
    }
  ]
}

Replace ns1.example.org

Based on the example.org zone above, replace the ns1.example.org A record with 192.0.2.5:

curl -X PATCH --data '{"rrsets": [{
  "name": "ns1.example.org.",
  "type": "A",
  "changetype": "REPLACE",
  "records": [ {
    "content": "192.0.2.5",
    "disabled": false,
    "name": "ns1.example.org.",
    "ttl": 86400,
    "type": "A"
  }]
}]}' -H 'X-API-Key: changeme' \
http://127.0.0.1:8081/api/v1/servers/localhost/zones/example.org. | jq .

Response:

{
  "id": "example.org.",
  ...
  "records": [
    {
      "name": "ns1.example.org.",
      "type": "A",
      "ttl": 86400,
      "disabled": false,
      "content": "192.0.2.5"
    },
    ...
  ],
  ...
}