Appearance
lastfm
81 endpoints at a glance
| Method | Path | Summary |
|---|---|---|
GET | /lastfm/albums/{artist}/{album}/info | Album Info |
GET | /lastfm/albums/{artist}/{album}/top-tags | Album Top Tags |
GET | /lastfm/albums/search | Album Search |
GET | /lastfm/artists/{artist}/correction | Artist Correction |
GET | /lastfm/artists/{artist}/info | Artist Info |
GET | /lastfm/artists/{artist}/similar | Artist Similar |
GET | /lastfm/artists/{artist}/top-albums | Artist Top Albums |
GET | /lastfm/artists/{artist}/top-tags | Artist Top Tags |
GET | /lastfm/artists/{artist}/top-tracks | Artist Top Tracks |
GET | /lastfm/artists/search | Artist Search |
GET | /lastfm/auth/callback | Auth Callback |
POST | /lastfm/auth/disconnect | Auth Disconnect |
GET | /lastfm/auth/start | Auth Start |
GET | /lastfm/charts/top-artists | Chart Top Artists |
GET | /lastfm/charts/top-tags | Chart Top Tags |
GET | /lastfm/charts/top-tracks | Chart Top Tracks |
GET | /lastfm/geo/{country}/top-artists | Geo Top Artists |
GET | /lastfm/geo/{country}/top-tracks | Geo Top Tracks |
GET | /lastfm/me/albums/{artist}/{album}/stats | Me Album Stats |
GET | /lastfm/me/albums/owned | List Owned |
POST | /lastfm/me/albums/owned | Mark Owned |
DELETE | /lastfm/me/albums/owned/{target_id} | Mark Not Owned |
GET | /lastfm/me/albums/wishlist | List Wishlist |
POST | /lastfm/me/albums/wishlist | Add To Wishlist |
DELETE | /lastfm/me/albums/wishlist/{target_id} | Remove From Wishlist |
GET | /lastfm/me/artists/{artist}/stats | Me Artist Stats |
GET | /lastfm/me/charts/{from_ts}/{to_ts}/albums | Me Chart Albums |
GET | /lastfm/me/charts/{from_ts}/{to_ts}/artists | Me Chart Artists |
GET | /lastfm/me/charts/{from_ts}/{to_ts}/tracks | Me Chart Tracks |
GET | /lastfm/me/charts/list | Me Charts List |
GET | /lastfm/me/dashboard | Me Dashboard |
GET | /lastfm/me/dashboard/heatmap-cell | Me Dashboard Heatmap Cell |
GET | /lastfm/me/favorites/albums | List Favorite Albums |
POST | /lastfm/me/favorites/albums | Favorite Album |
DELETE | /lastfm/me/favorites/albums/{target_id} | Unfavorite Album |
GET | /lastfm/me/favorites/artists | List Favorite Artists |
POST | /lastfm/me/favorites/artists | Favorite Artist |
DELETE | /lastfm/me/favorites/artists/{target_id} | Unfavorite Artist |
GET | /lastfm/me/favorites/tracks | List Favorite Tracks |
POST | /lastfm/me/favorites/tracks | Favorite Track |
DELETE | /lastfm/me/favorites/tracks/{target_id} | Unfavorite Track |
GET | /lastfm/me/friends | Me Friends |
GET | /lastfm/me/info | Me Info |
GET | /lastfm/me/library/artists | Me Library Artists |
POST | /lastfm/me/love | Me Love |
GET | /lastfm/me/loved-tracks | Me Loved Tracks |
GET | /lastfm/me/new-artists | Me New Artists |
POST | /lastfm/me/now-playing | Me Now Playing |
GET | /lastfm/me/recent-tracks | Me Recent Tracks |
GET | /lastfm/me/rediscover | Me Rediscover |
POST | /lastfm/me/refresh-mirror | Me Refresh Mirror |
POST | /lastfm/me/scrobble | Me Scrobble |
POST | /lastfm/me/scrobbles/{scrobble_id}/canonical-link | Stamp Scrobble Canonical |
POST | /lastfm/me/scrobbles/bulk-import | Me Scrobbles Bulk Import |
DELETE | /lastfm/me/scrobbles/bulk-import/{task_id} | Me Scrobbles Bulk Import Cancel |
GET | /lastfm/me/scrobbles/bulk-import/current | Me Scrobbles Bulk Import Current |
GET | /lastfm/me/scrobbles/bulk-import/history | Me Scrobbles Bulk Import History |
GET | /lastfm/me/top-albums | Me Top Albums |
GET | /lastfm/me/top-artists | Me Top Artists |
GET | /lastfm/me/top-tracks | Me Top Tracks |
GET | /lastfm/me/tracks/{artist}/{track}/stats | Me Track Stats |
POST | /lastfm/me/unlove | Me Unlove |
GET | /lastfm/picker/search | Lastfm Picker Search |
GET | /lastfm/tags/{tag}/info | Tag Info |
GET | /lastfm/tags/{tag}/similar | Tag Similar |
GET | /lastfm/tags/{tag}/top-albums | Tag Top Albums |
GET | /lastfm/tags/{tag}/top-artists | Tag Top Artists |
GET | /lastfm/tags/{tag}/top-tracks | Tag Top Tracks |
GET | /lastfm/tags/{tag}/weekly-chart-list | Tag Weekly Chart List |
GET | /lastfm/tracks/{artist}/{track}/correction | Track Correction |
GET | /lastfm/tracks/{artist}/{track}/info | Track Info |
GET | /lastfm/tracks/{artist}/{track}/similar | Track Similar |
GET | /lastfm/tracks/{artist}/{track}/top-tags | Track Top Tags |
GET | /lastfm/tracks/search | Track Search |
GET | /lastfm/users/{username}/friends | User Friends |
GET | /lastfm/users/{username}/info | User Info |
GET | /lastfm/users/{username}/loved-tracks | User Loved Tracks |
GET | /lastfm/users/{username}/recent-tracks | User Recent Tracks |
GET | /lastfm/users/{username}/top-albums | User Top Albums |
GET | /lastfm/users/{username}/top-artists | User Top Artists |
GET | /lastfm/users/{username}/top-tracks | User Top Tracks |
lastfm
Auth Start
Auth Callback
Auth Disconnect
Me Dashboard
GET
/lastfm/me/dashboard
One-shot aggregation of stats for the home dashboard.
Returns a discriminated-union shape: state is "no_lastfm"
when the user hasn't connected their LastFM account, "no_scrobbles"
when they have but haven't run an import yet, or "ready" with the
full payload otherwise.
window_days controls the time-scoped sections (window stats,
chart, top lists, genres, heatmap). Pass an integer for a rolling
window in days; omit or pass 0 / negative for all-time. Sections
that aren't time-scoped (totals, listening streak, latest scrobbles,
mirror) are unaffected.
Parameters
Query Parameters
window_days
Responses
Successful Response
application/json
JSON "additionalProperties": "string"
{
}
Me Dashboard Heatmap Cell
GET
/lastfm/me/dashboard/heatmap-cell
The scrobbles behind one listening-heatmap cell.
Drill-down for the dashboard heatmap: dow (0=Mon..6=Sun) × hour
(0..23, UTC) name a cell; we return the most-recent scrobbles in it.
window_days mirrors /me/dashboard (missing → 30, <=0 →
all-time) so the list matches the cell the user clicked.
Parameters
Query Parameters
dow*
Type
Requiredinteger
hour*
Type
Requiredinteger
window_days
Responses
Successful Response
application/json
JSON "additionalProperties": "string"
{
}
Me Rediscover
GET
/lastfm/me/rediscover
Dashboard "rediscover" panel: tracks played a lot but not in the
last not_played_days (30/90/180/365/… selectable), ranked by
all-time play count. On-demand (not part of the main dashboard
payload) so the window can be flipped without a full reload.
Parameters
Query Parameters
not_played_days
Type
integer
Default
90limit
Type
integer
Default
20Responses
Successful Response
application/json
JSON "additionalProperties": "string"
{
}
Me New Artists
GET
/lastfm/me/new-artists
Dashboard "new artists" panel: artists whose first-ever scrobble falls
in the window, with the songs played by each.
On-demand like /me/rediscover so the window can be flipped without a
full dashboard reload. The main payload's new_artists_count /
new_artists_sample stay where they are — they feed the one-line
activity stat, and this is the readable version of the same fact.
Parameters
Query Parameters
window_days
Type
integer
Default
30limit
Type
integer
Default
20tracks_per_artist
Type
integer
Default
5Responses
Successful Response
application/json
JSON "additionalProperties": "string"
{
}
Me Recent Tracks
GET
/lastfm/me/recent-tracks
Read scrobbles from the local mirror, paginated by uts desc.
Local-only — no LastFM call. The mirror is populated by the
bulk-import flow and the periodic refresh job.
Parameters
Query Parameters
page
Type
integer
Default
1limit
Type
integer
Default
50Responses
Successful Response
application/json
JSON "additionalProperties": "string"
{
}
Me Refresh Mirror
POST
/lastfm/me/refresh-mirror
Manually trigger a one-page mirror refresh for the current user.
Runs the same _refresh_recent_page1 path the periodic cron uses
— fetches LastFM's user.getRecentTracks page 1, upserts each
scrobble into the mirror, and fires the dedup-trigger so any new
artist/album/track lands in the cache.
Synchronous (one user, one page → ~1 sec on a warm cache, a bit
more on first run). Returns the count of newly-inserted scrobbles
plus the freshly-advanced last_refreshed_at so the SPA can
show "Mirror updated just now" without a second round-trip.
Parameters
Responses
Successful Response
application/json
JSON "additionalProperties": "string"
{
}
User Recent Tracks
Stamp Scrobble Canonical
POST
/lastfm/me/scrobbles/{scrobble_id}/canonical-link
Write canonical_{artist,album,track}_id onto a scrobble doc.
Used by the dashboard's click handler: the SPA resolves a
scrobble's name via Deezer search → canonical, then calls this
so the scrobble row picks up the canonical link without an
extra ingest/reconcile pass. Future dashboard reads find the
canonical_*_id already stamped and render source pills correctly.
Auth: caller must own the scrobble (lastfm_username on the doc
must match the caller's lastfm_username). Otherwise 403.
Parameters
Path Parameters
scrobble_id*
Type
Requiredstring
Request Body
application/json
JSON "canonical_artist_id": "string", "canonical_album_id": "string", "canonical_track_id": "string"
{
}
Responses
Successful Response
application/json
JSON "additionalProperties": "string"
{
}
Me Info
Me Top Artists
Me Top Tracks
Me Top Albums
Me Loved Tracks
Me Friends
Me Charts List
Me Chart Artists
Me Chart Tracks
Me Chart Albums
Me Library Artists
User Info
User Top Artists
User Top Tracks
User Top Albums
User Loved Tracks
User Friends
Artist Search
Artist Info
Artist Similar
Artist Top Albums
Artist Top Tracks
Artist Top Tags
Artist Correction
Album Search
Album Info
Album Top Tags
Track Search
Track Info
Track Similar
Track Top Tags
Track Correction
Lastfm Picker Search
GET
/lastfm/picker/search
Picker-shaped search across artists / albums / tracks.
Returns a list of {external_id, title, subtitle, thumbnail}
objects ready for the LinkSourceModal. external_id is the
canonical LastFM ref shape — lowercased name (artists) or
<artist>::<name> (albums + tracks) — produced by the same
helpers the resolver uses.
Why not consume LastFM's raw search response on the frontend? The
external_id construction has to match the resolver's
:func:lastfm_artist_id/:func:lastfm_album_id/:func:lastfm_track_id
exactly, or the picker's "Link" action would write a ref that no
subsequent lookup finds. Single source of truth → backend.
offset powers the picker's "Load more": LastFM's search methods
paginate by 1-based page, so we translate offset (which the
SPA advances in limit-sized steps) to page = offset // limit + 1.
Parameters
Query Parameters
kind*
Type
Requiredstring
q*
Type
Requiredstring
limit
Type
integer
Default
20offset
Type
integer
Default
0Responses
Successful Response
application/json
JSON { "additionalProperties": "string" }
[
]
Tag Info
Tag Similar
Tag Top Artists
Tag Top Tracks
Tag Top Albums
Tag Weekly Chart List
Chart Top Artists
Chart Top Tracks
Chart Top Tags
Geo Top Artists
Geo Top Tracks
Me Love
Me Unlove
Me Scrobble
Me Now Playing
List Favorite Artists
Favorite Artist
POST
/lastfm/me/favorites/artists
Mark an artist as favorite. Auto-fetches the artist into the catalog
if it isn't already cached (so the favorite always has hydration data).
Parameters
Request Body
application/json
JSON "artist": "string"
{
}
Responses
Successful Response
application/json
JSON "additionalProperties": "string"
{
}
Unfavorite Artist
List Favorite Albums
Favorite Album
Unfavorite Album
List Favorite Tracks
Favorite Track
Unfavorite Track
List Wishlist
Add To Wishlist
Remove From Wishlist
List Owned
Mark Owned
POST
/lastfm/me/albums/owned
Mark an album as owned. If it was on the wishlist, this transitions
it (preserving wishlisted_at as history).
Parameters
Request Body
application/json
JSON "artist": "string", "album": "string"
{
}
Responses
Successful Response
application/json
JSON "additionalProperties": "string"
{
}