docs
/
AppEngine API

Community

Pages, posts, stories, follows, connections, direct and group messaging, meetings, blocking and reporting, plus social-listening topics.

CommunityModule is the social layer for customers. Three surfaces, 116 routes in all: /client/community/* for the customer app (82 routes), /community/* for the older networking API (26 routes), and /social/topics/* for the Listening feature's keyword rules (8 routes). A socket gateway on the /community-chat namespace carries live messages.

Every community record is keyed by the person's email, read from the signed-in customer (data.email). Routes that need a person return 401 when there is none.

The community app tutorial builds a client on these routes; Event App networking uses the connection and messaging half.

Who may write

  • /client/community/* has no class-level role. Routes marked public carry @PublicRoute() and still read the viewer when one is signed in, so private content shows to members.
  • /community/* is @Roles(RoleType.User) at class level.
  • /social/topics/* has no @Roles or @StaffOnly; it needs a valid token.
  • A customer (or the site's app token acting for one) may not create, update, publish, approve or delete any community_* record through /repository/* or /upstream/save-integration. The JWT guard refuses with "Use the community endpoints to change community records". Staff with content permissions can still use the repository, which is how held posts get approved.

Pages

GET/client/community/pagesNo auth
GET/client/community/pages/mineJWT
GET/client/community/pages/:pageIdNo auth
POST/client/community/pagesJWT
PUT/client/community/pages/:pageIdJWT
POST/client/community/pages/:pageId/joinJWT
POST/client/community/pages/:pageId/leaveJWT
POST/client/community/pages/:pageId/inviteJWT
GET/client/community/pages/:pageId/membersNo auth

A page (community_page) is a group or space; membership is community_page_member with a role (owner, admin, member) and status. The creator becomes owner. Only owners and admins may update a page, invite people or add anyone other than themselves.

  • visibility: public pages are readable by anyone; others only by active members. Pages in draft, archived or removed status read as 404.
  • joinPolicy: open joins at once, approval_required creates a pending membership, invite_only refuses a self-join. A banned member cannot rejoin or leave.
  • postingPolicy: anyone, members (default) or admins_only.
  • moderationLevel: pre_approve holds posts and stories from non-admins as pending.

Update accepts only: title, slug, type, description, shortDescription, category, tags, status, coverImage, logo, images, visibility, joinPolicy, postingPolicy, moderationLevel, features, website.

Creating an event auto-creates a public, open page linked to it (linkedEntity); creating an event_ticket adds the holderEmail to that page as a member. See Events.

Feed, posts and comments

GET/client/community/feedNo auth
POST/client/community/postsJWT
GET/client/community/posts/:postIdNo auth
PUT/client/community/posts/:postIdJWT
DELETE/client/community/posts/:postIdJWT
POST/client/community/posts/:postId/shareJWT
POST/client/community/posts/:postId/voteJWT
GET/client/community/posts/:postId/commentsNo auth
POST/client/community/posts/:postId/commentsJWT
DELETE/client/community/comments/:commentIdJWT

The feed filters by page, author, type, hashtag, and sorts latest (default) or trending (by reaction count). It shows only posts from pages the viewer can read, hides private posts from everyone but the author, and hides pending/draft posts from everyone but the author. Signed-in viewers get viewerLiked and viewerSaved on each post.

Posting to a page follows that page's posting policy and moderation level. #tags and @mentions are pulled from the content; each hashtag is counted in community_hashtag. Only the author may edit or delete; delete sets status: removed. Editing a page post re-applies moderation. Page posts, private posts and held posts cannot be shared. A poll vote is refused twice unless poll.allowMultiple. Comments nest one level via parentComment.

Reactions and hashtags

POST/client/community/reactJWT
GET/client/community/reactionsNo auth
GET/client/community/hashtags/trendingNo auth

react takes target, targetType and type. Only post and comment targets are accepted. Sending the same type again removes it; a different type replaces it. Counts land in stats.reactions and reactionSummary. hashtags/trending currently returns an empty list.

Stories

GET/client/community/storiesNo auth
POST/client/community/storiesJWT
POST/client/community/stories/:storyId/viewJWT
DELETE/client/community/stories/:storyIdJWT

A story expires 24 hours after creation unless highlight is set. The list returns the active stories and the same stories grouped by author. Page stories follow the page's posting and moderation rules.

Follows, bookmarks, notifications, badges

POST/client/community/followJWT
DELETE/client/community/follow/:followingIdJWT
GET/client/community/followersJWT
GET/client/community/followingJWT
GET/client/community/bookmarksJWT
POST/client/community/bookmarksJWT
DELETE/client/community/bookmarks/:targetJWT
GET/client/community/notificationsJWT
POST/client/community/notifications/readJWT
POST/client/community/notifications/read-allJWT
GET/client/community/notifications/unread-countJWT
GET/client/community/badgesNo auth
GET/client/community/badges/mineJWT

A follow targets a person or a page (followingType); following twice returns the existing record. badges lists community_badge records not retired; badges/mine currently returns an empty list.

Announcements

GET/client/community/pages/:pageId/announcementsNo auth
GET/client/community/announcements/:announcementIdNo auth
POST/client/community/pages/:pageId/announcementsJWT

Only page owners and admins may create one. Reading follows the page's visibility.

People

GET/client/community/peopleNo auth
GET/client/community/people/suggestionsJWT
GET/client/community/people/:emailNo auth

people?page=<pageId>&q= searches that page's members; without page it returns an empty list. people/:email returns a public profile only: name, image, company, job title, bio, city, country, interests, social. people/suggestions returns an empty list for now.

Group chats

POST/client/community/groupsJWT
GET/client/community/groupsJWT
GET/client/community/groups/:groupIdJWT
POST/client/community/groups/:groupId/messagesJWT
GET/client/community/groups/:groupId/messagesJWT
POST/client/community/groups/:groupId/membersJWT
DELETE/client/community/groups/:groupId/members/:emailJWT

The creator is the group admin. Only members can read a group (others get 404); only admins add members or remove someone else; anyone may remove themselves. A group tied to a page can only be created by a page admin.

Connections, direct messages, meetings, blocking

The same 26 routes exist twice: under /client/community/* (customer; 401 without an email) and under /community/* (@Roles(User)).

POST/client/community/connections/requestJWT
PUT/client/community/connections/:id/respondJWT
GET/client/community/connectionsJWT
GET/client/community/connections/pendingJWT
GET/client/community/connections/sentJWT
GET/client/community/connections/statsJWT
POST/client/community/connections/accept-allJWT
DELETE/client/community/connections/:idJWT
POST/client/community/messagesJWT
GET/client/community/messages/threadsJWT
GET/client/community/messages/thread/:userIdJWT
POST/client/community/messages/readJWT
POST/client/community/messages/thread/:userId/readJWT
DELETE/client/community/messages/:idJWT
GET/client/community/messages/unread-countJWT
POST/client/community/meetingsJWT
GET/client/community/meetingsJWT
GET/client/community/meetings/upcomingJWT
GET/client/community/meetings/:idJWT
PUT/client/community/meetings/:id/respondJWT
PUT/client/community/meetings/:idJWT
DELETE/client/community/meetings/:idJWT
POST/client/community/blocksJWT
DELETE/client/community/blocks/:userIdJWT
GET/client/community/blocksJWT
POST/client/community/reportsJWT
  • Connections (community_connection): only the target may accept or reject a pending request. A second request while pending, connected or blocked is refused.
  • Messages (community_message): connection is not required, but a block in either direction refuses the send. A replyTo must be in the same one-to-one thread. Delete hides the message for the caller only.
  • Meetings (community_meeting): the organizer must be connected with every participant. It starts proposed and becomes confirmed when all accept. Only the organizer can edit; changing the time resets every response. Organizer or participants may cancel. upcoming lists confirmed meetings from now.
  • Blocks and reports (community_block): blocking marks any connection between the two as blocked. A report is a community_block with reported: true and reportStatus: pending; a second pending report on the same person is refused. Staff review them on the operator side: GET /community/reports lists the pending ones and POST /community/reports/:id/review takes { action: action_taken | dismissed, notes }. Both are staff-only — never a customer or the site's app token.

Media

POST/client/community/media/uploadJWT
GET/client/community/media/mineJWT
PUT/client/community/media/renameJWT
DELETE/client/community/media/:pathJWT

Uploads (multipart field file) are stored under community/<email>/media/ and belong to the uploader; posts, stories and profiles reference the URL. Rename and delete only accept a path inside the caller's own folder, and a new name may not contain directory separators.

Live chat socket

Namespace /community-chat, websocket transport. Connect with auth: { token, orgId } using a customer token. Client events: sendMessage, sendGroupMessage, typing, groupTyping, markRead, getOnlineUsers, joinGroup, leaveGroup. Server events include message, groupMessage, typing, groupTyping, onlineUsers, onlineStatus, joinedGroup, leftGroup and error. Sends go through the same services as the REST routes, so the same block and membership rules apply.

Social listening topics

GET/social/topicsJWT
GET/social/topics/:idJWT
POST/social/topicsJWT
PUT/social/topics/:idJWT
DELETE/social/topics/:idJWT
POST/social/topics/testJWT
POST/social/topics/backfillJWT
POST/social/topics/:id/backfillJWT

A topic (social_topic, a string datatype, not in the DataType enum) is a saved rule: patterns (each a string or { value, mode: keyword | phrase | regex, caseSensitive }), excludePatterns, optional platforms and activityTypes, and enabled. It triggers nothing; matches are written to social_activity.topicMatches[]. test dry-runs a topic against a sample without saving. backfill rescans recent social_activity rows (default 30 days, days in the body) and rewrites only the matches for the scanned topics. Deleting a topic leaves its old matches until the next scan.

Datatypes

community_page, community_page_member, community_post, community_comment, community_reaction, community_hashtag, community_story, community_follow, community_bookmark, community_notification, community_announcement, community_badge, community_group_chat, community_message, community_connection, community_meeting, community_block, plus social_topic and social_activity.