E_social-nexgate-service(8)

Nexgate Social Media service Overview

Nexgate's social media platform is a hybrid of Instagram and Twitter functionality, integrated deeply with the existing eCommerce and event management systems. The platform excludes stories but includes comprehensive posting, interaction, messaging, and discovery features.

Key Differentiators


Core Features

1. User Relationships

Follow System

Privacy Controls

Account Privacy


2. Posts

Post Creation

Posts are the central content type in the platform.

Post Types:

Post States:

Creation Features:

Post Management

Image Tagging System

Similar to Instagram's tag functionality:

Collaborative Posts

Collaborative posts allow multiple users to co-author a single post, with all authors displayed and the post appearing on all collaborators' profiles.

Features:

Use Cases:

Fashion Brand + Influencer Collaboration:
- Brand creates post about new collection
- Adds influencer as co-author
- Influencer accepts
- Post appears on both profiles
- Both audiences see the content
- Both get engagement metrics

Joint Product Launch:
- Two shops collaborate on bundle deal
- Create one post together
- Shows on both shop pages
- Shared promotion effort

Workflow:

  1. User A creates post
  2. User A adds User B, User C as collaborators during creation
  3. Post saved with status = "pending_collaboration"
  4. Notifications sent to User B and User C: "User A invited you to collaborate on a post"
  5. User B accepts → PostCollaborator status = "accepted"
  6. User C declines → PostCollaborator deleted, User A notified
  7. Once all pending invites resolved (accepted/declined), post can be published
  8. Published collaborative post appears on User A and User B profiles
  9. Byline shows: "By @userA and @userB"

Rules:


3. Interactions

Likes

Comments

Reposting/Sharing

Bookmarks


4. Polls

Polls are embedded within posts.

Poll Features:

Poll Actions:


5. Direct Messaging (DMs)

Basic Messaging

Conversation Management

Product-Context Messaging

Unique feature for commerce integration:

Use Case Example:

User sees a product → Clicks "Contact Seller"
→ DM opens with product banner at top
→ Conversation starts with product context
→ Easy reference throughout discussion

6. Commerce Integration

Product Linking

Shop Linking & Tagging

Event Linking

Buy-Together Group Linking

Users can share buy-together groups in posts to boost participation and fill group spots.

Features:

Use Case:

User creates buy-together group for iPhone 15
→ User shares group in post: "Join my iPhone group! Only 2 spots left, save $100!"
→ Followers see post with group card showing discount and spots
→ Click "Join Group" → Navigate to group page to complete joining
→ Group fills up → Post updates to show "Group Full"

Installment Plan Linking

Users can showcase flexible payment options for products in their posts.

Features:

Use Case:

Shop owner selling laptop at $1200
→ Has 3 installment plans: 3mo ($400/mo), 6mo ($200/mo), 12mo ($100/mo)
→ Creates post: "Get this gaming laptop! Pay as low as $100/month 💳"
→ Links 6-month and 12-month plans
→ Post shows both plans with monthly amounts
→ User clicks → Taken to checkout with 6mo plan selected

Integrated Discovery

Posts with linked products/shops/events/groups/plans appear in:


7. Hashtags & Discovery

Hashtags

Lists (Curated Feeds)

Search & Explore


8. User Profile

Profile Information

Profile Stats

Profile Actions


9. Notifications

Users receive notifications for various activities:

Social Interactions

Direct Messages

Notification Settings


10. Moderation & Safety

Reporting

Content Control

Account Actions


API Endpoints

Authentication

POST   /api/auth/register          - Register new user
POST   /api/auth/login             - Login user
POST   /api/auth/logout            - Logout user
POST   /api/auth/refresh-token     - Refresh access token
POST   /api/auth/forgot-password   - Request password reset
POST   /api/auth/reset-password    - Reset password

User Profile

GET    /api/users/:username        - Get user profile
GET    /api/users/:id              - Get user by ID
PATCH  /api/users/:id              - Update user profile
GET    /api/users/:id/posts        - Get user's posts
GET    /api/users/:id/followers    - Get followers list
GET    /api/users/:id/following    - Get following list
GET    /api/users/:id/stats        - Get user statistics

Follow System

POST   /api/users/:id/follow       - Follow user
DELETE /api/users/:id/unfollow     - Unfollow user
GET    /api/follows/requests       - Get pending follow requests (private accounts)
POST   /api/follows/:id/accept     - Accept follow request
POST   /api/follows/:id/decline    - Decline follow request

Block & Mute

POST   /api/users/:id/block        - Block user
DELETE /api/users/:id/unblock      - Unblock user
POST   /api/users/:id/mute         - Mute user
DELETE /api/users/:id/unmute       - Unmute user
GET    /api/users/blocked          - Get blocked users list
GET    /api/users/muted            - Get muted users list

Posts

POST   /api/posts                  - Create post
GET    /api/posts/:id              - Get single post
PATCH  /api/posts/:id              - Edit post
DELETE /api/posts/:id              - Delete post
GET    /api/posts/:id/likes        - Get post likes
GET    /api/posts/:id/comments     - Get post comments
GET    /api/posts/:id/reposts      - Get post reposts

GET    /api/posts                  - Get feed (from followed users)
GET    /api/posts/explore          - Get explore/discover feed
GET    /api/posts/drafts           - Get user's draft posts
POST   /api/posts/:id/publish      - Publish draft post

Post Interactions

POST   /api/posts/:id/like         - Like post
DELETE /api/posts/:id/unlike       - Unlike post
POST   /api/posts/:id/repost       - Repost (simple repost)
POST   /api/posts/:id/quote        - Quote post (with text)
DELETE /api/posts/:id/unrepost     - Remove repost/quote
POST   /api/posts/:id/bookmark     - Bookmark post
DELETE /api/posts/:id/unbookmark   - Remove bookmark
POST   /api/posts/:id/hide         - Hide post from feed
POST   /api/posts/:id/report       - Report post

Image Tags

POST   /api/posts/:id/media/:mediaId/tags     - Add tag to image
DELETE /api/posts/:id/media/:mediaId/tags/:tagId - Remove image tag
GET    /api/posts/:id/media/:mediaId/tags     - Get all tags on image

Comments

POST   /api/posts/:id/comments           - Add comment to post
GET    /api/comments/:id                 - Get single comment
PATCH  /api/comments/:id                 - Edit comment
DELETE /api/comments/:id                 - Delete comment
POST   /api/comments/:id/like            - Like comment
DELETE /api/comments/:id/unlike          - Unlike comment
POST   /api/comments/:id/reply           - Reply to comment
GET    /api/comments/:id/replies         - Get comment replies
POST   /api/comments/:id/report          - Report comment

Polls

POST   /api/polls/:id/vote               - Vote on poll
PATCH  /api/polls/:id/vote               - Change vote
GET    /api/polls/:id/results            - Get poll results
POST   /api/polls/:id/close              - Close poll early (creator only)

Bookmarks & Collections

GET    /api/bookmarks                    - Get all bookmarks
POST   /api/bookmarks/collections        - Create bookmark collection
GET    /api/bookmarks/collections        - Get all collections
GET    /api/bookmarks/collections/:id    - Get collection bookmarks
PATCH  /api/bookmarks/collections/:id    - Update collection
DELETE /api/bookmarks/collections/:id    - Delete collection
POST   /api/bookmarks/:id/move           - Move bookmark to collection

Hashtags

GET    /api/hashtags/:tag                - Get hashtag info
GET    /api/hashtags/:tag/posts          - Get posts with hashtag
GET    /api/hashtags/trending            - Get trending hashtags
POST   /api/hashtags/:tag/follow         - Follow hashtag
DELETE /api/hashtags/:tag/unfollow       - Unfollow hashtag

Lists

POST   /api/lists                        - Create list
GET    /api/lists                        - Get user's lists
GET    /api/lists/:id                    - Get single list
PATCH  /api/lists/:id                    - Update list
DELETE /api/lists/:id                    - Delete list
POST   /api/lists/:id/members            - Add user to list
DELETE /api/lists/:id/members/:userId    - Remove user from list
GET    /api/lists/:id/feed               - Get list feed (posts from members)

Direct Messages

GET    /api/conversations                      - Get user's conversations
POST   /api/conversations                      - Create new conversation
GET    /api/conversations/:id                  - Get conversation details
DELETE /api/conversations/:id                  - Delete conversation
POST   /api/conversations/:id/mute             - Mute conversation
DELETE /api/conversations/:id/unmute           - Unmute conversation

GET    /api/conversations/:id/messages         - Get conversation messages
POST   /api/conversations/:id/messages         - Send message
PATCH  /api/messages/:id                       - Edit message
DELETE /api/messages/:id                       - Delete message
POST   /api/messages/:id/reactions             - Add reaction to message
DELETE /api/messages/:id/reactions/:emoji      - Remove reaction
POST   /api/conversations/:id/read             - Mark conversation as read

Product Context Messaging

POST   /api/products/:id/contact               - Initiate message with product context
GET    /api/messages/:id/product-context       - Get product context for message

Notifications

GET    /api/notifications                      - Get user notifications
GET    /api/notifications/unread-count         - Get unread count
PATCH  /api/notifications/:id/read             - Mark notification as read
PATCH  /api/notifications/read-all             - Mark all as read
DELETE /api/notifications/:id                  - Delete notification
PATCH  /api/notifications/settings             - Update notification preferences
GET    /api/search/users?q=:query              - Search users
GET    /api/search/posts?q=:query              - Search posts
GET    /api/search/hashtags?q=:query           - Search hashtags
GET    /api/search/products?q=:query           - Search posts with products
GET    /api/search/shops?q=:query              - Search posts with shops
GET    /api/search/events?q=:query             - Search posts with events
GET    /api/search/groups?q=:query             - Search posts with buy-together groups
GET    /api/search/installment-plans?q=:query  - Search posts with installment plans
GET    /api/search/all?q=:query                - Search across all types

Reports & Moderation

POST   /api/reports                            - Submit report
GET    /api/reports                            - Get user's reports (admin only)
PATCH  /api/reports/:id                        - Update report status (admin only)

Business Logic

Feed Generation

Personal Feed (Home Feed)

Algorithm: Reverse Chronological (no complex algorithm for v1)

Logic:
1. Get list of users current user follows
2. Exclude blocked users
3. Exclude muted users
4. Fetch posts from followed users
5. Include reposts from followed users
6. Sort by published_at DESC
7. Apply pagination (cursor-based recommended)
8. Return posts with engagement counts

Optimizations:
- Cache follower list
- Use database indexes on (author_id, published_at)
- Consider read replicas for heavy read operations

Explore Feed

Logic:
1. Fetch recent posts from public accounts
2. Exclude posts from users you follow (already in home feed)
3. Exclude blocked/muted users
4. Optionally: boost posts with higher engagement
5. Optionally: filter by interests/hashtags
6. Sort by published_at DESC or trending_score
7. Apply pagination

v1 Recommendation: Simple recent public posts
v2: Add trending/engagement scoring

List Feed

Logic:
1. Get list members
2. Fetch posts from list members only
3. Sort by published_at DESC
4. Apply pagination

Hashtag Feed

Logic:
1. Fetch posts containing specific hashtag
2. Sort by published_at DESC
3. Apply pagination

Privacy & Visibility Rules

Post Visibility

Rules:
1. Public posts: Visible to everyone
2. Followers-only posts: Visible only to followers
3. Private posts: Visible only to mentioned users (if implemented)

Checks before showing post:
- Is viewer blocked by author? → Hide
- Is author blocked by viewer? → Hide
- Is author muted by viewer? → Hide (optional, depends on UX)
- Is account private and viewer not a follower? → Hide
- Is post status = published? → Show

Follow Request Logic (Private Accounts)

Flow:
1. User A clicks "Follow" on User B (private account)
2. Create Follow record with status = "pending"
3. Send notification to User B
4. User B approves/declines request
5. If approved: status = "accepted", User A sees User B's posts
6. If declined: Delete Follow record

Engagement Counters

Counter Management Strategy

Approach: Cached Counters with Periodic Sync

Counters to cache:
- posts.likes_count
- posts.comments_count
- posts.reposts_count
- comments.likes_count
- comments.replies_count
- users.followers_count
- users.following_count
- users.posts_count

Update Strategy:
1. On engagement action (like, comment, etc.):
   - Increment/decrement counter in database (same transaction)
   - Return updated count to client

2. Consistency:
   - Use database triggers or application-level transactions
   - Periodic reconciliation job to fix drift (run nightly)

3. Performance:
   - Index counter columns for sorting/filtering
   - Consider Redis cache for high-traffic posts

Notification Logic

Notification Triggers

When to create notification:
1. User followed: follower → followee
2. Post liked: liker → post author (exclude self-likes)
3. Post commented: commenter → post author (exclude self-comments)
4. Comment replied: replier → parent comment author
5. User mentioned in post: post author → mentioned user
6. User mentioned in comment: commenter → mentioned user
7. User tagged in post: post author → tagged user
8. User tagged in image: tagger → tagged user
9. Post reposted: reposter → original post author
10. Post quote-posted: quote poster → original post author

Batch Notifications:
- "X and 10 others liked your post" (if multiple users like same post)
- Group similar notifications within time window

Notification Delivery

Channels:
1. In-app: Store in notifications table, show in notification center
2. Push: Send to mobile/browser if user has push enabled
3. Email: Send digest email based on user preferences

Delivery Logic:
- Check user's notification preferences
- Respect mute/block relationships
- Don't notify for actions on muted content
- Rate limit notifications per user (prevent spam)

Message Delivery

Real-time Messaging

Technology: WebSockets or Server-Sent Events (SSE)

Flow:
1. User connects to WebSocket server
2. Authenticate connection
3. Subscribe to user's conversation channels
4. On new message:
   - Persist to database
   - Broadcast to conversation participants via WebSocket
   - Send push notification if recipient offline
   - Update conversation.last_message_at

Message Status:
- Sent: Message persisted to database
- Delivered: Recipient connected and received message
- Read: Recipient opened conversation and viewed message

Product Context Messages

Flow:
1. User on product page clicks "Contact Seller"
2. Check if conversation exists between user and seller
3. If exists: Open existing conversation
4. If not: Create new conversation
5. Create message with:
   - message_type = "product_context"
   - product_id = current product ID
   - content = optional user text or default template
6. Conversation UI shows product banner at top
7. Product info (image, name, price) displayed persistently

Template:
"Hi, I'm interested in [Product Name]. Is this still available?"

Search Implementation

Technology Options:
1. PostgreSQL Full-Text Search (simple, built-in)
2. Elasticsearch (powerful, scalable, recommended for production)
3. Algolia (managed, fast, but paid)

Search Scope:
- Users: username, display_name, bio
- Posts: content, hashtags
- Products: name, description (if linked)
- Shops: name, description (if linked)
- Events: title, description (if linked)

Ranking Factors:
- Relevance score
- Recency (for posts)
- Engagement (likes, comments) for popular content
- User's network (prioritize followed users)

Implementation with Elasticsearch:
1. Index documents on create/update
2. Use multi-field search (content, hashtags, etc.)
3. Apply filters (date range, post type, engagement threshold)
4. Return results with highlights

Content Moderation

Automated Moderation (Future)

Techniques:
1. Keyword filtering (offensive words, spam patterns)
2. Image moderation (AI-based NSFW detection)
3. Rate limiting (prevent spam posting)
4. URL reputation checking (malicious links)

Implementation:
- Run checks on post creation
- Flag suspicious content for review
- Auto-hide or require manual approval

Manual Moderation

Workflow:
1. User reports content
2. Report enters moderation queue
3. Moderator reviews report
4. Actions:
   - Dismiss: No violation
   - Warn user: Send warning notification
   - Remove content: Soft delete post/comment
   - Suspend user: Temporary ban
   - Ban user: Permanent account ban

Tools:
- Admin dashboard for reports
- Content review interface
- User management panel

Integration Points

eCommerce Integration

Product Linking

Data Flow:
1. During post creation, user searches products
2. API call to Product Service: GET /api/products/search?q=:query
3. Return product list with: id, name, image, price, shop_id
4. User selects products to link
5. On post save, create PostProduct records
6. On post display, fetch product details and show product cards

Product Card Display:
- Product image (thumbnail)
- Product name
- Price
- Shop name
- "View Product" CTA button
- Click → Navigate to product detail page

Shop Mentions/Tags

Shop Mention Parsing ($shopname):
1. On post creation, parse content for $shopname pattern
2. Validate shop exists: Query Shop Service
3. Create PostShop records with mention_type = "mention"
4. On post display, convert $shopname to clickable link

Shop Tagging:
1. User explicitly tags shop (separate from content)
2. Create PostShop record with mention_type = "tag"
3. Shop sees "tagged posts" feed

Shop Profile Integration:
- Show posts where shop is tagged/mentioned
- "Posts about this shop" section on shop page

Event Linking

Data Flow:
1. During post creation, user searches events
2. API call to Event Service: GET /api/events/search?q=:query
3. Return event list with: id, title, date, location, image, ticket_status
4. User selects events to link
5. On post save, create PostEvent records
6. On post display, fetch event details and show event cards

Event Card Display:
- Event image
- Event title
- Date & time
- Location
- Ticket availability status
- "View Event" CTA button
- Click → Navigate to event detail page

Buy-Together Group Linking

