Skip to content

Investments

An investment is created in active status immediately — funded synchronously from the owner’s main balance. There are three creation modes: one_time, recurring (auto-debit on a schedule), or saving_goal_conversion (a maturing saving goal becomes an investment). Withdrawals follow a notice flow before the investment moves to withdrawn.

Investments stay in active while the principal sits in the investment holding and earns ROI on the configured cycle (monthly, quarterly, or yearly). Recurring investments can be paused and resumed; one-time and conversion investments cannot. Any investment can be cancelled by the creator, and any active investment can move to withdrawn once the notice flow has run and the funds are released back to the main balance.

stateDiagram-v2
    direction LR

    [*] --> active: POST /v1/investments<br/>(funded from main balance)

    active --> paused: PATCH /:id/pause<br/>{ pause: true }<br/>(recurring only)
    paused --> active: PATCH /:id/pause<br/>{ pause: false }

    active --> withdrawn: withdrawal notice<br/>granted · funds<br/>released

    active --> cancelled: DELETE /:id<br/>(creator)
    paused --> cancelled: DELETE /:id

    withdrawn --> [*]
    cancelled --> [*]

    note right of active
        Three creation modes:
        one-time, recurring,
        or saving goal
        conversion.
        ROI cycle: monthly,
        quarterly, yearly.
    end note

    note right of withdrawn
        Withdrawal goes through
        notice → eligible →
        granted before funds
        return to the main balance.
    end note

Funding is synchronous: debit the main balance, credit the investment holding, status active. Withdrawal requires a two-step notice: the owner sends a withdrawal-notice request, an admin marks it eligible, and the owner then calls the platform-wide withdrawal endpoint with reference_type: "investment".

---
config:
  sequence:
    actorMargin: 380
    width: 240
    messageMargin: 38
    boxMargin: 14
    noteMargin: 12
---
sequenceDiagram
    autonumber
    actor U as Investor
    actor AD as Moria Admin
    participant API as Moria API

    Note over U,API: Create and fund<br/>• funded synchronously from the main balance<br/>• one-time, recurring, or saving goal conversion

    U->>API: POST /v1/investments<br/>{ amount, type: "one_time",<br/>roi_cycle: "monthly", product_id }
    API->>API: debit main balance<br/>credit investment holding
    API-->>U: 201 Created<br/>{ id, status: "active", funded_amount }

    Note over U,API: Read schedule and progress at any time
    U->>API: GET /v1/investments/:id/schedule
    API-->>U: 200 OK<br/>{ next_roi_date, projected_returns[] }

    Note over U,AD: Withdrawal notice<br/>(notice must be granted before payout)
    U->>API: POST /v1/investments/:id/withdrawal-notice
    API-->>U: 201 Created<br/>{ notice_id, status: "pending" }

    AD->>API: PATCH /v1/investments/withdrawal-notices/mark-eligible<br/>{ notice_ids: [...] }
    API-->>AD: 200 OK<br/>{ updated: N }

    U->>API: POST /v1/withdrawals<br/>{ reference_type: "investment", reference_id, amount }
    API-->>U: 200 OK<br/>{ status: "approved" }<br/>(main balance credited)