Finance OS / API

Managed Customers

Customer — это managed end-user партнёра. Партнёр создаёт customer'ов через API, привязывает к ним собственные external_id, проводит им KYC и платежи. У каждого customer'а отдельный жизненный цикл, статус KYC, баланс по валютам.

Idempotency
POST /customers идемпотентен по полю external_id в рамках одного partner-аккаунта и одного env. Если customer с таким external_id уже существует — возвращается существующая запись без создания дубля.

Модель customer

KYC.'], ['name' => 'consent_signed', 'type' => 'boolean', 'desc' => 'Партнёр подтвердил, что end-user дал согласие. Обязательно перед KYC-операциями.'], ['name' => 'consent_signed_at','type' => 'timestamp','desc' => 'Когда консент был зафиксирован.'], ['name' => 'consent_ip', 'type' => 'string', 'desc' => 'IP end-user в момент консента (партнёр передаёт).'], ['name' => 'metadata', 'type' => 'object', 'desc' => 'Произвольные key-value поля, передаваемые партнёром.'], ['name' => 'created_at', 'type' => 'timestamp','desc' => ''], ]" />

Создать customer

POST /api/v1/customers
Bearer Token

Создать managed-customer (idempotent)

Создаёт новый customer под текущим партнёром. Idempotent по external_id.

Request body

Name Type Required Description
name string required Имя customer, 2-255 символов.
email string optional Email формата RFC 5322.
phone string optional E.164 формат: ^\+[1-9][0-9]{6,19}$.
external_id string optional Partner-side ID. До 100 символов. Уникален в рамках partner+env.
metadata object optional Произвольный JSON.

Responses

{
  "data": {
    "uuid": "5f8d7a3c-1234-4567-89ab-cdef01234567",
    "external_id": "user-42",
    "name": "Иван Петров",
    "email": "ivan@partner.com",
    "phone": "+79001234567",
    "kyc_status": "not_started",
    "kyc_level": 0,
    "env": "live",
    "consent_signed": false,
    "metadata": {"tier": "gold"},
    "created_at": "2026-05-27T14:23:00.000000Z",
    "updated_at": "2026-05-27T14:23:00.000000Z"
  }
}
{
  "message": "B2B access is not enabled for this account.",
  "error_code": "B2B_ACCESS_REQUIRED",
  "docs": "https://fin-os.io/docs/b2b"
}
{
  "message": "The given data was invalid.",
  "errors": {
    "name": ["The name field is required."],
    "phone": ["The phone format is invalid."]
  }
}

Список customers

GET /api/v1/customers
Bearer Token

Пагинированный список customers партнёра

Query parameters

Name Type Required Description
filter[kyc_status] string optional not_started / pending / verified / rejected и др.
filter[env] string optional live / sandbox (по умолчанию — env ключа).
filter[search] string optional Подстрока по name/email/phone/external_id.
per_page integer optional Размер страницы, 1..100.
Default: 20
page integer optional Номер страницы.
Default: 1

Получить customer

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

Детали customer по UUID

Env-isolation
Если customer создан с env='live', то sk_test_ ключ получит 404 (и наоборот). Это намеренная утечка-защита: ключ не может узнать о существовании customer'а в чужом окружении.

Обновить customer

PATCH /api/v1/customers/{uuid}
Bearer Token

Обновить metadata customer (name/email/phone/external_id/metadata)

Поля kyc_*, env, consent_* через PATCH не обновляются — для них есть отдельные endpoint'ы.

Удалить customer

DELETE /api/v1/customers/{uuid}
Bearer Token

Soft-delete customer

Удаление мягкое — запись помечается deleted_at. Полный hard-delete не предусмотрен (compliance).

POST /api/v1/customers/{uuid}/consent
Bearer Token

Партнёр подтверждает: end-user дал согласие на обработку данных

Обязательно перед KYC-операциями. Сохраняет IP end-user'а и timestamp как доказательство согласия. Финансово-юридически — партнёр самостоятельно несёт ответственность за получение реального согласия от своего пользователя.

Request body

Name Type Required Description
ip string required IP end-user в момент консента. Валидный IPv4 или IPv6.

Балансы customer'а

GET /api/v1/customers/{uuid}/balance
Bearer Token

Балансы по всем валютам

Responses

{
  "data": [
    { "currency": "USDT", "available": "1250.4500000000", "locked": "100.0000000000" },
    { "currency": "RUB",  "available": "15000.0000000000", "locked": "0.0000000000" }
  ]
}
locked balance
locked — сумма, зарезервированная под активные операции (например, sell ещё не finalized'ан). Сумма недоступна для других списаний, но и не списана окончательно. При cancel/fail возвращается в available; при success — consume'ится.