📚 Forum API Documentation

Complete REST API documentation for Forum application

Base URL

https://api.forum.gutsylab.com/api

Authentication

This API uses Laravel Sanctum for authentication. After login/register, include the token in the header:

Authorization: Bearer {your_token}

Total Endpoints

🔐 Auth  5 📝 Topics  8 💬 Comments  4 ❤️ Likes  2 👥 Users  12 Total  31

🔐 Authentication

POST /auth/register

Register a new user account

Request Body:

{
  "name": "John Doe",
  "username": "johndoe",
  "email": "john@example.com",
  "password": "password123",
  "password_confirmation": "password123",
  "phone": "+6281234567890",
  "address": "Jakarta, Indonesia"
}

📌 Note

  • phone and address are optional fields

Response (201) - Success:

{
  "success": true,
  "message": "User registered successfully",
  "data": {
    "user": {
      "id": 1,
      "name": "John Doe",
      "username": "johndoe",
      "email": "john@example.com",
      "emailVerifiedAt": null,
      "profilePhoto": null,
      "phone": null,
      "address": null,
      "createdAtFormatted": "26 Mar 2026, 10:00",
      "createdAtAgo": "just now",
      "updatedAtFormatted": "26 Mar 2026, 10:00",
      "updatedAtAgo": "just now"
    },
    "accessToken": "1|abc123...",
    "tokenType": "Bearer"
  }
}

Response (200) - Validation Failed:

{
  "success": false,
  "message": "Registration validation failed",
  "errors": {
    "email": ["The email has already been taken."],
    "username": ["The username has already been taken."]
  }
}
POST /auth/login

Login to existing account

Request Body:

{
  "email": "john@example.com",
  "password": "password123"
}

Response (200) - Success:

{
  "success": true,
  "message": "Login successful",
  "data": {
    "user": {
      "id": 1,
      "name": "John Doe",
      "username": "johndoe",
      "email": "john@example.com",
      "emailVerifiedAt": null,
      "profilePhoto": "profile_photos/johndoe.jpg",
      "createdAtFormatted": "01 Jan 2026, 00:00",
      "createdAtAgo": "2 months ago",
      "updatedAtFormatted": "26 Mar 2026, 10:00",
      "updatedAtAgo": "just now"
    },
    "accessToken": "2|xyz789...",
    "tokenType": "Bearer"
  }
}

Response (200) - User Not Found:

{
  "success": false,
  "message": "User not found with this email."
}

Response (200) - Wrong Password:

{
  "success": false,
  "message": "Incorrect password."
}

Response (200) - Validation Failed:

{
  "success": false,
  "message": "Login validation failed",
  "errors": {
    "email": ["Email is required"]
  }
}
POST /auth/logout
Authentication Required

Logout from current session

Headers:

Authorization: Bearer {token}

Response (200):

{
  "success": true,
  "message": "Logged out successfully"
}
POST /auth/forgot-password

Request password reset link to be sent to user's email

Request Body:

{
  "email": "john@example.com"
}

Response (200) - Success:

{
  "success": true,
  "message": "Password reset link sent to your email"
}

Response (200) - Validation Failed:

{
  "success": false,
  "message": "Forgot password validation failed",
  "errors": {
    "email": ["No user found with this email address"]
  }
}

📌 Note

  • User will receive an email with password reset link
  • Reset link contains a token that expires after a certain time
  • Email must exist in the system
POST /auth/reset-password

Reset user password using the token from email

Request Body:

{
  "token": "reset_token_from_email",
  "email": "john@example.com",
  "password": "newpassword123",
  "password_confirmation": "newpassword123"
}

Validation Rules:

token: required
email: required, must be valid email
password: required, minimum 8 characters, must match confirmation
password_confirmation: required, must match password

Response (200) - Success:

{
  "success": true,
  "message": "Password reset successfully"
}

Response (422) - Validation Error:

{
  "message": "The given data was invalid.",
  "errors": {
    "email": ["This password reset token is invalid."]
  }
}

📌 Note

  • Token must be valid and not expired
  • Password must be at least 8 characters
  • Password confirmation must match
  • After successful reset, user must login with new password

📝 Topics

GET /topics
Authentication Required

Get topics from users you follow and your own topics with pagination

Query Parameters:

page (optional): Page number for pagination

📌 Note

  • Shows only topics from users you follow
  • Also includes your own topics
  • Use /topics/trending to see all trending topics

