Backlink monitor
Are the links you built still there? Watch individual links and whole backlink profiles.
Backlink monitor: plan and usage
GET/api/v1/backlinksScope backlinks:read
The plan, how many links and profiles may be watched, profile refreshes a month included and used, the refreshes your chosen cadences plan for, and how many watched links are live, gone or changed.
Example
curl -s "https://app.pbn.ltd/api/v1/backlinks" \
-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/backlinks", headers=headers, timeout=120)
print(r.status_code, r.json())
const res = await fetch("https://app.pbn.ltd/api/v1/backlinks", {
method: "GET",
headers: {Authorization: `Bearer ${process.env.PBN_API_KEY}`}
});
console.log(res.status, await res.json());
Response
200
{
"data": {
"active": true,
"plan": "Pro",
"paid_until": "2026-10-31",
"links": {
"used": 380,
"limit": 1000
},
"domains": {
"used": 7,
"limit": 10
},
"refreshes_this_month": {
"used": 22,
"limit": 60,
"planned": 30
},
"watched_links": {
"live": 350,
"gone": 18,
"changed": 6,
"pending": 4,
"errors": 2
}
}
}
Errors: rate_limited, scope_missing, unauthorized
List watched links
GET/api/v1/backlinks/linksScope backlinks:read
Every link you watch, problems first.
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
status | query | string (one of: live, lost, changed, pending, error, problem) | no | Only links in this state. "problem" means gone or changed. |
host | query | string | no | Only links from or to this domain (www. ignored). |
search | query | string | no | Part of an address or an anchor. |
limit | query | integer | no | Items per page. Default: 50. |
cursor | query | string | no | next_cursor of the previous page. |
Example
curl -s "https://app.pbn.ltd/api/v1/backlinks/links" \
-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/backlinks/links", headers=headers, timeout=120)
print(r.status_code, r.json())
const res = await fetch("https://app.pbn.ltd/api/v1/backlinks/links", {
method: "GET",
headers: {Authorization: `Bearer ${process.env.PBN_API_KEY}`}
});
console.log(res.status, await res.json());
Response
200
{
"data": [
{
"id": 4120,
"source_url": "https://blog.example.com/post/",
"target_url": "https://mysite.com/page/",
"status": "live",
"problem": "",
"anchor_wanted": "best widgets",
"anchor_found": "best widgets",
"rel": "",
"dofollow": true,
"http_status": 200,
"frequency": "weekly",
"last_checked_at": "2026-09-22T10:00:00Z",
"last_change_at": null,
"first_seen_at": "2026-08-01T10:00:00Z",
"checks": 8,
"hosted_site_id": null
}
],
"next_cursor": null,
"has_more": false
}
Errors: rate_limited, scope_missing, unauthorized
One watched link and its history
GET/api/v1/backlinks/links/{link_id}Scope backlinks:read
The link and up to 100 of its most recent checks.
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
link_id | path | integer | yes | The watched link id. |
Example
curl -s "https://app.pbn.ltd/api/v1/backlinks/links/link_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/backlinks/links/link_id", headers=headers, timeout=120)
print(r.status_code, r.json())
const res = await fetch("https://app.pbn.ltd/api/v1/backlinks/links/link_id", {
method: "GET",
headers: {Authorization: `Bearer ${process.env.PBN_API_KEY}`}
});
console.log(res.status, await res.json());
Response
200
{
"data": {
"id": 4120,
"source_url": "https://blog.example.com/post/",
"target_url": "https://mysite.com/page/",
"status": "live",
"problem": "",
"anchor_wanted": "best widgets",
"anchor_found": "best widgets",
"rel": "",
"dofollow": true,
"http_status": 200,
"frequency": "weekly",
"last_checked_at": "2026-09-22T10:00:00Z",
"last_change_at": null,
"first_seen_at": "2026-08-01T10:00:00Z",
"checks": 8,
"hosted_site_id": null,
"history": [
{
"checked_at": "2026-09-22T10:00:00Z",
"status": "live",
"changed": false,
"anchor": "best widgets",
"rel": "",
"dofollow": true,
"http_status": 200
}
]
}
}
Errors: not_found, rate_limited, scope_missing, unauthorized
Watch links
POST/api/v1/backlinks/linksScope backlinks:write
Adds links with the panel's own rules: anything past the plan's link limit is not added (see not_added). Checking a link costs nothing - we fetch the page ourselves.
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
links | body | array | yes | Up to 2,000 objects: {"source_url": "...", "target_url": "...", "anchor": "optional expected anchor text"}. |
frequency | body | string (one of: daily, weekly, monthly) | no | How often the link is checked. Checking links is included in every plan. Default: weekly. |
Example
curl -s -X POST "https://app.pbn.ltd/api/v1/backlinks/links" \
-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/backlinks/links", headers=headers, timeout=120)
print(r.status_code, r.json())
const res = await fetch("https://app.pbn.ltd/api/v1/backlinks/links", {
method: "POST",
headers: {Authorization: `Bearer ${process.env.PBN_API_KEY}`}
});
console.log(res.status, await res.json());
Response
201
{
"data": {
"added": [
{
"id": 4120,
"source_url": "https://blog.example.com/post/",
"target_url": "https://mysite.com/page/",
"status": "live",
"problem": "",
"anchor_wanted": "best widgets",
"anchor_found": "best widgets",
"rel": "",
"dofollow": true,
"http_status": 200,
"frequency": "weekly",
"last_checked_at": "2026-09-22T10:00:00Z",
"last_change_at": null,
"first_seen_at": "2026-08-01T10:00:00Z",
"checks": 8,
"hosted_site_id": null
}
],
"already_watched": 0,
"invalid": [
{
"url": "not a url",
"reason": "..."
}
],
"not_added": {
"count": 0,
"reason": null
}
}
}
Errors: payment_required, rate_limited, scope_missing, unauthorized, validation_failed
Change how often a link is checked
PATCH/api/v1/backlinks/links/{link_id}Scope backlinks:write
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
link_id | path | integer | yes | The watched link id. |
frequency | body | string (one of: daily, weekly, monthly) | no | How often the link is checked. Checking links is included in every plan. Default: weekly. |
Example
curl -s -X PATCH "https://app.pbn.ltd/api/v1/backlinks/links/link_id" \
-H "Authorization: Bearer $PBN_API_KEY"
import os
import requests
headers = {"Authorization": "Bearer " + os.environ["PBN_API_KEY"]}
r = requests.patch("https://app.pbn.ltd/api/v1/backlinks/links/link_id", headers=headers, timeout=120)
print(r.status_code, r.json())
const res = await fetch("https://app.pbn.ltd/api/v1/backlinks/links/link_id", {
method: "PATCH",
headers: {Authorization: `Bearer ${process.env.PBN_API_KEY}`}
});
console.log(res.status, await res.json());
Response
200
{
"data": {
"id": 4120,
"source_url": "https://blog.example.com/post/",
"target_url": "https://mysite.com/page/",
"status": "live",
"problem": "",
"anchor_wanted": "best widgets",
"anchor_found": "best widgets",
"rel": "",
"dofollow": true,
"http_status": 200,
"frequency": "weekly",
"last_checked_at": "2026-09-22T10:00:00Z",
"last_change_at": null,
"first_seen_at": "2026-08-01T10:00:00Z",
"checks": 8,
"hosted_site_id": null
}
}
Errors: not_found, rate_limited, scope_missing, unauthorized, validation_failed
Stop watching a link
DELETE/api/v1/backlinks/links/{link_id}Scope backlinks:write
Stops watching. Its history is kept and comes back if you add the link again.
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
link_id | path | integer | yes | The watched link id. |
Example
curl -s -X DELETE "https://app.pbn.ltd/api/v1/backlinks/links/link_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/backlinks/links/link_id", headers=headers, timeout=120)
print(r.status_code, r.json())
const res = await fetch("https://app.pbn.ltd/api/v1/backlinks/links/link_id", {
method: "DELETE",
headers: {Authorization: `Bearer ${process.env.PBN_API_KEY}`}
});
console.log(res.status, await res.json());
Response
200
{
"data": {
"deleted": true,
"id": 4120
}
}
Errors: not_found, rate_limited, scope_missing, unauthorized
Check a link now
POST/api/v1/backlinks/links/{link_id}/checkScope backlinks:write
Fetches the page immediately and re-reads the link. Costs nothing and uses no allowance; at most once every 10 minutes per link.
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
link_id | path | integer | yes | The watched link id. |
Example
curl -s -X POST "https://app.pbn.ltd/api/v1/backlinks/links/link_id/check" \
-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/backlinks/links/link_id/check", headers=headers, timeout=120)
print(r.status_code, r.json())
const res = await fetch("https://app.pbn.ltd/api/v1/backlinks/links/link_id/check", {
method: "POST",
headers: {Authorization: `Bearer ${process.env.PBN_API_KEY}`}
});
console.log(res.status, await res.json());
Response
200
{
"data": {
"id": 4120,
"source_url": "https://blog.example.com/post/",
"target_url": "https://mysite.com/page/",
"status": "live",
"problem": "",
"anchor_wanted": "best widgets",
"anchor_found": "best widgets",
"rel": "",
"dofollow": true,
"http_status": 200,
"frequency": "weekly",
"last_checked_at": "2026-09-22T10:00:00Z",
"last_change_at": null,
"first_seen_at": "2026-08-01T10:00:00Z",
"checks": 8,
"hosted_site_id": null
}
}
Errors: not_found, rate_limited, scope_missing, unauthorized
List watched backlink profiles
GET/api/v1/backlinks/domainsScope backlinks:read
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
limit | query | integer | no | Items per page. Default: 50. |
cursor | query | string | no | next_cursor of the previous page. |
Example
curl -s "https://app.pbn.ltd/api/v1/backlinks/domains" \
-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/backlinks/domains", headers=headers, timeout=120)
print(r.status_code, r.json())
const res = await fetch("https://app.pbn.ltd/api/v1/backlinks/domains", {
method: "GET",
headers: {Authorization: `Bearer ${process.env.PBN_API_KEY}`}
});
console.log(res.status, await res.json());
Response
200
{
"data": [
{
"id": 77,
"domain": "mysite.com",
"cadence": "weekly",
"authority": 249,
"backlinks": 881,
"referring_domains": 461,
"dofollow": 820,
"nofollow": 61,
"broken": 635,
"spam_score": 27,
"new_referring_domains": 4,
"lost_referring_domains": 1,
"last_refresh_at": "2026-09-22T03:00:00Z",
"refreshes": 12
}
],
"next_cursor": null,
"has_more": false
}
Errors: rate_limited, scope_missing, unauthorized
One backlink profile
GET/api/v1/backlinks/domains/{domain_id}Scope backlinks:read
The profile with its top referring domains, anchors, linked pages and monthly history. Reads what is stored - it never spends a refresh.
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
domain_id | path | integer | yes | The watched domain id. |
show | query | string (one of: live, new, lost) | no | Which referring domains to return. Default: live. |
Example
curl -s "https://app.pbn.ltd/api/v1/backlinks/domains/domain_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/backlinks/domains/domain_id", headers=headers, timeout=120)
print(r.status_code, r.json())
const res = await fetch("https://app.pbn.ltd/api/v1/backlinks/domains/domain_id", {
method: "GET",
headers: {Authorization: `Bearer ${process.env.PBN_API_KEY}`}
});
console.log(res.status, await res.json());
Response
200
{
"data": {
"id": 77,
"domain": "mysite.com",
"cadence": "weekly",
"authority": 249,
"backlinks": 881,
"referring_domains": [
{
"domain": "news.example",
"authority": 141,
"backlinks": 4,
"dofollow": 4,
"spam_score": 13,
"state": "live"
}
],
"dofollow": 820,
"nofollow": 61,
"broken": 635,
"spam_score": 27,
"new_referring_domains": 4,
"lost_referring_domains": 1,
"last_refresh_at": "2026-09-22T03:00:00Z",
"refreshes": 12,
"anchors": [
{
"anchor": "best widgets",
"backlinks": 36,
"referring_domains": 30
}
],
"top_pages": [
{
"url": "https://mysite.com/",
"backlinks": 400,
"referring_domains": 210
}
],
"history": [
{
"month": "2026-08",
"backlinks": 733,
"referring_domains": 383,
"new_referring_domains": 57,
"lost_referring_domains": 6
}
]
}
}
Errors: not_found, rate_limited, scope_missing, unauthorized
Watch a backlink profile
POST/api/v1/backlinks/domainsScope backlinks:write
Refused when it would pass the plan's domain limit, or when the chosen cadence would plan more refreshes a month than the plan includes.
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
domain | body | string | yes | Any domain. |
cadence | body | string (one of: weekly, monthly, manual) | no | How often the backlink profile is refreshed. A weekly domain uses about 4.3 refreshes a month, monthly 1; "manual" only when you ask. Default: weekly. |
Example
curl -s -X POST "https://app.pbn.ltd/api/v1/backlinks/domains" \
-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/backlinks/domains", headers=headers, timeout=120)
print(r.status_code, r.json())
const res = await fetch("https://app.pbn.ltd/api/v1/backlinks/domains", {
method: "POST",
headers: {Authorization: `Bearer ${process.env.PBN_API_KEY}`}
});
console.log(res.status, await res.json());
Response
201
{
"data": {
"id": 77,
"domain": "mysite.com",
"cadence": "weekly",
"authority": 249,
"backlinks": 881,
"referring_domains": 461,
"dofollow": 820,
"nofollow": 61,
"broken": 635,
"spam_score": 27,
"new_referring_domains": 4,
"lost_referring_domains": 1,
"last_refresh_at": "2026-09-22T03:00:00Z",
"refreshes": 12
}
}
Errors: payment_required, rate_limited, scope_missing, unauthorized, validation_failed
Stop watching a backlink profile
DELETE/api/v1/backlinks/domains/{domain_id}Scope backlinks:write
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
domain_id | path | integer | yes | The watched domain id. |
Example
curl -s -X DELETE "https://app.pbn.ltd/api/v1/backlinks/domains/domain_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/backlinks/domains/domain_id", headers=headers, timeout=120)
print(r.status_code, r.json())
const res = await fetch("https://app.pbn.ltd/api/v1/backlinks/domains/domain_id", {
method: "DELETE",
headers: {Authorization: `Bearer ${process.env.PBN_API_KEY}`}
});
console.log(res.status, await res.json());
Response
200
{
"data": {
"deleted": true,
"id": 77
}
}
Errors: not_found, rate_limited, scope_missing, unauthorized
Refresh a backlink profile now
POST/api/v1/backlinks/domains/{domain_id}/refreshScope backlinks:write
Uses one profile refresh of the monthly allowance, unless a recent shared snapshot of that domain can be reused, in which case it costs nothing. At most once a day per domain.
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
domain_id | path | integer | yes | The watched domain id. |
Example
curl -s -X POST "https://app.pbn.ltd/api/v1/backlinks/domains/domain_id/refresh" \
-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/backlinks/domains/domain_id/refresh", headers=headers, timeout=120)
print(r.status_code, r.json())
const res = await fetch("https://app.pbn.ltd/api/v1/backlinks/domains/domain_id/refresh", {
method: "POST",
headers: {Authorization: `Bearer ${process.env.PBN_API_KEY}`}
});
console.log(res.status, await res.json());
Response
200
{
"data": {
"id": 77,
"domain": "mysite.com",
"cadence": "weekly",
"authority": 249,
"backlinks": 881,
"referring_domains": 461,
"dofollow": 820,
"nofollow": 61,
"broken": 635,
"spam_score": 27,
"new_referring_domains": 4,
"lost_referring_domains": 1,
"last_refresh_at": "2026-09-22T03:00:00Z",
"refreshes": 12
}
}
Errors: not_found, rate_limited, scope_missing, unauthorized, unavailable