Перейти к содержанию

Admin Investment Management Endpoints

Аудитория: разработчики, разработчики админских панелей Последнее обновление: 2025-11-17 Краткое содержание: Детальная документация Admin Investment Management endpoints — просмотр инвестиций, одобрение/отклонение ожидающих, управление жизненным циклом инвестиций. Полное руководство по интеграции для админских операций с инвестициями.


Обзор Endpoints

Метод Endpoint Описание Auth Required Permission
GET /api/admin/investments Список всех инвестиций ✅ Admin investments:read
GET /api/admin/investments/pending Ожидающие инвестиции ✅ Admin investments:read
GET /api/admin/investments/:id Детали инвестиции ✅ Admin investments:read
PUT /api/admin/investments/:id/approve Одобрить инвестицию ✅ Admin investments:approve
PUT /api/admin/investments/:id/reject Отклонить инвестицию ✅ Admin investments:approve

GET /api/admin/investments

Получить постраничный список всех инвестиций платформы с фильтрацией и сортировкой.

Запрос

GET /api/admin/investments?page=1&limit=50&status=active&strategyId=balanced-10&userId=user_123abc
Authorization: Bearer <admin_jwt_token>

Заголовки:

Заголовок Значение Обязательно Описание
Authorization Bearer <admin_token> ✅ Да Admin JWT токен

Query параметры:

Параметр Тип Обязательно Описание По умолчанию
page number ❌ Нет Номер страницы (начинается с 1) 1
limit number ❌ Нет Элементов на странице (макс: 100) 50
status string ❌ Нет Фильтр по статусу: active, pending, completed, cancelled Все
strategyId string ❌ Нет Фильтр по ID стратегии Все
userId string ❌ Нет Фильтр по ID пользователя Все
minAmount string ❌ Нет Фильтр минимальной суммы инвестиции -
sortBy string ❌ Нет Поле сортировки: createdAt, amount, currentValue createdAt
orderBy string ❌ Нет Порядок сортировки: asc, desc desc
createdAfter string ❌ Нет Фильтр инвестиций после даты (ISO 8601) -

Ответ

Успех (200 OK):

{
  "success": true,
  "data": [
    {
      "id": "inv_abc123",
      "userId": "user_123abc",
      "userEmail": "john@example.com",
      "walletAddress": "0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb0",
      "strategyId": "balanced-10",
      "strategyName": "Balanced 10% APY Strategy",
      "amount": "1000.00",
      "currency": "USDC",
      "status": "active",
      "currentValue": "1050.25",
      "totalEarnings": "50.25",
      "roi": 5.025,
      "apy": 10.0,
      "allocation": {
        "pendle": "300.00",
        "curve": "400.00",
        "convex": "300.00"
      },
      "createdAt": "2025-09-15T10:00:00Z",
      "lastUpdatedAt": "2025-10-03T12:00:00Z",
      "approvedBy": "admin_456def",
      "approvedAt": "2025-09-15T10:05:00Z"
    },
    {
      "id": "inv_def456",
      "userId": "user_456def",
      "userEmail": "jane@example.com",
      "walletAddress": "0x8ba1f109551bD432803012645Ac136ddd64DBA72",
      "strategyId": "conservative-5",
      "strategyName": "Conservative 5% APY Strategy",
      "amount": "2000.00",
      "currency": "USDC",
      "status": "pending",
      "currentValue": "2000.00",
      "totalEarnings": "0.00",
      "roi": 0.0,
      "apy": 5.0,
      "allocation": {
        "pendle": "1200.00",
        "curve": "800.00"
      },
      "createdAt": "2025-10-03T11:00:00Z",
      "lastUpdatedAt": "2025-10-03T11:00:00Z",
      "approvedBy": null,
      "approvedAt": null
    }
  ],
  "summary": {
    "totalInvestments": 1250,
    "totalValue": "8500000.00",
    "totalEarnings": "425000.00",
    "activeInvestments": 1100,
    "pendingInvestments": 15,
    "averageInvestment": "6800.00",
    "topStrategy": "balanced-10"
  },
  "pagination": {
    "page": 1,
    "limit": 50,
    "total": 1250,
    "totalPages": 25,
    "hasNext": true,
    "hasPrevious": false
  },
  "timestamp": "2025-10-03T12:34:56Z"
}

