Skip to main content

Posts Management API

Author: Josh, Lead Backend Team
Last Updated: 2025-12-11
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:

  • All endpoints require authentication via Bearer token unless specified
  • Draft posts follow a "one draft at a time" rule - publish or discard before creating new
  • Posts support text content, media (images/videos), polls, and commerce attachments
  • Privacy settings control visibility, comment permissions, and repost permissions
  • Collaborative posts require accepted invitations from collaborators
  • Pagination is 1-indexed (page=1 for first page), default size is 20 items
  • Poll votes can be changed if poll allows it (allowVoteChange setting)

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:

  • GET - GET - Green (Safe, read-only operations)
  • POST - POST - Blue (Create new resources)
  • PUT - PUT - Yellow (Update/replace entire resource)
  • DELETE - DELETE - Red (Remove resources)

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",
  "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": false,
    "collaborators": [],
    "byline": 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,
    "hasCommented": false,
    "hasViewed": false
  },
  "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:

  • Creates a post with status DRAFT (unless scheduledAt is provided, then SCHEDULED)
  • Enforces "one draft at a time" rule - user must publish or discard existing draft first
  • Automatically parses @mentions, $shop tags, and #hashtags from content
  • Validates all attached products, shops, events exist and are active
  • Sends collaboration invitations to specified users via notifications
  • For scheduled posts, validates scheduledAt is at least 5 minutes in the future
  • Media files must already be uploaded to file service before creating post
  • Collaborative posts remain in PENDING status until all invitees accept/reject

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
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:

  • At least one of: content, media, or poll must be provided
  • If postType is POLL, content is optional but poll object is required
  • Media files must be pre-uploaded to file service and URLs must be from approved CDN domains
  • All UUIDs (products, shops, events, users) are validated for existence and status
  • Mentions (@username, $shopname) and hashtags (#tag) are automatically extracted from content
  • MENTIONED visibility requires at least one @mention in content
  • Scheduled posts cannot be in the past; minimum 5 minutes buffer required
  • Collaborative posts send real-time notifications to all invited users
  • External links are validated for protocol (http/https only) and reachability

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)

  • 400 BAD_REQUEST: Already have a draft post, invalid post data, or validation errors
  • 401 UNAUTHORIZED: Authentication issues (empty, invalid, expired, or malformed tokens)
  • 422 UNPROCESSABLE_ENTITY: Validation errors with detailed field information
  • 500 INTERNAL_SERVER_ERROR: Unexpected server errors

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"
  }
}

Result: Creates poll allowing multiple votes, non-anonymous (voters visible), votes can be changed, expires Dec 25.

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}/e-social/posts/publish

Access Level: 🔒 Protected (Requires Bearer Token Authentication)

Authentication: Bearer Token

Behavior:

  • Finds user's current draft post (status = DRAFT)
  • Changes post status from DRAFT to PUBLISHED
  • Sets publishedAt timestamp to current time
  • Sends notifications to all mentioned users (@username, $shopname)
  • For collaborative posts, only publishes if all collaborators have accepted
  • Increments engagement counters for all attached products/shops/events
  • Triggers feed distribution to all followers
  • No request body required - system automatically finds the user's draft

Business Rules:

  1. Draft Requirement: User must have exactly one draft post
  2. Collaboration Status: All invited collaborators must have accepted (status = ACCEPTED)
  3. Content Validation: Draft must pass all content validation rules before publishing
  4. Attachment Validation: All attached products/shops/events must still be active/valid
  5. Scheduled Posts: Cannot publish a scheduled post (status = SCHEDULED) using this endpoint
  6. Feed Distribution: Published posts immediately appear in followers' feeds
  7. Notification Triggers: Sends notifications to @mentioned users and collaborators
  8. Engagement Initialization: All engagement counters (likes, comments, etc.) start at 0

Validation Checks on Publish:

  • Draft exists and belongs to current user
  • All collaborators have accepted (if collaborative post)
  • All attached products are still ACTIVE
  • All attached shops are still VERIFIED
  • All attached events are still PUBLISHED
  • Content still meets length requirements (5000 chars)
  • Media URLs still valid and accessible
  • Poll configuration valid (if poll post)

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 changed to PUBLISHED

Success Response Message: "Post published successfully"

