Skip to content

Reference — Community and people

Community, messaging, gamification, resources, surveys, referrals, theming, member registration and membership. Every route hangs off /api/v1.

Auth: Bearer = an authenticated user · admin = tenant_admin/super_admin · staff = admin + instructor · Public = no session (the tenant is resolved by domain).

Community — /modules/community

Method Route Auth What it does
POST /modules/community/posts Bearer Creates a post: title, body, courseId?, tags? (≤10). notifyAll (admin only) also generates an email + bell broadcast; important ignores the opt-out.
GET /modules/community/posts Bearer The feed with filters (courseId, authorId, tag, source, sort: recent\|oldest\|most_commented, limit).
GET · PATCH · DELETE /modules/community/posts/:id Bearer Detail with comments and reactions · editing (author or admin) · soft delete (author).
POST /modules/community/posts/:id/comments Bearer Comments (1 level of nested replies).
DELETE /modules/community/comments/:id Bearer (author) Soft deletes the comment.
POST · DELETE /modules/community/reactions[/:id] Bearer Emoji reaction on a post or comment (idempotent) · removal.
GET /modules/community/attachments Bearer Attachments extracted from the posts (the gallery).
GET /modules/community/users/search?prefix= Bearer Mention autocomplete (max. 8).
GET /modules/community/mentions/me Bearer My most recent mentions.
GET · PUT /modules/community/me/preferences Bearer Preferences (for example digestOptOut).
POST /modules/community/posts/:id/moderate · comments/:id/moderate admin Hides/restores ({ hidden, reason? }) — reversible, and distinct from deletion by the author.
POST /modules/community/posts/:id/pin · unpin admin Pins/unpins the post in the feed.
GET · POST · PUT · DELETE /modules/community/tags[/:id] read Bearer · write admin Curated tags (name, hex color, icon).
GET · POST · PATCH · DELETE /modules/community/spaces[/:slug] read Bearer · write admin Spaces; the 4 system ones are editable but cannot be deleted (409).
GET /modules/community/members Bearer Paginated directory of active members.
GET /modules/community/stats Bearer The tenant's active members and courses.
GET · POST /modules/community/broadcasts admin Announcements with status and batch resumption.
POST /modules/community/digest/run-now super_admin Forces the weekly digest (QA) → 202.
GET /modules/community/unsubscribe?token= Public (HMAC token from the email) Unsubscribes from announcements; returns HTML.

External API — /community-api (an API key with the community:post scope, whose owner must be an admin): GET /community-api/spaces (where to publish) and POST /community-api/posts (publishes with source='api'; a non-existent space → 422 with the valid slugs).

Errors: NOT_AUTHOR / NOT_MODERATOR 403 · NESTED_REPLIES_TOO_DEEP / REACTION_TARGET_MISSING 422 · TAG_NAME_EXISTS / SPACE_EXISTS / SPACE_NOT_DELETABLE 409 · not found 404.

Messaging — /modules/messaging

Method Route Auth What it does
GET /modules/messaging/conversations Bearer The inbox: space rooms, the instructors channel and direct messages, with unread counts.
POST /modules/messaging/dm Bearer Opens (or creates, idempotent per pair) the direct message with another member.
POST /modules/messaging/spaces/:slug/open · faculty/open Bearer Opens the space's room · the private channel with the instructors (auto-provisioned).
GET · POST /modules/messaging/conversations/:id/messages Bearer Cursor-paginated history (50) · sending (body 1-4000, quota 20/min).
POST /modules/messaging/conversations/:id/typing Bearer The "typing" signal (SSE only, quota 30/min) → 204.
POST /modules/messaging/conversations/:id/read Bearer Marks it as read (lastReadAt).
GET /modules/messaging/presence · members?search= Bearer Live presence · member search for opening a direct message.
POST /modules/messaging/stream-ticket Bearer An SSE ticket of about 60 s.
GET /modules/messaging/stream?ticket= Ticket SSE: message.created, typing, ping.

Errors: MESSAGING_NOT_PARTICIPANT 403 · MESSAGING_SELF_DM / MESSAGING_STAFF_NO_FACULTY 422 · MESSAGING_RATE_LIMITED 429 · non-operational account 403.

Gamification — /modules/gamification

Member (Bearer): GET leaderboard?range=week|month|all · GET me · GET me/history · GET levels · GET challenges · GET me/perks · POST perks/:id/request · POST challenges/:id/submit (proofUrl?, note?).

Operator:

Method Route Auth What it does
GET · PUT /modules/gamification/admin/rules[/:key] admin Automatic rules: points, daily cap, activation.
POST · PUT · DELETE /modules/gamification/admin/levels[/:id] admin Levels (creating/editing repositions profiles).
GET · POST · PUT · DELETE /modules/gamification/admin/perks[/:id] admin Level perks (per-student quota, waiting period).
GET · POST /modules/gamification/admin/perk-requests[/:id/handle] staff Perk requests · handling them (APPROVED\|DONE\|REJECTED).
GET · POST · PUT · DELETE /modules/gamification/admin/challenges[/:id] staff Challenges with a reward and a date window (deleting one does not remove points already awarded).
GET · POST /modules/gamification/admin/submissions[/:id/review] staff Submissions · approving (crediting the points) or rejecting.
POST /modules/gamification/admin/backfill admin Populates the ledger with historical activity (idempotent).

