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¶
Получить детальную информацию о конкретной инвестиции.
Запрос¶
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:
- Admin Auth - Админская аутентификация
- Admin Users - Управление пользователями
- Admin Withdrawals - Управление выводами
- Admin Dashboard - Метрики панели управления
User Endpoints:
- User Investments - Пользовательские операции с инвестициями
- User Strategies - Доступные стратегии
Архитектура:
- Investment Lifecycle - Поток инвестирования
📋 Метаданные¶
Версия: 2.6.268
Обновлено: 2025-10-21
Статус: Published