Standard Error Types:

Application-Level Exceptions (400-499)

  • 400 BAD_REQUEST: No draft found, draft incomplete, or only draft posts can be published
  • 401 UNAUTHORIZED: Authentication issues
  • 403 FORBIDDEN: Collaborative post pending approval from collaborators
  • 404 NOT_FOUND: No draft post found for user
  • 422 UNPROCESSABLE_ENTITY: Draft validation failed (invalid attachments, etc.)
  • 500 INTERNAL_SERVER_ERROR: Unexpected server errors

Error Response Examples:

No Draft Found (404):

{
  "success": false,
  "httpStatus": "NOT_FOUND",
  "message": "No draft post found",
  "action_time": "2025-12-11T10:30:45",
  "data": "You don't have a draft post to publish"
}

Pending Collaborator Approval (403):

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

Invalid Attached Product (422):

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

Use Case Examples:

Example 1: Simple Draft Publish

POST /e-social/posts/publish

User has draft: "Hello world! This is my first post"
Result: Draft published, appears in followers' feeds, status = PUBLISHED, publishedAt set to current time

Example 2: Collaborative Draft Publish (All Accepted)

POST /e-social/posts/publish

User has draft with 2 collaborators
Both collaborators have accepted (status = ACCEPTED)
Result: Draft published, all 3 authors credited, appears on all 3 profiles, notifications sent

Example 3: Collaborative Draft Publish (Pending Approval)

POST /e-social/posts/publish

User has draft with 3 collaborators
Only 2 have accepted, 1 still pending
Result: Error 403 - Cannot publish until all collaborators accept

Example 4: Draft with Product Attachment

POST /e-social/posts/publish

User has draft with attached product
Product validation checks:
- Product exists? ✓
- Product status ACTIVE? ✓
- Product belongs to active shop? ✓
Result: Draft published, product card appears in post, shop gets notification

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:

  • Performs soft delete: Sets isDeleted flag to true, doesn't remove from database
  • Removes post from all users' feeds immediately
  • Preserves post data for analytics and audit purposes
  • All comments, likes, bookmarks remain in database but are hidden
  • Decrements engagement counters for attached products/shops/events
  • Sends notification to collaborators (if collaborative post)
  • Post no longer appears in searches, hashtag feeds, or explore pages
  • Only post author can delete their own posts (not collaborators)

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

What Gets Hidden:

  • Post itself (no longer visible to anyone)
  • All comments and replies on the post
  • All likes, bookmarks, reposts
  • Post no longer appears in:
    • User's profile
    • Followers' feeds
    • Hashtag pages
    • Search results
    • Product/shop/event pages (if attached)

What Gets Preserved (in database for analytics):

  • Original post content and metadata
  • All engagement metrics (historical counts)
  • All comments and their content
  • All likes, bookmarks, and reposts
  • Author and timestamp information
  • Attachment relationships

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)

  • 400 BAD_REQUEST: Can only delete your own posts
  • 401 UNAUTHORIZED: Authentication issues
  • 403 FORBIDDEN: Not the post author (collaborators cannot delete)
  • 404 NOT_FOUND: Post not found or already deleted
  • 500 INTERNAL_SERVER_ERROR: Unexpected server errors

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:

  • Returns full post details including author info, content, media, attachments, engagement
  • Respects post visibility settings (PUBLIC, FOLLOWERS, MENTIONED, PRIVATE)
  • Checks if requesting user has permission to view based on privacy settings
  • Includes user interaction state (hasLiked, hasBookmarked, etc.)
  • For poll posts, includes user's voting status and results if visible
  • Increments view counter if this is first view by this user
  • Returns parsed content with @mentions, $shops, and #hashtags highlighted
  • Includes collaboration info if collaborative post

Visibility Logic:

  • PUBLIC: Anyone can view
  • FOLLOWERS: Only followers of author can view
  • MENTIONED: Only users mentioned in post (@username) can view
  • PRIVATE: Only author can view

Additional Access Rules:

  • Blocked users cannot view each other's posts (even if PUBLIC)
  • Deleted posts (isDeleted = true) return 404 NOT_FOUND
  • Scheduled posts (status = SCHEDULED) only visible to author before scheduled time
  • Draft posts (status = DRAFT) only visible to author
  • Collaborative posts visible to all collaborators regardless of visibility setting

