Skip to content

API MLM

Общая информация

Базовый URL

/api/v1/mlm

Заголовок аутентификации

Authorization: Bearer <access_token>

Формат ответа

Все ответы следуют стандартному формату:

typescript
// Успешный ответ
interface SuccessResponse<T> {
  success: true;
  data: T;
  meta?: {
    pagination?: PaginationMeta;
    [key: string]: unknown;
  };
}

// Ответ с ошибкой
interface ErrorResponse {
  success: false;
  error: {
    code: string;
    message: string;
    details?: Record<string, string[]>;
  };
}

Формат пагинации

typescript
interface PaginationMeta {
  total: number;
  page: number;
  pageSize: number;
  totalPages: number;
  hasNext: boolean;
  hasPrevious: boolean;
}

Ограничения запросов

ЭндпоинтЛимит
Общие эндпоинты MLM100/мин
POST /payouts/request1/мин на пользователя
Запросы сети50/мин

Заголовки ограничения запросов для финансовых эндпоинтов

X-RateLimit-Limit: 1
X-RateLimit-Remaining: 0
X-RateLimit-Reset: 1705329600
X-RateLimit-Policy: financial

Эндпоинты партнёра

POST /api/v1/mlm/partner/register

Регистрация в качестве партнёра (Консультанта) в MLM сети. Новые партнёры начинают с Ранга 0 (Консультант) со ставкой 3%.

Аутентификация: Обязательна

Лимит запросов: 100 запросов в минуту

Заголовки запроса

Authorization: Bearer <access_token>

Тело запроса

typescript
interface PartnerRegisterRequest {
  referralCode?: string; // Реферальный код спонсора (опционально)
  acceptPartnerTerms: boolean; // Должно быть true
}

Параметры запроса

Нет

Ответ (201 Created)

typescript
interface PartnerRegisterResponse {
  partnerId: string;
  referralCode: string;
  status: "ACTIVE";
  rank: {
    code: string;
    name: string;
    level: number;
    personalSalesRate: number;
    passiveIncomeRate: number;
  };
  sponsor: {
    id: string;
    name: string;
  } | null;
  createdAt: string;
}

Ошибки

СтатусКодОписание
400VALIDATION_ERRORУсловия не приняты
401UNAUTHORIZEDНедействительный или истёкший токен доступа
404INVALID_REFERRAL_CODEРеферальный код спонсора не найден
409ALREADY_PARTNERПользователь уже зарегистрирован как партнёр
403KYC_REQUIREDТребуется KYC верификация для регистрации партнёра

Пример

Запрос:

bash
curl -X POST https://api.iwm-platform.com/api/v1/mlm/partner/register \
  -H "Authorization: Bearer eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9..." \
  -H "Content-Type: application/json" \
  -d '{
    "referralCode": "ABC123XY",
    "acceptPartnerTerms": true
  }'

Ответ:

json
{
  "success": true,
  "data": {
    "partnerId": "cc0e8400-e29b-41d4-a716-446655440000",
    "referralCode": "DEF456ZW",
    "status": "ACTIVE",
    "rank": {
      "code": "0",
      "name": "Консультант",
      "level": 0,
      "personalSalesRate": 3.0,
      "passiveIncomeRate": 0.0
    },
    "sponsor": {
      "id": "dd0e8400-e29b-41d4-a716-446655440000",
      "name": "Иванова Мария"
    },
    "createdAt": "2024-01-15T10:00:00Z"
  }
}

GET /api/v1/mlm/partner/me

Получение профиля текущего партнёра.

Аутентификация: Обязательна (Партнёр)

Лимит запросов: 100 запросов в минуту

Заголовки запроса

Authorization: Bearer <access_token>

Тело запроса

Нет

Параметры запроса

Нет

Ответ (200 OK)

typescript
interface PartnerProfileResponse {
  id: string;
  userId: string;
  referralCode: string;
  status: "PENDING" | "ACTIVE" | "SUSPENDED" | "TERMINATED";
  currentRank: {
    id: string;
    name: string;
    code: string; // "0", "1", "2", ..., "4_PRO", "5", "5_PRO", ... "11", "11_PRO"
    level: number; // 0-21
    personalSalesRate: number; // 3% - 20%
    passiveIncomeRate: number; // 0% - 20%
    entranceFeeRate: number; // 10.5% - 20%
    badgeUrl: string | null;
  } | null;
  highestRank: {
    id: string;
    name: string;
    code: string;
    level: number;
  } | null;
  sponsor: {
    id: string;
    name: string;
    rank: string | null;
  } | null;
  stats: {
    directReferralsCount: number;
    totalNetworkSize: number;
    maxDepth: number; // Неограниченная глубина
  };
  isActivated: boolean; // true если Ранг 1+ (совершена покупка на $1,100)
  joinedAt: string;
  activatedAt: string | null;
}

Ошибки

СтатусКодОписание
401UNAUTHORIZEDНедействительный или истёкший токен доступа
403NOT_A_PARTNERПользователь не зарегистрирован как партнёр

Пример

Запрос:

bash
curl -X GET https://api.iwm-platform.com/api/v1/mlm/partner/me \
  -H "Authorization: Bearer eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9..."

