Posts Management API Author : Josh, Lead Backend Team Last Updated : 2026-06-18 Version : v1.0 Base URL : https://api.nexgate.com/api/v1 Short Description : The Posts Management API provides comprehensive social media posting functionality including creating posts, polls, quote posts, drafts management, media attachments, commerce integrations, collaboration features, and engagement interactions (likes, bookmarks, reposts, comments). This API enables users to create rich content with privacy controls and scheduled publishing. Hints : 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", "postKind": "ORIGINAL", "status": "PUBLISHED", "media": [ { "id": "media-123", "mediaType": "IMAGE", "originalUrl": "https://cdn.nexgate.com/posts/image1.jpg", "thumbnailUrl": "https://cdn.nexgate.com/posts/image1_thumb.jpg", "placeholderBase64": "base64-string-here", "width": 1920, "height": 1080, "order": 1, "imageTags": [] } ], "attachments": { "products": [], "shops": [], "events": [], "buyTogetherGroups": [], "installmentPlans": [], "externalLink": null }, "collaboration": { "isCollaborative": true, "collaborators": [ { "id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890", "status": "ACCEPTED", "invitedAt": "2024-01-15T10:00:00", "respondedAt": "2024-01-15T10:30:00", "user": { "id": "u1b2c3d4-e5f6-7890-abcd-ef1234567890", "userName": "john_doe", "firstName": "John", "lastName": "Doe", "profilePictureUrl": "https://cdn.example.com/photos/john.jpg" } }, { "id": "b2c3d4e5-f6a7-8901-bcde-f12345678901", "status": "PENDING", "invitedAt": "2024-01-15T11:00:00", "respondedAt": null, "user": { "id": "u2c3d4e5-f6a7-8901-bcde-f12345678901", "userName": "current_user", "firstName": "Current", "lastName": "User", "profilePictureUrl": "https://cdn.example.com/photos/current.jpg" } } ], "byline": "By Jane Smith and 1 others", "currentUserStatus": "PENDING", "currentUserIsPendingCollaborator": true, "currentUserIsAcceptedCollaborator": false }, "privacySettings": { "visibility": "PUBLIC", "whoCanComment": "EVERYONE", "whoCanRepost": "EVERYONE", "hideLikesCount": false, "hideCommentsCount": false }, "engagement": { "likesCount": 0, "commentsCount": 0, "repostsCount": 0, "quotesCount": 0, "bookmarksCount": 0, "sharesCount": 0, "viewsCount": 0, "canLike": true, "canComment": true, "canRepost": true, "canShare": true }, "userInteraction": { "hasLiked": false, "hasBookmarked": true, "hasReposted": false, "myRepostId": null, "hasQuoted": true, "hasCommented": false, "hasViewed": true, "hasShared": false }, "topComments": [ { "id": "comment-001", "userId": "user-abc-123", "content": "This is amazing! 🔥", "userName": "sarah_smith", "displayName": "Sarah Smith", "profilePictureUrl": "https://cdn.nexgate.com/profiles/sarah_smith.jpg" }, { "id": "comment-002", "userId": "user-xyz-789", "content": "Where can I get this?", "userName": "mike_wilson", "displayName": "Mike Wilson", "profilePictureUrl": "https://cdn.nexgate.com/profiles/mike_wilson.jpg" } ], "topLikers": [ { "userId": "user-abc-123", "userName": "john_doe", "displayName": "John Doe", "profilePictureUrl": "https://cdn.nexgate.com/profiles/john_doe.jpg" }, { "userId": "user-xyz-789", "userName": "sarah_smith", "displayName": "Sarah Smith", "profilePictureUrl": "https://cdn.nexgate.com/profiles/sarah_smith.jpg" } ], "topReposters": [ { "userId": "user-lmn-456", "userName": "mike_wilson", "displayName": "Mike Wilson", "profilePictureUrl": "https://cdn.nexgate.com/profiles/mike_wilson.jpg" } ], "createdAt": "2025-12-11T10:30:45", "publishedAt": "2025-12-11T10:30:45", "scheduledAt": null } Endpoints 1. Create Post Purpose : Create a new post (draft or scheduled) with optional content, media, poll, attachments, and collaboration Endpoint : POST {base_url}/e-social/posts Access Level : 🔒 Protected (Requires Bearer Token Authentication) Authentication : Bearer Token Behavior : 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 : Draft System : Only one draft allowed per user at a time Content Requirements : Either content text OR media OR poll must be provided (not all optional) Poll Requirements : If postType is POLL, poll object with 2-10 options is required Media Limits : Maximum 10 media items per post Commerce Limits : Max 10 products, 5 shops, 3 events per post Collaboration Limits : Maximum 5 collaborators per post Scheduling Rules : Scheduled time must be at least 5 minutes in future, max 6 months ahead Mention Extraction : System automatically detects and links @username and $shopname mentions Hashtag Indexing : All #hashtags automatically indexed for search and trending 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 ) Content-Type string Yes Must be application/json Request JSON Sample : { "content": "Excited to share my latest project! @john_doe check this out #coding", "postType": "REGULAR", "media": [ { "mediaType": "IMAGE", "mediaUrl": "https://cdn.nexgate.com/uploads/image1.jpg", "placeholderBase64": "base64-string", "width": 1920, "height": 1080 } ], "privacySettings": { "visibility": "PUBLIC", "whoCanComment": "EVERYONE", "whoCanRepost": "EVERYONE", "hideLikesCount": false, "hideCommentsCount": false }, "scheduledAt": null } Request Body Parameters : Parameter Type Required Description Validation content string No* Post text content Max: 5000 characters. *Required if no media/poll postType string Yes Type of post enum: REGULAR, POLL media array No Array of media objects (images/videos) Max: 10 items media[].mediaType string Yes (if media provided) Type of media enum: IMAGE, VIDEO media[].mediaUrl string Yes (if media provided) URL of the media file Valid URL format, must be from approved CDN media[].placeholderBase64 string No BlurHash or base64 placeholder Used for progressive image loading media[].width integer No Media width in pixels Min: 1, Max: 8000 media[].height integer No Media height in pixels Min: 1, Max: 8000 media[].duration integer No Video duration in seconds Required for videos, Max: 600 (10 minutes) poll object No Poll configuration Required if postType is POLL poll.title string Yes (if poll provided) Poll question/title Min: 5, Max: 500 characters poll.description string No Additional poll description Max: 1000 characters poll.options array Yes (if poll provided) Array of poll options Min: 2, Max: 10 poll.options[].optionText string Yes Text for the poll option Min: 1, Max: 200 characters poll.options[].optionImageUrl string No Optional image for the option Valid URL format, must be from approved CDN poll.allowMultipleVotes boolean No Allow selecting multiple options Default: false poll.isAnonymous boolean No Hide voter identities Default: true. If false, voters visible to post author poll.allowVoteChange boolean No Allow users to change their vote Default: true. If false, votes are final poll.expiresAt string No Poll expiration datetime ISO 8601 format, must be future, max 30 days from now poll.hideResultsUntilExpiry boolean No Hide vote counts and results until the poll expires Default: false. When true , results are only revealed after expiresAt passes — even voters cannot see counts before then. Requires expiresAt to be meaningful; if no expiry is set, results remain hidden indefinitely attachments object No Commerce attachments attachments.productIds array No Array of product UUIDs to attach Max: 10. Products must be ACTIVE status attachments.shopIds array No Array of shop UUIDs to attach Max: 5. Shops must be VERIFIED attachments.eventIds array No Array of event UUIDs to attach Max: 3. Events must be PUBLISHED attachments.buyTogetherGroupIds array No Array of group purchase UUIDs Groups must be ACTIVE, not COMPLETED attachments.installmentPlanIds array No Array of installment plan UUIDs Plans must be ACTIVE, not EXPIRED attachments.externalLink object No External link object Only one external link allowed per post attachments.externalLink.url string Yes (if externalLink provided) URL to attach Valid URL format, supports http/https only collaboration object No Collaboration settings collaboration.collaboratorIds array No Array of user UUIDs to invite Max: 5. Users must not be blocked by author privacySettings object No Privacy configuration privacySettings.visibility string No Post visibility level enum: PUBLIC, FOLLOWERS, MENTIONED, PRIVATE. Default: PUBLIC privacySettings.whoCanComment string No Comment permission level enum: EVERYONE, FOLLOWERS, MENTIONED, DISABLED. Default: EVERYONE privacySettings.whoCanRepost string No Repost permission level enum: EVERYONE, FOLLOWERS, DISABLED. Default: EVERYONE privacySettings.hideLikesCount boolean No Hide like count from others Default: false. Author always sees true count privacySettings.hideCommentsCount boolean No Hide comment count from others Default: false. Author always sees true count scheduledAt string No Schedule post for future publication ISO 8601 format, must be 5+ minutes future, max 6 months ahead Validation Notes : At least one of: content, media, or poll must be provided If postType is POLL, content is optional but poll object is required hideResultsUntilExpiry: true without an expiresAt means results stay hidden indefinitely — set an expiry when using this flag 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", "hideResultsUntilExpiry": true } } Result: Creates poll allowing multiple votes, non-anonymous (voters visible), votes can be changed, expires Dec 25. Results (vote counts) are hidden from everyone until Dec 25 — after expiry they become visible automatically. Example 4: Scheduled Collaborative Event Post { "content": "Excited to announce our tech conference! @john_doe and I are hosting. Join us! 🚀 #TechConf2026", "postType": "REGULAR", "attachments": { "eventIds": ["880e8400-e29b-41d4-a716-446655440004"] }, "collaboration": { "collaboratorIds": ["770e8400-e29b-41d4-a716-446655440001"] }, "scheduledAt": "2025-12-20T08:00:00Z" } Result: Creates scheduled post for Dec 20, attaches event, sends collaboration invite to john_doe, extracts @john_doe mention and #TechConf2026 hashtag. 2. Publish Draft Post Purpose : Publish the current user's draft post Endpoint : POST {base_url}/api/v1/e-social/posts/publish Access Level : 🔒 Protected (Requires Authentication) Authentication : Bearer Token Request Headers : Header Type Required Description Authorization string Yes Bearer token for authentication Content-Type string Yes Must be application/json Content Validation Rules : The post must pass content validation before publishing. At minimum, a post must have meaningful content. Scenario Allowed? Notes Text only ✅ Yes Valid standalone post Text + Media ✅ Yes Valid post with images/videos Media only (no text) ✅ Yes Image/video post without caption Poll only ✅ Yes Poll title serves as content Poll + Text ✅ Yes Enhanced poll post Quote only ✅ Yes Quoted post provides context Quote + Text ✅ Yes Quote with commentary Attachment only (product/shop/event/link) ✅ Yes Commerce/social attachment Attachment + Text ✅ Yes Enhanced attachment post Attachment + Media (no text) ✅ Yes Rich commerce post Attachment + Media + Text ✅ Yes Full featured post Empty post ❌ No Must have at least one content type Validation Error Messages : Condition Error Message Media without text "Media posts must include text content" Empty post "Post must have at least one of: text content, poll, quote, or attachments" No draft found "No draft found" Pending collaborators "Cannot publish collaborative post - waiting for collaborator acceptance" Business Rules : Draft Requirement : User must have exactly one draft post Content Validation : Draft must pass all content validation rules (see table above) Media Rule : Posts with media (images/videos) must include text content Collaboration Status : All invited collaborators must have accepted (status = ACCEPTED) Attachment Validation : All attached products/shops/events must still be active/valid Scheduled Posts : Cannot publish a scheduled post using this endpoint Feed Distribution : Published posts immediately appear in followers' feeds Notification Triggers : Sends notifications to @mentioned users and collaborators Validation Checks on Publish : Draft exists and belongs to current user Content validation passes (text, media, poll, quote, or attachments) Media posts have accompanying text content 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 meets length requirements (max 5000 chars) Media URLs are valid and accessible Poll configuration is valid (if poll post) Success Response JSON Sample : { "success": true, "httpStatus": "OK", "message": "Post published successfully", "action_time": "2025-12-29T10:30:45", "data": { "id": "550e8400-e29b-41d4-a716-446655440000", "author": { "id": "660e8400-e29b-41d4-a716-446655440001", "userName": "john_doe", "firstName": "John", "lastName": "Doe", "profilePictureUrl": "https://storage.example.com/profiles/john.jpg", "isVerified": true }, "content": "Check out this amazing product! 🛍️", "postType": "REGULAR", "status": "PUBLISHED", "media": [ { "id": "media-001", "mediaType": "IMAGE", "originalUrl": "https://storage.example.com/posts/image1.jpg", "thumbnailUrl": "https://storage.example.com/posts/image1_thumb.jpg", "width": 1080, "height": 1080, "order": 0 } ], "attachments": { "products": [ { "id": "770e8400-e29b-41d4-a716-446655440002", "name": "Wireless Headphones", "price": 150000.00, "imageUrl": "https://storage.example.com/products/headphones.jpg", "shopName": "TechStore TZ", "inStock": true } ], "shops": [], "events": [], "buyTogetherGroups": [], "installmentPlans": [], "externalLink": null }, "privacySettings": { "visibility": "PUBLIC", "whoCanComment": "EVERYONE", "whoCanRepost": "EVERYONE", "hideLikesCount": false, "hideCommentsCount": false }, "engagement": { "likesCount": 0, "commentsCount": 0, "repostsCount": 0, "quotesCount": 0, "bookmarksCount": 0, "sharesCount": 0, "viewsCount": 0, "canLike": true, "canComment": true, "canRepost": true, "canShare": true }, "userInteraction": { "hasLiked": false, "hasBookmarked": false, "hasReposted": false, "myRepostId": null, "hasQuoted": false, "hasCommented": false, "hasViewed": false, "hasShared": false }, "createdAt": "2025-12-29T10:00:00", "publishedAt": "2025-12-29T10:30:45", "scheduledAt": null } } Success Response Fields : Field Description id Unique identifier of the published post author Information about the post author content Text content of the post postType Content type: REGULAR, POLL postKind Sharing kind: ORIGINAL, REPOST, QUOTE (derived, not stored in DB) status Post status (now PUBLISHED) media Array of media attachments (images/videos) attachments Commerce and social attachments privacySettings Privacy and interaction settings engagement Engagement counters (all start at 0) userInteraction Current user's interaction status publishedAt Timestamp when post was published Error Response JSON Samples : Media Without Text Content: { "success": false, "httpStatus": "BAD_REQUEST", "message": "Media posts must include text content", "action_time": "2025-12-29T10:30:45", "data": null } Empty Post: { "success": false, "httpStatus": "BAD_REQUEST", "message": "Post must have at least one of: text content, poll, quote, or attachments", "action_time": "2025-12-29T10:30:45", "data": null } No Draft Found: { "success": false, "httpStatus": "BAD_REQUEST", "message": "No draft found", "action_time": "2025-12-29T10:30:45", "data": null } Pending Collaborator Approval: { "success": false, "httpStatus": "FORBIDDEN", "message": "Cannot publish collaborative post - waiting for collaborator acceptance", "action_time": "2025-12-29T10:30:45", "data": "2 of 3 collaborators have accepted" } Invalid Attached Product: { "success": false, "httpStatus": "UNPROCESSABLE_ENTITY", "message": "Invalid product attachment", "action_time": "2025-12-29T10:30:45", "data": "Product 550e8400-e29b-41d4-a716-446655440001 is no longer active" } Standard Error Types : 400 BAD_REQUEST : No draft found, content validation failed, or media without text 401 UNAUTHORIZED : Missing or invalid authentication token 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, expired poll, etc.) Use Case Examples : Example 1: Text Only Post Draft: "Hello world! This is my first post" Result: ✅ Published successfully Example 2: Text + Media Post Draft: "Check out this sunset! 🌅" + [image.jpg] Result: ✅ Published successfully Example 3: Media Only (No Text) Draft: [image.jpg] (no text content) Result: ❌ Error - "Media posts must include text content" Example 4: Poll Only Draft: Poll "What's your favorite color?" with options [Red, Blue, Green] Result: ✅ Published successfully (poll title serves as content) Example 5: Product Attachment Only Draft: Attached product "Wireless Headphones" (no text) Result: ✅ Published successfully (attachment provides context) Example 6: Product + Media (No Text) Draft: Attached product + [product_photo.jpg] (no text) Result: ❌ Error - "Media posts must include text content" Example 7: Quote Post Only Draft: Quoting another post (no additional text) Result: ✅ Published successfully (quoted post provides context) Example 8: Empty Post Draft: No content, no media, no attachments Result: ❌ Error - "Post must have at least one of: text content, poll, quote, or attachments" 3. Delete Post Purpose : Soft delete a post (marks as deleted, doesn't remove from database) Endpoint : DELETE {base_url}/e-social/posts/{postId} Access Level : 🔒 Protected (Requires Bearer Token Authentication) Authentication : Bearer Token Behavior : 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) Cascade repost deletion : If this is an original post, all pure reposts of it are automatically soft-deleted asynchronously in the background. Quote posts (reposts with added text) are NOT deleted — they remain but show a tombstone where the original was embedded. Business Rules : Author Only : Only the original post author can delete (collaborators cannot) Soft Delete : Data retained in database with isDeleted = true Irreversible : Deleted posts cannot be undeleted (would need backend intervention) Cascade Hiding : Comments/likes/bookmarks hidden but not deleted Analytics Preservation : Engagement data preserved for historical analytics Feed Removal : Immediately removed from all feeds (home, explore, profile) Notification : Collaborators notified of deletion Attachment Impact : Products/shops/events lose post engagement stats Repost Cascade : All pure reposts (no added text) are automatically soft-deleted asynchronously — response is instant, cascade runs in background Quote Posts Survive : Quote posts (which have their own content) remain alive but show quotedPost.unavailable = true with message "This post is no longer available." Interactions on dead reposts : Once the original is deleted, likes/comments/views on any repost of it return "Post not found" — interactions are blocked What Gets Hidden : 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 ) 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 ) 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 ) 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 ) 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 ) 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 ) 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 ) 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 ) 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 Repost or Quote Post Purpose : Repost or quote an existing post. The same endpoint handles both — the presence or absence of content determines which one is created. Endpoint : POST {base_url}/e-social/posts/quote/{quotedPostId} Access Level : 🔒 Protected (Requires Bearer Token Authentication) Authentication : Bearer Token Repost vs Quote — The Difference Repost Quote Post content in body empty / omitted your text postKind in response REPOST QUOTE Counter on original repostsCount + 1 quotesCount + 1 Has its own engagement No (shows original's counts) Yes (its own likes/comments) Duplicate check Can't repost same post twice Can quote same post multiple times Daily limit Yes (configurable) No separate limit Repost (silent forward — no added text) Request : POST /e-social/posts/quote/aaa-111 Content-Type: application/json {} Body is empty — no content field means it's a pure repost. What happens : A new post is created with quotedPostId = aaa-111 , content = null Original post's repostsCount incremented by 1 Response engagement and interaction data comes from the original post , not this new repost post Response ( postKind: REPOST ): { "id": "bbb-222", "postKind": "REPOST", "author": { "userName": "mbappe" }, "content": null, "quotedPost": { "id": "aaa-111", "author": { "userName": "ronaldo" }, "content": "Siuuu! 🔥", "status": "PUBLISHED" }, "engagement": { "likesCount": 9001, "repostsCount": 1, "quotesCount": 1 }, "userInteraction": { "hasLiked": false, "hasReposted": true, "myRepostId": "bbb-222" } } Note : engagement and userInteraction on a repost always reflect the original post's data — not the repost itself. Likes, comments, views on the repost all flow through to the original. Quote Post (repost with your own added comment) Request : POST /e-social/posts/quote/aaa-111 Content-Type: application/json { "content": "Respect to the GOAT 🐐" } What happens : A new post is created with quotedPostId = aaa-111 , content = "Respect to the GOAT 🐐" Original post's quotesCount incremented by 1 This new post has its own independent engagement — its own likes, comments, views Response ( postKind: QUOTE ): { "id": "ccc-333", "postKind": "QUOTE", "author": { "userName": "messi" }, "content": "Respect to the GOAT 🐐", "quotedPost": { "id": "aaa-111", "author": { "userName": "ronaldo" }, "content": "Siuuu! 🔥", "status": "PUBLISHED" }, "engagement": { "likesCount": 0, "repostsCount": 0, "quotesCount": 0 }, "userInteraction": { "hasLiked": false, "hasReposted": false, "myRepostId": null, "hasQuoted": true } } Undo a Repost There is no dedicated "unrepost" endpoint. To undo a repost, the client reads userInteraction.myRepostId from the original post's response, then calls: DELETE /e-social/posts/{myRepostId} This soft-deletes the repost and decrements the original's repostsCount . How the client knows the user has reposted: When fetching any post, userInteraction includes: "userInteraction": { "hasReposted": true, "myRepostId": "bbb-222" } If hasReposted = false , myRepostId is null . Reposting a Repost (Chain Resolution) If you try to repost a post that is itself a pure repost, the system automatically resolves to the original post and creates the new repost pointing directly to it. Example : Ronaldo posts POST_A Mbappe reposts → POST_B (points to POST_A ) You repost POST_B → your new repost points to POST_A , not POST_B This prevents empty chains and ensures: The display always shows the original content Counts always go to the original author Duplicate detection correctly blocks you if you already reposted POST_A When the Original Post is Deleted Your repost : automatically soft-deleted in the background when original is deleted. No action needed. Your quote post : stays alive, but quotedPost.unavailable = true with message "This post is no longer available." . The quote retains its own content and engagement. Interactions on your repost (after original deleted): like/comment/view calls return "Post not found" — all blocked. Business Rules : Original post must be PUBLISHED Cannot repost the same post twice (duplicate check by author + quotedPostId) Daily limit applies to pure reposts (no-content) — configurable server-side Reposting a repost always resolves to the original (chain flattening) Privacy: original post's whoCanRepost setting is enforced Repost engagement (likes, comments, views) always routes to the original post Quote post engagement is independent — stays on the quote post Path Parameters : Parameter Type Required Description quotedPostId UUID Yes ID of the post to repost or quote Request Body Parameters : Parameter Type Required Description content string No Your added comment. Omit or leave empty for a pure repost. privacySettings object No Privacy for the new repost/quote post Success Response : Returns standard PostResponse with quotedPost populated and postKind set to REPOST or QUOTE . Success Response Message : "Quote post created successfully" Standard Error Types : 400 BAD_REQUEST : Already reposted this post, daily repost limit reached, or original not published 401 UNAUTHORIZED : Authentication required 403 FORBIDDEN : Original post's whoCanRepost setting blocks you 404 NOT_FOUND : Original post not found 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 : Visibility Check : User must have permission to view post based on privacy settings Blocking : Cannot like posts from blocked users or if author blocked you Deleted Posts : Cannot like deleted posts (isDeleted = true) Draft/Scheduled : Cannot like unpublished posts (must be PUBLISHED status) Idempotent : Multiple like attempts don't create duplicate likes Notification : Author receives notification (unless self-like) Counter Update : Post's engagement counter incremented atomically 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 : Silent Operation : No notification sent to post author Always Allowed : Can unlike even if blocked or post deleted (to clean up state) Idempotent : Multiple unlike attempts don't cause errors Counter Decrement : Post's engagement counter decremented atomically 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 : Private Action : Bookmarks are private, author doesn't get notified Visibility Required : Must have permission to view post based on privacy settings Persistent : Bookmarks persist even if post is deleted (for user's reference) Organization : Can be organized into collections (future feature) No Limit : Unlimited bookmarks allowed per user Idempotent : Multiple bookmark attempts don't create duplicates Counter Update : Post's engagement counter incremented 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 : Silent Operation : No notification sent Always Allowed : Can unbookmark anytime, even if post deleted Idempotent : Multiple unbookmark attempts don't cause errors 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 Use Case Examples : Example 1: Simple Repost (No Comment) POST /e-social/posts/550e8400-e29b-41d4-a716-446655440000/repost Body: {} or no body Result: Original post appears on user's profile with "reposted" badge Appears in followers' feeds Original author gets notification Example 2: Quote Post (With Comment) POST /e-social/posts/660e8400-e29b-41d4-a716-446655440001/repost Body: { "comment": "This is exactly what I've been saying! Great insight 🎯" } Result: Creates new quote post with comment Original post embedded in quote New post has own likes/comments Both posts' repost counters incremented 34. Undo Repost (Unrepost) Purpose : Remove your repost. There is no dedicated unrepost endpoint — unreposting is done by deleting the repost post itself using myRepostId from the post's userInteraction . How to undo a repost : Fetch the original post. The response contains: "userInteraction": { "hasReposted": true, "myRepostId": "bbb-222" } Call the standard delete endpoint with the repost's ID: Endpoint : DELETE {base_url}/e-social/posts/{myRepostId} Access Level : 🔒 Protected (Requires Bearer Token Authentication) What happens : The repost post ( bbb-222 ) is soft-deleted Original post's repostsCount decremented by 1 userInteraction.hasReposted returns false , myRepostId returns null on next fetch No notification sent (silent) Business Rules : Only the repost author can delete their own repost To remove a quote post (which has content), use the same DELETE /posts/{quotePostId} — this decrements quotesCount instead If original post is already deleted, the repost will have been auto-deleted by the cascade — nothing to undo Success Response JSON Sample : { "success": true, "httpStatus": "OK", "message": "Post deleted successfully", "action_time": "2025-12-11T10:30:45", "data": null } Standard Error Types : 400 BAD_REQUEST : Not your repost 401 UNAUTHORIZED : Authentication required 404 NOT_FOUND : Repost not found or already deleted 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 : One View Per User : Each user counted only once regardless of repeat views Private Metric : View counts not shown publicly (author sees in analytics) No Notification : Viewing doesn't notify author Automatic Tracking : Frontend typically calls this when post visible for 2+ seconds Respects Visibility : Must have permission to view post Author Excluded : Author's own views don't count 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 : Personal Collection : Only user's own bookmarks visible Persists Deletions : Bookmarked posts remain accessible even if deleted Persists Blocking : Can view bookmarked posts even if author blocked Chronological : Sorted by bookmark time (newest first) Full Details : Each post includes complete information 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 : Simple Reposts Only : Only shows direct reposts, not quote posts Quote Posts : Appear in regular "Get User Posts" endpoint as authored posts Current Visibility : If original post now private/deleted, it's excluded Chronological : Sorted by repost time (newest first) 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 : Simple Reposts Only : Only shows direct reposts, not quote posts Visibility Filtering : Only shows original posts requesting user can see Privacy Respected : Follows same visibility rules as original posts Blocking : Hidden if original author blocked requesting user 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 : Single vs Multiple : Respects poll's allowMultipleVotes setting Vote Changes : Allowed only if allowVoteChange is true Expiration : Cannot vote on expired polls Visibility : Must have access to view post Blocking : Cannot vote on polls from blocked users Option Validation : All optionIds must belong to this poll Single Vote Mode : If allowMultipleVotes false, only 1 optionId allowed Multiple Vote Mode : If allowMultipleVotes true, can select multiple options Anonymous : If isAnonymous true, voter identity hidden 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 : Vote Change Required : Only works if allowVoteChange is true Complete Removal : Removes ALL votes (if multiple vote poll) Idempotent : Safe to call if not voted Expired Polls : Can remove votes even after expiration Counter Updates : All affected option counts decremented 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 : Visibility : Must have access to view parent post Real-Time : Results update immediately after each vote Percentages : Calculated as (optionVotes / totalVotes) × 100 User State : Shows which options current user voted for Expiration Check : Indicates if poll has expired Zero Votes : Shows 0.0% for options with no votes Anonymous Respect : Voter identities hidden if isAnonymous true 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 (All Options) Purpose : Get a paginated list of all unique users who voted on a poll, across all options Endpoint : GET {base_url}/e-social/posts/{postId}/poll-voters Access Level : 🔒 Protected (Requires Bearer Token Authentication) Authentication : Bearer Token Behavior : Returns a deduplicated, paginated list of users who voted on this poll Only available for non-anonymous polls ( isAnonymous = false ) Accessible by any authenticated user (no author/collaborator restriction) Requires secondary onboarding completion (username + profile picture) Each voter entry includes follow relationship context ( youFollow , followsYou ) Deduplicates voters who voted on multiple options — one entry per unique voter Default page size is 5 Business Rules : Non-Anonymous Only : Returns error if isAnonymous = true Any Authenticated User : No author/collaborator restriction Secondary Onboarding Required : Caller must have username + profilePic set Deduplication : Users who voted on multiple options appear only once Follow Status : Response reflects the calling user's follow relationship with each voter Pagination : Default 5 voters per page, configurable via query params Request Headers : Header Type Required Description Authorization string Yes Bearer token for authentication Content-Type string Yes Must be application/json Path Parameters : Parameter Type Required Description Validation postId string Yes UUID of the poll post Must be valid UUID format Query Parameters : Parameter Type Required Description Validation Default page integer No Page number (1-indexed) Min: 1 1 size integer No Items per page Min: 1 5 Success Response JSON Sample : { "success": true, "httpStatus": "OK", "message": "Poll voters retrieved successfully", "action_time": "2025-12-11T10:30:45", "data": { "voters": [ { "userId": "123e4567-e89b-12d3-a456-426614174000", "displayName": "John Doe", "userName": "johndoe", "profileImageUrl": "https://cdn.nexgate.com/profiles/johndoe.jpg", "youFollow": true, "followsYou": false }, { "userId": "987e6543-e21b-12d3-a456-426614174999", "displayName": "Jane Smith", "userName": "janesmith", "profileImageUrl": "https://cdn.nexgate.com/profiles/janesmith.jpg", "youFollow": false, "followsYou": true } ], "totalElements": 42, "totalPages": 9, "hasNext": true, "hasPrevious": false, "isFirst": true, "isLast": false, "currentPage": 1 } } Response Fields Explained : Field Type Description voters array Paginated list of unique voters across all poll options voters[].userId string UUID of the voter voters[].displayName string Voter's full display name voters[].userName string Voter's unique username voters[].profileImageUrl string URL to voter's profile picture voters[].youFollow boolean Whether the calling user follows this voter voters[].followsYou boolean Whether this voter follows the calling user totalElements integer Total number of unique voters across all pages totalPages integer Total number of pages hasNext boolean Whether a next page exists hasPrevious boolean Whether a previous page exists isFirst boolean Whether this is the first page isLast boolean Whether this is the last page currentPage integer Current page number (1-indexed) Success Response Message : "Poll voters retrieved successfully" Standard Error Types : 400 BAD_REQUEST : Poll is anonymous — voter list not available 401 UNAUTHORIZED : Authentication required 403 FORBIDDEN : Secondary onboarding not complete 404 NOT_FOUND : Post not found or not a poll post 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." } Secondary Onboarding Incomplete (403): { "success": false, "httpStatus": "FORBIDDEN", "message": "Profile incomplete", "action_time": "2025-12-11T10:30:45", "data": "Please complete your profile setup (username and profile picture) to access this feature." } Use Case Examples : Example 1: View All Voters — First Page GET /e-social/posts/550e8400-e29b-41d4-a716-446655440000/poll-voters Poll is non-anonymous, 42 unique voters across all options Result: Returns first 5 voters with follow relationship context Example 2: Custom Page Size GET /e-social/posts/550e8400-e29b-41d4-a716-446655440000/poll-voters?page=2&size=10 Result: Returns voters 11–20 Example 3: Anonymous Poll GET /e-social/posts/770e8400-e29b-41d4-a716-446655440002/poll-voters Poll has isAnonymous = true Result: Error 400 — Voter identities hidden for anonymous polls Example 4: User Voted on Multiple Options (Deduplication) GET /e-social/posts/880e8400-e29b-41d4-a716-446655440003/poll-voters User voted on 3 options in a multiple-vote poll Result: User appears only once in the deduplicated voter list 43. Get Poll Voters by Option Purpose : Get list of users who voted for a specific poll option (post author/collaborators only, non-anonymous polls only) Endpoint : GET {base_url}/e-social/posts/{postId}/poll-voters/{optionId} Access Level : 🔒 Protected (Requires Bearer Token Authentication + Post Author/Collaborator) Authentication : Bearer Token Behavior : Returns list of users who voted for a 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 : Non-Anonymous Only : Only works if isAnonymous = false Author/Collaborator Access : Only post author and collaborators can view Privacy Protection : Regular users cannot see who voted per option Vote Time : Includes when each user voted Profile Info : Returns basic user profile (name, photo, verified status) Pagination : Default 50 voters per page Current Votes : Shows current votes (if user changed vote, shows new choice) Request Headers : Header Type Required Description Authorization string Yes Bearer token for authentication Content-Type string Yes Must be application/json Path Parameters : Parameter Type Required Description Validation postId string Yes UUID of the poll post Must be valid UUID format optionId string Yes UUID of the poll option Must belong to this poll Query Parameters : Parameter Type Required Description Validation Default page integer No Page number (1-indexed) Min: 1 1 size integer No Items per page Min: 1, Max: 100 50 Success Response JSON Sample : { "success": true, "httpStatus": "OK", "message": "Voters retrieved successfully", "action_time": "2025-12-11T10:30:45", "data": { "pollId": "poll-uuid", "pollTitle": "What's your favorite programming language?", "optionId": "option-uuid-1", "optionText": "Python", "totalVoters": 75, "voters": [ { "userId": "123e4567-e89b-12d3-a456-426614174000", "userName": "john_doe", "firstName": "John", "lastName": "Doe", "profilePictureUrl": "https://cdn.nexgate.com/profiles/john_doe.jpg", "isVerified": true, "votedAt": "2025-12-11T10:25:30" }, { "userId": "987e6543-e21b-12d3-a456-426614174999", "userName": "jane_smith", "firstName": "Jane", "lastName": "Smith", "profilePictureUrl": "https://cdn.nexgate.com/profiles/jane_smith.jpg", "isVerified": false, "votedAt": "2025-12-11T10:20:15" } ], "pagination": { "currentPage": 1, "pageSize": 50, "totalPages": 2, "totalElements": 75, "hasNext": true, "hasPrevious": false } } } Response Fields Explained : Field Type Description pollId string UUID of the poll pollTitle string Poll question/title optionId string UUID of the queried option optionText string Text of the queried option totalVoters integer Total voters for this specific option voters array Paginated list of users who voted for this option voters[].userId string UUID of the voter voters[].userName string Voter's unique username voters[].firstName string Voter's first name voters[].lastName string Voter's last name voters[].profilePictureUrl string URL to voter's profile picture voters[].isVerified boolean Whether voter's account is verified voters[].votedAt string ISO 8601 datetime when this user voted pagination.currentPage integer Current page number (1-indexed) pagination.pageSize integer Number of items per page pagination.totalPages integer Total number of pages pagination.totalElements integer Total voters for this option pagination.hasNext boolean Whether a next page exists pagination.hasPrevious boolean Whether a previous page exists Success Response Message : "Voters retrieved successfully" Standard Error Types : 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 or Collaborator (403): { "success": false, "httpStatus": "FORBIDDEN", "message": "Access denied", "action_time": "2025-12-11T10:30:45", "data": "Only the post author and collaborators can view voter lists" } Use Case Examples : Example 1: View Voters for a Specific Option as Post Author GET /e-social/posts/550e8400-e29b-41d4-a716-446655440000/poll-voters/option-uuid-1 User is post author Poll is non-anonymous, option has 75 voters Result: Returns paginated list of users who voted for this specific option Example 2: View Voters as Collaborator GET /e-social/posts/660e8400-e29b-41d4-a716-446655440001/poll-voters/option-uuid-2 User is accepted collaborator Poll is non-anonymous Result: Returns voter list (collaborators have same access as author) Example 3: Anonymous Poll — Access Denied GET /e-social/posts/770e8400-e29b-41d4-a716-446655440002/poll-voters/option-uuid-3 User is post author Poll is anonymous (isAnonymous = true) Result: Error 400 — Voter identities hidden for anonymous polls Example 4: Regular User — Access Denied GET /e-social/posts/880e8400-e29b-41d4-a716-446655440003/poll-voters/option-uuid-1 User is neither author nor collaborator Poll is non-anonymous Result: Error 403 — Only author/collaborators can view voters per option Comment Endpoints (43-52) 43. Create Comment Purpose : Create a comment or reply on a post Endpoint : POST {base_url}/e-social/posts/{postId}/comments Access Level : 🔒 Protected (Requires Bearer Token Authentication) Authentication : Bearer Token Behavior : 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 : Permission Check : Post must allow comments (whoCanComment setting) Visibility Check : Must have permission to view post to comment Blocking : Cannot comment on posts from blocked users Nesting : Supports unlimited reply depth (replies to replies to replies...) Mentions : All @mentioned users notified Notification : Post author and parent comment author notified Content Length : Min 1, Max 2000 characters Spam Prevention : Rate limited (max 10 comments per minute per user) Edit Window : Can edit within 15 minutes of posting 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 : Top-Level Only : Returns only direct comments on post, not replies Pinned Priority : Pinned comments always appear first Sorting : After pinned, sorted by newest first Reply Count : Each comment shows number of replies Pagination : Default 20 per page, max 100 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 : Visibility : Must be able to view parent post Deleted : Returns 404 if comment deleted Full Details : Includes all engagement metrics 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 : Direct Replies Only : Returns immediate children, not grandchildren Conversation Order : Sorted oldest first (chronological conversation) Nested Support : Each reply shows its own replyCount Recursive Loading : Frontend loads nested replies on-demand 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 : Author Only : Only comment author can edit Time Window : Can only edit within 15 minutes of creation Edit Flag : isEdited set to true (visible to users) Content Validation : Same rules as creation (1-2000 chars) Mention Updates : New mentions trigger notifications 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 : Who Can Delete : Comment author OR post author Soft Delete : Data retained in database Replies Preserved : Child replies remain visible Parent Reference : Replies show "[deleted]" as parent content Counter Update : Post's comment count decremented Cascade Option : Post author can cascade delete all replies (optional) 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 : Post Author Only : Only post author/collaborators can pin Single Pin : Only 1 comment pinned at a time Auto-Unpin : Pinning new comment unpins previous Top-Level Only : Can only pin top-level comments (not replies) Notification : Comment author notified of pin 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 : Post Author Only : Only post author/collaborators can unpin Silent Operation : No notification sent Idempotent : Safe to call on non-pinned comments 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 : Visibility : Must have access to parent post Blocking : Cannot like comments from blocked users Deleted : Cannot like deleted comments Idempotent : Safe to call multiple times Notification : Comment author notified (unless self-like) 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 : Silent Operation : No notification sent Always Allowed : Can unlike even if blocked or comment deleted Idempotent : Safe to call multiple times 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 53. Share Post Purpose : Record a post share action and track which platform was used for sharing Endpoint : POST {base_url}/api/v1/e-social/posts/{postId}/share Access Level : 🔒 Protected (Requires Authentication) Authentication : Bearer Token Request Headers : Header Type Required Description Authorization string Yes Bearer token for authentication Path Parameters : Parameter Type Required Description Validation postId UUID Yes Unique identifier of the post to share Valid UUID format Query Parameters : Parameter Type Required Description Validation Default platform string No Platform where the post is being shared Enum: WHATSAPP, TWITTER, FACEBOOK, INSTAGRAM, TELEGRAM, COPY_LINK, OTHER , IN_APP OTHER Success Response JSON Sample : { "success": true, "httpStatus": "OK", "message": "Post shared successfully", "action_time": "2025-12-29T14:30:45", "data": null } Success Response Fields : Field Description success Indicates if the share was recorded successfully message Confirmation message Error Response JSON Samples : Post Not Found: { "success": false, "httpStatus": "BAD_REQUEST", "message": "Post not found", "action_time": "2025-12-29T14:30:45", "data": null } Post Not Published: { "success": false, "httpStatus": "BAD_REQUEST", "message": "Can only share published posts", "action_time": "2025-12-29T14:30:45", "data": null } Unauthorized: { "success": false, "httpStatus": "UNAUTHORIZED", "message": "User not authenticated", "action_time": "2025-12-29T14:30:45", "data": null } Standard Error Types : 400 BAD_REQUEST : Post not found or post is not published 401 UNAUTHORIZED : Missing or invalid authentication token Share Platform Values : Platform Description WHATSAPP Shared via WhatsApp TWITTER Shared via Twitter/X FACEBOOK Shared via Facebook INSTAGRAM Shared via Instagram TELEGRAM Shared via Telegram COPY_LINK User copied the post link OTHER Shared via other means or unspecified Usage Notes : Unlike likes and bookmarks, shares can be recorded multiple times by the same user Each share is tracked separately for analytics purposes The share count on the post increments with each share action Invalid platform values default to OTHER Usage Examples : # Share post to WhatsApp curl -X POST "{base_url}/api/v1/e-social/posts/550e8400-e29b-41d4-a716-446655440000/share?platform=WHATSAPP" \ -H "Authorization: Bearer {token}" # Share post to Twitter curl -X POST "{base_url}/api/v1/e-social/posts/550e8400-e29b-41d4-a716-446655440000/share?platform=TWITTER" \ -H "Authorization: Bearer {token}" # Record copy link action curl -X POST "{base_url}/api/v1/e-social/posts/550e8400-e29b-41d4-a716-446655440000/share?platform=COPY_LINK" \ -H "Authorization: Bearer {token}" # Generic share (defaults to OTHER) curl -X POST "{base_url}/api/v1/e-social/posts/550e8400-e29b-41d4-a716-446655440000/share" \ -H "Authorization: Bearer {token}" Response in Post Object : After sharing, the post's engagement and user interaction data will reflect the share: { "engagement": { "likesCount": 42, "commentsCount": 15, "repostsCount": 8, "quotesCount": 3, "bookmarksCount": 12, "sharesCount": 25, "viewsCount": 1500, "canLike": true, "canComment": true, "canRepost": true, "canShare": true }, "userInteraction": { "hasLiked": true, "hasBookmarked": false, "hasReposted": false, "hasCommented": true, "hasViewed": true, "hasShared": true } } 54. Report Post Purpose : Report a post for violating community guidelines or platform rules Endpoint : POST {base_url}/api/v1/e-social/posts/{postId}/report Access Level : 🔒 Protected (Requires Authentication) Authentication : Bearer Token Request Headers : Header Type Required Description Authorization string Yes Bearer token for authentication Path Parameters : Parameter Type Required Description Validation postId UUID Yes Unique identifier of the post to report Valid UUID format Request JSON Sample : { "reason": "HATE_SPEECH", "description": "This post contains discriminatory language targeting a specific group." } Request Body Parameters : Parameter Type Required Description Validation reason string Yes Reason for reporting Enum: SPAM, MISLEADING_INFO, FALSE_INFORMATION, HATE_SPEECH, HARASSMENT, BULLYING, THREATS, NUDITY, SEXUAL_CONTENT, VIOLENCE, GRAPHIC_CONTENT, ILLEGAL_GOODS, FRAUD, SCAM, INTELLECTUAL_PROPERTY, SELF_HARM, SUICIDE, PRIVACY_VIOLATION, PERSONAL_INFO_EXPOSED, IMPERSONATION, FAKE_ACCOUNT, UNDERAGE_USER, OTHER description string No Additional details about the report Max 1000 characters Success Response JSON Sample : { "success": true, "httpStatus": "OK", "message": "Post reported successfully", "action_time": "2025-12-29T15:30:45", "data": null } Success Response Fields : Field Description success Indicates if the report was submitted successfully message Confirmation message Error Response JSON Sample : { "success": false, "httpStatus": "BAD_REQUEST", "message": "You have already reported this post", "action_time": "2025-12-29T15:30:45", "data": null } Standard Error Types : 400 BAD_REQUEST : Post not found, already reported, or attempting to report own post 401 UNAUTHORIZED : Missing or invalid authentication token 55. Get Post Reports (Admin) Purpose : Retrieve all reports for a specific post (Admin only) Endpoint : GET {base_url}/api/v1/e-social/posts/{postId}/reports Access Level : 🔒 Protected (Admin Only) Authentication : Bearer Token (Admin role required) Request Headers : Header Type Required Description Authorization string Yes Bearer token for admin authentication Path Parameters : Parameter Type Required Description Validation postId UUID Yes Unique identifier of the post Valid UUID format Query Parameters : Parameter Type Required Description Validation Default page integer No Page number for pagination Min: 1 1 size integer No Number of results per page Min: 1, Max: 100 20 Success Response JSON Sample : { "success": true, "httpStatus": "OK", "message": "Post reports retrieved successfully", "action_time": "2025-12-29T15:30:45", "data": { "content": [ { "id": "550e8400-e29b-41d4-a716-446655440000", "postId": "660e8400-e29b-41d4-a716-446655440001", "reporter": { "id": "770e8400-e29b-41d4-a716-446655440002", "userName": "john_doe", "firstName": "John", "lastName": "Doe", "profilePictureUrl": "https://storage.example.com/profiles/john.jpg" }, "postAuthor": { "id": "880e8400-e29b-41d4-a716-446655440003", "userName": "jane_smith", "firstName": "Jane", "lastName": "Smith", "profilePictureUrl": "https://storage.example.com/profiles/jane.jpg" }, "reason": "HATE_SPEECH", "description": "This post contains discriminatory language", "status": "PENDING", "review": null, "createdAt": "2025-12-29T14:00:00", "updatedAt": "2025-12-29T14:00:00" }, { "id": "550e8400-e29b-41d4-a716-446655440099", "postId": "660e8400-e29b-41d4-a716-446655440001", "reporter": { "id": "990e8400-e29b-41d4-a716-446655440004", "userName": "alex_wilson", "firstName": "Alex", "lastName": "Wilson", "profilePictureUrl": null }, "postAuthor": { "id": "880e8400-e29b-41d4-a716-446655440003", "userName": "jane_smith", "firstName": "Jane", "lastName": "Smith", "profilePictureUrl": "https://storage.example.com/profiles/jane.jpg" }, "reason": "HARASSMENT", "description": "Targeted harassment in the comments", "status": "ACTION_TAKEN", "review": { "reviewedBy": "aa0e8400-e29b-41d4-a716-446655440005", "reviewerName": "Admin User", "reviewedAt": "2025-12-29T15:00:00", "adminNotes": "Verified harassment, post removed", "actionTaken": "POST_REMOVED" }, "createdAt": "2025-12-29T13:00:00", "updatedAt": "2025-12-29T15:00:00" } ], "pageable": { "pageNumber": 0, "pageSize": 20, "sort": { "empty": true, "sorted": false, "unsorted": true }, "offset": 0, "paged": true, "unpaged": false }, "last": true, "totalPages": 1, "totalElements": 2, "first": true, "size": 20, "number": 0, "numberOfElements": 2, "empty": false } } Success Response Fields : Field Description content Array of report objects for the post content[].id Unique identifier of the report content[].postId ID of the reported post content[].reporter Information about the user who filed the report content[].postAuthor Information about the post author content[].reason Reason for the report content[].description Additional details provided by reporter content[].status Current status of the report content[].review Review information if report has been reviewed totalElements Total number of reports for this post Error Response JSON Sample : { "success": false, "httpStatus": "FORBIDDEN", "message": "Access denied", "action_time": "2025-12-29T15:30:45", "data": null } Standard Error Types : 401 UNAUTHORIZED : Missing or invalid authentication token 403 FORBIDDEN : User does not have admin role 56. Get All Reports (Admin) Purpose : Retrieve all reports with optional filters for status, reason, and date range (Admin only) Endpoint : GET {base_url}/api/v1/e-social/posts/reports Access Level : 🔒 Protected (Admin Only) Authentication : Bearer Token (Admin role required) Request Headers : Header Type Required Description Authorization string Yes Bearer token for admin authentication Query Parameters : Parameter Type Required Description Validation Default status string No Filter by report status Enum: PENDING, UNDER_REVIEW, ACTION_TAKEN, DISMISSED, ESCALATED null (all) reason string No Filter by report reason Enum: SPAM, MISLEADING_INFO, FALSE_INFORMATION, HATE_SPEECH, HARASSMENT, BULLYING, THREATS, NUDITY, SEXUAL_CONTENT, VIOLENCE, GRAPHIC_CONTENT, ILLEGAL_GOODS, FRAUD, SCAM, INTELLECTUAL_PROPERTY, SELF_HARM, SUICIDE, PRIVACY_VIOLATION, PERSONAL_INFO_EXPOSED, IMPERSONATION, FAKE_ACCOUNT, UNDERAGE_USER, OTHER null (all) startDate datetime No Filter reports created after this date ISO 8601 format null endDate datetime No Filter reports created before this date ISO 8601 format null page integer No Page number for pagination Min: 1 1 size integer No Number of results per page Min: 1, Max: 100 20 Success Response JSON Sample : { "success": true, "httpStatus": "OK", "message": "Reports retrieved successfully", "action_time": "2025-12-29T15:30:45", "data": { "content": [ { "id": "550e8400-e29b-41d4-a716-446655440000", "postId": "660e8400-e29b-41d4-a716-446655440001", "reporter": { "id": "770e8400-e29b-41d4-a716-446655440002", "userName": "john_doe", "firstName": "John", "lastName": "Doe", "profilePictureUrl": "https://storage.example.com/profiles/john.jpg" }, "postAuthor": { "id": "880e8400-e29b-41d4-a716-446655440003", "userName": "jane_smith", "firstName": "Jane", "lastName": "Smith", "profilePictureUrl": "https://storage.example.com/profiles/jane.jpg" }, "reason": "SPAM", "description": "This account is posting spam content repeatedly", "status": "PENDING", "review": null, "createdAt": "2025-12-29T14:00:00", "updatedAt": "2025-12-29T14:00:00" } ], "pageable": { "pageNumber": 0, "pageSize": 20, "sort": { "empty": true, "sorted": false, "unsorted": true }, "offset": 0, "paged": true, "unpaged": false }, "last": true, "totalPages": 1, "totalElements": 1, "first": true, "size": 20, "number": 0, "numberOfElements": 1, "empty": false } } Success Response Fields : Field Description content Array of report objects matching the filters content[].id Unique identifier of the report content[].postId ID of the reported post content[].reporter Information about the user who filed the report content[].postAuthor Information about the post author content[].reason Reason for the report content[].status Current status: PENDING, UNDER_REVIEW, ACTION_TAKEN, DISMISSED, ESCALATED totalElements Total number of matching reports totalPages Total number of pages Error Response JSON Sample : { "success": false, "httpStatus": "FORBIDDEN", "message": "Access denied", "action_time": "2025-12-29T15:30:45", "data": null } Standard Error Types : 401 UNAUTHORIZED : Missing or invalid authentication token 403 FORBIDDEN : User does not have admin role 57. Review Report (Admin) Purpose : Review and update the status of a report (Admin only) Endpoint : PATCH {base_url}/api/v1/e-social/posts/reports/{reportId}/review Access Level : 🔒 Protected (Admin Only) Authentication : Bearer Token (Admin role required) Request Headers : Header Type Required Description Authorization string Yes Bearer token for admin authentication Path Parameters : Parameter Type Required Description Validation reportId UUID Yes Unique identifier of the report Valid UUID format Request JSON Sample : { "status": "ACTION_TAKEN", "adminNotes": "Verified hate speech violation. Post has been removed and user warned.", "actionTaken": "POST_REMOVED_USER_WARNED" } Request Body Parameters : Parameter Type Required Description Validation status string Yes New status for the report Enum: PENDING, UNDER_REVIEW, ACTION_TAKEN, DISMISSED, ESCALATED adminNotes string No Internal notes about the review Max 500 characters actionTaken string No Description of action taken Max 50 characters Success Response JSON Sample : { "success": true, "httpStatus": "OK", "message": "Report reviewed successfully", "action_time": "2025-12-29T16:00:00", "data": { "id": "550e8400-e29b-41d4-a716-446655440000", "postId": "660e8400-e29b-41d4-a716-446655440001", "reporter": { "id": "770e8400-e29b-41d4-a716-446655440002", "userName": "john_doe", "firstName": "John", "lastName": "Doe", "profilePictureUrl": "https://storage.example.com/profiles/john.jpg" }, "postAuthor": { "id": "880e8400-e29b-41d4-a716-446655440003", "userName": "jane_smith", "firstName": "Jane", "lastName": "Smith", "profilePictureUrl": "https://storage.example.com/profiles/jane.jpg" }, "reason": "HATE_SPEECH", "description": "This post contains discriminatory language", "status": "ACTION_TAKEN", "review": { "reviewedBy": "aa0e8400-e29b-41d4-a716-446655440005", "reviewerName": "Admin User", "reviewedAt": "2025-12-29T16:00:00", "adminNotes": "Verified hate speech violation. Post has been removed and user warned.", "actionTaken": "POST_REMOVED_USER_WARNED" }, "createdAt": "2025-12-29T14:00:00", "updatedAt": "2025-12-29T16:00:00" } } Success Response Fields : Field Description id Unique identifier of the report postId ID of the reported post reporter Information about the user who filed the report postAuthor Information about the post author reason Reason for the report status Updated status of the report review Review details including reviewer info, notes, and action taken review.reviewedBy UUID of the admin who reviewed review.reviewerName Name of the admin who reviewed review.reviewedAt Timestamp of the review review.adminNotes Internal notes from the admin review.actionTaken Action taken on the report Error Response JSON Sample : { "success": false, "httpStatus": "BAD_REQUEST", "message": "Report not found", "action_time": "2025-12-29T16:00:00", "data": null } Standard Error Types : 400 BAD_REQUEST : Report not found or invalid status 401 UNAUTHORIZED : Missing or invalid authentication token 403 FORBIDDEN : User does not have admin role 58. Get Report Statistics (Admin) Purpose : Retrieve aggregate statistics about reports (Admin only) Endpoint : GET {base_url}/api/v1/e-social/posts/reports/stats Access Level : 🔒 Protected (Admin Only) Authentication : Bearer Token (Admin role required) Request Headers : Header Type Required Description Authorization string Yes Bearer token for admin authentication Success Response JSON Sample : { "success": true, "httpStatus": "OK", "message": "Report statistics retrieved successfully", "action_time": "2025-12-29T16:30:00", "data": { "totalReports": 1250, "pendingReports": 45, "underReviewReports": 12, "actionTakenReports": 890, "dismissedReports": 298, "escalatedReports": 5, "reportsByReason": { "SPAM": 320, "HATE_SPEECH": 180, "HARASSMENT": 150, "MISLEADING_INFO": 120, "NUDITY": 95, "VIOLENCE": 85, "SCAM": 75, "FALSE_INFORMATION": 60, "BULLYING": 55, "SEXUAL_CONTENT": 40, "PRIVACY_VIOLATION": 30, "IMPERSONATION": 20, "OTHER": 20 } } } Success Response Fields : Field Description totalReports Total number of reports in the system pendingReports Number of reports awaiting review underReviewReports Number of reports currently being reviewed actionTakenReports Number of reports where action was taken dismissedReports Number of reports that were dismissed escalatedReports Number of reports escalated for further review reportsByReason Object containing count of reports grouped by reason Error Response JSON Sample : { "success": false, "httpStatus": "FORBIDDEN", "message": "Access denied", "action_time": "2025-12-29T16:30:00", "data": null } Standard Error Types : 401 UNAUTHORIZED : Missing or invalid authentication token 403 FORBIDDEN : User does not have admin role 59. Edit Published Post Purpose : Edit a published post within the 60-minute edit window (max 3 edits) Endpoint : PUT {base_url}/e-social/posts/{postId}/edit Access Level : 🔒 Protected (Post owner only) Authentication : Bearer Token Request Headers : Header Type Required Description Authorization string Yes Bearer token for authentication Path Parameters : Parameter Type Required Description Validation postId UUID Yes ID of the post to edit Must be valid UUID, post must exist Request JSON Sample (Regular/Quote Post) : { "content": "Updated post content! 🔥", "media": [ { "mediaType": "IMAGE", "mediaUrl": "https://cdn.nexgate.it/new-image.jpg", "placeholderBase64": "data:image/jpeg;base64,/9j/4AAQ...", "width": 1080, "height": 1080 } ], "attachments": { "productIds": ["550e8400-e29b-41d4-a716-446655440001"], "shopIds": ["550e8400-e29b-41d4-a716-446655440002"], "eventIds": [], "buyTogetherGroupIds": null, "installmentPlanIds": null, "externalLink": { "url": "https://example.com/new-link" }, "removeExternalLink": false }, "collaboration": { "collaboratorIds": ["550e8400-e29b-41d4-a716-446655440003"] }, "privacySettings": { "visibility": "PUBLIC", "whoCanComment": "FOLLOWERS", "whoCanRepost": "EVERYONE", "hideLikesCount": false, "hideCommentsCount": false } } Request JSON Sample (Poll Post - Limited Fields) : { "content": "Updated poll question context", "pollTitle": "Updated Poll Title", "pollDescription": "Updated poll description", "privacySettings": { "visibility": "PUBLIC", "whoCanComment": "EVERYONE" } } Request Body Parameters : Parameter Type Required Description Validation content string No Updated post text content Max: 5000 characters media array No Updated media attachments Max: 10 items media[].mediaType string Yes* Type of media enum: IMAGE, VIDEO, GIF media[].mediaUrl string Yes* URL to media file Valid URL media[].placeholderBase64 string No BlurHash placeholder Base64 encoded media[].width integer No Media width in pixels Min: 1 media[].height integer No Media height in pixels Min: 1 media[].duration integer No Video duration in seconds Min: 1 (videos only) attachments object No Updated attachments See attachment behavior below attachments.productIds array No Product IDs to attach null=no change, []=remove all attachments.shopIds array No Shop IDs to attach null=no change, []=remove all attachments.eventIds array No Event IDs to attach null=no change, []=remove all attachments.buyTogetherGroupIds array No Buy Together Group IDs null=no change, []=remove all attachments.installmentPlanIds array No Installment Plan IDs null=no change, []=remove all attachments.externalLink object No External link to attach null=no change attachments.externalLink.url string Yes* URL of external link Valid URL attachments.removeExternalLink boolean No Remove existing external link Default: false collaboration object No Updated collaboration settings collaboration.collaboratorIds array No User IDs to invite as collaborators Valid user UUIDs privacySettings object No Updated privacy settings privacySettings.visibility string No Post visibility enum: PUBLIC, FOLLOWERS, MENTIONED, PRIVATE privacySettings.whoCanComment string No Comment permissions enum: EVERYONE, FOLLOWERS, MENTIONED, DISABLED privacySettings.whoCanRepost string No Repost permissions enum: EVERYONE, FOLLOWERS, DISABLED privacySettings.hideLikesCount boolean No Hide likes count Default: false privacySettings.hideCommentsCount boolean No Hide comments count Default: false pollTitle string No Poll title (poll posts only) Max: 200 characters pollDescription string No Poll description (poll posts only) Max: 1000 characters Attachment Edit Behavior : Field Value Behavior null No change to that attachment type [] (empty array) Remove all attachments of that type [ids...] Replace with new attachment IDs Collaboration Edit Behavior : Collaborator Status Behavior ACCEPTED Preserved (cannot be removed via edit) PENDING Can be removed DECLINED Can be removed New IDs Added as PENDING status Poll Post Restrictions : Field Can Edit content ✅ Yes pollTitle ✅ Yes pollDescription ✅ Yes privacySettings ✅ Yes Poll options ❌ No (would invalidate votes) media ❌ No attachments ❌ No Success Response JSON Sample : { "success": true, "httpStatus": "OK", "message": "Post edited successfully", "action_time": "2025-01-03T10:30:45", "data": { "id": "550e8400-e29b-41d4-a716-446655440000", "author": { "id": "660e8400-e29b-41d4-a716-446655440000", "userName": "johndoe", "displayName": "John Doe", "profileImage": "https://cdn.nexgate.it/profiles/johndoe.jpg", "isVerified": true }, "content": "Updated post content! 🔥", "postType": "REGULAR", "status": "PUBLISHED", "editInfo": { "isEdited": true, "editCount": 1, "canEdit": true, "lastEditedAt": "2025-01-03T10:30:45" }, "createdAt": "2025-01-03T10:00:00", "publishedAt": "2025-01-03T10:00:00" } } Success Response Fields : Field Description id Post UUID author Post author details content Updated post content postType Type of post (REGULAR, POLL, QUOTE, REPOST) status Post status (always PUBLISHED for edited posts) editInfo.isEdited Whether post has been edited editInfo.editCount Number of times post has been edited editInfo.canEdit Whether current user can still edit editInfo.lastEditedAt Timestamp of last edit Error Response Examples : Not Post Owner (400): { "success": false, "httpStatus": "BAD_REQUEST", "message": "You can only edit your own posts", "action_time": "2025-01-03T10:30:45", "data": "You can only edit your own posts" } Edit Limit Reached (400): { "success": false, "httpStatus": "BAD_REQUEST", "message": "Maximum edit limit reached. You can only edit a post 3 times.", "action_time": "2025-01-03T10:30:45", "data": "Maximum edit limit reached. You can only edit a post 3 times." } Edit Window Expired (400): { "success": false, "httpStatus": "BAD_REQUEST", "message": "Edit window has expired. Posts can only be edited within 60 minutes of publishing.", "action_time": "2025-01-03T10:30:45", "data": "Edit window has expired. Posts can only be edited within 60 minutes of publishing." } Post Not Published (400): { "success": false, "httpStatus": "BAD_REQUEST", "message": "Only published posts can be edited", "action_time": "2025-01-03T10:30:45", "data": "Only published posts can be edited" } Post Not Found (404): { "success": false, "httpStatus": "NOT_FOUND", "message": "Post not found", "action_time": "2025-01-03T10:30:45", "data": "Post not found" } Unauthorized (401): { "success": false, "httpStatus": "UNAUTHORIZED", "message": "Token has expired", "action_time": "2025-01-03T10:30:45", "data": "Token has expired" } 60. Get Post Edit Info Purpose : Get detailed edit status and eligibility information for a post Endpoint : GET {base_url}/e-social/posts/{postId}/edit-info Access Level : 🔒 Protected Authentication : Bearer Token Request Headers : Header Type Required Description Authorization string Yes Bearer token for authentication Path Parameters : Parameter Type Required Description Validation postId UUID Yes ID of the post Must be valid UUID, post must exist Success Response JSON Sample : { "success": true, "httpStatus": "OK", "message": "Post edit info retrieved successfully", "action_time": "2025-01-03T10:30:45", "data": { "postId": "550e8400-e29b-41d4-a716-446655440000", "isEdited": true, "editCount": 2, "maxEdits": 3, "remainingEdits": 1, "canEdit": true, "cannotEditReason": null, "publishedAt": "2025-01-03T10:00:00", "editWindowExpiresAt": "2025-01-03T11:00:00", "lastEditedAt": "2025-01-03T10:30:00", "minutesRemainingInWindow": 25 } } Success Response Fields : Field Description postId Post UUID isEdited Whether post has been edited at least once editCount Number of times post has been edited (0-3) maxEdits Maximum allowed edits (always 3) remainingEdits Edits remaining (maxEdits - editCount) canEdit Whether current user can edit this post now cannotEditReason Reason why editing is not allowed (null if canEdit is true) publishedAt When the post was originally published editWindowExpiresAt When the 60-minute edit window expires lastEditedAt Timestamp of most recent edit (null if never edited) minutesRemainingInWindow Minutes left in edit window (0 if expired) Cannot Edit Reasons : Reason Description "Authentication required" User not logged in "Only the author can edit this post" Current user is not the post owner "Only published posts can be edited" Post is in DRAFT or SCHEDULED status "Maximum edit limit reached (3 edits)" All 3 edits have been used "Edit window expired (60 minutes after publishing)" More than 60 minutes since publishing Error Response Examples : Post Not Found (404): { "success": false, "httpStatus": "NOT_FOUND", "message": "Post not found", "action_time": "2025-01-03T10:30:45", "data": "Post not found" } 61. Get Post Edit History Purpose : View complete edit history with immutable snapshots of each version Endpoint : GET {base_url}/e-social/posts/{postId}/edit-history Access Level : 🌐 Public (Anyone can view edit history of public posts) Authentication : Bearer Token (Optional - required for non-public posts) Request Headers : Header Type Required Description Authorization string No Bearer token for accessing non-public posts Path Parameters : Parameter Type Required Description Validation postId UUID Yes ID of the post Must be valid UUID, post must exist Success Response JSON Sample : { "success": true, "httpStatus": "OK", "message": "Post edit history retrieved successfully", "action_time": "2025-01-03T10:45:00", "data": { "postId": "550e8400-e29b-41d4-a716-446655440000", "totalEdits": 2, "remainingEdits": 1, "canStillEdit": true, "editWindowExpiresAt": "2025-01-03T11:00:00", "versions": [ { "id": "770e8400-e29b-41d4-a716-446655440001", "version": 0, "snapshot": { "content": "Original post content", "media": [ { "id": "m1", "mediaType": "IMAGE", "originalUrl": "https://cdn.nexgate.it/original.jpg", "placeholderBase64": "data:image/jpeg;base64,...", "width": 1080, "height": 1080 } ], "attachments": { "productIds": ["550e8400-e29b-41d4-a716-446655440111"], "shopIds": [], "eventIds": [], "buyTogetherGroupIds": [], "installmentPlanIds": [], "externalLink": null }, "collaboratorIds": [], "privacySettings": { "visibility": "PUBLIC", "whoCanComment": "EVERYONE", "whoCanRepost": "EVERYONE", "hideLikesCount": false, "hideCommentsCount": false }, "pollTitle": null, "pollDescription": null }, "editedAt": "2025-01-03T10:15:00", "isCurrent": false }, { "id": "770e8400-e29b-41d4-a716-446655440002", "version": 1, "snapshot": { "content": "First edit - added more details!", "media": [ { "id": "m1", "mediaType": "IMAGE", "originalUrl": "https://cdn.nexgate.it/original.jpg" }, { "id": "m2", "mediaType": "IMAGE", "originalUrl": "https://cdn.nexgate.it/new-image.jpg" } ], "attachments": { "productIds": ["550e8400-e29b-41d4-a716-446655440111", "550e8400-e29b-41d4-a716-446655440222"], "shopIds": ["550e8400-e29b-41d4-a716-446655440333"], "eventIds": [], "buyTogetherGroupIds": [], "installmentPlanIds": [], "externalLink": { "url": "https://example.com", "shortCode": "abc123", "domain": "example.com" } }, "collaboratorIds": ["550e8400-e29b-41d4-a716-446655440444"], "privacySettings": { "visibility": "PUBLIC", "whoCanComment": "FOLLOWERS", "whoCanRepost": "EVERYONE", "hideLikesCount": false, "hideCommentsCount": false }, "pollTitle": null, "pollDescription": null }, "editedAt": "2025-01-03T10:30:00", "isCurrent": false }, { "id": null, "version": 2, "snapshot": { "content": "Current version - final updates! 🔥", "media": [], "attachments": { "productIds": [], "shopIds": [], "eventIds": [], "buyTogetherGroupIds": [], "installmentPlanIds": [], "externalLink": null }, "collaboratorIds": [], "privacySettings": { "visibility": "PUBLIC", "whoCanComment": "EVERYONE", "whoCanRepost": "EVERYONE", "hideLikesCount": false, "hideCommentsCount": false }, "pollTitle": null, "pollDescription": null }, "editedAt": "2025-01-03T10:45:00", "isCurrent": true } ] } } Success Response Fields : Field Description postId Post UUID totalEdits Total number of edits made remainingEdits Edits still available (3 - totalEdits) canStillEdit Whether post can still be edited editWindowExpiresAt When edit window expires versions Array of all versions (original + edits + current) versions[].id History record UUID (null for current version) versions[].version Version number (0 = original, N = after Nth edit) versions[].snapshot Complete immutable state at that version versions[].snapshot.content Post content at that version versions[].snapshot.media Media attachments at that version versions[].snapshot.attachments All attachments at that version versions[].snapshot.collaboratorIds Collaborator IDs at that version versions[].snapshot.privacySettings Privacy settings at that version versions[].snapshot.pollTitle Poll title (null for non-poll posts) versions[].snapshot.pollDescription Poll description (null for non-poll posts) versions[].editedAt Timestamp of this version versions[].isCurrent Whether this is the current live version Version Numbering : Version Meaning 0 Original published state 1 State after 1st edit 2 State after 2nd edit 3 State after 3rd edit (final) Error Response Examples : Post Not Found (404): { "success": false, "httpStatus": "NOT_FOUND", "message": "Post not found", "action_time": "2025-01-03T10:30:45", "data": "Post not found" } 62. Check Post Edit Eligibility Purpose : Quick boolean check if current user can edit a post Endpoint : GET {base_url}/e-social/posts/{postId}/can-edit Access Level : 🔒 Protected Authentication : Bearer Token Request Headers : Header Type Required Description Authorization string Yes Bearer token for authentication Path Parameters : Parameter Type Required Description Validation postId UUID Yes ID of the post Must be valid UUID Success Response JSON Sample : { "success": true, "httpStatus": "OK", "message": "Edit eligibility checked", "action_time": "2025-01-03T10:30:45", "data": { "canEdit": true } } Success Response Fields : Field Description canEdit true if user can edit, false otherwise Eligibility Checks Performed : Check Must Be Post exists Yes User is post owner Yes Post status PUBLISHED Edit count Less than 3 Time since publish Less than 60 minutes Use Case : Frontend can call this endpoint before showing the edit button to avoid displaying unnecessary UI elements. Error Response Examples : Post Not Found (returns canEdit: false) : { "success": true, "httpStatus": "OK", "message": "Edit eligibility checked", "action_time": "2025-01-03T10:30:45", "data": { "canEdit": false } } Unauthorized (401): { "success": false, "httpStatus": "UNAUTHORIZED", "message": "Token has expired", "action_time": "2025-01-03T10:30:45", "data": "Token has expired" } 63. Get Post Likers Purpose : Retrieve a paginated list of users who liked a specific post. Authenticated viewers see people they follow prioritized at the top (Twitter-style). Returns social context flags ( followsYou , youFollow ) for each user. Endpoint : GET {base_url}/e-social/posts/{postId}/likers Access Level : 🌐 Public (social context requires authentication) Authentication : Bearer Token (optional — enhances response with follow-priority ordering and social flags) Request Headers : Header Type Required Description Authorization string No Bearer token — enables follow-priority ordering and followsYou / youFollow flags Path Parameters : Parameter Type Required Description Validation postId UUID Yes ID of the post Must be valid UUID Query Parameters : Parameter Type Required Default Description page int No 1 Page number (1-indexed) size int No 20 Items per page Success Response JSON Sample : { "success": true, "httpStatus": "OK", "message": "Post likers retrieved successfully", "action_time": "2025-01-03T10:30:45", "data": { "items": [ { "userId": "550e8400-e29b-41d4-a716-446655440000", "userName": "john_doe", "firstName": "John", "lastName": "Doe", "profilePictureUrls": ["https://cdn.example.com/photos/john.jpg"], "isVerified": true, "actedAt": "2025-01-03T09:15:00", "followsYou": true, "youFollow": true }, { "userId": "660e8400-e29b-41d4-a716-446655440001", "userName": "juma_ali", "firstName": "Juma", "lastName": "Ali", "profilePictureUrls": [], "isVerified": false, "actedAt": "2025-01-03T08:45:00", "followsYou": false, "youFollow": true } ], "totalElements": 142, "totalPages": 8, "hasNext": true, "hasPrevious": false, "isFirst": true, "isLast": false, "page": 1 } } Success Response Fields : Field Description items Array of users who liked the post items[].userId Unique identifier of the liker items[].userName Username handle items[].firstName First name items[].lastName Last name items[].profilePictureUrls List of profile picture URLs (empty if none set) items[].isVerified Whether the user has a verified badge items[].actedAt Timestamp when the user liked the post items[].followsYou true if this user follows the viewer; null when unauthenticated items[].youFollow true if the viewer follows this user; null when unauthenticated totalElements Total number of likes on this post totalPages Total number of pages hasNext Whether a next page exists hasPrevious Whether a previous page exists isFirst Whether this is the first page isLast Whether this is the last page page Current page number (1-indexed) Ordering Behavior : Viewer State Ordering Authenticated Users the viewer follows appear first, then by most recent like Unauthenticated Most recent likes first Error Response Examples : Post Not Found (404): { "success": false, "httpStatus": "NOT_FOUND", "message": "Post not found", "action_time": "2025-01-03T10:30:45", "data": "Post not found" } Use Case : Power a "Liked by" bottom sheet or modal. The post card previews this as "John, Juma + 140 others liked this" using topLikers in PostResponse ; tapping that label opens this paginated endpoint. 64. Get Post Reposters Purpose : Retrieve a paginated list of users who reposted a specific post. A repost is a quote post with no added text content. Authenticated viewers see people they follow prioritized at the top. Returns social context flags for each user. Endpoint : GET {base_url}/e-social/posts/{postId}/reposters Access Level : 🌐 Public (social context requires authentication) Authentication : Bearer Token (optional — enhances response with follow-priority ordering and social flags) Request Headers : Header Type Required Description Authorization string No Bearer token — enables follow-priority ordering and followsYou / youFollow flags Path Parameters : Parameter Type Required Description Validation postId UUID Yes ID of the post being reposted Must be valid UUID Query Parameters : Parameter Type Required Default Description page int No 1 Page number (1-indexed) size int No 20 Items per page Success Response JSON Sample : { "success": true, "httpStatus": "OK", "message": "Post reposters retrieved successfully", "action_time": "2025-01-03T10:30:45", "data": { "items": [ { "userId": "550e8400-e29b-41d4-a716-446655440000", "userName": "josh_kamau", "firstName": "Josh", "lastName": "Kamau", "profilePictureUrls": ["https://cdn.example.com/photos/josh.jpg"], "isVerified": false, "actedAt": "2025-01-03T11:20:00", "followsYou": false, "youFollow": true }, { "userId": "770e8400-e29b-41d4-a716-446655440002", "userName": "janeth_m", "firstName": "Janeth", "lastName": "Mwangi", "profilePictureUrls": [], "isVerified": true, "actedAt": "2025-01-03T10:55:00", "followsYou": true, "youFollow": false } ], "totalElements": 38, "totalPages": 2, "hasNext": true, "hasPrevious": false, "isFirst": true, "isLast": false, "page": 1 } } Success Response Fields : Field Description items Array of users who reposted the post items[].userId Unique identifier of the reposter items[].userName Username handle items[].firstName First name items[].lastName Last name items[].profilePictureUrls List of profile picture URLs (empty if none set) items[].isVerified Whether the user has a verified badge items[].actedAt Timestamp when the user reposted (quote post creation time) items[].followsYou true if this user follows the viewer; null when unauthenticated items[].youFollow true if the viewer follows this user; null when unauthenticated totalElements Total number of reposts on this post totalPages Total number of pages hasNext Whether a next page exists hasPrevious Whether a previous page exists isFirst Whether this is the first page isLast Whether this is the last page page Current page number (1-indexed) What Counts as a Repost : A repost is a quote post where content is null or blank. Quote posts with text content are not included here — they appear in the Quotes endpoint (65) instead. Users are rate-limited to 10 reposts per day . Ordering Behavior : Viewer State Ordering Authenticated Users the viewer follows appear first, then by most recent repost Unauthenticated Most recent reposts first Error Response Examples : Post Not Found (404): { "success": false, "httpStatus": "NOT_FOUND", "message": "Post not found", "action_time": "2025-01-03T10:30:45", "data": "Post not found" } Use Case : Power a "Reposted by" bottom sheet. The post card previews this as "Josh, Janeth reshared this post" using topReposters in PostResponse ; tapping that label opens this paginated endpoint. 65. Get Post Quotes Purpose : Retrieve a paginated list of quote posts — posts that reference this post and include added text commentary. Authenticated viewers see people they follow prioritized at the top. Each item includes the quoter's text so the viewer can read the added commentary inline. Endpoint : GET {base_url}/e-social/posts/{postId}/quotes Access Level : 🌐 Public (social context requires authentication) Authentication : Bearer Token (optional — enhances response with follow-priority ordering and social flags) Request Headers : Header Type Required Description Authorization string No Bearer token — enables follow-priority ordering and followsYou / youFollow flags Path Parameters : Parameter Type Required Description Validation postId UUID Yes ID of the original post being quoted Must be valid UUID Query Parameters : Parameter Type Required Default Description page int No 1 Page number (1-indexed) size int No 20 Items per page Success Response JSON Sample : { "success": true, "httpStatus": "OK", "message": "Post quotes retrieved successfully", "action_time": "2025-01-03T10:30:45", "data": { "items": [ { "id": "aa0e8400-e29b-41d4-a716-446655440099", "author": { "id": "550e8400-e29b-41d4-a716-446655440000", "userName": "alice_wanjiku", "firstName": "Alice", "lastName": "Wanjiku", "profilePictureUrl": "https://cdn.example.com/photos/alice.jpg", "isVerified": true }, "content": "This is such an important point! Everyone should read this.", "postType": "REGULAR", "status": "PUBLISHED", "media": [], "topComments": [], "topLikers": [], "topReposters": [], "engagement": { "likesCount": 12, "commentsCount": 3, "repostsCount": 0, "quotesCount": 0, "bookmarksCount": 5, "sharesCount": 1, "viewsCount": 240, "canLike": true, "canComment": true, "canRepost": true, "canShare": true }, "userInteraction": { "hasLiked": false, "hasBookmarked": false, "hasQuoted": false, "hasCommented": false, "hasViewed": true, "hasShared": false }, "quotedPost": { "id": "orig-post-uuid", "author": { "id": "orig-author-uuid", "userName": "original_author", "firstName": "Original", "lastName": "Author", "profilePictureUrl": null, "isVerified": false }, "content": "The original post content being quoted.", "postType": "REGULAR", "status": "PUBLISHED", "media": [], "createdAt": "2025-01-02T08:00:00Z", "publishedAt": "2025-01-02T08:00:00Z" }, "publishedAt": "2025-01-03T12:05:00", "createdAt": "2025-01-03T12:05:00" } ], "totalElements": 17, "totalPages": 1, "hasNext": false, "hasPrevious": false, "isFirst": true, "isLast": true, "page": 1 } } Success Response Fields : Field Description items Array of full PostResponse objects — one per quote post items[].id UUID of the quote post items[].author Author of the quote post (the person who quoted) items[].content Text commentary added by the quoter items[].postType Always REGULAR for quote posts items[].status Post status (usually PUBLISHED ) items[].media Any media the quoter attached to their quote items[].engagement Full engagement counters and permission flags for the quote post items[].userInteraction Current viewer's interaction state with the quote post items[].quotedPost The embedded original post being quoted (its own author, content, media, engagement) items[].topComments Top comments on the quote post items[].topLikers Top likers preview for the quote post items[].topReposters Top reposters preview for the quote post items[].publishedAt When the quote post was published totalElements Total number of quote posts for this post totalPages Total number of pages hasNext Whether a next page exists hasPrevious Whether a previous page exists isFirst Whether this is the first page isLast Whether this is the last page page Current page number (1-indexed) What Counts as a Quote : A quote is a post with quotedPostId set AND non-blank content . Posts with no content referencing this post are reposts and appear in endpoint 64 instead. Ordering Behavior : Viewer State Ordering Authenticated Users the viewer follows appear first, then by most recent quote Unauthenticated Most recent quotes first Error Response Examples : Post Not Found (404): { "success": false, "httpStatus": "NOT_FOUND", "message": "Post not found", "action_time": "2025-01-03T10:30:45", "data": "Post not found" } Use Case : Display a "Quotes" tab in the post detail view. Each item is a full post card — the quoter's post with their commentary, media, engagement counts, and the original post embedded inside as quotedPost . This is the same UX as X's quote tweets tab. Post Editing Rules Summary Rule Value Time window 60 minutes after publish Maximum edits 3 per post Poll options ❌ Cannot edit (would invalidate votes) Poll title/description ✅ Can edit Media ✅ Can add/remove/replace Attachments ✅ Can add/remove/replace Collaborators ✅ Can add new (accepted ones preserved) Privacy settings ✅ Can edit Engagement ✅ Preserved (likes, comments, reposts, views) After limits Must delete and repost (loses engagement) PostResponse.EditInfo Object Every post response now includes an editInfo object: { "id": "post-uuid", "content": "...", "editInfo": { "isEdited": true, "editCount": 2, "canEdit": false, "lastEditedAt": "2025-01-03T10:45:00" } } Frontend Usage : Field Use isEdited Show "Edited" label on post editCount Display "Edited 2 times" tooltip canEdit Show/hide edit button lastEditedAt Show "Last edited 2h ago" Quick Reference Guide Common HTTP Status Codes 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