Response Includes:

  • Full post content with parsed entities (mentions, hashtags, shops)
  • Author information with profile picture and verification status
  • All media with URLs, dimensions, placeholders (BlurHash)
  • All commerce attachments (products, shops, events, groups, installments)
  • Collaboration details (if collaborative post)
  • Privacy settings
  • Engagement metrics (likes, comments, reposts counts)
  • User's interaction state (liked?, bookmarked?, reposted?, etc.)
  • Poll results (if poll post and user can see results)
  • Creation and publication timestamps

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)

  • 401 UNAUTHORIZED: Authentication issues
  • 403 FORBIDDEN: User doesn't have permission to view this post (visibility restrictions)
  • 404 NOT_FOUND: Post not found, deleted, or not yet published (scheduled/draft)
  • 500 INTERNAL_SERVER_ERROR: Unexpected server errors

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)

  • 401 UNAUTHORIZED: Authentication issues
  • 500 INTERNAL_SERVER_ERROR: Unexpected server errors

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)

  • 401 UNAUTHORIZED: Authentication issues
  • 404 NOT_FOUND: Author not found
  • 500 INTERNAL_SERVER_ERROR: Unexpected server errors

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)

  • 401 UNAUTHORIZED: Authentication issues
  • 500 INTERNAL_SERVER_ERROR: Unexpected server errors

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)

  • 401 UNAUTHORIZED: Authentication issues
  • 500 INTERNAL_SERVER_ERROR: Unexpected server errors

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)

  • 400 BAD_REQUEST: No draft found or can only discard your own draft
  • 401 UNAUTHORIZED: Authentication issues
  • 500 INTERNAL_SERVER_ERROR: Unexpected server errors

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)

  • 400 BAD_REQUEST: No draft found, can only update your own posts, or only draft posts can be updated
  • 401 UNAUTHORIZED: Authentication issues
  • 422 UNPROCESSABLE_ENTITY: Validation errors
  • 500 INTERNAL_SERVER_ERROR: Unexpected server errors

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}

  • /draft/attach-product/{productId}
  • /draft/attach-shop/{shopId}
  • /draft/attach-event/{eventId}
  • /draft/attach-group/{groupId}
  • /draft/attach-plan/{planId}

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

  • /draft/remove-product/{productId}
  • /draft/remove-shop/{shopId}
  • /draft/remove-event/{eventId}
  • /draft/remove-group/{groupId}
  • /draft/remove-plan/{planId}

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 Quote Post

Purpose: Create a new post that quotes an existing post

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

Request Body: CreateQuotePostRequest object (similar to CreatePostRequest but without poll support)

Success Response: Returns standard PostResponse structure with quotedPost field populated

Success Response Message: "Quote post created successfully"


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:

  • Adds current user's like to the specified post
  • Increments post's likesCount by 1
  • Creates like record with timestamp
  • Sends notification to post author (unless liking own post)
  • Updates user's userInteraction.hasLiked to true
  • Idempotent: If already liked, returns success without changes
  • Respects post visibility (must be able to view post to like it)
  • For collaborative posts, all collaborators receive notification

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:

  • 401 UNAUTHORIZED: Authentication required
  • 403 FORBIDDEN: Cannot like this post (blocked, visibility, etc.)
  • 404 NOT_FOUND: Post not found or deleted
  • 500 INTERNAL_SERVER_ERROR: Unexpected errors

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:

  • Removes current user's like from the specified post
  • Decrements post's likesCount by 1
  • Deletes like record from database
  • No notification sent (unlike is silent)
  • Updates user's userInteraction.hasLiked to false
  • Idempotent: If not liked, returns success without changes
  • Can unlike even if post is now deleted or user is blocked

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:

  • 401 UNAUTHORIZED: Authentication required
  • 404 NOT_FOUND: Post not found (permanent deletion from DB)
  • 500 INTERNAL_SERVER_ERROR: Unexpected errors

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:

  • Adds post to user's bookmark collection
  • Creates bookmark record with timestamp
  • Post appears in user's bookmarks list (GET /posts/bookmarks)
  • Increments post's bookmarksCount by 1
  • No notification sent (bookmarking is private)
  • Updates user's userInteraction.hasBookmarked to true
  • Idempotent: If already bookmarked, returns success without changes
  • Respects visibility (must be able to view post to bookmark it)

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:

  • 401 UNAUTHORIZED: Authentication required
  • 403 FORBIDDEN: Cannot bookmark this post (visibility restrictions)
  • 404 NOT_FOUND: Post not found
  • 500 INTERNAL_SERVER_ERROR: Unexpected errors

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:

  • Removes post from user's bookmark collection
  • Deletes bookmark record from database
  • Post no longer appears in user's bookmarks list
  • Decrements post's bookmarksCount by 1
  • No notification sent (unbookmarking is private)
  • Updates user's userInteraction.hasBookmarked to false
  • Idempotent: If not bookmarked, returns success without changes

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:

  • 401 UNAUTHORIZED: Authentication required
  • 404 NOT_FOUND: Post not found (permanent deletion)
  • 500 INTERNAL_SERVER_ERROR: Unexpected errors

