Skip to content

Investment Participation Flow

Complete user journey from strategy discovery to active investment management.

Overview

The investment flow includes:

  1. Strategy discovery and research
  2. Participation initiation
  3. Multi-step participation process
  4. Payment and confirmation
  5. Portfolio management
  6. Returns tracking and maturity handling

Main Flow Diagram


Step Details

1. Strategy Discovery

Endpoint: GET /strategies

Query Parameters:

ParameterTypeDescription
categorystringCategory slug
riskLevelstringLOW, MEDIUM, HIGH, VERY_HIGH
minAmountnumberMinimum investment filter
maxReturnnumberMaximum expected return filter
durationstringSHORT (< 6mo), MEDIUM (6-12mo), LONG (> 12mo)
sortstringpopular, newest, return_desc, min_amount_asc
pagenumberPage number
limitnumberItems per page

Strategy List Item:

json
{
  "id": "uuid",
  "name": "Commercial Real Estate Fund",
  "slug": "commercial-real-estate-fund",
  "shortDescription": "Diversified portfolio of commercial properties",
  "riskLevel": "MEDIUM",
  "minAmount": 50000.00,
  "expectedReturnMin": 12.0,
  "expectedReturnMax": 18.0,
  "durationMonths": 24,
  "imageUrl": "https://cdn.../strategy.jpg",
  "participantsCount": 245,
  "totalInvested": 15000000.00,
  "status": "ACTIVE"
}

2. Strategy Details

Endpoint: GET /strategies/{slug}

Response:

json
{
  "id": "uuid",
  "name": "Commercial Real Estate Fund",
  "slug": "commercial-real-estate-fund",
  "shortDescription": "Diversified portfolio of commercial properties",
  "description": "Full HTML description with investment thesis...",
  "terms": "Full terms and conditions...",
  "riskLevel": "MEDIUM",
  "riskDisclosure": "Investment risks description...",
  "minAmount": 50000.00,
  "maxAmount": 5000000.00,
  "durationMonths": 24,
  "expectedReturnMin": 12.0,
  "expectedReturnMax": 18.0,
  "payoutSchedule": "QUARTERLY",
  "earlyWithdrawalAllowed": true,
  "earlyWithdrawalPenalty": 5.0,
  "documents": [
    {
      "name": "Investment Memorandum",
      "type": "PDF",
      "url": "https://cdn.../memorandum.pdf"
    },
    {
      "name": "Risk Disclosure Statement",
      "type": "PDF",
      "url": "https://cdn.../risk-disclosure.pdf"
    }
  ],
  "participationSteps": [
    {
      "stepNumber": 1,
      "title": "Select Investment Amount",
      "stepType": "FORM",
      "isRequired": true
    },
    {
      "stepNumber": 2,
      "title": "Review Terms & Risk Disclosure",
      "stepType": "CONFIRMATION",
      "isRequired": true
    },
    {
      "stepNumber": 3,
      "title": "Payment",
      "stepType": "PAYMENT",
      "isRequired": true
    }
  ],
  "category": {
    "id": "uuid",
    "name": "Real Estate",
    "slug": "real-estate"
  },
  "stats": {
    "participantsCount": 245,
    "totalInvested": 15000000.00,
    "averageInvestment": 61224.49
  },
  "status": "ACTIVE",
  "publishedAt": "2024-01-01T00:00:00Z"
}

3. Start Participation

Endpoint: POST /strategies/{id}/participate

Eligibility Requirements:

RequirementCheck
User authenticatedValid JWT token
Email verifieduser.email_verified_at IS NOT NULL
KYC approvedkyc_verification.status = 'APPROVED'
KYC level sufficientBased on investment amount
No pending participationFor same strategy

KYC Level Requirements:

KYC LevelMax Investment
BASICNot allowed
STANDARD1,000,000 RUB
ENHANCEDUnlimited

Response:

