There is a compact index and there are full records. Start with the index.
Compact index (static, canonical)
GET /registry/v1/index.json
Each entry is small: id, status, name, domain, updatedAt, categories, path. No icon or screenshot payloads.
const index = await fetch(
"https://pwaregistry.org/registry/v1/index.json",
).then((r) => r.json());
const active = index.apps.filter((a) => a.status === "ACTIVE");
Fetch a full record only when you will display it:
const rec = await fetch(
"https://pwaregistry.org" + app.path,
).then((r) => r.json());
path looks like /registry/v1/apps/squoosh.app.
Active-only file
GET /registry/v1/status/active.json — same lightweight entries, already filtered.
API list (paginated)
GET /api/v1/apps
GET /api/v1/apps?status=active
GET /api/v1/apps?limit=50&cursor=squoosh.app
Default status is ACTIVE. Default limit is 50, max 200. If nextCursor is present, pass it as cursor for the next page.
Use the API list for prototypes and small tools. For a catalog of thousands of apps, download index.json once and follow changes.
Do not fetch the entire PWARegistry every time a user loads your page.