Finance OS / API

Identity Verification (KYC)

Персональная KYC-верификация — flow для подтверждения личности любого физического лица в системе: end-user'а вашего приложения, держателя кошелька, владельца API-ключа. Состоит из загрузки документов, верификации телефона по SMS и проверки статуса.

KYC vs KYB
Эта страница — про KYC (Know Your Customer): идентификация физического лица (паспорт + селфи + телефон). Для верификации юридического лица (компании) используется KYB API — другой набор данных (ОГРН/ИНН, директор, бухгалтер, бенефициары, 12+ типов документов, AML-проверка).

В B2B-сценарии перед KYC-операциями партнёр обязан зафиксировать факт согласия end-user'а через POST /customers/{uuid}/consent. Для собственного аккаунта KYC проводится через mobile-эндпоинты (см. Authentication).

Когда нужен KYC
Платежи (buy/sell/withdraw) требуют kyc_status = 'verified'. Без верификации возвращается 422 KYC_REQUIRED. Чтение баланса и история транзакций KYC не требуют.

Стандартный flow

  1. ConsentPOST /customers/{uuid}/consent (один раз на customer'а).
  2. Start sessionPOST /customers/{uuid}/kyc/start с phone + passport_type.
  3. Upload documentsPOST /customers/{uuid}/kyc/documents multipart c selfie/passport/address.
  4. Request SMS codePOST /customers/{uuid}/kyc/request-code.
  5. Verify codePOST /customers/{uuid}/kyc/verify-code с 6-значным кодом → переход в verified.
  6. Poll statusGET /customers/{uuid}/kyc/status в любое время. Или подпишитесь на webhook customer.kyc.verified.

Жизненный цикл

kyc_status переходы

Name Type Required Description
not_started optional Начальное состояние, KYC ещё не запускался.
pending после start optional Session создана, ожидаем documents/phone.
processing после documents optional Документы загружены, идёт верификация (для live — провайдером).
verified финальный optional KYC успешно пройден. Платежи разрешены.
rejected финальный optional Документы отклонены. Причина в kyc_rejection_reason. Возможен reset.
expired финальный optional KYC просрочен (raz v 3 года). Требуется reset + повтор.

Уровни KYC

kyc_level

Name Type Required Description
0 Anonymous optional KYC не пройден. Платежи запрещены.
1 Phone+Email optional Базовая верификация. Депозиты до 500 USD/день, без вывода.
2 ID Verified optional Документы и SMS пройдены. Все операции до 10 000 USD/день.
3 Address Proof optional Подтверждённый адрес. Без дневных лимитов (subject to AML).

Старт верификации

POST /api/v1/customers/{uuid}/kyc/start
Bearer Token

Создать KYC-сессию

Создаёт upstream-сессию (в sandbox — мок). Должен вызываться после POST /consent.

Request body

Name Type Required Description
phone string required E.164 формат.
passport_type enum optional ru (РФ паспорт + адрес) или foreign (загранник + текстовый адрес).
Default: ru

Responses

{
  "data": {
    "session_id": "sbx_aXmjv1X5tw9J8CLdynh6ZfE8",
    "next": "upload_documents",
    "env": "sandbox",
    "customer_uuid": "5f8d7a3c-...",
    "kyc_status": "pending"
  }
}
{
  "message": "The given data was invalid.",
  "errors": {
    "consent": ["End-user consent must be recorded before KYC operations. POST /api/v1/customers/{uuid}/consent first."]
  }
}

Загрузка документов

POST /api/v1/customers/{uuid}/kyc/documents
Bearer Token

Multipart upload документов

Content-Type: multipart/form-data. Каждое поле опционально, но все 3 типа обычно нужны для уровня 2.

Files

Name Type Required Description
selfie file optional Фото лица. jpg/jpeg/png/pdf, до 10 MB.
passport file optional Скан/фото паспорта. То же ограничение.
address file optional Подтверждение адреса (proof of address). Опционально.
Хранение
Файлы хранятся в Finance OS. Партнёр не должен хранить их у себя после успешного аплоада — это нарушает GDPR / 152-ФЗ. Удалите файлы локально сразу после ответа 200.

SMS-код

POST /api/v1/customers/{uuid}/kyc/request-code
Bearer Token

Запросить код подтверждения

Отправляет 6-значный код на телефон, указанный в start. В sandbox возвращает фиксированный mock-код для тестирования.

Responses

{
  "data": {
    "sent": true,
    "channel": "sandbox",
    "mock_code": "000000",
    "expires_in": 300,
    "note": "In sandbox the code \"000000\" always succeeds."
  }
}
{
  "data": {
    "sent": true,
    "channel": "sms",
    "expires_in": 300
  }
}

Проверка кода

POST /api/v1/customers/{uuid}/kyc/verify-code
Bearer Token

Завершить верификацию

Передайте 6-значный код. При успехе customer переходит в verified + уровень 2. Партнёрский webhook customer.kyc.verified диспатчится автоматически.

Request body

Name Type Required Description
code string required 6 цифр. В sandbox только 000000 проходит.

Responses

{
  "data": {
    "customer_uuid": "5f8d7a3c-...",
    "kyc_status": "verified",
    "kyc_level": 2
  }
}
{
  "message": "The given data was invalid.",
  "errors": {"code": ["Invalid code. In sandbox the code \"000000\" always succeeds."]}
}

Статус

GET /api/v1/customers/{uuid}/kyc/status
Bearer Token

Текущий статус верификации

Responses

{
  "data": {
    "kyc_status": "verified",
    "kyc_level": 2,
    "kyc_rejection_reason": null,
    "consent_signed": true,
    "documents": {
      "selfie_uploaded": true,
      "passport_state": "success",
      "address_state": "success"
    },
    "phone": "+79001234567",
    "env": "live",
    "attempts_remaining": 5
  }
}

Reset

POST /api/v1/customers/{uuid}/kyc/reset
Bearer Token

Сбросить сессию и начать заново

Удаляет загруженные документы и сбрасывает kyc_status в not_started. Полезно при rejected. Rate-limit: 5 reset'ов в 24 часа на customer.

Коды ошибок

Name Type Required Description
CONSENT_REQUIRED 422 optional Не было вызова POST /consent перед KYC-операцией.
SESSION_NOT_STARTED 422 optional Не было POST /kyc/start перед документами/кодом.
INVALID_CODE 422 optional Неверный SMS-код.
RATE_LIMITED 422 optional Превышен лимит reset (5/24h).
PROVIDER_DOWN 422 optional Upstream verification провайдер недоступен. Retry через минуту.