Ответ:

json
{
  "success": true,
  "data": {
    "id": "cc0e8400-e29b-41d4-a716-446655440000",
    "userId": "550e8400-e29b-41d4-a716-446655440000",
    "referralCode": "DEF456ZW",
    "status": "ACTIVE",
    "currentRank": {
      "id": "ee0e8400-e29b-41d4-a716-446655440001",
      "name": "Консультант 5",
      "code": "5",
      "level": 9,
      "personalSalesRate": 14.0,
      "passiveIncomeRate": 14.0,
      "entranceFeeRate": 13.5,
      "badgeUrl": "https://cdn.iwm-platform.com/badges/rank-5.png"
    },
    "highestRank": {
      "id": "ee0e8400-e29b-41d4-a716-446655440001",
      "name": "Консультант 5",
      "code": "5",
      "level": 9
    },
    "sponsor": {
      "id": "dd0e8400-e29b-41d4-a716-446655440000",
      "name": "Иванова Мария",
      "rank": "Консультант 6"
    },
    "stats": {
      "directReferralsCount": 15,
      "totalNetworkSize": 87,
      "maxDepth": 7
    },
    "isActivated": true,
    "joinedAt": "2024-01-15T10:00:00Z",
    "activatedAt": "2024-01-15T10:00:00Z"
  }
}

PATCH /api/v1/mlm/partner/me

Обновление профиля партнёра.

Аутентификация: Обязательна (Партнёр)

Лимит запросов: 100 запросов в минуту

Заголовки запроса

Authorization: Bearer <access_token>

Тело запроса

typescript
interface UpdatePartnerRequest {
  payoutDetails?: {
    method: "BANK_CARD" | "BANK_TRANSFER" | "CRYPTO";
    cardNumber?: string; // Для BANK_CARD
    bankName?: string; // Для BANK_TRANSFER
    bankSwift?: string; // Для BANK_TRANSFER
    accountNumber?: string; // Для BANK_TRANSFER
    cryptoNetwork?: string; // Для CRYPTO (например, 'USDT_TRC20', 'USDT_ERC20')
    walletAddress?: string; // Для CRYPTO
  };
}

Параметры запроса

Нет

Ответ (200 OK)

typescript
interface UpdatePartnerResponse {
  id: string;
  payoutDetails: {
    method: string;
    maskedDetails: string; // например, "**** **** **** 1234" или "TRC20: T***...xyz"
    lastUpdated: string;
  } | null;
  updatedAt: string;
}

Ошибки

СтатусКодОписание
400VALIDATION_ERRORНеверные данные для выплаты
401UNAUTHORIZEDНедействительный или истёкший токен доступа
403NOT_A_PARTNERПользователь не зарегистрирован как партнёр

Пример

Запрос:

bash
curl -X PATCH https://api.iwm-platform.com/api/v1/mlm/partner/me \
  -H "Authorization: Bearer eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9..." \
  -H "Content-Type: application/json" \
  -d '{
    "payoutDetails": {
      "method": "CRYPTO",
      "cryptoNetwork": "USDT_TRC20",
      "walletAddress": "TXyz1234567890abcdefghijklmnop"
    }
  }'

Ответ:

json
{
  "success": true,
  "data": {
    "id": "cc0e8400-e29b-41d4-a716-446655440000",
    "payoutDetails": {
      "method": "CRYPTO",
      "maskedDetails": "TRC20: TXyz...mnop",
      "lastUpdated": "2024-01-15T16:00:00Z"
    },
    "updatedAt": "2024-01-15T16:00:00Z"
  }
}

GET /api/v1/mlm/partner/network

Получение структуры нижестоящей сети (неограниченная глубина).

Аутентификация: Обязательна (Партнёр)

Лимит запросов: 50 запросов в минуту

Заголовки запроса

Authorization: Bearer <access_token>

Тело запроса

Нет

Параметры запроса

ПараметрТипОписание
pagenumberНомер страницы (опционально)
pageSizenumberЭлементов на странице, макс. 100 (опционально)
depthnumberМаксимальная глубина (опционально, без ограничений)
levelnumberКонкретный уровень для выборки (опционально)
statusstringФильтр по статусу: 'ACTIVE', 'SUSPENDED', 'ALL' (опционально)
searchstringПоиск по имени или реферальному коду (опционально)

Ответ (200 OK)

typescript
interface NetworkResponse {
  partners: NetworkPartner[];
  summary: {
    totalCount: number;
    byLevel: {
      level: number;
      count: number;
    }[];
  };
}

interface NetworkPartner {
  id: string;
  name: string;
  referralCode: string;
  depth: number; // Глубина от текущего партнёра (неограниченная)
  status: string;
  rank: {
    name: string;
    code: string;
    level: number;
  } | null;
  directReferralsCount: number;
  joinedAt: string;
  lastActiveAt: string | null;
}

Ошибки

СтатусКодОписание
400VALIDATION_ERRORНеверные параметры запроса
401UNAUTHORIZEDНедействительный или истёкший токен доступа
403NOT_A_PARTNERПользователь не зарегистрирован как партнёр

Пример

