Skip to main content

Membership

:::info Status Implemented. Source: fastapi-backend/api/v1/endpoints/{memberships,invites,join}.py, core/mosque_registration.py. :::

The memberships table records a user's relationship to one mosque — distinct from Mosque Management's admin relationship, and distinct from Device or App Install ownership. An approved membership is what Playback Entitlement is ultimately derived from.

Status state machine

Valid statuses: pending, approved, rejected, banned (core/db.py:VALID_MEMBERSHIP_STATUSES). Only an admin (mosque admin for that mosque, or superadmin) may change status — a member can only edit their own notification toggles (notify_azaan, notify_jummah, notify_waaz, notify_announcement). This split exists specifically so a banned member can't PATCH themself back to approved.

Every status change an admin makes (not the member acting on themself) fires an Expo push notification to the affected member, with copy specific to the transition (e.g. "Membership restored" when moving bannedapproved, vs. "Membership approved" for pendingapproved).

Three ways to become a member

PathEndpointResulting status
Self-service joinPOST /mosques/{id}/joinapproved if the mosque has auto_approve_members, else pending
Join by codePOST /join (body: code)Same auto-approve logic, resolved via db.get_mosque_by_join_code
Admin adds directlyPOST /mosques/{mosque_id}/membershipsAlways approved immediately — there is no admin-initiated pending state
Admin invites by contactPOST /invites (email or WhatsApp/phone contact)approved if auto_approve requested, else pending; creates the user account first if none exists for that contact

Joining (self-service or by code) makes the target mosque the user's only active mosque — a previous mosque's membership is demoted in the same transaction so it stops triggering azaan for that user (core/mosque_registration.py:register_user_with_mosque).

Invite edge case: promoting an existing member to admin

POST /invites with role: "mosque_admin" against a contact that already has an approved membership at the mosque doesn't create a second membership — it adds a mosque-admin row for the existing member (is_owner: false, can_trigger: true, can_manage: true) and returns a 409 if they're already an admin. mosque_admin role invites require auto_approve: true — you can't invite a pending admin.

Leaving / removing

DELETE /memberships/{id} — the member themself, or a mosque admin/ superadmin for that mosque.

API

EndpointPurpose
GET /membershipsCurrent user's own memberships, filterable by status/mosque
PATCH /memberships/{id}Update status (admin) or notification toggles (member, own membership only)
DELETE /memberships/{id}Leave / remove a membership
GET /mosques/{mosque_id}/membershipsAdmin view of a mosque's memberships

Full request/response schemas: API Reference.