PBN.LTD API docs
View as Markdown

Logs

Error log and access log of a site.

Error log

GET/api/v1/sites/{site_id}/logs/errors

Scope logs:read

Recent PHP and web server errors of THIS site (the Error log tab): last 7 days, grouped, sanitised (paths shown relative to the site folder, secrets hidden). php_hint=true when the errors look like code written for an older PHP version. Cached 60 s; 20 fetches per 10 minutes per account.

Parameters

NameInTypeRequiredDescription
site_idpathintegeryesThe site id (see GET /sites).

Example

curl -s "https://app.pbn.ltd/api/v1/sites/123/logs/errors" \
  -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/logs/errors", headers=headers, timeout=120)
print(r.status_code, r.json())
const res = await fetch("https://app.pbn.ltd/api/v1/sites/123/logs/errors", {
  method: "GET",
  headers: {Authorization: `Bearer ${process.env.PBN_API_KEY}`}
});
console.log(res.status, await res.json());

Response

200

{
  "data": {
    "entries": [
      {
        "level": "Fatal error",
        "message": "Uncaught Error: Call to undefined function mysql_connect() in /wp-content/plugins/old/db.php:12",
        "count": 3,
        "first": "2026-09-19T08:00:00",
        "last": "2026-09-19T09:30:00"
      }
    ],
    "total": 3,
    "partial": false,
    "lookback_days": 7,
    "php_version": "PHP 8.3",
    "php_hint": true,
    "fetched_at": "2026-09-20 09:00:00 UTC",
    "seconds": 1.8,
    "cached": false
  }
}

Errors: conflict, not_found, rate_limited, scope_missing, unauthorized

Access log

GET/api/v1/sites/{site_id}/logs/access

Scope logs:read

Requests that reached the web server for this site's hostnames, newest last. The client IP is the visitor as the CDN reported it. 30 fetches per 10 minutes per account.

Parameters

NameInTypeRequiredDescription
site_idpathintegeryesThe site id (see GET /sites).
hoursqueryintegernoHow far back to look. Default: 1.
linesqueryintegernoAt most this many (the newest) lines. Default: 200.

Example

curl -s "https://app.pbn.ltd/api/v1/sites/123/logs/access?hours=1&lines=100" \
  -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/logs/access?hours=1&lines=100", headers=headers, timeout=120)
print(r.status_code, r.json())
const res = await fetch("https://app.pbn.ltd/api/v1/sites/123/logs/access?hours=1&lines=100", {
  method: "GET",
  headers: {Authorization: `Bearer ${process.env.PBN_API_KEY}`}
});
console.log(res.status, await res.json());

Response

200

{
  "data": {
    "entries": [
      {
        "time": "2026-09-20T08:59:58+00:00",
        "client_ip": "203.0.113.9",
        "host": "example.com",
        "method": "GET",
        "path": "/",
        "protocol": "HTTP/1.1",
        "status": 200,
        "bytes": 5123,
        "referer": null,
        "user_agent": "Mozilla/5.0 ...",
        "scheme": "https"
      }
    ],
    "count": 1,
    "status_counts": {
      "2xx": 1
    },
    "hours": 1,
    "partial": false,
    "note": "Requests the CDN answered from its cache never reach the server and are not in this log."
  }
}

Errors: conflict, not_found, rate_limited, scope_missing, unauthorized