# 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 /domain-vetting` · scope `vetting:read`

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

### Example

```bash
curl -s "https://app.pbn.ltd/api/v1/domain-vetting" \
  -H "Authorization: Bearer $PBN_API_KEY"
```

```python
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())
```

```javascript
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`

```json
{
  "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 /domain-vetting/reports` · scope `vetting:read`

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

### Parameters

| Name | In | Type | Required | Description |
|---|---|---|---|---|
| `verdict` | query | string (one of: clean, care, risk) | no | Only reports with this verdict. |
| `search` | query | string | no | Part of the domain name. |
| `limit` | query | integer | no | Items per page. Default: `50`. |
| `cursor` | query | string | no | next_cursor of the previous page. |

### Example

```bash
curl -s "https://app.pbn.ltd/api/v1/domain-vetting/reports" \
  -H "Authorization: Bearer $PBN_API_KEY"
```

```python
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())
```

```javascript
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`

```json
{
  "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 /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

| Name | In | Type | Required | Description |
|---|---|---|---|---|
| `report_id` | path | integer | yes | The report id. |

### Example

```bash
curl -s "https://app.pbn.ltd/api/v1/domain-vetting/reports/report_id" \
  -H "Authorization: Bearer $PBN_API_KEY"
```

```python
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())
```

```javascript
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`

```json
{
  "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 /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

| Name | In | Type | Required | Description |
|---|---|---|---|---|
| `domain` | body | string | yes | The domain to vet, e.g. example.com. |
| `location_code` | body | integer | no | The market its search data is read for (2840 = United States). Default: `2840`. |

### Example

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

```python
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())
```

```javascript
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`

```json
{
  "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 /domain-alerts` · scope `vetting:read`

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

### Example

```bash
curl -s "https://app.pbn.ltd/api/v1/domain-alerts" \
  -H "Authorization: Bearer $PBN_API_KEY"
```

```python
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())
```

```javascript
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`

```json
{
  "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 /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

| Name | In | Type | Required | Description |
|---|---|---|---|---|
| `name` | body | string | no | What to call it (we name it after the filters if empty). |
| `filters` | body | string | no | The aged-domain list's own filter, as a query string, e.g. "tld=.com&dr_min=30&price_max=300". |

### Example

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

```python
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())
```

```javascript
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`

```json
{
  "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 /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

| Name | In | Type | Required | Description |
|---|---|---|---|---|
| `alert_id` | path | integer | yes | The saved search id. |
| `limit` | query | integer | no | How many to return. Default: `50`. |

### Example

```bash
curl -s "https://app.pbn.ltd/api/v1/domain-alerts/alert_id/matches" \
  -H "Authorization: Bearer $PBN_API_KEY"
```

```python
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())
```

```javascript
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`

```json
{
  "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 /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

| Name | In | Type | Required | Description |
|---|---|---|---|---|
| `alert_id` | path | integer | yes | The saved search id. |

### Example

```bash
curl -s -X DELETE "https://app.pbn.ltd/api/v1/domain-alerts/alert_id" \
  -H "Authorization: Bearer $PBN_API_KEY"
```

```python
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())
```

```javascript
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`

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

Errors: `not_found`, `rate_limited`, `scope_missing`, `unauthorized`
