Skip to content

API Contracts ​

TuneCamp exposes a RESTful API for webapp–backend communication, plus dedicated endpoints for ActivityPub and the Subsonic protocol. The full OpenAPI specification is in openapi.yml.

Authentication ​

Most endpoints require a JWT (JSON Web Token) in the Authorization header:

Authorization: Bearer <token>

Obtain a token by posting credentials to POST /api/auth/login.


Core Endpoints ​

Authentication (/api/auth) ​

MethodPathDescription
POST/api/users/registerRegister a new user
POST/api/auth/loginAuthenticate and receive a JWT
GET/api/auth/statusReturn the current session and user profile

Music Catalog (/api/catalog, /api/tracks, /api/albums) ​

MethodPathDescription
GET/api/albumsList all local albums. Returns status (draft | published) and is_release (boolean) to distinguish library content from official releases
GET/api/albums/:idAlbum details including the track list
GET/api/artistsList all artists
POST/api/tracksCreate a track from metadata (a link, or a row awaiting its file). The audio is not fetched: the track is created with no file_path until a file is uploaded for it. There is no localize option here β€” this server does not download audio from streaming platforms
GET/api/tracksList tracks visible to the caller. Each row carries downloadable: whether THIS viewer may take the file, not just stream it (clients offering a download button read it instead of guessing)
GET/api/tracks/:idTrack metadata
GET/api/tracks/:id/streamBinary audio stream (supports Range for cloud tracks)
GET/api/tracks/:id/downloadDownload a single track's local audio file. Gated by the release's distribution mode: paid content needs an unlock code (?code=), a recorded purchase or an active subscription (402 otherwise), streaming-only and external-showcase releases answer 403. Staff, the owner and the linked artist bypass it
POST/api/tracks/:id/localizeAdmin-only: copy a cloud-backed track (a gdrive:// path) into a durable local file. Streaming platforms are refused with 400 β€” use Sidecamp
GET/api/albums/:id/downloadDownload a ZIP of the album's local audio files (skips streaming/linked tracks). Same distribution-mode gate as the single-track route
GET/api/releases/:id/downloadDownload a ZIP of a release's local audio files. Resolves numeric id or slug; private releases gated to owner/admin, and the same distribution-mode gate as the single-track route applies
GET/api/waveform/:idWaveform data for visualisation
GET/api/releases/:id/artwork/:filenameServe additional release artwork securely

Free Samples (/api/samples) ​

MethodPathDescription
GET/api/samplesList approved samples. mine=true scopes to the caller's own uploads (any status); q filters by search term
GET/api/samples/moderation/pendingRoot-admin/admin/super-user: list samples awaiting curation
GET/api/samples/:idSample metadata
GET/api/samples/:id/downloadDownload the sample audio file. Supports ?token= query auth (approved samples are public; pending samples require the owner or a moderator)
POST/api/samplesUpload a sample (multipart/form-data: file, title, description, bpm, musicalKey, license, attributionName, tags). Starts in pending status
PUT/api/samples/:idUpdate sample metadata (owner or moderator)
DELETE/api/samples/:idDelete a sample (owner or moderator)
POST/api/samples/:id/approveRoot-admin/admin/super-user: approve a pending sample
POST/api/samples/:id/rejectRoot-admin/admin/super-user: reject a pending sample with optional notes

Free samples are not store assets: no price, no purchase flow, no credits. License is one of cc0, cc-by, cc-by-sa, royalty-free. Upload is reachable from /publish; managing your own uploads is under the "Samples" tab on /my-music; moderation is under "Sample Curation" on /admin.

Sample Packs (/api/sample-packs) ​

MethodPathDescription
GET/api/sample-packsList approved packs. mine=true scopes to the caller's own packs (any status); q filters by search term
GET/api/sample-packs/moderation/pendingRoot-admin/admin/super-user: list packs awaiting curation
GET/api/sample-packs/:idPack metadata plus its member samples
GET/api/sample-packs/:id/coverPack cover image; falls back to a generated placeholder SVG if none is set
POST/api/sample-packsUpload multiple files at once as a pack (multipart/form-data: files[], title, description, license, attributionName). Same publish gate and auto-approve rules as /api/samples; starts in pending unless auto-approved
POST/api/sample-packs/:id/coverSet/replace the pack cover image (multipart/form-data: cover). Owner/moderator only
PUT/api/sample-packs/:idUpdate pack metadata (owner or moderator)
DELETE/api/sample-packs/:idDelete a pack and all its member samples (owner or moderator)
POST/api/sample-packs/:id/approveRoot-admin/admin/super-user: approve a pending pack (cascades to its samples)
POST/api/sample-packs/:id/rejectRoot-admin/admin/super-user: reject a pending pack with optional notes

A packed sample (samples.pack_id set) is excluded from the public /api/samples listing β€” it only surfaces through its pack.

Collab (/api/collab) ​

All routes require login. See COLLAB.md for the full feature writeup.

MethodPathDescription
GET/api/collabList shared projects. mine=true scopes to the caller's own
GET/api/collab/:idProject metadata plus its versions and stems
POST/api/collabCreate a project (requires canPublishContent)
DELETE/api/collab/:idDelete a project and its stems (owner only)
POST/api/collab/:id/versionsSave an append-only version snapshot (state, optional note)
POST/api/collab/:id/stemsUpload an audio stem (multipart/form-data: file, optional name)
GET/api/collab/:id/stems/:stemId/downloadStream a stem's audio
DELETE/api/collab/:id/stems/:stemIdDelete a stem (stem author or project owner)

Payments & Monetisation (/api/payments) ​

MethodPathDescription
POST/api/payments/stripe/create-sessionCreate a Stripe Checkout session for fiat purchases
POST/api/payments/stripe/create-trackcap-sessionCreate a Stripe Checkout session to buy extra track-upload slots
GET/api/payments/onramp-configStripe Crypto Onramp configuration
POST/api/payments/verifyVerify an on-chain transaction (ETH/USDC) on Base
GET/api/payments/download/:trackId?code=...Download a purchased track via unlock code
GET/api/payments/rate/USDCurrent ETH/USD exchange rate

Storage & Cloud (/api/storage) ​

MethodPathDescription
GET/api/storage/gdrive/authStart the Google Drive OAuth2 flow
GET/api/storage/gdrive/filesList files and folders on Google Drive
POST/api/storage/gdrive/importImport a Drive file as a gdrive:// reference
POST/api/storage/gdrive/localize/:idPermanently download a cloud file to the local server

Metadata & External Search (/api/metadata) ​

MethodPathDescription
GET/api/metadata/search?q=...Search album metadata across external providers (MusicBrainz, Discogs, iTunes, TheAudioDB)
GET/api/metadata/lyrics?artist=...&title=...Fetch song lyrics via Lyrics.ovh
POST/api/metadata/applyApply selected metadata to a local track

Social, Comments & Posts (/api/artists, /api/comments, /api/ap) ​

MethodPathDescription
GET/api/artists/:id/postsList an artist's public posts
POST/api/admin/postsCreate a new post (admin only)
GET/api/comments/track/:trackIdList comments for a specific track
POST/api/comments/track/:trackIdAdd a comment (requires authentication)
GET/api/ap/timeline/:artistIdRecent activity from followed actors
GET/api/ap/users/:slugActivityPub profile (actor) for a local user
POST/api/ap/inboxReceive incoming remote ActivityPub messages
POST/api/releases/:id/reportReport a release for copyright or inappropriate content
GET/api/admin/reportsList all active release reports (admin only)
DELETE/api/admin/reports/:idResolve or dismiss a report (admin only)

Administration (/api/admin) ​

MethodPathDescription
GET/api/admin/system/usersList registered users (admin only)
POST/api/admin/system/rescanTrigger a full library rescan
POST/api/admin/upload/tracksStore one or more audio files and scan them into the library (admin/artist only). releaseSlug links them to a release; artist/album name the container. title and trackNum set one track's title and position and are honoured only when a single file is sent β€” with several files each one keeps its own tags. Used by the release editor to fill an imported tracklist, whose files are rarely tagged the way the release lists them
POST/api/admin/upload/additional-artworksUpload multiple additional artworks/booklets for a release (admin/artist only)
GET/api/admin/statsServer and database usage statistics
GET/api/admin/system/resourcesLive process/host resource snapshot β€” CPU, memory, host RAM, SQLite DB size, and running background tasks (root admin only)
GET/api/admin/storage/overviewInstance-wide disk usage and per-user breakdown (root admin only)

P2P content acquisition (Soulseek, BitTorrent, yt-dlp) has moved out of the backend into the Sidecamp desktop app; the former /api/admin/torrents* endpoints no longer exist.

Radio (/api/radio) ​

A single always-on station that streams the instance's catalog. Start/stop is admin-only; the stream and feeds are public.

MethodPathDescription
GET/api/radioCurrent station status (playing track, listener count)
POST/api/radio/startStart the station (admin only)
POST/api/radio/stopStop the station (admin only)
GET/api/radio/stream.m3uM3U playlist for external players
GET/api/radio/feed.rssRSS feed of the station
GET/api/radio/hls/:fileHLS playlist/segments for in-browser playback

Third-Party Protocols ​

Subsonic API (/rest) ​

TuneCamp implements the Subsonic protocol (v1.16.1) for compatibility with existing mobile clients such as DSub, Symfonium, Tempo, and Substreamer.

  • Base path: /rest/*.view
  • Supported methods include: getAlbumList, getMusicDirectory, stream, and more.

See SUBSONIC.md for the full compatibility table.

Model Context Protocol (/api/mcp) ​

TuneCamp implements MCP so that external AI clients can query the catalog and server statistics.

MethodPathDescription
GET/api/mcp/sseOpen the async SSE channel. Requires Bearer tc_... authentication
POST/api/mcp/messageSend a JSON-RPC request from client to server

See mcp-setup-guide.md for client configuration.


Response Format ​

All API responses (except audio streams) are JSON. On error, the server returns an appropriate HTTP status code and an error object:

json
{
  "error": "Descriptive error message"
}

Released under the MIT License.