Поля ответа:

Поле Тип Описание
data[].currentValue string Текущая стоимость инвестиции (SafeDecimal)
data[].totalEarnings string Пожизненные доходы от инвестиции
data[].roi number Процент возврата инвестиций
data[].allocation object Разбивка по протоколам
summary.totalValue string Общая заблокированная стоимость всех инвестиций
summary.totalEarnings string Доходы от инвестиций на платформе

Ошибки:

Код статуса Код ошибки Описание
401 TOKEN_EXPIRED Admin JWT токен истёк
403 PERMISSION_DENIED Недостаточно разрешений (требуется investments:read)
400 INVALID_PAGINATION Невалидные page или limit

Пример cURL

ADMIN_TOKEN="eyJhbGciOiJIUzI1NiIs..."

# Получить все активные инвестиции
curl -X GET "https://app.saga.surf/api/admin/investments?status=active" \
  -H "Authorization: Bearer $ADMIN_TOKEN"

# Крупные инвестиции (> $10K)
curl -X GET "https://app.saga.surf/api/admin/investments?minAmount=10000&sortBy=amount&orderBy=desc" \
  -H "Authorization: Bearer $ADMIN_TOKEN"

# Инвестиции конкретного пользователя
curl -X GET "https://app.saga.surf/api/admin/investments?userId=user_123abc" \
  -H "Authorization: Bearer $ADMIN_TOKEN"

Пример TypeScript

const fetchAllInvestments = async (filters = {}) => {
  const params = new URLSearchParams({
    page: '1',
    limit: '50',
    ...filters
  });

  const response = await fetch(`/api/admin/investments?${params}`, {
    headers: {
      'Authorization': `Bearer ${adminToken}`
    }
  });

  const { data: investments, summary, pagination } = await response.json();

  console.log('Platform Investment Summary:');
  console.log('  Total Investments:', summary.totalInvestments);
  console.log('  Total Value: $', summary.totalValue);
  console.log('  Total Earnings: $', summary.totalEarnings);
  console.log('  Pending Approvals:', summary.pendingInvestments);

  investments.forEach(inv => {
    console.log(`\n${inv.userEmail} - ${inv.strategyName}`);
    console.log(`  Amount: $${inv.amount} → Current: $${inv.currentValue}`);
    console.log(`  ROI: ${inv.roi.toFixed(2)}% | Earnings: $${inv.totalEarnings}`);
    console.log(`  Status: ${inv.status}`);
  });

  return { investments, summary, pagination };
};

⏳ GET /api/admin/investments/pending

Получить список инвестиций, ожидающих одобрения админа.

Запрос

GET /api/admin/investments/pending?sortBy=createdAt&orderBy=asc
Authorization: Bearer <admin_jwt_token>

Query параметры:

Параметр Тип Обязательно Описание По умолчанию
sortBy string ❌ Нет Поле сортировки: createdAt, amount createdAt
orderBy string ❌ Нет Порядок сортировки: asc, desc asc

Ответ

Успех (200 OK):

{
  "success": true,
  "data": [
    {
      "id": "inv_pending_001",
      "userId": "user_789ghi",
      "userEmail": "alice@example.com",
      "walletAddress": "0x95222290DD7278Aa3Ddd389Cc1E1d165CC4BAfe5",
      "strategyId": "aggressive-20",
      "strategyName": "Aggressive 20% APY Strategy",
      "amount": "5000.00",
      "currency": "USDC",
      "status": "pending",
      "createdAt": "2025-10-03T09:00:00Z",
      "userVerificationStatus": "verified",
      "riskAssessment": {
        "userRiskLevel": "high",
        "strategyRiskLevel": "high",
        "match": true
      },
      "complianceChecks": {
        "kycStatus": "not_required",
        "amlChecks": "passed",
        "sanctionsList": "clear"
      }
    },
    {
      "id": "inv_pending_002",
      "userId": "user_101jkl",
      "userEmail": "bob@example.com",
      "walletAddress": "0x3C44CdDdB6a900fa2b585dd299e03d12FA4293BC",
      "strategyId": "balanced-10",
      "strategyName": "Balanced 10% APY Strategy",
      "amount": "3000.00",
      "currency": "USDC",
      "status": "pending",
      "createdAt": "2025-10-03T10:30:00Z",
      "userVerificationStatus": "verified",
      "riskAssessment": {
        "userRiskLevel": "medium",
        "strategyRiskLevel": "medium",
        "match": true
      },
      "complianceChecks": {
        "kycStatus": "not_required",
        "amlChecks": "passed",
        "sanctionsList": "clear"
      }
    }
  ],
  "summary": {
    "totalPending": 15,
    "totalPendingValue": "45000.00",
    "oldestPending": "2025-10-02T14:00:00Z",
    "averageWaitTime": "2.5 hours"
  },
  "timestamp": "2025-10-03T12:34:56Z"
}

