Руководство по интеграции
Всё, что нужно знать для подключения к Twin Bridge — без лишней технической глубины.
Что такое Twin Bridge
Twin Bridge — это технологический мост между международными крипто-провайдерами и локальными лицензированными криптоVASP-операторами. Простыми словами: если провайдер хочет предложить своим клиентам обмен KGS/USDT, но не имеет локальной лицензии и инфраструктуры — Twin Bridge решает эту задачу.
Важно понимать: Twin Bridge не является финансовой компанией, VASP-оператором или кошельком. Мы не прикасаемся к деньгам и не храним средства. Мы передаём данные между участниками — как почтальон, который доставляет письма, но не читает их.
Юридически просто: Twin Bridge — IT-решение. Провайдеры и VASP-операторы берут на себя все финансовые лицензии и KYC. Twin Bridge только обеспечивает технологическое соединение между ними.
Для провайдеров
международные On/Off-Ramp провайдеры. Получаете доступ к локальным VASP-операторам через единый API. Один раз интегрировались — работаете со всеми партнёрами.
Для VASP-операторов
Лицензированные VASP-операторы. Получаете поток международных клиентов без необходимости строить собственные API-интеграции с каждым провайдером.
Как это работает
Рассмотрим на примере: клиент провайдера хочет купить USDT за KGS в Кыргызстане.
Создание транзакции
Провайдер отправляет запрос: хочу обменять 5 000 KGS на USDT для клиента с подтверждённым KYC. Twin Bridge принимает запрос, проверяет подпись, регистрирует транзакцию и передаёт команду в маршрут VASP.
Получение курса и QR-кода
Twin Bridge запрашивает актуальный курс у VASP-оператора. Затем VASP-оператор формирует QR-код для оплаты через ELQR и передаёт его в Twin Bridge. QR действителен ограниченное время.
QR возвращается клиенту
Провайдер получает QR-данные и показывает их клиенту в своём виджете. Клиент сканирует QR и оплачивает счёт VASP-оператора через ELQR (KGS).
Подтверждение оплаты
После подтверждения оплаты в ELQR VASP-оператор отправляет подписанный webhook. Twin Bridge проверяет подлинность и обновляет статус транзакции.
Финальное уведомление
Twin Bridge передаёт payment.completed на webhook-URL провайдера. На этом роль Twin Bridge завершена — мы передали данные.
До этого момента:
— ON_RAMP: VASP-оператор отправил USDT на крипто-адрес клиента.
— OFF_RAMP: VASP-оператор выплатил KGS клиенту на банковские реквизиты (телефон / банк).
Twin Bridge в движении денег не участвует — только передаёт данные между сторонами.
Интерактивную визуализацию потока данных смотри в Admin-кабинете → Инструменты → Граф потока.
Для кого
Если вы — провайдер (On/Off-Ramp)
У вас есть международные клиенты, которые хотят работать с KGS или другими локальными валютами. Вам нужны локальные лицензированные партнёры для исполнения — но строить интеграцию с каждым по отдельности долго и дорого.
Twin Bridge даёт вам единый API для доступа ко всем подключённым VASP-операторам. Интегрировались один раз — получили доступ к экосистеме.
Если вы — VASP-оператор
У вас есть лицензия, инфраструктура и возможность исполнять сделки. Но привлечение международного трафика требует ресурсов. Самостоятельно интегрироваться с провайдерами — это месяцы работы для каждого.
Twin Bridge берёт это на себя. Вы подключаетесь один раз, получаете поток клиентов от всех провайдеров в экосистеме.
- Не нужна финансовая лицензия от Twin Bridge — её имеют провайдеры и VASP-операторы
- KYC не нужно проходить повторно — клиент уже верифицирован у провайдера, токен передаётся через Twin Bridge
- Один API вместо N интеграций с каждым партнёром
- Sandbox-режим для тестирования без реальных денег
Способы подключения
Twin Bridge поддерживает пять путей интеграции в зависимости от ваших технических возможностей и категории партнёра. Способ хранится в partners.integration_mode и виден в админ-кабинете.
Актуальная модель состоит из двух осей. Ось 1 — способ работы: провайдер может быть custody / Phase 1 (держит USDT и сам зачисляет или выплачивает клиенту) либо lead-gen / Phase 2 (USDT не держит, деньги двигает VASP). Ось 2 — способ подключения: self_api, we_pull или widget для провайдера; we_built или self_pushed для VASP. Эти оси независимы.
Для провайдеров (PROVIDER) — три варианта
Для провайдера бизнес-модель фиксируется отдельно от подключения флагом partners.has_usdt_custody: custody означает Phase 1, lead-gen означает Phase 2. В режимах self_api и we_pull провайдер остаётся активным участником: ведёт свой KYC, свой UI и передаёт данные в Twin Bridge.
self_api — провайдер пишет код под наш API (по умолчанию).У провайдера есть свой backend и свой KYC (Sumsub или собственный). Он читает Provider API spec, реализует HMAC-подпись, шлёт
POST /v1/transactions и принимает наши webhooks. KYC передаёт либо через kyc_share_token, либо как набор PII-полей в payload.
widget — встраиваемый виджет для провайдеров без своего KYC.E-commerce магазины, гэмблинг, кошельки, новые сервисы — те, у кого нет своей KYC-инфраструктуры. Провайдер вставляет наш iframe на свой сайт, виджет сам проводит KYC через Sumsub (наш аккаунт) и проводит обмен. Минимум кода у провайдера — только HTML-snippet с publishable key.
we_pull — мы интегрируемся к API провайдера (enterprise).Крупный провайдер с уже работающим API (Onramper, Transak, Ramp) — мы пишем Go-адаптер у себя который их API опрашивает каждые несколько секунд и создаёт транзакции на нашей стороне. Только по подписанному commercial deal.
Для VASP-операторов (VASP) — два варианта
we_built — мы пишем адаптер под ваш API (по умолчанию).Вы даёте нам документацию своего API + test credentials + webhook secret. Мы пишем Go-адаптер в
adapters/vasp/<your-slug>/ под ваш конкретный формат: HMAC, маппинг статусов, парсер webhooks. ~2–5 дней работы на нашей стороне.
self_pushed — вы реализуете наш стандартный VASP-контракт.Если у вас нет своего API или вы готовы построить его под нашу спецификацию — вы реализуете hybrid-контракт из 7 endpoints: 5 базовых (
/vasp/v1/quote, /qr, /payout, /tx/{id}, /health) плюс 2 Phase 2 endpoint'а (/vasp/v1/send-usdt, /vasp/v1/usdt-deposit-address) с HMAC-валидацией. Спецификация: vasp-contract.md. Reference implementation: simulator/mock-self-pushed-vasp/main.go.
Webhook-форматы. У каждого партнёра свой формат webhooks — это нормально. Различия скрываются в адаптерах: каждый адаптер в adapters/<type>/<slug>/ парсит входящий формат и нормализует в общие типы. Ядро системы работает с одним общим контрактом, независимо от формата конкретного партнёра.
С чего начать
Шаг 1. Свяжитесь с нами
Напишите на [email protected] или заполните форму на главной странице. Мы согласуем тип партнёрства (провайдер или VASP-оператор) и подпишем NDA.
Шаг 2. Получите API-ключи
После подписания договора вы получите два набора ключей:
- Sandbox-ключи — для тестирования. Реальные сервисы не вызываются, деньги не двигаются.
- Production-ключи — выдаются после успешного тестирования.
Каждый запрос подписывается через HMAC-SHA256. Ключи хранятся только на вашей стороне — мы их не храним в открытом виде.
Шаг 3. Настройте webhook-URL
Укажите URL, на который Twin Bridge будет отправлять уведомления о статусах транзакций. Все входящие webhooks подписаны — вы проверяете подпись и принимаете только легитимные запросы.
Шаг 4. Протестируйте в Sandbox
Запустите несколько тестовых транзакций через Симулятор. Убедитесь, что ваш сервис корректно обрабатывает все статусы и вебхуки.
Шаг 5. Production
Замените Sandbox-ключи на Production. Первые транзакции проходят под нашим мониторингом — мы готовы помочь оперативно, если что-то пойдёт не так.
Важно: Production-ключи активируются только после того, как вы успешно прошли все тестовые сценарии в Sandbox и мы подтвердили готовность.
Поток транзакции
Транзакция проходит через несколько статусов. Каждый статус означает конкретное состояние и следующий ожидаемый шаг.
ON_RAMP (KGS → USDT)
- Провайдер создаёт транзакцию → статус
INITIATED - Twin Bridge получает курс и QR → статус
PENDING_PAYMENT, QR возвращается провайдеру - Клиент оплачивает → статус
PAID - VASP-оператор исполняет → статус
PROCESSING - Успешно завершено → статус
COMPLETED, webhook провайдеру
Если QR истёк до оплаты — транзакция переходит в CANCELLED. Провайдер может создать новую транзакцию.
Статусы транзакции
Это все возможные состояния транзакции, которые вы будете получать в webhooks и ответах API.
| Статус | Значение | Следующий шаг |
|---|---|---|
| INITIATED | Транзакция создана | Ждём QR от VASP-оператора |
| PENDING_PAYMENT | QR готов, ждём оплату | Показать QR клиенту |
| PAID | Оплата поступила | VASP-оператор исполняет |
| PROCESSING | VASP-оператор выполняет сделку | Ждём подтверждения |
| COMPLETED | Транзакция завершена успешно | Финальное состояние |
| FAILED | Ошибка при исполнении VASP-оператором | Финальное состояние |
| CANCELLED | Отменена (напр. QR истёк) | Финальное состояние |
Webhooks
Twin Bridge передаёт уведомления на ваш webhook-URL при каждом изменении статуса транзакции. Это основной способ получать обновления в реальном времени.
Какие события приходят
payment.created— транзакция создана, QR готовpayment.completed— транзакция успешно завершенаpayment.failed— транзакция не удаласьpayment.cancelled— транзакция отменена
Как проверить подлинность webhook
Каждый webhook подписан через HMAC-SHA256. Заголовки запроса содержат:
X-Timestamp— время отправки (Unix timestamp)X-Signature— подпись:HMAC_SHA256(secret, timestamp + "." + body)
Проверяйте подпись и убеждайтесь, что timestamp не старше 300 секунд — это защита от replay-атак.
Обязательно: всегда проверяйте подпись перед обработкой webhook. Запросы без корректной подписи следует отклонять с кодом 401.
Структура payload
Тело каждого webhook — JSON-объект следующей структуры:
{
"event_type": "payment.completed",
"tx_id": "8f3d2a1b-...",
"status": "COMPLETED",
"timestamp": "2026-04-13T10:23:45Z",
"payload": {
"tx_id": "8f3d2a1b-...",
"status": "COMPLETED",
"direction": "ON_RAMP",
"fiat_amount": "5000.00",
"fiat_currency": "KGS",
"crypto_amount": "57.93",
"crypto_currency": "USDT",
"rate": "86.30",
"created_at": "2026-04-13T10:20:00Z",
"paid_at": "2026-04-13T10:22:10Z",
"completed_at": "2026-04-13T10:23:45Z"
}
}
Поле failure_reason присутствует только в событиях payment.failed и payment.cancelled. В событии payment.created дополнительно возвращается объект payment с qr_data, qr_url, expires_at, amount, currency.
Гарантия доставки
Twin Bridge использует Outbox Pattern. Если ваш сервер временно недоступен, webhook повторяется по расписанию: немедленно, затем через 1 с, 5 с, 30 с и 5 мин — итого 5 попыток. После исчерпания попыток событие помечается как необработанное и требует ручного разбора. Сделайте ваш обработчик идемпотентным — одно событие может прийти более одного раза.
Авторизация
Каждый запрос к API Twin Bridge должен содержать три заголовка:
X-API-Key— ваш публичный API-ключX-Timestamp— текущий Unix timestampX-Signature— HMAC-SHA256 подпись запроса
Подпись формируется так: HMAC_SHA256(api_secret, timestamp + method + path + sha256(body))
Timestamp не должен отличаться от серверного времени более чем на 300 секунд. Это защищает от перехвата и повторного использования запросов.
Для POST-запросов также необходим заголовок Idempotency-Key — уникальный UUID для каждой новой транзакции. Повторный запрос с тем же ключом вернёт результат первого запроса без создания дубликата.
Коды ошибок
Все ошибки возвращаются в едином формате:
{
"error": "Человекочитаемое описание",
"code": "MACHINE_READABLE_CODE"
}
Для ошибок, связанных с конкретной транзакцией, дополнительно возвращается поле tx_id.
| HTTP | Код | Когда возникает | Что делать |
|---|---|---|---|
| 400 | INVALID_BODY |
Тело запроса не является корректным JSON | Проверьте Content-Type и формат тела |
| 400 | VALIDATION_ERROR |
Обязательное поле отсутствует или имеет неверный тип/значение | Проверьте поля запроса по схеме |
| 400 | INVALID_ID |
Параметр :id в пути не является корректным UUID |
Убедитесь, что передаёте полный UUID транзакции |
| 400 | IDEMPOTENCY_MISSING |
POST-запрос отправлен без заголовка Idempotency-Key |
Добавьте заголовок Idempotency-Key с уникальным UUID |
| 401 | AUTH_MISSING |
Один или несколько обязательных auth-заголовков отсутствуют | Передайте X-API-Key, X-Timestamp, X-Signature |
| 401 | AUTH_TIMESTAMP |
Timestamp отличается от серверного времени более чем на 300 секунд | Синхронизируйте системное время, используйте NTP |
| 401 | AUTH_INVALID_KEY |
API-ключ не найден или отозван | Проверьте, что используете правильный ключ (Sandbox ≠ Production) |
| 401 | AUTH_INVALID_SIGNATURE |
Подпись HMAC-SHA256 не совпадает | Проверьте алгоритм подписи и порядок конкатенации |
| 403 | FORBIDDEN |
Запрос к транзакции, которая принадлежит другому партнёру | Убедитесь, что используете верный API-ключ |
| 404 | NOT_FOUND |
Транзакция с указанным ID не найдена | Проверьте корректность ID |
| 422 | CREATE_FAILED |
Транзакцию не удалось создать (ошибка на стороне VASP или внутренняя) | Повторите запрос с новым Idempotency-Key |
| 422 | CANCEL_FAILED |
Отмена невозможна — транзакция уже в финальном статусе | Проверьте текущий статус транзакции |
| 429 | RATE_LIMIT_EXCEEDED |
Превышен лимит запросов | Подождите значение в заголовке Retry-After |
| 500 | FETCH_FAILED |
Внутренняя ошибка при получении данных транзакции | Повторите запрос через несколько секунд; при повторении — свяжитесь с нами |
Лимиты запросов
Twin Bridge применяет rate limiting на уровне API-ключа. Лимит: 100 запросов в минуту на каждый ключ (Production и Sandbox считаются раздельно).
При превышении лимита API возвращает 429 Too Many Requests с заголовком Retry-After, указывающим, через сколько секунд лимит сбросится.
HTTP/1.1 429 Too Many Requests
Retry-After: 12
{
"error": "rate limit exceeded",
"code": "RATE_LIMIT_EXCEEDED"
}
Рекомендуем реализовать экспоненциальный backoff: при получении 429 подождите значение Retry-After, прежде чем повторить запрос. Не повторяйте запросы в tight loop — это только продлит время блокировки.
Идемпотентность
Все POST-запросы требуют заголовок Idempotency-Key. Это защита от дублирования: если запрос был отправлен, но ответ не получен (сетевой сбой, таймаут), повторная отправка с тем же ключом вернёт тот же результат без создания новой транзакции.
Как работает
- При первом запросе с ключом — выполняется операция, результат сохраняется на 24 часа
- При повторном запросе с тем же ключом — возвращается сохранённый результат, операция не выполняется повторно
- Ответ на повторный запрос содержит заголовок
X-Idempotency-Replayed: true
POST /v1/transactions Idempotency-Key: 550e8400-e29b-41d4-a716-446655440000 # Повторный запрос с тем же ключом — ответ идентичен первому: # X-Idempotency-Replayed: true
Важно: Idempotency-Key должен быть уникальным для каждого нового бизнес-действия. Используйте UUID v4. Не переиспользуйте ключи между разными транзакциями — иначе получите ответ от первой операции вместо новой.
Версионирование
Текущая версия API — v1. Все B2B-эндпоинты доступны по префиксу /v1/.
Политика совместимости
В рамках версии v1 мы гарантируем обратную совместимость: не удаляем существующие поля из ответов, не меняем типы данных и не изменяем семантику статусов. Добавление новых необязательных полей в ответы не считается breaking change.
При необходимости ввести несовместимые изменения — выпускается версия v2 по префиксу /v2/. Версия v1 при этом продолжает работать с периодом поддержки не менее 12 месяцев.
Публичные эндпоинты (GET /v1/rates, GET /v1/quote) доступны без авторизации — для встраивания виджетов на стороне провайдера.
Что скачать для интеграции
Готовые артефакты — копируйте и адаптируйте. Все самодостаточные, зависят только от стандартной библиотеки.
- openapi.yaml — машиночитаемый контракт нашего API (Swagger UI, Postman import, codegen)
- openapi-ru.yaml — то же на русском
- openapi-vasp.yaml — обратный контракт для VASP-операторов (DantePay и др.)
- twin-bridge.postman_collection.json — Postman-коллекция со всеми endpoints и авто-подписью запросов
- samples/ — примеры кода:
hmac-sign.{go,js,php}— подпись исходящего запроса к TBwebhook-receiver.{go,js,php}— приёмник и верификация входящего webhook
Алгоритмы подписи исходящих запросов и webhook'ов отличаются намеренно — см. samples/README.md.
Примеры запросов
Ниже — cURL-примеры для основных операций. Замените $API_KEY, $TIMESTAMP и $SIGNATURE своими значениями согласно алгоритму авторизации или используйте готовые sample'ы.
Получить текущие курсы
curl -X GET https://twinbridge.kg/v1/rates
Получить котировку
curl -X GET "https://twinbridge.kg/v1/quote?direction=ON_RAMP&fiat_amount=5000&fiat_currency=KGS&crypto_currency=USDT"
Создать транзакцию
curl -X POST https://twinbridge.kg/v1/transactions \
-H "Content-Type: application/json" \
-H "X-API-Key: $API_KEY" \
-H "X-Timestamp: $TIMESTAMP" \
-H "X-Signature: $SIGNATURE" \
-H "Idempotency-Key: 550e8400-e29b-41d4-a716-446655440000" \
-d '{
"direction": "ON_RAMP",
"fiat_amount": "5000.00",
"fiat_currency": "KGS",
"crypto_currency": "USDT",
"crypto_address": "TRX_ADDRESS_OF_CLIENT",
"flow": "QR",
"kyc_share_token": "sumsub_share_token_here"
}'
Получить статус транзакции
curl -X GET https://twinbridge.kg/v1/transactions/8f3d2a1b-4c5e-6f7a-8b9c-0d1e2f3a4b5c \ -H "X-API-Key: $API_KEY" \ -H "X-Timestamp: $TIMESTAMP" \ -H "X-Signature: $SIGNATURE"
Отменить транзакцию
curl -X POST https://twinbridge.kg/v1/transactions/8f3d2a1b-4c5e-6f7a-8b9c-0d1e2f3a4b5c/cancel \
-H "X-API-Key: $API_KEY" \
-H "X-Timestamp: $TIMESTAMP" \
-H "X-Signature: $SIGNATURE" \
-H "Idempotency-Key: 660f9511-f3ac-52e5-b827-557766551111" \
-H "Content-Type: application/json" \
-d '{}'
Шлите заголовок X-Sandbox: true на всех интеграционных запросах. На production-окружении установлен TB_REQUIRE_SANDBOX=true — без этого заголовка /v1/* вернёт 503 NOT_PRODUCTION_READY. Флаг снимем только после подключения реального DantePay-адаптера и получения legal opinion letter.
Если вы — VASP-оператор
Вы — лицензированный криптообменник Кыргызстана. У вас есть инфраструктура для исполнения сделок KGS/USDT через ELQR. Twin Bridge подключает вас к потоку международных провайдеров через единый стандартизированный интерфейс.
Мы онбордим hybrid VASP. VASP должен поддерживать обе реализованные фазы: Phase 1 custody-провайдеров и Phase 2 lead-gen провайдеров. Для этого контракт включает 7 endpoints: 5 базовых для quote/QR/payout/status/health и 2 Phase 2 endpoint'а — send-usdt и usdt-deposit-address. Актуальная спецификация — vasp-contract.md.
Ваша роль в системе: Twin Bridge получает заказ от провайдера, выбирает вас (по курсу, надёжности, ликвидности) через Rate Engine и передаёт команду на исполнение. Вы исполняете сделку — получаете реферальный доход.
ON-RAMP (KGS → USDT)
Клиент провайдера платит KGS через ELQR QR-код. Вы формируете QR через ELQR, фиксируете поступление KGS, отправляете USDT на крипто-адрес клиента.
OFF-RAMP (USDT → KGS)
Провайдер автоматически отправляет USDT на ваш депозитный адрес (TRC-20). Вы фиксируете поступление, выплачиваете KGS клиенту через ELQR на его телефон/реквизиты.
С чего начать (VASP-оператор)
Шаг 1. Свяжитесь с нами
Напишите на [email protected]. Мы проверим наличие лицензии ФСА, согласуем коммерческие условия (referral fee) и подпишем договор.
Шаг 2. Получите API-ключи и webhook-секрет
После подписания договора вы получаете два набора ключей:
- Sandbox API-ключ — для тестирования. Реальные деньги не двигаются.
- Production API-ключ — после успешного прохождения sandbox.
- Webhook-секрет — для верификации входящих запросов от Twin Bridge.
Шаг 3. Реализуйте интеграцию
Twin Bridge вызывает ваш API по стандартному интерфейсу. Подробности — в разделе Что нужно реализовать.
Шаг 4. Настройте входящий webhook-endpoint
Укажите URL вашего сервиса. Twin Bridge передаёт на него подписанные запросы от провайдера при создании транзакции, получении котировки и команды на исполнение. Проверяйте подпись перед обработкой.
Шаг 5. Протестируйте в Sandbox
Пройдите полный цикл в Sandbox: ON_RAMP и OFF_RAMP, успешное завершение, отмена по TTL, FAILED сценарий. Только после этого — Production.
Важно: Production-ключи активируются только после того, как вы успешно прошли все сценарии в Sandbox и мы подтвердили готовность с нашей стороны.
Что нужно реализовать (VASP-оператор)
Twin Bridge вызывает ваш сервис через стандартизированный интерфейс. Вам нужно реализовать следующие методы:
По актуальной модели VASP подключается как hybrid: умеет Phase 1 для custody-провайдеров и Phase 2 для lead-gen провайдеров. Канонический контракт — 7 endpoint'ов /vasp/v1/*: 5 базовых (quote, qr, payout, tx, health) плюс Phase 2 send-usdt и usdt-deposit-address, точная HMAC-подпись и webhooks. Полная спецификация: site/docs/vasp-contract.md.
GetQuote — получить котировку
Twin Bridge запрашивает актуальный курс перед созданием каждой транзакции. Rate Engine параллельно опрашивает всех подключённых VASP и выбирает лучший.
# Входящий запрос от Twin Bridge — POST /vasp/v1/quote
{
"pair": "KGS/USDT",
"amount": "5000.00",
"direction": "ON_RAMP", // или "OFF_RAMP"
"payment_method": "elqr" // опционально
}
# Ожидаемый ответ
{
"quote_id": "q_7f3d...",
"rate": "86.30", // курс KGS за 1 USDT
"fiat_amount": "5000.00",
"crypto_amount": "57.93",
"fee": "0",
"expires_at": "2026-04-16T10:25:00Z" // max 5 мин
}
GenerateQR — создать QR для ON_RAMP
Twin Bridge запрашивает QR-ссылку ELQR, которую провайдер покажет клиенту. Клиент сканирует и оплачивает KGS через ELQR — деньги приходят на ваш счёт.
# Входящий запрос от Twin Bridge — POST /vasp/v1/qr
{
"tx_id": "8f3d2a1b-...",
"provider_slug": "guardarian", // counterparty-провайдер (attribution)
"amount": "5000.00",
"currency": "KGS",
"kyc_share_token": "sumsub_token_here" // passthrough, не расшифровывайте
}
# Ожидаемый ответ
{
"external_tx_id": "vasp-tx-abc", // ваш ID — по нему матчатся все webhooks
"data": "00020101...", // данные QR (ELQR формат)
"image_url": "https://elqr.kg/pay/...",
"expires_at": "2026-04-16T10:25:00Z"
}
ExecuteKGSPayout (OFF_RAMP) — выплатить KGS клиенту
Провайдер уже дебетовал USDT у клиента в своей системе; Twin Bridge командует выплатить KGS на реквизиты клиента через ELQR.
# Входящий запрос от Twin Bridge — POST /vasp/v1/payout
# HTTP-заголовок Idempotency-Key = idempotency_key — дедуплицируйте, НЕ платите дважды
{
"tx_id": "8f3d2a1b-...",
"provider_slug": "guardarian",
"idempotency_key": "550e8400-e29b-41d4-a716-446655440000",
"kgs_amount": "4996.00", // KGS к выплате (за вычетом комиссии)
"recipient_wallet": "1234567890", // ELQR-кошелёк/счёт ...
"recipient_phone": "996700123456" // ... либо телефон (одно из двух)
}
# Ожидаемый ответ (async ACCEPTED либо sync EXECUTED)
{ "external_tx_id": "vasp-payout-xyz", "status": "EXECUTED" }
Все входящие запросы от Twin Bridge подписаны через HMAC-SHA256. Заголовки: X-Signature, X-Timestamp. Проверяйте подпись до обработки — аналогично тому, как провайдер проверяет ваши webhooks.
Webhooks от VASP → Twin Bridge
После подтверждения событий на вашей стороне — вы отправляете подписанный webhook в Twin Bridge. Это единственный способ обновить статус транзакции.
Какие события отправлять
- PAID — клиент оплатил KGS через ELQR (ON_RAMP) или вы получили USDT (OFF_RAMP)
- COMPLETED — USDT отправлен клиенту (ON_RAMP) или KGS выплачен клиенту (OFF_RAMP)
- FAILED — исполнение не удалось (технический сбой, нет ликвидности)
Endpoint Twin Bridge для webhooks от вас
POST https://twinbridge.kg/internal/webhooks/{your_vasp_slug}
X-Signature: HMAC_SHA256(secret, "{timestamp}\n{METHOD}\n{path}\nsha256:{body_hash}")
X-Timestamp: 1713260625
{
"tx_id": "8f3d2a1b-...",
"status": "PAID", // или "COMPLETED", "FAILED"
"event": "payment.paid",
"timestamp": "2026-04-16T10:22:10Z"
}
Алгоритм подписи
Подпись формируется так же, как у провайдеров: HMAC_SHA256(webhook_secret, timestamp + "." + body). Секрет выдаётся при подключении. Timestamp не должен отличаться от серверного времени более чем на 300 секунд.
Гарантия доставки
Twin Bridge принимает ваш webhook и подтверждает приём кодом 200 OK. Если ваш webhook не дошёл (ошибка сети), повторите отправку с тем же tx_id — Twin Bridge идемпотентен и не создаст дубликат.
Критично: Если ExecuteKGSPayout() принял команду (вернул ACCEPTED), но финальный ответ не вернул — НЕ вызывайте повторно. Отправьте webhook с фактическим статусом когда он определится. Twin Bridge поддерживает внутреннее состояние UNKNOWN и polling через GET /vasp/v1/tx/:id — повторный вызов /payout создаст дубль транзакции.
KYC и комплаенс
Для self_api и we_pull KYC проводит провайдер, а Twin Bridge передаёт kyc_share_token или зашифрованные PII. Для widget KYC проходит через TB-managed Sumsub-ready поток.
Вариант A. KYC passthrough (для self_api / we_pull)
Если провайдер уже верифицировал клиента (через Sumsub или аналогичный сервис), он передаёт kyc_share_token при создании транзакции. Twin Bridge передаёт этот токен VASP-оператору — тот проверяет его напрямую у KYC-провайдера.
Twin Bridge не видит содержимое токена и не расшифровывает его. Только транспортирует. Альтернативно, провайдер может передать 30+ PII-полей (имя, паспорт, адрес, документы) прямо в payload POST /v1/transactions — TB шифрует их AES-256-GCM на 24 часа и передаёт VASP'у.
Вариант B. TB-managed KYC (для widget)
Если провайдер использует наш виджет (например, e-commerce без своего KYC), верификация клиента проводится через наш Sumsub-аккаунт. PII шифруется и хранится у TB в таблице customers. При создании транзакции виджет связывает её с customer_id, а в момент GenerateQR/Payout мы передаём данные VASP'у через тот же интерфейс vasp.KYCData.
В этом режиме TB становится data controller для клиентских PII. Поток уже Sumsub-ready: при заданном SUMSUB_APP_TOKEN включается Sumsub WebSDK, а без ключа используется sandbox-форма для тестирования интеграции. Для production также нужны privacy policy и обновлённое legal opinion.
- Twin Bridge не является VASP и не требует финансовой лицензии
- KYC/AML — ответственность провайдера (при passthrough) или TB (при widget-режиме)
- PII шифруются AES-256-GCM, ключ хранится отдельно от БД
- Все VASP-операторы в экосистеме лицензированы ФСА КР
Тестовая среда (Sandbox)
Sandbox позволяет протестировать полный поток транзакции без реальных денег. Все вызовы к VASP-операторам и провайдерам перехватываются Mock-адаптерами.
Как включить Sandbox
Добавьте заголовок X-Sandbox: true к любому запросу — и он будет обработан через Mock-адаптеры. Используйте Sandbox API-ключи (они отличаются от Production).
Симулятор
Откройте Симулятор — интерактивный дашборд, который демонстрирует все тестовые сценарии: успешный ON_RAMP, отмену, возврат, таймаут и другие.
Рекомендуем: перед выходом в Production пройдите все 10 тестовых сценариев в Симуляторе. Это займёт 15–20 минут и гарантирует, что ваша интеграция готова к реальным транзакциям.
Вопросы и ответы
Готовы к интеграции?
Начните с Симулятора или сразу обратитесь к нам для получения API-ключей.