PBN.LTD API docs
View as Markdown

Domain vetting

Check a domain before you buy it, and get told when a new aged domain matches a search you saved.

Domain vetting: credits and usage

GET/api/v1/domain-vetting

Scope vetting:read

How many report credits this account holds, how many reports it has run, and the prices.

Example

curl -s "https://app.pbn.ltd/api/v1/domain-vetting" \
  -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/domain-vetting", headers=headers, timeout=120)
print(r.status_code, r.json())
const res = await fetch("https://app.pbn.ltd/api/v1/domain-vetting", {
  method: "GET",
  headers: {Authorization: `Bearer ${process.env.PBN_API_KEY}`}
});
console.log(res.status, await res.json());

Response

200

{
  "data": {
    "credits": 7,
    "unlimited": false,
    "reports": 12,
    "price_per_report_from": "1.38",
    "free_with_every_aged_domain": 1
  }
}

Errors: rate_limited, scope_missing, unauthorized

List your vetting reports

GET/api/v1/domain-vetting/reports

Scope vetting:read

Every vetting report this account has run, newest first, with its verdict and score.

Parameters

NameInTypeRequiredDescription
verdictquerystring (one of: clean, care, risk)noOnly reports with this verdict.
searchquerystringnoPart of the domain name.
limitqueryintegernoItems per page. Default: 50.
cursorquerystringnonext_cursor of the previous page.

Example

curl -s "https://app.pbn.ltd/api/v1/domain-vetting/reports" \
  -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/domain-vetting/reports", headers=headers, timeout=120)
print(r.status_code, r.json())
const res = await fetch("https://app.pbn.ltd/api/v1/domain-vetting/reports", {
  method: "GET",
  headers: {Authorization: `Bearer ${process.env.PBN_API_KEY}`}
});
console.log(res.status, await res.json());

Response

200

{
  "data": [
    {
      "id": 51,
      "domain": "example.com",
      "state": "ready",
      "score": 68,
      "verdict": "care",
      "created_at": "2026-09-22T10:00:00Z"
    }
  ],
  "next_cursor": null,
  "has_more": false
}

Errors: rate_limited, scope_missing, unauthorized

One vetting report

GET/api/v1/domain-vetting/reports/{report_id}

Scope vetting:read

The whole report: the verdict, every reason, the key numbers, the anchor texts, the link and traffic history and what the site was in the web archive.

Parameters

NameInTypeRequiredDescription
report_idpathintegeryesThe report id.

Example

curl -s "https://app.pbn.ltd/api/v1/domain-vetting/reports/report_id" \
  -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/domain-vetting/reports/report_id", headers=headers, timeout=120)
print(r.status_code, r.json())
const res = await fetch("https://app.pbn.ltd/api/v1/domain-vetting/reports/report_id", {
  method: "GET",
  headers: {Authorization: `Bearer ${process.env.PBN_API_KEY}`}
});
console.log(res.status, await res.json());

Response

200

{
  "data": {
    "id": 51,
    "domain": "example.com",
    "state": "ready",
    "score": 68,
    "verdict": "care",
    "created_at": "2026-09-22T10:00:00Z",
    "credits_used": 1,
    "summary": "Proceed with care (68/100). Read the reasons below before you buy.",
    "reasons": [
      {
        "weight": -12,
        "text": "Raised spam score (41/100): ...",
        "area": "links"
      }
    ],
    "facts": {
      "referring_domains": 177,
      "backlinks": 23794,
      "spam_score": 40,
      "keywords": 0,
      "traffic": 0,
      "indexed": false,
      "archived_from": "2019-01",
      "registered": "2018-11-02",
      "expires": "2026-11-02"
    }
  }
}

Errors: not_found, rate_limited, scope_missing, unauthorized

Vet a domain

POST/api/v1/domain-vetting/reports

Scope vetting:write

Runs a full report and returns it. Spends one report credit, unless you already vetted this domain recently - then the report you already have comes back and nothing is charged.

Parameters

NameInTypeRequiredDescription
domainbodystringyesThe domain to vet, e.g. example.com.
location_codebodyintegernoThe market its search data is read for (2840 = United States). Default: 2840.

Example

curl -s -X POST "https://app.pbn.ltd/api/v1/domain-vetting/reports" \
  -H "Authorization: Bearer $PBN_API_KEY"
import os
import requests

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

Response

201

