Agency SEO data
Authority and link data for up to 200 domains hosted anywhere, read every week: domain rank, referring domains, backlinks, spam score and the organic traffic estimate.
Agency SEO data: plan and usage
GET/api/v1/agency-seo-dataScope agency:read
Your plan, how many domains it covers and how many you track.
Example
curl -s "https://app.pbn.ltd/api/v1/agency-seo-data" \
-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/agency-seo-data", headers=headers, timeout=120)
print(r.status_code, r.json())
const res = await fetch("https://app.pbn.ltd/api/v1/agency-seo-data", {
method: "GET",
headers: {Authorization: `Bearer ${process.env.PBN_API_KEY}`}
});
console.log(res.status, await res.json());
Response
200
{
"data": {
"plan": "200 domains",
"unlimited": false,
"paid_until": "2026-10-25",
"tracked": 184,
"switched_off": 3,
"domains_included": 200,
"moves_this_week": 2,
"labels": [
"Acme Ltd"
],
"price_from": "49.00"
}
}
Errors: rate_limited, scope_missing, unauthorized
List your tracked domains
GET/api/v1/agency-seo-data/domainsScope agency:read
Every domain you track, with its latest weekly reading (null = not measured, never zero).
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
label | query | string | no | Only the domains with this client label. |
Example
curl -s "https://app.pbn.ltd/api/v1/agency-seo-data/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/agency-seo-data/domains", headers=headers, timeout=120)
print(r.status_code, r.json())
const res = await fetch("https://app.pbn.ltd/api/v1/agency-seo-data/domains", {
method: "GET",
headers: {Authorization: `Bearer ${process.env.PBN_API_KEY}`}
});
console.log(res.status, await res.json());
Response
200
{
"data": [
{
"id": 31,
"domain": "client-site.com",
"label": "Acme Ltd",
"note": "",
"country": "GB",
"switched_on": true,
"covered": true,
"state": "ok",
"domain_rank": 312,
"referring_domains": 1480,
"new_referring_domains": 22,
"lost_referring_domains": 9,
"backlinks": 40211,
"spam_score": 4,
"organic_traffic": "5210.4",
"organic_keywords": 1893,
"last_read_at": "2026-09-26T12:00:00Z"
}
]
}
Errors: rate_limited, scope_missing, unauthorized
One tracked domain
GET/api/v1/agency-seo-data/domains/{item_id}Scope agency:read
One domain with the history of its weekly readings (newest first, up to two years).
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
item_id | path | integer | yes | The tracked domain id. |
Example
curl -s "https://app.pbn.ltd/api/v1/agency-seo-data/domains/item_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/agency-seo-data/domains/item_id", headers=headers, timeout=120)
print(r.status_code, r.json())
const res = await fetch("https://app.pbn.ltd/api/v1/agency-seo-data/domains/item_id", {
method: "GET",
headers: {Authorization: `Bearer ${process.env.PBN_API_KEY}`}
});
console.log(res.status, await res.json());
Response
200
{
"data": {
"id": 31,
"domain": "client-site.com",
"label": "Acme Ltd",
"note": "",
"country": "GB",
"switched_on": true,
"covered": true,
"state": "ok",
"domain_rank": 312,
"referring_domains": 1480,
"new_referring_domains": 22,
"lost_referring_domains": 9,
"backlinks": 40211,
"spam_score": 4,
"organic_traffic": "5210.4",
"organic_keywords": 1893,
"last_read_at": "2026-09-26T12:00:00Z",
"history": [
{
"read_at": "2026-09-19T12:00:00Z",
"domain_rank": 309,
"referring_domains": 1466,
"backlinks": 39870,
"spam_score": 4,
"organic_traffic": "5102.0",
"organic_keywords": 1870
}
]
}
}
Errors: not_found, rate_limited, scope_missing, unauthorized
Track domains
POST/api/v1/agency-seo-data/domainsScope agency:write
Adds domains to your list; their first reading arrives within minutes. Adds as many as your plan has room for and says why each other one was skipped. Nothing is spent on a refusal.
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
domains | body | array | yes | The domains, e.g. ["client-site.com", "other-client.co.uk"] (up to 500 per call). |
country | body | string (one of: US, GB, DE, FR, ES, IT, CA, AU) | yes | The country for the organic traffic estimate (the list is kept by us and may grow). |
label | body | string | no | A client label for all of them (up to 60 characters). |
Example
curl -s -X POST "https://app.pbn.ltd/api/v1/agency-seo-data/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/agency-seo-data/domains", headers=headers, timeout=120)
print(r.status_code, r.json())
const res = await fetch("https://app.pbn.ltd/api/v1/agency-seo-data/domains", {
method: "POST",
headers: {Authorization: `Bearer ${process.env.PBN_API_KEY}`}
});
console.log(res.status, await res.json());
Response
201
{
"data": {
"added": [
{
"id": 31,
"domain": "client-site.com",
"label": "Acme Ltd",
"note": "",
"country": "GB",
"switched_on": true,
"covered": true,
"state": "ok",
"domain_rank": 312,
"referring_domains": 1480,
"new_referring_domains": 22,
"lost_referring_domains": 9,
"backlinks": 40211,
"spam_score": 4,
"organic_traffic": "5210.4",
"organic_keywords": 1893,
"last_read_at": "2026-09-26T12:00:00Z"
}
],
"skipped": [
{
"domain": "localhost",
"reason": "does not look like a public domain"
}
],
"room_left": 15
}
}
Errors: payment_required, rate_limited, scope_missing, unauthorized, validation_failed
Label or switch a tracked domain
PATCH/api/v1/agency-seo-data/domains/{item_id}Scope agency:write
Changes the client label or note, or switches the domain off / on.
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
item_id | path | integer | yes | The tracked domain id. |
label | body | string | no | The client label (up to 60 characters). |
note | body | string | no | Your note (up to 120 characters). |
switched_on | body | boolean | no | false = keep it with its history but stop reading and counting it. |
Example
curl -s -X PATCH "https://app.pbn.ltd/api/v1/agency-seo-data/domains/item_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/agency-seo-data/domains/item_id", headers=headers, timeout=120)
print(r.status_code, r.json())
const res = await fetch("https://app.pbn.ltd/api/v1/agency-seo-data/domains/item_id", {
method: "PATCH",
headers: {Authorization: `Bearer ${process.env.PBN_API_KEY}`}
});
console.log(res.status, await res.json());
Response
200
{
"data": {
"id": 31,
"domain": "client-site.com",
"label": "Acme Ltd",
"note": "",
"country": "GB",
"switched_on": true,
"covered": true,
"state": "ok",
"domain_rank": 312,
"referring_domains": 1480,
"new_referring_domains": 22,
"lost_referring_domains": 9,
"backlinks": 40211,
"spam_score": 4,
"organic_traffic": "5210.4",
"organic_keywords": 1893,
"last_read_at": "2026-09-26T12:00:00Z"
}
}
Errors: not_found, rate_limited, scope_missing, unauthorized, validation_failed
Stop tracking a domain
DELETE/api/v1/agency-seo-data/domains/{item_id}Scope agency:write
Removes the domain from your list.
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
item_id | path | integer | yes | The tracked domain id. |
Example
curl -s -X DELETE "https://app.pbn.ltd/api/v1/agency-seo-data/domains/item_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/agency-seo-data/domains/item_id", headers=headers, timeout=120)
print(r.status_code, r.json())
const res = await fetch("https://app.pbn.ltd/api/v1/agency-seo-data/domains/item_id", {
method: "DELETE",
headers: {Authorization: `Bearer ${process.env.PBN_API_KEY}`}
});
console.log(res.status, await res.json());
Response
200
{
"data": {
"deleted": true
}
}
Errors: not_found, rate_limited, scope_missing, unauthorized