{season}/standings.json
/api/v1/{season}/standings.json
Win/loss records, point differential, and division for one season.
Seasons
Replace {season} with one of 2026, 2025, 2024, 2023, 2022. Not every season has every endpoint — check themanifest first. If it is not listed there, the URL 404s.
Response
Every endpoint returns the same envelope. Your data is indata — data is the array itself — there is no wrapper object inside it.
{
"schemaVersion": "1.0",
"generatedAt": "2026-06-23T14:03:13.152995-04:00",
"league": "PUL",
"data": [ ... ]
}generatedAt is a nullable ISO-8601 timestamp that may or may not carry a UTC offset — parse leniently. It is null for 2022 and 2023, which predate the pipeline that records it.
Fields
| Field | Type | Meaning |
|---|---|---|
| abbrev | string|null | Canonical team abbreviation. |
| name | string|null | Full team name. |
| division | string|null | Division name, or null in seasons that had none. |
| wins | number|null | Regular-season wins. |
| losses | number|null | Regular-season losses. |
| pointsFor | number|null | Goals scored. |
| pointsAgainst | number|null | Goals conceded. |
| games | number|null | Games played. |
| winPct | number|null | Win percentage on a 0–100 scale, e.g. 83.3 — not a 0–1 fraction. |
| pointDiff | number|null | pointsFor minus pointsAgainst. |
| last6 | array|null | Up to six "W"/"L" strings for the team's most recent regular-season games, oldest first (a "T" is also possible on a tie, though that is effectively unreachable in this sport). Postseason results are excluded. |
Dotted names are nested — colors.primary means{ colors: { primary } }. When the parent is a list of objects (like seasons on the manifest),seasons.season means each entry in that array has its ownseason field — access it as seasons[i].season, not seasons.season.
Examples
curl -s https://pul-stats-hub.pages.dev/api/v1/2025/standings.json// 2025 table, sorted by point differential
const res = await fetch('https://pul-stats-hub.pages.dev/api/v1/2025/standings.json');
const { data } = await res.json();
for (const row of [...data].sort((a, b) => b.pointDiff - a.pointDiff)) {
console.log(`${row.abbrev} ${row.wins}-${row.losses} (${row.pointDiff > 0 ? '+' : ''}${row.pointDiff})`);
}# 2025 table, sorted by point differential
import json, urllib.request
URL = "https://pul-stats-hub.pages.dev/api/v1/2025/standings.json"
with urllib.request.urlopen(URL) as response:
rows = json.load(response)["data"]
for row in sorted(rows, key=lambda r: r["pointDiff"], reverse=True):
print(f'{row["abbrev"]:>4} {row["wins"]}-{row["losses"]} {row["pointDiff"]:+d}')Worth knowing
- Regular season only — postseason games are excluded from these records, so they will not reconcile with a naive count over games.json unless you filter `isPostseason`.
- These rows only became trustworthy on 2026-07-29. Before that fix, 2024 and 2025 had postseason baked in asymmetrically.
