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/waybackScope 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
| Name | In | Type | Required | Description |
|---|---|---|---|---|
domain | path | string | yes | The 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
| Name | In | Type | Required | Description |
|---|---|---|---|---|
restore_id | path | integer | yes | The 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/restoresScope 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
| Name | In | Type | Required | Description |
|---|---|---|---|---|
domain | body | string | yes | The domain to rebuild. |
day | body | string | yes | A day from GET /wayback/archive/{domain} (YYYY-MM-DD). |
output | body | string (one of: static, wordpress) | no | Static 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}/orderScope 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
| Name | In | Type | Required | Description |
|---|---|---|---|---|
restore_id | path | integer | yes | The restore id. |
output | body | string (one of: static, wordpress) | yes | Static HTML or converted to WordPress. |
target | body | string (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_domain | body | string | no | For a new site: its domain (default: the old domain). |
site_id | body | integer | no | For an existing site: its id. |
accept_terms | body | boolean | yes | Must be true: you agree to the Terms and Conditions (https://pbn.ltd/terms/), recorded exactly like the box on the order page. |
ack_rights | body | boolean | yes | Must 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