33. Repost Post

Purpose: Share a post to your profile and followers' feeds (with optional comment)

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

Access Level: 🔒 Protected (Requires Bearer Token Authentication)

Authentication: Bearer Token

Behavior:

  • Creates a repost record linking user to original post
  • Original post appears in user's profile with "reposted" indicator
  • Original post appears in all followers' feeds attributed to reposter
  • Increments original post's repostsCount by 1
  • If comment provided, creates quote post instead (separate post with original embedded)
  • Sends notification to original post author
  • For collaborative posts, all collaborators receive notification
  • Updates user's userInteraction.hasReposted to true
  • Idempotent: If already reposted without comment, returns success
  • Respects post's whoCanRepost privacy setting

Business Rules:

  1. Permission Check: Post must allow reposts (whoCanRepost setting)
  2. Visibility Check: Must have permission to view post
  3. Blocking: Cannot repost from blocked users
  4. With Comment: If comment provided, creates separate quote post
  5. Without Comment: Direct repost, original post shown on profile
  6. Notification: Original author notified
  7. Feed Distribution: Appears in reposter's followers' feeds
  8. Attribution: Always shows original author prominently
  9. Idempotent: Second repost without comment is no-op
  10. Counter Update: Original post's repost counter incremented

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 repost Must be valid UUID format

Request Body (Optional):

{
  "comment": "This is amazing! Everyone should see this 🔥"
}

Request Body Parameters:

Parameter Type Required Description Validation
comment string No Optional comment for quote post Max: 500 characters. If provided, creates quote post instead

Success Response JSON Sample (Simple Repost):

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

Success Response JSON Sample (Quote Post):

{
  "success": true,
  "httpStatus": "OK",
  "message": "Quote post created successfully",
  "action_time": "2025-12-11T10:30:45",
  "data": {
    // Returns full PostResponse for the new quote post
    // with quotedPost field containing original post
  }
}

Standard Error Types:

  • 401 UNAUTHORIZED: Authentication required
  • 403 FORBIDDEN: Cannot repost (blocked, privacy settings, disabled reposts)
  • 404 NOT_FOUND: Post not found
  • 500 INTERNAL_SERVER_ERROR: Unexpected errors

Error Response Examples:

Reposts Disabled (403):

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

Reposts Followers Only (403):

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

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. Unrepost Post

Purpose: Remove a repost from your profile

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

Access Level: 🔒 Protected (Requires Bearer Token Authentication)

Authentication: Bearer Token

Behavior:

  • Removes repost from user's profile
  • Original post no longer appears in user's profile reposts
  • Decrements original post's repostsCount by 1
  • No notification sent (unrepost is silent)
  • Updates user's userInteraction.hasReposted to false
  • Does NOT delete quote posts (those are separate posts, use delete endpoint)
  • Idempotent: If not reposted, returns success without changes

Business Rules:

  1. Simple Reposts Only: Only removes simple reposts, not quote posts
  2. Quote Posts: To remove quote post, use DELETE /posts/{quotePostId}
  3. Silent Operation: No notification sent to original author
  4. Always Allowed: Can unrepost anytime, even if blocked or post deleted
  5. Counter Decrement: Original post's repost counter decremented
  6. Idempotent: Multiple unrepost attempts don't cause errors

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 original post to unrepost Must be valid UUID format