Запрос:

bash
curl -X GET "https://api.iwm-platform.com/api/v1/mlm/partner/network?depth=5&page=1&pageSize=20" \
  -H "Authorization: Bearer eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9..."

Ответ:

json
{
  "success": true,
  "data": {
    "partners": [
      {
        "id": "ff0e8400-e29b-41d4-a716-446655440001",
        "name": "Петров Алексей",
        "referralCode": "ALI789AB",
        "depth": 1,
        "status": "ACTIVE",
        "rank": {
          "name": "Консультант 3",
          "code": "3",
          "level": 4
        },
        "directReferralsCount": 5,
        "joinedAt": "2024-01-20T14:00:00Z",
        "lastActiveAt": "2024-01-25T10:30:00Z"
      },
      {
        "id": "ff0e8400-e29b-41d4-a716-446655440002",
        "name": "Сидорова Елена",
        "referralCode": "BOB456CD",
        "depth": 2,
        "status": "ACTIVE",
        "rank": {
          "name": "Консультант 1",
          "code": "1",
          "level": 2
        },
        "directReferralsCount": 2,
        "joinedAt": "2024-01-22T09:00:00Z",
        "lastActiveAt": "2024-01-24T16:45:00Z"
      }
    ],
    "summary": {
      "totalCount": 87,
      "byLevel": [
        { "level": 1, "count": 15 },
        { "level": 2, "count": 32 },
        { "level": 3, "count": 25 },
        { "level": 4, "count": 10 },
        { "level": 5, "count": 5 }
      ]
    }
  },
  "meta": {
    "pagination": {
      "total": 87,
      "page": 1,
      "pageSize": 20,
      "totalPages": 5,
      "hasNext": true,
      "hasPrevious": false
    }
  }
}

GET /api/v1/mlm/partner/network/stats

Получение статистики сети.

Аутентификация: Обязательна (Партнёр)

Лимит запросов: 50 запросов в минуту

Заголовки запроса

Authorization: Bearer <access_token>

Тело запроса

Нет

Параметры запроса

ПараметрТипОписание
periodstringПериод: 'DAY', 'WEEK', 'MONTH', 'QUARTER', 'YEAR', 'ALL' (опционально)

Ответ (200 OK)

typescript
interface NetworkStatsResponse {
  period: string;
  periodStart: string;
  periodEnd: string;
  overview: {
    totalPartners: number;
    activePartners: number;
    newPartnersInPeriod: number;
    totalVolumeUsd: number;
    personalVolumeUsd: number;
    groupVolumeUsd: number;
  };
  growth: {
    date: string;
    newPartners: number;
    volumeUsd: number;
  }[];
  topPerformers: {
    id: string;
    name: string;
    volumeUsd: number;
    referrals: number;
  }[];
  rankDistribution: {
    rankCode: string;
    rankName: string;
    count: number;
    percentage: number;
  }[];
}

Ошибки

СтатусКодОписание
400VALIDATION_ERRORНеверный период
401UNAUTHORIZEDНедействительный или истёкший токен доступа
403NOT_A_PARTNERПользователь не зарегистрирован как партнёр

Пример

Запрос:

bash
curl -X GET "https://api.iwm-platform.com/api/v1/mlm/partner/network/stats?period=MONTH" \
  -H "Authorization: Bearer eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9..."

Ответ:

json
{
  "success": true,
  "data": {
    "period": "MONTH",
    "periodStart": "2024-01-01T00:00:00Z",
    "periodEnd": "2024-01-31T23:59:59Z",
    "overview": {
      "totalPartners": 87,
      "activePartners": 65,
      "newPartnersInPeriod": 12,
      "totalVolumeUsd": 125000.0,
      "personalVolumeUsd": 15000.0,
      "groupVolumeUsd": 110000.0
    },
    "growth": [
      { "date": "2024-01-01", "newPartners": 2, "volumeUsd": 4500.0 },
      { "date": "2024-01-08", "newPartners": 3, "volumeUsd": 6200.0 },
      { "date": "2024-01-15", "newPartners": 4, "volumeUsd": 7800.0 },
      { "date": "2024-01-22", "newPartners": 3, "volumeUsd": 5500.0 }
    ],
    "topPerformers": [
      {
        "id": "ff0e8400-e29b-41d4-a716-446655440001",
        "name": "Петров Алексей",
        "volumeUsd": 25000.0,
        "referrals": 8
      },
      {
        "id": "ff0e8400-e29b-41d4-a716-446655440002",
        "name": "Сидорова Елена",
        "volumeUsd": 18000.0,
        "referrals": 5
      }
    ],
    "rankDistribution": [
      {
        "rankCode": "0",
        "rankName": "Консультант 0",
        "count": 25,
        "percentage": 28.74
      },
      {
        "rankCode": "1",
        "rankName": "Консультант 1",
        "count": 20,
        "percentage": 22.99
      },
      {
        "rankCode": "2",
        "rankName": "Консультант 2",
        "count": 15,
        "percentage": 17.24
      },
      {
        "rankCode": "3",
        "rankName": "Консультант 3",
        "count": 12,
        "percentage": 13.79
      },
      {
        "rankCode": "4",
        "rankName": "Консультант 4",
        "count": 8,
        "percentage": 9.2
      },
      {
        "rankCode": "5",
        "rankName": "Консультант 5",
        "count": 5,
        "percentage": 5.75
      },
      {
        "rankCode": "6",
        "rankName": "Консультант 6",
        "count": 2,
        "percentage": 2.3
      }
    ]
  }
}