Response (200):

{
  "success": true,
  "data": {
    "currentPage": 1,
    "data": [
      {
        "id": 1,
        "title": "Laravel Best Practices",
        "body": "What are the best practices...",
        "userId": 1,
        "topicCategoryId": 1,
        "createdAtFormatted": "26 Mar 2026, 10:00",
        "createdAtAgo": "2 hours ago",
        "updatedAtFormatted": "26 Mar 2026, 12:00",
        "updatedAtAgo": "just now",
        "commentsCount": 5,
        "likesCount": 10,
        "isLike": false,
        "user": {
          "id": 1,
          "name": "John Doe",
          "username": "johndoe",
          "email": "john@example.com",
          "emailVerifiedAt": null,
          "profilePhoto": "profile_photos/johndoe.jpg",
          "createdAtFormatted": "01 Jan 2026, 00:00",
          "createdAtAgo": "2 months ago",
          "updatedAtFormatted": "26 Mar 2026, 10:00",
          "updatedAtAgo": "just now",
          "profilePhotoUrl": "https://domain.com/storage/profile_photos/johndoe.jpg"
        },
        "category": {
          "id": 1,
          "name": "Laravel"
        },
        "comments": [...],
        "likes": [...]
      }
    ],
    "perPage": 20,
    "total": 50,
    "lastPage": 3
  }
}
GET /topics/trending
Authentication Required

Get top 10 trending topics with most comments

Response (200):

{
  "success": true,
  "data": [
    {
      "id": 1,
      "title": "Laravel Best Practices",
      "body": "What are the best practices...",
      "userId": 1,
      "topicCategoryId": 1,
      "createdAtFormatted": "26 Mar 2026, 10:00",
      "createdAtAgo": "2 hours ago",
      "updatedAtFormatted": "26 Mar 2026, 12:00",
      "updatedAtAgo": "just now",
      "commentsCount": 25,
      "likesCount": 10,
      "isLiked": false,
      "user": {
        "id": 1,
        "name": "John Doe",
        "username": "johndoe",
        "email": "john@example.com",
        "emailVerifiedAt": null,
        "profilePhoto": "profile_photos/johndoe.jpg",
        "createdAtFormatted": "01 Jan 2026, 00:00",
        "createdAtAgo": "2 months ago",
        "updatedAtFormatted": "26 Mar 2026, 10:00",
        "updatedAtAgo": "just now",
        "profilePhotoUrl": "https://domain.com/storage/profile_photos/johndoe.jpg"
      },
      "category": {
        "id": 1,
        "name": "Laravel"
      },
      "likes": [...]
    }
  ]
}

📌 Note

  • Returns maximum 10 topics
  • Sorted by comments count (descending)
  • Includes all topic details with relationships
GET /topics/categories
Authentication Required

Get all distinct categories that have at least one topic, sorted alphabetically

Response (200) - Success:

{
  "success": true,
  "data": [
    {
      "id": 1,
      "name": "JavaScript",
      "topics_count": 8
    },
    {
      "id": 2,
      "name": "Laravel",
      "topics_count": 12
    },
    {
      "id": 3,
      "name": "PHP",
      "topics_count": 5
    }
  ]
}

📌 Note

  • Only returns categories that have at least one topic
  • Sorted alphabetically by category name
  • Includes topics_count for each category
GET /topics/category/{categoryName}
Authentication Required

Get paginated topics filtered by a specific category name

URL Parameters:

categoryName (required): The name of the category (e.g. Laravel, PHP, JavaScript)

Query Parameters:

page (optional): Page number for pagination

Example:

GET /topics/category/Laravel?page=1

Response (200) - Success:

{
  "success": true,
  "category": "Laravel",
  "data": {
    "currentPage": 1,
    "data": [
      {
        "id": 1,
        "title": "Laravel Best Practices",
        "body": "What are the best practices...",
        "userId": 1,
        "topicCategoryId": 1,
        "createdAtFormatted": "26 Mar 2026, 10:00",
        "createdAtAgo": "2 hours ago",
        "updatedAtFormatted": "26 Mar 2026, 12:00",
        "updatedAtAgo": "just now",
        "commentsCount": 5,
        "likesCount": 10,
        "isLiked": false,
        "user": {
          "id": 1,
          "name": "John Doe",
          "username": "johndoe",
          "email": "john@example.com",
          "profilePhotoUrl": "https://domain.com/storage/profile_photos/johndoe.jpg"
        },
        "category": {
          "id": 1,
          "name": "Laravel"
        },
        "comments": [...],
        "likes": [...]
      }
    ],
    "perPage": 20,
    "total": 30,
    "lastPage": 2
  }
}