Data Flow:
1. During post creation, user searches active buy-together groups (own or others they've joined)
2. API call to BuyTogether Service: GET /api/buy-together/groups?status=active&user=:userId
3. Return group list with: id, product_info, current_count, total_slots, target_price, expires_at
4. User selects group(s) to promote
5. On post save, create PostBuyTogetherGroup records
6. On post display, fetch real-time group status and show group cards

Group Card Display:
- Product image
- Product name with group label "Buy Together 🤝"
- Progress bar: "3/5 spots filled"
- Target price with discount badge: "$800 (Save $100!)"
- Time remaining: "2 days left"
- Status indicator: Open/Almost Full/Full/Expired
- "Join Group" CTA button (disabled if full/expired)
- Click → Navigate to group detail page

Real-Time Updates:
- WebSocket connection for live group status updates
- When spots fill up, button changes to "Group Full"
- When time expires, entire card grays out with "Expired" badge
- Post feed auto-refreshes group status every 30 seconds

Boost Strategy:
User creates group → Shares on social feed → Friends see discount → Join group → Group fills faster

Installment Plan Linking

Data Flow:
1. During post creation, user searches products with installment plans
2. API call to Product Service: GET /api/products/:id/installment-plans
3. Return available plans for product: id, duration_months, monthly_amount, total_cost, interest_rate, down_payment
4. User selects which plan(s) to feature (can select multiple for comparison)
5. On post save, create PostInstallmentPlan records
6. On post display, fetch plan details and show plan cards

Single Plan Display:
- Product image
- Product name
- "Pay in installments 💳" badge
- Monthly payment: "$99/month"
- Plan duration: "6 months"
- Total cost (if different from base price): "$594 total"
- Interest rate (if applicable): "0% interest" or "5% APR"
- "Buy with Plan" CTA button
- Click → Navigate to product page with plan pre-selected

Multiple Plans Comparison Display:
- Product image at top
- Side-by-side plan cards:
  
  [3 Months]        [6 Months]        [12 Months]
  $200/mo           $100/mo           $50/mo
  $600 total        $600 total        $650 total
  0% interest       0% interest       5% APR
  [Select]          [Select]          [Select]

- Each card clickable to product page with that plan

Marketing Use Cases:
- Shop owner: "Get this laptop for just $99/month! 💳"
- Influencer: "No need to pay all at once! Check out these flexible plans"
- User sharing deal: "Found this phone with 0% financing!"

Integration with Checkout:
- When user clicks "Buy with Plan"
- Deep link to product page: /products/:id?plan=:planId
- Checkout page has plan pre-selected
- User completes purchase with chosen installment plan

Notification Integration

Cross-Service Notifications

Scenario 1: User likes a post that has a linked product

Notification Recipients:
1. Post author: "X liked your post"
2. Product owner (if different from post author): "X liked a post featuring your product"

Scenario 2: User joins a buy-together group from a post

Notification Recipients:
1. Post author: "X joined your buy-together group from your post!"
2. Group creator (if different): "X joined your group"
3. Other group members: "X joined the group - 1 more spot to go!"

Scenario 3: Buy-together group gets filled from post shares

Notification to:
- Post author: "Your group is full! 🎉 Your post helped fill 3 spots"
- All group members: "Group is full! Order will be placed soon"

Scenario 4: User clicks installment plan from post

Analytics Event (not push notification):
- Track which posts drive installment plan conversions
- Shop owner can see: "5 users viewed installment plans from your post"

Implementation:
- Social media service creates Like/Share/Join record
- Triggers notification service
- Notification service:
  - Checks PostProduct for linked products
  - Identifies product owner via Product Service
  - Creates notifications for both post author and product owner

Notifications System

Notification Types & Templates

Social Notifications

Type: FOLLOW
Template: "{actor_name} started following you"
Action: View {actor_name}'s profile

Type: LIKE_POST
Template: "{actor_name} liked your post"
Action: View post

Type: COMMENT_POST
Template: "{actor_name} commented on your post: '{comment_preview}'"
Action: View post/comment

Type: REPLY_COMMENT
Template: "{actor_name} replied to your comment: '{reply_preview}'"
Action: View comment thread

Type: MENTION_POST
Template: "{actor_name} mentioned you in a post"
Action: View post

Type: MENTION_COMMENT
Template: "{actor_name} mentioned you in a comment"
Action: View comment

Type: TAG_POST
Template: "{actor_name} tagged you in a post"
Action: View post

Type: TAG_IMAGE
Template: "{actor_name} tagged you in an image"
Action: View image/post

Type: REPOST
Template: "{actor_name} reposted your post"
Action: View repost

Type: QUOTE_POST
Template: "{actor_name} quoted your post: '{quote_preview}'"
Action: View quote post

Type: COLLABORATION_INVITE
Template: "{actor_name} invited you to collaborate on a post"
Action: View post to accept/decline

Type: COLLABORATION_ACCEPTED
Template: "{actor_name} accepted your collaboration invite"
Action: View collaborative post

Type: COLLABORATION_DECLINED
Template: "{actor_name} declined your collaboration invite"
Action: Dismiss notification

Type: COLLABORATOR_EDITED_POST
Template: "{actor_name} edited your collaborative post"
Action: View post changes

Messaging Notifications

Type: NEW_MESSAGE
Template: "New message from {actor_name}"
Action: View conversation

Type: PRODUCT_MESSAGE
Template: "{actor_name} messaged you about {product_name}"
Action: View conversation with product context

Commerce Notifications

Type: PRODUCT_POST_LIKE
Template: "{actor_name} liked a post featuring your product '{product_name}'"
Action: View post

Type: PRODUCT_POST_COMMENT
Template: "{actor_name} commented on a post featuring your product"
Action: View post/comment

Type: SHOP_TAGGED
Template: "{actor_name} tagged your shop in a post"
Action: View post

Notification Batching

Batching Strategy

Rules:
- Same type + same entity within 5 minutes → Batch
- Max 100 actors in batch
- Update existing notification instead of creating new

Example:
Instead of:
- "Alice liked your post"
- "Bob liked your post"
- "Charlie liked your post"

Show:
- "Alice, Bob, Charlie and 10 others liked your post"

Implementation:
- Use transaction to check for recent similar notifications
- Update existing notification's actor list
- Increment count
- Update timestamp to latest

Notification Preferences

Preference Options

Categories:
1. Social Interactions
   - Follows
   - Likes
   - Comments
   - Mentions
   - Tags
   - Reposts
   - Collaborations

2. Messages
   - Direct messages
   - Message reactions

3. Commerce
   - Product interactions
   - Shop tags

Settings per category:
- Push: ON/OFF
- In-app: ON/OFF (always ON for critical notifications)
- Email: ON/OFF/DIGEST (daily/weekly)
- Frequency: All / Important only / None

Default:
- All push notifications: ON
- All in-app: ON
- Email: DIGEST (daily)

Data Privacy

Sensitive Data Handling

Personal Information:
- Email: Never exposed in API responses (except to owner)
- Password: Always hashed (bcrypt, Argon2)
- Profile: Respect account privacy (public/private)

Data Retention:
- Deleted posts: Soft delete, retain for 30 days, then hard delete
- Deleted messages: Soft delete, retain for 90 days for legal compliance
- Deleted accounts: Anonymize after 30 days, hard delete after 90 days

Export & Deletion (GDPR):
- User data export: Provide JSON export of all user data
- Right to be forgotten: Delete all user content and personal info

Privacy Controls

Block Functionality

When User A blocks User B:
- B cannot see A's profile or posts
- B cannot follow A
- B cannot message A
- B cannot comment on A's posts
- B cannot tag or mention A
- Existing follows are removed
- B is not notified of the block

Implementation:
- Before showing content, check if viewer is blocked
- Before allowing action, check if actor is blocked

Mute Functionality

When User A mutes User B:
- B's posts don't appear in A's feed
- B's comments on others' posts may still appear (optional)
- B is not notified of the mute
- A can still see B's profile if directly visited

Implementation:
- Filter out muted users in feed queries
- Store mute relationship in Mute table

Conclusion

This documentation provides a complete blueprint for implementing a social media platform integrated with eCommerce and events. The architecture is designed to scale from MVP to millions of users while maintaining code quality and user experience.

User Relations Endpoints


User Relations Endpoints

Account Privacy APIs

Author: Kibuti, Backend Developer
Last Updated: 2025-12-11
Version: v1.0

Base URL: https://api.nexgate.com/api/v1

Short Description: The Account Privacy API allows users to manage their account privacy settings, controlling whether their account is private or public. Private accounts require follow request approval before users can see their content and follow them.

Hints:


Standard Response Format

All API responses follow a consistent structure using our Globe Response Builder pattern:

Success Response Structure

{
  "success": true,
  "httpStatus": "OK",
  "message": "Operation completed successfully",
  "action_time": "2025-09-23T10:30:45",
  "data": {
    // Actual response data goes here
  }
}

Error Response Structure

{
  "success": false,
  "httpStatus": "BAD_REQUEST",
  "message": "Error description",
  "action_time": "2025-09-23T10:30:45",
  "data": "Error description"
}

Standard Response Fields

Field Type Description
success boolean Always true for successful operations, false for errors
httpStatus string HTTP status name (OK, BAD_REQUEST, NOT_FOUND, etc.)
message string Human-readable message describing the operation result
action_time string ISO 8601 timestamp of when the response was generated
data object/string Response payload for success, error details for failures

HTTP Method Badge Standards

For better visual clarity, all endpoints use colored badges for HTTP methods with the following standard colors:


Endpoints

1. Get Privacy Settings

Purpose: Retrieve the current privacy settings for the authenticated user's account

Endpoint: GET {base_url}/e-social/privacy/account

Access Level: 🔒 Protected (Requires Bearer Token Authentication)

Authentication: Bearer Token

Request Headers:

Header Type Required Description
Authorization string Yes Bearer token for authentication (format: Bearer <token>)
Content-Type string Yes Must be application/json

Success Response JSON Sample:

{
  "success": true,
  "httpStatus": "OK",
  "message": "Privacy settings retrieved successfully",
  "action_time": "2025-12-11T10:30:45",
  "data": {
    "id": "550e8400-e29b-41d4-a716-446655440000",
    "userId": "123e4567-e89b-12d3-a456-426614174000",
    "isPrivate": false,
    "createdAt": "2025-01-15T08:20:30",
    "updatedAt": "2025-12-11T10:30:45"
  }
}

Success Response Fields:

Field Description
id Unique identifier for the privacy settings record (UUID format)
userId Unique identifier of the user who owns these settings (UUID format)
isPrivate Boolean flag indicating if the account is private (true) or public (false)
createdAt Timestamp when the privacy settings were first created (ISO 8601 format)
updatedAt Timestamp when the privacy settings were last modified (ISO 8601 format)

Error Response JSON Sample:

{
  "success": false,
  "httpStatus": "UNAUTHORIZED",
  "message": "Token has expired",
  "action_time": "2025-12-11T10:30:45",
  "data": "Token has expired"
}

Standard Error Types:

Application-Level Exceptions (400-499)

Error Response Examples:

Unauthorized - Token Issues (401):

{
  "success": false,
  "httpStatus": "UNAUTHORIZED",
  "message": "Token has expired",
  "action_time": "2025-12-11T10:30:45",
  "data": "Token has expired"
}

Unauthorized - Missing Token (401):

{
  "success": false,
  "httpStatus": "UNAUTHORIZED",
  "message": "Authentication token is required",
  "action_time": "2025-12-11T10:30:45",
  "data": "Authentication token is required"
}

2. Update Privacy Settings

Purpose: Update the privacy settings for the authenticated user's account (switch between private and public)

Endpoint: PUT {base_url}/e-social/privacy/account

Access Level: 🔒 Protected (Requires Bearer Token Authentication)

Authentication: Bearer Token

Request Headers:

Header Type Required Description
Authorization string Yes Bearer token for authentication (format: Bearer <token>)
Content-Type string Yes Must be application/json

Request JSON Sample:

{
  "isPrivate": true
}

Request Body Parameters:

Parameter Type Required Description Validation
isPrivate boolean Yes Flag to set account as private (true) or public (false) Must not be null

Success Response JSON Sample:

{
  "success": true,
  "httpStatus": "OK",
  "message": "Privacy settings updated successfully",
  "action_time": "2025-12-11T10:30:45",
  "data": {
    "id": "550e8400-e29b-41d4-a716-446655440000",
    "userId": "123e4567-e89b-12d3-a456-426614174000",
    "isPrivate": true,
    "createdAt": "2025-01-15T08:20:30",
    "updatedAt": "2025-12-11T10:30:45"
  }
}

Success Response Fields:

Field Description
id Unique identifier for the privacy settings record (UUID format)
userId Unique identifier of the user who owns these settings (UUID format)
isPrivate Boolean flag indicating if the account is private (true) or public (false)
createdAt Timestamp when the privacy settings were first created (ISO 8601 format)
updatedAt Timestamp when the privacy settings were last modified (ISO 8601 format)

Error Response JSON Sample:

{
  "success": false,
  "httpStatus": "UNPROCESSABLE_ENTITY",
  "message": "Validation failed",
  "action_time": "2025-12-11T10:30:45",
  "data": {
    "isPrivate": "must not be null"
  }
}

Standard Error Types:

Application-Level Exceptions (400-499)

Error Response Examples:

Validation Error (422):

{
  "success": false,
  "httpStatus": "UNPROCESSABLE_ENTITY",
  "message": "Validation failed",
  "action_time": "2025-12-11T10:30:45",
  "data": {
    "isPrivate": "must not be null"
  }
}

Unauthorized - Token Issues (401):

{
  "success": false,
  "httpStatus": "UNAUTHORIZED",
  "message": "Token has expired",
  "action_time": "2025-12-11T10:30:45",
  "data": "Token has expired"
}

Quick Reference Guide

Common HTTP Status Codes

Authentication

Data Format Standards

User Relations Endpoints

Follow System APIs

Author: Josh, Lead Backend Developer
Last Updated: 2025-12-20
Version: v1.1

Base URL: https://api.nexgate.com/api/v1

Short Description: The Follow System API manages user relationships including following/unfollowing users, handling follow requests for private accounts, retrieving followers and following lists, and discovering featured users. It supports both immediate follows (public accounts) and pending follow requests (private accounts). The system intelligently tracks mutual relationships and provides contextual follow/unfollow buttons based on the authenticated user's relationship with other users.

Hints:


How The Follow System Works

Relationship Context Logic

The Follow System provides intelligent relationship tracking between the authenticated user (you) and listed users across different profile views:

1. Your Own Followers List (/followers/{yourUserId})

2. Your Own Following List (/following/{yourUserId})

3. Friend's Followers List (/followers/{friendUserId})

4. Friend's Following List (/following/{friendUserId})

Privacy & Status Rules

Private Accounts:

Public Accounts:

Blocking Behavior:

Key Principle: All relationship indicators (followsYou, youFollow) are always calculated relative to the authenticated user, regardless of whose profile is being viewed.


UI Implementation Best Practices

Button State Management

The follow system uses a single button that changes state based on the relationship context. This follows industry standards (Twitter/X, Instagram, LinkedIn).

Button Logic by Relationship State:

if (youFollow) {
  // Button: "Following"
  // Action: Click to unfollow (with confirmation)
  // Style: Secondary/outlined button
} else if (followsYou) {
  // Button: "Follow Back"
  // Action: Click to follow immediately (no confirmation)
  // Style: Primary/solid button
} else {
  // Button: "Follow"
  // Action: Click to follow immediately (no confirmation)
  // Style: Primary/solid button
}

Why Single Button Design:

Advantages:

Avoid:

Confirmation Dialog Best Practices

Show confirmation ONLY for destructive actions:

Unfollow Action (Destructive):

User clicks "Following" button
↓
Show confirmation modal:
"Unfollow @username?"
[Cancel] [Unfollow]
↓
On confirm: Call DELETE /e-social/follows/{userId}

Follow/Follow Back Actions (Constructive):

User clicks "Follow" or "Follow Back" button
↓
Immediately call POST /e-social/follows/{userId}
No confirmation needed

Rationale:

Visual States & Feedback

Button States:

State Label Style On Click
Not Following "Follow" Primary/Solid Follow immediately
Mutual Follow Possible "Follow Back" Primary/Solid Follow immediately
Currently Following "Following" Secondary/Outlined Show unfollow confirmation
Pending Request "Requested" Secondary/Disabled Cancel request (optional)

Loading States:

Error Handling:

Additional UI Elements

Badges:

Private Account Indicators:


Standard Response Format

All API responses follow a consistent structure using our Globe Response Builder pattern:

Success Response Structure

{
  "success": true,
  "httpStatus": "OK",
  "message": "Operation completed successfully",
  "action_time": "2025-09-23T10:30:45",
  "data": {
    // Actual response data goes here
  }
}

Error Response Structure

{
  "success": false,
  "httpStatus": "BAD_REQUEST",
  "message": "Error description",
  "action_time": "2025-09-23T10:30:45",
  "data": "Error description"
}

Standard Response Fields

Field Type Description
success boolean Always true for successful operations, false for errors
httpStatus string HTTP status name (OK, BAD_REQUEST, NOT_FOUND, etc.)
message string Human-readable message describing the operation result
action_time string ISO 8601 timestamp of when the response was generated
data object/string Response payload for success, error details for failures

HTTP Method Badge Standards

For better visual clarity, all endpoints use colored badges for HTTP methods with the following standard colors:


Endpoints

1. Follow User

Purpose: Follow a user or create a follow request if the target account is private

Endpoint: POST {base_url}/e-social/follows/{userId}

Access Level: 🔒 Protected (Requires Bearer Token Authentication)

Authentication: Bearer Token

Request Headers:

Header Type Required Description
Authorization string Yes Bearer token for authentication (format: Bearer <token>)
Content-Type string Yes Must be application/json

Path Parameters:

Parameter Type Required Description Validation
userId string Yes UUID of the user to follow Must be valid UUID format

Success Response JSON Sample:

{
  "success": true,
  "httpStatus": "OK",
  "message": "User followed successfully",
  "action_time": "2025-12-11T10:30:45",
  "data": {
    "id": "660e8400-e29b-41d4-a716-446655440011",
    "followerId": "123e4567-e89b-12d3-a456-426614174000",
    "followingId": "987e6543-e21b-12d3-a456-426614174999",
    "follower": {
      "id": "123e4567-e89b-12d3-a456-426614174000",
      "userName": "john_doe",
      "firstName": "John",
      "lastName": "Doe",
      "profilePictureUrls": ["https://cdn.nexgate.com/profiles/john_doe.jpg"],
      "isVerified": true
    },
    "following": {
      "id": "987e6543-e21b-12d3-a456-426614174999",
      "userName": "jane_smith",
      "firstName": "Jane",
      "lastName": "Smith",
      "profilePictureUrls": ["https://cdn.nexgate.com/profiles/jane_smith.jpg"],
      "isVerified": false
    },
    "status": "ACCEPTED",
    "createdAt": "2025-12-11T10:30:45"
  }
}

Success Response Fields:

Field Description
id Unique identifier for the follow relationship (UUID format)
followerId UUID of the user who initiated the follow
followingId UUID of the user being followed
follower Object containing summary information about the follower user
follower.id UUID of the follower user
follower.userName Username of the follower
follower.firstName First name of the follower
follower.lastName Last name of the follower
follower.profilePictureUrls Array of profile picture URLs for the follower
follower.isVerified Boolean indicating if the follower account is verified
following Object containing summary information about the user being followed
following.id UUID of the user being followed
following.userName Username of the user being followed
following.firstName First name of the user being followed
following.lastName Last name of the user being followed
following.profilePictureUrls Array of profile picture URLs for the user being followed
following.isVerified Boolean indicating if the followed account is verified
status Follow status - "ACCEPTED" for public accounts, "PENDING" for private accounts
createdAt Timestamp when the follow relationship was created (ISO 8601 format)

Error Response JSON Sample:

{
  "success": false,
  "httpStatus": "BAD_REQUEST",
  "message": "Cannot follow yourself",
  "action_time": "2025-12-11T10:30:45",
  "data": "Cannot follow yourself"
}

Standard Error Types:

Application-Level Exceptions (400-499)

Error Response Examples:

Bad Request - Self Follow (400):

{
  "success": false,
  "httpStatus": "BAD_REQUEST",
  "message": "Cannot follow yourself",
  "action_time": "2025-12-11T10:30:45",
  "data": "Cannot follow yourself"
}

Bad Request - Already Following (400):

{
  "success": false,
  "httpStatus": "BAD_REQUEST",
  "message": "Already following this user",
  "action_time": "2025-12-11T10:30:45",
  "data": "Already following this user"
}

Not Found (404):

{
  "success": false,
  "httpStatus": "NOT_FOUND",
  "message": "User not found",
  "action_time": "2025-12-11T10:30:45",
  "data": "User not found"
}

2. Unfollow User

Purpose: Remove a follow relationship with another user

Endpoint: DELETE {base_url}/e-social/follows/{userId}

Access Level: 🔒 Protected (Requires Bearer Token Authentication)

Authentication: Bearer Token

Request Headers:

Header Type Required Description
Authorization string Yes Bearer token for authentication (format: Bearer <token>)
Content-Type string Yes Must be application/json

Path Parameters:

Parameter Type Required Description Validation
userId string Yes UUID of the user to unfollow Must be valid UUID format

Success Response JSON Sample:

{
  "success": true,
  "httpStatus": "OK",
  "message": "User unfollowed successfully",
  "action_time": "2025-12-11T10:30:45",
  "data": null
}

Success Response Fields:

Field Description
data Always null for this endpoint

Error Response JSON Sample:

{
  "success": false,
  "httpStatus": "NOT_FOUND",
  "message": "User not found",
  "action_time": "2025-12-11T10:30:45",
  "data": "User not found"
}

Standard Error Types:

Application-Level Exceptions (400-499)

Error Response Examples:

Not Found (404):

{
  "success": false,
  "httpStatus": "NOT_FOUND",
  "message": "User not found",
  "action_time": "2025-12-11T10:30:45",
  "data": "User not found"
}

3. Accept Follow Request

Purpose: Accept a pending follow request from another user

Endpoint: POST {base_url}/e-social/follows/requests/{followId}/accept

Access Level: 🔒 Protected (Requires Bearer Token Authentication)

Authentication: Bearer Token

Request Headers:

Header Type Required Description
Authorization string Yes Bearer token for authentication (format: Bearer <token>)
Content-Type string Yes Must be application/json

Path Parameters:

Parameter Type Required Description Validation
followId string Yes UUID of the follow request to accept Must be valid UUID format

Success Response JSON Sample:

{
  "success": true,
  "httpStatus": "OK",
  "message": "Follow request accepted",
  "action_time": "2025-12-11T10:30:45",
  "data": {
    "id": "660e8400-e29b-41d4-a716-446655440011",
    "followerId": "987e6543-e21b-12d3-a456-426614174999",
    "followingId": "123e4567-e89b-12d3-a456-426614174000",
    "follower": {
      "id": "987e6543-e21b-12d3-a456-426614174999",
      "userName": "jane_smith",
      "firstName": "Jane",
      "lastName": "Smith",
      "profilePictureUrls": ["https://cdn.nexgate.com/profiles/jane_smith.jpg"],
      "isVerified": false
    },
    "following": {
      "id": "123e4567-e89b-12d3-a456-426614174000",
      "userName": "john_doe",
      "firstName": "John",
      "lastName": "Doe",
      "profilePictureUrls": ["https://cdn.nexgate.com/profiles/john_doe.jpg"],
      "isVerified": true
    },
    "status": "ACCEPTED",
    "createdAt": "2025-12-11T09:15:30"
  }
}

Standard Error Types:

Application-Level Exceptions (400-499)


4. Decline Follow Request

Purpose: Decline a pending follow request from another user

Endpoint: DELETE {base_url}/e-social/follows/requests/{followId}/decline

Access Level: 🔒 Protected (Requires Bearer Token Authentication)

Authentication: Bearer Token

Request Headers:

Header Type Required Description
Authorization string Yes Bearer token for authentication (format: Bearer <token>)
Content-Type string Yes Must be application/json

Path Parameters:

Parameter Type Required Description Validation
followId string Yes UUID of the follow request to decline Must be valid UUID format

Success Response JSON Sample:

{
  "success": true,
  "httpStatus": "OK",
  "message": "Follow request declined",
  "action_time": "2025-12-11T10:30:45",
  "data": null
}

Standard Error Types:

Application-Level Exceptions (400-499)


5. Get Followers

Purpose: Retrieve the complete list of users following a specified user with relationship context

Endpoint: GET {base_url}/e-social/follows/followers/{userId}

Access Level: 🔒 Protected (Requires Bearer Token Authentication)

Authentication: Bearer Token

Request Headers:

Header Type Required Description
Authorization string Yes Bearer token for authentication (format: Bearer <token>)
Content-Type string Yes Must be application/json

Path Parameters:

Parameter Type Required Description Validation
userId string Yes UUID of the user whose followers to retrieve Must be valid UUID format

Success Response JSON Sample:

{
  "success": true,
  "httpStatus": "OK",
  "message": "Followers retrieved successfully",
  "action_time": "2025-12-11T10:30:45",
  "data": [
    {
      "id": "660e8400-e29b-41d4-a716-446655440011",
      "user": {
        "id": "987e6543-e21b-12d3-a456-426614174999",
        "userName": "jane_smith",
        "firstName": "Jane",
        "lastName": "Smith",
        "profilePictureUrls": ["https://cdn.nexgate.com/profiles/jane_smith.jpg"],
        "isVerified": false
      },
      "status": "ACCEPTED",
      "createdAt": "2025-12-10T14:20:15",
      "followsYou": true,
      "youFollow": false
    },
    {
      "id": "770e8400-e29b-41d4-a716-446655440022",
      "user": {
        "id": "111e1111-e11b-11d1-a111-111111111111",
        "userName": "bob_wilson",
        "firstName": "Bob",
        "lastName": "Wilson",
        "profilePictureUrls": ["https://cdn.nexgate.com/profiles/bob_wilson.jpg"],
        "isVerified": true
      },
      "status": "ACCEPTED",
      "createdAt": "2025-12-09T08:45:30",
      "followsYou": true,
      "youFollow": true
    }
  ]
}

Success Response Fields:

Field Description
data Array of follower objects
data[].id Unique identifier for the follow relationship (UUID format)
data[].user Object containing information about the follower user
data[].user.id UUID of the follower user
data[].user.userName Username of the follower
data[].user.firstName First name of the follower
data[].user.lastName Last name of the follower
data[].user.profilePictureUrls Array of profile picture URLs for the follower
data[].user.isVerified Boolean indicating if the follower account is verified
data[].status Follow status - always "ACCEPTED" for this endpoint
data[].createdAt Timestamp when the follow relationship was created (ISO 8601 format)
data[].followsYou NEW: Does this follower follow the authenticated user?
data[].youFollow NEW: Does the authenticated user follow this follower back?

Standard Error Types:

Application-Level Exceptions (400-499)


6. Get Following

Purpose: Retrieve the complete list of users that a specified user is following with relationship context

Endpoint: GET {base_url}/e-social/follows/following/{userId}

Access Level: 🔒 Protected (Requires Bearer Token Authentication)

Authentication: Bearer Token

Request Headers:

Header Type Required Description
Authorization string Yes Bearer token for authentication (format: Bearer <token>)
Content-Type string Yes Must be application/json

Path Parameters:

Parameter Type Required Description Validation
userId string Yes UUID of the user whose following list to retrieve Must be valid UUID format

Success Response JSON Sample:

{
  "success": true,
  "httpStatus": "OK",
  "message": "Following retrieved successfully",
  "action_time": "2025-12-11T10:30:45",
  "data": [
    {
      "id": "660e8400-e29b-41d4-a716-446655440011",
      "user": {
        "id": "222e2222-e22b-22d2-a222-222222222222",
        "userName": "alice_johnson",
        "firstName": "Alice",
        "lastName": "Johnson",
        "profilePictureUrls": ["https://cdn.nexgate.com/profiles/alice_johnson.jpg"],
        "isVerified": true
      },
      "status": "ACCEPTED",
      "createdAt": "2025-12-08T16:30:00",
      "followsYou": true,
      "youFollow": true
    }
  ]
}

Success Response Fields:

Field Description
data Array of following objects
data[].id Unique identifier for the follow relationship (UUID format)
data[].user Object containing information about the followed user
data[].user.id UUID of the followed user
data[].user.userName Username of the followed user
data[].user.firstName First name of the followed user
data[].user.lastName Last name of the followed user
data[].user.profilePictureUrls Array of profile picture URLs for the followed user
data[].user.isVerified Boolean indicating if the followed account is verified
data[].status Follow status - always "ACCEPTED" for this endpoint
data[].createdAt Timestamp when the follow relationship was created (ISO 8601 format)
data[].followsYou NEW: Does this user follow the authenticated user back?
data[].youFollow NEW: Does the authenticated user follow this user?

Standard Error Types:

Application-Level Exceptions (400-499)


7. Get Followers (Paginated)

Purpose: Retrieve a paginated list of users following a specified user with relationship context

Endpoint: GET {base_url}/e-social/follows/followers/{userId}/paged

Access Level: 🔒 Protected (Requires Bearer Token Authentication)

Authentication: Bearer Token

Request Headers:

Header Type Required Description
Authorization string Yes Bearer token for authentication (format: Bearer <token>)
Content-Type string Yes Must be application/json

Path Parameters:

Parameter Type Required Description Validation
userId string Yes UUID of the user whose followers to retrieve Must be valid UUID format

Query Parameters:

Parameter Type Required Description Validation Default
page integer No Page number (1-indexed) Min: 1 1
size integer No Number of items per page Min: 1, Max: 100 20

Success Response JSON Sample:

{
  "success": true,
  "httpStatus": "OK",
  "message": "Followers retrieved successfully",
  "action_time": "2025-12-11T10:30:45",
  "data": {
    "content": [
      {
        "id": "660e8400-e29b-41d4-a716-446655440011",
        "user": {
          "id": "987e6543-e21b-12d3-a456-426614174999",
          "userName": "jane_smith",
          "firstName": "Jane",
          "lastName": "Smith",
          "profilePictureUrls": ["https://cdn.nexgate.com/profiles/jane_smith.jpg"],
          "isVerified": false
        },
        "status": "ACCEPTED",
        "createdAt": "2025-12-10T14:20:15",
        "followsYou": true,
        "youFollow": false
      }
    ],
    "pageable": {
      "pageNumber": 0,
      "pageSize": 20,
      "sort": {
        "empty": true,
        "sorted": false,
        "unsorted": true
      },
      "offset": 0,
      "paged": true,
      "unpaged": false
    },
    "last": true,
    "totalPages": 1,
    "totalElements": 1,
    "first": true,
    "size": 20,
    "number": 0,
    "sort": {
      "empty": true,
      "sorted": false,
      "unsorted": true
    },
    "numberOfElements": 1,
    "empty": false
  }
}

Success Response Fields:

Field Description
data.content Array of follower objects for the current page (includes followsYou and youFollow fields)
data.content[].followsYou NEW: Does this follower follow the authenticated user?
data.content[].youFollow NEW: Does the authenticated user follow this follower back?
data.pageable Pagination metadata
data.totalPages Total number of pages available
data.totalElements Total number of followers
data.first Boolean indicating if this is the first page
data.last Boolean indicating if this is the last page
data.size Page size
data.number Current page number (0-indexed)
data.numberOfElements Number of elements in current page
data.empty Boolean indicating if the page is empty

8. Get Following (Paginated)

Purpose: Retrieve a paginated list of users that a specified user is following with relationship context

Endpoint: GET {base_url}/e-social/follows/following/{userId}/paged

Access Level: 🔒 Protected (Requires Bearer Token Authentication)

Authentication: Bearer Token

Request Headers:

Header Type Required Description
Authorization string Yes Bearer token for authentication (format: Bearer <token>)
Content-Type string Yes Must be application/json

Path Parameters:

Parameter Type Required Description Validation
userId string Yes UUID of the user whose following list to retrieve Must be valid UUID format

Query Parameters:

Parameter Type Required Description Validation Default
page integer No Page number (1-indexed) Min: 1 1
size integer No Number of items per page Min: 1, Max: 100 20

Success Response JSON Sample:

{
  "success": true,
  "httpStatus": "OK",
  "message": "Following retrieved successfully",
  "action_time": "2025-12-11T10:30:45",
  "data": {
    "content": [
      {
        "id": "660e8400-e29b-41d4-a716-446655440011",
        "user": {
          "id": "222e2222-e22b-22d2-a222-222222222222",
          "userName": "alice_johnson",
          "firstName": "Alice",
          "lastName": "Johnson",
          "profilePictureUrls": ["https://cdn.nexgate.com/profiles/alice_johnson.jpg"],
          "isVerified": true
        },
        "status": "ACCEPTED",
        "createdAt": "2025-12-08T16:30:00",
        "followsYou": true,
        "youFollow": true
      }
    ],
    "pageable": {
      "pageNumber": 0,
      "pageSize": 20,
      "sort": {
        "empty": true,
        "sorted": false,
        "unsorted": true
      },
      "offset": 0,
      "paged": true,
      "unpaged": false
    },
    "last": true,
    "totalPages": 1,
    "totalElements": 1,
    "first": true,
    "size": 20,
    "number": 0,
    "sort": {
      "empty": true,
      "sorted": false,
      "unsorted": true
    },
    "numberOfElements": 1,
    "empty": false
  }
}

Success Response Fields:

Field Description
data.content Array of following objects for the current page (includes followsYou and youFollow fields)
data.content[].followsYou NEW: Does this user follow the authenticated user back?
data.content[].youFollow NEW: Does the authenticated user follow this user?
data.pageable Pagination metadata
data.totalPages Total number of pages available
data.totalElements Total number of users being followed
data.first Boolean indicating if this is the first page
data.last Boolean indicating if this is the last page
data.size Page size
data.number Current page number (0-indexed)
data.numberOfElements Number of elements in current page
data.empty Boolean indicating if the page is empty

9. Get Pending Follow Requests

Purpose: Retrieve all pending follow requests for the authenticated user (requests they need to approve)

Endpoint: GET {base_url}/e-social/follows/requests/pending

Access Level: 🔒 Protected (Requires Bearer Token Authentication)

Authentication: Bearer Token

Request Headers:

Header Type Required Description
Authorization string Yes Bearer token for authentication (format: Bearer <token>)
Content-Type string Yes Must be application/json

Success Response JSON Sample:

{
  "success": true,
  "httpStatus": "OK",
  "message": "Pending requests retrieved successfully",
  "action_time": "2025-12-11T10:30:45",
  "data": [
    {
      "id": "660e8400-e29b-41d4-a716-446655440011",
      "user": {
        "id": "333e3333-e33b-33d3-a333-333333333333",
        "userName": "charlie_brown",
        "firstName": "Charlie",
        "lastName": "Brown",
        "profilePictureUrls": ["https://cdn.nexgate.com/profiles/charlie_brown.jpg"],
        "isVerified": false
      },
      "status": "PENDING",
      "createdAt": "2025-12-11T09:15:30",
      "followsYou": false,
      "youFollow": false
    }
  ]
}

Success Response Fields:

Field Description
data Array of pending follow request objects
data[].id Unique identifier for the follow relationship (UUID format)
data[].user Object containing information about the user requesting to follow
data[].status Follow status - always "PENDING" for this endpoint
data[].createdAt Timestamp when the follow request was created (ISO 8601 format)
data[].followsYou NEW: Does this requester follow the authenticated user?
data[].youFollow NEW: Does the authenticated user follow this requester?

10. Get User Stats

Purpose: Retrieve follower, following, and pending request counts for a specified user

Endpoint: GET {base_url}/e-social/follows/stats/{userId}

Access Level: 🔒 Protected (Requires Bearer Token Authentication)

Authentication: Bearer Token

Request Headers:

Header Type Required Description
Authorization string Yes Bearer token for authentication (format: Bearer <token>)
Content-Type string Yes Must be application/json

Path Parameters:

Parameter Type Required Description Validation
userId string Yes UUID of the user whose stats to retrieve Must be valid UUID format

Success Response JSON Sample:

{
  "success": true,
  "httpStatus": "OK",
  "message": "User stats retrieved successfully",
  "action_time": "2025-12-11T10:30:45",
  "data": {
    "userId": "123e4567-e89b-12d3-a456-426614174000",
    "followersCount": 1250,
    "followingCount": 487,
    "pendingRequestsCount": 15
  }
}

Success Response Fields:

Field Description
userId UUID of the user these stats belong to
followersCount Total number of accepted followers for this user
followingCount Total number of users this user is following (accepted follows only)
pendingRequestsCount Total number of pending follow requests for this user

11. Check Follow Status

Purpose: Check if the authenticated user is following a specified user

Endpoint: GET {base_url}/e-social/follows/check/{userId}

Access Level: 🔒 Protected (Requires Bearer Token Authentication)

Authentication: Bearer Token

Request Headers:

Header Type Required Description
Authorization string Yes Bearer token for authentication (format: Bearer <token>)
Content-Type string Yes Must be application/json

Path Parameters:

Parameter Type Required Description Validation
userId string Yes UUID of the user to check follow status for Must be valid UUID format

Success Response JSON Sample:

{
  "success": true,
  "httpStatus": "OK",
  "message": "Follow status checked",
  "action_time": "2025-12-11T10:30:45",
  "data": {
    "userId": "987e6543-e21b-12d3-a456-426614174999",
    "isFollowing": true
  }
}

Success Response Fields:

Field Description
userId UUID of the user being checked
isFollowing Boolean indicating if the authenticated user is following this user (includes pending and accepted follows)

Purpose: Retrieve a list of suggested users to follow, sorted by follower count, excluding users already followed by the authenticated user

Endpoint: GET {base_url}/e-social/follows/featured

Access Level: 🔒 Protected (Requires Bearer Token Authentication)

Authentication: Bearer Token

Request Headers:

Header Type Required Description
Authorization string Yes Bearer token for authentication (format: Bearer <token>)
Content-Type string Yes Must be application/json

Query Parameters:

Parameter Type Required Description Validation Default
limit integer No Maximum number of featured users to return Min: 1, Max: 100 20

Success Response JSON Sample:

{
  "success": true,
  "httpStatus": "OK",
  "message": "Featured users retrieved successfully",
  "action_time": "2025-12-11T10:30:45",
  "data": [
    {
      "id": "555e5555-e55b-55d5-a555-555555555555",
      "userName": "tech_guru",
      "firstName": "Sarah",
      "lastName": "Martinez",
      "profilePictureUrls": ["https://cdn.nexgate.com/profiles/tech_guru.jpg"],
      "isVerified": true,
      "followersCount": 125000,
      "followsMe": false
    },
    {
      "id": "666e6666-e66b-66d6-a666-666666666666",
      "userName": "travel_explorer",
      "firstName": "Mike",
      "lastName": "Chen",
      "profilePictureUrls": ["https://cdn.nexgate.com/profiles/travel_explorer.jpg"],
      "isVerified": true,
      "followersCount": 98500,
      "followsMe": true
    }
  ]
}

Success Response Fields:

Field Description
data Array of featured user objects
data[].id UUID of the featured user
data[].userName Username of the featured user
data[].firstName First name of the featured user
data[].lastName Last name of the featured user
data[].profilePictureUrls Array of profile picture URLs for the featured user
data[].isVerified Boolean indicating if the featured account is verified
data[].followersCount Total number of followers the featured user has
data[].followsMe Boolean indicating if this featured user follows the authenticated user

Purpose: Retrieve a paginated list of suggested users to follow, sorted by follower count, excluding users already followed by the authenticated user

Endpoint: GET {base_url}/e-social/follows/featured/paged

Access Level: 🔒 Protected (Requires Bearer Token Authentication)

Authentication: Bearer Token

Request Headers:

Header Type Required Description
Authorization string Yes Bearer token for authentication (format: Bearer <token>)
Content-Type string Yes Must be application/json

Query Parameters:

Parameter Type Required Description Validation Default
page integer No Page number (1-indexed) Min: 1 1
size integer No Number of items per page Min: 1, Max: 100 20

Success Response JSON Sample:

{
  "success": true,
  "httpStatus": "OK",
  "message": "Featured users retrieved successfully",
  "action_time": "2025-12-11T10:30:45",
  "data": {
    "content": [
      {
        "id": "555e5555-e55b-55d5-a555-555555555555",
        "userName": "tech_guru",
        "firstName": "Sarah",
        "lastName": "Martinez",
        "profilePictureUrls": ["https://cdn.nexgate.com/profiles/tech_guru.jpg"],
        "isVerified": true,
        "followersCount": 125000,
        "followsMe": false
      }
    ],
    "pageable": {
      "pageNumber": 0,
      "pageSize": 20,
      "sort": {
        "empty": true,
        "sorted": false,
        "unsorted": true
      },
      "offset": 0,
      "paged": true,
      "unpaged": false
    },
    "last": false,
    "totalPages": 5,
    "totalElements": 87,
    "first": true,
    "size": 20,
    "number": 0,
    "sort": {
      "empty": true,
      "sorted": false,
      "unsorted": true
    },
    "numberOfElements": 20,
    "empty": false
  }
}

Success Response Fields:

Field Description
data.content Array of featured user objects for the current page
data.content[].id UUID of the featured user
data.content[].userName Username of the featured user
data.content[].firstName First name of the featured user
data.content[].lastName Last name of the featured user
data.content[].profilePictureUrls Array of profile picture URLs
data.content[].isVerified Boolean indicating if account is verified
data.content[].followersCount Total number of followers
data.content[].followsMe Boolean indicating if this user follows the authenticated user
data.pageable Pagination metadata
data.totalPages Total number of pages available
data.totalElements Total number of featured users
data.first Boolean indicating if this is the first page
data.last Boolean indicating if this is the last page
data.size Page size
data.number Current page number (0-indexed)
data.numberOfElements Number of elements in current page
data.empty Boolean indicating if the page is empty

Quick Reference Guide

Common HTTP Status Codes

Authentication

Data Format Standards

Relationship Field Reference

Field Meaning
followsYou Does this user follow you (authenticated user)?
youFollow Do you (authenticated user) follow this user?

These fields enable smart UI rendering:


Version History

v1.1 (2025-12-20)

v1.0 (2025-12-11)

User Relations Endpoints

Privacy Control API

Author: Kibuti, Backend Developer
Last Updated: 2025-12-11
Version: v1.0

Base URL: https://api.nexgate.com/api/v1

Short Description: The Privacy Control API allows users to block and mute other users to control their social interactions. Blocking removes all follow relationships and prevents future interactions, while muting hides content without breaking the follow relationship. These features give users granular control over their social experience.

Hints:


Standard Response Format

All API responses follow a consistent structure using our Globe Response Builder pattern:

Success Response Structure

{
  "success": true,
  "httpStatus": "OK",
  "message": "Operation completed successfully",
  "action_time": "2025-09-23T10:30:45",
  "data": {
    // Actual response data goes here
  }
}

Error Response Structure

{
  "success": false,
  "httpStatus": "BAD_REQUEST",
  "message": "Error description",
  "action_time": "2025-09-23T10:30:45",
  "data": "Error description"
}

Standard Response Fields

Field Type Description
success boolean Always true for successful operations, false for errors
httpStatus string HTTP status name (OK, BAD_REQUEST, NOT_FOUND, etc.)
message string Human-readable message describing the operation result
action_time string ISO 8601 timestamp of when the response was generated
data object/string Response payload for success, error details for failures

HTTP Method Badge Standards

For better visual clarity, all endpoints use colored badges for HTTP methods with the following standard colors:


Endpoints

1. Block User

Purpose: Block a user to prevent all interactions and remove existing follow relationships

Endpoint: POST {base_url}/e-social/privacy-control/block/{userId}

Access Level: 🔒 Protected (Requires Bearer Token Authentication)

Authentication: Bearer Token

Request Headers:

Header Type Required Description
Authorization string Yes Bearer token for authentication (format: Bearer <token>)
Content-Type string Yes Must be application/json

Path Parameters:

Parameter Type Required Description Validation
userId string Yes UUID of the user to block Must be valid UUID format

Success Response JSON Sample:

{
  "success": true,
  "httpStatus": "OK",
  "message": "User blocked successfully",
  "action_time": "2025-12-11T10:30:45",
  "data": {
    "id": "880e8400-e29b-41d4-a716-446655440033",
    "user": {
      "id": "777e7777-e77b-77d7-a777-777777777777",
      "userName": "spam_account",
      "firstName": "Spam",
      "lastName": "Account",
      "profilePictureUrls": ["https://cdn.nexgate.com/profiles/spam_account.jpg"],
      "isVerified": false
    },
    "createdAt": "2025-12-11T10:30:45"
  }
}

Success Response Fields:

Field Description
id Unique identifier for the block record (UUID format)
user Object containing information about the blocked user
user.id UUID of the blocked user
user.userName Username of the blocked user
user.firstName First name of the blocked user
user.lastName Last name of the blocked user
user.profilePictureUrls Array of profile picture URLs for the blocked user
user.isVerified Boolean indicating if the blocked account is verified
createdAt Timestamp when the block was created (ISO 8601 format)

Error Response JSON Sample:

{
  "success": false,
  "httpStatus": "BAD_REQUEST",
  "message": "Cannot block yourself",
  "action_time": "2025-12-11T10:30:45",
  "data": "Cannot block yourself"
}

Standard Error Types:

Application-Level Exceptions (400-499)

Error Response Examples:

Bad Request - Self Block (400):

{
  "success": false,
  "httpStatus": "BAD_REQUEST",
  "message": "Cannot block yourself",
  "action_time": "2025-12-11T10:30:45",
  "data": "Cannot block yourself"
}

Bad Request - Already Blocked (400):

{
  "success": false,
  "httpStatus": "BAD_REQUEST",
  "message": "User already blocked",
  "action_time": "2025-12-11T10:30:45",
  "data": "User already blocked"
}

Not Found (404):

{
  "success": false,
  "httpStatus": "NOT_FOUND",
  "message": "User not found",
  "action_time": "2025-12-11T10:30:45",
  "data": "User not found"
}

2. Unblock User

Purpose: Remove a block on a previously blocked user

Endpoint: DELETE {base_url}/e-social/privacy-control/unblock/{userId}

Access Level: 🔒 Protected (Requires Bearer Token Authentication)

Authentication: Bearer Token

Request Headers:

Header Type Required Description
Authorization string Yes Bearer token for authentication (format: Bearer <token>)
Content-Type string Yes Must be application/json

Path Parameters:

Parameter Type Required Description Validation
userId string Yes UUID of the user to unblock Must be valid UUID format

Success Response JSON Sample:

{
  "success": true,
  "httpStatus": "OK",
  "message": "User unblocked successfully",
  "action_time": "2025-12-11T10:30:45",
  "data": null
}

Success Response Fields:

Field Description
data Always null for this endpoint

Error Response JSON Sample:

{
  "success": false,
  "httpStatus": "NOT_FOUND",
  "message": "User not found",
  "action_time": "2025-12-11T10:30:45",
  "data": "User not found"
}

Standard Error Types:

Application-Level Exceptions (400-499)

Error Response Examples:

Not Found (404):

{
  "success": false,
  "httpStatus": "NOT_FOUND",
  "message": "User not found",
  "action_time": "2025-12-11T10:30:45",
  "data": "User not found"
}

3. Mute User

Purpose: Mute a user to hide their content without breaking the follow relationship

Endpoint: POST {base_url}/e-social/privacy-control/mute/{userId}

Access Level: 🔒 Protected (Requires Bearer Token Authentication)

Authentication: Bearer Token

Request Headers:

Header Type Required Description
Authorization string Yes Bearer token for authentication (format: Bearer <token>)
Content-Type string Yes Must be application/json

Path Parameters:

Parameter Type Required Description Validation
userId string Yes UUID of the user to mute Must be valid UUID format

Success Response JSON Sample:

{
  "success": true,
  "httpStatus": "OK",
  "message": "User muted successfully",
  "action_time": "2025-12-11T10:30:45",
  "data": {
    "id": "990e8400-e29b-41d4-a716-446655440044",
    "user": {
      "id": "888e8888-e88b-88d8-a888-888888888888",
      "userName": "noisy_user",
      "firstName": "Noisy",
      "lastName": "User",
      "profilePictureUrls": ["https://cdn.nexgate.com/profiles/noisy_user.jpg"],
      "isVerified": true
    },
    "createdAt": "2025-12-11T10:30:45"
  }
}

Success Response Fields:

Field Description
id Unique identifier for the mute record (UUID format)
user Object containing information about the muted user
user.id UUID of the muted user
user.userName Username of the muted user
user.firstName First name of the muted user
user.lastName Last name of the muted user
user.profilePictureUrls Array of profile picture URLs for the muted user
user.isVerified Boolean indicating if the muted account is verified
createdAt Timestamp when the mute was created (ISO 8601 format)

Error Response JSON Sample:

{
  "success": false,
  "httpStatus": "BAD_REQUEST",
  "message": "Cannot mute yourself",
  "action_time": "2025-12-11T10:30:45",
  "data": "Cannot mute yourself"
}

Standard Error Types:

Application-Level Exceptions (400-499)

Error Response Examples:

Bad Request - Self Mute (400):

{
  "success": false,
  "httpStatus": "BAD_REQUEST",
  "message": "Cannot mute yourself",
  "action_time": "2025-12-11T10:30:45",
  "data": "Cannot mute yourself"
}

Bad Request - Already Muted (400):

{
  "success": false,
  "httpStatus": "BAD_REQUEST",
  "message": "User already muted",
  "action_time": "2025-12-11T10:30:45",
  "data": "User already muted"
}

Not Found (404):

{
  "success": false,
  "httpStatus": "NOT_FOUND",
  "message": "User not found",
  "action_time": "2025-12-11T10:30:45",
  "data": "User not found"
}

4. Unmute User

Purpose: Remove a mute on a previously muted user

Endpoint: DELETE {base_url}/e-social/privacy-control/unmute/{userId}

Access Level: 🔒 Protected (Requires Bearer Token Authentication)

Authentication: Bearer Token

Request Headers:

Header Type Required Description
Authorization string Yes Bearer token for authentication (format: Bearer <token>)
Content-Type string Yes Must be application/json

Path Parameters:

Parameter Type Required Description Validation
userId string Yes UUID of the user to unmute Must be valid UUID format

Success Response JSON Sample:

{
  "success": true,
  "httpStatus": "OK",
  "message": "User unmuted successfully",
  "action_time": "2025-12-11T10:30:45",
  "data": null
}

Success Response Fields:

Field Description
data Always null for this endpoint

Error Response JSON Sample:

{
  "success": false,
  "httpStatus": "NOT_FOUND",
  "message": "User not found",
  "action_time": "2025-12-11T10:30:45",
  "data": "User not found"
}

Standard Error Types:

Application-Level Exceptions (400-499)

Error Response Examples:

Not Found (404):

{
  "success": false,
  "httpStatus": "NOT_FOUND",
  "message": "User not found",
  "action_time": "2025-12-11T10:30:45",
  "data": "User not found"
}

5. Get Blocked Users

Purpose: Retrieve the complete list of users blocked by the authenticated user

Endpoint: GET {base_url}/e-social/privacy-control/blocked

Access Level: 🔒 Protected (Requires Bearer Token Authentication)

Authentication: Bearer Token

Request Headers:

Header Type Required Description
Authorization string Yes Bearer token for authentication (format: Bearer <token>)
Content-Type string Yes Must be application/json

Success Response JSON Sample:

{
  "success": true,
  "httpStatus": "OK",
  "message": "Blocked users retrieved successfully",
  "action_time": "2025-12-11T10:30:45",
  "data": [
    {
      "id": "880e8400-e29b-41d4-a716-446655440033",
      "user": {
        "id": "777e7777-e77b-77d7-a777-777777777777",
        "userName": "spam_account",
        "firstName": "Spam",
        "lastName": "Account",
        "profilePictureUrls": ["https://cdn.nexgate.com/profiles/spam_account.jpg"],
        "isVerified": false
      },
      "createdAt": "2025-12-11T10:30:45"
    },
    {
      "id": "991e8400-e29b-41d4-a716-446655440044",
      "user": {
        "id": "999e9999-e99b-99d9-a999-999999999999",
        "userName": "troll_user",
        "firstName": "Troll",
        "lastName": "User",
        "profilePictureUrls": ["https://cdn.nexgate.com/profiles/troll_user.jpg"],
        "isVerified": false
      },
      "createdAt": "2025-12-10T15:20:00"
    }
  ]
}

Success Response Fields:

Field Description
data Array of blocked user objects, sorted by createdAt in descending order (newest first)
data[].id Unique identifier for the block record (UUID format)
data[].user Object containing information about the blocked user
data[].user.id UUID of the blocked user
data[].user.userName Username of the blocked user
data[].user.firstName First name of the blocked user
data[].user.lastName Last name of the blocked user
data[].user.profilePictureUrls Array of profile picture URLs for the blocked user
data[].user.isVerified Boolean indicating if the blocked account is verified
data[].createdAt Timestamp when the block was created (ISO 8601 format)

Error Response JSON Sample:

{
  "success": false,
  "httpStatus": "UNAUTHORIZED",
  "message": "Token has expired",
  "action_time": "2025-12-11T10:30:45",
  "data": "Token has expired"
}

Standard Error Types:

Application-Level Exceptions (400-499)

Error Response Examples:

Unauthorized - Token Issues (401):

{
  "success": false,
  "httpStatus": "UNAUTHORIZED",
  "message": "Token has expired",
  "action_time": "2025-12-11T10:30:45",
  "data": "Token has expired"
}

6. Get Muted Users

Purpose: Retrieve the complete list of users muted by the authenticated user

Endpoint: GET {base_url}/e-social/privacy-control/muted

Access Level: 🔒 Protected (Requires Bearer Token Authentication)

Authentication: Bearer Token

Request Headers:

Header Type Required Description
Authorization string Yes Bearer token for authentication (format: Bearer <token>)
Content-Type string Yes Must be application/json

Success Response JSON Sample:

{
  "success": true,
  "httpStatus": "OK",
  "message": "Muted users retrieved successfully",
  "action_time": "2025-12-11T10:30:45",
  "data": [
    {
      "id": "990e8400-e29b-41d4-a716-446655440044",
      "user": {
        "id": "888e8888-e88b-88d8-a888-888888888888",
        "userName": "noisy_user",
        "firstName": "Noisy",
        "lastName": "User",
        "profilePictureUrls": ["https://cdn.nexgate.com/profiles/noisy_user.jpg"],
        "isVerified": true
      },
      "createdAt": "2025-12-11T10:30:45"
    },
    {
      "id": "101e8400-e29b-41d4-a716-446655440055",
      "user": {
        "id": "100e1000-e10b-10d1-a100-100000000000",
        "userName": "oversharer",
        "firstName": "Over",
        "lastName": "Sharer",
        "profilePictureUrls": ["https://cdn.nexgate.com/profiles/oversharer.jpg"],
        "isVerified": false
      },
      "createdAt": "2025-12-09T08:15:30"
    }
  ]
}

Success Response Fields:

Field Description
data Array of muted user objects, sorted by createdAt in descending order (newest first)
data[].id Unique identifier for the mute record (UUID format)
data[].user Object containing information about the muted user
data[].user.id UUID of the muted user
data[].user.userName Username of the muted user
data[].user.firstName First name of the muted user
data[].user.lastName Last name of the muted user
data[].user.profilePictureUrls Array of profile picture URLs for the muted user
data[].user.isVerified Boolean indicating if the muted account is verified
data[].createdAt Timestamp when the mute was created (ISO 8601 format)

Error Response JSON Sample:

{
  "success": false,
  "httpStatus": "UNAUTHORIZED",
  "message": "Token has expired",
  "action_time": "2025-12-11T10:30:45",
  "data": "Token has expired"
}

Standard Error Types:

Application-Level Exceptions (400-499)

Error Response Examples:

Unauthorized - Token Issues (401):

{
  "success": false,
  "httpStatus": "UNAUTHORIZED",
  "message": "Token has expired",
  "action_time": "2025-12-11T10:30:45",
  "data": "Token has expired"
}

Quick Reference Guide

Common HTTP Status Codes

Authentication

Data Format Standards

Key Differences Between Block and Mute

Feature Block Mute
Removes follow relationships Yes No
Hides content Yes Yes
User knows they're blocked/muted Possibly (can't follow) No
Can send messages No Yes (if messaging exists)
Can view profile Limited Yes