Поля ответа:

Поле Тип Описание
data[].riskAssessment object Оценка соответствия рисков
data[].complianceChecks object Статус KYC/AML соответствия
summary.totalPending number Общее количество ожидающих инвестиций
summary.totalPendingValue string Общая стоимость ожидающих одобрения
summary.averageWaitTime string Среднее время ожидания одобрения

Ошибки:

Код статуса Код ошибки Описание
403 PERMISSION_DENIED Недостаточно разрешений

Пример cURL

ADMIN_TOKEN="eyJhbGciOiJIUzI1NiIs..."
curl -X GET https://app.saga.surf/api/admin/investments/pending \
  -H "Authorization: Bearer $ADMIN_TOKEN"

Пример TypeScript

const fetchPendingInvestments = async () => {
  const response = await fetch('/api/admin/investments/pending', {
    headers: {
      'Authorization': `Bearer ${adminToken}`
    }
  });

  const { data: pending, summary } = await response.json();

  console.log('🔔 Pending Investment Approvals:');
  console.log(`  Total: ${summary.totalPending}`);
  console.log(`  Value: $${summary.totalPendingValue}`);
  console.log(`  Avg Wait: ${summary.averageWaitTime}`);

  pending.forEach(inv => {
    console.log(`\n📋 ${inv.id}`);
    console.log(`  User: ${inv.userEmail}`);
    console.log(`  Amount: $${inv.amount}${inv.strategyName}`);
    console.log(`  Risk Match: ${inv.riskAssessment.match ? '✅' : '⚠️'}`);
    console.log(`  Compliance: ${inv.complianceChecks.amlChecks}`);
  });

  return { pending, summary };
};

GET /api/admin/investments/:id

Получить детальную информацию о конкретной инвестиции.

Запрос

GET /api/admin/investments/inv_abc123
Authorization: Bearer <admin_jwt_token>

Path параметры:

Параметр Тип Обязательно Описание
id string ✅ Да ID инвестиции (например, inv_abc123)

Ответ

Успех (200 OK):

{
  "success": true,
  "data": {
    "id": "inv_abc123",
    "userId": "user_123abc",
    "user": {
      "id": "user_123abc",
      "email": "john@example.com",
      "walletAddress": "0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb0",
      "verificationStatus": "verified",
      "accountCreated": "2025-09-01T10:00:00Z"
    },
    "strategy": {
      "id": "balanced-10",
      "name": "Balanced 10% APY Strategy",
      "apy": 10.0,
      "riskLevel": "medium"
    },
    "investment": {
      "amount": "1000.00",
      "currency": "USDC",
      "currentValue": "1050.25",
      "totalEarnings": "50.25",
      "roi": 5.025,
      "dailyYield": "0.27",
      "estimatedAnnualEarnings": "100.00"
    },
    "allocation": {
      "pendle": {
        "amount": "300.00",
        "currentValue": "315.08",
        "earnings": "15.08",
        "apy": 7.0
      },
      "curve": {
        "amount": "400.00",
        "currentValue": "420.10",
        "earnings": "20.10",
        "apy": 5.0
      },
      "convex": {
        "amount": "300.00",
        "currentValue": "315.07",
        "earnings": "15.07",
        "apy": 15.0
      }
    },
    "performance": {
      "last7Days": {
        "earnings": "1.89",
        "roi": 0.189
      },
      "last30Days": {
        "earnings": "8.10",
        "roi": 0.81
      },
      "allTime": {
        "earnings": "50.25",
        "roi": 5.025
      }
    },
    "status": "active",
    "lifecycle": {
      "createdAt": "2025-09-15T10:00:00Z",
      "approvedAt": "2025-09-15T10:05:00Z",
      "approvedBy": "admin_456def",
      "lastUpdatedAt": "2025-10-03T12:00:00Z"
    },
    "transactions": [
      {
        "id": "tx_001",
        "type": "investment",
        "amount": "-1000.00",
        "timestamp": "2025-09-15T10:05:00Z",
        "txHash": "0xabcd1234..."
      },
      {
        "id": "tx_002",
        "type": "earning",
        "amount": "+0.27",
        "timestamp": "2025-10-03T00:00:00Z",
        "description": "Daily yield"
      }
    ],
    "complianceInfo": {
      "kycStatus": "not_required",
      "amlChecks": "passed",
      "sanctionsList": "clear",
      "lastChecked": "2025-09-15T10:00:00Z"
    }
  },
  "timestamp": "2025-10-03T12:34:56Z"
}

