Site audit
Crawl a site you own and find what is holding it back, with a fix for each finding. Richer for sites hosted with us.
Site audit: plan and usage
GET/api/v1/site-auditScope audit:read
Your plan, audits a month included and used, the page cap per audit, and your most recent audit.
Example
curl -s "https://app.pbn.ltd/api/v1/site-audit" \
-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/site-audit", headers=headers, timeout=120)
print(r.status_code, r.json())
const res = await fetch("https://app.pbn.ltd/api/v1/site-audit", {
method: "GET",
headers: {Authorization: `Bearer ${process.env.PBN_API_KEY}`}
});
console.log(res.status, await res.json());
Response
200
{
"data": {
"active": true,
"plan": "Growth",
"paid_until": "2026-10-31",
"audits_this_month": {
"used": 3,
"limit": 25
},
"pages_per_audit": 300,
"scheduled_reaudits": true,
"latest": {
"id": 88,
"host": "example.com",
"state": "done",
"score": 74,
"grade": "C",
"pages_crawled": 100,
"issues": 12,
"critical": 1,
"warnings": 6,
"notices": 5,
"hosted": true,
"verified": true,
"finished_at": "2026-09-22T09:00:00Z"
}
}
}
Errors: rate_limited, scope_missing, unauthorized
List audits
GET/api/v1/site-audit/auditsScope audit:read
Your finished audits, newest first.
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
host | query | string | no | Only audits of this site. |
limit | query | integer | no | Default: 25. |
cursor | query | string | no | next_cursor of the previous page. |
Example
curl -s "https://app.pbn.ltd/api/v1/site-audit/audits" \
-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/site-audit/audits", headers=headers, timeout=120)
print(r.status_code, r.json())
const res = await fetch("https://app.pbn.ltd/api/v1/site-audit/audits", {
method: "GET",
headers: {Authorization: `Bearer ${process.env.PBN_API_KEY}`}
});
console.log(res.status, await res.json());
Response
200
{
"data": [
{
"id": 88,
"host": "example.com",
"state": "done",
"score": 74,
"grade": "C",
"pages_crawled": 100,
"issues": 12,
"critical": 1,
"warnings": 6,
"notices": 5,
"hosted": true,
"verified": true,
"finished_at": "2026-09-22T09:00:00Z"
}
],
"next_cursor": null,
"has_more": false
}
Errors: rate_limited, scope_missing, unauthorized
One audit and its findings
GET/api/v1/site-audit/audits/{audit_id}Scope audit:read
The audit with every finding: what it is, what it means, which pages it affects and how to fix it. A finding with source: server comes from your hosting with us rather than from the crawl.
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
audit_id | path | integer | yes | The audit id. |
Example
curl -s "https://app.pbn.ltd/api/v1/site-audit/audits/audit_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/site-audit/audits/audit_id", headers=headers, timeout=120)
print(r.status_code, r.json())
const res = await fetch("https://app.pbn.ltd/api/v1/site-audit/audits/audit_id", {
method: "GET",
headers: {Authorization: `Bearer ${process.env.PBN_API_KEY}`}
});
console.log(res.status, await res.json());
Response
200
{
"data": {
"id": 88,
"host": "example.com",
"state": "done",
"score": 74,
"grade": "C",
"pages_crawled": 100,
"issues": [
{
"code": "title_duplicate",
"severity": "warning",
"source": "crawl",
"title": "8 pages share a title with another page",
"what_it_means": "When several pages carry the same title ...",
"how_to_fix": "Give every page a title that describes that page ...",
"pages": [
"https://example.com/a",
"https://example.com/b"
],
"count": 8
}
],
"critical": 1,
"warnings": 6,
"notices": 5,
"hosted": true,
"verified": true,
"finished_at": "2026-09-22T09:00:00Z"
}
}
Errors: not_found, rate_limited, scope_missing, unauthorized
The pages an audit fetched
GET/api/v1/site-audit/audits/{audit_id}/pagesScope audit:read
Every page the crawl fetched, with what was measured on it.
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
audit_id | path | integer | yes | The audit id. |
Example
curl -s "https://app.pbn.ltd/api/v1/site-audit/audits/audit_id/pages" \
-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/site-audit/audits/audit_id/pages", headers=headers, timeout=120)
print(r.status_code, r.json())
const res = await fetch("https://app.pbn.ltd/api/v1/site-audit/audits/audit_id/pages", {
method: "GET",
headers: {Authorization: `Bearer ${process.env.PBN_API_KEY}`}
});
console.log(res.status, await res.json());
Response
200
{
"data": {
"items": [
{
"url": "https://example.com/",
"status": 200,
"title": "Home",
"words": 820,
"load_ms": 410,
"noindex": false
}
],
"total": 100
},
"next_cursor": null,
"has_more": false
}
Errors: not_found, rate_limited, scope_missing, unauthorized
Audit a site
POST/api/v1/site-audit/auditsScope audit:write
Queues an audit; results are usually ready within a few minutes - poll /site-audit/audits/{id}. A site whose ownership you have not proved is crawled shallowly (see pages in the response); verify it to unlock a full crawl.
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
url | body | string | yes | The site to audit, e.g. https://example.com/ |
Example
curl -s -X POST "https://app.pbn.ltd/api/v1/site-audit/audits" \
-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/site-audit/audits", headers=headers, timeout=120)
print(r.status_code, r.json())
const res = await fetch("https://app.pbn.ltd/api/v1/site-audit/audits", {
method: "POST",
headers: {Authorization: `Bearer ${process.env.PBN_API_KEY}`}
});
console.log(res.status, await res.json());
Response
202
{
"data": {
"queued": true,
"audit_id": 89,
"pages": 300,
"verified": true
}
}
Errors: payment_required, rate_limited, scope_missing, unauthorized, validation_failed
How to prove a site is yours
GET/api/v1/site-audit/verificationScope audit:read
The three ways to prove a site is yours. Any one of them is enough, and a site hosted with us needs none.
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
host | query | string | yes | e.g. example.com |
Example
curl -s "https://app.pbn.ltd/api/v1/site-audit/verification" \
-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/site-audit/verification", headers=headers, timeout=120)
print(r.status_code, r.json())
const res = await fetch("https://app.pbn.ltd/api/v1/site-audit/verification", {
method: "GET",
headers: {Authorization: `Bearer ${process.env.PBN_API_KEY}`}
});
console.log(res.status, await res.json());
Response
200
{
"data": {
"host": "example.com",
"verified": false,
"method": null,
"dns": {
"name": "_pbn-site-audit.example.com",
"type": "TXT",
"value": "pbn-site-audit=..."
},
"meta": "<meta name=\"pbn-site-audit\" content=\"pbn-site-audit=...\">",
"file": {
"path": "/.well-known/pbn-site-audit.txt",
"contents": "pbn-site-audit=..."
}
}
}
Errors: rate_limited, scope_missing, unauthorized
Check the proof now
POST/api/v1/site-audit/verificationScope audit:write
Looks for the DNS record, the meta tag and the file, in that order.
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
host | body | string | yes | e.g. example.com |
Example
curl -s -X POST "https://app.pbn.ltd/api/v1/site-audit/verification" \
-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/site-audit/verification", headers=headers, timeout=120)
print(r.status_code, r.json())
const res = await fetch("https://app.pbn.ltd/api/v1/site-audit/verification", {
method: "POST",
headers: {Authorization: `Bearer ${process.env.PBN_API_KEY}`}
});
console.log(res.status, await res.json());
Response
200
{
"data": {
"verified": true,
"method": "dns",
"message": "Verified. Full audits are unlocked for this site."
}
}
Errors: rate_limited, scope_missing, unauthorized, validation_failed