Unofficial, derived from public PBLeague pages. Not affiliated with PBLI. Full route reference (a bit denser) is at /docs.
Two ways to put a team's stats on your own site, depending on how often you rebuild it.
Drop this in your HTML. It fetches once and caches the result in the visitor's browser for 30 days (configurable) — most page loads never hit the API at all.
<div id="my-team-widget"></div>
<script
src="https://pblidb.org/widgets/team-stats.js"
data-team="red-legion"
data-target="my-team-widget"
data-cache-days="30"
></script>
Live example, rendered right now on this page from the sandbox dataset:
If your site is static and rebuilds occasionally (a few times a week or less), skip the runtime API dependency entirely: fetch the data once during your build and bundle it as local JSON.
// Run this during your static site's build step (Node 18+, no dependencies).
// Fetch once per build, write to a local JSON file, and read that file
// from your templates — no runtime dependency on this API at all.
import { writeFileSync } from "node:fs";
const TEAM = "red-legion"; // your team's slug — see /docs or ask us for yours
const BASE = "https://pblidb.org/v1";
const [team, stats, roster] = await Promise.all([
fetch(`${BASE}/teams/${TEAM}`).then((r) => r.json()),
fetch(`${BASE}/teams/${TEAM}/stats`).then((r) => r.json()),
fetch(`${BASE}/teams/${TEAM}/roster`).then((r) => r.json()),
]);
writeFileSync("src/data/team-stats.json", JSON.stringify({ team, stats, roster }, null, 2));
// Your site generator (Eleventy, Hugo, Astro, Jekyll, ...) reads that file
// like any other local data source. Re-run this script whenever you
// rebuild — nothing on the live site ever calls this API directly.
Both hit the same routes: GET /v1/teams/{slug}, GET /v1/teams/{slug}/stats, GET /v1/teams/{slug}/roster. Full reference at /docs; try /v1/sandbox/events/9319/teams to find a team slug to experiment with.