The Charitable Cause module enables crowdfunding projects: organizations or individuals register a cause (funding target, regulations, benefit), assign managers, and receive donations. User-facing endpoints live in CharitableCauseController (/charitable-causes) for CRUD + assign manager. Admin endpoints live in CharitableCauseAdminController for summary, cause approval, and allocation of open donations (donations without a specific cause) to ACTIVE causes.
Property
Value
Base URL
{HOST}/v1
Auth
Bearer JWT (header Authorization) or cookie access_token
Typical flow: create cause → platform admin approves → donor contributes via the payments module (donation flow) → the creator may assign additional managers. Donations without a specific cause (type OPEN) are pooled and allocated by MORIA superadmin via the admin endpoint POST /donations/allocate.
Method
Path
Auth
Summary
GET
/v1/charitable-causes
bearer
List causes (scoped by role)
GET
/v1/charitable-causes/:id
bearer
Detail of a single cause
POST
/v1/charitable-causes
bearer
Create a new cause
PATCH
/v1/charitable-causes/:id
bearer
Update a cause
DELETE
/v1/charitable-causes/:id
bearer
Deactivate (soft-cancel)
POST
/v1/charitable-causes/:id/assign-manager
bearer
Assign an additional manager
GET
/v1/summary/charitable-causes
bearer
Statistics summary (admin)
GET
/v1/donations/open
bearer
List open donations (MORIA only)
POST
/v1/donations/allocate
bearer
Allocate a batch of open donations to a cause (MORIA only)
INDIVIDUAL — controlled by the scope param. Default (marketplace) returns donatable causes (approved, active, in_progress) within the caller’s own organization — the browse/donate view. scope=mine returns the causes the caller created/owns across all statuses (so a creator can track a still-pending submission).
ORGANIZATION admin — the org’s causes (all statuses), for review/approval.
MORIA — all causes.
Web / mobile — honors x-client-type (default mobile). See Client types (web vs mobile) for the full rules. Concretely: web nests audit fields as created/updated/deleted{ at, by } objects, replaces relations with formatted manager/organization objects, and exposes the attached photo_document/video_document/report/signature (each as { id, created, document_type, document(url) } when present); mobile returns the raw entity with flat created_at/updated_at + created_by/updated_by/deleted_by and foreign-key ids (organization_id, owner_id, user_id, account_id, address_id). Both clients include the document slots (photo_document/video_document/report/signature) — web formatted, mobile as the raw Documents row (or null).
INDIVIDUAL only.marketplace (default) → donatable causes in the caller’s org; mine → causes the caller created/owns, all statuses. Ignored for ORGANIZATION/MORIA.
status
enum CharitableCauseStatus
optional
Explicit status filter; overrides the default set (all means no filter). For marketplace the default set is approved/active/in_progress; for mine it is all statuses.
order
'asc' | 'desc'
desc
Sort by created_at
organization_id
string (UUID)
optional
Marketplace lookup; INDIVIDUAL may only use their own organization
photo_document is an array of raw Documents rows (cause images; [] when none, currently capped at one): e.g. photo_document: [{ "id": "…", "url": "https://s3-dev.moriafund.com/moria-bucket-dev/image/….jpg", "document_type": "image", … }]. The single-slot documents (video_document/report/signature) return the raw Documents row (or null). In all cases the url is the absolute, ready-to-use public URL — no need to prepend a base. The web shape formats each (and photo_document stays an array of formatted docs).
Detail of a single cause. Response format differs between MOBILE (raw) and WEB (formatted with aggregation). Scope organization_id is passed from the user.
Web / mobile — honors x-client-type (default mobile). See Client types (web vs mobile) for the full rules. Concretely: web nests audit fields as created/updated/deleted{ at, by } objects, replaces relations with formatted manager/organization objects, exposes the attached photo_document/video_document/report/signature (each as { id, created, document_type, document(url) } when present), and returns the contributions summary under donations; mobile returns the raw entity with flat audit columns + foreign-key ids (organization_id, owner_id, user_id, account_id, address_id) and the summary under member_contributions (documents are still attached as FK-resolved fields).
Create a new cause. Ownership is always derived from the JWT (Architecture B): INDIVIDUAL → individual-owned cause with the caller’s address; ORGANIZATION → organization-owned cause with the org address. Org admins may pass an optional user_id to create an individual-owned cause on behalf of a member of their own organization (the cause address is taken from that user). The initial status is pending until a MORIA admin approves it.
New. Only meaningful when the caller is an organization admin — create an INDIVIDUAL-owned cause on behalf of a member of the admin’s own organization. Ignored for individual callers (must match own user.id if sent — otherwise 403). When omitted, an org caller creates an ORGANIZATION-owned cause and an individual caller creates a cause for themselves.
Validation failed (non-numeric target_amount, required field empty, legacy account_id/organization_id field sent)
401 Unauthorized
Bearer/cookie token invalid
403 Forbidden
Missing create-charitable-cause permission · individual caller sent a user_id that does not match their own · org admin sent a user_id for a user outside their organization
Designate another user as a manager of the cause. Only the creator is allowed — additional managers may update the cause but may not assign further managers.
Allocate a batch of OPEN donations to a single active cause. Atomic — if any donation is invalid (already allocated / cause not active), the entire batch is rolled back.