Vexora is a mood-based music recommendation system that uses facial emotion detection to suggest personalized music
playlists. The system leverages CNN for emotion detection.

- π€ User authentication and profile management
- π Facial emotion detection using CNN
- π΅ Mood-based music recommendations
- π Music history tracking
- πΌ Playlist management
- Happy π
- Sad π’
- Angry π
- Neutral/Calm π
- Fiber Go
- PostgreSQL
- Redis
- ImageKit
docker compose watch
The API uses JWT Bearer token authentication. Include your token in the Authorization header:
Authorization: Bearer <your_token>
POST /registerRequest Body:
{
"name": "John Doe",
"email": "john@example.com",
"username": "john_doe",
"password": "********"
}Success Response (200):
{
"success": true,
"shouldNotify": true,
"message": "register success!",
"data": {
"id": 1,
"profile_picture": "https://example.com/default.jpg",
"file_id": "abc123",
"name": "John Doe",
"email": "john@example.com",
"username": "john_doe",
"created_at": "2024-01-01T00:00:00Z"
}
}Error Response (400):
{
"success": false,
"shouldNotify": true,
"message": "username or email already exists",
"data": null
}POST /loginRequest Body:
{
"username": "john_doe",
"password": "********"
}Success Response (200):
{
"success": true,
"shouldNotify": true,
"message": "login success!",
"data": {
"access_token": "eyJhbGciOiJIUzI1NiIs...",
"refresh_token": "eyJhbGciOiJIUzI1NiIs..."
}
}Error Response (401):
{
"success": false,
"shouldNotify": true,
"message": "invalid username or password",
"data": null
}POST /logoutRequest Body:
{
"refresh_token": "eyJhbGciOiJIUzI1NiIs..."
}Success Response (200):
{
"success": true,
"shouldNotify": false,
"message": "logout success!",
"data": null
}POST /refreshRequest Body:
{
"refresh_token": "eyJhbGciOiJIUzI1NiIs..."
}Success Response (200):
{
"success": true,
"shouldNotify": false,
"message": "refresh token success!",
"data": {
"access_token": "eyJhbGciOiJIUzI1NiIs...",
"refresh_token": "eyJhbGciOiJIUzI1NiIs..."
}
}- Send OTP
POST /send-otpRequest Body:
{
"email": "example@gmail.com"
}Success Response (200):
{
"success": true,
"shouldNotify": true,
"message": "OTP sent successfully!",
"data": null
}- Verify OTP
POST /verify-emailRequest Body:
{
"email": "example@gmail.com",
"otp": "123456"
}Success Response (200):
{
"success": true,
"shouldNotify": true,
"message": "email verification success!",
"data": null
}- Reset Password
POST /reset-passwordRequest Body:
{
"email": "example@gmail.com",
"otp": "123456",
"new_password": "newpassword"
}Success Response (200):
{
"success": true,
"shouldNotify": true,
"message": "password reset success!",
"data": null
}Error Response (401):
{
"success": false,
"shouldNotify": true,
"message": "invalid or expired refresh token",
"data": null
}GET /userSuccess Response (200):
{
"success": true,
"shouldNotify": false,
"message": "get profile success!",
"data": {
"uuid": 1,
"profile_picture": "https://example.com/profile.jpg",
"file_id": "abc123",
"name": "John Doe",
"email": "john@example.com",
"username": "john_doe",
"created_at": "2024-01-01T00:00:00Z"
}
}PUT /userRequest Body (multipart/form-data):
name: "John Doe Updated"username: "john_doe_updated"
Success Response (200):
{
"success": true,
"shouldNotify": true,
"message": "update profile success!",
"data": {
"uuid": 1,
"profile_picture": "https://example.com/profile.jpg",
"file_id": "abc123",
"name": "John Doe",
"email": "john@example.com",
"username": "john_doe",
"created_at": "2024-01-01T00:00:00Z"
}
}PUT /user/change-passwordRequest Body:
{
"previous_password": "currentpass123",
"new_password": "newpass123"
}Success Response (200):
{
"success": true,
"shouldNotify": true,
"message": "change password success!",
"data": null
}Error Response (400):
{
"success": false,
"shouldNotify": true,
"message": "current password is incorrect",
"data": null
}PUT /user/profile-pictureRequest Body (multipart/form-data):
image: [File Upload]
Success Response (200):
{
"success": true,
"shouldNotify": true,
"message": "upload image success!",
"data": null
}GET /historySuccess Response (200):
{
"success": true,
"shouldNotify": false,
"message": "history retrieved successfully!",
"data": [
{
"uuid": "abc123",
"user_id": 1,
"mood": "happy",
"created_at": "2024-01-01T00:00:00Z"
}
]
}GET /music/{id}Success Response (200):
{
"success": true,
"shouldNotify": false,
"message": "history entry found!",
"data": [
{
"uuid": "2c187355-9a61-4b22-b40b-c4636a01ad52",
"created_at": "2024-11-30T18:36:23.872084Z",
"history_uuid": "aaea230a-6846-438f-b566-3ff9f1256622",
"id": "3puYuuZ7lmlTjIgXBOT01k",
"playlist_name": "Pilihanku",
"artist": "MALIQ & D'Essentials",
"path": "https://open.spotify.com/track/3puYuuZ7lmlTjIgXBOT01k",
"thumbnail": "https://i.scdn.co/image/ab67616d0000b2734b274090757829034de581df"
}
]
}GET /history/most-moodSuccess Response (200):
{
"success": true,
"shouldNotify": false,
"message": "success",
"data": {
"mood": "happy"
}
}GET /spotify/random-playlistSuccess Response (200):
{
"success": true,
"shouldNotify": false,
"message": "random playlist retrieved successfully!",
"data": {
"music": [
{
"id": "0lYBSQXN6rCTvUZvg9S0lU",
"playlist_name": "Let Me Love You",
"artist": "DJ Snake",
"path": "https://open.spotify.com/track/0lYBSQXN6rCTvUZvg9S0lU",
"thumbnail": "https://i.scdn.co/image/ab67616d0000b273212d776c31027c511f0ee3bc"
}
]
}
}GET /spotify/{id}Success Response (200):
{
"success": true,
"shouldNotify": false,
"message": "success",
"data": {
"music": [
{
"id": "6TQghwJw3Sh8h9mTcV5BR7",
"playlist_name": "Sewanee Mountain Catfight",
"artist": "Old Crow Medicine Show",
"path": "https://open.spotify.com/track/6TQghwJw3Sh8h9mTcV5BR7",
"thumbnail": "https://i.scdn.co/image/ab67616d0000b27366990be0a5b69a9a1ca8b882"
}
]
}
}GET /spotify/search?search={query}Success Response (200):
{
"success": true,
"shouldNotify": false,
"message": "success",
"data": {
"music": [
{
"id": "0PtJbtW50jcvvswNPn3QGd",
"playlist_name": "Serana",
"artist": "For Revenge",
"path": "https://open.spotify.com/track/0PtJbtW50jcvvswNPn3QGd",
"thumbnail": "https://i.scdn.co/image/ab67616d0000b27346f02ffc0922f939ed0fd53f"
},
}
}POST /mood-detectionRequest Body (multipart/form-data):
user_id: 1image: [Selfie Image File]
Success Response (200):
{
"success": true,
"shouldNotify": false,
"message": "mood detected successfully!",
"data": {
"detected_mood": "happy",
"music": [
{
"id": "daskd2312opdask",
"name": "Happy Track",
"artist": "Happy Artist",
"path": "https://open.spotify.com/track/123abc",
"thumbnail": "https://example.com/album/cover1"
}
],
"created_at": "timestamp"
}
}200: Success400: Bad Request401: Unauthorized404: Not Found500: Internal Server Error
- All sensitive routes require JWT authentication
- Refresh tokens are valid for 30 days
- File uploads are restricted to PNG, JPEG, and JPG formats
- Profile pictures are processed and stored securely
- Supports image upload for facial detection
- Handles multipart/form-data for file uploads
- Processes JSON for standard requests
- Returns standardized JSON responses
For support or inquiries, please contact:
- Email: syahrul4w@gmail.com
Please note that API endpoints may have rate limiting applied. Contact support for specific limitations.
