PBN.LTD API docs
View as Markdown

DNS records

The site's own DNS records (A, AAAA, CNAME, TXT, MX, SRV, CAA, NS).

Nameserver status

GET/api/v1/sites/{site_id}/nameservers

Scope dns:read

The nameservers the domain must use (required), what it uses now (current, checked daily), whether it is pointed, whether the DNS zone expired at the provider (zone_expired: re-create it from the site page), and the registrar autopilot status when a registrar connection sets them for you.

Parameters

NameInTypeRequiredDescription
site_idpathintegeryesThe site id (see GET /sites).

Example

curl -s "https://app.pbn.ltd/api/v1/sites/123/nameservers" \
  -H "Authorization: Bearer $PBN_API_KEY"
import os
import requests

headers = {"Authorization": "Bearer " + os.environ["PBN_API_KEY"]}
r = requests.get("https://app.pbn.ltd/api/v1/sites/123/nameservers", headers=headers, timeout=120)
print(r.status_code, r.json())
const res = await fetch("https://app.pbn.ltd/api/v1/sites/123/nameservers", {
  method: "GET",
  headers: {Authorization: `Bearer ${process.env.PBN_API_KEY}`}
});
console.log(res.status, await res.json());

Response

200

{
  "data": {
    "current": [
      "ada.ns.cloudflare.com",
      "bob.ns.cloudflare.com"
    ],
    "required": [
      "ada.ns.cloudflare.com",
      "bob.ns.cloudflare.com"
    ],
    "pointed": true,
    "main_cloud": false,
    "zone_expired": false,
    "dns_provider": "Cloudflare",
    "checked_at": "2026-09-19T13:25:00Z",
    "autopilot": null
  }
}

Errors: not_found, rate_limited, scope_missing, unauthorized

List DNS records

GET/api/v1/sites/{site_id}/dns

Scope dns:read

The site's own DNS records (the DNS records tab), and the publishing state: the DNS provider, when the records were last published and any record the provider refused (with its error). Records the platform manages for the CDN are not listed and are never changed through this API.

Parameters

NameInTypeRequiredDescription
site_idpathintegeryesThe site id (see GET /sites).

Example

curl -s "https://app.pbn.ltd/api/v1/sites/123/dns" \
  -H "Authorization: Bearer $PBN_API_KEY"
import os
import requests

headers = {"Authorization": "Bearer " + os.environ["PBN_API_KEY"]}
r = requests.get("https://app.pbn.ltd/api/v1/sites/123/dns", headers=headers, timeout=120)
print(r.status_code, r.json())
const res = await fetch("https://app.pbn.ltd/api/v1/sites/123/dns", {
  method: "GET",
  headers: {Authorization: `Bearer ${process.env.PBN_API_KEY}`}
});
console.log(res.status, await res.json());

Response

200

{
  "data": {
    "records": [
      {
        "id": 5501,
        "type": "MX",
        "name": "@",
        "value": "10 mail.example.com",
        "proxied": false,
        "updated_at": "2026-09-19T10:00:00Z",
        "parts": {
          "priority": 10,
          "target": "mail.example.com"
        }
      }
    ],
    "publishing": {
      "provider": "Cloudflare",
      "errors": [],
      "last_synced_at": "2026-09-19T10:01:00Z"
    }
  }
}

Errors: not_found, rate_limited, scope_missing, unauthorized

Add a DNS record

POST/api/v1/sites/{site_id}/dns

Scope dns:write

Adds a record with the panel's own validation. It is published to the site's DNS provider within a minute or two (follow the job); your records are never overwritten by the platform.

Parameters

NameInTypeRequiredDescription
site_idpathintegeryesThe site id (see GET /sites).
typebodystring (one of: A, AAAA, CNAME, TXT, MX, SRV, CAA, NS)yesRecord type.
namebodystringyes"@" for the domain itself, or a name like blog, shop.eu, _dmarc, _sip._tcp.
valuebodystringyesIPv4 (A), IPv6 (AAAA), host name (CNAME, MX, SRV target, NS), text (TXT) or CA domain (CAA).
prioritybodyintegernoMX and SRV.
weightbodyintegernoSRV.
portbodyintegernoSRV.
caa_flagsbodyinteger (one of: 0, 128)noCAA: 0 or 128 (critical).
caa_tagbodystring (one of: issue, issuewild, iodef)noCAA tag.
proxiedbodybooleannoCloudflare only, A/AAAA/CNAME: proxy through the CDN (off = DNS only).

Example

curl -s -X POST "https://app.pbn.ltd/api/v1/sites/123/dns" \
  -H "Authorization: Bearer $PBN_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"type": "TXT", "name": "@", "value": "google-site-verification=abc123"}'
