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
Sets how often this one link is re-checked (daily, weekly or monthly) and schedules its next check to match. The answer is the link with its new frequency.
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 · destructive
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
Every domain whose backlink profile you watch, most recently added first, with its latest totals (backlinks, referring domains, referring domains won and lost in the last 30 days) and when it was last refreshed. Reads what is stored - it never spends a refresh.
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 · destructive
Stops watching the profile: no more scheduled refreshes, and it no longer counts towards your plan. Nothing is charged.
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