PBN.LTD API docs
View as Markdown

Wayback restore

Rebuild a website from the public web archive: look a domain up, pick a day, see what would be rebuilt and order it with a restore credit.

Wayback restore: credits, prices and restores

GET/api/v1/wayback

Scope wayback:read

Your restore credits, the price of a restore of each kind (what the page would charge, with your VAT), how many new sites your plan still has room for, and your restores, newest first.

Example

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

Response

200

{
  "data": {
    "available": true,
    "credits": 3,
    "free_site_slots": 12,
    "site_limit": 50,
    "prices": {
      "static": {
        "price": "9.00",
        "vat": "0",
        "charge": "9.00"
      },
      "wordpress": {
        "price": "19.00",
        "vat": "0",
        "charge": "19.00"
      }
    },
    "restores": [
      {
        "id": 812,
        "reference": "WB-7Q2K9",
        "domain": "old-site.com",
        "day": "2019-05-14",
        "output": "static",
        "target_domain": "old-site.com",
        "target": "new",
        "site_id": null,
        "state": "planned",
        "state_label": "Ready to order",
        "pay_status": "unpaid",
        "pay_label": "Not paid",
        "message": "",
        "pages": 38,
        "assets": 212,
        "archive_mb": 14.2,
        "fetched": 0,
        "missing": 0,
        "failed": 0,
        "progress_pct": 0,
        "running": false,
        "done": false,
        "created_at": "2026-09-26T10:00:00Z"
      }
    ],
    "page_url": "https://app.pbn.ltd/wayback/"
  }
}

Errors: rate_limited, scope_missing, unauthorized

Days the archive holds

GET/api/v1/wayback/archive/{domain}

Scope wayback:read

The days the public web archive has a copy of the domain's home page on, as the calendar shows. The first look-up of a domain reads the archive in the background: state is "pending" - ask again in a minute until it reads "ready" (or "error", with the reason).

Parameters

NameInTypeRequiredDescription
domainpathstringyesThe domain, e.g. old-site.com.

Example

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

Response

200

{
  "data": {
    "domain": "old-site.com",
    "state": "ready",
    "days": [
      "2019-05-14",
      "2019-06-02"
    ],
    "truncated": false,
    "error": ""
  }
}

Errors: not_found, rate_limited, scope_missing, unauthorized, unavailable, validation_failed

One restore

GET/api/v1/wayback/restores/{restore_id}

Scope wayback:read

One restore: its progress and, while it is "planned" (ready to order), a sample of the pages that would be rebuilt and your existing sites it could be restored into.

Parameters

NameInTypeRequiredDescription
restore_idpathintegeryesThe restore id.

Example

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

Response

200

{
  "data": {
    "id": 812,
    "reference": "WB-7Q2K9",
    "domain": "old-site.com",
    "day": "2019-05-14",
    "output": "static",
    "target_domain": "old-site.com",
    "target": "new",
    "site_id": null,
    "state": "planned",
    "state_label": "Ready to order",
    "pay_status": "unpaid",
    "pay_label": "Not paid",
    "message": "",
    "pages": 38,
    "assets": 212,
    "archive_mb": 14.2,
    "fetched": 0,
    "missing": 0,
    "failed": 0,
    "progress_pct": 0,
    "running": false,
    "done": false,
    "created_at": "2026-09-26T10:00:00Z",
    "sample": [
      "/",
      "/about/",
      "/contact/"
    ],
    "existing_sites": {
      "static": [
        {
          "id": 123,
          "domain": "example.com"
        }
      ],
      "wordpress": []
    }
  }
}

Errors: not_found, rate_limited, scope_missing, unauthorized

Start a restore (free)

POST/api/v1/wayback/restores

Scope wayback:write

Reads that day's copy from the archive and works out what would be rebuilt. Nothing is charged: the restore waits at "planned" until you order it.

Parameters

NameInTypeRequiredDescription
domainbodystringyesThe domain to rebuild.
daybodystringyesA day from GET /wayback/archive/{domain} (YYYY-MM-DD).
outputbodystring (one of: static, wordpress)noStatic HTML, or converted to WordPress (changeable when ordering). Default: static.

Example

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

Response

201

{
  "data": {
    "id": 812,
    "reference": "WB-7Q2K9",
    "domain": "old-site.com",
    "day": "2019-05-14",
    "output": "static",
    "target_domain": "old-site.com",
    "target": "new",
    "site_id": null,
    "state": "planned",
    "state_label": "Ready to order",
    "pay_status": "unpaid",
    "pay_label": "Not paid",
    "message": "",
    "pages": 38,
    "assets": 212,
    "archive_mb": 14.2,
    "fetched": 0,
    "missing": 0,
    "failed": 0,
    "progress_pct": 0,
    "running": false,
    "done": false,
    "created_at": "2026-09-26T10:00:00Z"
  }
}

Errors: rate_limited, scope_missing, unauthorized, unavailable, validation_failed

Order a restore with a restore credit

POST/api/v1/wayback/restores/{restore_id}/order

Scope wayback:write

Uses ONE restore credit and starts the rebuild (restore credits are bought in packs on the Wayback page; paying one restore by PayPal or crypto is done there too). Restoring into an existing site replaces what it serves.

Parameters

NameInTypeRequiredDescription
restore_idpathintegeryesThe restore id.
outputbodystring (one of: static, wordpress)yesStatic HTML or converted to WordPress.
targetbodystring (one of: new, existing)yes"new" makes a new site (needs a free site slot); "existing" restores into one of your sites of that type (it is overwritten).
new_domainbodystringnoFor a new site: its domain (default: the old domain).
site_idbodyintegernoFor an existing site: its id.
accept_termsbodybooleanyesMust be true: you agree to the Terms and Conditions (https://pbn.ltd/terms/), recorded exactly like the box on the order page.
ack_rightsbodybooleanyesMust be true: you confirm you have the right to republish this content (the trademark / copyright acknowledgement on the order page).

Example

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

Response

202

{
  "data": {
    "id": 812,
    "reference": "WB-7Q2K9",
    "domain": "old-site.com",
    "day": "2019-05-14",
    "output": "static",
    "target_domain": "old-site.com",
    "target": "new",
    "site_id": null,
    "state": "queued",
    "state_label": "Ready to order",
    "pay_status": "paid",
    "pay_label": "Paid",
    "message": "",
    "pages": 38,
    "assets": 212,
    "archive_mb": 14.2,
    "fetched": 0,
    "missing": 0,
    "failed": 0,
    "progress_pct": 0,
    "running": false,
    "done": false,
    "created_at": "2026-09-26T10:00:00Z",
    "credits_left": 2
  }
}

Errors: conflict, not_found, payment_required, rate_limited, scope_missing, unauthorized, unavailable, validation_failed