Appearance
API ↔ Frontend Endpoint Map
This document provides a complete picture of every endpoint exposed by apps/api, which pages and components in apps/web and apps/members call each one, and a summary of what is used vs. unused.
Table of Contents
- API Endpoints by Controller
- apps/web — Pages & API Calls
- apps/members — Pages, Components & API Calls
- Coverage Table
1. API Endpoints by Controller
Auth note:
- Admin endpoints (non-member) require a Clerk JWT ******
- Member portal endpoints (
/api/member/*) use a cookie-based session (MemberSessionDefaults), set byPOST /api/member/auth/login.POST /api/member/auth/loginandGET /api/healthare anonymous (no auth required).POST /api/webhooks/clerkis verified by Svix signature — not a ******
AdminController — GET/POST/PUT/DELETE /api/admin
| Verb | Route | Return Type | Inputs |
|---|---|---|---|
| GET | /api/admin/roles | AdminRole[] | — |
| POST | /api/admin/roles | { adminRoleId } | Body: CreateAdminRoleRequest |
| PUT | /api/admin/roles/{id} | 204 No Content | Route: id: guid; Body: UpdateAdminRoleRequest |
| DELETE | /api/admin/roles/{id} | 204 No Content | Route: id: guid |
| PUT | /api/admin/roles/{id}/permissions | 204 No Content | Route: id: guid; Body: SetRolePermissionsRequest |
| GET | /api/admin/permissions | AdminPermission[] | — |
| GET | /api/admin/users | user list | Query: search?, isActive?, skip, take |
| POST | /api/admin/login-users | — | Body: ProvisionLoginUserRequest |
| GET | /api/admin/teams | team list | — |
ApplicationsController — /api/applications
| Verb | Route | Return Type | Inputs |
|---|---|---|---|
| GET | /api/applications | PagedResult<MembershipApplicationListItemDto> | Query: status?, applicantType?, skip, take |
| GET | /api/applications/{id} | MembershipApplicationDetailDto | Route: id: guid |
| PUT | /api/applications/{id}/approve | MembershipApplicationDetailDto | Route: id: guid; Body: ApproveApplicationRequest |
| PUT | /api/applications/{id}/reject | MembershipApplicationDetailDto | Route: id: guid; Body: RejectApplicationRequest |
AuditController — /api/audit
| Verb | Route | Return Type | Inputs |
|---|---|---|---|
| GET | /api/audit | PagedResult<AuditLogDto> | Query: entityId?, entityType?, userId?, skip, take |
| GET | /api/audit/{id} | AuditLogWithDetailsDto | Route: id: guid |
AuthController — /api/auth
| Verb | Route | Return Type | Inputs |
|---|---|---|---|
| POST | /api/auth/jit | JitResponse | Body: JitRequest (Clerk JWT required; ClerkId from JWT sub, not body) |
| GET | /api/auth/me | JitResponse | Clerk JWT required |
CampaignsController — /api/campaigns
| Verb | Route | Return Type | Inputs |
|---|---|---|---|
| GET | /api/campaigns/summary | campaign summary object | — |
| GET | /api/campaigns | { total, items } | Query: status?, type?, search?, skip, take |
| GET | /api/campaigns/{id} | campaign detail object | Route: id: guid |
| GET | /api/campaigns/{id}/recipients | { total, items } | Route: id: guid; Query: skip, take |
| POST | /api/campaigns | { campaignId } | Body: CreateCampaignRequest |
| PUT | /api/campaigns/{id} | 204 No Content | Route: id: guid; Body: UpdateCampaignRequest |
| DELETE | /api/campaigns/{id} | 204 No Content | Route: id: guid |
ClerkWebhookController — /api/webhooks/clerk
| Verb | Route | Return Type | Inputs |
|---|---|---|---|
| POST | /api/webhooks/clerk | 200 OK | Svix signature header; raw request body |
ContactsController — /api/contacts
| Verb | Route | Return Type | Inputs |
|---|---|---|---|
| GET | /api/contacts | PagedResult<ContactListItemDto> | Query: skip, take, search?, status?, type? |
| GET | /api/contacts/summary | summary object (counts by status) | — |
| GET | /api/contacts/export | 501 Not Implemented | — |
| GET | /api/contacts/{id} | ContactDetailDto | Route: id: guid |
| POST | /api/contacts | ContactListItemDto | Body: CreateContactRequest |
| PUT | /api/contacts/{id} | ContactDetailDto | Route: id: guid; Body: UpdateContactRequest |
| DELETE | /api/contacts/{id} | 204 No Content | Route: id: guid |
DashboardController — /api/dashboard
| Verb | Route | Return Type | Inputs |
|---|---|---|---|
| GET | /api/dashboard/stats | DashboardStatsDto | — |
| GET | /api/dashboard/growth | GrowthPointDto[] | — |
| GET | /api/dashboard/renewals-due | DashboardRenewalsDueDto | Query: take |
| GET | /api/dashboard/activity | ActivityItemDto[] | Query: take |
EventsController — /api/events
| Verb | Route | Return Type | Inputs |
|---|---|---|---|
| GET | /api/events/summary | EventSummaryDto | — |
| GET | /api/events | PagedResult<EventListItemDto> | Query: search?, statusFilter?, skip, take |
| GET | /api/events/{id} | EventDetailDto | Route: id: guid |
| POST | /api/events | { eventId } | Body: CreateEventRequest |
| PUT | /api/events/{id} | 204 No Content | Route: id: guid; Body: UpdateEventRequest |
| DELETE | /api/events/{id} | 204 No Content | Route: id: guid |
| GET | /api/events/{id}/registrations | PagedResult<EventRegistrationListItemDto> | Route: id: guid; Query: skip, take |
| GET | /api/events/{id}/sessions | EventSessionListItemDto[] | Route: id: guid |
| POST | /api/events/{id}/cancel | 204 No Content | Route: id: guid |
HealthController — /api/health
| Verb | Route | Return Type | Inputs |
|---|---|---|---|
| GET | /api/health | { Status: "Healthy" } | — (anonymous, no auth required) |
InvoicesController — /api/invoices
| Verb | Route | Return Type | Inputs |
|---|---|---|---|
| GET | /api/invoices/summary | InvoiceSummaryDto | — |
| GET | /api/invoices | PagedResult<InvoiceListItemDto> | Query: partyId?, statusFilter?, search?, skip, take |
| GET | /api/invoices/{id}/payments | payment list | Route: id: guid |
| GET | /api/invoices/{id} | InvoiceDetailDto | Route: id: guid |
| POST | /api/invoices/{id}/void | 204 No Content | Route: id: guid |
| POST | /api/invoices | { invoiceId } | Body: CreateInvoiceRequest |
| PUT | /api/invoices/{id} | InvoiceDetailDto | Route: id: guid; Body: UpdateInvoiceRequest |
MediaController — /api/member/media
| Verb | Route | Return Type | Inputs |
|---|---|---|---|
| GET | /api/member/media/{*storageKey} | file content (binary) | Route: storageKey (wildcard); Member session auth |
MemberAuthController — /api/member/auth
| Verb | Route | Return Type | Inputs |
|---|---|---|---|
| POST | /api/member/auth/login | MemberAuthUserDto + session cookie | Body: MemberLoginRequest { email, password } (anonymous) |
| POST | /api/member/auth/logout | 204 No Content | Member session auth |
| GET | /api/member/auth/me | session user info | Member session auth |
MemberCertificatesController — /api/member/certificates
| Verb | Route | Return Type | Inputs |
|---|---|---|---|
| GET | /api/member/certificates | MemberCertificateDto[] | Member session auth |
MemberCertificationsController — /api/member/certifications
| Verb | Route | Return Type | Inputs |
|---|---|---|---|
| POST | /api/member/certifications | MemberCertificationDto | Multipart form: file, title, issuingAuthority?; Member session auth |
MemberCommunicationsController — /api/member/communications
| Verb | Route | Return Type | Inputs |
|---|---|---|---|
| GET | /api/member/communications/preferences | MemberCommunicationPreferenceDto[] | Member session auth |
| PUT | /api/member/communications/preferences | MemberCommunicationPreferenceDto[] | Body: MemberCommunicationPreferenceUpdateRequest[]; Member session auth |
MemberEventsController — /api/member/events
| Verb | Route | Return Type | Inputs |
|---|---|---|---|
| GET | /api/member/events/upcoming | MemberUpcomingEventDto[] | Member session auth |
MemberInvoicesController — /api/member/invoices
| Verb | Route | Return Type | Inputs |
|---|---|---|---|
| GET | /api/member/invoices | MemberInvoiceListDto | Query: limit; Member session auth |
MemberMembershipController — /api/member/membership
| Verb | Route | Return Type | Inputs |
|---|---|---|---|
| GET | /api/member/membership/current | MemberCurrentMembershipDto | Member session auth |
| POST | /api/member/membership/renew | MemberRenewResponse | Body: MemberRenewRequest; Member session auth |
MemberProfileController — /api/member/profile
| Verb | Route | Return Type | Inputs |
|---|---|---|---|
| GET | /api/member/profile | MemberSelfProfileDto | Member session auth |
| GET | /api/member/profile/completeness | MemberCompletenessDto | Member session auth |
| PATCH | /api/member/profile | MemberSelfProfileDto | Body: MemberProfileUpdateRequest; Member session auth |
MembersController — /api/members
| Verb | Route | Return Type | Inputs |
|---|---|---|---|
| GET | /api/members | PagedResult<MemberListItemDto> | Query: search?, status?, skip, take |
| GET | /api/members/summary | summary object | — |
| GET | /api/members/export | 501 Not Implemented | — |
| GET | /api/members/{id} | MemberDetailDto | Route: id: guid |
| POST | /api/members | MemberListItemDto | Body: CreateMemberRequest |
| PUT | /api/members/{id} | MemberDetailDto | Route: id: guid; Body: UpdateMemberRequest |
| DELETE | /api/members/{id} | 204 No Content | Route: id: guid |
MembershipPlansController — /api/membership-plans
| Verb | Route | Return Type | Inputs |
|---|---|---|---|
| GET | /api/membership-plans | MembershipPlanListItemDto[] | Query: isActive? |
MembershipsController — /api/memberships
| Verb | Route | Return Type | Inputs |
|---|---|---|---|
| GET | /api/memberships | PagedResult<MembershipListItemDto> | Query: status?, planId?, expiryWindow?, autoRenew?, skip, take |
| GET | /api/memberships/due | PagedResult<MembershipListItemDto> | Query: days, autoRenew?, skip, take |
| POST | /api/memberships/batch-renew | RenewalBatchResult | Body: RenewalBatchRequest { membershipIds[] } |
| POST | /api/memberships/{id}/renew | 204 No Content | Route: id: guid |
| GET | /api/memberships/{id} | membership detail | Route: id: guid |
| POST | /api/memberships | 204 No Content | Body: CreateMembershipRequest |
| PUT | /api/memberships/{id} | 204 No Content | Route: id: guid; Body: UpdateMembershipRequest |
| DELETE | /api/memberships/{id} | 204 No Content | Route: id: guid |
PaymentsController — /api/payments
| Verb | Route | Return Type | Inputs |
|---|---|---|---|
| GET | /api/payments | PagedResult<PaymentListItemDto> | Query: partyId?, search?, skip, take |
| GET | /api/payments/{id} | PaymentDetailDto | Route: id: guid |
| POST | /api/payments | PaymentDetailDto | Body: RecordPaymentRequest |
PeopleController — /api/people
| Verb | Route | Return Type | Inputs |
|---|---|---|---|
| GET | /api/people | Party[] | Query: skip, take |
ReportsController — /api/reports
| Verb | Route | Return Type | Inputs |
|---|---|---|---|
| GET | /api/reports | ReportDefinitionDto[] | Query: reportType?, isActive? |
| GET | /api/reports/recent-runs | ReportRunDto[] | Query: take |
| GET | /api/reports/runs/{runId} | ReportRunDto | Route: runId: guid |
| POST | /api/reports/{id}/run | ReportRunDto | Route: id: guid |
2. apps/web — Pages & API Calls
Authentication model: apps/web uses Clerk JWT. On each sign-in the auth store calls
POST /api/auth/jitonce to provision/resolve the user and obtain role + permissions.GET /api/auth/meis called on-demand to refresh permissions without a new sign-in. All other API calls use theuseApi()composable or directofetch()calls with the Clerk ******Redirect-only pages (no API calls):
pages/members/index.vue→/contacts/,pages/members/[id].vue→/contacts/[id],pages/marketing/*→/communications/*,pages/prospects.vue→/memberships/applications.
pages/index.vue — Dashboard home
| Verb | Endpoint | Controller |
|---|---|---|
| GET | /api/dashboard/stats | DashboardController |
| GET | /api/dashboard/growth | DashboardController |
| GET | /api/dashboard/renewals-due | DashboardController |
| GET | /api/dashboard/activity | DashboardController |
pages/contacts/index.vue — Contacts list
| Verb | Endpoint | Controller |
|---|---|---|
| GET | /api/contacts | ContactsController |
| GET | /api/contacts/summary | ContactsController |
| POST | /api/contacts | ContactsController |
pages/contacts/[id].vue — Contact detail
| Verb | Endpoint | Controller |
|---|---|---|
| GET | /api/contacts/{id} | ContactsController |
| PUT | /api/contacts/{id} | ContactsController |
| GET | /api/invoices?partyId={id} | InvoicesController |
| GET | /api/audit?entityId={id}&entityType=Party | AuditController |
| GET | /api/membership-plans | MembershipPlansController |
| POST | /api/memberships/{id}/renew | MembershipsController |
| POST | /api/memberships | MembershipsController |
pages/events/index.vue — Events list
| Verb | Endpoint | Controller |
|---|---|---|
| GET | /api/events/summary | EventsController |
| GET | /api/events | EventsController |
| POST | /api/events | EventsController |
pages/events/[id].vue — Event detail
| Verb | Endpoint | Controller |
|---|---|---|
| GET | /api/events/{id} | EventsController |
| GET | /api/events/{id}/registrations | EventsController |
| GET | /api/events/{id}/sessions | EventsController |
| POST | /api/events/{id}/cancel | EventsController |
| PUT | /api/events/{id} | EventsController |
pages/communications/index.vue — Campaigns list
| Verb | Endpoint | Controller |
|---|---|---|
| GET | /api/campaigns/summary | CampaignsController |
| GET | /api/campaigns | CampaignsController |
| POST | /api/campaigns | CampaignsController |
pages/communications/[id].vue — Campaign detail
| Verb | Endpoint | Controller |
|---|---|---|
| GET | /api/campaigns/{id} | CampaignsController |
| GET | /api/campaigns/{id}/recipients | CampaignsController |
| PUT | /api/campaigns/{id} | CampaignsController |
| DELETE | /api/campaigns/{id} | CampaignsController |
pages/communications/editor.vue — Campaign editor
| Verb | Endpoint | Controller |
|---|---|---|
| GET | /api/campaigns/{id} | CampaignsController |
| PUT | /api/campaigns/{id} | CampaignsController |
pages/payments/index.vue — Payments / invoices list
| Verb | Endpoint | Controller |
|---|---|---|
| GET | /api/invoices/summary | InvoicesController |
| GET | /api/invoices | InvoicesController |
pages/payments/[invoice].vue — Invoice detail
| Verb | Endpoint | Controller |
|---|---|---|
| GET | /api/invoices/{id} | InvoicesController |
| GET | /api/invoices/{id}/payments | InvoicesController |
| POST | /api/invoices/{id}/void | InvoicesController |
pages/memberships/index.vue — Memberships list
| Verb | Endpoint | Controller |
|---|---|---|
| GET | /api/memberships | MembershipsController |
pages/memberships/applications.vue — Applications
| Verb | Endpoint | Controller |
|---|---|---|
| GET | /api/applications | ApplicationsController |
| GET | /api/applications/{id} | ApplicationsController |
| PUT | /api/applications/{id}/approve | ApplicationsController |
| PUT | /api/applications/{id}/reject | ApplicationsController |
pages/memberships/renewals.vue & pages/renewals/batch.vue — Batch renewals
Both pages contain identical logic;
renewals/batch.vueappears to be a legacy duplicate.
| Verb | Endpoint | Controller |
|---|---|---|
| GET | /api/memberships/due | MembershipsController |
| POST | /api/memberships/batch-renew | MembershipsController |
pages/settings/roles.vue — Role management
| Verb | Endpoint | Controller |
|---|---|---|
| GET | /api/admin/roles | AdminController |
| GET | /api/admin/permissions | AdminController |
| PUT | /api/admin/roles/{id} | AdminController |
| POST | /api/admin/roles | AdminController |
| PUT | /api/admin/roles/{id}/permissions | AdminController |
pages/settings/audit.vue — Audit log
| Verb | Endpoint | Controller |
|---|---|---|
| GET | /api/audit | AuditController |
pages/reports/index.vue — Recent report runs
| Verb | Endpoint | Controller |
|---|---|---|
| GET | /api/reports/recent-runs | ReportsController |
pages/reports/library.vue — Report library
| Verb | Endpoint | Controller |
|---|---|---|
| GET | /api/reports | ReportsController |
| POST | /api/reports/{id}/run | ReportsController |
pages/login.vue, pages/about.vue, pages/resources/index.vue, pages/[...404].vue
No API calls. (resources/index.vue shows a static "coming soon" placeholder.)
Auth Store — stores/auth.ts
Called globally (not from a single page), triggered by Clerk sign-in state:
| Verb | Endpoint | Controller | When |
|---|---|---|---|
| POST | /api/auth/jit | AuthController | Once per session on sign-in |
| GET | /api/auth/me | AuthController | On-demand permission refresh |
3. apps/members — Pages, Components & API Calls
Authentication model: apps/members uses a cookie-based session.
POST /api/member/auth/loginsets the session; all other member endpoints require the session cookie. All API calls are routed through theuseMemberApi()composable (inapp/composables/useMemberApi.ts), which wrapsuseApi()→apiFetch().
pages/login.vue — Member login
| Verb | Endpoint | Controller |
|---|---|---|
| POST | /api/member/auth/login | MemberAuthController |
pages/index.vue — Public landing page
No API calls. Marketing/landing page visible before login.
pages/account/index.vue — Member dashboard
All calls made on mount via useMemberApi():
| Verb | Endpoint | Controller |
|---|---|---|
| GET | /api/member/profile | MemberProfileController |
| GET | /api/member/profile/completeness | MemberProfileController |
| GET | /api/member/membership/current | MemberMembershipController |
| GET | /api/member/invoices | MemberInvoicesController |
| GET | /api/member/certificates | MemberCertificatesController |
| GET | /api/member/events/upcoming | MemberEventsController |
| GET | /api/member/communications/preferences | MemberCommunicationsController |
pages/account/events.vue — Events sub-page
No API calls. Static placeholder linking back to dashboard.
pages/account/invoices.vue — Invoices sub-page
No API calls. Static placeholder linking back to dashboard.
components/members/MembersBand.vue — Nav/header band
| Verb | Endpoint | Controller |
|---|---|---|
| POST | /api/member/auth/logout | MemberAuthController |
components/members/renew/RenewNowModal.vue — Renew membership modal
| Verb | Endpoint | Controller |
|---|---|---|
| POST | /api/member/membership/renew | MemberMembershipController |
components/members/edit/EditProfileModal.vue — Edit personal profile
| Verb | Endpoint | Controller |
|---|---|---|
| PATCH | /api/member/profile | MemberProfileController |
components/members/edit/EditBusinessDetailsModal.vue — Edit organisation profile
| Verb | Endpoint | Controller |
|---|---|---|
| PATCH | /api/member/profile | MemberProfileController |
components/members/edit/FinishProfileModal.vue — Complete profile wizard
| Verb | Endpoint | Controller |
|---|---|---|
| PATCH | /api/member/profile | MemberProfileController |
components/members/edit/EditCommunicationsModal.vue — Edit communication preferences
| Verb | Endpoint | Controller |
|---|---|---|
| PUT | /api/member/communications/preferences | MemberCommunicationsController |
components/members/upload/UploadCertificateModal.vue — Upload certification
| Verb | Endpoint | Controller |
|---|---|---|
| POST | /api/member/certifications | MemberCertificationsController |
Display-only components (no API calls)
These receive data via props from the dashboard page and make no direct API calls:
MembershipCard, InvoicesCard, CertificationsCard, UpcomingEventsCard, CommunicationsCard, PersonalDetailsCard, BusinessDetailsCard, ProfileCompletenessCard, MembersHero, MembersNav, MembersFooter, QuickActions, CardError, Toaster
4. Coverage Table
The table below shows every API endpoint and which frontend project(s) consume it.
| Endpoint | apps/web | apps/members | Status |
|---|---|---|---|
| AdminController | |||
GET /api/admin/roles | settings/roles.vue | — | ✅ Used |
POST /api/admin/roles | settings/roles.vue | — | ✅ Used |
PUT /api/admin/roles/{id} | settings/roles.vue | — | ✅ Used |
DELETE /api/admin/roles/{id} | — | — | ⚠️ Unused |
PUT /api/admin/roles/{id}/permissions | settings/roles.vue | — | ✅ Used |
GET /api/admin/permissions | settings/roles.vue | — | ✅ Used |
GET /api/admin/users | — | — | ⚠️ Unused |
POST /api/admin/login-users | — | — | ⚠️ Unused |
GET /api/admin/teams | — | — | ⚠️ Unused |
| ApplicationsController | |||
GET /api/applications | memberships/applications.vue | — | ✅ Used |
GET /api/applications/{id} | memberships/applications.vue | — | ✅ Used |
PUT /api/applications/{id}/approve | memberships/applications.vue | — | ✅ Used |
PUT /api/applications/{id}/reject | memberships/applications.vue | — | ✅ Used |
| AuditController | |||
GET /api/audit | settings/audit.vue, contacts/[id].vue | — | ✅ Used |
GET /api/audit/{id} | — | — | ⚠️ Unused |
| AuthController | |||
POST /api/auth/jit | stores/auth.ts | — | ✅ Used |
GET /api/auth/me | stores/auth.ts | — | ✅ Used |
| CampaignsController | |||
GET /api/campaigns/summary | communications/index.vue | — | ✅ Used |
GET /api/campaigns | communications/index.vue | — | ✅ Used |
GET /api/campaigns/{id} | communications/[id].vue, editor.vue | — | ✅ Used |
GET /api/campaigns/{id}/recipients | communications/[id].vue | — | ✅ Used |
POST /api/campaigns | communications/index.vue | — | ✅ Used |
PUT /api/campaigns/{id} | communications/[id].vue, editor.vue | — | ✅ Used |
DELETE /api/campaigns/{id} | communications/[id].vue | — | ✅ Used |
| ClerkWebhookController | |||
POST /api/webhooks/clerk | — (Clerk infrastructure) | — | ✅ Used (external) |
| ContactsController | |||
GET /api/contacts | contacts/index.vue | — | ✅ Used |
GET /api/contacts/summary | contacts/index.vue | — | ✅ Used |
GET /api/contacts/export | — | — | ⚠️ Unused (501) |
GET /api/contacts/{id} | contacts/[id].vue | — | ✅ Used |
POST /api/contacts | contacts/index.vue | — | ✅ Used |
PUT /api/contacts/{id} | contacts/[id].vue | — | ✅ Used |
DELETE /api/contacts/{id} | — | — | ⚠️ Unused |
| DashboardController | |||
GET /api/dashboard/stats | pages/index.vue | — | ✅ Used |
GET /api/dashboard/growth | pages/index.vue | — | ✅ Used |
GET /api/dashboard/renewals-due | pages/index.vue | — | ✅ Used |
GET /api/dashboard/activity | pages/index.vue | — | ✅ Used |
| EventsController | |||
GET /api/events/summary | events/index.vue | — | ✅ Used |
GET /api/events | events/index.vue | — | ✅ Used |
GET /api/events/{id} | events/[id].vue | — | ✅ Used |
POST /api/events | events/index.vue | — | ✅ Used |
PUT /api/events/{id} | events/[id].vue | — | ✅ Used |
DELETE /api/events/{id} | — | — | ⚠️ Unused |
GET /api/events/{id}/registrations | events/[id].vue | — | ✅ Used |
GET /api/events/{id}/sessions | events/[id].vue | — | ✅ Used |
POST /api/events/{id}/cancel | events/[id].vue | — | ✅ Used |
| HealthController | |||
GET /api/health | — (infra/monitoring) | — | ✅ Used (external) |
| InvoicesController | |||
GET /api/invoices/summary | payments/index.vue | — | ✅ Used |
GET /api/invoices | payments/index.vue, contacts/[id].vue | — | ✅ Used |
GET /api/invoices/{id}/payments | payments/[invoice].vue | — | ✅ Used |
GET /api/invoices/{id} | payments/[invoice].vue | — | ✅ Used |
POST /api/invoices/{id}/void | payments/[invoice].vue | — | ✅ Used |
POST /api/invoices | — | — | ⚠️ Unused |
PUT /api/invoices/{id} | — | — | ⚠️ Unused |
| MediaController | |||
GET /api/member/media/{*storageKey} | — | — | ⚠️ Unused (no frontend call found) |
| MemberAuthController | |||
POST /api/member/auth/login | — | pages/login.vue | ✅ Used |
POST /api/member/auth/logout | — | MembersBand.vue | ✅ Used |
GET /api/member/auth/me | — | — | ⚠️ Unused (no frontend call found) |
| MemberCertificatesController | |||
GET /api/member/certificates | — | pages/account/index.vue | ✅ Used |
| MemberCertificationsController | |||
POST /api/member/certifications | — | UploadCertificateModal.vue | ✅ Used |
| MemberCommunicationsController | |||
GET /api/member/communications/preferences | — | pages/account/index.vue | ✅ Used |
PUT /api/member/communications/preferences | — | EditCommunicationsModal.vue | ✅ Used |
| MemberEventsController | |||
GET /api/member/events/upcoming | — | pages/account/index.vue | ✅ Used |
| MemberInvoicesController | |||
GET /api/member/invoices | — | pages/account/index.vue | ✅ Used |
| MemberMembershipController | |||
GET /api/member/membership/current | — | pages/account/index.vue | ✅ Used |
POST /api/member/membership/renew | — | RenewNowModal.vue | ✅ Used |
| MemberProfileController | |||
GET /api/member/profile | — | pages/account/index.vue | ✅ Used |
GET /api/member/profile/completeness | — | pages/account/index.vue | ✅ Used |
PATCH /api/member/profile | — | EditProfileModal.vue, EditBusinessDetailsModal.vue, FinishProfileModal.vue | ✅ Used |
| MembersController | |||
GET /api/members | — | — | ⚠️ Unused (web uses /api/contacts instead) |
GET /api/members/summary | — | — | ⚠️ Unused |
GET /api/members/export | — | — | ⚠️ Unused (501) |
GET /api/members/{id} | — | — | ⚠️ Unused |
POST /api/members | — | — | ⚠️ Unused |
PUT /api/members/{id} | — | — | ⚠️ Unused |
DELETE /api/members/{id} | — | — | ⚠️ Unused |
| MembershipPlansController | |||
GET /api/membership-plans | contacts/[id].vue | — | ✅ Used |
| MembershipsController | |||
GET /api/memberships | memberships/index.vue | — | ✅ Used |
GET /api/memberships/due | memberships/renewals.vue, renewals/batch.vue | — | ✅ Used |
POST /api/memberships/batch-renew | memberships/renewals.vue, renewals/batch.vue | — | ✅ Used |
POST /api/memberships/{id}/renew | contacts/[id].vue | — | ✅ Used |
GET /api/memberships/{id} | — | — | ⚠️ Unused |
POST /api/memberships | contacts/[id].vue | — | ✅ Used |
PUT /api/memberships/{id} | — | — | ⚠️ Unused |
DELETE /api/memberships/{id} | — | — | ⚠️ Unused |
| PaymentsController | |||
GET /api/payments | — | — | ⚠️ Unused |
GET /api/payments/{id} | — | — | ⚠️ Unused |
POST /api/payments | — | — | ⚠️ Unused |
| PeopleController | |||
GET /api/people | — | — | ⚠️ Unused |
| ReportsController | |||
GET /api/reports | reports/library.vue | — | ✅ Used |
GET /api/reports/recent-runs | reports/index.vue | — | ✅ Used |
GET /api/reports/runs/{runId} | — | — | ⚠️ Unused |
POST /api/reports/{id}/run | reports/library.vue | — | ✅ Used |
Summary
| Category | Count |
|---|---|
| Total API endpoints | 74 |
| ✅ Used by apps/web | 46 |
| ✅ Used by apps/members | 14 |
| ✅ Used by both | 0 (separate auth schemes) |
| ✅ Used externally (health/webhooks) | 2 |
| ⚠️ Unused by any frontend | 22 |
Unused endpoints to investigate
The following endpoints have no frontend consumer and may be candidates for removal, future feature scaffolding, or need a UI built:
- AdminController:
DELETE /api/admin/roles/{id},GET /api/admin/users,POST /api/admin/login-users,GET /api/admin/teams - AuditController:
GET /api/audit/{id} - ContactsController:
GET /api/contacts/export(501),DELETE /api/contacts/{id} - EventsController:
DELETE /api/events/{id} - InvoicesController:
POST /api/invoices(create),PUT /api/invoices/{id}(update) - MediaController:
GET /api/member/media/{*storageKey} - MemberAuthController:
GET /api/member/auth/me - MembersController: all 7 endpoints (the web app redirects
/members/*to/contacts/*and usesContactsControllerexclusively —MembersControllerappears to be a superseded parallel implementation) - MembershipsController:
GET /api/memberships/{id},PUT /api/memberships/{id},DELETE /api/memberships/{id} - PaymentsController: all 3 endpoints (
GET /api/payments,GET /api/payments/{id},POST /api/payments) - PeopleController:
GET /api/people - ReportsController:
GET /api/reports/runs/{runId}