Эндпоинты реферальных ссылок

Получение списка реферальных ссылок.

Аутентификация: Обязательна (Партнёр)

Лимит запросов: 100 запросов в минуту

Ответ (200 OK)

typescript
interface ReferralLinksResponse {
  links: ReferralLink[];
  defaultLink: string;
}

interface ReferralLink {
  id: string;
  code: string;
  name: string | null;
  fullUrl: string;
  targetUrl: string | null;
  utmParams: {
    source: string | null;
    medium: string | null;
    campaign: string | null;
  };
  stats: {
    clicks: number;
    registrations: number;
    conversions: number;
  };
  isActive: boolean;
  expiresAt: string | null;
  createdAt: string;
}

POST /api/v1/mlm/referrals/links

Создание новой реферальной ссылки.

Аутентификация: Обязательна (Партнёр)

Лимит запросов: 100 запросов в минуту

Тело запроса

typescript
interface CreateReferralLinkRequest {
  name: string; // Описательное название
  targetUrl?: string; // URL целевой страницы
  utmSource?: string; // UTM source параметр
  utmMedium?: string; // UTM medium параметр
  utmCampaign?: string; // UTM campaign параметр
  expiresAt?: string; // Дата истечения (ISO 8601)
}

Ошибки

СтатусКодОписание
400MAX_LINKS_REACHEDДостигнут лимит в 20 реферальных ссылок

Эндпоинты комиссий

GET /api/v1/mlm/commissions

Получение списка комиссионных транзакций с 7 типами дохода.

Аутентификация: Обязательна (Партнёр)

Лимит запросов: 100 запросов в минуту

Параметры запроса

ПараметрТипОписание
pagenumberНомер страницы (опционально)
pageSizenumberЭлементов на странице, макс. 100 (опционально)
statusstringФильтр: 'PENDING', 'APPROVED', 'PAID', 'REVERSED', 'ALL' (опционально)
incomeTypestringФильтр: 'PERSONAL_SALES', 'TEAM_SALES', 'REPEAT_SALES', 'PORTFOLIO_RETURNS', 'CLIENT_PROFITS', 'NETWORK_PROFITS', 'LEADERSHIP_POOL' (опционально)
sourceTypestringФильтр: 'ORDER', 'INVESTMENT', 'INVESTMENT_PROFIT', 'POOL_DISTRIBUTION' (опционально)
dateFromstringНачальная дата (ISO 8601) (опционально)
dateTostringКонечная дата (ISO 8601) (опционально)

Ответ (200 OK)

typescript
interface CommissionsResponse {
  commissions: Commission[];
}

interface Commission {
  id: string;
  incomeType:
    | "PERSONAL_SALES"
    | "TEAM_SALES"
    | "REPEAT_SALES"
    | "PORTFOLIO_RETURNS"
    | "CLIENT_PROFITS"
    | "NETWORK_PROFITS"
    | "LEADERSHIP_POOL";
  sourceType:
    | "ORDER"
    | "INVESTMENT"
    | "INVESTMENT_PROFIT"
    | "POOL_DISTRIBUTION"
    | "CLAWBACK";
  sourceId: string;
  sourcePartner: {
    id: string;
    name: string;
    rank: string;
  } | null;
  // Детали дифференциальной комиссии
  ownRate: number; // Ваша ставка (например, 14%)
  sourceRate: number; // Ставка партнёра-источника (например, 8%)
  differentialRate: number; // Разница (например, 6%)
  baseAmountUsd: number; // Сумма, с которой рассчитана комиссия
  grossAmountUsd: number;
  netAmountUsd: number;
  currency: string; // Всегда 'USD'
  status:
    | "PENDING"
    | "APPROVED"
    | "PAID"
    | "HELD"
    | "REVERSED"
    | "CLAWBACK"
    | "CANCELLED";
  periodId: string | null;
  processedAt: string | null;
  createdAt: string;
}

Пример

Запрос:

bash
curl -X GET "https://api.iwm-platform.com/api/v1/mlm/commissions?status=APPROVED&incomeType=TEAM_SALES&page=1&pageSize=20" \
  -H "Authorization: Bearer eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9..."

Ответ:

json
{
  "success": true,
  "data": {
    "commissions": [
      {
        "id": "jj0e8400-e29b-41d4-a716-446655440001",
        "incomeType": "TEAM_SALES",
        "sourceType": "ORDER",
        "sourceId": "kk0e8400-e29b-41d4-a716-446655440001",
        "sourcePartner": {
          "id": "ff0e8400-e29b-41d4-a716-446655440001",
          "name": "Петров Алексей",
          "rank": "Консультант 3"
        },
        "ownRate": 14.0,
        "sourceRate": 10.0,
        "differentialRate": 4.0,
        "baseAmountUsd": 5000.0,
        "grossAmountUsd": 200.0,
        "netAmountUsd": 200.0,
        "currency": "USD",
        "status": "APPROVED",
        "periodId": "2024-01",
        "processedAt": "2024-01-16T09:00:00Z",
        "createdAt": "2024-01-15T18:00:00Z"
      },
      {
        "id": "jj0e8400-e29b-41d4-a716-446655440002",
        "incomeType": "PERSONAL_SALES",
        "sourceType": "ORDER",
        "sourceId": "kk0e8400-e29b-41d4-a716-446655440002",
        "sourcePartner": null,
        "ownRate": 14.0,
        "sourceRate": 0,
        "differentialRate": 14.0,
        "baseAmountUsd": 3000.0,
        "grossAmountUsd": 420.0,
        "netAmountUsd": 420.0,
        "currency": "USD",
        "status": "APPROVED",
        "periodId": "2024-01",
        "processedAt": "2024-01-16T09:00:00Z",
        "createdAt": "2024-01-15T14:00:00Z"
      }
    ]
  },
  "meta": {
    "pagination": {
      "total": 156,
      "page": 1,
      "pageSize": 20,
      "totalPages": 8,
      "hasNext": true,
      "hasPrevious": false
    }
  }
}

GET /api/v1/mlm/commissions/summary

Получение сводки комиссий с разбивкой по 7 типам дохода.

Аутентификация: Обязательна (Партнёр)

Лимит запросов: 100 запросов в минуту

Ответ (200 OK)

typescript
interface CommissionSummaryResponse {
  period: string;
  periodStart: string;
  periodEnd: string;
  totals: {
    grossEarnedUsd: number;
    netEarnedUsd: number;
    pendingUsd: number;
    approvedUsd: number;
    paidUsd: number;
    reversedUsd: number;
  };
  byIncomeType: {
    incomeType: string;
    incomeTypeName: string;
    count: number;
    totalUsd: number;
  }[];
  bySource: {
    sourceType: string;
    count: number;
    totalUsd: number;
  }[];
  trend: {
    date: string;
    earnedUsd: number;
  }[];
}

Пример ответа

json
{
  "success": true,
  "data": {
    "period": "MONTH",
    "periodStart": "2024-01-01T00:00:00Z",
    "periodEnd": "2024-01-31T23:59:59Z",
    "totals": {
      "grossEarnedUsd": 12500.0,
      "netEarnedUsd": 12500.0,
      "pendingUsd": 1500.0,
      "approvedUsd": 5000.0,
      "paidUsd": 6000.0,
      "reversedUsd": 0.0
    },
    "byIncomeType": [
      {
        "incomeType": "PERSONAL_SALES",
        "incomeTypeName": "Личные продажи",
        "count": 15,
        "totalUsd": 4200.0
      },
      {
        "incomeType": "TEAM_SALES",
        "incomeTypeName": "Командные продажи",
        "count": 45,
        "totalUsd": 3600.0
      },
      {
        "incomeType": "REPEAT_SALES",
        "incomeTypeName": "Повторные продажи",
        "count": 8,
        "totalUsd": 800.0
      },
      {
        "incomeType": "CLIENT_PROFITS",
        "incomeTypeName": "Прибыль клиентов",
        "count": 12,
        "totalUsd": 1400.0
      },
      {
        "incomeType": "NETWORK_PROFITS",
        "incomeTypeName": "Прибыль сети",
        "count": 30,
        "totalUsd": 1800.0
      },
      {
        "incomeType": "LEADERSHIP_POOL",
        "incomeTypeName": "Лидерский пул",
        "count": 4,
        "totalUsd": 700.0
      }
    ],
    "bySource": [
      { "sourceType": "ORDER", "count": 68, "totalUsd": 8600.0 },
      { "sourceType": "INVESTMENT", "count": 12, "totalUsd": 2000.0 },
      { "sourceType": "INVESTMENT_PROFIT", "count": 42, "totalUsd": 1200.0 },
      { "sourceType": "POOL_DISTRIBUTION", "count": 4, "totalUsd": 700.0 }
    ],
    "trend": [
      { "date": "2024-01-01", "earnedUsd": 450.0 },
      { "date": "2024-01-02", "earnedUsd": 320.0 }
    ]
  }
}

Эндпоинты рангов

GET /api/v1/mlm/ranks

Получение всех доступных рангов.

Аутентификация: Обязательна (Партнёр)

Ответ (200 OK)

typescript
interface RanksListResponse {
  ranks: Rank[];
}

interface Rank {
  id: string;
  code: string; // "0", "1", ..., "4_PRO", "5", "5_PRO", ..., "11", "11_PRO"
  name: string; // "Консультант 0", "Консультант 1", ..., "Консультант 11 PRO"
  level: number; // 0-21
  personalSalesRate: number; // 3% - 20%
  entranceFeeRate: number; // 10.5% - 20%
  passiveIncomeRate: number; // 0% - 20%
  requirements: {
    personalVolumeUsd: number;
    groupVolumeUsd: number | null;
    directReferrals: number | null;
    rankedPartnersRequired: number | null;
    rankedPartnerRank: string | null;
  };
  eligibleForPools: string[]; // ["POOL_5", "POOL_6"] и т.д.
  badgeUrl: string | null;
  colorCode: string | null;
}