Response (404) - Category Not Found:

{
  "success": false,
  "message": "Category not found"
}

📌 Note

  • Category name is case-sensitive
  • Returns 20 topics per page, sorted by latest
  • Includes full topic details with user, category, comments, and likes
POST /topics
Authentication Required

Create a new topic. Category will be created automatically if not exists.

Request Body:

{
  "title": "Laravel Best Practices",
  "body": "What are the best practices when using Laravel?",
  "category_name": "Laravel"
}

Response (201) - Success:

{
  "success": true,
  "message": "Topic created successfully",
  "data": {
    "id": 1,
    "title": "Laravel Best Practices",
    "body": "What are the best practices when using Laravel?",
    "userId": 1,
    "topicCategoryId": 1,
    "createdAt": "2026-03-26T10:00:00.000000Z",
    "updatedAt": "2026-03-26T10:00:00.000000Z",
    "user": {
      "id": 1,
      "name": "John Doe",
      "username": "johndoe",
      "email": "john@example.com"
    },
    "category": {
      "id": 1,
      "name": "Laravel"
    }
  }
}

Response (200) - Validation Error:

{
  "success": false,
  "message": "Validation error",
  "errors": {
    "title": ["The title field is required."],
    "categoryName": ["The category name field is required."]
  }
}
GET /topics/{id}
Authentication Required

Get detailed information about a specific topic

Response (200) - Success:

{
  "success": true,
  "data": {
    "id": 1,
    "title": "Laravel Best Practices",
    "body": "What are the best practices...",
    "userId": 1,
    "topicCategoryId": 1,
    "createdAtFormatted": "26 Mar 2026, 10:00",
    "createdAtAgo": "2 hours ago",
    "updatedAtFormatted": "26 Mar 2026, 12:00",
    "updatedAtAgo": "just now",
    "commentsCount": 5,
    "likesCount": 10,
    "isLiked": false,
    "user": {
      "id": 1,
      "name": "John Doe",
      "username": "johndoe",
      "email": "john@example.com",
      "emailVerifiedAt": null,
      "profilePhoto": "profile_photos/johndoe.jpg",
      "createdAtFormatted": "01 Jan 2026, 00:00",
      "createdAtAgo": "2 months ago",
      "updatedAtFormatted": "26 Mar 2026, 10:00",
      "updatedAtAgo": "just now",
      "profilePhotoUrl": "https://domain.com/storage/profile_photos/johndoe.jpg"
    },
    "category": {
      "id": 1,
      "name": "Laravel"
    },
    "comments": [
      {
        "id": 1,
        "topicId": 1,
        "userId": 2,
        "body": "Great question!",
        "createdAtFormatted": "26 Mar 2026, 10:30",
        "createdAtAgo": "30 minutes ago",
        "updatedAtFormatted": "26 Mar 2026, 10:30",
        "updatedAtAgo": "30 minutes ago",
        "user": {
          "id": 2,
          "name": "Jane Doe",
          "username": "janedoe",
          "email": "jane@example.com",
          "profilePhotoUrl": "https://domain.com/storage/profile_photos/janedoe.jpg"
        }
      }
    ],
    "likes": [...]
  }
}

Response (404) - Not Found:

{
  "success": false,
  "message": "Topic not found"
}
PUT /topics/{id}
Authentication Required

Update a topic. Only the owner can update their topic.

Request Body (all fields optional):

{
  "title": "Updated Title",
  "body": "Updated body content",
  "category_name": "PHP"
}

Response (200) - Success:

{
  "success": true,
  "message": "Topic updated successfully",
  "data": {
    "id": 1,
    "title": "Updated Title",
    "body": "Updated body content",
    "userId": 1,
    "topicCategoryId": 2,
    "createdAt": "2026-03-26T10:00:00.000000Z",
    "updatedAt": "2026-03-26T12:00:00.000000Z",
    "user": {
      "id": 1,
      "name": "John Doe",
      "username": "johndoe",
      "email": "john@example.com"
    },
    "category": {
      "id": 2,
      "name": "PHP"
    }
  }
}

Response (403) - Unauthorized:

{
  "success": false,
  "message": "Unauthorized to update this topic"
}