Success Response JSON Sample:

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

Standard Error Types:

  • 401 UNAUTHORIZED: Authentication required
  • 404 NOT_FOUND: Post not found (permanent deletion)
  • 500 INTERNAL_SERVER_ERROR: Unexpected errors

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:

  • Records that current user viewed the post
  • Increments post's viewsCount by 1 (first view only)
  • Creates view record with timestamp
  • Idempotent: Multiple views from same user only count once
  • Updates user's userInteraction.hasViewed to true
  • No notification sent (views are private analytics)
  • View counts visible to post author in analytics dashboard
  • Automatic: Usually called by frontend when post enters viewport

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:

  • 401 UNAUTHORIZED: Authentication required
  • 403 FORBIDDEN: Cannot view this post (visibility restrictions)
  • 404 NOT_FOUND: Post not found
  • 500 INTERNAL_SERVER_ERROR: Unexpected errors

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:

  • Returns all posts bookmarked by current user
  • Sorted by bookmark date (newest first)
  • Includes posts even if deleted or author blocked (user retains access)
  • Paginated results for performance
  • Each post includes full PostResponse structure
  • Shows deleted posts with special indicator (for user reference)
  • Includes posts from private/followers-only accounts if bookmarked when accessible

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:

  • 401 UNAUTHORIZED: Authentication required
  • 500 INTERNAL_SERVER_ERROR: Unexpected errors

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:

  • Returns all posts reposted by current user (simple reposts only)
  • Does NOT include quote posts (those are separate posts in user's profile)
  • Sorted by repost date (newest first)
  • Paginated results for performance
  • Each post shows original author and content
  • Respects current visibility settings of original posts

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:

  • 401 UNAUTHORIZED: Authentication required
  • 500 INTERNAL_SERVER_ERROR: Unexpected errors

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:

  • Returns all posts reposted by specified user (simple reposts only)
  • Does NOT include quote posts (those are in user's authored posts)
  • Respects privacy settings of original posts
  • Only shows reposts visible to requesting user based on:
    • Original post visibility settings
    • Blocking status
    • Follow relationships
  • Sorted by repost date (newest first)
  • Paginated results for performance

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:

  • 401 UNAUTHORIZED: Authentication required
  • 404 NOT_FOUND: User not found
  • 500 INTERNAL_SERVER_ERROR: Unexpected errors

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:

  • Records user's vote on poll options
  • Supports single or multiple option selection based on poll settings
  • If allowVoteChange is true, replaces existing vote
  • If allowVoteChange is false, rejects vote if user already voted
  • Increments vote counts for selected options
  • Updates poll's totalVotes count
  • If non-anonymous, records voter identity
  • If anonymous, records vote without identity
  • Validates poll hasn't expired before accepting vote
  • Respects post visibility (must be able to view post to vote)

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:

  • 400 BAD_REQUEST: Poll expired, vote change not allowed, or invalid options
  • 401 UNAUTHORIZED: Authentication required
  • 403 FORBIDDEN: Cannot vote (blocked, visibility restrictions)
  • 404 NOT_FOUND: Post or poll not found
  • 422 UNPROCESSABLE_ENTITY: Validation errors (too many options, invalid IDs)
  • 500 INTERNAL_SERVER_ERROR: Unexpected errors

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:

  • Removes all of user's votes from the poll
  • Decrements vote counts for previously selected options
  • Decrements poll's totalVotes count
  • Only allowed if allowVoteChange is true
  • Idempotent: If not voted, returns success without changes
  • Can remove votes even if poll expired (cleanup)

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:

  • 400 BAD_REQUEST: Vote removal not allowed (allowVoteChange is false)
  • 401 UNAUTHORIZED: Authentication required
  • 403 FORBIDDEN: Cannot access poll
  • 404 NOT_FOUND: Post or poll not found
  • 500 INTERNAL_SERVER_ERROR: Unexpected errors

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:

  • Returns complete poll details and voting statistics
  • Calculates percentages for each option
  • Shows user's voting status (hasVoted, which options voted)
  • Displays poll configuration (anonymous, multiple votes, change allowed)
  • Shows expiration status
  • Respects post visibility (must be able to view post)
  • Real-time results update as votes come in

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:

  • 401 UNAUTHORIZED: Authentication required
  • 403 FORBIDDEN: Cannot view poll (post visibility restrictions)
  • 404 NOT_FOUND: Post not found or not a poll post
  • 500 INTERNAL_SERVER_ERROR: Unexpected errors

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

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:

  • Returns list of users who voted for specific poll option
  • Only available for non-anonymous polls (isAnonymous = false)
  • Only accessible by post author and accepted collaborators
  • Sorted by vote time (newest first)
  • Includes user profile information
  • Paginated for large polls

Business Rules:

  1. Non-Anonymous Only: Only works if isAnonymous is false
  2. Author/Collaborator Access: Only post author and collaborators can view
  3. Privacy Protection: Regular users cannot see who voted
  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
    }
  }
}

