Skip to Content
Living documentation — last reviewed 2026-05-28
FeaturesMembershipsMemberships — Code Map

Memberships — Code Map

API

FilePurpose
apps/api/src/memberships/memberships.module.tsWires MembershipsController, InvitationsController, MembershipsService. Imports UsersModule + EventEmitter.
apps/api/src/memberships/memberships.controller.tsOrg-scoped CRUD: list, detail, stats, invite, resend, revoke, bulk-invite, send-invitation, update.
apps/api/src/memberships/invitations.controller.tsBearer-auth POST /invitations/accept-pending (throttled 10/min).
apps/api/src/memberships/memberships.service.tsAll business logic + Clerk invitation orchestration + per-process 30s membership cache.
apps/api/src/memberships/membership-events.tsMEMBERSHIP_ACTIVATED event name + MembershipActivatedEvent payload type.
apps/api/src/memberships/dto/invite-member.dto.ts{email, role}.
apps/api/src/memberships/dto/bulk-invite.dto.ts{membershipIds: uuid[]}.
apps/api/src/memberships/dto/list-members-query.dto.tssearch/status/role/page/limit/sortBy/sortOrder/hasClerkAccount/profileComplete.
apps/api/src/memberships/dto/update-member.dto.ts{role?, status?, profile?: UpdateProfileDto}.

Routes

MethodPathHandler
GET/organizations/:orgId/memberslistMembers
GET/organizations/:orgId/members/me/statsgetMyStats
GET/organizations/:orgId/members/:membershipIdgetMemberDetail
GET/organizations/:orgId/members/:membershipId/statsgetMemberStats
PATCH/organizations/:orgId/members/:membershipIdupdateMembership
POST/organizations/:orgId/members/bulk-invitebulkInvite
POST/organizations/:orgId/members/:membershipId/send-invitationsendMemberInvitation
GET/organizations/:orgId/invitationslistInvitations
POST/organizations/:orgId/invitationscreateInvitation (single)
POST/organizations/:orgId/invitations/:invitationId/resendresendInvitation
DELETE/organizations/:orgId/invitations/:invitationIdrevokeInvitation
POST/invitations/accept-pendingacceptPendingInvitations (bearer)

Web

Component / RouteDescription
apps/web/src/app/[lang]/(protected)/dashboard/members/page.tsx + members-content.tsxPaginated member list, filters, search.
apps/web/src/app/[lang]/(protected)/dashboard/members/[id]/...Member detail.
apps/web/src/components/members/bulk-invite-dialog.tsxUI for bulk-invite.
apps/web/src/components/members/card-registration-dialog.tsxCard-registration flow (payment provider tie-in).
apps/web/src/components/onboarding/invite-members-form.tsxThe onboarding-time invite list, hits createInvitation per email.
i18n: members.*, members.invite.* in apps/web/src/i18n/dictionaries/.

Events

EventProducerConsumers (known)
MEMBERSHIP_ACTIVATEDacceptPendingInvitations, OrganizationLeadsService.convertLeadForms fan-out (onboarding compliance forms), analytics tracking, future welcome emails / push (per code comments).

DB tables

TableUsed as
membershipsOwned.
invitationsOwned (alongside Clerk invitation).
usersJoined for list/detail/search.
organizationsJoined for tier check (platform_tier).
bookings, class_sessions, class_types, programsJoined for computeMemberStats.

Shared schemas

  • MembershipResponse, MembershipRole, MembershipStatus, MembershipPaymentStatuslibs/shared/src/lib/schemas/membership.schema.ts.
  • isStaffRole(role) — boolean helper that returns true for owner|admin|coach.

Clerk integration

  • clerk.invitations.createInvitation({emailAddress, redirectUrl, ignoreExisting:true}) on create, resend, bulk-invite, send-member-invitation.
  • clerk.invitations.revokeInvitation(clerkInvitationId) best-effort on revoke and resend.
  • No Clerk org membership API used — invitation acceptance ties to FitKit memberships only.

Tests

FileWhat it covers
apps/api/src/memberships/memberships.service.unit.spec.tsInvitation flow, acceptance, last-owner protection, tier limit, bulk-invite skip reasons.
Web integrationapps/web/src/app/[lang]/(protected)/dashboard/members/members-page.int.spec.tsx, members-ribbon.int.spec.tsx.