Lookup · playback

A title and a hint in. A confirmed play out.

Submit { name, artist?, album?, year? } and get back one fully populated result per item, in order, each with its own status. Issue a playback command and get the player state that confirms it took effect.

Python 3.12+ Serves on :8007 No credential of its own MIT licensed
POST /v1/lookup
{
  "items": [
    { "name": "Bohemian Rhapsody", "artist": "Queen", "year": 1975 },
    { "name": "Redbone" },
    { "name": "a track that does not exist" }
  ]
}

# three results, in order, each with its own status
Only a name is requiredArtist, album and year are hints that narrow the search.
Partial successOne item that cannot be resolved does not fail the batch.
Confirmed, not assumedA command answers with the player state that shows it took effect.
Your account, your tokenKeyring hands over the headers for that person's own connection.

How it works

It implements the family's music contract.

The LUCY hub speaks to music through a contract, not a named service; this is the implementation of it for Spotify. Every request carries the caller's token, verified locally against the keys keyring publishes.

01

Messy metadata in

A track title, maybe an artist, maybe a year, from a spreadsheet, a playlist export or someone typing.

02

Canonical data out

IDs, URIs, ISRCs, album and release date, duration and popularity, one result per item, in order.

03

Playback that answers honestly

Play, pause, seek, queue and transfer each answer with the player state that confirms the command, rather than a bare acknowledgement.

The API

A contract that is deliberately boring and stable.

The OpenAPI schema is complete enough to generate a client from. The reference is docs/api.md.

POST /v1/lookup

Lookup

Resolve a batch of tracks, with partial success.

GET /v1/player

Playback state

The player, its devices, what is playing, the queue and what was played recently.

POST /v1/player/play

Commands

Play, pause, next, previous, seek, volume, shuffle, repeat, transfer and queue, each confirmed.

GET /v1/jobs

Jobs

Poll or cancel work started with ?async=true.

GET /ready

Health

GET /healthy and GET /ready need no token.

401 · 503

Refusals

A token keyring did not mint for this service is a 401 with one fixed message; keyring's keys being unreachable is a 503.

Run it

Clone, install, point it at keyring.

You need Python 3.12 or newer and uv. Spotify access belongs to a person and lives in keyring, never here.

  1. Clone and install.
    git clone https://github.com/tochi-mba/Spotify-api.git && cd Spotify-api && make install
  2. Point it at keyring.
    cp .env.example .env
  3. Serve it; the interactive docs are at /docs.
    make run

Register the service with keyring, connect Spotify to a profile through keyring's consent flow, then call this service with a token minted for the audience spotify-api. The README has the three steps in full.

What to know first

What to know before you lean on it.

Does it store my Spotify credentials?

No. It holds no Spotify credential of its own. Keyring holds the connection and hands over the headers to attach, per request, for that person.

What does a playback command return?

The player state that confirms the command took effect. A command whose effect cannot be confirmed says so, rather than reporting success.

Which tokens does it accept?

Only one keyring minted for this service: RS256, with the issuer and the audience pinned and the expiry checked, before any work starts.

Is it affiliated with Spotify?

No. It is independent software that uses the Spotify Web API, and is not affiliated with or endorsed by Spotify.

Docs

Written for the person who has to run it.