Posts Management API

Author: Josh, Lead Backend Team
Last Updated: 2026-06-18
Version: v1.0

Base URL: https://api.nexgate.com/api/v1

Short Description: The Posts Management API provides comprehensive social media posting functionality including creating posts, polls, quote posts, drafts management, media attachments, commerce integrations, collaboration features, and engagement interactions (likes, bookmarks, reposts, comments). This API enables users to create rich content with privacy controls and scheduled publishing.

Hints:


Standard Response Format

All API responses follow a consistent structure using our Globe Response Builder pattern:

Success Response Structure

{
  "success": true,
  "httpStatus": "OK",
  "message": "Operation completed successfully",
  "action_time": "2025-09-23T10:30:45",
  "data": {
    // Actual response data goes here
  }
}

Error Response Structure

{
  "success": false,
  "httpStatus": "BAD_REQUEST",
  "message": "Error description",
  "action_time": "2025-09-23T10:30:45",
  "data": "Error description"
}

Standard Response Fields

Field Type Description
success boolean Always true for successful operations, false for errors
httpStatus string HTTP status name (OK, BAD_REQUEST, NOT_FOUND, etc.)
message string Human-readable message describing the operation result
action_time string ISO 8601 timestamp of when the response was generated
data object/string Response payload for success, error details for failures

HTTP Method Badge Standards

For better visual clarity, all endpoints use colored badges for HTTP methods with the following standard colors:


Common Response Structure for POST/PUT Operations

Most POST and PUT operations return a PostResponse object. For brevity, this documentation references the detailed PostResponse structure defined below instead of repeating it for each endpoint.

Standard Success Response for Post Creation/Update:

{
  "success": true,
  "httpStatus": "OK",
  "message": "[Operation-specific message]",
  "action_time": "2025-12-11T10:30:45",
  "data": {
    // PostResponse object - see "PostResponse Structure" section below
  }
}

PostResponse Structure

This is the standard response structure returned by most post-related endpoints:

{
  "id": "550e8400-e29b-41d4-a716-446655440000",
  "author": {
    "id": "123e4567-e89b-12d3-a456-426614174000",
    "userName": "john_doe",
    "firstName": "John",
    "lastName": "Doe",
    "profilePictureUrl": "https://cdn.nexgate.com/profiles/john_doe.jpg",
    "isVerified": true
  },
  "content": "Check out this amazing product! @jane_doe #shopping",
  "contentParsed": {
    "text": "Check out this amazing product! @jane_doe #shopping",
    "entities": [
      {
        "type": "MENTION",
        "text": "@jane_doe",
        "startIndex": 33,
        "endIndex": 42,
        "user": {
          "id": "987e6543-e21b-12d3-a456-426614174999",
          "userName": "jane_doe",
          "firstName": "Jane",
          "lastName": "Doe",
          "profilePictureUrl": "https://cdn.nexgate.com/profiles/jane_doe.jpg"
        }
      },
      {
        "type": "HASHTAG",
        "text": "#shopping",
        "startIndex": 43,
        "endIndex": 52,
        "hashtag": "shopping"
      }
    ]
  },
  "postType": "REGULAR",
  "postKind": "ORIGINAL",
  "status": "PUBLISHED",
  "media": [
    {
      "id": "media-123",
      "mediaType": "IMAGE",
      "originalUrl": "https://cdn.nexgate.com/posts/image1.jpg",
      "thumbnailUrl": "https://cdn.nexgate.com/posts/image1_thumb.jpg",
      "placeholderBase64": "base64-string-here",
      "width": 1920,
      "height": 1080,
      "order": 1,
      "imageTags": []
    }
  ],
  "attachments": {
    "products": [],
    "shops": [],
    "events": [],
    "buyTogetherGroups": [],
    "installmentPlans": [],
    "externalLink": null
  },
 "collaboration": {
  "isCollaborative": true,
  "collaborators": [
    {
      "id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
      "status": "ACCEPTED",
      "invitedAt": "2024-01-15T10:00:00",
      "respondedAt": "2024-01-15T10:30:00",
      "user": {
        "id": "u1b2c3d4-e5f6-7890-abcd-ef1234567890",
        "userName": "john_doe",
        "firstName": "John",
        "lastName": "Doe",
        "profilePictureUrl": "https://cdn.example.com/photos/john.jpg"
      }
    },
    {
      "id": "b2c3d4e5-f6a7-8901-bcde-f12345678901",
      "status": "PENDING",
      "invitedAt": "2024-01-15T11:00:00",
      "respondedAt": null,
      "user": {
        "id": "u2c3d4e5-f6a7-8901-bcde-f12345678901",
        "userName": "current_user",
        "firstName": "Current",
        "lastName": "User",
        "profilePictureUrl": "https://cdn.example.com/photos/current.jpg"
      }
    }
  ],
  "byline": "By Jane Smith and 1 others",
  "currentUserStatus": "PENDING",
  "currentUserIsPendingCollaborator": true,
  "currentUserIsAcceptedCollaborator": false
},
  "privacySettings": {
    "visibility": "PUBLIC",
    "whoCanComment": "EVERYONE",
    "whoCanRepost": "EVERYONE",
    "hideLikesCount": false,
    "hideCommentsCount": false
  },
  "engagement": {
    "likesCount": 0,
    "commentsCount": 0,
    "repostsCount": 0,
    "quotesCount": 0,
    "bookmarksCount": 0,
    "sharesCount": 0,
    "viewsCount": 0,
    "canLike": true,
    "canComment": true,
    "canRepost": true,
    "canShare": true
  },
   "userInteraction": {
      "hasLiked": false,
      "hasBookmarked": true,
      "hasReposted": false,
      "myRepostId": null,
      "hasQuoted": true,
      "hasCommented": false,
      "hasViewed": true,
      "hasShared": false
    },
  "topComments": [
    {
      "id": "comment-001",
      "userId": "user-abc-123",
      "content": "This is amazing! 🔥",
      "userName": "sarah_smith",
      "displayName": "Sarah Smith",
      "profilePictureUrl": "https://cdn.nexgate.com/profiles/sarah_smith.jpg"
    },
    {
      "id": "comment-002",
      "userId": "user-xyz-789",
      "content": "Where can I get this?",
      "userName": "mike_wilson",
      "displayName": "Mike Wilson",
      "profilePictureUrl": "https://cdn.nexgate.com/profiles/mike_wilson.jpg"
    }
  ],
  "topLikers": [
    {
      "userId": "user-abc-123",
      "userName": "john_doe",
      "displayName": "John Doe",
      "profilePictureUrl": "https://cdn.nexgate.com/profiles/john_doe.jpg"
    },
    {
      "userId": "user-xyz-789",
      "userName": "sarah_smith",
      "displayName": "Sarah Smith",
      "profilePictureUrl": "https://cdn.nexgate.com/profiles/sarah_smith.jpg"
    }
  ],
  "topReposters": [
    {
      "userId": "user-lmn-456",
      "userName": "mike_wilson",
      "displayName": "Mike Wilson",
      "profilePictureUrl": "https://cdn.nexgate.com/profiles/mike_wilson.jpg"
    }
  ],
  "createdAt": "2025-12-11T10:30:45",
  "publishedAt": "2025-12-11T10:30:45",
  "scheduledAt": null
}

Endpoints

1. Create Post

Purpose: Create a new post (draft or scheduled) with optional content, media, poll, attachments, and collaboration

Endpoint: POST {base_url}/e-social/posts