{
  "data": {
    "id": 51,
    "domain": "example.com",
    "state": "ready",
    "score": 68,
    "verdict": "care",
    "created_at": "2026-09-22T10:00:00Z",
    "credits_used": 1,
    "summary": "Proceed with care (68/100). Read the reasons below before you buy.",
    "reasons": [
      {
        "weight": -12,
        "text": "Raised spam score (41/100): ...",
        "area": "links"
      }
    ],
    "facts": {
      "referring_domains": 177,
      "backlinks": 23794,
      "spam_score": 40,
      "keywords": 0,
      "traffic": 0,
      "indexed": false,
      "archived_from": "2019-01",
      "registered": "2018-11-02",
      "expires": "2026-11-02"
    }
  }
}

Errors: payment_required, rate_limited, scope_missing, unauthorized, validation_failed

List your saved domain searches

GET/api/v1/domain-alerts

Scope vetting:read

Every aged-domain search you saved, what it looks for and how many domains match it now.

Example

curl -s "https://app.pbn.ltd/api/v1/domain-alerts" \
  -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/domain-alerts", headers=headers, timeout=120)
print(r.status_code, r.json())
const res = await fetch("https://app.pbn.ltd/api/v1/domain-alerts", {
  method: "GET",
  headers: {Authorization: `Bearer ${process.env.PBN_API_KEY}`}
});
console.log(res.status, await res.json());

Response

200

{
  "data": [
    {
      "id": 9,
      "name": "DR 30+ finance .com",
      "filters": "TLD .com, Ahrefs DR at least 30",
      "active": true,
      "matching_now": 14,
      "last_email": "2026-09-21T06:15:00Z"
    }
  ]
}

Errors: rate_limited, scope_missing, unauthorized

Save a domain search

POST/api/v1/domain-alerts

Scope vetting:write

Domains matching it today are the starting point, not news: from now on you get an e-mail when a NEW one matches.

Parameters

NameInTypeRequiredDescription
namebodystringnoWhat to call it (we name it after the filters if empty).
filtersbodystringnoThe aged-domain list's own filter, as a query string, e.g. "tld=.com&dr_min=30&price_max=300".

Example

curl -s -X POST "https://app.pbn.ltd/api/v1/domain-alerts" \
  -H "Authorization: Bearer $PBN_API_KEY"
import os
import requests

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

Response

201

{
  "data": {
    "id": 9,
    "name": "DR 30+ .com",
    "filters": "TLD .com, Ahrefs DR at least 30",
    "matching_now": 14
  }
}

Errors: payment_required, rate_limited, scope_missing, unauthorized, validation_failed

The domains a saved search matches now

GET/api/v1/domain-alerts/{alert_id}/matches

Scope vetting:read

The aged domains this saved search matches at this moment, with the price you would pay and a link to each listing.

Parameters

NameInTypeRequiredDescription
alert_idpathintegeryesThe saved search id.
limitqueryintegernoHow many to return. Default: 50.

Example

curl -s "https://app.pbn.ltd/api/v1/domain-alerts/alert_id/matches" \
  -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/domain-alerts/alert_id/matches", headers=headers, timeout=120)
print(r.status_code, r.json())
const res = await fetch("https://app.pbn.ltd/api/v1/domain-alerts/alert_id/matches", {
  method: "GET",
  headers: {Authorization: `Bearer ${process.env.PBN_API_KEY}`}
});
console.log(res.status, await res.json());

Response

200

{
  "data": [
    {
      "domain": "example.com",
      "price_usd": "129.00",
      "dr": 34,
      "referring_domains": 212,
      "monthly_traffic": 900,
      "listing_url": "https://app.pbn.ltd/domains/domain/1234"
    }
  ]
}

Errors: not_found, rate_limited, scope_missing, unauthorized

Delete a saved search

DELETE/api/v1/domain-alerts/{alert_id}

Scope vetting:write · destructive

Deletes the saved search and stops its e-mails. What it already told you about is forgotten with it.

Parameters

NameInTypeRequiredDescription
alert_idpathintegeryesThe saved search id.

Example

curl -s -X DELETE "https://app.pbn.ltd/api/v1/domain-alerts/alert_id" \
  -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/domain-alerts/alert_id", headers=headers, timeout=120)
print(r.status_code, r.json())
const res = await fetch("https://app.pbn.ltd/api/v1/domain-alerts/alert_id", {
  method: "DELETE",
  headers: {Authorization: `Bearer ${process.env.PBN_API_KEY}`}
});
console.log(res.status, await res.json());

Response

200

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

Errors: not_found, rate_limited, scope_missing, unauthorized