Mandarin API v1
Одна интеграция для финансовых маршрутов
Ваш код работает с клиентами, балансами и операциями Mandarin. Конкретного брокера, платёжного агента или сервиса выплат выбирает платформа.
Ключи регистрации относятся к тестовому партнёру. Доступность реальных реквизитов зависит от назначенного подключения. Проверяйте paymentInstructions.sandbox: тестовые инструкции оплачивать нельзя.
Авторизация
Передавайте ключ в заголовке каждого запроса. Полное значение показывается один раз в кабинете.
X-API-Key: mnd_test_••••••••.••••••••••••Создайте клиента
curl https://api.mandarinex.io/v1/customers \
-H "X-API-Key: $MANDARIN_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"externalCustomerId": "client-001",
"type": "person"
}'Показывайте клиенту именно замороженные инструкции из ответа. Если в paymentInstructions.details.payableAmount есть сумма, оплатить нужно её: она может включать комиссию назначенного канала. Поле верхнего уровня amount остаётся суммой RUB, которая будет зачислена после подтверждения. Даже если канал внутри Mandarin получает другой обеспечивающий актив, клиентский депозит остаётся RUB до отдельной операции обмена.
Некоторые маршруты бесшовно передают уже одобренную анкету Mandarin сервер-сервер, без второго KYC-интерфейса для клиента. 409 funding_customer_profile_incomplete означает, что в анкете не хватает обязательных данных; 409 funding_customer_not_ready — канал ещё не разрешил пополнение; 409 funding_liquidity_unavailable — сейчас нельзя полностью исполнить указанную сумму.
Пройдите KYC
KYC — обязательный отдельный этап до получения QR и котировки выплаты. Сохраните анкету, загрузите документы, зафиксируйте фактически принятое согласие и отправьте пакет. Для каждого изменяющего запроса используйте отдельный стабильный Idempotency-Key.
1. Анкета клиента
curl -X PUT https://api.mandarinex.io/v1/customers/CUSTOMER_UUID/kyc/profile \
-H "X-API-Key: $MANDARIN_API_KEY" \
-H "Idempotency-Key: kyc-profile-client-001-v1" \
-H "Content-Type: application/json" \
-d '{
"profile": {
"firstName": "Иван",
"lastName": "Петров",
"middleName": "Сергеевич",
"dateOfBirth": "1990-04-12",
"phone": "+79991234567",
"email": "ivan.petrov@example.com",
"citizenship": "RU",
"residency": "RU",
"address": {"country": "RU", "city": "Москва", "addressLine": "ул. Примерная, д. 1"},
"passport": {"number": "4500 123456", "issuedBy": "ГУ МВД России по г. Москве", "issuedAt": "2015-05-20"}
}
}'Для российского паспорта передавайте серию (4 цифры) и номер (6 цифр) вместе в passport.number: например, 4500 123456 или 4500123456. Автопроверка понимает этот формат и прежние анкеты snake_case. Поля passport.divisionCode и placeOfBirth необязательны; если переданы, они сверяются с документом.
2. Документы
Поддерживаются JPEG, PNG и PDF. Для текущей автоматической проверки загрузите три файла отдельными запросами: passport_spread, registration и selfie_with_passport.
curl -X POST https://api.mandarinex.io/v1/customers/CUSTOMER_UUID/kyc/documents \
-H "X-API-Key: $MANDARIN_API_KEY" \
-H "Idempotency-Key: kyc-passport-client-001-v1" \
-F "documentType=passport_spread" \
-F "file=@passport.jpg;type=image/jpeg"Для дозапроса прочитайте GET /v1/customers/{id}/document-requests и передайте его documentRequestId при загрузке каждого запрошенного типа.
3. Согласие и отправка
Используйте только согласованный с Mandarin тип и версию текста, которые клиент действительно принял.
curl -X POST https://api.mandarinex.io/v1/customers/CUSTOMER_UUID/kyc/consents \
-H "X-API-Key: $MANDARIN_API_KEY" \
-H "Idempotency-Key: kyc-consent-client-001-v1" \
-H "Content-Type: application/json" \
-d '{"consentType":"personal_data_processing","consentVersion":"2026-09-01","evidenceReference":"consent-client-001-20260917T101500Z"}'
curl -X POST https://api.mandarinex.io/v1/customers/CUSTOMER_UUID/kyc/submit \
-H "X-API-Key: $MANDARIN_API_KEY" \
-H "Idempotency-Key: kyc-submit-client-001-v1"HTTP 202 означает начало проверки, а не одобрение. Читайте GET /v1/customers/{id}/kyc до approved. При rejected покажите клиенту rejectionReason, дайте исправить анкету или документы и отправьте пакет повторно с новым Idempotency-Key. Дозапрос используйте, если нужен только дополнительный документ. При 409 kyc_package_incomplete ответ содержит список missing.
4. Онбординг у брокера и ДБО
Этот этап нужен только маршрутам с брокером. Одобрение Mandarin не заменяет решение брокера и подписание ДБО. POST /v1/customers/{id}/onboardings передаст пакет брокеру, выбранному маршрутом.
curl https://api.mandarinex.io/v1/customers/CUSTOMER_UUID/onboardings \
-X POST \
-H "X-API-Key: $MANDARIN_API_KEY" \
-H "Idempotency-Key: onboarding-client-001"Когда статус станет `awaiting_signature`, создайте signing session, покажите клиенту все возвращённые PDF и подтвердите их хэши. Вместе с подтверждением показа передайте PNG собственноручной подписи, нормализованные штрихи, время создания и версию согласия client-signature-use-v1. Брокер хранит образец зашифрованно и активирует его только после правильного OTP для неизменённого пакета. Подтверждение переведёт онбординг в `active`. До статуса `active` пополнение и вывод через этого брокера недоступны. Для банковской анкеты партнёр может получить подтверждённый PNG через GET /v1/customers/{id}/card-signature с правами kyc:read и kyc:documents:read; нужно отдельно оформить согласие клиента на такое использование подписи.
Если email клиента исправлен до подписания ДБО, передайте новый адрес в PUT /v1/customers/{id}/onboardings/{onboarding_id}/contact-email с телом {"email":"new@example.com"}. Старые неподписанные сессии и коды аннулируются; создайте новую сессию подписания.
Проверьте лимит клиента
GET /v1/customers/{id}/limit возвращает максимальный, использованный и доступный RUB-лимит физического лица. При исчерпании лимита брокер блокирует обмен и вывод, но продолжает выдавать реквизиты для пополнения.
Для повышения передайте в POST /v1/customers/{id}/limit-requests новый лимит, стабильный externalRequestId и 1–10 документов ИПДС в base64. Поддерживаются PDF, DOCX, JPEG и PNG до 10 МБ каждый. Решение брокера появится в следующем ответе метода лимита.
Создайте пополнение RUB
Сначала дождитесь статуса KYC approved, затем запросите доступные реквизиты. Без одобренного KYC оба метода вернут 409 kyc_not_approved, а запрос к банку или QR-провайдеру не уйдёт. Если маршрут вернул несколько вариантов, покажите их клиенту и передайте выбранный `id` при создании пополнения.
curl "https://api.mandarinex.io/v1/deposit-methods?customerId=CUSTOMER_UUID&amount=10000.00&asset=RUB" \
-H "X-API-Key: $MANDARIN_API_KEY"`Idempotency-Key` защищает от случайного повторного создания операции.
curl https://api.mandarinex.io/v1/deposits \
-H "X-API-Key: $MANDARIN_API_KEY" \
-H "Idempotency-Key: order-001" \
-H "Content-Type: application/json" \
-d '{
"creditOwner": {"type": "customer", "id": "CUSTOMER_UUID"},
"money": {"amount": "10000.00", "asset": "RUB"},
"method": {"id": "OPAQUE_METHOD_ID"},
"partnerReference": "order-001"
}'Отмените неоплаченную заявку
Для заявки в статусе awaiting_funds вызовите отмену. Требуется право deposits:write. Тело запроса и Idempotency-Key не требуются: повтор привязан к тому же идентификатору заявки.
curl -X POST https://api.mandarinex.io/v1/deposits/DEPOSIT_UUID/cancel \
-H "X-API-Key: $MANDARIN_API_KEY"Ответ HTTP 200 — полный объект пополнения с status: cancelled и paymentInstructions.status: cancelled. Скрывайте QR и возможность оплаты. Баланс не меняется. Повторная отмена возвращает тот же результат.
Отмена доступна только для способов пополнения, которые вернул назначенный маршрут и которые поддерживают отмену. Для остальных возвращается 409 deposit_cancellation_unavailable. Оплаченную или недоступную для отмены заявку нельзя отменить: 409 deposit_not_cancellable. После 503 deposit_cancellation_unconfirmed повторите отмену того же ID: не создавайте заменяющую заявку и не показывайте успешную отмену до подтверждения.
Обменяйте RUB в нужный актив
Сначала получите короткоживущую котировку. Источник курса, внутренняя наценка и актив вывода выбираются маршрутом партнёра и не передаются как название провайдера.
curl https://api.mandarinex.io/v1/exchange-quotes \
-H "X-API-Key: $MANDARIN_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"owner": {"type": "customer", "id": "CUSTOMER_UUID"},
"fromAsset": "RUB",
"toAsset": "USDT",
"sourceAmount": "10000.00"
}'Зафиксируйте обмен отдельным запросом `POST /v1/exchanges` с `quoteId` и `Idempotency-Key`.
Закрепите RUB по принятой OTC-сделке
POST /v1/otc-reserves требует exchanges:write и стабильный Idempotency-Key. Передайте UUID клиента, внешний UUID сделки, принятую сумму, курс, итог USDT, сеть и адрес. После ответа RubleReserved сумма атомарно перемещена из доступного RUB в резерв брокера. Последующие поручения и выплата этим методом не исполняются.
Если адрес не прошёл проверку перед выплатой, отправьте PATCH /v1/otc-reserves/{operationId}/destination с {"destinationAddress":"T..."}. Адрес обновится у брокера без изменения резерва; перед выплатой проверьте новый адрес заново.
После одобрения KYC для СБП-канала с отдельной верификацией вызовите POST /v1/customers/CUSTOMER_UUID/funding-verification с {"amount":"1000.00","startVerification":false}, правом deposits:write и Idempotency-Key. Дождитесь ready=true. Статусы pending, customer_action_required и operator_action_required означают ожидание, действие клиента или обращение в поддержку. Для новой проверки используйте новый ключ. Если телефон клиента не привязан к его ФИО в СБП, вызовите метод для того же CUSTOMER_UUID с новым ключом и {"amount":"1000.00","startVerification":false,"phone":"+79990000001"}. Mandarin передаст одобренные данные с новым номером в канал пополнения без новой анкеты и без ссылки. При неопределённом ответе повторяйте тот же ключ и тело; при 409 funding_customer_phone_rejected уточните номер у клиента. Поля phone и startVerification=true нельзя совмещать. Значение startVerification=true явно запрашивает одноразовую ссылку verificationUrl; её открывает клиент, не предзагружайте её. Метод не создаёт QR и не перемещает деньги.
Выведите USDT или KGS
Сначала запросите GET /v1/payout-methods, затем создайте котировку выплаты. Если items пуст, партнёру не назначен активный способ вывода — выполнение выплаты недоступно. Для USDT маршрут может вернуть crypto_address, для KGS — mobile_wallet, card или оба способа одновременно. Интеграция всегда использует тип и поля, полученные из discovery-метода, и не зависит от внутреннего исполнителя. Для карт список service ограничен разрешёнными партнёру активными сервисами Hyperion и обновляется не реже раза в 60 секунд. Если каталог провайдера недоступен, метод вернёт 503 payout_provider_unavailable; повторите получение списка позже. После пополнения QR в RUB сначала выполните явный обмен в актив вывода. Без KYC approved котировка вернёт 409 kyc_not_approved до обращения к каналу выплаты; исполнение повторно проверит KYC до списания. Списание выполняется только с баланса UUID клиента из котировки.
KYC approved → проверка готовности пополнения → GET /v1/deposit-methods → POST /v1/deposits → дождаться succeeded → котировка и обмен в актив вывода → GET /v1/payout-methods → котировка выплаты → исполнение → проверка финального статуса. QR и котировка сами по себе деньги не перемещают. Оплата QR проверяется фоновым процессом примерно каждые 30 секунд, в том числе до истечения QR; запрос статуса не подтверждает оплату и не зачисляет деньги сам. Для автоматической проверки KYC передавайте анкету и три изображения: passport_spread, registration, selfie_with_passport. Каждая новая финансовая команда использует собственный ключ идемпотентности; повтор той же команды — прежний ключ и то же тело. Конкретный банк, брокер или сервис выплаты выбирает маршрут Mandarin и в партнёрском API не раскрывается.
Если discovery вернул card, выберите значение поля service из его destinationFields и отправьте {"type":"card","service":"bakai","account":"4111111111111111","recipient":{"firstName":"Иван","lastName":"Петров"}}. Код сервиса берётся из ответа API, номер карты содержит 16–19 цифр; пробелы и дефисы допускаются при вводе. Mandarin проверит активность сервиса, лимит и комиссию до выдачи котировки. Для KGS на карту или мобильный кошелёк обязательны recipient.firstName и recipient.lastName фактического получателя; дополнительно можно передать middleName и dateOfBirth. Данные получателя сохраняются зашифрованно в котировке. Не подменяйте mobile_wallet картой.
curl https://api.mandarinex.io/v1/payout-quotes \
-H "X-API-Key: $MANDARIN_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"owner": {"type": "customer", "id": "CUSTOMER_UUID"},
"money": {"amount": "1.00", "asset": "KGS"},
"destination": {"type": "mobile_wallet", "account": "996700000000",
"recipient": {"firstName": "Иван", "lastName": "Петров"}}
}'Ответ содержит `fee`, `totalDebit` и замаскированный адресат. Передайте `quoteId` в `POST /v1/payouts` с уникальным `Idempotency-Key`; итоговый статус читайте через `GET /v1/payouts/{id}`. Тип KGS зависит от назначенного маршрута.
Подтверждённое пополнение зачисляет RUB клиенту. Обмен RUB → KGS меняет клиентские балансы с проводками в Mandarin; остатки исполнителей не синхронизируются. При выплате KGS резервируются до конечного результата: успех списывает резерв, отказ возвращает доступный остаток.
Проверьте баланс
curl https://api.mandarinex.io/v1/customers/CUSTOMER_UUID/balances \
-H "X-API-Key: $MANDARIN_API_KEY"Создание пополнения не меняет баланс. RUB появляются только после подтверждённого расчёта.
Доступные методы
/v1/capabilitiesCapabilities/v1/customersCreate Customer/v1/customersList Customers/v1/customers/{customer_id}Get Customer/v1/customers/{customer_id}/balancesGet Customer Balances/v1/customers/{customer_id}/card-signatureRetrieve the broker's active client signature specimen for a card application/v1/customers/{customer_id}/document-requestsList Customer Document Requests/v1/customers/{customer_id}/funding-verificationPrepare or check an approved customer's funding verification/v1/customers/{customer_id}/kycGet the customer's Mandarin KYC status/v1/customers/{customer_id}/kyc/consentsRecord customer consent evidence/v1/customers/{customer_id}/kyc/documentsList Customer Kyc Documents/v1/customers/{customer_id}/kyc/documentsUpload an encrypted KYC document/v1/customers/{customer_id}/kyc/documents/{document_id}Download Customer Kyc Document/v1/customers/{customer_id}/kyc/profileSave a versioned KYC questionnaire/v1/customers/{customer_id}/kyc/submitSubmit the KYC package for Mandarin review/v1/customers/{customer_id}/limitПолучить лимит клиента/v1/customers/{customer_id}/limit-requestsЗапросить увеличение лимита/v1/customers/{customer_id}/onboardingsList Onboardings/v1/customers/{customer_id}/onboardingsSubmit Onboarding/v1/customers/{customer_id}/onboardings/{onboarding_id}/contact-emailSynchronize a corrected email before signing/v1/customers/{customer_id}/onboardings/{onboarding_id}/signing-sessionsCreate Signing Session/v1/customers/{customer_id}/onboardings/{onboarding_id}/signing-sessions/{signing_id}Get Signing Session/v1/customers/{customer_id}/onboardings/{onboarding_id}/signing-sessions/{signing_id}/confirmConfirm Signing/v1/customers/{customer_id}/onboardings/{onboarding_id}/signing-sessions/{signing_id}/display-confirmationConfirm Signing Display/v1/customers/{customer_id}/onboardings/{onboarding_id}/signing-sessions/{signing_id}/otp/sendResend Signing Otp/v1/deposit-methodsList RUB deposit methods for an approved customer/v1/depositsCreate a RUB deposit for an approved customer/v1/depositsList RUB deposits/v1/deposits/{deposit_id}Get a RUB deposit/v1/deposits/{deposit_id}/cancelCancel an unpaid deposit/v1/deposits/{deposit_id}/payment-claimReport client payment without crediting funds/v1/exchange-quotesPost Exchange Quote/v1/exchange-quotes/{quote_id}Get Exchange Quote/v1/exchangesPost Exchange/v1/exchangesList Exchanges/v1/exchanges/{exchange_id}Get Exchange/v1/otc-reservesPost Otc Reserve/v1/otc-reserves/{operation_id}/destinationPatch Otc Destination/v1/partnerGet Partner/v1/payout-methodsPayout Methods/v1/payout-quotesQuote a payout for an approved customer/v1/payout-quotes/{quote_id}Get Payout Quote/v1/payoutsReserve and submit an approved customer's payout/v1/payoutsList Payouts/v1/payouts/{payout_id}Get PayoutПолная актуальная схема, форматы KYC и примеры ответов доступны в интерактивном OpenAPI.
Основные статусы
- awaiting_funds
- Реквизиты созданы, подтверждённого платежа нет.
- cancelled
- Неоплаченная заявка отменена, QR больше не используется, баланс не меняется.
- expired
- Срок действия реквизитов истёк; прекратите показывать их клиенту, баланс не меняется.
- processing
- Операция обрабатывается внешним сервисом.
- succeeded
- Расчёт подтверждён, результат отражён в балансе ровно один раз.
- failed
- Операция окончательно отклонена или завершилась ошибкой, баланс не зачислен.
Клиент сообщил об оплате
POST /v1/deposits/{depositId}/payment-claim требует deposits:write. Передайте фактически отправленную сумму в теле {"amount":"8063000.00"}. До банковской сверки Mandarin обновит сумму заявки, если она отличается от первоначальной. Повтор безопасен для той же заявки и суммы. paymentInstructions.paymentClaimed означает сообщение клиента; баланс изменяется только после подтверждения банка. При payment_claim_unconfirmed повторите ту же заявку.
Причины ручной AI-проверки
В событии kyc.manual_review_required поле reasonCodes разделяет технические ошибки (ai_request_rejected, ai_authentication_failed, ai_rate_limited, ai_service_unavailable, ai_connection_failed, ai_timeout), нечитаемые поля (unreadable:field), несовпадения (mismatch:field) и незаполненные поля анкеты (profile_missing:field). Технический сбой не является отказом по документам.
Ошибки
API возвращает HTTP-статус и стабильный машинный код в поле detail. Повторяйте запрос с тем же Idempotency-Key только если тело запроса не менялось.
{"detail": "idempotency_conflict"}