Authentication
All endpoints, except registration and public profile pictures, require a bearer token in the header:
Authorization: Bearer <Your_API_Token>
Users
GET /users/id/<user_id>
→ Params:
→ Returns: user data by ID
→ Params:
user_id (int)→ Returns: user data by ID
GET /users/username/<username>
→ Params:
→ Returns: user data by username
→ Params:
username (str)→ Returns: user data by username
GET /users/search/<name>
→ Params:
→ Returns: users with matching display names (partial match)
→ Params:
name (str)→ Returns: users with matching display names (partial match)
GET /users/filter
→ Query Params:
→ Filters users based on options
→ Query Params:
role, notifications, data_sharing, emails,
account_visibility, fcm_token→ Filters users based on options
GET /users/get_pfp/<username>
→ Params:
→ Returns: profile picture URL
→ Params:
username (str)→ Returns: profile picture URL
POST /users/register
→ JSON Body:
→ Registers a new user (password optional for Google sign-in)
→ JSON Body:
{ "username": str, "password": str?, "displayName": str?, "isGoogleSignIn": bool }→ Registers a new user (password optional for Google sign-in)
POST /users/login
→ JSON Body:
→ Authenticates a user and returns info
→ JSON Body:
{ "username": str, "password": str?, "isGoogleSignIn": bool }→ Authenticates a user and returns info
POST /users/delete
→ JSON Body:
→ Deletes a user by ID
→ JSON Body:
{ "user_id": int }→ Deletes a user by ID
POST /users/update
→ JSON Body:
→ Updates a field for the user (e.g., display name, password, etc.)
→ JSON Body:
{ "user_id": int, "field": str, "value": any }→ Updates a field for the user (e.g., display name, password, etc.)
POST /users/upload_pfp
→ Form Data:
→ Uploads and sets the user's profile picture (min 50x50px, max 1024x1024px)
→ Form Data:
file (image), username (str)→ Uploads and sets the user's profile picture (min 50x50px, max 1024x1024px)
Exercises
GET /exercises
→ Returns: all exercises with muscles, equipment, description, and image
→ Returns: all exercises with muscles, equipment, description, and image
GET /exercises/filter
→ Optional Query Params:
→ Filters exercises by muscle and/or equipment
→ Optional Query Params:
muscle (str), equipment (str)→ Filters exercises by muscle and/or equipment
POST /exercises/create
→ JSON Body:
→ Creates a new exercise
→ JSON Body:
{ "name": str, "equipment": str?, "description": str?, "image_url": str? }→ Creates a new exercise
POST /exercises/update
→ JSON Body:
→ Updates a specific field of an exercise
→ JSON Body:
{ "exerciseName": str, "field": str, "value": any }→ Updates a specific field of an exercise
POST /exercises/delete
→ JSON Body:
→ Deletes an exercise by name
→ JSON Body:
{ "name": str }→ Deletes an exercise by name
POST /exercises/upload_image
→ Form Data:
→ Uploads and links an image to an exercise
→ Form Data:
file (image), name (str)→ Uploads and links an image to an exercise
Muscles
GET /muscles
→ Returns: all muscles with details
→ Returns: all muscles with details
GET /muscles/<muscle_name>
→ Params:
→ Returns: specific infos on a muscle
→ Params:
muscle_name (str)→ Returns: specific infos on a muscle
POST /muscles/update
→ JSON Body:
→ Updates a specific field of a muscle
→ JSON Body:
{ "muscleName": str, "field": str, "value": any }→ Updates a specific field of a muscle
Equipments
GET /equipments
→ Returns: all equipments (id, name, description)
→ Returns: all equipments (id, name, description)
POST /equipments/create
→ JSON Body:
→ Creates a new equipment
→ JSON Body:
{ "name": str, "description": str }→ Creates a new equipment
POST /equipments/delete
→ JSON Body:
→ Deletes an equipment by name or id (one required)
→ JSON Body:
{ "name": str? / "id": int? }→ Deletes an equipment by name or id (one required)
POST /equipments/update
→ JSON Body:
→ Updates a specific field of an equipment
→ JSON Body:
{ "id": int, "field": "name|description", "value": any }→ Updates a specific field of an equipment
Feedbacks
GET /feedbacks
→ Returns: all submitted feedbacks (latest first)
→ Returns: all submitted feedbacks (latest first)
POST /feedbacks/submit
→ JSON Body:
→ Submits new feedback
→ JSON Body:
{ "user_id": int, "feedback_type": str, "title": str, "description": str }→ Submits new feedback
POST /feedbacks/delete
→ JSON Body:
→ Deletes a feedback by its ID
→ JSON Body:
{ "feedback_id": int }→ Deletes a feedback by its ID
Notifications
GET /notifications/<user_id>
→ Params:
→ Returns: notifications for a user (newest first)
→ Params:
user_id (int)→ Returns: notifications for a user (newest first)
POST /notifications/send
→ JSON Body:
→ Sends a new notification to a user
→ JSON Body:
{ "user_id": int, "title": str, "message": str }→ Sends a new notification to a user
POST /notifications/delete
→ JSON Body:
→ Deletes a notification by its ID
→ JSON Body:
{ "notification_id": int }→ Deletes a notification by its ID
Requests
GET /requests
→ Returns: all pending user requests (exercise/equipment)
→ Returns: all pending user requests (exercise/equipment)
POST /requests/submit
→ JSON Body:
→ Submits a new request (exercise may include muscles and equipment)
→ JSON Body:
{ "request_type": "exercise|equipment", "name": str, "user_id": int, "muscles": str?, "equipment": str? }
→ Submits a new request (exercise may include muscles and equipment)
POST /requests/accept
→ JSON Body:
→ Accepts and deletes the request, and notifies the user
→ JSON Body:
{ "request_id": int }→ Accepts and deletes the request, and notifies the user
POST /requests/reject
→ JSON Body:
→ Rejects (deletes) the request without notification
→ JSON Body:
{ "request_id": int }→ Rejects (deletes) the request without notification
Tasks
GET /tasks
→ Returns: all tasks (ordered by newest first)
→ Returns: all tasks (ordered by newest first)
POST /tasks/create
→ JSON Body:
→ Creates a new task
→ JSON Body:
{ "title": str, "type": str, "priority": str }→ Creates a new task
POST /tasks/update
→ JSON Body:
→ Updates a specific field of a task
→ JSON Body:
{ "id": int, "field": "title|type|priority", "value": any }→ Updates a specific field of a task
POST /tasks/delete
→ JSON Body:
→ Deletes a task by its ID
→ JSON Body:
{ "id": int }→ Deletes a task by its ID
Workouts
GET /workouts?user_id=<id>
→ Query Param:
→ Returns: all workouts for a user with exercises included
→ Query Param:
user_id (int)→ Returns: all workouts for a user with exercises included
POST /workouts/create
→ JSON Body:
→ Creates a new workout (max 10 per user)
→ JSON Body:
{ "user_id": int, "title": str, "recovery_time": int? }→ Creates a new workout (max 10 per user)
POST /workouts/delete
→ JSON Body:
→ Deletes a workout by its ID
→ JSON Body:
{ "workout_id": int }→ Deletes a workout by its ID
POST /workouts/modify_exercise
→ JSON Body:
Add Exercise:
Remove Exercise:
→ Adds or removes an exercise in a workout
→ JSON Body:
Add Exercise:
{ "action": "add", "workout_id": int, "exercise_id": int, "sets": int?, "reps": int?, "weight": float?, "order_index": int? }Remove Exercise:
{ "action": "remove", "workout_id": int, "exercise_id": int }→ Adds or removes an exercise in a workout
POST /workouts/update
→ JSON Body:
→ Updates a workout field
→ JSON Body:
{ "workout_id": int, "field": "title|recovery_time", "value": any }→ Updates a workout field
Calendars
GET /calendars?user_id=<id>
→ Query Param:
→ Returns: all calendar entries for the user (with workout title)
→ Query Param:
user_id (int)→ Returns: all calendar entries for the user (with workout title)
GET /calendars/day?user_id=<id>&date=YYYY-MM-DD
→ Query Params:
→ Returns: calendar entries for the specific day
→ Query Params:
user_id (int), date (YYYY-MM-DD)→ Returns: calendar entries for the specific day
POST /calendars/schedule
→ JSON Body:
→ Schedules a workout on the calendar, optionally recurring
→ JSON Body:
{ "user_id": int, "workout_id": int, "date_time": str (ISO), "comment": str?, "recurrence": "daily|weekly|monthly"?, "repeat": int? }
→ Schedules a workout on the calendar, optionally recurring
POST /calendars/delete
→ JSON Body:
→ Deletes a calendar entry by ID
→ JSON Body:
{ "calendar_id": int }→ Deletes a calendar entry by ID
Muscle Cards
GET /muscle_cards?user_id=<id>
→ Query Param:
→ Returns: all muscle scores for the user (default 50 if unset)
→ Query Param:
user_id (int)→ Returns: all muscle scores for the user (default 50 if unset)
GET /muscle_cards/score?user_id=<id>&muscle_name=abs
→ Query Params:
→ Returns: the score for a specific muscle
→ Query Params:
user_id (int), muscle_name (str)→ Returns: the score for a specific muscle
POST /muscle_cards/set
→ JSON Body:
→ Sets or updates the score for a specific muscle
→ JSON Body:
{ "user_id": int, "muscle": str, "score": int (1–100) }→ Sets or updates the score for a specific muscle
POST /muscle_cards/reset
→ JSON Body:
→ Resets all muscle scores for the user to 50
→ JSON Body:
{ "user_id": int }→ Resets all muscle scores for the user to 50
User Stats
GET /user_stats?user_id=<id>
→ Query Param:
→ Returns: all custom stats for the user (max 5 per user)
→ Query Param:
user_id (int)→ Returns: all custom stats for the user (max 5 per user)
POST /user_stats/create
→ JSON Body:
→ Creates a new user-defined stat
→ JSON Body:
{ "user_id": int, "name": str, "description": str?, "symbol": str?, "color": str?, "decimal_places": int? }
→ Creates a new user-defined stat
POST /user_stats/update
→ JSON Body:
→ Updates a field of a stat (e.g. name, color, etc.)
→ JSON Body:
{ "stat_id": int, "field": str, "value": any }→ Updates a field of a stat (e.g. name, color, etc.)
POST /user_stats/delete
→ JSON Body:
→ Deletes a stat and all its entries
→ JSON Body:
{ "stat_id": int }→ Deletes a stat and all its entries
POST /user_stats/entry
→ JSON Body:
→ Adds a stat entry (only one per day)
→ JSON Body:
{ "user_id": int, "stat_id": int, "value": float, "date": str? }→ Adds a stat entry (only one per day)
GET /user_stats/entries?user_id=<id>&stat_id=<id>
→ Query Params:
→ Returns: all entries for the given stat
→ Query Params:
user_id (int), stat_id (int)→ Returns: all entries for the given stat
POST /user_stats/entry/update
→ JSON Body:
→ Updates value or date of an existing entry
→ JSON Body:
{ "entry_id": int, "value": float?, "date": str? }→ Updates value or date of an existing entry
POST /user_stats/entry/delete
→ JSON Body:
→ Deletes a stat entry by its ID
→ JSON Body:
{ "entry_id": int }→ Deletes a stat entry by its ID
GET /user_stats/entry/latest?user_id=<id>&stat_id=<id>
→ Query Params:
→ Returns: the most recent stat entry
→ Query Params:
user_id (int), stat_id (int)→ Returns: the most recent stat entry
Friendships
GET /friends?user_id=<id>&filter=all|pending|accepted|blocked
→ Query Params:
→ Returns: list of friendships with usernames and statuses
→ Query Params:
user_id (int), filter (str, optional)→ Returns: list of friendships with usernames and statuses
POST /friends/request
→ JSON Body:
→ Sends or re-sends a friend request (status: pending)
→ JSON Body:
{ "user_id": int, "friend_id": int }→ Sends or re-sends a friend request (status: pending)
POST /friends/accept
→ JSON Body:
→ Accepts a friend request (status: accepted)
→ JSON Body:
{ "user_id": int, "friend_id": int }→ Accepts a friend request (status: accepted)
POST /friends/block
→ JSON Body:
→ Blocks the user (status: blocked)
→ JSON Body:
{ "user_id": int, "friend_id": int }→ Blocks the user (status: blocked)
POST /friends/remove
→ JSON Body:
→ Deletes the friendship regardless of status
→ JSON Body:
{ "user_id": int, "friend_id": int }→ Deletes the friendship regardless of status
Messages
GET /messages/conversation?user_id=<id>&friend_id=<id>
→ Query Params:
→ Returns: full conversation history between both users (last 30 days)
→ Query Params:
user_id (int), friend_id (int)→ Returns: full conversation history between both users (last 30 days)
POST /messages/send
→ JSON Body:
→ Sends a message from sender to receiver
→ JSON Body:
{ "sender_id": int, "receiver_id": int, "content": str }→ Sends a message from sender to receiver
POST /messages/delete
→ JSON Body:
→ Deletes a message by its ID
→ JSON Body:
{ "message_id": int }→ Deletes a message by its ID