Access Level: 🔒 Protected (Requires Bearer Token Authentication)

Authentication: Bearer Token

Behavior:

Business Rules:

  1. Draft System: Only one draft allowed per user at a time
  2. Content Requirements: Either content text OR media OR poll must be provided (not all optional)
  3. Poll Requirements: If postType is POLL, poll object with 2-10 options is required
  4. Media Limits: Maximum 10 media items per post
  5. Commerce Limits: Max 10 products, 5 shops, 3 events per post
  6. Collaboration Limits: Maximum 5 collaborators per post
  7. Scheduling Rules: Scheduled time must be at least 5 minutes in future, max 6 months ahead
  8. Mention Extraction: System automatically detects and links @username and $shopname mentions
  9. Hashtag Indexing: All #hashtags automatically indexed for search and trending
  10. Privacy Inheritance: MENTIONED visibility requires at least one @mention in content

Request Headers:

Header Type Required Description
Authorization string Yes Bearer token for authentication (format: Bearer <token>)
Content-Type string Yes Must be application/json

Request JSON Sample:

{
  "content": "Excited to share my latest project! @john_doe check this out #coding",
  "postType": "REGULAR",
  "media": [
    {
      "mediaType": "IMAGE",
      "mediaUrl": "https://cdn.nexgate.com/uploads/image1.jpg",
      "placeholderBase64": "base64-string",
      "width": 1920,
      "height": 1080
    }
  ],
  "privacySettings": {
    "visibility": "PUBLIC",
    "whoCanComment": "EVERYONE",
    "whoCanRepost": "EVERYONE",
    "hideLikesCount": false,
    "hideCommentsCount": false
  },
  "scheduledAt": null
}

Request Body Parameters:

Parameter Type Required Description Validation
content string No* Post text content Max: 5000 characters. *Required if no media/poll
postType string Yes Type of post enum: REGULAR, POLL
media array No Array of media objects (images/videos) Max: 10 items
media[].mediaType string Yes (if media provided) Type of media enum: IMAGE, VIDEO
media[].mediaUrl string Yes (if media provided) URL of the media file Valid URL format, must be from approved CDN
media[].placeholderBase64 string No BlurHash or base64 placeholder Used for progressive image loading
media[].width integer No Media width in pixels Min: 1, Max: 8000
media[].height integer No Media height in pixels Min: 1, Max: 8000
media[].duration integer No Video duration in seconds Required for videos, Max: 600 (10 minutes)
poll object No Poll configuration Required if postType is POLL
poll.title string Yes (if poll provided) Poll question/title Min: 5, Max: 500 characters
poll.description string No Additional poll description Max: 1000 characters
poll.options array Yes (if poll provided) Array of poll options Min: 2, Max: 10
poll.options[].optionText string Yes Text for the poll option Min: 1, Max: 200 characters
poll.options[].optionImageUrl string No Optional image for the option Valid URL format, must be from approved CDN
poll.allowMultipleVotes boolean No Allow selecting multiple options Default: false
poll.isAnonymous boolean No Hide voter identities Default: true. If false, voters visible to post author
poll.allowVoteChange boolean No Allow users to change their vote Default: true. If false, votes are final
poll.expiresAt string No Poll expiration datetime ISO 8601 format, must be future, max 30 days from now
poll.hideResultsUntilExpiry boolean No Hide vote counts and results until the poll expires Default: false. When true, results are only revealed after expiresAt passes — even voters cannot see counts before then. Requires expiresAt to be meaningful; if no expiry is set, results remain hidden indefinitely
attachments object No Commerce attachments
attachments.productIds array No Array of product UUIDs to attach Max: 10. Products must be ACTIVE status
attachments.shopIds array No Array of shop UUIDs to attach Max: 5. Shops must be VERIFIED
attachments.eventIds array No Array of event UUIDs to attach Max: 3. Events must be PUBLISHED
attachments.buyTogetherGroupIds array No Array of group purchase UUIDs Groups must be ACTIVE, not COMPLETED
attachments.installmentPlanIds array No Array of installment plan UUIDs Plans must be ACTIVE, not EXPIRED
attachments.externalLink object No External link object Only one external link allowed per post
attachments.externalLink.url string Yes (if externalLink provided) URL to attach Valid URL format, supports http/https only
collaboration object No Collaboration settings
collaboration.collaboratorIds array No Array of user UUIDs to invite Max: 5. Users must not be blocked by author
privacySettings object No Privacy configuration
privacySettings.visibility string No Post visibility level enum: PUBLIC, FOLLOWERS, MENTIONED, PRIVATE. Default: PUBLIC
privacySettings.whoCanComment string No Comment permission level enum: EVERYONE, FOLLOWERS, MENTIONED, DISABLED. Default: EVERYONE
privacySettings.whoCanRepost string No Repost permission level enum: EVERYONE, FOLLOWERS, DISABLED. Default: EVERYONE
privacySettings.hideLikesCount boolean No Hide like count from others Default: false. Author always sees true count
privacySettings.hideCommentsCount boolean No Hide comment count from others Default: false. Author always sees true count
scheduledAt string No Schedule post for future publication ISO 8601 format, must be 5+ minutes future, max 6 months ahead

Validation Notes:

Success Response: Returns standard PostResponse structure (see "PostResponse Structure" section above)

Success Response Message: "Post created successfully"

Error Response JSON Sample:

{
  "success": false,
  "httpStatus": "BAD_REQUEST",
  "message": "You already have a draft post",
  "action_time": "2025-12-11T10:30:45",
  "data": "You already have a draft post. Please update or publish your existing draft before creating a new one."
}

Standard Error Types:

Application-Level Exceptions (400-499)

Error Response Examples:

Bad Request - Existing Draft (400):

{
  "success": false,
  "httpStatus": "BAD_REQUEST",
  "message": "You already have a draft post",
  "action_time": "2025-12-11T10:30:45",
  "data": "You already have a draft post. Please update or publish your existing draft before creating a new one."
}

Validation Error - Content Too Long (422):

{
  "success": false,
  "httpStatus": "UNPROCESSABLE_ENTITY",
  "message": "Validation failed",
  "action_time": "2025-12-11T10:30:45",
  "data": {
    "content": "Content exceeds maximum length of 5000 characters"
  }
}

Validation Error - Invalid Poll (422):

{
  "success": false,
  "httpStatus": "UNPROCESSABLE_ENTITY",
  "message": "Validation failed",
  "action_time": "2025-12-11T10:30:45",
  "data": {
    "poll.options": "Poll must have at least 2 options"
  }
}

Validation Error - Empty Post (422):

{
  "success": false,
  "httpStatus": "UNPROCESSABLE_ENTITY",
  "message": "Post must have content, media, or poll",
  "action_time": "2025-12-11T10:30:45",
  "data": "At least one of content, media, or poll must be provided"
}

Validation Error - Invalid Product Attachment (404):

{
  "success": false,
  "httpStatus": "NOT_FOUND",
  "message": "Product not found",
  "action_time": "2025-12-11T10:30:45",
  "data": "Product with ID 550e8400-e29b-41d4-a716-446655440000 not found or inactive"
}

Validation Error - Scheduled Time in Past (400):

{
  "success": false,
  "httpStatus": "BAD_REQUEST",
  "message": "Invalid scheduled time",
  "action_time": "2025-12-11T10:30:45",
  "data": "Scheduled time must be at least 5 minutes in the future"
}

Validation Error - Blocked Collaborator (403):

{
  "success": false,
  "httpStatus": "FORBIDDEN",
  "message": "Cannot collaborate with blocked user",
  "action_time": "2025-12-11T10:30:45",
  "data": "User 770e8400-e29b-41d4-a716-446655440001 has blocked you or you have blocked them"
}

Use Case Examples:

Example 1: Simple Text Post

{
  "content": "Just launched my new product! Check it out at nexgate.com/myshop",
  "postType": "REGULAR"
}

Result: Creates a PUBLIC draft post with text only, no attachments.

Example 2: Product Showcase Post

{
  "content": "New arrivals! 🎉 Amazing deals on electronics. $TechWorld #shopping #deals",
  "postType": "REGULAR",
  "media": [
    {
      "mediaType": "IMAGE",
      "mediaUrl": "https://cdn.nexgate.com/uploads/product1.jpg",
      "width": 1920,
      "height": 1080
    }
  ],
  "attachments": {
    "productIds": ["550e8400-e29b-41d4-a716-446655440001", "550e8400-e29b-41d4-a716-446655440002"],
    "shopIds": ["660e8400-e29b-41d4-a716-446655440003"]
  }
}

Result: Creates draft with image, attaches 2 products and 1 shop, extracts $TechWorld mention and #shopping/#deals hashtags.

Example 3: Poll Post

{
  "content": "What feature should we build next? Vote below! 👇",
  "postType": "POLL",
  "poll": {
    "title": "Next Feature Priority",
    "description": "Help us decide what to build for Q1 2026",
    "options": [
      {"optionText": "Dark Mode"},
      {"optionText": "Video Upload"},
      {"optionText": "Live Streaming"},
      {"optionText": "Advanced Analytics"}
    ],
    "allowMultipleVotes": true,
    "isAnonymous": false,
    "allowVoteChange": true,
    "expiresAt": "2025-12-25T23:59:59Z",
    "hideResultsUntilExpiry": true
  }
}

Result: Creates poll allowing multiple votes, non-anonymous (voters visible), votes can be changed, expires Dec 25. Results (vote counts) are hidden from everyone until Dec 25 — after expiry they become visible automatically.

Example 4: Scheduled Collaborative Event Post

{
  "content": "Excited to announce our tech conference! @john_doe and I are hosting. Join us! 🚀 #TechConf2026",
  "postType": "REGULAR",
  "attachments": {
    "eventIds": ["880e8400-e29b-41d4-a716-446655440004"]
  },
  "collaboration": {
    "collaboratorIds": ["770e8400-e29b-41d4-a716-446655440001"]
  },
  "scheduledAt": "2025-12-20T08:00:00Z"
}

Result: Creates scheduled post for Dec 20, attaches event, sends collaboration invite to john_doe, extracts @john_doe mention and #TechConf2026 hashtag.


2. Publish Draft Post

Purpose: Publish the current user's draft post

Endpoint: POST {base_url}/api/v1/e-social/posts/publish

Access Level: 🔒 Protected (Requires Authentication)

Authentication: Bearer Token

Request Headers:

Header Type Required Description
Authorization string Yes Bearer token for authentication
Content-Type string Yes Must be application/json

Content Validation Rules:

The post must pass content validation before publishing. At minimum, a post must have meaningful content.

Scenario Allowed? Notes
Text only ✅ Yes Valid standalone post
Text + Media ✅ Yes Valid post with images/videos
Media only (no text) ✅ Yes Image/video post without caption
Poll only ✅ Yes Poll title serves as content
Poll + Text ✅ Yes Enhanced poll post
Quote only ✅ Yes Quoted post provides context
Quote + Text ✅ Yes Quote with commentary
Attachment only (product/shop/event/link) ✅ Yes Commerce/social attachment
Attachment + Text ✅ Yes Enhanced attachment post
Attachment + Media (no text) ✅ Yes Rich commerce post
Attachment + Media + Text ✅ Yes Full featured post
Empty post ❌ No Must have at least one content type

Validation Error Messages:

Condition Error Message
Media without text "Media posts must include text content"
Empty post "Post must have at least one of: text content, poll, quote, or attachments"
No draft found "No draft found"
Pending collaborators "Cannot publish collaborative post - waiting for collaborator acceptance"

Business Rules:

  1. Draft Requirement: User must have exactly one draft post
  2. Content Validation: Draft must pass all content validation rules (see table above)
  3. Media Rule: Posts with media (images/videos) must include text content
  4. Collaboration Status: All invited collaborators must have accepted (status = ACCEPTED)
  5. Attachment Validation: All attached products/shops/events must still be active/valid
  6. Scheduled Posts: Cannot publish a scheduled post using this endpoint
  7. Feed Distribution: Published posts immediately appear in followers' feeds
  8. Notification Triggers: Sends notifications to @mentioned users and collaborators

Validation Checks on Publish:

Success Response JSON Sample:

{
  "success": true,
  "httpStatus": "OK",
  "message": "Post published successfully",
  "action_time": "2025-12-29T10:30:45",
  "data": {
    "id": "550e8400-e29b-41d4-a716-446655440000",
    "author": {
      "id": "660e8400-e29b-41d4-a716-446655440001",
      "userName": "john_doe",
      "firstName": "John",
      "lastName": "Doe",
      "profilePictureUrl": "https://storage.example.com/profiles/john.jpg",
      "isVerified": true
    },
    "content": "Check out this amazing product! 🛍️",
    "postType": "REGULAR",
    "status": "PUBLISHED",
    "media": [
      {
        "id": "media-001",
        "mediaType": "IMAGE",
        "originalUrl": "https://storage.example.com/posts/image1.jpg",
        "thumbnailUrl": "https://storage.example.com/posts/image1_thumb.jpg",
        "width": 1080,
        "height": 1080,
        "order": 0
      }
    ],
    "attachments": {
      "products": [
        {
          "id": "770e8400-e29b-41d4-a716-446655440002",
          "name": "Wireless Headphones",
          "price": 150000.00,
          "imageUrl": "https://storage.example.com/products/headphones.jpg",
          "shopName": "TechStore TZ",
          "inStock": true
        }
      ],
      "shops": [],
      "events": [],
      "buyTogetherGroups": [],
      "installmentPlans": [],
      "externalLink": null
    },
    "privacySettings": {
      "visibility": "PUBLIC",
      "whoCanComment": "EVERYONE",
      "whoCanRepost": "EVERYONE",
      "hideLikesCount": false,
      "hideCommentsCount": false
    },
    "engagement": {
      "likesCount": 0,
      "commentsCount": 0,
      "repostsCount": 0,
      "quotesCount": 0,
      "bookmarksCount": 0,
      "sharesCount": 0,
      "viewsCount": 0,
      "canLike": true,
      "canComment": true,
      "canRepost": true,
      "canShare": true
    },
    "userInteraction": {
      "hasLiked": false,
      "hasBookmarked": false,
      "hasReposted": false,
      "myRepostId": null,
      "hasQuoted": false,
      "hasCommented": false,
      "hasViewed": false,
      "hasShared": false
    },
    "createdAt": "2025-12-29T10:00:00",
    "publishedAt": "2025-12-29T10:30:45",
    "scheduledAt": null
  }
}

Success Response Fields:

Field Description
id Unique identifier of the published post
author Information about the post author
content Text content of the post
postType Content type: REGULAR, POLL
postKind Sharing kind: ORIGINAL, REPOST, QUOTE (derived, not stored in DB)
status Post status (now PUBLISHED)
media Array of media attachments (images/videos)
attachments Commerce and social attachments
privacySettings Privacy and interaction settings
engagement Engagement counters (all start at 0)
userInteraction Current user's interaction status
publishedAt Timestamp when post was published

Error Response JSON Samples:

Media Without Text Content:

{
  "success": false,
  "httpStatus": "BAD_REQUEST",
  "message": "Media posts must include text content",
  "action_time": "2025-12-29T10:30:45",
  "data": null
}

Empty Post:

{
  "success": false,
  "httpStatus": "BAD_REQUEST",
  "message": "Post must have at least one of: text content, poll, quote, or attachments",
  "action_time": "2025-12-29T10:30:45",
  "data": null
}

No Draft Found:

{
  "success": false,
  "httpStatus": "BAD_REQUEST",
  "message": "No draft found",
  "action_time": "2025-12-29T10:30:45",
  "data": null
}

Pending Collaborator Approval:

{
  "success": false,
  "httpStatus": "FORBIDDEN",
  "message": "Cannot publish collaborative post - waiting for collaborator acceptance",
  "action_time": "2025-12-29T10:30:45",
  "data": "2 of 3 collaborators have accepted"
}

Invalid Attached Product:

{
  "success": false,
  "httpStatus": "UNPROCESSABLE_ENTITY",
  "message": "Invalid product attachment",
  "action_time": "2025-12-29T10:30:45",
  "data": "Product 550e8400-e29b-41d4-a716-446655440001 is no longer active"
}

Standard Error Types:

Use Case Examples:

Example 1: Text Only Post

Draft: "Hello world! This is my first post"
Result: ✅ Published successfully

Example 2: Text + Media Post

Draft: "Check out this sunset! 🌅" + [image.jpg]
Result: ✅ Published successfully

Example 3: Media Only (No Text)

Draft: [image.jpg] (no text content)
Result: ❌ Error - "Media posts must include text content"

Example 4: Poll Only

Draft: Poll "What's your favorite color?" with options [Red, Blue, Green]
Result: ✅ Published successfully (poll title serves as content)

Example 5: Product Attachment Only

Draft: Attached product "Wireless Headphones" (no text)
Result: ✅ Published successfully (attachment provides context)

Example 6: Product + Media (No Text)

Draft: Attached product + [product_photo.jpg] (no text)
Result: ❌ Error - "Media posts must include text content"

Example 7: Quote Post Only

Draft: Quoting another post (no additional text)
Result: ✅ Published successfully (quoted post provides context)

Example 8: Empty Post

Draft: No content, no media, no attachments
Result: ❌ Error - "Post must have at least one of: text content, poll, quote, or attachments"

3. Delete Post