Success Response Message: "Voters retrieved successfully"

Standard Error Types:

  • 400 BAD_REQUEST: Anonymous poll (voter list not available)
  • 401 UNAUTHORIZED: Authentication required
  • 403 FORBIDDEN: Not post author/collaborator
  • 404 NOT_FOUND: Post or option not found
  • 500 INTERNAL_SERVER_ERROR: Unexpected errors

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 (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 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 75 users who voted for this 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

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:

  • Creates top-level comment if parentCommentId is null
  • Creates nested reply if parentCommentId provided
  • Increments post's commentsCount by 1
  • Sends notification to post author (unless commenting on own post)
  • For replies, notifies parent comment author
  • Automatically parses @mentions in comment content
  • All mentioned users receive notifications
  • Respects post's whoCanComment privacy setting
  • Supports nested replies (unlimited depth)
  • Updates post's engagement metrics

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:

  • 400 BAD_REQUEST: Invalid content, parent comment not found, or spam detected
  • 401 UNAUTHORIZED: Authentication required
  • 403 FORBIDDEN: Cannot comment (permissions, blocked, disabled comments)
  • 404 NOT_FOUND: Post not found
  • 422 UNPROCESSABLE_ENTITY: Validation errors (content too long/short)
  • 429 TOO_MANY_REQUESTS: Rate limit exceeded
  • 500 INTERNAL_SERVER_ERROR: Unexpected errors

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:

  • Returns top-level comments only (parentCommentId = null)
  • Sorted by: Pinned first, then by createdAt (newest first)
  • Includes replyCount for each comment
  • Respects post visibility (must be able to view post)
  • Paginated for performance
  • Each comment includes author info and engagement metrics
  • Does NOT include replies (use Get Replies endpoint)

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:

  • 401 UNAUTHORIZED: Authentication required
  • 403 FORBIDDEN: Cannot view post
  • 404 NOT_FOUND: Post not found
  • 500 INTERNAL_SERVER_ERROR: Unexpected errors

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:

  • Returns full comment details including author, content, engagement
  • Includes parsed content with @mentions
  • Shows user's interaction state (hasLiked)
  • Respects post visibility rules
  • Returns parent comment info if it's a reply

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:

  • 401 UNAUTHORIZED: Authentication required
  • 403 FORBIDDEN: Cannot view post
  • 404 NOT_FOUND: Comment not found
  • 500 INTERNAL_SERVER_ERROR: Unexpected errors

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:

  • Returns all direct replies to specified comment
  • Sorted by createdAt (oldest first for conversation flow)
  • Each reply can have its own replies (nested)
  • Paginated for performance
  • Includes reply count for each reply (supports infinite nesting)

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:

  • 401 UNAUTHORIZED: Authentication required
  • 403 FORBIDDEN: Cannot view post
  • 404 NOT_FOUND: Comment not found
  • 500 INTERNAL_SERVER_ERROR: Unexpected errors

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:

  • Updates comment content
  • Sets isEdited flag to true
  • Updates updatedAt timestamp
  • Preserves original createdAt timestamp
  • Re-parses @mentions in updated content
  • Sends notifications to newly mentioned users
  • Only comment author can edit
  • Edit window: 15 minutes from creation (configurable)

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:

  • 400 BAD_REQUEST: Edit window expired (>15 minutes)
  • 401 UNAUTHORIZED: Authentication required
  • 403 FORBIDDEN: Not comment author
  • 404 NOT_FOUND: Comment not found
  • 422 UNPROCESSABLE_ENTITY: Validation errors
  • 500 INTERNAL_SERVER_ERROR: Unexpected errors

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:

  • Performs soft delete: Sets isDeleted flag, doesn't remove from DB
  • Decrements post's commentsCount by 1
  • Replies remain visible but show "[deleted]" as parent
  • Comment author and post author can delete
  • Preserves comment data for audit/analytics
  • Updates comment content to "[deleted]" in responses
  • No notification sent

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:

  • 401 UNAUTHORIZED: Authentication required
  • 403 FORBIDDEN: Not comment author or post author
  • 404 NOT_FOUND: Comment not found
  • 500 INTERNAL_SERVER_ERROR: Unexpected errors

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:

  • Pins comment to top of comment list
  • Sets isPinned flag to true
  • Only one comment can be pinned per post
  • If another comment already pinned, it gets unpinned automatically
  • Post author or collaborators can pin
  • Pinned comment always appears first in GET /comments
  • Sends notification to comment author

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:

  • 400 BAD_REQUEST: Cannot pin replies, only top-level comments
  • 401 UNAUTHORIZED: Authentication required
  • 403 FORBIDDEN: Not post author/collaborator
  • 404 NOT_FOUND: Post or comment not found
  • 500 INTERNAL_SERVER_ERROR: Unexpected errors

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:

  • Removes pin from comment
  • Sets isPinned flag to false
  • Comment returns to normal sort order (by createdAt)
  • Post author or collaborators can unpin
  • No notification sent
  • Idempotent: Unpinning non-pinned comment returns success

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:

  • 401 UNAUTHORIZED: Authentication required
  • 403 FORBIDDEN: Not post author/collaborator
  • 404 NOT_FOUND: Comment not found
  • 500 INTERNAL_SERVER_ERROR: Unexpected errors

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:

  • Adds current user's like to comment
  • Increments comment's likesCount by 1
  • Sends notification to comment author (unless self-like)
  • Updates user's interaction state (hasLiked = true)
  • Idempotent: Multiple like attempts don't create duplicates
  • Must be able to view parent post to like comment

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:

  • 401 UNAUTHORIZED: Authentication required
  • 403 FORBIDDEN: Cannot like (blocked, no post access)
  • 404 NOT_FOUND: Comment not found
  • 500 INTERNAL_SERVER_ERROR: Unexpected errors

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:

  • Removes current user's like from comment
  • Decrements comment's likesCount by 1
  • No notification sent (silent operation)
  • Updates user's interaction state (hasLiked = false)
  • Idempotent: Multiple unlike attempts safe
  • Can unlike even if comment deleted or user blocked

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:

  • 401 UNAUTHORIZED: Authentication required
  • 404 NOT_FOUND: Comment not found (permanent deletion)
  • 500 INTERNAL_SERVER_ERROR: Unexpected errors

Quick Reference Guide

Common HTTP Status Codes

  • 200 OK: Successful GET/POST/PUT/DELETE request
  • 400 Bad Request: Invalid request data or business rule violation
  • 401 Unauthorized: Authentication required/failed
  • 404 Not Found: Resource not found
  • 422 Unprocessable Entity: Validation errors
  • 500 Internal Server Error: Server error

Authentication

  • Bearer Token: Include Authorization: Bearer your_token in headers

Data Format Standards

  • Dates: Use ISO 8601 format (2025-12-11T14:30:00Z)
  • IDs: UUID format (e.g., 550e8400-e29b-41d4-a716-446655440000)
  • Pagination: 1-indexed pages (page=1 for first page), default size=20

Post Type Values

  • REGULAR: Standard text/media post
  • POLL: Poll post with voting options

Post Status Values

  • DRAFT: Unpublished draft
  • SCHEDULED: Scheduled for future publication
  • PUBLISHED: Live and visible
  • DELETED: Soft deleted

Visibility Levels

  • PUBLIC: Anyone can see
  • FOLLOWERS: Only followers can see
  • MENTIONED: Only mentioned users can see
  • PRIVATE: Only author can see

Permission Levels

  • EVERYONE: All users
  • FOLLOWERS: Only followers
  • MENTIONED: Only mentioned users (for comments)
  • DISABLED: Feature disabled