GET /api/v1/mlm/ranks/current

Получение текущего ранга.

Аутентификация: Обязательна (Партнёр)

Ответ (200 OK)

typescript
interface CurrentRankResponse {
  currentRank: {
    id: string;
    name: string;
    code: string;
    level: number;
    description: string | null;
    badgeUrl: string | null;
    colorCode: string | null;
  } | null;
  achievedAt: string | null;
  rates: {
    personalSalesRate: number;
    entranceFeeRate: number;
    passiveIncomeRate: number;
  };
  eligibleForPools: string[];
}

GET /api/v1/mlm/ranks/progress

Получение прогресса к следующему рангу.

Аутентификация: Обязательна (Партнёр)

Ответ (200 OK)

typescript
interface RankProgressResponse {
  currentRank: {
    id: string;
    name: string;
    code: string;
    level: number;
  } | null;
  nextRank: {
    id: string;
    name: string;
    code: string;
    level: number;
    badgeUrl: string | null;
    newRates: {
      personalSalesRate: number;
      entranceFeeRate: number;
      passiveIncomeRate: number;
    };
  } | null;
  requirements: {
    type: string;
    description: string;
    currentUsd: number;
    requiredUsd: number;
    percentage: number;
    isMet: boolean;
  }[];
  overallProgress: number;
  isMaxRank: boolean;
}

GET /api/v1/mlm/ranks/history

Получение истории продвижения по рангам. Ранги в IWM Platform бессрочные (без понижения).

Аутентификация: Обязательна (Партнёр)

Ответ (200 OK)

typescript
interface RankHistoryResponse {
  history: RankChange[];
}

interface RankChange {
  id: string;
  fromRank: {
    name: string;
    code: string;
    level: number;
  } | null;
  toRank: {
    name: string;
    code: string;
    level: number;
  };
  changeType: "PROMOTION" | "INITIAL"; // Нет DEMOTION - ранги не истекают
  qualificationSnapshot: {
    personalVolumeUsd: number;
    groupVolumeUsd: number;
    directReferrals: number;
    rankedPartners: number;
  };
  createdAt: string;
}

Эндпоинты баланса и выплат

GET /api/v1/mlm/balance

Получение баланса с разбивкой по 7 типам дохода.

Аутентификация: Обязательна (Партнёр)

Лимит запросов: 100 запросов в минуту

Ответ (200 OK)

typescript
interface BalanceResponse {
  availableBalanceUsd: number;
  pendingBalanceUsd: number;
  totalEarnedUsd: number;
  totalWithdrawnUsd: number;
  incomeBreakdown: {
    personalSalesUsd: number;
    teamSalesUsd: number;
    repeatSalesUsd: number;
    portfolioReturnsUsd: number;
    clientProfitsUsd: number;
    networkProfitsUsd: number;
    leadershipPoolUsd: number;
  };
  currency: string; // Всегда 'USD'
  lastCalculatedAt: string | null;
  minimumPayoutUsd: number; // $100
  canRequestPayout: boolean;
  payoutRestrictions: string[];
}

Пример

Запрос:

bash
curl -X GET https://api.iwm-platform.com/api/v1/mlm/balance \
  -H "Authorization: Bearer eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9..."

Ответ:

json
{
  "success": true,
  "data": {
    "availableBalanceUsd": 4500.0,
    "pendingBalanceUsd": 1500.0,
    "totalEarnedUsd": 18000.0,
    "totalWithdrawnUsd": 12000.0,
    "incomeBreakdown": {
      "personalSalesUsd": 5200.0,
      "teamSalesUsd": 6800.0,
      "repeatSalesUsd": 1200.0,
      "portfolioReturnsUsd": 800.0,
      "clientProfitsUsd": 1800.0,
      "networkProfitsUsd": 1500.0,
      "leadershipPoolUsd": 700.0
    },
    "currency": "USD",
    "lastCalculatedAt": "2024-01-15T23:59:59Z",
    "minimumPayoutUsd": 100.0,
    "canRequestPayout": true,
    "payoutRestrictions": []
  }
}

GET /api/v1/mlm/payouts

Получение списка запросов на выплату.

Аутентификация: Обязательна (Партнёр)

Лимит запросов: 100 запросов в минуту

Ответ (200 OK)

typescript
interface PayoutsResponse {
  payouts: Payout[];
}

interface Payout {
  id: string;
  amountUsd: number;
  currency: string; // Всегда 'USD'
  method: {
    type: "BANK_CARD" | "BANK_TRANSFER" | "CRYPTO";
    maskedDetails: string;
  };
  status:
    | "PENDING"
    | "APPROVED"
    | "PROCESSING"
    | "COMPLETED"
    | "REJECTED"
    | "CANCELLED";
  rejectionReason: string | null;
  externalReference: string | null;
  processedAt: string | null;
  completedAt: string | null;
  createdAt: string;
}

POST /api/v1/mlm/payouts/request

Запрос на выплату (минимум $100 USD).