Errors: GAMIFICATION_CHALLENGE_CLOSED / GAMIFICATION_PERK_UNAVAILABLE / GAMIFICATION_ALREADY_SUBMITTED / GAMIFICATION_ALREADY_REVIEWED 409 · validation 422 · not found 404.

Resources — /modules/resources

Method Route Auth What it does
GET · POST /modules/resources/collections read Bearer · write staff Collections (it seeds the 6 defaults) · creation with a cover image.
GET · PUT · DELETE /modules/resources/collections/:id staff (read Bearer) The collection + its resources with a search · editing · deletion only if it is empty.
POST /modules/resources Bearer Shares a resource: collectionId, kind: FILE\|LINK, title, url.
POST /modules/resources/:id/download Bearer Records the download and returns the URL.
DELETE /modules/resources/:id author or staff Deletes the resource.

Surveys — /modules/surveys (anonymous responses)

Method Route Auth What it does
GET /modules/surveys/sessions/:sessionId Bearer A live class's survey + whether I have already answered.
POST /modules/surveys/:id/responses Bearer An anonymous response (1 per survey; deduplicated by HMAC hash, the userId is never persisted).
GET /modules/surveys/admin[/:id/results] admin Listing · aggregate results (NPS, averages, free text).
POST /modules/surveys/admin/sessions/:sessionId admin Creates the post-class survey without waiting for the Zoom webhook.
POST /modules/surveys/admin/:id/close · reminders/run admin Closes the survey · forces the reminder sweep.

Errors: SURVEYS_CLOSED / SURVEYS_ALREADY_RESPONDED 409 · SURVEYS_INVALID_ANSWER 422.

Referrals — /modules/referrals

Method Route Auth What it does
GET /modules/referrals/me · me/stats Bearer My code and link (/unete?ref=) · clicks, sign-ups, commissions and history.
POST /modules/referrals/track Public Records a click (deduplicated by code + day + IP hash; the IP is never stored in the clear).
GET · PUT /modules/referrals/admin/config admin The program's policy: commissionBps, scope, windows, guarantee, minimum payout.
GET /modules/referrals/admin/commissions · referrers admin Commissions with filters and totals · referrers with their metrics.
POST /modules/referrals/admin/commissions/:id/approve · revoke admin Approves · revokes with a mandatory reason.
POST /modules/referrals/admin/payouts admin An atomic manual payout of a batch of APPROVED commissions, with an external reference.

Theming — /modules/theming

Method Route Auth What it does
GET · PUT /modules/theming/me read Bearer · write admin The tenant's theme (hue/saturation, whitelisted fonts, sign-in headlines). A non-empty customCss/footerHtml requires feat:white_label (402).
POST /modules/theming/me/reset admin Returns to the defaults.
POST · DELETE /modules/theming/me/logo admin Uploads (base64, ≤2 MB, png/jpeg/svg/webp) · deletes the logo.
GET /modules/theming/tenants/:tenantId/logo Public Serves the logo (needed on /signin before authentication).

Member registration — /modules/member-registration

Public flow (tenant resolved by domain; the steps are chained with signed tickets):

Method Route What it does
GET /modules/member-registration/config Which steps the wizard requires (verifiers, botUsername).
POST /modules/member-registration/telegram/verify Validates the Telegram Login Widget signature and group membership → a ticket (15 min).
POST /modules/member-registration/otp/request · otp/verify Sends the code by email · validates it → a verificationToken (30 min).
POST /modules/member-registration/register Creates the PENDING user and notifies the approver → { status: 'PENDING' }.
GET /modules/member-registration/decision?token= The approve/reject link from the approver's email (302 to the result).

If the tenant requires a verifier that is not operational (for example Telegram with no bot), it returns a fail-closed 503.

Administration (admin):

Method Route What it does
GET · POST /modules/member-registration/admin/requests Pending requests with the payment lookup · manual sign-up without OTP.
POST …/admin/requests/:userId/rerun · decision Re-runs the subscription lookup · approves/rejects from the panel.
GET · POST …/admin/requests/:userId/renewal-context · renewal-email Renewal context (the Stripe link) · sends the payment reminder.
GET · POST · DELETE /modules/member-registration/payment-flags[/:id] Overdue payment flags (matched by email or Telegram) + POST …/import for an atomic CSV load (≤5000).

Membership — /membership

Method Route Auth What it does
GET /membership/page Public The data behind /unete: active plans, courses with a reference price, testimonial.
POST /membership/checkout Public Anonymous subscription checkout: { planId, email?, referralCode? } → { url, sessionId }.
GET · POST · PATCH · DELETE /membership/admin/plans[/:id] admin Plans: name, billing period (1-12 months), price in cents, struck-through price, trial, featured. Deleting a plan that has sales deactivates it instead.
GET · PUT /membership/admin/config admin The public page: active, headlines, access group, lesson limit during the trial, per-course prices, testimonial.

Errors: MEMBERSHIP_PAGE_INACTIVE 404 · MEMBERSHIP_CONFIG_INCOMPLETE 422 · SUBSCRIPTIONS_STRIPE_CONFIG_MISSING 503 · SUBSCRIPTIONS_STRIPE_API_ERROR 502.