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) β
| Method | Path | Description |
|---|---|---|
POST | /api/users/register | Register a new user |
POST | /api/auth/login | Authenticate and receive a JWT |
GET | /api/auth/status | Return the current session and user profile |
Music Catalog (/api/catalog, /api/tracks, /api/albums) β
| Method | Path | Description |
|---|---|---|
GET | /api/albums | List all local albums. Returns status (draft | published) and is_release (boolean) to distinguish library content from official releases |
GET | /api/albums/:id | Album details including the track list |
GET | /api/artists | List all artists |
POST | /api/tracks | Create 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/tracks | List 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/:id | Track metadata |
GET | /api/tracks/:id/stream | Binary audio stream (supports Range for cloud tracks) |
GET | /api/tracks/:id/download | Download 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/localize | Admin-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/download | Download 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/download | Download 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/:id | Waveform data for visualisation |
GET | /api/releases/:id/artwork/:filename | Serve additional release artwork securely |
Free Samples (/api/samples) β
| Method | Path | Description |
|---|---|---|
GET | /api/samples | List approved samples. mine=true scopes to the caller's own uploads (any status); q filters by search term |
GET | /api/samples/moderation/pending | Root-admin/admin/super-user: list samples awaiting curation |
GET | /api/samples/:id | Sample metadata |
GET | /api/samples/:id/download | Download the sample audio file. Supports ?token= query auth (approved samples are public; pending samples require the owner or a moderator) |
POST | /api/samples | Upload a sample (multipart/form-data: file, title, description, bpm, musicalKey, license, attributionName, tags). Starts in pending status |
PUT | /api/samples/:id | Update sample metadata (owner or moderator) |
DELETE | /api/samples/:id | Delete a sample (owner or moderator) |
POST | /api/samples/:id/approve | Root-admin/admin/super-user: approve a pending sample |
POST | /api/samples/:id/reject | Root-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) β
| Method | Path | Description |
|---|---|---|
GET | /api/sample-packs | List approved packs. mine=true scopes to the caller's own packs (any status); q filters by search term |
GET | /api/sample-packs/moderation/pending | Root-admin/admin/super-user: list packs awaiting curation |
GET | /api/sample-packs/:id | Pack metadata plus its member samples |
GET | /api/sample-packs/:id/cover | Pack cover image; falls back to a generated placeholder SVG if none is set |
POST | /api/sample-packs | Upload 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/cover | Set/replace the pack cover image (multipart/form-data: cover). Owner/moderator only |
PUT | /api/sample-packs/:id | Update pack metadata (owner or moderator) |
DELETE | /api/sample-packs/:id | Delete a pack and all its member samples (owner or moderator) |
POST | /api/sample-packs/:id/approve | Root-admin/admin/super-user: approve a pending pack (cascades to its samples) |
POST | /api/sample-packs/:id/reject | Root-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.
| Method | Path | Description |
|---|---|---|
GET | /api/collab | List shared projects. mine=true scopes to the caller's own |
GET | /api/collab/:id | Project metadata plus its versions and stems |
POST | /api/collab | Create a project (requires canPublishContent) |
DELETE | /api/collab/:id | Delete a project and its stems (owner only) |
POST | /api/collab/:id/versions | Save an append-only version snapshot (state, optional note) |
POST | /api/collab/:id/stems | Upload an audio stem (multipart/form-data: file, optional name) |
GET | /api/collab/:id/stems/:stemId/download | Stream a stem's audio |
DELETE | /api/collab/:id/stems/:stemId | Delete a stem (stem author or project owner) |
Payments & Monetisation (/api/payments) β
| Method | Path | Description |
|---|---|---|
POST | /api/payments/stripe/create-session | Create a Stripe Checkout session for fiat purchases |
POST | /api/payments/stripe/create-trackcap-session | Create a Stripe Checkout session to buy extra track-upload slots |
GET | /api/payments/onramp-config | Stripe Crypto Onramp configuration |
POST | /api/payments/verify | Verify 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/USD | Current ETH/USD exchange rate |
Storage & Cloud (/api/storage) β
| Method | Path | Description |
|---|---|---|
GET | /api/storage/gdrive/auth | Start the Google Drive OAuth2 flow |
GET | /api/storage/gdrive/files | List files and folders on Google Drive |
POST | /api/storage/gdrive/import | Import a Drive file as a gdrive:// reference |
POST | /api/storage/gdrive/localize/:id | Permanently download a cloud file to the local server |
Metadata & External Search (/api/metadata) β
| Method | Path | Description |
|---|---|---|
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/apply | Apply selected metadata to a local track |
Social, Comments & Posts (/api/artists, /api/comments, /api/ap) β
| Method | Path | Description |
|---|---|---|
GET | /api/artists/:id/posts | List an artist's public posts |
POST | /api/admin/posts | Create a new post (admin only) |
GET | /api/comments/track/:trackId | List comments for a specific track |
POST | /api/comments/track/:trackId | Add a comment (requires authentication) |
GET | /api/ap/timeline/:artistId | Recent activity from followed actors |
GET | /api/ap/users/:slug | ActivityPub profile (actor) for a local user |
POST | /api/ap/inbox | Receive incoming remote ActivityPub messages |
POST | /api/releases/:id/report | Report a release for copyright or inappropriate content |
GET | /api/admin/reports | List all active release reports (admin only) |
DELETE | /api/admin/reports/:id | Resolve or dismiss a report (admin only) |
Administration (/api/admin) β
| Method | Path | Description |
|---|---|---|
GET | /api/admin/system/users | List registered users (admin only) |
POST | /api/admin/system/rescan | Trigger a full library rescan |
POST | /api/admin/upload/tracks | Store 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-artworks | Upload multiple additional artworks/booklets for a release (admin/artist only) |
GET | /api/admin/stats | Server and database usage statistics |
GET | /api/admin/system/resources | Live process/host resource snapshot β CPU, memory, host RAM, SQLite DB size, and running background tasks (root admin only) |
GET | /api/admin/storage/overview | Instance-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.
| Method | Path | Description |
|---|---|---|
GET | /api/radio | Current station status (playing track, listener count) |
POST | /api/radio/start | Start the station (admin only) |
POST | /api/radio/stop | Stop the station (admin only) |
GET | /api/radio/stream.m3u | M3U playlist for external players |
GET | /api/radio/feed.rss | RSS feed of the station |
GET | /api/radio/hls/:file | HLS 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.
| Method | Path | Description |
|---|---|---|
GET | /api/mcp/sse | Open the async SSE channel. Requires Bearer tc_... authentication |
POST | /api/mcp/message | Send 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:
{
"error": "Descriptive error message"
}