Bowmark AIdocs

Music (catalogue search)

Search a music catalogue by artist, title, genre or mood and get back normalized tracks — artist, public URL, duration and play count — ranked by…

Search a music catalogue by artist, title, genre or mood and get back normalized tracks — artist, public URL, duration and play count — ranked by popularity, or read one track URL you already have back to its full detail (artwork, description, genre, likes, release date, label). Direct API, no browser.

Also known as: track, song, audio, artist, playlist, tune, music track

Call it

bowmark.music.search(query: string, limit?: number, options?: CallOptions): Promise<MusicSearchResult>
bowmark.music.getTrack(track: string | Track, options?: CallOptions): Promise<MusicTrackResult>

Functions

FunctionWhat it does
searchSearches the catalogue for tracks matching free text ("aphex twin", "lofi hip hop", "80s synthwave") and returns up to limit normalized tracks (default 20, max 200), most-played first.
getTrackReads ONE track you already have a URL for — a public track link, or a Track that search returned — and returns the full detail a search row never carried: artwork, the publisher's…

Types

type Track = {
  source: "soundcloud"        // which catalogue this came from
  id: string                  // that catalogue's id for the track
  title: string               // track title as published
  artist: string              // publishing artist or account
  url: string                 // public track page
  durationMs: number          // length in milliseconds
  playCount: number | null    // plays; null when not reported (never 0)
}
type MusicSearchResult = {
  tracks: Track[]             // most-played first
  warnings: string[]          // always present; empty when nothing was dropped. A
                              // catalogue named here returned NOTHING, which is a
                              // different fact from a query with no matches
}

type CallOptions = {
  timeoutMs?: number   // per-provider budget in ms, default 30000, clamped to 1000-55000.
                       // A provider slower than this is DROPPED from the results and
                       // NAMED in warnings — never silently absent
}

// What getTrack adds: the fields only a detail view carries. Every one is
// nullable because catalogues genuinely omit them — null means "this catalogue
// does not report it", never "we failed to read it".
type TrackDetail = Track & {
  artworkUrl: string | null       // cover art; null when published without any
  description: string | null      // publisher's notes — a mix's tracklist lives here
  genre: string | null
  likeCount: number | null        // null when not reported (never 0)
  releaseDate: string | null      // for a reissue, the ORIGINAL release date
  publisherArtist: string | null  // label credit ("Aphex Twin") vs account ("aphextwin")
  labelName: string | null
}
type MusicTrackResult = {
  track: TrackDetail
  warnings: string[]          // always present; names the fields left unreported
}

Examples

// Build a listening shortlist: search several moods at once, keep the most
// played track per mood, and total the runtime.
const moods = ["lofi hip hop", "ambient techno", "80s synthwave", "bossa nova"];
const picks = await Promise.all(moods.map(async (mood) => {
  const { tracks, warnings } = await bowmark.music.search(mood, 25);
  for (const w of warnings) log(`${mood}: ${w}`);
  const top = tracks[0] || null;
  log(`${mood}: ${top ? top.artist + " — " + top.title : "no matches"}`);
  return top ? { mood, artist: top.artist, title: top.title, url: top.url, durationMs: top.durationMs, plays: top.playCount } : { mood, artist: null, durationMs: 0 };
}));
const found = picks.filter(p => p.artist);
return { totalMinutes: Math.round(found.reduce((s, p) => s + p.durationMs, 0) / 60000), picks: found };
// Credit a set properly: search finds the upload, getTrack says who actually
// published it and when — the account that uploaded a reissue is not the artist,
// and the release date is the ORIGINAL one, not the upload day.
const { tracks } = await bowmark.music.search("selected ambient works", 10);
const detailed = [];
for (const t of tracks.slice(0, 3)) {
  const { track, warnings } = await bowmark.music.getTrack(t);
  for (const w of warnings) log(w);
  detailed.push({
    title: track.title,
    uploadedBy: track.artist,
    credited: track.publisherArtist ?? "(the catalogue names no publisher)",
    label: track.labelName,
    released: track.releaseDate,
    artwork: track.artworkUrl,
  });
}
return detailed;

Providers behind it

Provider
soundcloudSoundCloud