Purpose: Soft delete a post (marks as deleted, doesn't remove from database)

Endpoint: DELETE {base_url}/e-social/posts/{postId}

Access Level: 🔒 Protected (Requires Bearer Token Authentication)

Authentication: Bearer Token

Behavior:

Business Rules:

  1. Author Only: Only the original post author can delete (collaborators cannot)
  2. Soft Delete: Data retained in database with isDeleted = true
  3. Irreversible: Deleted posts cannot be undeleted (would need backend intervention)
  4. Cascade Hiding: Comments/likes/bookmarks hidden but not deleted
  5. Analytics Preservation: Engagement data preserved for historical analytics
  6. Feed Removal: Immediately removed from all feeds (home, explore, profile)
  7. Notification: Collaborators notified of deletion
  8. Attachment Impact: Products/shops/events lose post engagement stats
  9. Repost Cascade: All pure reposts (no added text) are automatically soft-deleted asynchronously — response is instant, cascade runs in background
  10. Quote Posts Survive: Quote posts (which have their own content) remain alive but show quotedPost.unavailable = true with message "This post is no longer available."
  11. Interactions on dead reposts: Once the original is deleted, likes/comments/views on any repost of it return "Post not found" — interactions are blocked

What Gets Hidden:

What Gets Preserved (in database for analytics):

Request Headers:

Header Type Required Description
Authorization string Yes Bearer token for authentication (format: Bearer <token>)
Content-Type string Yes Must be application/json

Path Parameters:

Parameter Type Required Description Validation
postId string Yes UUID of the post to delete Must be valid UUID format

Success Response JSON Sample:

{
  "success": true,
  "httpStatus": "OK",
  "message": "Post deleted successfully",
  "action_time": "2025-12-11T10:30:45",
  "data": null
}

Success Response Fields:

Field Description
data Always null for this endpoint

Standard Error Types:

Application-Level Exceptions (400-499)

Error Response Examples:

Not Post Author (403):

{
  "success": false,
  "httpStatus": "FORBIDDEN",
  "message": "Cannot delete post",
  "action_time": "2025-12-11T10:30:45",
  "data": "Only the post author can delete this post. Collaborators cannot delete."
}

Post Not Found (404):

{
  "success": false,
  "httpStatus": "NOT_FOUND",
  "message": "Post not found",
  "action_time": "2025-12-11T10:30:45",
  "data": "Post with ID 550e8400-e29b-41d4-a716-446655440000 not found or already deleted"
}

Use Case Examples:

Example 1: Delete Regular Post

DELETE /e-social/posts/550e8400-e29b-41d4-a716-446655440000

Post has: 50 likes, 10 comments, 5 reposts
Result: Post soft deleted, all engagement hidden, removed from feeds, data preserved in DB

Example 2: Delete Post with Product Attachments

DELETE /e-social/posts/660e8400-e29b-41d4-a716-446655440001

Post attached to 2 products
Result: Post deleted, product engagement counters decremented, post removed from product pages

Example 3: Collaborator Tries to Delete (Fails)

DELETE /e-social/posts/770e8400-e29b-41d4-a716-446655440002

User is collaborator, not author
Result: Error 403 - Only original author can delete collaborative posts

4. Get Post by ID

Purpose: Retrieve a single post by its ID with full details

Endpoint: GET {base_url}/e-social/posts/{postId}

Access Level: 🔒 Protected (Requires Bearer Token Authentication)

Authentication: Bearer Token

Behavior:

Visibility Logic:

Additional Access Rules:

Response Includes:

Request Headers:

Header Type Required Description
Authorization string Yes Bearer token for authentication (format: Bearer <token>)
Content-Type string Yes Must be application/json

Path Parameters:

Parameter Type Required Description Validation
postId string Yes UUID of the post to retrieve Must be valid UUID format

Success Response: Returns standard PostResponse structure

Success Response Message: "Post retrieved successfully"

Standard Error Types:

Application-Level Exceptions (400-499)

Error Response Examples:

Post Not Found (404):

{
  "success": false,
  "httpStatus": "NOT_FOUND",
  "message": "Post not found",
  "action_time": "2025-12-11T10:30:45",
  "data": "Post with ID 550e8400-e29b-41d4-a716-446655440000 not found"
}

Insufficient Permissions - Followers Only (403):

{
  "success": false,
  "httpStatus": "FORBIDDEN",
  "message": "Cannot view this post",
  "action_time": "2025-12-11T10:30:45",
  "data": "This post is visible to followers only. Follow the author to view."
}

Blocked User (403):

{
  "success": false,
  "httpStatus": "FORBIDDEN",
  "message": "Cannot view this post",
  "action_time": "2025-12-11T10:30:45",
  "data": "You cannot view posts from this user"
}

Use Case Examples:

Example 1: View Public Post

GET /e-social/posts/550e8400-e29b-41d4-a716-446655440000

Post visibility: PUBLIC
Result: Full post details returned, view counter incremented, engagement visible

Example 2: View Followers-Only Post (Not Following)

GET /e-social/posts/660e8400-e29b-41d4-a716-446655440001

Post visibility: FOLLOWERS
User is not following author
Result: Error 403 - Must follow author to view

Example 3: View Mentioned Post (Not Mentioned)

GET /e-social/posts/770e8400-e29b-41d4-a716-446655440002

Post visibility: MENTIONED
User not mentioned in post
Result: Error 403 - Only mentioned users can view

Example 4: View Own Draft Post

GET /e-social/posts/880e8400-e29b-41d4-a716-446655440003

Post status: DRAFT
User is post author
Result: Full post details returned with status = DRAFT

Example 5: View Collaborative Post (As Collaborator)

GET /e-social/posts/990e8400-e29b-41d4-a716-446655440004

Post visibility: PRIVATE
User is accepted collaborator
Result: Full post details returned (collaborators can always view)

5. Get Published Posts

Purpose: Retrieve all published posts with pagination (for discovery/explore feed)

Endpoint: GET {base_url}/e-social/posts

Access Level: 🔒 Protected (Requires Bearer Token Authentication)

Authentication: Bearer Token

Request Headers:

Header Type Required Description
Authorization string Yes Bearer token for authentication (format: Bearer <token>)
Content-Type string Yes Must be application/json

Query Parameters:

Parameter Type Required Description Validation Default
page integer No Page number (1-indexed) Min: 1 1
size integer No Number of items per page Min: 1, Max: 100 20

Success Response JSON Sample:

{
  "success": true,
  "httpStatus": "OK",
  "message": "Posts retrieved successfully",
  "action_time": "2025-12-11T10:30:45",
  "data": [
    {
      // PostResponse object
    },
    {
      // PostResponse object
    }
  ]
}

Success Response Fields:

Field Description
data Array of PostResponse objects

Standard Error Types:

Application-Level Exceptions (400-499)


6. Get Posts by Author

Purpose: Retrieve all posts from a specific author with pagination

Endpoint: GET {base_url}/e-social/posts/author/{authorId}

Access Level: 🔒 Protected (Requires Bearer Token Authentication)

Authentication: Bearer Token

Request Headers:

Header Type Required Description
Authorization string Yes Bearer token for authentication (format: Bearer <token>)
Content-Type string Yes Must be application/json

Path Parameters:

Parameter Type Required Description Validation
authorId string Yes UUID of the author Must be valid UUID format

Query Parameters:

Parameter Type Required Description Validation Default
page integer No Page number (1-indexed) Min: 1 1
size integer No Number of items per page Min: 1, Max: 100 20

Success Response: Returns array of PostResponse objects

Success Response Message: "Posts retrieved successfully"

Standard Error Types:

Application-Level Exceptions (400-499)


7. Get My Scheduled Posts

Purpose: Retrieve all scheduled posts for the authenticated user

Endpoint: GET {base_url}/e-social/posts/scheduled

Access Level: 🔒 Protected (Requires Bearer Token Authentication)

Authentication: Bearer Token

Request Headers:

Header Type Required Description
Authorization string Yes Bearer token for authentication (format: Bearer <token>)
Content-Type string Yes Must be application/json

Success Response: Returns array of PostResponse objects with status SCHEDULED

Success Response Message: "Scheduled posts retrieved successfully"

Standard Error Types:

Application-Level Exceptions (400-499)


8. Get My Current Draft

Purpose: Retrieve the authenticated user's current draft post

Endpoint: GET {base_url}/e-social/posts/draft

Access Level: 🔒 Protected (Requires Bearer Token Authentication)

Authentication: Bearer Token

Request Headers:

Header Type Required Description
Authorization string Yes Bearer token for authentication (format: Bearer <token>)
Content-Type string Yes Must be application/json

Success Response: Returns standard PostResponse structure with status DRAFT, or null if no draft exists

Success Response Message: "Draft retrieved successfully"

Standard Error Types:

Application-Level Exceptions (400-499)


9. Discard Draft

Purpose: Delete the current draft post permanently

Endpoint: DELETE {base_url}/e-social/posts/draft

Access Level: 🔒 Protected (Requires Bearer Token Authentication)

Authentication: Bearer Token

Request Headers:

Header Type Required Description
Authorization string Yes Bearer token for authentication (format: Bearer <token>)
Content-Type string Yes Must be application/json

Success Response JSON Sample:

{
  "success": true,
  "httpStatus": "OK",
  "message": "Draft discarded successfully",
  "action_time": "2025-12-11T10:30:45",
  "data": null
}

Standard Error Types:

Application-Level Exceptions (400-499)


10. Update Draft

Purpose: Update content, media, or privacy settings of the current draft

Endpoint: PUT {base_url}/e-social/posts

Access Level: 🔒 Protected (Requires Bearer Token Authentication)

Authentication: Bearer Token

Request Headers:

Header Type Required Description
Authorization string Yes Bearer token for authentication (format: Bearer <token>)
Content-Type string Yes Must be application/json

Request JSON Sample:

{
  "content": "Updated post content",
  "media": [
    {
      "mediaType": "IMAGE",
      "mediaUrl": "https://cdn.nexgate.com/uploads/new_image.jpg",
      "width": 1920,
      "height": 1080
    }
  ],
  "privacySettings": {
    "visibility": "FOLLOWERS",
    "whoCanComment": "FOLLOWERS"
  }
}

Request Body Parameters:

Parameter Type Required Description Validation
content string No Updated post text content Max: 5000 characters
media array No Updated media array Max: 10 items
privacySettings object No Updated privacy settings

Success Response: Returns standard PostResponse structure with updated values

Success Response Message: "Draft updated successfully"

Standard Error Types:

Application-Level Exceptions (400-499)


11-20. Draft Commerce Attachments (Attach/Remove Products, Shops, Events, Groups, Plans)

For brevity, these endpoints follow the same pattern:

Attach Endpoints: POST {base_url}/e-social/posts/draft/attach-{type}/{id}

Remove Endpoints: DELETE {base_url}/e-social/posts/draft/remove-{type}/{id}

All return standard PostResponse structure. Success messages follow pattern: "{Type} attached/removed to/from draft successfully"


21. Update Draft Content Only

Purpose: Update only the text content of the current draft

Endpoint: PUT {base_url}/e-social/posts/content

Request Body: Plain text string (not JSON object)

Success Response: Returns standard PostResponse structure

Success Response Message: "Draft content updated successfully"


22. Update Draft Media Only

Purpose: Update only the media attachments of the current draft

Endpoint: PUT {base_url}/e-social/posts/media

Request Body: Array of MediaRequest objects

Success Response: Returns standard PostResponse structure

Success Response Message: "Media added to draft successfully"


23. Update Draft Privacy Settings Only

Purpose: Update only the privacy settings of the current draft

Endpoint: PUT {base_url}/e-social/posts/privacy

Request Body: PrivacySettingsRequest object

Success Response: Returns standard PostResponse structure

Success Response Message: "Privacy settings updated successfully"


24. Update Draft Collaboration

Purpose: Update collaborator invitations for the current draft

Endpoint: PUT {base_url}/e-social/posts/collaboration

Request Body: CollaborationRequest object with collaboratorIds array

Success Response: Returns standard PostResponse structure

Success Response Message: "Collaboration settings updated successfully"


25. Accept Collaboration

Purpose: Accept a collaboration invitation on a published post

Endpoint: POST {base_url}/e-social/posts/{postId}/collaboration/accept

Success Response: Returns standard PostResponse structure

Success Response Message: "Collaboration accepted successfully"


26. Decline Collaboration

Purpose: Decline a collaboration invitation on a published post

Endpoint: POST {base_url}/e-social/posts/{postId}/collaboration/decline

Success Response: Returns standard PostResponse structure

Success Response Message: "Collaboration declined successfully"


27. Remove Collaborator

Purpose: Remove a collaborator from a published post (author or self only)

Endpoint: DELETE {base_url}/e-social/posts/{postId}/collaborators/{collaboratorId}

Success Response Message: "Collaborator removed successfully"


28. Create Repost or Quote Post

Purpose: Repost or quote an existing post. The same endpoint handles both — the presence or absence of content determines which one is created.

Endpoint: POST {base_url}/e-social/posts/quote/{quotedPostId}

Access Level: 🔒 Protected (Requires Bearer Token Authentication)

Authentication: Bearer Token


Repost vs Quote — The Difference

Repost Quote Post
content in body empty / omitted your text
postKind in response REPOST QUOTE
Counter on original repostsCount + 1 quotesCount + 1
Has its own engagement No (shows original's counts) Yes (its own likes/comments)
Duplicate check Can't repost same post twice Can quote same post multiple times
Daily limit Yes (configurable) No separate limit

Repost (silent forward — no added text)

Request:

POST /e-social/posts/quote/aaa-111
Content-Type: application/json

{}

Body is empty — no content field means it's a pure repost.

What happens:

Response (postKind: REPOST):

{
  "id": "bbb-222",
  "postKind": "REPOST",
  "author": { "userName": "mbappe" },
  "content": null,
  "quotedPost": {
    "id": "aaa-111",
    "author": { "userName": "ronaldo" },
    "content": "Siuuu! 🔥",
    "status": "PUBLISHED"
  },
  "engagement": {
    "likesCount": 9001,
    "repostsCount": 1,
    "quotesCount": 1
  },
  "userInteraction": {
    "hasLiked": false,
    "hasReposted": true,
    "myRepostId": "bbb-222"
  }
}

Note: engagement and userInteraction on a repost always reflect the original post's data — not the repost itself. Likes, comments, views on the repost all flow through to the original.


Quote Post (repost with your own added comment)

Request:

POST /e-social/posts/quote/aaa-111
Content-Type: application/json

{
  "content": "Respect to the GOAT 🐐"
}

What happens:

Response (postKind: QUOTE):

{
  "id": "ccc-333",
  "postKind": "QUOTE",
  "author": { "userName": "messi" },
  "content": "Respect to the GOAT 🐐",
  "quotedPost": {
    "id": "aaa-111",
    "author": { "userName": "ronaldo" },
    "content": "Siuuu! 🔥",
    "status": "PUBLISHED"
  },
  "engagement": {
    "likesCount": 0,
    "repostsCount": 0,
    "quotesCount": 0
  },
  "userInteraction": {
    "hasLiked": false,
    "hasReposted": false,
    "myRepostId": null,
    "hasQuoted": true
  }
}

Undo a Repost

There is no dedicated "unrepost" endpoint. To undo a repost, the client reads userInteraction.myRepostId from the original post's response, then calls:

DELETE /e-social/posts/{myRepostId}

This soft-deletes the repost and decrements the original's repostsCount.

How the client knows the user has reposted:

When fetching any post, userInteraction includes:

"userInteraction": {
  "hasReposted": true,
  "myRepostId": "bbb-222"
}

If hasReposted = false, myRepostId is null.


Reposting a Repost (Chain Resolution)

If you try to repost a post that is itself a pure repost, the system automatically resolves to the original post and creates the new repost pointing directly to it.

Example:

This prevents empty chains and ensures:


When the Original Post is Deleted


Business Rules:

  1. Original post must be PUBLISHED
  2. Cannot repost the same post twice (duplicate check by author + quotedPostId)
  3. Daily limit applies to pure reposts (no-content) — configurable server-side
  4. Reposting a repost always resolves to the original (chain flattening)
  5. Privacy: original post's whoCanRepost setting is enforced
  6. Repost engagement (likes, comments, views) always routes to the original post
  7. Quote post engagement is independent — stays on the quote post

Path Parameters:

Parameter Type Required Description
quotedPostId UUID Yes ID of the post to repost or quote

Request Body Parameters:

Parameter Type Required Description
content string No Your added comment. Omit or leave empty for a pure repost.
privacySettings object No Privacy for the new repost/quote post

Success Response: Returns standard PostResponse with quotedPost populated and postKind set to REPOST or QUOTE.

Success Response Message: "Quote post created successfully"

Standard Error Types:


Interaction Endpoints (29-38)

29. Like Post

Purpose: Add a like to a post

Endpoint: POST {base_url}/e-social/posts/{postId}/like

Access Level: 🔒 Protected (Requires Bearer Token Authentication)

Authentication: Bearer Token

Behavior:

Business Rules:

  1. Visibility Check: User must have permission to view post based on privacy settings
  2. Blocking: Cannot like posts from blocked users or if author blocked you
  3. Deleted Posts: Cannot like deleted posts (isDeleted = true)
  4. Draft/Scheduled: Cannot like unpublished posts (must be PUBLISHED status)
  5. Idempotent: Multiple like attempts don't create duplicate likes
  6. Notification: Author receives notification (unless self-like)
  7. Counter Update: Post's engagement counter incremented atomically
  8. User State: User's interaction state updated for this post

Request Headers:

Header Type Required Description
Authorization string Yes Bearer token for authentication
Content-Type string Yes Must be application/json

Path Parameters:

Parameter Type Required Description Validation
postId string Yes UUID of the post to like Must be valid UUID format

Success Response JSON Sample:

{
  "success": true,
  "httpStatus": "OK",
  "message": "Post liked successfully",
  "action_time": "2025-12-11T10:30:45",
  "data": null
}

Standard Error Types:

Error Response Examples:

Cannot Like - Blocked User (403):

{
  "success": false,
  "httpStatus": "FORBIDDEN",
  "message": "Cannot like this post",
  "action_time": "2025-12-11T10:30:45",
  "data": "You cannot interact with posts from this user"
}

Post Not Found (404):

{
  "success": false,
  "httpStatus": "NOT_FOUND",
  "message": "Post not found",
  "action_time": "2025-12-11T10:30:45",
  "data": "Post with ID 550e8400-e29b-41d4-a716-446655440000 not found"
}

30. Unlike Post

Purpose: Remove a like from a post

Endpoint: DELETE {base_url}/e-social/posts/{postId}/like

Access Level: 🔒 Protected (Requires Bearer Token Authentication)

Authentication: Bearer Token

Behavior:

Business Rules:

  1. Silent Operation: No notification sent to post author
  2. Always Allowed: Can unlike even if blocked or post deleted (to clean up state)
  3. Idempotent: Multiple unlike attempts don't cause errors
  4. Counter Decrement: Post's engagement counter decremented atomically
  5. State Cleanup: User's interaction state updated

Request Headers:

Header Type Required Description
Authorization string Yes Bearer token for authentication
Content-Type string Yes Must be application/json

Path Parameters:

Parameter Type Required Description Validation
postId string Yes UUID of the post to unlike Must be valid UUID format

Success Response JSON Sample:

{
  "success": true,
  "httpStatus": "OK",
  "message": "Post unliked successfully",
  "action_time": "2025-12-11T10:30:45",
  "data": null
}

Standard Error Types:


31. Bookmark Post

Purpose: Save a post to bookmarks for later viewing

Endpoint: POST {base_url}/e-social/posts/{postId}/bookmark

Access Level: 🔒 Protected (Requires Bearer Token Authentication)

Authentication: Bearer Token

Behavior:

Business Rules:

  1. Private Action: Bookmarks are private, author doesn't get notified
  2. Visibility Required: Must have permission to view post based on privacy settings
  3. Persistent: Bookmarks persist even if post is deleted (for user's reference)
  4. Organization: Can be organized into collections (future feature)
  5. No Limit: Unlimited bookmarks allowed per user
  6. Idempotent: Multiple bookmark attempts don't create duplicates
  7. Counter Update: Post's engagement counter incremented
  8. Access Anytime: User can always access their bookmarked posts

Request Headers:

Header Type Required Description
Authorization string Yes Bearer token for authentication
Content-Type string Yes Must be application/json

Path Parameters:

Parameter Type Required Description Validation
postId string Yes UUID of the post to bookmark Must be valid UUID format

Success Response JSON Sample:

{
  "success": true,
  "httpStatus": "OK",
  "message": "Post bookmarked successfully",
  "action_time": "2025-12-11T10:30:45",
  "data": null
}

Standard Error Types:

Use Case Examples:

Example 1: Bookmark for Later Reading

POST /e-social/posts/550e8400-e29b-41d4-a716-446655440000/bookmark

User sees interesting post with products attached
Bookmarks to check products later
Result: Post saved to bookmarks, appears in GET /posts/bookmarks

Example 2: Bookmark Collaborative Post

POST /e-social/posts/660e8400-e29b-41d4-a716-446655440001/bookmark

Post has 3 collaborators
User bookmarks for reference
Result: Post bookmarked, visible in bookmarks even if one collaborator leaves

32. Unbookmark Post

Purpose: Remove a post from bookmarks

Endpoint: DELETE {base_url}/e-social/posts/{postId}/bookmark

Access Level: 🔒 Protected (Requires Bearer Token Authentication)

Authentication: Bearer Token

Behavior:

Business Rules:

  1. Silent Operation: No notification sent
  2. Always Allowed: Can unbookmark anytime, even if post deleted
  3. Idempotent: Multiple unbookmark attempts don't cause errors
  4. Counter Decrement: Post's engagement counter decremented

Request Headers:

Header Type Required Description
Authorization string Yes Bearer token for authentication
Content-Type string Yes Must be application/json

Path Parameters:

Parameter Type Required Description Validation
postId string Yes UUID of the post to unbookmark Must be valid UUID format

Success Response JSON Sample:

{
  "success": true,
  "httpStatus": "OK",
  "message": "Post unbookmarked successfully",
  "action_time": "2025-12-11T10:30:45",
  "data": null
}

Standard Error Types:


Use Case Examples:

Example 1: Simple Repost (No Comment)

POST /e-social/posts/550e8400-e29b-41d4-a716-446655440000/repost

Body: {} or no body

Result: Original post appears on user's profile with "reposted" badge
Appears in followers' feeds
Original author gets notification

Example 2: Quote Post (With Comment)

POST /e-social/posts/660e8400-e29b-41d4-a716-446655440001/repost

Body: {
  "comment": "This is exactly what I've been saying! Great insight 🎯"
}

Result: Creates new quote post with comment
Original post embedded in quote
New post has own likes/comments
Both posts' repost counters incremented

34. Undo Repost (Unrepost)

Purpose: Remove your repost. There is no dedicated unrepost endpoint — unreposting is done by deleting the repost post itself using myRepostId from the post's userInteraction.

How to undo a repost:

  1. Fetch the original post. The response contains:
"userInteraction": {
  "hasReposted": true,
  "myRepostId": "bbb-222"
}
  1. Call the standard delete endpoint with the repost's ID:

Endpoint: DELETE {base_url}/e-social/posts/{myRepostId}

Access Level: 🔒 Protected (Requires Bearer Token Authentication)

What happens:

Business Rules:

  1. Only the repost author can delete their own repost
  2. To remove a quote post (which has content), use the same DELETE /posts/{quotePostId} — this decrements quotesCount instead
  3. If original post is already deleted, the repost will have been auto-deleted by the cascade — nothing to undo

Success Response JSON Sample:

{
  "success": true,
  "httpStatus": "OK",
  "message": "Post deleted successfully",
  "action_time": "2025-12-11T10:30:45",
  "data": null
}

Standard Error Types:


35. Record View

Purpose: Track post views for analytics

Endpoint: POST {base_url}/e-social/posts/{postId}/view

Access Level: 🔒 Protected (Requires Bearer Token Authentication)

Authentication: Bearer Token

Behavior:

Business Rules:

  1. One View Per User: Each user counted only once regardless of repeat views
  2. Private Metric: View counts not shown publicly (author sees in analytics)
  3. No Notification: Viewing doesn't notify author
  4. Automatic Tracking: Frontend typically calls this when post visible for 2+ seconds
  5. Respects Visibility: Must have permission to view post
  6. Author Excluded: Author's own views don't count
  7. Idempotent: Multiple calls from same user don't inflate count

Request Headers:

Header Type Required Description
Authorization string Yes Bearer token for authentication
Content-Type string Yes Must be application/json

Path Parameters:

Parameter Type Required Description Validation
postId string Yes UUID of the post being viewed Must be valid UUID format

Success Response JSON Sample:

{
  "success": true,
  "httpStatus": "OK",
  "message": "View recorded successfully",
  "action_time": "2025-12-11T10:30:45",
  "data": null
}

Standard Error Types:


36. Get My Bookmarks

Purpose: Retrieve all posts bookmarked by current user

Endpoint: GET {base_url}/e-social/posts/bookmarks

Access Level: 🔒 Protected (Requires Bearer Token Authentication)

Authentication: Bearer Token

Behavior:

Business Rules:

  1. Personal Collection: Only user's own bookmarks visible
  2. Persists Deletions: Bookmarked posts remain accessible even if deleted
  3. Persists Blocking: Can view bookmarked posts even if author blocked
  4. Chronological: Sorted by bookmark time (newest first)
  5. Full Details: Each post includes complete information
  6. Pagination: Default 20 per page, max 100

Request Headers:

Header Type Required Description
Authorization string Yes Bearer token for authentication
Content-Type string Yes Must be application/json

Query Parameters:

Parameter Type Required Description Validation Default
page integer No Page number (1-indexed) Min: 1 1
size integer No Items per page Min: 1, Max: 100 20

Success Response JSON Sample:

{
  "success": true,
  "httpStatus": "OK",
  "message": "Bookmarks retrieved successfully",
  "action_time": "2025-12-11T10:30:45",
  "data": [
    {
      // Full PostResponse object
      "id": "550e8400-e29b-41d4-a716-446655440000",
      "content": "Bookmarked post content...",
      // ... rest of PostResponse
    },
    {
      // Another PostResponse object
    }
  ]
}

Standard Error Types:


37. Get My Reposts

Purpose: Retrieve all posts reposted by current user

Endpoint: GET {base_url}/e-social/posts/my-reposts

Access Level: 🔒 Protected (Requires Bearer Token Authentication)

Authentication: Bearer Token

Behavior:

Business Rules:

  1. Simple Reposts Only: Only shows direct reposts, not quote posts
  2. Quote Posts: Appear in regular "Get User Posts" endpoint as authored posts
  3. Current Visibility: If original post now private/deleted, it's excluded
  4. Chronological: Sorted by repost time (newest first)
  5. Full Details: Each post includes complete original information

Request Headers:

Header Type Required Description
Authorization string Yes Bearer token for authentication
Content-Type string Yes Must be application/json

Query Parameters:

Parameter Type Required Description Validation Default
page integer No Page number (1-indexed) Min: 1 1
size integer No Items per page Min: 1, Max: 100 20

Success Response JSON Sample:

{
  "success": true,
  "httpStatus": "OK",
  "message": "Reposts retrieved successfully",
  "action_time": "2025-12-11T10:30:45",
  "data": [
    {
      // Full PostResponse object of reposted post
      "id": "550e8400-e29b-41d4-a716-446655440000",
      "author": {
        // Original author info
      },
      "content": "Original post content...",
      // ... rest of PostResponse
    }
  ]
}

Standard Error Types:


38. Get User Reposts

Purpose: Retrieve all posts reposted by a specific user

Endpoint: GET {base_url}/e-social/posts/users/{userId}/reposts

Access Level: 🔒 Protected (Requires Bearer Token Authentication)

Authentication: Bearer Token

Behavior:

Business Rules:

  1. Simple Reposts Only: Only shows direct reposts, not quote posts
  2. Visibility Filtering: Only shows original posts requesting user can see
  3. Privacy Respected: Follows same visibility rules as original posts
  4. Blocking: Hidden if original author blocked requesting user
  5. Chronological: Sorted by repost time (newest first)

Request Headers:

Header Type Required Description
Authorization string Yes Bearer token for authentication
Content-Type string Yes Must be application/json

Path Parameters:

Parameter Type Required Description Validation
userId string Yes UUID of user whose reposts to retrieve Must be valid UUID format

Query Parameters:

Parameter Type Required Description Validation Default
page integer No Page number (1-indexed) Min: 1 1
size integer No Items per page Min: 1, Max: 100 20

Success Response JSON Sample:

{
  "success": true,
  "httpStatus": "OK",
  "message": "User reposts retrieved successfully",
  "action_time": "2025-12-11T10:30:45",
  "data": [
    {
      // Full PostResponse object of reposted post
      "id": "550e8400-e29b-41d4-a716-446655440000",
      "author": {
        // Original author info
      },
      "content": "Original post content...",
      // ... rest of PostResponse
    }
  ]
}

Standard Error Types:


Summary: All interaction endpoints return data: null except GET endpoints (36-38) which return paginated PostResponse arrays.


Poll Endpoints (39-42)

39. Vote on Poll

Purpose: Cast a vote on a poll post

Endpoint: POST {base_url}/e-social/posts/{postId}/vote

Access Level: 🔒 Protected (Requires Bearer Token Authentication)

Authentication: Bearer Token

Behavior:

Business Rules:

  1. Single vs Multiple: Respects poll's allowMultipleVotes setting
  2. Vote Changes: Allowed only if allowVoteChange is true
  3. Expiration: Cannot vote on expired polls
  4. Visibility: Must have access to view post
  5. Blocking: Cannot vote on polls from blocked users
  6. Option Validation: All optionIds must belong to this poll
  7. Single Vote Mode: If allowMultipleVotes false, only 1 optionId allowed
  8. Multiple Vote Mode: If allowMultipleVotes true, can select multiple options
  9. Anonymous: If isAnonymous true, voter identity hidden
  10. Non-Anonymous: If isAnonymous false, voter identity visible to post author

Request Headers:

Header Type Required Description
Authorization string Yes Bearer token for authentication
Content-Type string Yes Must be application/json

Path Parameters:

Parameter Type Required Description Validation
postId string Yes UUID of the poll post Must be valid UUID format

Request JSON Sample (Single Vote):

{
  "optionIds": ["option-uuid-1"]
}

Request JSON Sample (Multiple Votes):

{
  "optionIds": ["option-uuid-1", "option-uuid-2", "option-uuid-4"]
}

Request Body Parameters:

Parameter Type Required Description Validation
optionIds array Yes Array of poll option UUIDs Min: 1 option. If allowMultipleVotes false, max: 1. All IDs must belong to poll

Success Response JSON Sample:

{
  "success": true,
  "httpStatus": "OK",
  "message": "Vote recorded successfully",
  "action_time": "2025-12-11T10:30:45",
  "data": null
}

Standard Error Types:

Error Response Examples:

Poll Expired (400):

{
  "success": false,
  "httpStatus": "BAD_REQUEST",
  "message": "Cannot vote on poll",
  "action_time": "2025-12-11T10:30:45",
  "data": "This poll has expired and is no longer accepting votes"
}

Vote Change Not Allowed (400):

{
  "success": false,
  "httpStatus": "BAD_REQUEST",
  "message": "Cannot change vote",
  "action_time": "2025-12-11T10:30:45",
  "data": "You have already voted on this poll and vote changes are not allowed"
}

Too Many Options - Single Vote Mode (422):

{
  "success": false,
  "httpStatus": "UNPROCESSABLE_ENTITY",
  "message": "Validation failed",
  "action_time": "2025-12-11T10:30:45",
  "data": {
    "optionIds": "This poll allows only one vote. You selected 3 options."
  }
}

Invalid Option ID (404):

{
  "success": false,
  "httpStatus": "NOT_FOUND",
  "message": "Invalid poll option",
  "action_time": "2025-12-11T10:30:45",
  "data": "Option option-uuid-5 does not belong to this poll"
}

Use Case Examples:

Example 1: Single Vote Poll

POST /e-social/posts/550e8400-e29b-41d4-a716-446655440000/vote

Poll settings: allowMultipleVotes = false

Body: {
  "optionIds": ["option-uuid-2"]
}

Result: Vote recorded for option 2, totalVotes++, option vote count++

Example 2: Multiple Vote Poll

POST /e-social/posts/660e8400-e29b-41d4-a716-446655440001/vote

Poll settings: allowMultipleVotes = true

Body: {
  "optionIds": ["option-uuid-1", "option-uuid-3", "option-uuid-5"]
}

Result: Votes recorded for 3 options, totalVotes++, each option count++

Example 3: Change Vote (Allowed)

POST /e-social/posts/770e8400-e29b-41d4-a716-446655440002/vote

Poll settings: allowVoteChange = true
User already voted for option 1

Body: {
  "optionIds": ["option-uuid-4"]
}

Result: Previous vote removed, new vote recorded, counts updated

Example 4: Change Vote (Not Allowed)

POST /e-social/posts/880e8400-e29b-41d4-a716-446655440003/vote

Poll settings: allowVoteChange = false
User already voted

Body: {
  "optionIds": ["option-uuid-2"]
}

Result: Error 400 - Vote changes not allowed, original vote preserved

40. Remove Vote

Purpose: Remove your vote from a poll

Endpoint: DELETE {base_url}/e-social/posts/{postId}/vote

Access Level: 🔒 Protected (Requires Bearer Token Authentication)

Authentication: Bearer Token

Behavior:

Business Rules:

  1. Vote Change Required: Only works if allowVoteChange is true
  2. Complete Removal: Removes ALL votes (if multiple vote poll)
  3. Idempotent: Safe to call if not voted
  4. Expired Polls: Can remove votes even after expiration
  5. Counter Updates: All affected option counts decremented
  6. Silent Operation: No notification sent

Request Headers:

Header Type Required Description
Authorization string Yes Bearer token for authentication
Content-Type string Yes Must be application/json

Path Parameters:

Parameter Type Required Description Validation
postId string Yes UUID of the poll post Must be valid UUID format

Success Response JSON Sample:

{
  "success": true,
  "httpStatus": "OK",
  "message": "Vote removed successfully",
  "action_time": "2025-12-11T10:30:45",
  "data": null
}

Standard Error Types:

Error Response Examples:

Vote Removal Not Allowed (400):

{
  "success": false,
  "httpStatus": "BAD_REQUEST",
  "message": "Cannot remove vote",
  "action_time": "2025-12-11T10:30:45",
  "data": "This poll does not allow vote changes or removal"
}

Use Case Examples:

Example 1: Remove Single Vote

DELETE /e-social/posts/550e8400-e29b-41d4-a716-446655440000/vote

Poll settings: allowVoteChange = true
User voted for option 2

Result: Vote removed, option 2 count--, totalVotes--

Example 2: Remove Multiple Votes

DELETE /e-social/posts/660e8400-e29b-41d4-a716-446655440001/vote

Poll settings: allowMultipleVotes = true, allowVoteChange = true
User voted for options 1, 3, 5

Result: All 3 votes removed, all option counts--, totalVotes--

Example 3: Remove Vote - Not Allowed

DELETE /e-social/posts/770e8400-e29b-41d4-a716-446655440002/vote

Poll settings: allowVoteChange = false

Result: Error 400 - Vote removal not allowed, original vote preserved

41. Get Poll Results

Purpose: Get detailed poll results including vote counts and percentages

Endpoint: GET {base_url}/e-social/posts/{postId}/poll-results

Access Level: 🔒 Protected (Requires Bearer Token Authentication)

Authentication: Bearer Token

Behavior:

Business Rules:

  1. Visibility: Must have access to view parent post
  2. Real-Time: Results update immediately after each vote
  3. Percentages: Calculated as (optionVotes / totalVotes) × 100
  4. User State: Shows which options current user voted for
  5. Expiration Check: Indicates if poll has expired
  6. Zero Votes: Shows 0.0% for options with no votes
  7. Anonymous Respect: Voter identities hidden if isAnonymous true
  8. Public Results: Anyone who can view post can see results

Request Headers:

Header Type Required Description
Authorization string Yes Bearer token for authentication
Content-Type string Yes Must be application/json

Path Parameters:

Parameter Type Required Description Validation
postId string Yes UUID of the poll post Must be valid UUID format

Success Response JSON Sample:

{
  "success": true,
  "httpStatus": "OK",
  "message": "Poll results retrieved successfully",
  "action_time": "2025-12-11T10:30:45",
  "data": {
    "pollId": "poll-uuid",
    "title": "What's your favorite programming language?",
    "description": "Choose your top pick for backend development",
    "totalVotes": 150,
    "allowMultipleVotes": false,
    "isAnonymous": true,
    "allowVoteChange": true,
    "expiresAt": "2025-12-15T10:30:45",
    "hasExpired": false,
    "userHasVoted": true,
    "options": [
      {
        "optionId": "option-uuid-1",
        "optionText": "Python",
        "optionImageUrl": null,
        "optionOrder": 1,
        "votesCount": 75,
        "percentage": 50.0,
        "userVoted": true
      },
      {
        "optionId": "option-uuid-2",
        "optionText": "JavaScript",
        "optionImageUrl": null,
        "optionOrder": 2,
        "votesCount": 50,
        "percentage": 33.3,
        "userVoted": false
      },
      {
        "optionId": "option-uuid-3",
        "optionText": "Java",
        "optionImageUrl": null,
        "optionOrder": 3,
        "votesCount": 25,
        "percentage": 16.7,
        "userVoted": false
      }
    ]
  }
}

Response Fields Explained:

Field Type Description
pollId string UUID of the poll
title string Poll question/title
description string Additional poll description (optional)
totalVotes integer Total number of votes cast
allowMultipleVotes boolean Can users select multiple options
isAnonymous boolean Are voter identities hidden
allowVoteChange boolean Can users change their vote
expiresAt string Poll expiration datetime (ISO 8601, null if no expiration)
hasExpired boolean Whether poll has passed expiration time
userHasVoted boolean Has current user voted on this poll
options array Array of poll options with results
options[].optionId string UUID of this option
options[].optionText string Text for this option
options[].optionImageUrl string Optional image for this option (null if none)
options[].optionOrder integer Display order (1, 2, 3...)
options[].votesCount integer Number of votes for this option
options[].percentage number Percentage of total votes (0.0–100.0)
options[].userVoted boolean Did current user vote for this option

Success Response Message: "Poll results retrieved successfully"

Standard Error Types:

Use Case Examples:

Example 1: View Active Poll Results

GET /e-social/posts/550e8400-e29b-41d4-a716-446655440000/poll-results

Poll has 150 total votes, user voted for Python
Result: Returns all options with vote counts, percentages, user's vote highlighted

Example 2: View Expired Poll

GET /e-social/posts/660e8400-e29b-41d4-a716-446655440001/poll-results

Poll expired yesterday, hasExpired = true
Result: Results displayed, voting disabled, final counts shown

Example 3: View Poll Without Voting

GET /e-social/posts/770e8400-e29b-41d4-a716-446655440002/poll-results

User hasn't voted yet, userHasVoted = false
Result: All options shown with current results, all userVoted = false

42. Get Poll Voters (All Options)

Purpose: Get a paginated list of all unique users who voted on a poll, across all options

Endpoint: GET {base_url}/e-social/posts/{postId}/poll-voters

Access Level: 🔒 Protected (Requires Bearer Token Authentication)

Authentication: Bearer Token

Behavior:

Business Rules:

  1. Non-Anonymous Only: Returns error if isAnonymous = true
  2. Any Authenticated User: No author/collaborator restriction
  3. Secondary Onboarding Required: Caller must have username + profilePic set
  4. Deduplication: Users who voted on multiple options appear only once
  5. Follow Status: Response reflects the calling user's follow relationship with each voter
  6. Pagination: Default 5 voters per page, configurable via query params

Request Headers:

Header Type Required Description
Authorization string Yes Bearer token for authentication
Content-Type string Yes Must be application/json

Path Parameters:

Parameter Type Required Description Validation
postId string Yes UUID of the poll post Must be valid UUID format

Query Parameters:

Parameter Type Required Description Validation Default
page integer No Page number (1-indexed) Min: 1 1
size integer No Items per page Min: 1 5

Success Response JSON Sample:

{
  "success": true,
  "httpStatus": "OK",
  "message": "Poll voters retrieved successfully",
  "action_time": "2025-12-11T10:30:45",
  "data": {
    "voters": [
      {
        "userId": "123e4567-e89b-12d3-a456-426614174000",
        "displayName": "John Doe",
        "userName": "johndoe",
        "profileImageUrl": "https://cdn.nexgate.com/profiles/johndoe.jpg",
        "youFollow": true,
        "followsYou": false
      },
      {
        "userId": "987e6543-e21b-12d3-a456-426614174999",
        "displayName": "Jane Smith",
        "userName": "janesmith",
        "profileImageUrl": "https://cdn.nexgate.com/profiles/janesmith.jpg",
        "youFollow": false,
        "followsYou": true
      }
    ],
    "totalElements": 42,
    "totalPages": 9,
    "hasNext": true,
    "hasPrevious": false,
    "isFirst": true,
    "isLast": false,
    "currentPage": 1
  }
}

Response Fields Explained:

Field Type Description
voters array Paginated list of unique voters across all poll options
voters[].userId string UUID of the voter
voters[].displayName string Voter's full display name
voters[].userName string Voter's unique username
voters[].profileImageUrl string URL to voter's profile picture
voters[].youFollow boolean Whether the calling user follows this voter
voters[].followsYou boolean Whether this voter follows the calling user
totalElements integer Total number of unique voters across all pages
totalPages integer Total number of pages
hasNext boolean Whether a next page exists
hasPrevious boolean Whether a previous page exists
isFirst boolean Whether this is the first page
isLast boolean Whether this is the last page
currentPage integer Current page number (1-indexed)

Success Response Message: "Poll voters retrieved successfully"

Standard Error Types:

Error Response Examples:

Anonymous Poll (400):

{
  "success": false,
  "httpStatus": "BAD_REQUEST",
  "message": "Voters not available",
  "action_time": "2025-12-11T10:30:45",
  "data": "This is an anonymous poll. Voter identities are hidden."
}

Secondary Onboarding Incomplete (403):

{
  "success": false,
  "httpStatus": "FORBIDDEN",
  "message": "Profile incomplete",
  "action_time": "2025-12-11T10:30:45",
  "data": "Please complete your profile setup (username and profile picture) to access this feature."
}

Use Case Examples:

Example 1: View All Voters — First Page

GET /e-social/posts/550e8400-e29b-41d4-a716-446655440000/poll-voters

Poll is non-anonymous, 42 unique voters across all options
Result: Returns first 5 voters with follow relationship context

Example 2: Custom Page Size

GET /e-social/posts/550e8400-e29b-41d4-a716-446655440000/poll-voters?page=2&size=10

Result: Returns voters 11–20

Example 3: Anonymous Poll

GET /e-social/posts/770e8400-e29b-41d4-a716-446655440002/poll-voters

Poll has isAnonymous = true
Result: Error 400 — Voter identities hidden for anonymous polls

Example 4: User Voted on Multiple Options (Deduplication)

GET /e-social/posts/880e8400-e29b-41d4-a716-446655440003/poll-voters

User voted on 3 options in a multiple-vote poll
Result: User appears only once in the deduplicated voter list

43. Get Poll Voters by Option

Purpose: Get list of users who voted for a specific poll option (post author/collaborators only, non-anonymous polls only)

Endpoint: GET {base_url}/e-social/posts/{postId}/poll-voters/{optionId}

Access Level: 🔒 Protected (Requires Bearer Token Authentication + Post Author/Collaborator)

Authentication: Bearer Token

Behavior:

Business Rules:

  1. Non-Anonymous Only: Only works if isAnonymous = false
  2. Author/Collaborator Access: Only post author and collaborators can view
  3. Privacy Protection: Regular users cannot see who voted per option
  4. Vote Time: Includes when each user voted
  5. Profile Info: Returns basic user profile (name, photo, verified status)
  6. Pagination: Default 50 voters per page
  7. Current Votes: Shows current votes (if user changed vote, shows new choice)

Request Headers:

Header Type Required Description
Authorization string Yes Bearer token for authentication
Content-Type string Yes Must be application/json

Path Parameters:

Parameter Type Required Description Validation
postId string Yes UUID of the poll post Must be valid UUID format
optionId string Yes UUID of the poll option Must belong to this poll

Query Parameters:

Parameter Type Required Description Validation Default
page integer No Page number (1-indexed) Min: 1 1
size integer No Items per page Min: 1, Max: 100 50

Success Response JSON Sample:

{
  "success": true,
  "httpStatus": "OK",
  "message": "Voters retrieved successfully",
  "action_time": "2025-12-11T10:30:45",
  "data": {
    "pollId": "poll-uuid",
    "pollTitle": "What's your favorite programming language?",
    "optionId": "option-uuid-1",
    "optionText": "Python",
    "totalVoters": 75,
    "voters": [
      {
        "userId": "123e4567-e89b-12d3-a456-426614174000",
        "userName": "john_doe",
        "firstName": "John",
        "lastName": "Doe",
        "profilePictureUrl": "https://cdn.nexgate.com/profiles/john_doe.jpg",
        "isVerified": true,
        "votedAt": "2025-12-11T10:25:30"
      },
      {
        "userId": "987e6543-e21b-12d3-a456-426614174999",
        "userName": "jane_smith",
        "firstName": "Jane",
        "lastName": "Smith",
        "profilePictureUrl": "https://cdn.nexgate.com/profiles/jane_smith.jpg",
        "isVerified": false,
        "votedAt": "2025-12-11T10:20:15"
      }
    ],
    "pagination": {
      "currentPage": 1,
      "pageSize": 50,
      "totalPages": 2,
      "totalElements": 75,
      "hasNext": true,
      "hasPrevious": false
    }
  }
}

Response Fields Explained:

Field Type Description
pollId string UUID of the poll
pollTitle string Poll question/title
optionId string UUID of the queried option
optionText string Text of the queried option
totalVoters integer Total voters for this specific option
voters array Paginated list of users who voted for this option
voters[].userId string UUID of the voter
voters[].userName string Voter's unique username
voters[].firstName string Voter's first name
voters[].lastName string Voter's last name
voters[].profilePictureUrl string URL to voter's profile picture
voters[].isVerified boolean Whether voter's account is verified
voters[].votedAt string ISO 8601 datetime when this user voted
pagination.currentPage integer Current page number (1-indexed)
pagination.pageSize integer Number of items per page
pagination.totalPages integer Total number of pages
pagination.totalElements integer Total voters for this option
pagination.hasNext boolean Whether a next page exists
pagination.hasPrevious boolean Whether a previous page exists

Success Response Message: "Voters retrieved successfully"

Standard Error Types:

Error Response Examples:

Anonymous Poll (400):

{
  "success": false,
  "httpStatus": "BAD_REQUEST",
  "message": "Voters not available",
  "action_time": "2025-12-11T10:30:45",
  "data": "This is an anonymous poll. Voter identities are hidden."
}

Not Post Author or Collaborator (403):

{
  "success": false,
  "httpStatus": "FORBIDDEN",
  "message": "Access denied",
  "action_time": "2025-12-11T10:30:45",
  "data": "Only the post author and collaborators can view voter lists"
}

Use Case Examples:

Example 1: View Voters for a Specific Option as Post Author

GET /e-social/posts/550e8400-e29b-41d4-a716-446655440000/poll-voters/option-uuid-1

User is post author
Poll is non-anonymous, option has 75 voters

Result: Returns paginated list of users who voted for this specific option

Example 2: View Voters as Collaborator

GET /e-social/posts/660e8400-e29b-41d4-a716-446655440001/poll-voters/option-uuid-2

User is accepted collaborator
Poll is non-anonymous

Result: Returns voter list (collaborators have same access as author)

Example 3: Anonymous Poll — Access Denied

GET /e-social/posts/770e8400-e29b-41d4-a716-446655440002/poll-voters/option-uuid-3

User is post author
Poll is anonymous (isAnonymous = true)

Result: Error 400 — Voter identities hidden for anonymous polls

Example 4: Regular User — Access Denied

GET /e-social/posts/880e8400-e29b-41d4-a716-446655440003/poll-voters/option-uuid-1

User is neither author nor collaborator
Poll is non-anonymous

Result: Error 403 — Only author/collaborators can view voters per option

Comment Endpoints (43-52)

43. Create Comment

Purpose: Create a comment or reply on a post

Endpoint: POST {base_url}/e-social/posts/{postId}/comments

Access Level: 🔒 Protected (Requires Bearer Token Authentication)

Authentication: Bearer Token

Behavior:

Business Rules:

  1. Permission Check: Post must allow comments (whoCanComment setting)
  2. Visibility Check: Must have permission to view post to comment
  3. Blocking: Cannot comment on posts from blocked users
  4. Nesting: Supports unlimited reply depth (replies to replies to replies...)
  5. Mentions: All @mentioned users notified
  6. Notification: Post author and parent comment author notified
  7. Content Length: Min 1, Max 2000 characters
  8. Spam Prevention: Rate limited (max 10 comments per minute per user)
  9. Edit Window: Can edit within 15 minutes of posting
  10. Deleted Posts: Cannot comment on deleted posts

Request Headers:

Header Type Required Description
Authorization string Yes Bearer token for authentication
Content-Type string Yes Must be application/json

Path Parameters:

Parameter Type Required Description Validation
postId string Yes UUID of the post to comment on Must be valid UUID format

Request JSON Sample (Top-level Comment):

{
  "content": "Great post! @john_doe you should check this out",
  "parentCommentId": null
}

Request JSON Sample (Nested Reply):

{
  "content": "I completely agree with you @jane_doe! 💯",
  "parentCommentId": "660e8400-e29b-41d4-a716-446655440001"
}

Request Body Parameters:

Parameter Type Required Description Validation
content string Yes Comment text Min: 1, Max: 2000 characters
parentCommentId string No UUID of parent comment for replies Must be valid UUID if provided, must belong to same post

Success Response: Returns CommentResponse object

CommentResponse Structure:

{
  "id": "770e8400-e29b-41d4-a716-446655440001",
  "postId": "550e8400-e29b-41d4-a716-446655440000",
  "author": {
    "id": "123e4567-e89b-12d3-a456-426614174000",
    "userName": "john_doe",
    "firstName": "John",
    "lastName": "Doe",
    "profilePictureUrl": "https://cdn.nexgate.com/profiles/john_doe.jpg",
    "isVerified": true
  },
  "content": "Great post! @john_doe you should check this out",
  "contentParsed": {
    "text": "Great post! @john_doe you should check this out",
    "entities": [
      {
        "type": "MENTION",
        "text": "@john_doe",
        "startIndex": 12,
        "endIndex": 21,
        "user": {
          "id": "987e6543-e21b-12d3-a456-426614174999",
          "userName": "john_doe"
        }
      }
    ]
  },
  "parentCommentId": null,
  "replyCount": 5,
  "likesCount": 12,
  "isPinned": false,
  "isEdited": false,
  "userInteraction": {
    "hasLiked": false
  },
  "createdAt": "2025-12-11T10:30:45",
  "updatedAt": null
}

Success Response Message: "Comment created successfully"

Standard Error Types:

Error Response Examples:

Comments Disabled (403):

{
  "success": false,
  "httpStatus": "FORBIDDEN",
  "message": "Cannot comment on this post",
  "action_time": "2025-12-11T10:30:45",
  "data": "The author has disabled comments for this post"
}

Comments Followers Only (403):

{
  "success": false,
  "httpStatus": "FORBIDDEN",
  "message": "Cannot comment on this post",
  "action_time": "2025-12-11T10:30:45",
  "data": "Only followers can comment on this post. Follow the author to comment."
}

Invalid Parent Comment (400):

{
  "success": false,
  "httpStatus": "BAD_REQUEST",
  "message": "Invalid parent comment",
  "action_time": "2025-12-11T10:30:45",
  "data": "Parent comment does not belong to this post"
}

Rate Limit Exceeded (429):

{
  "success": false,
  "httpStatus": "TOO_MANY_REQUESTS",
  "message": "Too many comments",
  "action_time": "2025-12-11T10:30:45",
  "data": "Maximum 10 comments per minute. Please wait 30 seconds."
}

Use Case Examples:

Example 1: Top-Level Comment

POST /e-social/posts/550e8400-e29b-41d4-a716-446655440000/comments

Body: {
  "content": "This is exactly what I needed! Thank you 🙏",
  "parentCommentId": null
}

Result: Top-level comment created, post author notified, commentsCount++

Example 2: Reply to Comment

POST /e-social/posts/550e8400-e29b-41d4-a716-446655440000/comments

Body: {
  "content": "Glad you found it helpful! @jane_doe",
  "parentCommentId": "660e8400-e29b-41d4-a716-446655440001"
}

Result: Nested reply created, parent comment author + @jane_doe notified

Example 3: Nested Reply (Reply to Reply)

POST /e-social/posts/550e8400-e29b-41d4-a716-446655440000/comments

Body: {
  "content": "Same here! Following this thread 👀",
  "parentCommentId": "770e8400-e29b-41d4-a716-446655440002"
}

Result: 2nd-level nested reply created, forms conversation thread

44. Get Comments

Purpose: Retrieve all top-level comments for a post (paginated)

Endpoint: GET {base_url}/e-social/posts/{postId}/comments

Access Level: 🔒 Protected (Requires Bearer Token Authentication)

Authentication: Bearer Token

Behavior:

Business Rules:

  1. Top-Level Only: Returns only direct comments on post, not replies
  2. Pinned Priority: Pinned comments always appear first
  3. Sorting: After pinned, sorted by newest first
  4. Reply Count: Each comment shows number of replies
  5. Pagination: Default 20 per page, max 100
  6. Visibility: Same visibility rules as viewing the post

Request Headers:

Header Type Required Description
Authorization string Yes Bearer token for authentication
Content-Type string Yes Must be application/json

Path Parameters:

Parameter Type Required Description Validation
postId string Yes UUID of the post Must be valid UUID format

Query Parameters:

Parameter Type Required Description Validation Default
page integer No Page number (1-indexed) Min: 1 1
size integer No Items per page Min: 1, Max: 100 20

Success Response: Returns array of CommentResponse objects

Success Response Message: "Comments retrieved successfully"

Standard Error Types:


45. Get Comment

Purpose: Retrieve a single comment by ID with full details

Endpoint: GET {base_url}/e-social/posts/comments/{commentId}

Access Level: 🔒 Protected (Requires Bearer Token Authentication)

Authentication: Bearer Token

Behavior:

Business Rules:

  1. Visibility: Must be able to view parent post
  2. Deleted: Returns 404 if comment deleted
  3. Full Details: Includes all engagement metrics
  4. Context: Can get comment without knowing postId

Request Headers:

Header Type Required Description
Authorization string Yes Bearer token for authentication
Content-Type string Yes Must be application/json

Path Parameters:

Parameter Type Required Description Validation
commentId string Yes UUID of the comment Must be valid UUID format

Success Response: Returns CommentResponse object

Success Response Message: "Comment retrieved successfully"

Standard Error Types:


46. Get Replies

Purpose: Retrieve all replies to a specific comment (nested comments)

Endpoint: GET {base_url}/e-social/posts/comments/{commentId}/replies

Access Level: 🔒 Protected (Requires Bearer Token Authentication)

Authentication: Bearer Token

Behavior:

Business Rules:

  1. Direct Replies Only: Returns immediate children, not grandchildren
  2. Conversation Order: Sorted oldest first (chronological conversation)
  3. Nested Support: Each reply shows its own replyCount
  4. Recursive Loading: Frontend loads nested replies on-demand
  5. Pagination: Default 50 per page (comments usually have fewer replies)

Request Headers:

Header Type Required Description
Authorization string Yes Bearer token for authentication
Content-Type string Yes Must be application/json

Path Parameters:

Parameter Type Required Description Validation
commentId string Yes UUID of parent comment Must be valid UUID format

Query Parameters:

Parameter Type Required Description Validation Default
page integer No Page number (1-indexed) Min: 1 1
size integer No Items per page Min: 1, Max: 100 50

Success Response: Returns array of CommentResponse objects

Success Response Message: "Replies retrieved successfully"

Standard Error Types:


47. Update Comment

Purpose: Edit an existing comment's content

Endpoint: PUT {base_url}/e-social/posts/comments/{commentId}

Access Level: 🔒 Protected (Requires Bearer Token Authentication)

Authentication: Bearer Token

Behavior:

Business Rules:

  1. Author Only: Only comment author can edit
  2. Time Window: Can only edit within 15 minutes of creation
  3. Edit Flag: isEdited set to true (visible to users)
  4. Content Validation: Same rules as creation (1-2000 chars)
  5. Mention Updates: New mentions trigger notifications
  6. No History: Only current version stored (no edit history)

Request Headers:

Header Type Required Description
Authorization string Yes Bearer token for authentication
Content-Type string Yes Must be application/json

Path Parameters:

Parameter Type Required Description Validation
commentId string Yes UUID of comment to edit Must be valid UUID format

Request JSON Sample:

{
  "content": "Updated comment with correction! @new_user check this"
}

Request Body Parameters:

Parameter Type Required Description Validation
content string Yes Updated comment text Min: 1, Max: 2000 characters

Success Response: Returns updated CommentResponse object with isEdited = true

Success Response Message: "Comment updated successfully"

Standard Error Types:

Error Response Examples:

Edit Window Expired (400):

{
  "success": false,
  "httpStatus": "BAD_REQUEST",
  "message": "Cannot edit comment",
  "action_time": "2025-12-11T10:30:45",
  "data": "Comments can only be edited within 15 minutes of posting"
}

Not Comment Author (403):

{
  "success": false,
  "httpStatus": "FORBIDDEN",
  "message": "Cannot edit comment",
  "action_time": "2025-12-11T10:30:45",
  "data": "Only the comment author can edit this comment"
}

48. Delete Comment

Purpose: Soft delete a comment (marks as deleted, preserves data)

Endpoint: DELETE {base_url}/e-social/posts/comments/{commentId}

Access Level: 🔒 Protected (Requires Bearer Token Authentication)

Authentication: Bearer Token

Behavior:

Business Rules:

  1. Who Can Delete: Comment author OR post author
  2. Soft Delete: Data retained in database
  3. Replies Preserved: Child replies remain visible
  4. Parent Reference: Replies show "[deleted]" as parent content
  5. Counter Update: Post's comment count decremented
  6. Cascade Option: Post author can cascade delete all replies (optional)
  7. Silent Operation: No notifications sent

Request Headers:

Header Type Required Description
Authorization string Yes Bearer token for authentication
Content-Type string Yes Must be application/json

Path Parameters:

Parameter Type Required Description Validation
commentId string Yes UUID of comment to delete Must be valid UUID format

Success Response JSON Sample:

{
  "success": true,
  "httpStatus": "OK",
  "message": "Comment deleted successfully",
  "action_time": "2025-12-11T10:30:45",
  "data": null
}

Standard Error Types:

Use Case Examples:

Example 1: Author Deletes Own Comment

DELETE /e-social/posts/comments/770e8400-e29b-41d4-a716-446655440001

User is comment author
Comment has 3 replies
Result: Comment deleted, replies preserved, show "[deleted]" as parent

Example 2: Post Author Deletes Inappropriate Comment

DELETE /e-social/posts/comments/880e8400-e29b-41d4-a716-446655440002

User is post author (not comment author)
Comment violates community guidelines
Result: Comment deleted by post author, content moderation applied

49. Pin Comment

Purpose: Pin a comment to the top of post's comment section (post author only)

Endpoint: POST {base_url}/e-social/posts/{postId}/comments/{commentId}/pin

Access Level: 🔒 Protected (Requires Bearer Token Authentication)

Authentication: Bearer Token

Behavior:

Business Rules:

  1. Post Author Only: Only post author/collaborators can pin
  2. Single Pin: Only 1 comment pinned at a time
  3. Auto-Unpin: Pinning new comment unpins previous
  4. Top-Level Only: Can only pin top-level comments (not replies)
  5. Notification: Comment author notified of pin
  6. Visibility: Pinned indicator shown to all users

Request Headers:

Header Type Required Description
Authorization string Yes Bearer token for authentication
Content-Type string Yes Must be application/json

Path Parameters:

Parameter Type Required Description Validation
postId string Yes UUID of the post Must be valid UUID format
commentId string Yes UUID of comment to pin Must be valid UUID, must be top-level comment

Success Response JSON Sample:

{
  "success": true,
  "httpStatus": "OK",
  "message": "Comment pinned successfully",
  "action_time": "2025-12-11T10:30:45",
  "data": null
}

Standard Error Types:

Error Response Examples:

Cannot Pin Reply (400):

{
  "success": false,
  "httpStatus": "BAD_REQUEST",
  "message": "Cannot pin reply",
  "action_time": "2025-12-11T10:30:45",
  "data": "Only top-level comments can be pinned. Replies cannot be pinned."
}

Use Case Examples:

Example 1: Pin Important Comment

POST /e-social/posts/550e8400-e29b-41d4-a716-446655440000/comments/770e8400-e29b-41d4-a716-446655440001/pin

Post author pins helpful comment
Result: Comment appears at top, comment author notified, isPinned = true

Example 2: Pin New Comment (Auto-Unpins Previous)

POST /e-social/posts/550e8400-e29b-41d4-a716-446655440000/comments/880e8400-e29b-41d4-a716-446655440002/pin

Already have pinned comment
Result: Previous comment unpinned automatically, new comment pinned

50. Unpin Comment

Purpose: Remove pin from a comment

Endpoint: DELETE {base_url}/e-social/posts/comments/{commentId}/pin

Access Level: 🔒 Protected (Requires Bearer Token Authentication)

Authentication: Bearer Token

Behavior:

Business Rules:

  1. Post Author Only: Only post author/collaborators can unpin
  2. Silent Operation: No notification sent
  3. Idempotent: Safe to call on non-pinned comments
  4. Sort Restoration: Comment returns to chronological position

Request Headers:

Header Type Required Description
Authorization string Yes Bearer token for authentication
Content-Type string Yes Must be application/json

Path Parameters:

Parameter Type Required Description Validation
commentId string Yes UUID of comment to unpin Must be valid UUID format

Success Response JSON Sample:

{
  "success": true,
  "httpStatus": "OK",
  "message": "Comment unpinned successfully",
  "action_time": "2025-12-11T10:30:45",
  "data": null
}

Standard Error Types:


51. Like Comment

Purpose: Add a like to a comment

Endpoint: POST {base_url}/e-social/posts/comments/{commentId}/like

Access Level: 🔒 Protected (Requires Bearer Token Authentication)

Authentication: Bearer Token

Behavior:

Business Rules:

  1. Visibility: Must have access to parent post
  2. Blocking: Cannot like comments from blocked users
  3. Deleted: Cannot like deleted comments
  4. Idempotent: Safe to call multiple times
  5. Notification: Comment author notified (unless self-like)
  6. Counter Update: Atomic increment

Request Headers:

Header Type Required Description
Authorization string Yes Bearer token for authentication
Content-Type string Yes Must be application/json

Path Parameters:

Parameter Type Required Description Validation
commentId string Yes UUID of comment to like Must be valid UUID format

Success Response JSON Sample:

{
  "success": true,
  "httpStatus": "OK",
  "message": "Comment liked successfully",
  "action_time": "2025-12-11T10:30:45",
  "data": null
}

Standard Error Types:


52. Unlike Comment

Purpose: Remove a like from a comment

Endpoint: DELETE {base_url}/e-social/posts/comments/{commentId}/like

Access Level: 🔒 Protected (Requires Bearer Token Authentication)

Authentication: Bearer Token

Behavior:

Business Rules:

  1. Silent Operation: No notification sent
  2. Always Allowed: Can unlike even if blocked or comment deleted
  3. Idempotent: Safe to call multiple times
  4. Counter Decrement: Atomic decrement

Request Headers:

Header Type Required Description
Authorization string Yes Bearer token for authentication
Content-Type string Yes Must be application/json

Path Parameters:

Parameter Type Required Description Validation
commentId string Yes UUID of comment to unlike Must be valid UUID format

Success Response JSON Sample:

{
  "success": true,
  "httpStatus": "OK",
  "message": "Comment unliked successfully",
  "action_time": "2025-12-11T10:30:45",
  "data": null
}

Standard Error Types:


53. Share Post

Purpose: Record a post share action and track which platform was used for sharing

Endpoint: POST {base_url}/api/v1/e-social/posts/{postId}/share

Access Level: 🔒 Protected (Requires Authentication)

Authentication: Bearer Token

Request Headers:

Header Type Required Description
Authorization string Yes Bearer token for authentication

Path Parameters:

Parameter Type Required Description Validation
postId UUID Yes Unique identifier of the post to share Valid UUID format

Query Parameters:

Parameter Type Required Description Validation Default
platform string No Platform where the post is being shared Enum: WHATSAPP, TWITTER, FACEBOOK, INSTAGRAM, TELEGRAM, COPY_LINK, OTHER , IN_APP OTHER

Success Response JSON Sample:

{
  "success": true,
  "httpStatus": "OK",
  "message": "Post shared successfully",
  "action_time": "2025-12-29T14:30:45",
  "data": null
}

Success Response Fields:

Field Description
success Indicates if the share was recorded successfully
message Confirmation message

Error Response JSON Samples:

Post Not Found:

{
  "success": false,
  "httpStatus": "BAD_REQUEST",
  "message": "Post not found",
  "action_time": "2025-12-29T14:30:45",
  "data": null
}

Post Not Published:

{
  "success": false,
  "httpStatus": "BAD_REQUEST",
  "message": "Can only share published posts",
  "action_time": "2025-12-29T14:30:45",
  "data": null
}

Unauthorized:

{
  "success": false,
  "httpStatus": "UNAUTHORIZED",
  "message": "User not authenticated",
  "action_time": "2025-12-29T14:30:45",
  "data": null
}

Standard Error Types:

Share Platform Values:

Platform Description
WHATSAPP Shared via WhatsApp
TWITTER Shared via Twitter/X
FACEBOOK Shared via Facebook
INSTAGRAM Shared via Instagram
TELEGRAM Shared via Telegram
COPY_LINK User copied the post link
OTHER Shared via other means or unspecified

Usage Notes:

Usage Examples:

# Share post to WhatsApp
curl -X POST "{base_url}/api/v1/e-social/posts/550e8400-e29b-41d4-a716-446655440000/share?platform=WHATSAPP" \
  -H "Authorization: Bearer {token}"

# Share post to Twitter
curl -X POST "{base_url}/api/v1/e-social/posts/550e8400-e29b-41d4-a716-446655440000/share?platform=TWITTER" \
  -H "Authorization: Bearer {token}"

# Record copy link action
curl -X POST "{base_url}/api/v1/e-social/posts/550e8400-e29b-41d4-a716-446655440000/share?platform=COPY_LINK" \
  -H "Authorization: Bearer {token}"

# Generic share (defaults to OTHER)
curl -X POST "{base_url}/api/v1/e-social/posts/550e8400-e29b-41d4-a716-446655440000/share" \
  -H "Authorization: Bearer {token}"

Response in Post Object:

After sharing, the post's engagement and user interaction data will reflect the share:

{
  "engagement": {
    "likesCount": 42,
    "commentsCount": 15,
    "repostsCount": 8,
    "quotesCount": 3,
    "bookmarksCount": 12,
    "sharesCount": 25,
    "viewsCount": 1500,
    "canLike": true,
    "canComment": true,
    "canRepost": true,
    "canShare": true
  },
  "userInteraction": {
    "hasLiked": true,
    "hasBookmarked": false,
    "hasReposted": false,
    "hasCommented": true,
    "hasViewed": true,
    "hasShared": true
  }
}

54. Report Post

Purpose: Report a post for violating community guidelines or platform rules

Endpoint: POST {base_url}/api/v1/e-social/posts/{postId}/report

Access Level: 🔒 Protected (Requires Authentication)

Authentication: Bearer Token

Request Headers:

Header Type Required Description
Authorization string Yes Bearer token for authentication

Path Parameters:

Parameter Type Required Description Validation
postId UUID Yes Unique identifier of the post to report Valid UUID format

Request JSON Sample:

{
  "reason": "HATE_SPEECH",
  "description": "This post contains discriminatory language targeting a specific group."
}

Request Body Parameters:

Parameter Type Required Description Validation
reason string Yes Reason for reporting Enum: SPAM, MISLEADING_INFO, FALSE_INFORMATION, HATE_SPEECH, HARASSMENT, BULLYING, THREATS, NUDITY, SEXUAL_CONTENT, VIOLENCE, GRAPHIC_CONTENT, ILLEGAL_GOODS, FRAUD, SCAM, INTELLECTUAL_PROPERTY, SELF_HARM, SUICIDE, PRIVACY_VIOLATION, PERSONAL_INFO_EXPOSED, IMPERSONATION, FAKE_ACCOUNT, UNDERAGE_USER, OTHER
description string No Additional details about the report Max 1000 characters

Success Response JSON Sample:

{
  "success": true,
  "httpStatus": "OK",
  "message": "Post reported successfully",
  "action_time": "2025-12-29T15:30:45",
  "data": null
}

Success Response Fields:

Field Description
success Indicates if the report was submitted successfully
message Confirmation message

Error Response JSON Sample:

{
  "success": false,
  "httpStatus": "BAD_REQUEST",
  "message": "You have already reported this post",
  "action_time": "2025-12-29T15:30:45",
  "data": null
}

Standard Error Types:


55. Get Post Reports (Admin)

Purpose: Retrieve all reports for a specific post (Admin only)

Endpoint: GET {base_url}/api/v1/e-social/posts/{postId}/reports

Access Level: 🔒 Protected (Admin Only)

Authentication: Bearer Token (Admin role required)

Request Headers:

Header Type Required Description
Authorization string Yes Bearer token for admin authentication

Path Parameters:

Parameter Type Required Description Validation
postId UUID Yes Unique identifier of the post Valid UUID format

Query Parameters:

Parameter Type Required Description Validation Default
page integer No Page number for pagination Min: 1 1
size integer No Number of results per page Min: 1, Max: 100 20

Success Response JSON Sample:

{
  "success": true,
  "httpStatus": "OK",
  "message": "Post reports retrieved successfully",
  "action_time": "2025-12-29T15:30:45",
  "data": {
    "content": [
      {
        "id": "550e8400-e29b-41d4-a716-446655440000",
        "postId": "660e8400-e29b-41d4-a716-446655440001",
        "reporter": {
          "id": "770e8400-e29b-41d4-a716-446655440002",
          "userName": "john_doe",
          "firstName": "John",
          "lastName": "Doe",
          "profilePictureUrl": "https://storage.example.com/profiles/john.jpg"
        },
        "postAuthor": {
          "id": "880e8400-e29b-41d4-a716-446655440003",
          "userName": "jane_smith",
          "firstName": "Jane",
          "lastName": "Smith",
          "profilePictureUrl": "https://storage.example.com/profiles/jane.jpg"
        },
        "reason": "HATE_SPEECH",
        "description": "This post contains discriminatory language",
        "status": "PENDING",
        "review": null,
        "createdAt": "2025-12-29T14:00:00",
        "updatedAt": "2025-12-29T14:00:00"
      },
      {
        "id": "550e8400-e29b-41d4-a716-446655440099",
        "postId": "660e8400-e29b-41d4-a716-446655440001",
        "reporter": {
          "id": "990e8400-e29b-41d4-a716-446655440004",
          "userName": "alex_wilson",
          "firstName": "Alex",
          "lastName": "Wilson",
          "profilePictureUrl": null
        },
        "postAuthor": {
          "id": "880e8400-e29b-41d4-a716-446655440003",
          "userName": "jane_smith",
          "firstName": "Jane",
          "lastName": "Smith",
          "profilePictureUrl": "https://storage.example.com/profiles/jane.jpg"
        },
        "reason": "HARASSMENT",
        "description": "Targeted harassment in the comments",
        "status": "ACTION_TAKEN",
        "review": {
          "reviewedBy": "aa0e8400-e29b-41d4-a716-446655440005",
          "reviewerName": "Admin User",
          "reviewedAt": "2025-12-29T15:00:00",
          "adminNotes": "Verified harassment, post removed",
          "actionTaken": "POST_REMOVED"
        },
        "createdAt": "2025-12-29T13:00:00",
        "updatedAt": "2025-12-29T15:00:00"
      }
    ],
    "pageable": {
      "pageNumber": 0,
      "pageSize": 20,
      "sort": {
        "empty": true,
        "sorted": false,
        "unsorted": true
      },
      "offset": 0,
      "paged": true,
      "unpaged": false
    },
    "last": true,
    "totalPages": 1,
    "totalElements": 2,
    "first": true,
    "size": 20,
    "number": 0,
    "numberOfElements": 2,
    "empty": false
  }
}

Success Response Fields:

Field Description
content Array of report objects for the post
content[].id Unique identifier of the report
content[].postId ID of the reported post
content[].reporter Information about the user who filed the report
content[].postAuthor Information about the post author
content[].reason Reason for the report
content[].description Additional details provided by reporter
content[].status Current status of the report
content[].review Review information if report has been reviewed
totalElements Total number of reports for this post

Error Response JSON Sample:

{
  "success": false,
  "httpStatus": "FORBIDDEN",
  "message": "Access denied",
  "action_time": "2025-12-29T15:30:45",
  "data": null
}

Standard Error Types:


56. Get All Reports (Admin)

Purpose: Retrieve all reports with optional filters for status, reason, and date range (Admin only)

Endpoint: GET {base_url}/api/v1/e-social/posts/reports

Access Level: 🔒 Protected (Admin Only)

Authentication: Bearer Token (Admin role required)

Request Headers:

Header Type Required Description
Authorization string Yes Bearer token for admin authentication

Query Parameters:

Parameter Type Required Description Validation Default
status string No Filter by report status Enum: PENDING, UNDER_REVIEW, ACTION_TAKEN, DISMISSED, ESCALATED null (all)
reason string No Filter by report reason Enum: SPAM, MISLEADING_INFO, FALSE_INFORMATION, HATE_SPEECH, HARASSMENT, BULLYING, THREATS, NUDITY, SEXUAL_CONTENT, VIOLENCE, GRAPHIC_CONTENT, ILLEGAL_GOODS, FRAUD, SCAM, INTELLECTUAL_PROPERTY, SELF_HARM, SUICIDE, PRIVACY_VIOLATION, PERSONAL_INFO_EXPOSED, IMPERSONATION, FAKE_ACCOUNT, UNDERAGE_USER, OTHER null (all)
startDate datetime No Filter reports created after this date ISO 8601 format null
endDate datetime No Filter reports created before this date ISO 8601 format null
page integer No Page number for pagination Min: 1 1
size integer No Number of results per page Min: 1, Max: 100 20

Success Response JSON Sample:

{
  "success": true,
  "httpStatus": "OK",
  "message": "Reports retrieved successfully",
  "action_time": "2025-12-29T15:30:45",
  "data": {
    "content": [
      {
        "id": "550e8400-e29b-41d4-a716-446655440000",
        "postId": "660e8400-e29b-41d4-a716-446655440001",
        "reporter": {
          "id": "770e8400-e29b-41d4-a716-446655440002",
          "userName": "john_doe",
          "firstName": "John",
          "lastName": "Doe",
          "profilePictureUrl": "https://storage.example.com/profiles/john.jpg"
        },
        "postAuthor": {
          "id": "880e8400-e29b-41d4-a716-446655440003",
          "userName": "jane_smith",
          "firstName": "Jane",
          "lastName": "Smith",
          "profilePictureUrl": "https://storage.example.com/profiles/jane.jpg"
        },
        "reason": "SPAM",
        "description": "This account is posting spam content repeatedly",
        "status": "PENDING",
        "review": null,
        "createdAt": "2025-12-29T14:00:00",
        "updatedAt": "2025-12-29T14:00:00"
      }
    ],
    "pageable": {
      "pageNumber": 0,
      "pageSize": 20,
      "sort": {
        "empty": true,
        "sorted": false,
        "unsorted": true
      },
      "offset": 0,
      "paged": true,
      "unpaged": false
    },
    "last": true,
    "totalPages": 1,
    "totalElements": 1,
    "first": true,
    "size": 20,
    "number": 0,
    "numberOfElements": 1,
    "empty": false
  }
}

Success Response Fields:

Field Description
content Array of report objects matching the filters
content[].id Unique identifier of the report
content[].postId ID of the reported post
content[].reporter Information about the user who filed the report
content[].postAuthor Information about the post author
content[].reason Reason for the report
content[].status Current status: PENDING, UNDER_REVIEW, ACTION_TAKEN, DISMISSED, ESCALATED
totalElements Total number of matching reports
totalPages Total number of pages

Error Response JSON Sample:

{
  "success": false,
  "httpStatus": "FORBIDDEN",
  "message": "Access denied",
  "action_time": "2025-12-29T15:30:45",
  "data": null
}

Standard Error Types:


57. Review Report (Admin)

Purpose: Review and update the status of a report (Admin only)

Endpoint: PATCH {base_url}/api/v1/e-social/posts/reports/{reportId}/review

Access Level: 🔒 Protected (Admin Only)

Authentication: Bearer Token (Admin role required)

Request Headers:

Header Type Required Description
Authorization string Yes Bearer token for admin authentication

Path Parameters:

Parameter Type Required Description Validation
reportId UUID Yes Unique identifier of the report Valid UUID format

Request JSON Sample:

{
  "status": "ACTION_TAKEN",
  "adminNotes": "Verified hate speech violation. Post has been removed and user warned.",
  "actionTaken": "POST_REMOVED_USER_WARNED"
}

Request Body Parameters:

Parameter Type Required Description Validation
status string Yes New status for the report Enum: PENDING, UNDER_REVIEW, ACTION_TAKEN, DISMISSED, ESCALATED
adminNotes string No Internal notes about the review Max 500 characters
actionTaken string No Description of action taken Max 50 characters

Success Response JSON Sample:

{
  "success": true,
  "httpStatus": "OK",
  "message": "Report reviewed successfully",
  "action_time": "2025-12-29T16:00:00",
  "data": {
    "id": "550e8400-e29b-41d4-a716-446655440000",
    "postId": "660e8400-e29b-41d4-a716-446655440001",
    "reporter": {
      "id": "770e8400-e29b-41d4-a716-446655440002",
      "userName": "john_doe",
      "firstName": "John",
      "lastName": "Doe",
      "profilePictureUrl": "https://storage.example.com/profiles/john.jpg"
    },
    "postAuthor": {
      "id": "880e8400-e29b-41d4-a716-446655440003",
      "userName": "jane_smith",
      "firstName": "Jane",
      "lastName": "Smith",
      "profilePictureUrl": "https://storage.example.com/profiles/jane.jpg"
    },
    "reason": "HATE_SPEECH",
    "description": "This post contains discriminatory language",
    "status": "ACTION_TAKEN",
    "review": {
      "reviewedBy": "aa0e8400-e29b-41d4-a716-446655440005",
      "reviewerName": "Admin User",
      "reviewedAt": "2025-12-29T16:00:00",
      "adminNotes": "Verified hate speech violation. Post has been removed and user warned.",
      "actionTaken": "POST_REMOVED_USER_WARNED"
    },
    "createdAt": "2025-12-29T14:00:00",
    "updatedAt": "2025-12-29T16:00:00"
  }
}

Success Response Fields:

Field Description
id Unique identifier of the report
postId ID of the reported post
reporter Information about the user who filed the report
postAuthor Information about the post author
reason Reason for the report
status Updated status of the report
review Review details including reviewer info, notes, and action taken
review.reviewedBy UUID of the admin who reviewed
review.reviewerName Name of the admin who reviewed
review.reviewedAt Timestamp of the review
review.adminNotes Internal notes from the admin
review.actionTaken Action taken on the report

Error Response JSON Sample:

{
  "success": false,
  "httpStatus": "BAD_REQUEST",
  "message": "Report not found",
  "action_time": "2025-12-29T16:00:00",
  "data": null
}

Standard Error Types:


58. Get Report Statistics (Admin)

Purpose: Retrieve aggregate statistics about reports (Admin only)

Endpoint: GET {base_url}/api/v1/e-social/posts/reports/stats

Access Level: 🔒 Protected (Admin Only)

Authentication: Bearer Token (Admin role required)

Request Headers:

Header Type Required Description
Authorization string Yes Bearer token for admin authentication

Success Response JSON Sample:

{
  "success": true,
  "httpStatus": "OK",
  "message": "Report statistics retrieved successfully",
  "action_time": "2025-12-29T16:30:00",
  "data": {
    "totalReports": 1250,
    "pendingReports": 45,
    "underReviewReports": 12,
    "actionTakenReports": 890,
    "dismissedReports": 298,
    "escalatedReports": 5,
    "reportsByReason": {
      "SPAM": 320,
      "HATE_SPEECH": 180,
      "HARASSMENT": 150,
      "MISLEADING_INFO": 120,
      "NUDITY": 95,
      "VIOLENCE": 85,
      "SCAM": 75,
      "FALSE_INFORMATION": 60,
      "BULLYING": 55,
      "SEXUAL_CONTENT": 40,
      "PRIVACY_VIOLATION": 30,
      "IMPERSONATION": 20,
      "OTHER": 20
    }
  }
}

Success Response Fields:

Field Description
totalReports Total number of reports in the system
pendingReports Number of reports awaiting review
underReviewReports Number of reports currently being reviewed
actionTakenReports Number of reports where action was taken
dismissedReports Number of reports that were dismissed
escalatedReports Number of reports escalated for further review
reportsByReason Object containing count of reports grouped by reason

Error Response JSON Sample:

{
  "success": false,
  "httpStatus": "FORBIDDEN",
  "message": "Access denied",
  "action_time": "2025-12-29T16:30:00",
  "data": null
}

Standard Error Types:

59. Edit Published Post

Purpose: Edit a published post within the 60-minute edit window (max 3 edits)

Endpoint: PUT {base_url}/e-social/posts/{postId}/edit

Access Level: 🔒 Protected (Post owner only)

Authentication: Bearer Token

Request Headers:

Header Type Required Description
Authorization string Yes Bearer token for authentication

Path Parameters:

Parameter Type Required Description Validation
postId UUID Yes ID of the post to edit Must be valid UUID, post must exist

Request JSON Sample (Regular/Quote Post):

{
  "content": "Updated post content! 🔥",
  "media": [
    {
      "mediaType": "IMAGE",
      "mediaUrl": "https://cdn.nexgate.it/new-image.jpg",
      "placeholderBase64": "data:image/jpeg;base64,/9j/4AAQ...",
      "width": 1080,
      "height": 1080
    }
  ],
  "attachments": {
    "productIds": ["550e8400-e29b-41d4-a716-446655440001"],
    "shopIds": ["550e8400-e29b-41d4-a716-446655440002"],
    "eventIds": [],
    "buyTogetherGroupIds": null,
    "installmentPlanIds": null,
    "externalLink": {
      "url": "https://example.com/new-link"
    },
    "removeExternalLink": false
  },
  "collaboration": {
    "collaboratorIds": ["550e8400-e29b-41d4-a716-446655440003"]
  },
  "privacySettings": {
    "visibility": "PUBLIC",
    "whoCanComment": "FOLLOWERS",
    "whoCanRepost": "EVERYONE",
    "hideLikesCount": false,
    "hideCommentsCount": false
  }
}

Request JSON Sample (Poll Post - Limited Fields):

{
  "content": "Updated poll question context",
  "pollTitle": "Updated Poll Title",
  "pollDescription": "Updated poll description",
  "privacySettings": {
    "visibility": "PUBLIC",
    "whoCanComment": "EVERYONE"
  }
}

Request Body Parameters:

Parameter Type Required Description Validation
content string No Updated post text content Max: 5000 characters
media array No Updated media attachments Max: 10 items
media[].mediaType string Yes* Type of media enum: IMAGE, VIDEO, GIF
media[].mediaUrl string Yes* URL to media file Valid URL
media[].placeholderBase64 string No BlurHash placeholder Base64 encoded
media[].width integer No Media width in pixels Min: 1
media[].height integer No Media height in pixels Min: 1
media[].duration integer No Video duration in seconds Min: 1 (videos only)
attachments object No Updated attachments See attachment behavior below
attachments.productIds array No Product IDs to attach null=no change, []=remove all
attachments.shopIds array No Shop IDs to attach null=no change, []=remove all
attachments.eventIds array No Event IDs to attach null=no change, []=remove all
attachments.buyTogetherGroupIds array No Buy Together Group IDs null=no change, []=remove all
attachments.installmentPlanIds array No Installment Plan IDs null=no change, []=remove all
attachments.externalLink object No External link to attach null=no change
attachments.externalLink.url string Yes* URL of external link Valid URL
attachments.removeExternalLink boolean No Remove existing external link Default: false
collaboration object No Updated collaboration settings
collaboration.collaboratorIds array No User IDs to invite as collaborators Valid user UUIDs
privacySettings object No Updated privacy settings
privacySettings.visibility string No Post visibility enum: PUBLIC, FOLLOWERS, MENTIONED, PRIVATE
privacySettings.whoCanComment string No Comment permissions enum: EVERYONE, FOLLOWERS, MENTIONED, DISABLED
privacySettings.whoCanRepost string No Repost permissions enum: EVERYONE, FOLLOWERS, DISABLED
privacySettings.hideLikesCount boolean No Hide likes count Default: false
privacySettings.hideCommentsCount boolean No Hide comments count Default: false
pollTitle string No Poll title (poll posts only) Max: 200 characters
pollDescription string No Poll description (poll posts only) Max: 1000 characters

Attachment Edit Behavior:

Field Value Behavior
null No change to that attachment type
[] (empty array) Remove all attachments of that type
[ids...] Replace with new attachment IDs

Collaboration Edit Behavior:

Collaborator Status Behavior
ACCEPTED Preserved (cannot be removed via edit)
PENDING Can be removed
DECLINED Can be removed
New IDs Added as PENDING status

Poll Post Restrictions:

Field Can Edit
content ✅ Yes
pollTitle ✅ Yes
pollDescription ✅ Yes
privacySettings ✅ Yes
Poll options ❌ No (would invalidate votes)
media ❌ No
attachments ❌ No

Success Response JSON Sample:

{
  "success": true,
  "httpStatus": "OK",
  "message": "Post edited successfully",
  "action_time": "2025-01-03T10:30:45",
  "data": {
    "id": "550e8400-e29b-41d4-a716-446655440000",
    "author": {
      "id": "660e8400-e29b-41d4-a716-446655440000",
      "userName": "johndoe",
      "displayName": "John Doe",
      "profileImage": "https://cdn.nexgate.it/profiles/johndoe.jpg",
      "isVerified": true
    },
    "content": "Updated post content! 🔥",
    "postType": "REGULAR",
    "status": "PUBLISHED",
    "editInfo": {
      "isEdited": true,
      "editCount": 1,
      "canEdit": true,
      "lastEditedAt": "2025-01-03T10:30:45"
    },
    "createdAt": "2025-01-03T10:00:00",
    "publishedAt": "2025-01-03T10:00:00"
  }
}

Success Response Fields:

Field Description
id Post UUID
author Post author details
content Updated post content
postType Type of post (REGULAR, POLL, QUOTE, REPOST)
status Post status (always PUBLISHED for edited posts)
editInfo.isEdited Whether post has been edited
editInfo.editCount Number of times post has been edited
editInfo.canEdit Whether current user can still edit
editInfo.lastEditedAt Timestamp of last edit

Error Response Examples:

Not Post Owner (400):

{
  "success": false,
  "httpStatus": "BAD_REQUEST",
  "message": "You can only edit your own posts",
  "action_time": "2025-01-03T10:30:45",
  "data": "You can only edit your own posts"
}

Edit Limit Reached (400):

{
  "success": false,
  "httpStatus": "BAD_REQUEST",
  "message": "Maximum edit limit reached. You can only edit a post 3 times.",
  "action_time": "2025-01-03T10:30:45",
  "data": "Maximum edit limit reached. You can only edit a post 3 times."
}

Edit Window Expired (400):

{
  "success": false,
  "httpStatus": "BAD_REQUEST",
  "message": "Edit window has expired. Posts can only be edited within 60 minutes of publishing.",
  "action_time": "2025-01-03T10:30:45",
  "data": "Edit window has expired. Posts can only be edited within 60 minutes of publishing."
}

Post Not Published (400):

{
  "success": false,
  "httpStatus": "BAD_REQUEST",
  "message": "Only published posts can be edited",
  "action_time": "2025-01-03T10:30:45",
  "data": "Only published posts can be edited"
}

Post Not Found (404):

{
  "success": false,
  "httpStatus": "NOT_FOUND",
  "message": "Post not found",
  "action_time": "2025-01-03T10:30:45",
  "data": "Post not found"
}

Unauthorized (401):

{
  "success": false,
  "httpStatus": "UNAUTHORIZED",
  "message": "Token has expired",
  "action_time": "2025-01-03T10:30:45",
  "data": "Token has expired"
}

60. Get Post Edit Info

Purpose: Get detailed edit status and eligibility information for a post

Endpoint: GET {base_url}/e-social/posts/{postId}/edit-info

Access Level: 🔒 Protected

Authentication: Bearer Token

Request Headers:

Header Type Required Description
Authorization string Yes Bearer token for authentication

Path Parameters:

Parameter Type Required Description Validation
postId UUID Yes ID of the post Must be valid UUID, post must exist

Success Response JSON Sample:

{
  "success": true,
  "httpStatus": "OK",
  "message": "Post edit info retrieved successfully",
  "action_time": "2025-01-03T10:30:45",
  "data": {
    "postId": "550e8400-e29b-41d4-a716-446655440000",
    "isEdited": true,
    "editCount": 2,
    "maxEdits": 3,
    "remainingEdits": 1,
    "canEdit": true,
    "cannotEditReason": null,
    "publishedAt": "2025-01-03T10:00:00",
    "editWindowExpiresAt": "2025-01-03T11:00:00",
    "lastEditedAt": "2025-01-03T10:30:00",
    "minutesRemainingInWindow": 25
  }
}

Success Response Fields:

Field Description
postId Post UUID
isEdited Whether post has been edited at least once
editCount Number of times post has been edited (0-3)
maxEdits Maximum allowed edits (always 3)
remainingEdits Edits remaining (maxEdits - editCount)
canEdit Whether current user can edit this post now
cannotEditReason Reason why editing is not allowed (null if canEdit is true)
publishedAt When the post was originally published
editWindowExpiresAt When the 60-minute edit window expires
lastEditedAt Timestamp of most recent edit (null if never edited)
minutesRemainingInWindow Minutes left in edit window (0 if expired)

Cannot Edit Reasons:

Reason Description
"Authentication required" User not logged in
"Only the author can edit this post" Current user is not the post owner
"Only published posts can be edited" Post is in DRAFT or SCHEDULED status
"Maximum edit limit reached (3 edits)" All 3 edits have been used
"Edit window expired (60 minutes after publishing)" More than 60 minutes since publishing

Error Response Examples:

Post Not Found (404):

{
  "success": false,
  "httpStatus": "NOT_FOUND",
  "message": "Post not found",
  "action_time": "2025-01-03T10:30:45",
  "data": "Post not found"
}

61. Get Post Edit History

Purpose: View complete edit history with immutable snapshots of each version

Endpoint: GET {base_url}/e-social/posts/{postId}/edit-history

Access Level: 🌐 Public (Anyone can view edit history of public posts)

Authentication: Bearer Token (Optional - required for non-public posts)

Request Headers:

Header Type Required Description
Authorization string No Bearer token for accessing non-public posts

Path Parameters:

Parameter Type Required Description Validation
postId UUID Yes ID of the post Must be valid UUID, post must exist

Success Response JSON Sample:

{
  "success": true,
  "httpStatus": "OK",
  "message": "Post edit history retrieved successfully",
  "action_time": "2025-01-03T10:45:00",
  "data": {
    "postId": "550e8400-e29b-41d4-a716-446655440000",
    "totalEdits": 2,
    "remainingEdits": 1,
    "canStillEdit": true,
    "editWindowExpiresAt": "2025-01-03T11:00:00",
    "versions": [
      {
        "id": "770e8400-e29b-41d4-a716-446655440001",
        "version": 0,
        "snapshot": {
          "content": "Original post content",
          "media": [
            {
              "id": "m1",
              "mediaType": "IMAGE",
              "originalUrl": "https://cdn.nexgate.it/original.jpg",
              "placeholderBase64": "data:image/jpeg;base64,...",
              "width": 1080,
              "height": 1080
            }
          ],
          "attachments": {
            "productIds": ["550e8400-e29b-41d4-a716-446655440111"],
            "shopIds": [],
            "eventIds": [],
            "buyTogetherGroupIds": [],
            "installmentPlanIds": [],
            "externalLink": null
          },
          "collaboratorIds": [],
          "privacySettings": {
            "visibility": "PUBLIC",
            "whoCanComment": "EVERYONE",
            "whoCanRepost": "EVERYONE",
            "hideLikesCount": false,
            "hideCommentsCount": false
          },
          "pollTitle": null,
          "pollDescription": null
        },
        "editedAt": "2025-01-03T10:15:00",
        "isCurrent": false
      },
      {
        "id": "770e8400-e29b-41d4-a716-446655440002",
        "version": 1,
        "snapshot": {
          "content": "First edit - added more details!",
          "media": [
            {
              "id": "m1",
              "mediaType": "IMAGE",
              "originalUrl": "https://cdn.nexgate.it/original.jpg"
            },
            {
              "id": "m2",
              "mediaType": "IMAGE",
              "originalUrl": "https://cdn.nexgate.it/new-image.jpg"
            }
          ],
          "attachments": {
            "productIds": ["550e8400-e29b-41d4-a716-446655440111", "550e8400-e29b-41d4-a716-446655440222"],
            "shopIds": ["550e8400-e29b-41d4-a716-446655440333"],
            "eventIds": [],
            "buyTogetherGroupIds": [],
            "installmentPlanIds": [],
            "externalLink": {
              "url": "https://example.com",
              "shortCode": "abc123",
              "domain": "example.com"
            }
          },
          "collaboratorIds": ["550e8400-e29b-41d4-a716-446655440444"],
          "privacySettings": {
            "visibility": "PUBLIC",
            "whoCanComment": "FOLLOWERS",
            "whoCanRepost": "EVERYONE",
            "hideLikesCount": false,
            "hideCommentsCount": false
          },
          "pollTitle": null,
          "pollDescription": null
        },
        "editedAt": "2025-01-03T10:30:00",
        "isCurrent": false
      },
      {
        "id": null,
        "version": 2,
        "snapshot": {
          "content": "Current version - final updates! 🔥",
          "media": [],
          "attachments": {
            "productIds": [],
            "shopIds": [],
            "eventIds": [],
            "buyTogetherGroupIds": [],
            "installmentPlanIds": [],
            "externalLink": null
          },
          "collaboratorIds": [],
          "privacySettings": {
            "visibility": "PUBLIC",
            "whoCanComment": "EVERYONE",
            "whoCanRepost": "EVERYONE",
            "hideLikesCount": false,
            "hideCommentsCount": false
          },
          "pollTitle": null,
          "pollDescription": null
        },
        "editedAt": "2025-01-03T10:45:00",
        "isCurrent": true
      }
    ]
  }
}

Success Response Fields:

Field Description
postId Post UUID
totalEdits Total number of edits made
remainingEdits Edits still available (3 - totalEdits)
canStillEdit Whether post can still be edited
editWindowExpiresAt When edit window expires
versions Array of all versions (original + edits + current)
versions[].id History record UUID (null for current version)
versions[].version Version number (0 = original, N = after Nth edit)
versions[].snapshot Complete immutable state at that version
versions[].snapshot.content Post content at that version
versions[].snapshot.media Media attachments at that version
versions[].snapshot.attachments All attachments at that version
versions[].snapshot.collaboratorIds Collaborator IDs at that version
versions[].snapshot.privacySettings Privacy settings at that version
versions[].snapshot.pollTitle Poll title (null for non-poll posts)
versions[].snapshot.pollDescription Poll description (null for non-poll posts)
versions[].editedAt Timestamp of this version
versions[].isCurrent Whether this is the current live version

Version Numbering:

Version Meaning
0 Original published state
1 State after 1st edit
2 State after 2nd edit
3 State after 3rd edit (final)

Error Response Examples:

Post Not Found (404):

{
  "success": false,
  "httpStatus": "NOT_FOUND",
  "message": "Post not found",
  "action_time": "2025-01-03T10:30:45",
  "data": "Post not found"
}

62. Check Post Edit Eligibility

Purpose: Quick boolean check if current user can edit a post

Endpoint: GET {base_url}/e-social/posts/{postId}/can-edit

Access Level: 🔒 Protected

Authentication: Bearer Token

Request Headers:

Header Type Required Description
Authorization string Yes Bearer token for authentication

Path Parameters:

Parameter Type Required Description Validation
postId UUID Yes ID of the post Must be valid UUID

Success Response JSON Sample:

{
  "success": true,
  "httpStatus": "OK",
  "message": "Edit eligibility checked",
  "action_time": "2025-01-03T10:30:45",
  "data": {
    "canEdit": true
  }
}

Success Response Fields:

Field Description
canEdit true if user can edit, false otherwise

Eligibility Checks Performed:

Check Must Be
Post exists Yes
User is post owner Yes
Post status PUBLISHED
Edit count Less than 3
Time since publish Less than 60 minutes

Use Case: Frontend can call this endpoint before showing the edit button to avoid displaying unnecessary UI elements.

Error Response Examples:

Post Not Found (returns canEdit: false):

{
  "success": true,
  "httpStatus": "OK",
  "message": "Edit eligibility checked",
  "action_time": "2025-01-03T10:30:45",
  "data": {
    "canEdit": false
  }
}

Unauthorized (401):

{
  "success": false,
  "httpStatus": "UNAUTHORIZED",
  "message": "Token has expired",
  "action_time": "2025-01-03T10:30:45",
  "data": "Token has expired"
}

63. Get Post Likers

Purpose: Retrieve a paginated list of users who liked a specific post. Authenticated viewers see people they follow prioritized at the top (Twitter-style). Returns social context flags (followsYou, youFollow) for each user.

Endpoint: GET {base_url}/e-social/posts/{postId}/likers

Access Level: 🌐 Public (social context requires authentication)

Authentication: Bearer Token (optional — enhances response with follow-priority ordering and social flags)

Request Headers:

Header Type Required Description
Authorization string No Bearer token — enables follow-priority ordering and followsYou/youFollow flags

Path Parameters:

Parameter Type Required Description Validation
postId UUID Yes ID of the post Must be valid UUID

Query Parameters:

Parameter Type Required Default Description
page int No 1 Page number (1-indexed)
size int No 20 Items per page

Success Response JSON Sample:

{
  "success": true,
  "httpStatus": "OK",
  "message": "Post likers retrieved successfully",
  "action_time": "2025-01-03T10:30:45",
  "data": {
    "items": [
      {
        "userId": "550e8400-e29b-41d4-a716-446655440000",
        "userName": "john_doe",
        "firstName": "John",
        "lastName": "Doe",
        "profilePictureUrls": ["https://cdn.example.com/photos/john.jpg"],
        "isVerified": true,
        "actedAt": "2025-01-03T09:15:00",
        "followsYou": true,
        "youFollow": true
      },
      {
        "userId": "660e8400-e29b-41d4-a716-446655440001",
        "userName": "juma_ali",
        "firstName": "Juma",
        "lastName": "Ali",
        "profilePictureUrls": [],
        "isVerified": false,
        "actedAt": "2025-01-03T08:45:00",
        "followsYou": false,
        "youFollow": true
      }
    ],
    "totalElements": 142,
    "totalPages": 8,
    "hasNext": true,
    "hasPrevious": false,
    "isFirst": true,
    "isLast": false,
    "page": 1
  }
}

Success Response Fields:

Field Description
items Array of users who liked the post
items[].userId Unique identifier of the liker
items[].userName Username handle
items[].firstName First name
items[].lastName Last name
items[].profilePictureUrls List of profile picture URLs (empty if none set)
items[].isVerified Whether the user has a verified badge
items[].actedAt Timestamp when the user liked the post
items[].followsYou true if this user follows the viewer; null when unauthenticated
items[].youFollow true if the viewer follows this user; null when unauthenticated
totalElements Total number of likes on this post
totalPages Total number of pages
hasNext Whether a next page exists
hasPrevious Whether a previous page exists
isFirst Whether this is the first page
isLast Whether this is the last page
page Current page number (1-indexed)

Ordering Behavior:

Viewer State Ordering
Authenticated Users the viewer follows appear first, then by most recent like
Unauthenticated Most recent likes first

Error Response Examples:

Post Not Found (404):

{
  "success": false,
  "httpStatus": "NOT_FOUND",
  "message": "Post not found",
  "action_time": "2025-01-03T10:30:45",
  "data": "Post not found"
}

Use Case: Power a "Liked by" bottom sheet or modal. The post card previews this as "John, Juma + 140 others liked this" using topLikers in PostResponse; tapping that label opens this paginated endpoint.


64. Get Post Reposters

Purpose: Retrieve a paginated list of users who reposted a specific post. A repost is a quote post with no added text content. Authenticated viewers see people they follow prioritized at the top. Returns social context flags for each user.

Endpoint: GET {base_url}/e-social/posts/{postId}/reposters

Access Level: 🌐 Public (social context requires authentication)

Authentication: Bearer Token (optional — enhances response with follow-priority ordering and social flags)

Request Headers:

Header Type Required Description
Authorization string No Bearer token — enables follow-priority ordering and followsYou/youFollow flags

Path Parameters:

Parameter Type Required Description Validation
postId UUID Yes ID of the post being reposted Must be valid UUID

Query Parameters:

Parameter Type Required Default Description
page int No 1 Page number (1-indexed)
size int No 20 Items per page

Success Response JSON Sample:

{
  "success": true,
  "httpStatus": "OK",
  "message": "Post reposters retrieved successfully",
  "action_time": "2025-01-03T10:30:45",
  "data": {
    "items": [
      {
        "userId": "550e8400-e29b-41d4-a716-446655440000",
        "userName": "josh_kamau",
        "firstName": "Josh",
        "lastName": "Kamau",
        "profilePictureUrls": ["https://cdn.example.com/photos/josh.jpg"],
        "isVerified": false,
        "actedAt": "2025-01-03T11:20:00",
        "followsYou": false,
        "youFollow": true
      },
      {
        "userId": "770e8400-e29b-41d4-a716-446655440002",
        "userName": "janeth_m",
        "firstName": "Janeth",
        "lastName": "Mwangi",
        "profilePictureUrls": [],
        "isVerified": true,
        "actedAt": "2025-01-03T10:55:00",
        "followsYou": true,
        "youFollow": false
      }
    ],
    "totalElements": 38,
    "totalPages": 2,
    "hasNext": true,
    "hasPrevious": false,
    "isFirst": true,
    "isLast": false,
    "page": 1
  }
}

Success Response Fields:

Field Description
items Array of users who reposted the post
items[].userId Unique identifier of the reposter
items[].userName Username handle
items[].firstName First name
items[].lastName Last name
items[].profilePictureUrls List of profile picture URLs (empty if none set)
items[].isVerified Whether the user has a verified badge
items[].actedAt Timestamp when the user reposted (quote post creation time)
items[].followsYou true if this user follows the viewer; null when unauthenticated
items[].youFollow true if the viewer follows this user; null when unauthenticated
totalElements Total number of reposts on this post
totalPages Total number of pages
hasNext Whether a next page exists
hasPrevious Whether a previous page exists
isFirst Whether this is the first page
isLast Whether this is the last page
page Current page number (1-indexed)

What Counts as a Repost: A repost is a quote post where content is null or blank. Quote posts with text content are not included here — they appear in the Quotes endpoint (65) instead. Users are rate-limited to 10 reposts per day.

Ordering Behavior:

Viewer State Ordering
Authenticated Users the viewer follows appear first, then by most recent repost
Unauthenticated Most recent reposts first

Error Response Examples:

Post Not Found (404):

{
  "success": false,
  "httpStatus": "NOT_FOUND",
  "message": "Post not found",
  "action_time": "2025-01-03T10:30:45",
  "data": "Post not found"
}

Use Case: Power a "Reposted by" bottom sheet. The post card previews this as "Josh, Janeth reshared this post" using topReposters in PostResponse; tapping that label opens this paginated endpoint.


65. Get Post Quotes

Purpose: Retrieve a paginated list of quote posts — posts that reference this post and include added text commentary. Authenticated viewers see people they follow prioritized at the top. Each item includes the quoter's text so the viewer can read the added commentary inline.

Endpoint: GET {base_url}/e-social/posts/{postId}/quotes

Access Level: 🌐 Public (social context requires authentication)

Authentication: Bearer Token (optional — enhances response with follow-priority ordering and social flags)

Request Headers:

Header Type Required Description
Authorization string No Bearer token — enables follow-priority ordering and followsYou/youFollow flags

Path Parameters:

Parameter Type Required Description Validation
postId UUID Yes ID of the original post being quoted Must be valid UUID

Query Parameters:

Parameter Type Required Default Description
page int No 1 Page number (1-indexed)
size int No 20 Items per page

Success Response JSON Sample:

{
  "success": true,
  "httpStatus": "OK",
  "message": "Post quotes retrieved successfully",
  "action_time": "2025-01-03T10:30:45",
  "data": {
    "items": [
      {
        "id": "aa0e8400-e29b-41d4-a716-446655440099",
        "author": {
          "id": "550e8400-e29b-41d4-a716-446655440000",
          "userName": "alice_wanjiku",
          "firstName": "Alice",
          "lastName": "Wanjiku",
          "profilePictureUrl": "https://cdn.example.com/photos/alice.jpg",
          "isVerified": true
        },
        "content": "This is such an important point! Everyone should read this.",
        "postType": "REGULAR",
        "status": "PUBLISHED",
        "media": [],
        "topComments": [],
        "topLikers": [],
        "topReposters": [],
        "engagement": {
          "likesCount": 12,
          "commentsCount": 3,
          "repostsCount": 0,
          "quotesCount": 0,
          "bookmarksCount": 5,
          "sharesCount": 1,
          "viewsCount": 240,
          "canLike": true,
          "canComment": true,
          "canRepost": true,
          "canShare": true
        },
        "userInteraction": {
          "hasLiked": false,
          "hasBookmarked": false,
          "hasQuoted": false,
          "hasCommented": false,
          "hasViewed": true,
          "hasShared": false
        },
        "quotedPost": {
          "id": "orig-post-uuid",
          "author": {
            "id": "orig-author-uuid",
            "userName": "original_author",
            "firstName": "Original",
            "lastName": "Author",
            "profilePictureUrl": null,
            "isVerified": false
          },
          "content": "The original post content being quoted.",
          "postType": "REGULAR",
          "status": "PUBLISHED",
          "media": [],
          "createdAt": "2025-01-02T08:00:00Z",
          "publishedAt": "2025-01-02T08:00:00Z"
        },
        "publishedAt": "2025-01-03T12:05:00",
        "createdAt": "2025-01-03T12:05:00"
      }
    ],
    "totalElements": 17,
    "totalPages": 1,
    "hasNext": false,
    "hasPrevious": false,
    "isFirst": true,
    "isLast": true,
    "page": 1
  }
}

Success Response Fields:

Field Description
items Array of full PostResponse objects — one per quote post
items[].id UUID of the quote post
items[].author Author of the quote post (the person who quoted)
items[].content Text commentary added by the quoter
items[].postType Always REGULAR for quote posts
items[].status Post status (usually PUBLISHED)
items[].media Any media the quoter attached to their quote
items[].engagement Full engagement counters and permission flags for the quote post
items[].userInteraction Current viewer's interaction state with the quote post
items[].quotedPost The embedded original post being quoted (its own author, content, media, engagement)
items[].topComments Top comments on the quote post
items[].topLikers Top likers preview for the quote post
items[].topReposters Top reposters preview for the quote post
items[].publishedAt When the quote post was published
totalElements Total number of quote posts for this post
totalPages Total number of pages
hasNext Whether a next page exists
hasPrevious Whether a previous page exists
isFirst Whether this is the first page
isLast Whether this is the last page
page Current page number (1-indexed)

What Counts as a Quote: A quote is a post with quotedPostId set AND non-blank content. Posts with no content referencing this post are reposts and appear in endpoint 64 instead.

Ordering Behavior:

Viewer State Ordering
Authenticated Users the viewer follows appear first, then by most recent quote
Unauthenticated Most recent quotes first

Error Response Examples:

Post Not Found (404):

{
  "success": false,
  "httpStatus": "NOT_FOUND",
  "message": "Post not found",
  "action_time": "2025-01-03T10:30:45",
  "data": "Post not found"
}

Use Case: Display a "Quotes" tab in the post detail view. Each item is a full post card — the quoter's post with their commentary, media, engagement counts, and the original post embedded inside as quotedPost. This is the same UX as X's quote tweets tab.


Post Editing Rules Summary

Rule Value
Time window 60 minutes after publish
Maximum edits 3 per post
Poll options ❌ Cannot edit (would invalidate votes)
Poll title/description ✅ Can edit
Media ✅ Can add/remove/replace
Attachments ✅ Can add/remove/replace
Collaborators ✅ Can add new (accepted ones preserved)
Privacy settings ✅ Can edit
Engagement ✅ Preserved (likes, comments, reposts, views)
After limits Must delete and repost (loses engagement)

PostResponse.EditInfo Object

Every post response now includes an editInfo object:

{
  "id": "post-uuid",
  "content": "...",
  "editInfo": {
    "isEdited": true,
    "editCount": 2,
    "canEdit": false,
    "lastEditedAt": "2025-01-03T10:45:00"
  }
}

Frontend Usage:

Field Use
isEdited Show "Edited" label on post
editCount Display "Edited 2 times" tooltip
canEdit Show/hide edit button
lastEditedAt Show "Last edited 2h ago"

Quick Reference Guide

Common HTTP Status Codes

Authentication

Data Format Standards

Post Type Values

Post Status Values

Visibility Levels

Permission Levels

Hashtag API

Author: Josh, Lead Backend Developer Last Updated: 2026-03-02 Version: v1.0

Base URL: https://api.nexgate.com/api/v1

Short Description: The Hashtag API enables content discovery through hashtags. Users can browse posts by hashtag with optional filters for products, shops, and events, and explore trending hashtags across configurable time windows.

Hints:


Standard Response Format

{
  "success": true,
  "httpStatus": "OK",
  "message": "Operation completed successfully",
  "action_time": "2025-09-23T10:30:45",
  "data": {}
}

HTTP Method Badge Standards


Endpoints


1. Get Posts By Hashtag

Purpose: Retrieve paginated posts that contain a specific hashtag, with optional filtering by attachment type

Endpoint: GET {base_url}/e-social/hashtags/{hashtag}/posts

Access Level: 🔒 Protected (Requires Bearer Token Authentication)

Path Parameters:

Parameter Type Required Description
hashtag string Yes The hashtag to search (without #, e.g. MbeyaFashion)

Query Parameters:

Parameter Type Required Default Description
filter string No ALL Filter by attachment type. Accepted values: ALL, PRODUCTS, SHOPS, EVENTS
page integer No 1 Page number
size integer No 20 Number of posts per page

Request Headers:

Header Type Required Description
Authorization string Yes Bearer <token>
Content-Type string Yes application/json

Success Response JSON Sample:

{
  "success": true,
  "httpStatus": "OK",
  "message": "Posts retrieved",
  "action_time": "2026-03-02T10:30:45",
  "data": {
    "content": [
      {
        "id": "550e8400-e29b-41d4-a716-446655440000",
        "author": {
          "id": "123e4567-e89b-12d3-a456-426614174000",
          "userName": "kibuti_dev",
          "firstName": "Kibuti",
          "lastName": "Dev",
          "profilePictureUrl": "https://cdn.nexgate.com/profiles/kibuti.jpg",
          "isVerified": false
        },
        "content": "New collection just dropped! #MbeyaFashion #Summer",
        "contentParsed": {
          "text": "New collection just dropped! #MbeyaFashion #Summer",
          "entities": [
            {
              "type": "HASHTAG",
              "text": "#MbeyaFashion",
              "startIndex": 29,
              "endIndex": 42,
              "hashtag": "mbeyafashion"
            }
          ]
        },
        "postType": "REGULAR",
        "status": "PUBLISHED",
        "attachments": {
          "products": [
            {
              "id": "789e0123-e89b-12d3-a456-426614174000",
              "name": "Summer Dress",
              "price": 45000.00,
              "imageUrl": "https://cdn.nexgate.com/products/dress.jpg",
              "shopName": "Mbeya Styles",
              "shopId": "abc12345-e89b-12d3-a456-426614174000",
              "inStock": true,
              "socialContext": null
            }
          ],
          "shops": [],
          "events": [],
          "buyTogetherGroups": [],
          "installmentPlans": [],
          "externalLink": null
        },
        "engagement": {
          "likesCount": 24,
          "commentsCount": 5,
          "repostsCount": 3,
          "bookmarksCount": 8,
          "viewsCount": 120,
          "sharesCount": 2,
          "quotesCount": 1
        },
        "publishedAt": "2026-03-01T14:22:00",
        "createdAt": "2026-03-01T14:20:00"
      }
    ],
    "pageable": {
      "pageNumber": 0,
      "pageSize": 20
    },
    "totalElements": 54,
    "totalPages": 3,
    "last": false,
    "first": true
  }
}

Filter Behavior:

Filter Value Returns
ALL All posts containing the hashtag
PRODUCTS Only posts with the hashtag that have attached products
SHOPS Only posts with the hashtag that have attached shops
EVENTS Only posts with the hashtag that have attached events

Standard Error Types:

Error Response Example:

Unauthorized (401):

{
  "success": false,
  "httpStatus": "UNAUTHORIZED",
  "message": "Token has expired",
  "action_time": "2026-03-02T10:30:45",
  "data": "Token has expired"
}

Purpose: Retrieve the most used hashtags within a given time window, ordered by post count descending

Endpoint: GET {base_url}/e-social/hashtags/trending

Access Level: 🔒 Protected (Requires Bearer Token Authentication)

Query Parameters:

Parameter Type Required Default Description
window string No 24h Time window for trending calculation. Accepted values: 24h, 7d, 30d
limit integer No 15 Maximum number of trending hashtags to return

Request Headers:

Header Type Required Description
Authorization string Yes Bearer <token>
Content-Type string Yes application/json

Success Response JSON Sample:

{
  "success": true,
  "httpStatus": "OK",
  "message": "Trending hashtags",
  "action_time": "2026-03-02T10:30:45",
  "data": [
    {
      "hashtag": "mbeyafashion",
      "postCount": 312
    },
    {
      "hashtag": "daressalaamtech",
    "postCount": 278
    },
    {
      "hashtag": "tanzaniastartups",
      "postCount": 195
    },
    {
      "hashtag": "summer2026",
      "postCount": 143
    }
  ]
}

Response Fields:

Field Type Description
hashtag string The hashtag text (always lowercase, without #)
postCount long Number of posts using this hashtag within the selected time window

Window Behavior:

Window Value Looks Back
24h Last 24 hours — what's trending right now
7d Last 7 days — weekly trends
30d Last 30 days — monthly trends

Standard Error Types:


3. Search Hashtags

Purpose: Search hashtags by prefix query, used in post composer to suggest similar hashtags while typing. Results are sorted by a weighted score combining recent activity and all-time popularity.

Endpoint: GET {base_url}/e-social/hashtags/search

Access Level: 🔒 Protected (Requires Bearer Token Authentication)

Query Parameters:

Parameter Type Required Default Description
q string Yes Prefix query string (e.g. Mbe matches mbeyafashion, mbeyatech)
limit integer No 5 Maximum number of suggestions to return

Request Headers:

Header Type Required Description
Authorization string Yes Bearer <token>
Content-Type string Yes application/json

Success Response JSON Sample:

{
  "success": true,
  "httpStatus": "OK",
  "message": "Hashtag suggestions",
  "action_time": "2026-03-02T10:30:45",
  "data": [
    {
      "hashtag": "mbeyafashion",
      "postCount": 312
    },
    {
      "hashtag": "mbeyatech",
      "postCount": 89
    },
    {
      "hashtag": "mbeyafoods",
      "postCount": 45
    }
  ]
}

Response Fields:

Field Type Description
hashtag string Matched hashtag text (always lowercase, without #)
postCount long Total number of posts using this hashtag

Scoring & Sort Logic:

Results are sorted by a weighted score combining recency and popularity:

Post Age Score Weight
Posted within last 7 days 2 points per post
Older than 7 days 1 point per post

So a hashtag with 50 recent posts can outrank one with 200 old posts — fresh and trending tags float to the top naturally.

Empty Query Behavior: If q is empty or blank, returns an empty list immediately without querying the database.

Standard Error Types:

Error Response Example:

Unauthorized (401):

{
  "success": false,
  "httpStatus": "UNAUTHORIZED",
  "message": "Token has expired",
  "action_time": "2026-03-02T10:30:45",
  "data": "Token has expired"
}

Quick Reference Guide

Endpoints Summary

Method Endpoint Description
GET /e-social/hashtags/{hashtag}/posts Get posts by hashtag with optional filter
GET /e-social/hashtags/trending Get trending hashtags by time window

Filter Values

ALL PRODUCTS SHOPS EVENTS

24h 7d 30d

Authentication

Data Format Standards