Аутентификация: Обязательна (Партнёр)

Лимит запросов: 1 запрос в минуту (финансовый эндпоинт)

Тело запроса

typescript
interface PayoutRequestBody {
  amountUsd: number; // Должно быть >= $100
  methodType: "BANK_CARD" | "BANK_TRANSFER" | "CRYPTO";
  useSavedDetails?: boolean; // Использовать сохранённые реквизиты
  details?: {
    cardNumber?: string; // Для BANK_CARD
    bankName?: string; // Для BANK_TRANSFER
    bankSwift?: string; // Для BANK_TRANSFER
    accountNumber?: string; // Для BANK_TRANSFER
    cryptoNetwork?: string; // Для CRYPTO (например, 'USDT_TRC20')
    walletAddress?: string; // Для CRYPTO
  };
}

Ответ (201 Created)

typescript
interface PayoutRequestResponse {
  payoutId: string;
  amountUsd: number;
  currency: string;
  method: {
    type: string;
    maskedDetails: string;
  };
  status: "PENDING";
  estimatedProcessingTime: string;
  newAvailableBalanceUsd: number;
  createdAt: string;
}

Ошибки

СтатусКодОписание
400VALIDATION_ERRORНеверные входные данные
400AMOUNT_BELOW_MINIMUMСумма ниже минимальной выплаты $100
400INSUFFICIENT_BALANCEНедостаточно средств
400PAYOUT_DETAILS_REQUIREDРеквизиты не указаны и не сохранены
401UNAUTHORIZEDНедействительный или истёкший токен доступа
403NOT_A_PARTNERПользователь не зарегистрирован как партнёр
403KYC_REQUIREDТребуется KYC верификация для выплат
409PAYOUT_ALREADY_PENDINGЗапрос на выплату уже в обработке
429RATE_LIMIT_EXCEEDEDСлишком много запросов на выплату

GET /api/v1/mlm/payouts/:id

Получение деталей выплаты.

Аутентификация: Обязательна (Партнёр)

Ответ (200 OK)

typescript
interface PayoutDetailsResponse {
  id: string;
  amountUsd: number;
  currency: string;
  method: {
    type: "BANK_CARD" | "BANK_TRANSFER" | "CRYPTO";
    maskedDetails: string;
  };
  status:
    | "PENDING"
    | "APPROVED"
    | "PROCESSING"
    | "COMPLETED"
    | "REJECTED"
    | "CANCELLED";
  statusHistory: {
    status: string;
    changedAt: string;
    changedBy: string | null;
    note: string | null;
  }[];
  rejectionReason: string | null;
  externalReference: string | null;
  processedBy: string | null;
  processedAt: string | null;
  completedAt: string | null;
  createdAt: string;
}

Эндпоинты лидерских пулов

GET /api/v1/mlm/pools

Получение конфигурации всех лидерских пулов.

Аутентификация: Обязательна (Партнёр)

Лимит запросов: 100 запросов в минуту

Ответ (200 OK)

typescript
interface PoolsListResponse {
  pools: LeadershipPool[];
}

interface LeadershipPool {
  id: string;
  code: string; // "POOL_5", "POOL_6" и т.д.
  name: string;
  eligibleRanks: string[]; // ["5", "5_PRO"]
  percentageOfTurnover: number; // 0.5% - 1%
  frequency: "WEEKLY" | "MONTHLY";
  qualificationVolumes: {
    rankCode: string;
    requiredVolumeUsd: number;
  }[];
  branchCapPercentage: number; // Правило 50% ветви
  isActive: boolean;
}

Пример

Ответ:

json
{
  "success": true,
  "data": {
    "pools": [
      {
        "id": "pp0e8400-e29b-41d4-a716-446655440001",
        "code": "POOL_5",
        "name": "Пул 5 (Еженедельный)",
        "eligibleRanks": ["5", "5_PRO"],
        "percentageOfTurnover": 1.0,
        "frequency": "WEEKLY",
        "qualificationVolumes": [
          { "rankCode": "5", "requiredVolumeUsd": 5000.0 },
          { "rankCode": "5_PRO", "requiredVolumeUsd": 10000.0 }
        ],
        "branchCapPercentage": 50,
        "isActive": true
      },
      {
        "id": "pp0e8400-e29b-41d4-a716-446655440002",
        "code": "POOL_6",
        "name": "Пул 6 (Еженедельный)",
        "eligibleRanks": ["6", "6_PRO"],
        "percentageOfTurnover": 0.5,
        "frequency": "WEEKLY",
        "qualificationVolumes": [
          { "rankCode": "6", "requiredVolumeUsd": 20000.0 },
          { "rankCode": "6_PRO", "requiredVolumeUsd": 30000.0 }
        ],
        "branchCapPercentage": 50,
        "isActive": true
      },
      {
        "id": "pp0e8400-e29b-41d4-a716-446655440007",
        "code": "POOL_9",
        "name": "Пул 9 (Ежемесячный)",
        "eligibleRanks": ["9", "9_PRO"],
        "percentageOfTurnover": 1.0,
        "frequency": "MONTHLY",
        "qualificationVolumes": [
          { "rankCode": "9", "requiredVolumeUsd": 0 },
          { "rankCode": "9_PRO", "requiredVolumeUsd": 0 }
        ],
        "branchCapPercentage": 50,
        "isActive": true
      }
    ]
  }
}

