SEO metrics and backlinks
The SEO figures measured for each site, and the backlink tracker with its bulk link editor.
SEO metrics history of a site
GET/api/v1/sites/{site_id}/seo-metricsScope sites:read
The same figures as the site's SEO metrics charts tab: Trust Flow, Citation Flow, backlinks and referring domains at every reading, with the change since the reading before. latest is null until the first reading.
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
site_id | path | integer | yes | The site id (see GET /sites). |
limit | query | integer | no | How many readings, newest first. Default: 90. |
Example
curl -s "https://app.pbn.ltd/api/v1/sites/123/seo-metrics" \
-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/seo-metrics", headers=headers, timeout=120)
print(r.status_code, r.json())
const res = await fetch("https://app.pbn.ltd/api/v1/sites/123/seo-metrics", {
method: "GET",
headers: {Authorization: `Bearer ${process.env.PBN_API_KEY}`}
});
console.log(res.status, await res.json());
Response
200
{
"data": {
"site_id": 123,
"latest": {
"measured_at": "2026-09-20T03:10:00Z",
"trust_flow": 21,
"citation_flow": 30,
"backlinks": 1840,
"referring_domains": 212,
"trust_flow_change": 1,
"citation_flow_change": 0,
"backlinks_change": 35,
"referring_domains_change": 4
},
"history": [
{
"measured_at": "2026-09-20T03:10:00Z",
"trust_flow": 21,
"citation_flow": 30,
"backlinks": 1840,
"referring_domains": 212,
"trust_flow_change": 1,
"citation_flow_change": 0,
"backlinks_change": 35,
"referring_domains_change": 4
}
]
}
}
Errors: not_found, rate_limited, scope_missing, unauthorized
Domains your posts link to
GET/api/v1/backlink-trackerScope sites:read
The backlink tracker: every domain the posts on your sites link to, with how many links, posts and sites carry them (your_site_id when the domain is one of your own sites).
Example
curl -s "https://app.pbn.ltd/api/v1/backlink-tracker" \
-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/backlink-tracker", headers=headers, timeout=120)
print(r.status_code, r.json())
const res = await fetch("https://app.pbn.ltd/api/v1/backlink-tracker", {
method: "GET",
headers: {Authorization: `Bearer ${process.env.PBN_API_KEY}`}
});
console.log(res.status, await res.json());
Response
200
{
"data": [
{
"id": 77,
"domain": "money-site.com",
"your_site_id": null,
"links": 41,
"posts": 38,
"sites": 12
}
]
}
Errors: rate_limited, scope_missing, unauthorized
Every link to one domain
GET/api/v1/backlink-tracker/{domain_id}Scope sites:read
One backlink domain: each distinct link to it (address + text) with how many times, posts and sites carry it, and which of your sites each address is found on. A link id is what the link editor endpoints take.
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
domain_id | path | integer | yes | The backlink domain id (see GET /backlink-tracker). |
Example
curl -s "https://app.pbn.ltd/api/v1/backlink-tracker/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/backlink-tracker/domain_id", headers=headers, timeout=120)
print(r.status_code, r.json())
const res = await fetch("https://app.pbn.ltd/api/v1/backlink-tracker/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": "money-site.com",
"your_site_id": null,
"links": [
{
"id": 9031,
"url": "https://money-site.com/page",
"text": "best widgets",
"anchor": "<a href=\"https://money-site.com/page\">best widgets</a>",
"links": 6,
"posts": 5,
"sites": 3
}
],
"posts": 38,
"sites": 12,
"found_on": [
{
"url": "https://money-site.com/page",
"site_id": 123,
"site_domain": "example.com"
}
]
}
}
Errors: not_found, rate_limited, scope_missing, unauthorized
Change a link everywhere
PATCH/api/v1/backlink-tracker/links/{anchor_id}Scope content:write
The bulk link editor's "Edit": the link is searched and replaced in the posts of every site that carries it (one job per site, in each site's operations log).
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
anchor_id | path | integer | yes | The link id (see GET /backlink-tracker/{domain_id}). |
url | body | string | no | The new address (default: unchanged). |
text | body | string | no | The new link text (default: unchanged). |
Example
curl -s -X PATCH "https://app.pbn.ltd/api/v1/backlink-tracker/links/anchor_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/backlink-tracker/links/anchor_id", headers=headers, timeout=120)
print(r.status_code, r.json())
const res = await fetch("https://app.pbn.ltd/api/v1/backlink-tracker/links/anchor_id", {
method: "PATCH",
headers: {Authorization: `Bearer ${process.env.PBN_API_KEY}`}
});
console.log(res.status, await res.json());
Response
202
{
"data": {
"queued": true,
"sites": 3
}
}
Errors: not_found, rate_limited, scope_missing, unauthorized, validation_failed
Remove a link everywhere
DELETE/api/v1/backlink-tracker/links/{anchor_id}Scope content:write · destructive
The bulk link editor's "Delete": the whole link, its text too, is removed from the posts of every site that carries it (one job per site). It cannot be undone except from a backup.
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
anchor_id | path | integer | yes | The link id (see GET /backlink-tracker/{domain_id}). |
confirm | body | boolean | yes | Must be true: the link (with its text) is removed from every post. |
Example
curl -s -X DELETE "https://app.pbn.ltd/api/v1/backlink-tracker/links/anchor_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/backlink-tracker/links/anchor_id", headers=headers, timeout=120)
print(r.status_code, r.json())
const res = await fetch("https://app.pbn.ltd/api/v1/backlink-tracker/links/anchor_id", {
method: "DELETE",
headers: {Authorization: `Bearer ${process.env.PBN_API_KEY}`}
});
console.log(res.status, await res.json());
Response
202
{
"data": {
"queued": true,
"sites": 3
}
}
Errors: not_found, rate_limited, scope_missing, unauthorized, validation_failed