json
{
  "participationId": "uuid",
  "strategyId": "uuid",
  "currentStep": 1,
  "totalSteps": 3,
  "status": "IN_PROGRESS",
  "nextStep": {
    "stepNumber": 1,
    "title": "Select Investment Amount",
    "stepType": "FORM",
    "config": {
      "minAmount": 50000,
      "maxAmount": 5000000,
      "currency": "RUB",
      "suggestedAmounts": [50000, 100000, 250000, 500000]
    }
  }
}

4. Step 1: Select Amount

Endpoint: POST /participations/{id}/steps/1

Request:

json
{
  "amount": 100000.00,
  "currency": "RUB"
}

Validation Rules:

RuleConstraint
Amount>= strategy.min_amount
Amount<= strategy.max_amount (if set)
Amount<= user's KYC level limit
CurrencyMust match strategy currency

Error Scenarios:

ScenarioError CodeMessage
Below minimumBELOW_MINIMUM"Minimum investment is X RUB"
Above maximumABOVE_MAXIMUM"Maximum investment is X RUB"
KYC limit exceededKYC_LIMIT_EXCEEDED"Upgrade KYC for larger investments"

5. Step 2: Review Terms

Endpoint: POST /participations/{id}/steps/2

Request:

json
{
  "acceptTerms": true,
  "acceptRiskDisclosure": true,
  "acknowledgeNoGuarantee": true,
  "confirmOwnFunds": true
}

Required Acknowledgments:

FieldDescription
acceptTermsAccept investment terms
acceptRiskDisclosureAcknowledge risk disclosure
acknowledgeNoGuaranteeUnderstand returns not guaranteed
confirmOwnFundsConfirm using own funds

Recorded Data:

json
{
  "termsAcceptedAt": "2024-01-15T10:30:00Z",
  "riskDisclosureAcceptedAt": "2024-01-15T10:30:00Z",
  "ipAddress": "192.168.1.1",
  "userAgent": "Mozilla/5.0..."
}

6. Step 3: Payment

Create Payment Intent: POST /participations/{id}/payment/intent

Response:

json
{
  "paymentIntentId": "pi_xxx",
  "clientSecret": "pi_xxx_secret_xxx",
  "amount": 100000.00,
  "currency": "RUB",
  "paymentMethods": ["card", "bank_transfer"]
}

Payment Processing:

  1. Frontend creates Stripe Elements form
  2. User enters payment details
  3. Frontend calls stripe.confirmPayment()
  4. Stripe sends webhook to backend
  5. Backend updates participation status

Payment Confirmation:

  • Status changes to PENDING_APPROVAL
  • Participation submitted_at is set
  • User receives confirmation email

7. Confirmation and Activation

Approval Methods:

MethodCriteria
Auto-approvalAmount < 100,000 RUB, user has previous investments
Manual approvalAmount >= 100,000 RUB or first-time investor

Portfolio Record Created:

json
{
  "id": "uuid",
  "userId": "user-uuid",
  "participationId": "participation-uuid",
  "strategyId": "strategy-uuid",
  "investedAmount": 100000.00,
  "currentValue": 100000.00,
  "totalReturns": 0.00,
  "currency": "RUB",
  "status": "ACTIVE",
  "startDate": "2024-01-15",
  "maturityDate": "2026-01-15"
}

Commission Triggered:

  • Commission job enqueued for MLM processing
  • Referring partner receives commission
  • See Commission Lifecycle

8. Portfolio Dashboard

Endpoint: GET /users/me/portfolio

Response:

json
{
  "summary": {
    "totalInvested": 350000.00,
    "currentValue": 378500.00,
    "totalReturns": 28500.00,
    "overallReturnPercent": 8.14,
    "currency": "RUB"
  },
  "investments": [
    {
      "id": "portfolio-uuid",
      "strategyName": "Commercial Real Estate Fund",
      "strategySlug": "commercial-real-estate-fund",
      "investedAmount": 100000.00,
      "currentValue": 108500.00,
      "totalReturns": 8500.00,
      "returnPercent": 8.5,
      "status": "ACTIVE",
      "startDate": "2024-01-15",
      "maturityDate": "2026-01-15",
      "daysToMaturity": 365,
      "nextPayoutDate": "2024-04-15",
      "nextPayoutEstimate": 3000.00
    }
  ],
  "recentActivity": [
    {
      "type": "RETURN_CREDITED",
      "amount": 3000.00,
      "date": "2024-01-01",
      "portfolioId": "portfolio-uuid"
    }
  ]
}

9. Returns Tracking

Returns Calculation Schedule:

  • Daily: Update current_value based on strategy NAV
  • Quarterly: Credit returns to user balance (if payout schedule is QUARTERLY)

Returns History Endpoint: GET /portfolio/{id}/returns

Response:

json
{
  "portfolioId": "uuid",
  "investedAmount": 100000.00,
  "currentValue": 108500.00,
  "totalReturns": 8500.00,
  "history": [
    {
      "period": "2024-Q1",
      "startValue": 100000.00,
      "endValue": 103000.00,
      "returnAmount": 3000.00,
      "returnPercent": 3.0,
      "paidOut": true,
      "paidDate": "2024-04-01"
    }
  ],
  "projectedAnnualReturn": 12.0
}

10. Maturity Handling

Maturity Check: Scheduled job runs daily at 00:00 UTC

Maturity Options:

Option A: Withdraw

json
POST /portfolio/{id}/withdraw
{
  "withdrawalMethod": "BANK_TRANSFER",
  "bankDetails": {
    "accountNumber": "40817810xxx",
    "bankName": "Sberbank",
    "bik": "044525225"
  }
}

Option B: Reinvest

json
POST /portfolio/{id}/reinvest
{
  "strategyId": "same-or-different-uuid",
  "amount": "FULL",
  "additionalAmount": 0
}

Reinvestment Options:

OptionDescription
Same strategyContinue in current strategy
Different strategyMove to another strategy
Partial reinvestWithdraw some, reinvest rest

11. Early Withdrawal

Endpoint: POST /portfolio/{id}/early-withdraw

Early Withdrawal Rules:

ConditionPenalty
Strategy allows early withdrawalstrategy.early_withdrawal_penalty (e.g., 5%)
Before 6 monthsAdditional 2% penalty
Before 3 monthsAdditional 5% penalty

Request:

json
{
  "amount": "FULL",
  "withdrawalMethod": "BANK_TRANSFER",
  "acknowledgedPenalty": true
}

Penalty Calculation Response:

json
{
  "currentValue": 108500.00,
  "penaltyPercent": 5.0,
  "penaltyAmount": 5425.00,
  "netWithdrawal": 103075.00,
  "confirmationRequired": true,
  "confirmationUrl": "/portfolio/{id}/early-withdraw/confirm"
}

Error Scenarios

Participation Errors

ScenarioHTTP CodeError CodeMessage
KYC not approved403KYC_REQUIRED"Complete identity verification first"
KYC level insufficient403KYC_UPGRADE_REQUIRED"Upgrade KYC for this investment amount"
Strategy closed422STRATEGY_CLOSED"This strategy is no longer accepting investments"
Already participating409ALREADY_PARTICIPATING"You have a pending participation"

Payment Errors

ScenarioHTTP CodeError CodeMessage
Payment declined422PAYMENT_DECLINED"Payment was declined"
Payment timeout408PAYMENT_TIMEOUT"Payment session expired"
Amount mismatch400AMOUNT_MISMATCH"Payment amount does not match"

Withdrawal Errors

ScenarioHTTP CodeError CodeMessage
Early withdrawal not allowed403EARLY_WITHDRAWAL_DISABLED"This strategy does not allow early withdrawal"
Already processing409WITHDRAWAL_PENDING"A withdrawal is already in progress"
Insufficient balance422INSUFFICIENT_BALANCE"Investment value is insufficient"