import os
import requests

headers = {"Authorization": "Bearer " + os.environ["PBN_API_KEY"]}
r = requests.post("https://app.pbn.ltd/api/v1/sites/123/dns", headers=headers, json={"type": "TXT", "name": "@", "value": "google-site-verification=abc123"}, timeout=120)
print(r.status_code, r.json())
const res = await fetch("https://app.pbn.ltd/api/v1/sites/123/dns", {
  method: "POST",
  headers: {Authorization: `Bearer ${process.env.PBN_API_KEY}`, "Content-Type": "application/json"},
  body: JSON.stringify({"type": "TXT", "name": "@", "value": "google-site-verification=abc123"})
});
console.log(res.status, await res.json());

Response

201

{
  "data": {
    "id": 5501,
    "type": "MX",
    "name": "@",
    "value": "10 mail.example.com",
    "proxied": false,
    "updated_at": "2026-09-19T10:00:00Z",
    "parts": {
      "priority": 10,
      "target": "mail.example.com"
    }
  }
}

Errors: conflict, not_found, rate_limited, scope_missing, unauthorized, validation_failed

Change a DNS record

PATCH/api/v1/sites/{site_id}/dns/{record_id}

Scope dns:write

Changes a record; send only the fields that change.

Parameters

NameInTypeRequiredDescription
site_idpathintegeryesThe site id (see GET /sites).
record_idpathintegeryesThe DNS record id.
typebodystring (one of: A, AAAA, CNAME, TXT, MX, SRV, CAA, NS)noRecord type.
namebodystringno"@" for the domain itself, or a name like blog, shop.eu, _dmarc, _sip._tcp.
valuebodystringnoIPv4 (A), IPv6 (AAAA), host name (CNAME, MX, SRV target, NS), text (TXT) or CA domain (CAA).
prioritybodyintegernoMX and SRV.
weightbodyintegernoSRV.
portbodyintegernoSRV.
caa_flagsbodyinteger (one of: 0, 128)noCAA: 0 or 128 (critical).
caa_tagbodystring (one of: issue, issuewild, iodef)noCAA tag.
proxiedbodybooleannoCloudflare only, A/AAAA/CNAME: proxy through the CDN (off = DNS only).

Example

curl -s -X PATCH "https://app.pbn.ltd/api/v1/sites/123/dns/5501" \
  -H "Authorization: Bearer $PBN_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"value": "google-site-verification=xyz789"}'
import os
import requests

headers = {"Authorization": "Bearer " + os.environ["PBN_API_KEY"]}
r = requests.patch("https://app.pbn.ltd/api/v1/sites/123/dns/5501", headers=headers, json={"value": "google-site-verification=xyz789"}, timeout=120)
print(r.status_code, r.json())
const res = await fetch("https://app.pbn.ltd/api/v1/sites/123/dns/5501", {
  method: "PATCH",
  headers: {Authorization: `Bearer ${process.env.PBN_API_KEY}`, "Content-Type": "application/json"},
  body: JSON.stringify({"value": "google-site-verification=xyz789"})
});
console.log(res.status, await res.json());

Response

200

{
  "data": {
    "id": 5501,
    "type": "MX",
    "name": "@",
    "value": "10 mail.example.com",
    "proxied": false,
    "updated_at": "2026-09-19T10:00:00Z",
    "parts": {
      "priority": 10,
      "target": "mail.example.com"
    }
  }
}

Errors: not_found, rate_limited, scope_missing, unauthorized, validation_failed

Delete a DNS record

DELETE/api/v1/sites/{site_id}/dns/{record_id}

Scope dns:write

Deletes a record; it is removed at the DNS provider within a minute or two.

Parameters

NameInTypeRequiredDescription
site_idpathintegeryesThe site id (see GET /sites).
record_idpathintegeryesThe DNS record id.

Example

curl -s -X DELETE "https://app.pbn.ltd/api/v1/sites/123/dns/5501" \
  -H "Authorization: Bearer $PBN_API_KEY"
import os
import requests

headers = {"Authorization": "Bearer " + os.environ["PBN_API_KEY"]}
r = requests.delete("https://app.pbn.ltd/api/v1/sites/123/dns/5501", headers=headers, timeout=120)
print(r.status_code, r.json())
const res = await fetch("https://app.pbn.ltd/api/v1/sites/123/dns/5501", {
  method: "DELETE",
  headers: {Authorization: `Bearer ${process.env.PBN_API_KEY}`}
});
console.log(res.status, await res.json());

Response

200

{
  "data": {
    "deleted": true,
    "id": 5501
  }
}

Errors: not_found, rate_limited, scope_missing, unauthorized