API reference

Everything a deck will answer.

288 operations across 227 paths. The deck is the server, so anything the web UI does, a client of yours can do too.

Describes v0.120.0. Your own deck is the authority on what it runs — ask it for GET /api/openapi.yaml and you get this document as that binary actually serves it.

Self-hosted scrobbler and listening journal.

Tapedeck ingests listens, enriches them with MusicBrainz metadata, stores them in SQLite and forwards them to Last.fm / ListenBrainz / Libre.fm. It also records how you listened — signal chains, gear, audio quality — which is the part no other scrobbler models.

Three auth mechanisms, and they are not interchangeable

How Reaches
Session cookie td_session, set by POST /api/v1/auth/login everything
API token Authorization: Token <t> /1/*, plus whatever its scopes allow
Metrics bearer Authorization: Bearer <t> GET /metrics only

Token scopes

tokens.scopes is a space- or comma-separated set. Three grants matter, and none of them implies another:

  • submit — post listens (POST /1/submit-listens). Every scrobble client has this; it must not carry the power to delete the history it appends to.
  • read (since v0.37) — read your own data on the endpoints whose security lists apiToken: [read].
  • write (since v0.39) — change your own data on the endpoints whose security lists apiToken: [write].

all grants both read and write. Matching is exact — a scope of rewrite does not grant write.

A valid token that lacks the required scope gets 403, not 401. It authenticated fine and re-authenticating will not help; a 401 would send a client into a token-refresh loop it cannot win.

What a token can never reach

Everything under /admin/, plus your sources, your forwarding connections, Discogs credentials, data export/backup, the sanitiser and the enrichment jobs. Those are session-only, permanently. A leaked token is a bad afternoon; a leaked token that can mint more tokens, read another household member's data, or repoint where your listens are forwarded is a different category. Requests to them with a token get 401.

Getting a token

Two ways, and neither asks anyone to type a token by hand:

  • Device-code pairing — POST /1/pair/start, poll /1/pair/poll while the user approves the short code in Settings. For clients with no browser.
  • Password → token — post credentials to POST /api/v1/auth/login, then mint a named token. This is the phone's flow. A named token appears in Settings and can be revoked when the device is lost; a session cookie expires hard at 7 days with no sliding renewal and cannot be told apart from any other browser.

Conventions

  • Timestamps are Unix seconds, UTC, and always the start of play.
  • Errors are { "code": <int>, "error": "<message>" } with a matching HTTP status.
  • Every user-scoped query is filtered by the caller's own user_id. Scopes widen who may ask, never whose data is returned.
  • Counting endpoints exclude skipped listens (skipped = FALSE).
  • Extra keys may appear in any response body; ignore what you do not know.

Instance-specific

GET /api/openapi.yaml serves this document from the running binary, so a client can ask its own server what that version supports rather than guessing from a hosted copy.

The document is generated from the handlers themselves: every schema in it is the type the server actually reads or writes, so a field documented here is a field that exists.

Credentials

Three mechanisms, and they are not interchangeable. Each endpoint below says which it takes.

Token

header · Authorization

Authorization: Token <token>. What the token reaches depends on its scopes — see the description at the top of this document. Lowercase token is also accepted.

MCP bearer

http · bearer

An MCP connection credential, from Settings → AI Connections or from the OAuth flow. Checked against mcp_connections — not against tokens, which is a separate credential store for scrobble clients.

Used by POST /mcp and nothing else. A 401 from that endpoint carries WWW-Authenticate with a resource_metadata pointer, which is how a client discovers the authorization server.

Metrics bearer

http · bearer

Authorization: Bearer $TAPEDECK_METRICS_TOKEN, for GET /metrics only. An admin session also works. Never open.

Session

cookie · td_session

Set by POST /api/v1/auth/login. HttpOnly, SameSite=Lax, and Secure when the instance can tell the browser used HTTPS (derived from X-Forwarded-Proto, and only trusted when trust_proxy is set — behind a tunnel the origin sees plain HTTP while the client is on TLS). Expires hard at 7 days with no sliding renewal.

By area

Auth

5

Login, first-run setup, session state.

ListenBrainz

9

ListenBrainz-compatible surface under /1/. Shapes follow the LB Core API because clients branch on those exact fields. Two deliberate divergences: these require auth and are scoped to the caller (LB serves them publicly; a self-hosted instance must not), and an invalid token on validate-token is 200 {valid:false}, never 401, because clients read the field.

Pairing

4

Device-code pairing for clients with no browser.

Patch

46

Patch — following people, on this instance and others. The ActivityPub surface (/users/…, /.well-known/webfinger) is unauthenticated and lets another server find out who somebody here is and say something to them; the rest is the session-only local half: the Reel, decks, Dubs and Shared Spools.

Every federated endpoint is off until a user switches federation on, and an account that has not is indistinguishable from one that does not exist — the same rule the public now-playing widget and device pairing follow.

Account

6

Your own account — password, display name, bio, profile picture. Scoped to the caller and never takes an id, unlike the admin routes under /admin/users. Session-only: a scrobble client has no business changing the credential it authenticates with.

Listens

14

The scrobble history — read, edit, delete, search.

Statistics

13

Aggregations, charts, personality.

Library

16

Album, artist and entity pages.

Loves

8

Loved recordings, releases and artists.

Notes

9

Liner notes — your own writing about records.

Sessions

7

Contiguous listening, grouped.

Chains

21

Signal chains, gear, devices and bindings.

Shelf

29

Records, tapes and discs — a shelf you catalogue and sides you play.

Genre map

3

Every Noise at Once — coverage, colour, trajectory, neighbours.

Rediscovery

2

Five lists, all built from your own history.

Sources

5

Where listens are polled from. Session-only — holds credentials.

Connections

15

Where listens are forwarded. Session-only — holds credentials.

Import & export

8

Bulk in and out. Session-only.

Maintenance

9

Enrichment backfills and the metadata sanitiser. Session-only.

Settings

7

Preferences and artwork.

Admin

19

Users, tokens, genre-map scrape. Session-only, admin role.

MCP

7

The Model Context Protocol surface — one endpoint that lets an AI assistant read this user's listening and hand playlists back. Runs for every user, reaches nobody's data until they authorise a connection.

Dual-era. Revision 2026-07-28 is stateless with per-request _meta and mirrored headers; 2025-11-25 and earlier open with an initialize handshake. Both are served on the same endpoint.

Credentials live in mcp_connections, not in tokens — an MCP grant is a standing permission given to somebody else's service, tokens.scopes treats all as a wildcard, and an OAuth credential expires and refreshes.

OAuth

7

An OAuth 2.1 authorization server, scoped to one job: letting a hosted assistant obtain an MCP credential. PKCE S256 only, public clients only, exact redirect_uri matching, single-use codes.

Playlists

10

Playlists that live in Tapedeck, reviewed before they reach a media server, plus the direct push that has always existed.

Crate

4

Records and artists somebody suggested that you do not own — the one place in Tapedeck that names music outside the collection.

Tapedeck does not recommend; it records recommendations made to you. The vision rule governs what Tapedeck generates (Rediscovery is built entirely from your own history and stays that way); this stores what an assistant said, the way notes store what you wrote. It is its own table, its own endpoints and its own page, and never appears in a history or statistics readout.

Ops

5

Health, metrics, log level.