Domainless Music API

Self-hosted music streaming infrastructure. Upload, transcode to multi-bitrate AAC, and stream audio with waveform generation.

https://api.music.domainless.fun/api

Authentication

JWT Bearer Token

Register or log in to receive a JWT token. Include it in requests:

Authorization: Bearer <token>

Some endpoints are public (no auth). Others accept optional auth to personalize responses.

Auth

POST /auth/register Public
Create a new account.
Request Body
{ "email": "you@example.com", "password": "...", "displayName": "DJ Name" }
Response
{ "token": "eyJ...", "user": { "id": 1, "email": "...", "display_name": "..." } }
POST /auth/login Public
Log in with existing credentials.
Request Body
{ "email": "you@example.com", "password": "..." }
Response
{ "token": "eyJ...", "user": { "id": 1, "email": "...", "display_name": "..." } }
GET /auth/me JWT
Get the current authenticated user.
Response
{ "user": { "id": 1, "email": "...", "display_name": "..." } }

Tracks

POST /tracks/upload JWT
Upload an audio file. Transcodes to AAC at 128k, 256k, and 320k with waveform generation.
Request
Content-Type: multipart/form-data

file: (binary)
title: "Track Title"
artistName: "Artist Name"
album: "Optional Album"
genre: "Optional Genre"
Response
{
  "track": {
    "id": "a1b2c3...",
    "title": "Track Title",
    "artist_name": "Artist Name",
    "status": "processing"
  }
}
Status Values

uploadingprocessingready or error

GET /tracks JWT
List your uploaded tracks.
Query Params
?page=0&limit=20  (max limit: 100)
Response
{ "tracks": [...], "total": 42 }
GET /tracks/recent Public
Get recently uploaded tracks (status: ready).
Query Params
?page=0&limit=20  (max limit: 50)
Response
{ "tracks": [{ "id": "...", "title": "...", "artist_name": "...", "play_count": 10, ... }] }
GET /tracks/trending Public
Get top 20 tracks ranked by play count.
Response
{ "tracks": [...] }
GET /tracks/search Public
Search tracks by title, artist, or album.
Query Params
?q=search+term  (min 2 chars, returns max 30 results)
Response
{ "tracks": [...] }
GET /tracks/:id Public
Get a single track's details.
Response
{
  "track": {
    "id": "a1b2c3...",
    "title": "Track Title",
    "artist_name": "Artist",
    "duration_seconds": 210.5,
    "play_count": 42,
    "waveform_data": "/audio/a1b2c3.../waveform.png",
    "cover_art": "/audio/a1b2c3.../cover.jpg",
    "status": "ready"
  }
}
GET /tracks/:id/stream Public
Stream the audio file. Returns AAC in M4A container.
Query Params
?q=256k  (options: 128k, 256k, 320k — default: 256k)
Usage
const audio = new Audio();
audio.src = 'https://api.music.domainless.fun/api/tracks/TRACK_ID/stream?q=320k';
audio.play();
POST /tracks/:id/play Optional
Log a play event for analytics. Returns 204.
Request Body
{ "duration": 45.2 }
DELETE /tracks/:id JWT
Delete a track and all transcoded files.
Response
{ "ok": true }

Playlists

POST /playlists JWT
Create a new playlist.
Request Body
{ "title": "My Playlist", "description": "Optional", "isPublic": true }
Response
{ "playlist": { "id": 1, "title": "My Playlist", "track_count": 0, ... } }
GET /playlists JWT
List your playlists.
Response
{ "playlists": [...] }
GET /playlists/public Public
Browse public playlists.
Query Params
?page=0&limit=20
Response
{ "playlists": [{ "id": 1, "title": "...", "creator_name": "...", "track_count": 5, ... }] }
GET /playlists/:id Public
Get a playlist with all its tracks.
Response
{ "playlist": { "id": 1, "title": "...", "tracks": [...], "track_count": 5, ... } }
PUT /playlists/:id JWT
Update a playlist's title, description, or visibility.
Request Body
{ "title": "New Title", "description": "...", "isPublic": false }
DELETE /playlists/:id JWT
Delete a playlist.
Response
{ "ok": true }
POST /playlists/:id/tracks JWT
Add a track to a playlist.
Request Body
{ "trackId": "a1b2c3..." }
DELETE /playlists/:id/tracks JWT
Remove a track from a playlist.
Request Body
{ "trackId": "a1b2c3..." }

Social

POST /tracks/:trackId/like JWT
Like a track.
Response
{ "liked": true, "count": 42 }
DELETE /tracks/:trackId/like JWT
Unlike a track.
Response
{ "liked": false, "count": 41 }
GET /me/likes JWT
Get your liked tracks.
Query Params
?page=0&limit=20
Response
{ "tracks": [...], "total": 15 }
POST /users/:userId/follow JWT
Follow an artist.
Response
{ "following": true, "followers": 100 }
DELETE /users/:userId/follow JWT
Unfollow an artist.
Response
{ "following": false, "followers": 99 }
GET /artists/:id Optional
Get an artist's profile with their tracks, play counts, and follower info.
Response
{
  "artist": {
    "id": 1,
    "display_name": "Artist Name",
    "track_count": 12,
    "total_plays": 5000,
    "followers": 100,
    "following": false,
    "tracks": [...]
  }
}