Response (404) - Not Found:

{
  "success": false,
  "message": "Topic not found"
}
DELETE /topics/{id}
Authentication Required

Delete a topic. Only the owner can delete their topic.

Response (200) - Success:

{
  "success": true,
  "message": "Topic deleted successfully"
}

Response (403) - Unauthorized:

{
  "success": false,
  "message": "Unauthorized to delete this topic"
}

Response (404) - Not Found:

{
  "success": false,
  "message": "Topic not found"
}

💬 Comments

GET /topics/{topicId}/comments
Authentication Required

Get all comments for a specific topic

Response (200) - Success:

{
  "success": true,
  "data": {
    "currentPage": 1,
    "data": [
      {
        "id": 1,
        "topicId": 1,
        "userId": 2,
        "body": "Great question!",
        "createdAtAgo": "30 minutes ago",
        "createdAtFormatted": "26 Mar 2026, 10:30",
        "updatedAtAgo": "30 minutes ago",
        "updatedAtFormatted": "26 Mar 2026, 10:30",
        "user": {
          "id": 2,
          "name": "Jane Doe",
          "email": "jane@example.com",
          "username": "janedoe",
          "profilePhotoUrl": "https://domain.com/storage/profile_photos/janedoe.jpg"
        }
      }
    ],
    "perPage": 20,
    "total": 10,
    "lastPage": 1
  }
}

Response (404) - Topic Not Found:

{
  "success": false,
  "message": "Topic not found"
}
POST /topics/{topicId}/comments
Authentication Required

Create a new comment on a topic

Request Body:

{
  "body": "This is a great topic!"
}

Response (201) - Success:

{
  "success": true,
  "message": "Comment created successfully",
  "data": {
    "id": 1,
    "topicId": 1,
    "userId": 2,
    "body": "This is a great topic!",
    "createdAt": "2026-03-26T10:00:00.000000Z",
    "updatedAt": "2026-03-26T10:00:00.000000Z",
    "user": {
      "id": 2,
      "name": "Jane Doe",
      "username": "janedoe",
      "email": "jane@example.com",
      "profilePhotoUrl": "https://domain.com/storage/profile_photos/janedoe.jpg"
    }
  }
}

Response (404) - Topic Not Found:

{
  "success": false,
  "message": "Topic not found"
}
PUT /topics/{topicId}/comments/{commentId}
Authentication Required

Update a comment. Only the owner can update their comment.

Request Body:

{
  "body": "Updated comment text"
}

Response (200) - Success:

{
  "success": true,
  "message": "Comment updated successfully",
  "data": {
    "id": 1,
    "topicId": 1,
    "userId": 2,
    "body": "Updated comment text",
    "createdAt": "2026-03-26T10:00:00.000000Z",
    "updatedAt": "2026-03-26T12:00:00.000000Z",
    "user": {
      "id": 2,
      "name": "Jane Doe",
      "username": "janedoe",
      "email": "jane@example.com",
      "profilePhotoUrl": "https://domain.com/storage/profile_photos/janedoe.jpg"
    }
  }
}

Response (403) - Unauthorized:

{
  "success": false,
  "message": "Unauthorized to update this comment"
}

Response (404) - Not Found:

{
  "success": false,
  "message": "Comment not found"
}
DELETE /topics/{topicId}/comments/{commentId}
Authentication Required

Delete a comment. Only the owner can delete their comment.

Response (200) - Success:

{
  "success": true,
  "message": "Comment deleted successfully"
}

Response (403) - Unauthorized:

{
  "success": false,
  "message": "Unauthorized to delete this comment"
}

Response (404) - Not Found:

{
  "success": false,
  "message": "Comment not found"
}

❤️ Likes

POST /topics/{topicId}/like
Authentication Required

Toggle like/unlike on a topic

Response (200) - Liked:

{
  "success": true,
  "message": "Topic liked successfully",
  "data": {
    "liked": true,
    "likesCount": 11
  }
}

Response (200) - Unliked:

{
  "success": true,
  "message": "Topic unliked successfully",
  "data": {
    "liked": false,
    "likesCount": 10
  }
}

Response (404) - Topic Not Found:

{
  "success": false,
  "message": "Topic not found"
}
GET /topics/{topicId}/likes
Authentication Required

Get list of users who liked a topic

Response (200) - Success:

{
  "success": true,
  "data": {
    "currentPage": 1,
    "data": [
      {
        "id": 2,
        "name": "Jane Doe",
        "username": "janedoe",
        "email": "jane@example.com",
        "createdAtFormatted": "01 Feb 2026, 14:30",
        "createdAtAgo": "1 month ago",
        "updatedAtFormatted": "10 Mar 2026, 09:15",
        "updatedAtAgo": "3 days ago",
        "profilePhotoUrl": "https://domain.com/storage/profile_photos/janedoe.jpg"
      }
    ],
    "perPage": 20,
    "total": 11,
    "lastPage": 1
  }
}

Response (404) - Topic Not Found:

{
  "success": false,
  "message": "Topic not found"
}

👥 Users

GET /users/search
Authentication Required

Search users by username, email, or name

Query Parameters:

query (required): Search term
page (optional): Page number

Example:

GET /users/search?query=john&page=1

Response (200) - Success:

{
  "success": true,
  "data": {
    "currentPage": 1,
    "data": [
      {
        "id": 2,
        "name": "John Smith",
        "username": "johnsmith",
        "email": "johnsmith@example.com",
        "createdAtFormatted": "15 Feb 2026, 10:00",
        "createdAtAgo": "1 month ago",
        "updatedAtFormatted": "12 Mar 2026, 14:20",
        "updatedAtAgo": "1 day ago",
        "isFollow": false,
        "profilePhotoUrl": "https://domain.com/storage/profile_photos/johnsmith.jpg"
      }
    ],
    "perPage": 20,
    "total": 5,
    "lastPage": 1
  }
}

Response (422) - Validation Error:

{
  "success": false,
  "message": "Query parameter is required"
}

📌 Note

  • Searches in username, email, and name fields
  • Results exclude the currently authenticated user
  • isFollow indicates if you're following that user
  • Returns 20 results per page
GET /users/{id}
Authentication Required

Get user profile with stats

Response (200):

{
  "success": true,
  "data": {
    "id": 1,
    "name": "John Doe",
    "username": "johndoe",
    "email": "john@example.com",
    "emailVerifiedAt": null,
    "profilePhoto": "profile_photos/johndoe.jpg",
    "createdAtFormatted": "01 Jan 2026, 00:00",
    "createdAtAgo": "2 months ago",
    "updatedAtFormatted": "10 Mar 2026, 15:30",
    "updatedAtAgo": "3 days ago",
    "topicsCount": 15,
    "followersCount": 20,
    "followingCount": 10,
    "isFollow": false,
    "isYou": false,
    "profilePhotoUrl": "https://domain.com/storage/profile_photos/johndoe.jpg"
  }
}

Response (404) - User Not Found:

{
  "success": false,
  "message": "User not found"
}

📌 Note

  • isFollow: indicates if the authenticated user is following this profile
  • isYou: true if viewing your own profile
  • Includes counts for topics, followers, and following
POST /users/{id}/follow
Authentication Required

Follow a user

Response (200) - Success:

{
  "success": true,
  "message": "User followed successfully"
}

Response (422) - Already Following:

{
  "success": false,
  "message": "You are already following this user"
}

Response (422) - Cannot Follow Self:

{
  "success": false,
  "message": "You cannot follow yourself"
}

Response (404) - User Not Found:

{
  "success": false,
  "message": "User not found"
}
DELETE /users/{id}/follow
Authentication Required

Unfollow a user

Response (200):

{
  "success": true,
  "message": "User unfollowed successfully"
}

Response (422) - Not Following:

{
  "success": false,
  "message": "You are not following this user"
}

Response (404) - User Not Found:

{
  "success": false,
  "message": "User not found"
}
GET /users/{id}/followers
Authentication Required

Get list of user's followers with pagination

Query Parameters:

page (optional): Page number for pagination

Response (200):

{
  "success": true,
  "data": {
    "currentPage": 1,
    "data": [
      {
        "id": 2,
        "name": "Jane Doe",
        "username": "janedoe",
        "email": "jane@example.com",
        "createdAtFormatted": "01 Feb 2026, 14:30",
        "createdAtAgo": "1 month ago",
        "updatedAtFormatted": "10 Mar 2026, 09:15",
        "updatedAtAgo": "3 days ago",
        "isFollow": true,
        "profilePhotoUrl": "https://domain.com/storage/profile_photos/janedoe.jpg"
      }
    ],
    "perPage": 20,
    "total": 100,
    "lastPage": 5
  }
}

Response (404) - User Not Found:

{
  "success": false,
  "message": "User not found"
}

📌 Note

  • Returns paginated list of followers (20 per page)
  • Includes isFollow field indicating if you follow them back
  • Timestamps are formatted in both human-readable and relative formats
GET /users/{id}/following
Authentication Required

Get list of users that this user is following with pagination

Query Parameters:

page (optional): Page number for pagination

Response (200):

{
  "success": true,
  "data": {
    "currentPage": 1,
    "data": [
      {
        "id": 3,
        "name": "Bob Smith",
        "username": "bobsmith",
        "email": "bob@example.com",
        "createdAtFormatted": "15 Jan 2026, 08:00",
        "createdAtAgo": "2 months ago",
        "updatedAtFormatted": "12 Mar 2026, 16:45",
        "updatedAtAgo": "1 day ago",
        "isFollow": false,
        "profilePhotoUrl": null
      }
    ],
    "perPage": 20,
    "total": 50,
    "lastPage": 3
  }
}

Response (404) - User Not Found:

{
  "success": false,
  "message": "User not found"
}

📌 Note

  • Returns paginated list of following (20 per page)
  • Includes isFollow field indicating if you also follow them
  • Can view following list of any user
GET /users/{id}/topics
Authentication Required

Get all topics created by a specific user with pagination

Query Parameters:

page (optional): Page number for pagination

📌 Note

  • Shows all topics created by the specified user
  • Can view topics from any user (not limited to following)
  • Includes full topic details with user, category, comments, and likes
  • Returns 20 topics per page

Response (200):

{
  "success": true,
  "data": {
    "currentPage": 1,
    "data": [
      {
        "id": 1,
        "title": "Laravel Best Practices",
        "body": "What are the best practices...",
        "userId": 1,
        "topicCategoryId": 1,
        "createdAtFormatted": "13 Mar 2026, 10:30",
        "createdAtAgo": "2 hours ago",
        "updatedAtFormatted": "13 Mar 2026, 10:30",
        "updatedAtAgo": "2 hours ago",
        "commentsCount": 5,
        "likesCount": 10,
        "isLike": false,
        "user": {
          "id": 1,
          "name": "John Doe",
          "username": "johndoe",
          "email": "john@example.com",
          "createdAtFormatted": "01 Jan 2026, 00:00",
          "createdAtAgo": "2 months ago",
          "updatedAtFormatted": "13 Mar 2026, 10:30",
          "updatedAtAgo": "2 hours ago",
          "profilePhotoUrl": "https://domain.com/storage/profile_photos/johndoe.jpg"
        },
        "category": {
          "id": 1,
          "name": "Laravel"
        },
        "comments": [...],
        "likes": [...]
      }
    ],
    "perPage": 20,
    "total": 50,
    "lastPage": 3
  }
}

Response (404) - User Not Found:

{
  "success": false,
  "message": "User not found"
}

🖼️ Profile

GET /users/profile
Authentication Required

Get the authenticated user's own profile with stats

Response (200):

{
  "success": true,
  "data": {
    "id": 1,
    "name": "John Doe",
    "username": "johndoe",
    "email": "john@example.com",
    "emailVerifiedAt": null,
    "profilePhoto": "profile_photos/johndoe.jpg",
    "createdAtFormatted": "01 Jan 2026, 00:00",
    "createdAtAgo": "2 months ago",
    "updatedAtFormatted": "27 Mar 2026, 10:00",
    "updatedAtAgo": "just now",
    "topicsCount": 15,
    "followersCount": 20,
    "followingCount": 10,
    "isFollow": false,
    "isYou": true,
    "profilePhotoUrl": "https://domain.com/storage/profile_photos/johndoe.jpg"
  }
}

📌 Note

  • isYou will always be true for this endpoint
  • Response is identical to GET /users/{id} for the authenticated user
GET /users/profile-followers
Authentication Required

Get the authenticated user's own followers list with pagination

Query Parameters:

page (optional): Page number for pagination

Response (200):

{
  "success": true,
  "data": {
    "currentPage": 1,
    "data": [
      {
        "id": 2,
        "name": "Jane Doe",
        "username": "janedoe",
        "email": "jane@example.com",
        "createdAtFormatted": "01 Feb 2026, 14:30",
        "createdAtAgo": "1 month ago",
        "updatedAtFormatted": "10 Mar 2026, 09:15",
        "updatedAtAgo": "3 days ago",
        "isFollow": true,
        "profilePhotoUrl": "https://domain.com/storage/profile_photos/janedoe.jpg"
      }
    ],
    "perPage": 20,
    "total": 100,
    "lastPage": 5
  }
}