Поля ответа:

Поле Тип Описание
data.allocation object Разбивка по протоколам
data.performance object Исторические метрики производительности
data.transactions array Транзакции связанные с инвестицией
data.complianceInfo object Детали проверки соответствия

Ошибки:

Код статуса Код ошибки Описание
403 PERMISSION_DENIED Недостаточно разрешений
404 INVESTMENT_NOT_FOUND ID инвестиции не существует

Пример cURL

ADMIN_TOKEN="eyJhbGciOiJIUzI1NiIs..."
curl -X GET https://app.saga.surf/api/admin/investments/inv_abc123 \
  -H "Authorization: Bearer $ADMIN_TOKEN"

PUT /api/admin/investments/:id/approve

Одобрить ожидающую инвестицию и инициировать blockchain распределение.

Запрос

PUT /api/admin/investments/inv_pending_001/approve
Authorization: Bearer <admin_jwt_token>
Content-Type: application/json

{
  "note": "Risk assessment verified, user KYC clear",
  "notifyUser": true
}

Схема тела запроса:

Поле Тип Обязательно Описание
note string ❌ Нет Заметка админа об одобрении (внутренняя)
notifyUser boolean ❌ Нет Отправить email уведомление (по умолчанию: true)

Ответ

Успех (200 OK):

{
  "success": true,
  "data": {
    "investmentId": "inv_pending_001",
    "status": "active",
    "approvedAt": "2025-10-03T12:34:56Z",
    "approvedBy": "admin_456def",
    "allocation": {
      "pendle": "1000.00",
      "curve": "2000.00",
      "convex": "2000.00"
    },
    "blockchainTransactions": [
      {
        "protocol": "pendle",
        "txHash": "0xabcd1234...",
        "status": "confirmed",
        "amount": "1000.00"
      },
      {
        "protocol": "curve",
        "txHash": "0xef567890...",
        "status": "confirmed",
        "amount": "2000.00"
      },
      {
        "protocol": "convex",
        "txHash": "0x12345678...",
        "status": "confirmed",
        "amount": "2000.00"
      }
    ],
    "user": {
      "email": "alice@example.com",
      "notified": true
    }
  },
  "timestamp": "2025-10-03T12:34:56Z"
}

Поля ответа:

Поле Тип Описание
data.blockchainTransactions array On-chain транзакции распределения
data.user.notified boolean Статус отправки email уведомления

Ошибки:

Код статуса Код ошибки Описание
400 INVALID_STATUS Инвестиция не в статусе pending
403 PERMISSION_DENIED Недостаточно разрешений (требуется investments:approve)
404 INVESTMENT_NOT_FOUND ID инвестиции не существует
422 BLOCKCHAIN_ERROR Blockchain распределение провалилось

Пример cURL

ADMIN_TOKEN="eyJhbGciOiJIUzI1NiIs..."
curl -X PUT https://app.saga.surf/api/admin/investments/inv_pending_001/approve \
  -H "Authorization: Bearer $ADMIN_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "note": "Risk assessment verified, user KYC clear",
    "notifyUser": true
  }'

Пример TypeScript

