First release.
- NBA box scores from espn.com: one row per player per game, carrying the
player's full statline and that team's totals. The two closest
competitors sell those as two separate actors.
- 93 columns. Minutes, points, field goals / three pointers / free throws as
made, attempted and percentage, offensive and defensive rebounds, assists,
turnovers, steals, blocks, personal fouls, plus/minus. Team totals add
largest lead, technical and flagrant fouls, team turnovers and the
assist-to-turnover ratio. Every row also names the opponent, the venue, the
score, the margin and the result.
query takes a season (season:2025), a date (2025-03-15), a range
(2025-03-14..2025-03-16) or one game (game:401705534). Empty means the
current season.
- Incremental mode delivers and charges only for rows that are new or whose
content moved. The change signature covers the whole delivered row, so a
statline ESPN corrects after the final whistle is caught.
- Notifications: Telegram, Slack, Discord, WhatsApp Cloud API, generic webhook.
- Transport: one request per game returns both rosters and both teams' totals.
No proxy, no browser, no custom headers. Measured 2026-09-03 from a bare
datacenter IP: 4 requests, 82 rows, 2.0 s.
- Retries a throttled response. Measured 2026-09-03: a burst at 50 concurrent
requests leaves ESPN returning a flapping 403 — the same URL alternating
403 / 200 / 403 for minutes. Unretried that killed the run, so 403 is treated
as a rate limit and retried with backoff, while a 404 is not. Concurrency is
set from the measured ceiling (20 held at 100%, 50 collapsed to 40%).
Three additions, all measured against what rivals with real traction actually
ship (audit of 11 competitor input schemas and READMEs).
teams filter. Only games involving the teams you name — abbreviation or
name both work (BOS, Celtics, Boston Celtics). Applied when the calendar
is listed, before any game is fetched, so you are not charged for the
other 29 teams. The three rivals with the most users between them make a team
selector their primary input; we had no way to say "just the Lakers" without
pulling a whole season.
- Quarter-by-quarter score, both sides:
teamQ1Points..teamQ4Points,
teamOvertimePoints and the matching opponent* columns. It rides along in
the payload we already fetch, so it costs nothing extra. Overtime is summed,
so a double-OT game keeps both periods.
teamHomeAway and teamIsHome. Which side of the court the row's team
was on. An earlier pass left this out on the reasoning that team-versus-
opponent already said it — it does not, that pairing is symmetric, and
home/away splits are one of the first cuts anyone makes on a box score.
teamVenueCity and teamVenueState alongside the arena name.
Also: unplayed games are now dropped when the calendar is read. A scheduled
game's box score is empty (measured on 401909834, 2026-10-21), so a query over
a future window used to pay one request per game and deliver nothing.
Considered and NOT added: broadcast networks. The source returned an empty list
on every game we measured, and a column that is null on every historical row is
worse than no column at all.