📌 Note

  • Response is identical to GET /users/{id}/followers for the authenticated user
  • Includes isFollow field indicating if you follow them back
GET /users/profile-following
Authentication Required

Get the list of users that the authenticated user is following with pagination

Query Parameters:

page (optional): Page number for pagination

Response (200):

{
  "success": true,
  "data": {
    "currentPage": 1,
    "data": [
      {
        "id": 3,
        "name": "Bob Smith",
        "username": "bobsmith",
        "email": "bob@example.com",
        "createdAtFormatted": "15 Jan 2026, 08:00",
        "createdAtAgo": "2 months ago",
        "updatedAtFormatted": "12 Mar 2026, 16:45",
        "updatedAtAgo": "1 day ago",
        "isFollow": false,
        "profilePhotoUrl": null
      }
    ],
    "perPage": 20,
    "total": 50,
    "lastPage": 3
  }
}

📌 Note

  • Response is identical to GET /users/{id}/following for the authenticated user
  • Includes isFollow field indicating if you also follow them
GET /users/profile-topics
Authentication Required

Get all topics created by the authenticated user with pagination

Query Parameters:

page (optional): Page number for pagination

Response (200):

{
  "success": true,
  "data": {
    "currentPage": 1,
    "data": [
      {
        "id": 1,
        "title": "Laravel Best Practices",
        "body": "What are the best practices...",
        "userId": 1,
        "topicCategoryId": 1,
        "createdAtFormatted": "13 Mar 2026, 10:30",
        "createdAtAgo": "2 hours ago",
        "updatedAtFormatted": "13 Mar 2026, 10:30",
        "updatedAtAgo": "2 hours ago",
        "commentsCount": 5,
        "likesCount": 10,
        "isLike": false,
        "user": {
          "id": 1,
          "name": "John Doe",
          "username": "johndoe",
          "email": "john@example.com",
          "createdAtFormatted": "01 Jan 2026, 00:00",
          "createdAtAgo": "2 months ago",
          "updatedAtFormatted": "13 Mar 2026, 10:30",
          "updatedAtAgo": "2 hours ago",
          "profilePhotoUrl": "https://domain.com/storage/profile_photos/johndoe.jpg"
        },
        "category": {
          "id": 1,
          "name": "Laravel"
        },
        "comments": [...],
        "likes": [...]
      }
    ],
    "perPage": 20,
    "total": 50,
    "lastPage": 3
  }
}

📌 Note

  • Response is identical to GET /users/{id}/topics for the authenticated user
  • Includes full topic details with user, category, comments, and likes
  • Returns 20 topics per page
POST /users/profile-photo
Authentication Required

Upload or replace the authenticated user's profile photo

Request Body (multipart/form-data):

photo: (file) jpeg/png/jpg/gif, max 2MB

Response (200) - Success:

{
  "success": true,
  "message": "Profile photo uploaded successfully",
  "data": {
    "profilePhoto": "profile_photos/johndoe.jpg",
    "profilePhotoUrl": "https://domain.com/storage/profile_photos/johndoe.jpg"
  }
}

Response (422) - Validation Error:

{
  "message": "The photo field is required.",
  "errors": {
    "photo": ["The photo must be an image.", "The photo must not be greater than 2048 kilobytes."]
  }
}

📌 Note

  • Accepted formats: jpeg, png, jpg, gif
  • Maximum file size: 2MB
  • Previous photo is automatically deleted when a new one is uploaded
  • Filename is set to {username}.{extension}

📌 Important Notes

  • All endpoints requiring authentication must include Authorization: Bearer {token} header
  • Default pagination is 20 items per page
  • Only topic/comment owners can update or delete their content
  • Categories are automatically created when creating a topic
  • Like endpoint uses toggle mechanism (same endpoint for like/unlike)
  • Users cannot follow themselves
  • Search excludes the currently logged-in user
  • All response keys are in camelCase
  • profilePhotoUrl is the full URL to the profile photo, profilePhoto is the raw storage path
  • GET /topics only shows topics from users you follow and your own topics
  • GET /topics/trending shows top 10 topics with most comments from all users
  • GET /users/{id}/topics shows all topics created by a specific user (any user, not limited to following)