const approveInvestment = async (investmentId: string, note?: string) => {
  const response = await fetch(`/api/admin/investments/${investmentId}/approve`, {
    method: 'PUT',
    headers: {
      'Authorization': `Bearer ${adminToken}`,
      'Content-Type': 'application/json'
    },
    body: JSON.stringify({
      note,
      notifyUser: true
    })
  });

  if (!response.ok) {
    const error = await response.json();
    throw new Error(error.error.message);
  }

  const { data } = await response.json();

  console.log('✅ Investment Approved:');
  console.log(`  Investment ID: ${data.investmentId}`);
  console.log(`  Status: ${data.status}`);
  console.log(`  Approved By: ${data.approvedBy}`);
  console.log('\n📊 Blockchain Allocation:');
  data.blockchainTransactions.forEach(tx => {
    console.log(`  ${tx.protocol}: $${tx.amount} (${tx.status})`);
    console.log(`    TX: ${tx.txHash}`);
  });
  console.log(`\n📧 User notified: ${data.user.notified}`);

  return data;
};

// Использование
await approveInvestment('inv_pending_001', 'Risk verified');

PUT /api/admin/investments/:id/reject

Отклонить ожидающую инвестицию с указанием причины.

Запрос

PUT /api/admin/investments/inv_pending_002/reject
Authorization: Bearer <admin_jwt_token>
Content-Type: application/json

{
  "reason": "User risk level does not match aggressive strategy requirements",
  "notifyUser": true
}

Схема тела запроса:

Поле Тип Обязательно Описание
reason string ✅ Да Причина отклонения (видна пользователю)
notifyUser boolean ❌ Нет Отправить email уведомление (по умолчанию: true)

Ответ

Успех (200 OK):

{
  "success": true,
  "data": {
    "investmentId": "inv_pending_002",
    "status": "rejected",
    "rejectedAt": "2025-10-03T12:34:56Z",
    "rejectedBy": "admin_456def",
    "reason": "User risk level does not match aggressive strategy requirements",
    "refund": {
      "amount": "3000.00",
      "currency": "USDC",
      "processedAt": "2025-10-03T12:35:00Z",
      "txHash": "0x9876abcd...",
      "status": "completed"
    },
    "user": {
      "email": "bob@example.com",
      "notified": true
    }
  },
  "timestamp": "2025-10-03T12:34:56Z"
}

Поля ответа:

Поле Тип Описание
data.refund object Детали автоматической возвратной транзакции
data.reason string Причина отклонения (видна пользователю)

Ошибки:

Код статуса Код ошибки Описание
400 INVALID_STATUS Инвестиция не в статусе pending
400 REASON_REQUIRED Причина отклонения обязательна
403 PERMISSION_DENIED Недостаточно разрешений (требуется investments:approve)
404 INVESTMENT_NOT_FOUND ID инвестиции не существует
422 REFUND_FAILED Blockchain возврат средств провалился

Пример cURL

ADMIN_TOKEN="eyJhbGciOiJIUzI1NiIs..."
curl -X PUT https://app.saga.surf/api/admin/investments/inv_pending_002/reject \
  -H "Authorization: Bearer $ADMIN_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "reason": "User risk level does not match aggressive strategy requirements",
    "notifyUser": true
  }'

Пример TypeScript

const rejectInvestment = async (investmentId: string, reason: string) => {
  const response = await fetch(`/api/admin/investments/${investmentId}/reject`, {
    method: 'PUT',
    headers: {
      'Authorization': `Bearer ${adminToken}`,
      'Content-Type': 'application/json'
    },
    body: JSON.stringify({
      reason,
      notifyUser: true
    })
  });

  if (!response.ok) {
    const error = await response.json();
    throw new Error(error.error.message);
  }

  const { data } = await response.json();

  console.log('❌ Investment Rejected:');
  console.log(`  Investment ID: ${data.investmentId}`);
  console.log(`  Rejected By: ${data.rejectedBy}`);
  console.log(`  Reason: ${data.reason}`);
  console.log('\n💰 Automatic Refund:');
  console.log(`  Amount: $${data.refund.amount}`);
  console.log(`  Status: ${data.refund.status}`);
  console.log(`  TX: ${data.refund.txHash}`);
  console.log(`\n📧 User notified: ${data.user.notified}`);

  return data;
};

// Использование
await rejectInvestment(
  'inv_pending_002',
  'User risk level does not match strategy requirements'
);

Связанная документация

Другие Admin Endpoints:

User Endpoints:

Архитектура:




📋 Метаданные

Версия: 2.6.268

Обновлено: 2025-10-21

Статус: Published