GET /api/v1/mlm/pools/qualification

Получение текущего статуса квалификации для лидерских пулов.

Аутентификация: Обязательна (Партнёр)

Лимит запросов: 100 запросов в минуту

Параметры запроса

ПараметрТипОписание
periodstringПериод: 'CURRENT_WEEK', 'LAST_WEEK', 'CURRENT_MONTH', 'LAST_MONTH' (опционально)

Ответ (200 OK)

typescript
interface PoolQualificationResponse {
  currentRank: {
    code: string;
    name: string;
  };
  eligiblePools: string[];
  qualificationStatus: {
    poolCode: string;
    poolName: string;
    isQualified: boolean;
    requiredVolumeUsd: number;
    currentVolumeUsd: number;
    cappedVolumeUsd: number; // После применения 50% ограничения ветви
    percentage: number;
    branchVolumes: {
      branchPartnerId: string;
      branchPartnerName: string;
      rawVolumeUsd: number;
      cappedVolumeUsd: number;
      capApplied: boolean;
    }[];
  }[];
}

Пример

Ответ:

json
{
  "success": true,
  "data": {
    "currentRank": {
      "code": "5",
      "name": "Консультант 5"
    },
    "eligiblePools": ["POOL_5"],
    "qualificationStatus": [
      {
        "poolCode": "POOL_5",
        "poolName": "Пул 5 (Еженедельный)",
        "isQualified": true,
        "requiredVolumeUsd": 5000.0,
        "currentVolumeUsd": 12000.0,
        "cappedVolumeUsd": 6500.0,
        "percentage": 130.0,
        "branchVolumes": [
          {
            "branchPartnerId": "ff0e8400-e29b-41d4-a716-446655440001",
            "branchPartnerName": "Петров Алексей",
            "rawVolumeUsd": 8000.0,
            "cappedVolumeUsd": 2500.0,
            "capApplied": true
          },
          {
            "branchPartnerId": "ff0e8400-e29b-41d4-a716-446655440002",
            "branchPartnerName": "Сидорова Елена",
            "rawVolumeUsd": 4000.0,
            "cappedVolumeUsd": 4000.0,
            "capApplied": false
          }
        ]
      }
    ]
  }
}

GET /api/v1/mlm/pools/distributions

Получение истории распределений лидерского пула.

Аутентификация: Обязательна (Партнёр)

Лимит запросов: 100 запросов в минуту

Параметры запроса

ПараметрТипОписание
pagenumberНомер страницы (опционально)
pageSizenumberЭлементов на странице, макс. 50 (опционально)
poolCodestringФильтр по пулу: 'POOL_5', 'POOL_6' и т.д. (опционально)

Ответ (200 OK)

typescript
interface PoolDistributionsResponse {
  distributions: PoolDistribution[];
}

interface PoolDistribution {
  id: string;
  poolCode: string;
  poolName: string;
  periodStart: string;
  periodEnd: string;
  totalTurnoverUsd: number;
  poolAmountUsd: number;
  qualifiedParticipants: number;
  perPersonAmountUsd: number;
  yourParticipation: {
    qualified: boolean;
    qualificationVolumeUsd: number;
    amountReceivedUsd: number;
  } | null;
  distributedAt: string;
}

Пример

Ответ:

json
{
  "success": true,
  "data": {
    "distributions": [
      {
        "id": "qq0e8400-e29b-41d4-a716-446655440001",
        "poolCode": "POOL_5",
        "poolName": "Пул 5 (Еженедельный)",
        "periodStart": "2024-01-08T00:00:00Z",
        "periodEnd": "2024-01-14T23:59:59Z",
        "totalTurnoverUsd": 500000.0,
        "poolAmountUsd": 5000.0,
        "qualifiedParticipants": 25,
        "perPersonAmountUsd": 200.0,
        "yourParticipation": {
          "qualified": true,
          "qualificationVolumeUsd": 6500.0,
          "amountReceivedUsd": 200.0
        },
        "distributedAt": "2024-01-14T23:00:00Z"
      },
      {
        "id": "qq0e8400-e29b-41d4-a716-446655440000",
        "poolCode": "POOL_5",
        "poolName": "Пул 5 (Еженедельный)",
        "periodStart": "2024-01-01T00:00:00Z",
        "periodEnd": "2024-01-07T23:59:59Z",
        "totalTurnoverUsd": 450000.0,
        "poolAmountUsd": 4500.0,
        "qualifiedParticipants": 22,
        "perPersonAmountUsd": 204.55,
        "yourParticipation": {
          "qualified": false,
          "qualificationVolumeUsd": 4200.0,
          "amountReceivedUsd": 0
        },
        "distributedAt": "2024-01-07T23:00:00Z"
      }
    ]
  },
  "meta": {
    "pagination": {
      "total": 8,
      "page": 1,
      "pageSize": 10,
      "totalPages": 1,
      "hasNext": false,
      "hasPrevious": false
    }
  }
}

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