API Reference
The Watermelon server provides a RESTful API for the Android app to search, stream, and download music. By default it runs on port 3000.
Base URL
When self-hosting, the base URL is your server address:
http://your-server.com:3000Endpoints
Health Check
GET /
GET /health
Returns a simple 200 OK to verify the server is running.
curl http://localhost:3000/healthResponse:
"OK"Search
Search Songs
GET /search/songs?q={query}
Returns a list of songs matching the search query.
Query Parameters:
| Parameter | Type | Required | Description |
|---|---|---|---|
q | string | Yes | The song search query |
curl "http://localhost:3000/search/songs?q=never+gonna+give+you+up"Response:
[
{
"id": "dQw4w9WgXcQ",
"title": "Never Gonna Give You Up",
"artist": "Rick Astley",
"thumbnail": "https://img.youtube.com/vi/dQw4w9WgXcQ/0.jpg",
"duration": 213
}
]Search Artists
GET /search/artists?q={query}
Returns artists matching the search query.
Query Parameters:
| Parameter | Type | Required | Description |
|---|---|---|---|
q | string | Yes | The artist search query |
curl "http://localhost:3000/search/artists?q=rick+astley"Search Albums
GET /search/albums?q={query}
Returns albums matching the search query.
Query Parameters:
| Parameter | Type | Required | Description |
|---|---|---|---|
q | string | Yes | The album search query |
curl "http://localhost:3000/search/albums?q=whenever+you+need+somebody"Search Playlists
GET /search/playlists?q={query}
Returns YouTube playlists matching the search query.
Query Parameters:
| Parameter | Type | Required | Description |
|---|---|---|---|
q | string | Yes | The playlist search query |
curl "http://localhost:3000/search/playlists?q=best+of+80s"Song Metadata
GET /song/{videoId}
Returns metadata for a specific YouTube video.
Path Parameters:
| Parameter | Type | Description |
|---|---|---|
videoId | string | The YouTube video ID |
curl "http://localhost:3000/song/dQw4w9WgXcQ"Stream
GET /stream/{id}
Streams audio for a given track ID. This endpoint is proxied through yt-dlp to extract the audio stream URL from YouTube Music.
Path Parameters:
| Parameter | Type | Description |
|---|---|---|
id | string | The track ID to stream |
curl "http://localhost:3000/stream/dQw4w9WgXcQ" \
-H "Range: bytes=0-"Headers:
| Header | Description |
|---|---|
Range | Optional byte range for seeking |
Response: Audio stream with audio/mpeg content type. Supports HTTP range requests for seeking.
Download
GET /download/{id}
Downloads the audio file for a given track ID. Returns the file as an attachment.
Path Parameters:
| Parameter | Type | Description |
|---|---|---|
id | string | The track ID to download |
curl "http://localhost:3000/download/dQw4w9WgXcQ" \
-o "song.mp3"Response: Audio file served with Content-Disposition: attachment header.
Radio
Search Radio Stations
GET /radio/search?q={query}
Searches radio stations via Radio Browser API.
curl "http://localhost:3000/radio/search?q=jazz"Browse Radio Stations
GET /radio/stations
Returns a list of radio stations.
curl "http://localhost:3000/radio/stations"AI Recommendations
POST /api/recommendations
Generates AI-powered song recommendations using Gemini 2.5 Flash based on the currently playing song.
Request Body:
| Field | Type | Required | Description |
|---|---|---|---|
title | string | Yes | Current song title |
artist | string | Yes | Current song artist |
language | string | No | Song language |
genre | string | No | Song genre |
curl -X POST "http://localhost:3000/api/recommendations" \
-H "Content-Type: application/json" \
-d '{"title":"Never Gonna Give You Up","artist":"Rick Astley"}'Response: Array of resolved YouTube search results.
Payments
Create Payment Order
POST /payments/create
Creates a Razorpay payment order.
Request Body:
| Field | Type | Required | Description |
|---|---|---|---|
userId | string | No | User UUID |
amount | int | Yes | Amount in paise (min 100) |
currency | string | No | Currency code (default INR) |
plan | string | No | Plan identifier |
curl -X POST "http://localhost:3000/payments/create" \
-H "Content-Type: application/json" \
-d '{"amount":49900,"currency":"INR","plan":"PREMIUM_INDIVIDUAL"}'Response:
{
"success": true,
"orderId": "order_xxx",
"amount": 49900,
"currency": "INR"
}Verify Payment
POST /payments/verify
Verifies a Razorpay payment signature and submits for admin approval.
Request Body:
| Field | Type | Required | Description |
|---|---|---|---|
orderId | string | Yes | Razorpay order ID |
paymentId | string | Yes | Razorpay payment ID |
signature | string | Yes | Payment signature |
email | string | Yes | User email |
userId | string | No | User UUID |
plan | string | No | Plan identifier |
curl -X POST "http://localhost:3000/payments/verify" \
-H "Content-Type: application/json" \
-d '{
"orderId": "order_xxx",
"paymentId": "pay_xxx",
"signature": "sig_xxx",
"email": "user@example.com"
}'Authentication
Delete User Account
DELETE /auth/delete-user
POST /auth/delete-user
Deletes the authenticated user’s account. Requires a valid Supabase JWT in the Authorization header.
Headers:
| Header | Required | Description |
|---|---|---|
Authorization | Yes | Bearer <supabase-jwt> |
curl -X DELETE "http://localhost:3000/auth/delete-user" \
-H "Authorization: Bearer your-jwt-token"Response:
{ "success": true, "message": "User deleted successfully" }Stats
GET /stats
Returns aggregate app usage statistics.
curl "http://localhost:3000/stats"Response:
{
"totalUsers": 6,
"paidUsers": 0,
"freeUsers": 6,
"totalPlaylists": 0,
"totalFavorites": 1,
"totalStreams": 36,
"refreshedAt": "2026-06-20T07:40:53Z"
}Error Handling
All endpoints return standard HTTP status codes:
| Status | Meaning |
|---|---|
200 | Success |
400 | Bad Request — Missing or invalid parameters |
401 | Unauthorized — Missing or invalid auth token |
404 | Not Found — Song or resource not found |
500 | Server Error — yt-dlp or internal error |
Error Response:
{
"error": "Song not found",
"message": "The requested song ID does not exist"
}Architecture
The API server is built with:
- Node.js + Express — Lightweight REST API
- yt-dlp — Extracts audio URLs from YouTube Music
- NewPipe Extractor — Alternative extraction backend
- Supabase — PostgreSQL database for playlists, favorites, and user data
- Razorpay SDK — Payment processing for premium subscriptions
- Telegram Bot API — Optional bot commands for remote search
- Gemini AI — AI-powered song recommendations
Credits
The Watermelon API is powered by these amazing open-source tools:
| Project | What it does for us | Link |
|---|---|---|
| Express.js | Lightweight REST API framework | expressjs.com |
| yt-dlp | Extracts audio streams from YouTube Music | github.com/yt-dlp/yt-dlp |
| NewPipe Extractor | Alternative extraction backend | github.com/TeamNewPipe/NewPipeExtractor |
| Supabase | PostgreSQL database & auth | supabase.com |
| Razorpay SDK | Payment processing for premium | razorpay.com |
| Telegram Bot API | Remote bot commands | core.telegram.org/bots |
| Node.js | JavaScript runtime for the backend | nodejs.org |
⭐ These tools make self-hosted music streaming possible. Consider supporting their developers.