B2B API - Introduction
B2B API позволяет партнёрам Finance OS управлять своими конечными пользователями через единый набор endpoints: создавать managed-customers, проводить им KYC-верификацию, инициировать платежи и подписываться на webhook-события.
⚠
Регуляторное предусловие
B2B-режим - не self-service. Он включается только после подписания договора с Finance OS (агентская модель + соглашение об обработке данных). До этого момента API-ключи получают 403 B2B_ACCESS_REQUIRED на любой /api/v1/customers/* endpoint. Свяжитесь с admin@fin-os.io, чтобы инициировать процесс.
Две модели работы
Merchant API покрывает два разных сценария. Выберите тот, который описывает ваш продукт - от этого зависит, какие разделы документации вам нужны.
Классический мерчант
клиенты и кошельки
optional
Вы ведёте на платформе своих конечных пользователей: заводите клиентов, выдаёте им крипто-адреса, принимаете депозиты, выводите средства, рассчитываетесь с ними и проверяете адреса на комплаенс. Расчёты платформы с вами идут через мастер-счёт - предоплатный сервисный баланс вашей учётной записи. Это основной сценарий, и о нём вся документация ниже.
Партнёр по приёму платежей
payin
optional
Отдельный контур приёма рублёвых платежей с расчётом в USDT - собственные эндпоинты, статусы и события. Описан в разделе Payment Gateway (RUB) и подключается по отдельному договору.
| Name | Type | Required | Description |
|---|---|---|---|
Классический мерчант
|
клиенты и кошельки
|
optional | Вы ведёте на платформе своих конечных пользователей: заводите клиентов, выдаёте им крипто-адреса, принимаете депозиты, выводите средства, рассчитываетесь с ними и проверяете адреса на комплаенс. Расчёты платформы с вами идут через мастер-счёт - предоплатный сервисный баланс вашей учётной записи. Это основной сценарий, и о нём вся документация ниже. |
Партнёр по приёму платежей
|
payin
|
optional | Отдельный контур приёма рублёвых платежей с расчётом в USDT - собственные эндпоинты, статусы и события. Описан в разделе Payment Gateway (RUB) и подключается по отдельному договору. |
Что входит в контур классического мерчанта
- Клиенты - ваши конечные пользователи: создание по телефону, поиск, блокировка, единая история операций.
- Крипто-кошельки клиентов - адреса пополнения по сетям, депозиты, выводы на внешние адреса, расчёты
charge/payout. - Мастер-счёт - предоплатный сервисный баланс: пополнение, леджер, витрина тарифа и лимитов.
- AML-проверки - скоринг блокчейн-адресов с отчётом в JSON и PDF, оплата с мастер-счёта.
- Верификация - KYC физических лиц и KYB компаний.
- Платежи - покупка и продажа криптовалюты за рубли, баланс клиента.
- Вебхуки - асинхронные события с HMAC-подписью и повторами доставки.
- Песочница - изолированное окружение: ключи
sk_test_не двигают реальных денег.
ℹ
Мастер-счёт нужен до первого платного вызова
Услуги платформы (например AML-проверки) и выплаты клиентам списываются с мастер-счёта. Пополните его до запуска в бой, иначе первый же платный вызов вернёт 402. Порог низкого остатка и вебхук о нём - в разделе Merchant Balance.
Модель доступа
B2B endpoints проверяют стек middleware в таком порядке:
- API Key auth - обычная аутентификация через
Authorization: Bearer sk_(live|test)_xxx. См. Authentication. - B2B gate - проверка флага
users.b2b_enabled = trueна учётке владельца ключа. Включается админом Finance OS вручную после договора. - Environment isolation -
sk_test_ключ видит толькоenv='sandbox'customers,sk_live_- толькоenv='live'. Попытка cross-env →404(намеренно, не403: чтобы не утечь существование).
Сквозной пример интеграции
Шаги для полной интеграции нового партнёра:
- Партнёр регистрируется на fin-os.io, проходит свой собственный KYC.
- Партнёр и Finance OS подписывают B2B-договор, флаг
b2b_enabledподнимается админом. - Партнёр генерирует
sk_live_иsk_test_ключи в Личном Кабинете → API ключи. - Партнёр подписывает webhook-endpoint через
POST /api/v1/webhooksи сохраняет полученный одноразовый секрет. - Партнёр пополняет мастер-счёт: с него оплачиваются услуги платформы и выплаты клиентам.
- Для каждого своего end-user'а:
- Партнёр собирает консент end-user'а на обработку его данных в Finance OS.
POST /api/v1/customers- создать клиента (телефон в E.164 обязателен).POST /api/v1/customers/{uuid}/consent- зафиксировать факт получения консента (IP + timestamp).POST /api/v1/customers/{uuid}/wallet/addresses- выдать адрес пополнения в нужной сети.- Депозиты, выводы и расчёты - по событиям вебхуков, без опроса.
- Для фиатных операций дополнительно проводится KYC; после
kyc_status='verified'доступны платежи.
Логика данных
Finance OS - это прокси-фасад поверх внутренних провайдеров (платежи, KYC). Партнёр взаимодействует только с Finance OS API; внутренняя инфраструктура провайдеров скрыта.
- Customer state хранится у Finance OS:
kyc_status,kyc_level, балансы. - Документы KYC хранятся у Finance OS, переадресуются провайдеру для верификации.
- Платежи (СБП) идут через расчётный счёт Finance OS; Finance OS внутренне маркирует операцию customer'ом и обновляет баланс customer'а.
- Webhook delivery - Finance OS подписывает HMAC и пушит на партнёрский URL с retry-логикой.
Что дальше
- Customers - модель клиента, идемпотентное создание, поиск, блокировка, история
- Customer Wallets - адреса, депозиты, выводы, расчёты
charge/payout - Merchant Balance - мастер-счёт, леджер, тариф и лимиты
- AML Screening - проверка адресов, отчёты, тарификация
- KYC Verification - полный flow с примерами
- Payments - buy/sell/deposit/withdraw
- Webhooks - подписка, подпись, повторы доставки
- Sandbox - тестирование без реальных операций
- Error Codes - полный реестр кодов и стратегия повторов
Примеры кода
# Проверка B2B доступа: список customers
curl -X GET https://fin-os.io/api/v1/customers \
-H "Authorization: Bearer sk_test_..." \
-H "Accept: application/json"
# 403 если b2b_enabled=false:
# {
# "message": "B2B access is not enabled for this account...",
# "error_code": "B2B_ACCESS_REQUIRED",
# "docs": "https://fin-os.io/docs/b2b"
# }
# 200 если включено:
# {
# "data": [],
# "meta": { "total": 0, ... }
# }
const FINOS_API = 'https://fin-os.io/api/v1';
const SECRET = process.env.FINOS_SECRET_KEY; // sk_test_ или sk_live_
async function checkB2bAccess() {
const res = await fetch(`${FINOS_API}/customers`, {
headers: { 'Authorization': `Bearer ${SECRET}` },
});
if (res.status === 403) {
const err = await res.json();
throw new Error(`B2B not enabled: ${err.docs}`);
}
return res.json();
}
$response = Http::withToken(config('services.finos.secret_key'))
->acceptJson()
->get('https://fin-os.io/api/v1/customers');
if ($response->status() === 403) {
throw new \RuntimeException(
'B2B access required: ' . $response->json('docs')
);
}
$customers = $response->json('data');
import requests, os
resp = requests.get(
'https://fin-os.io/api/v1/customers',
headers={'Authorization': f"Bearer {os.environ['FINOS_SECRET_KEY']}"},
)
if resp.status_code == 403:
raise RuntimeError(f"B2B not enabled. See {resp.json()['docs']}")
customers = resp.json()['data']