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 /register
Request 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 /login
Request 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 /logout
Request Body:
{
"refresh_token": "eyJhbGciOiJIUzI1NiIs..."
}
Success Response (200):
{
"success": true,
"shouldNotify": false,
"message": "logout success!",
"data": null
}
POST /refresh
Request 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-otp
Request Body:
{
"email": "example@gmail.com"
}
Success Response (200):
{
"success": true,
"shouldNotify": true,
"message": "OTP sent successfully!",
"data": null
}
- Verify OTP
POST /verify-email
Request Body:
{
"email": "example@gmail.com",
"otp": "123456"
}
Success Response (200):
{
"success": true,
"shouldNotify": true,
"message": "email verification success!",
"data": null
}
- Reset Password
POST /reset-password
Request 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 /user
Success 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 /user
Request 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-password
Request 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-picture
Request Body (multipart/form-data):
image
: [File Upload]
Success Response (200):
{
"success": true,
"shouldNotify": true,
"message": "upload image success!",
"data": null
}
GET /history
Success 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-mood
Success Response (200):
{
"success": true,
"shouldNotify": false,
"message": "success",
"data": {
"mood": "happy"
}
}
GET /spotify/random-playlist
Success 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-detection
Request 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.