feat(research): add GET /api/research/track/stats — per-track Songstats stats
Implements recoupable/chat#1789 (api step) against the docs#236 contract. Pairs with recoupable/docs#236 (merge docs first).
Adds GET /api/research/track/stats — per-track, per-source current stats (incl. absolute streams_total) so agents can attribute streams to specific recordings. Today /api/research/metrics is artist-level only and /api/research/track(s) return metadata without stream counts.
Design — thin passthrough, not new infra
- Resolution:
isrc(orsongstats_track_id/spotify_track_id/apple_music_track_id);sourcerequired (comma list orall); optionalwith_playlists/charts/stations/videos/links,only_current,limit,offsetforwarded 1:1 to Songstatsenterprise/v1/tracks/stats. - Reuses the existing
fetchSongstatsclient (enterpriseapikeyserver-side viaSONGSTATS_API_KEY, never echoed) and the researchvalidate → handler → successResponseshape. Response mirrors/api/research/metrics({ status, result, message, stats:[{source,data}], track_info }). - Auth + credits identical to other
/api/research/*endpoints:validateAuthContext(401),ensureResearchCreditsgate, 5-credit deduction on a successful read. No database change.
Files
app/api/research/track/stats/route.ts(GET + OPTIONS)lib/research/validateGetResearchTrackStatsRequest.ts·getResearchTrackStats.ts·getResearchTrackStatsHandler.ts
Tests (TDD, red→green)
validate (5), getResearchTrackStats (2), handler (3) — 10 new, all green; full lib/research suite 151/151 (no regressions); tsc + lint clean.
Test plan (preview, per #1789 Done-when)
-
?isrc=USQY51771120&source=spotify→ 200 withstats[0].data.streams_totalinteger (Mac Miller — K.I.D.S.). -
source=all→ onestats[]per source; resolving bysongstats_track_id/spotify_track_idworks equivalently. - 401 without a valid key;
SONGSTATS_API_KEYnever echoed. - Sum of K.I.D.S. per-track
streams_total≪ artist-levelstreams_total(~19.9B).
🤖 Generated with Claude Code
Summary by cubic
Adds GET /api/research/track/stats to return per-track, per-source Songstats current stats, including streams_total, so agents can attribute streams to specific recordings. This is a thin passthrough and reuses existing auth and credit rules.
-
New Features
- Resolve by
isrc,songstats_track_id,spotify_track_id, orapple_music_track_id;sourceis required. Optionalwith_*,only_current,limit, andoffsetare forwarded 1:1. - Response mirrors
/api/research/metrics({ status, result, message, stats:[{ source, data }], track_info }); includes CORSOPTIONS. - Reuses
fetchSongstats; same auth and credits as other research endpoints with a 5-credit deduction on successful 200. No database changes.
- Resolve by
-
Bug Fixes
- Validator now enforces exactly one track identifier; returns 400 if multiple are provided (per docs#236).