Convert API
Конвертация криптовалют напрямую из баланса мерчанта — живая котировка и исполнение по рыночной цене.
Convert API позволяет обменивать валюты внутри баланса вашего мерчанта по текущей рыночной цене — тот же движок, что работает во вкладке Обмен в личном кабинете, теперь доступный из вашего бэкенда.
Ручки Convert подписываются вашим обычным API-ключом — тем же, что используется для запросов Payment API, а не ключом Payout. Исполнение конверта сразу списывает и зачисляет баланс мерчанта, поэтому относитесь к этому ключу с той же осторожностью, что и к любому денежному credential.
Получить цену конверта
Возвращает индикативную котировку конверта по текущей рыночной цене — эффективный курс и итоговые суммы. Ничего не списывается и не резервируется; вызывайте сколько угодно раз перед исполнением.
/v1/convert/priceПараметры котировки
| Поле | Тип | Обязательно | Описание | Значение |
|---|---|---|---|---|
from_currency | string | да | Валюта, из которой конвертируем | |
to_currency | string | да | Валюта, в которую конвертируем. Должна отличаться от from_currency | |
amount | decimal | да | Сумма конвертации, больше 0 | |
amount_type | string | да | К какой стороне относится amount |
amount_type=from — потратить ровно amount в from_currency. amount_type=to — получить ровно amount в to_currency.
🟢 200 OK · application/json
{
"state": 0,
"result": {
"success": true,
"from_currency": "BTC",
"to_currency": "USDT",
"amount_type": "from",
"from_amount": "0.01000000",
"to_amount": "947.86690000",
"effective_rate": "94786.69000000",
"from_amount_usd": "947.87",
"to_amount_usd": "947.87"
}
}Поля ответа
| Поле | Тип | Описание |
|---|---|---|
success | boolean | Успешно ли рассчитана котировка |
from_currency | string | Исходная валюта |
to_currency | string | Целевая валюта |
amount_type | string | Повторяет amount_type из запроса |
from_amount | string | Сумма, которая будет списана в from_currency |
to_amount | string | Сумма, которая будет зачислена в to_currency |
effective_rate | string | Курс, применённый к этой котировке — 1 единица from_currency в to_currency (уже включает ценообразование платформы) |
from_amount_usd | string | null | USD-эквивалент from_amount |
to_amount_usd | string | null | USD-эквивалент to_amount |
- Котировка только индикативная — рыночная цена может измениться между запросом котировки и исполнением.
- Ничего не списывается и не резервируется этим вызовом.
curl -X POST https://api.2328.io/api/v1/convert/price \
-H "Content-Type: application/json" \
-H "User-Agent: MyShop/1.0 (+https://myshop.example)" \
-H "project: YOUR_PROJECT_UUID" \
-H "sign: YOUR_HMAC_SIGNATURE"Исполнить конверт
Исполняет конверт по текущей рыночной цене и обновляет баланс мерчанта. Отдельного шага «подтвердить котировку» нет — вызывайте эту ручку напрямую с той суммой, которую хотите конвертировать.
/v1/convertИдемпотентность. Повтор ровно того же запроса (те же from_currency, to_currency, amount, amount_type) в течение примерно минуты после первого вызова вернёт уже существующий конверт вместо создания второго. После истечения этого окна идентичный запрос будет воспринят как новый конверт — не ретраьте вслепую при таймауте, сначала проверьте результат предыдущего вызова.
Эта ручка ограничена 10 запросами в минуту на вызывающего — жёстче общего лимита API, — потому что каждый вызов двигает реальный баланс.
Параметры конверта
| Поле | Тип | Обязательно | Описание | Значение |
|---|---|---|---|---|
from_currency | string | да | Валюта, из которой конвертируем | |
to_currency | string | да | Валюта, в которую конвертируем. Должна отличаться от from_currency | |
amount | decimal | да | Сумма конвертации, больше 0 | |
amount_type | string | да | К какой стороне относится amount |
🟢 200 OK · application/json
{
"state": 0,
"result": {
"id": 12345,
"type": "manual",
"status": "completed",
"from_currency": "BTC",
"to_currency": "USDT",
"from_amount": "0.01000000",
"requested_from_amount": "0.01000000",
"refund_amount": null,
"to_amount": "947.86690000",
"exchange_rate": "94786.69000000",
"fee_amount": "0.00000000",
"from_amount_usd": "947.87",
"to_amount_usd": "947.87",
"processed_at": "2026-01-20T15:30:24Z",
"created_at": "2026-01-20T15:30:22Z"
}
}Поля ответа
| Поле | Тип | Описание |
|---|---|---|
id | int | ID конверт-ордера, присвоенный системой |
type | string | Всегда manual для этого API |
status | string | Текущий статус (см. «Статусы конверта» ниже) |
from_currency | string | Исходная валюта |
to_currency | string | Целевая валюта |
from_amount | string | Списанная сумма в from_currency |
requested_from_amount | string | null | Запрошенная вами исходная сумма при amount_type = from. null при amount_type = to |
refund_amount | string | null | Часть предварительно списанной суммы, возвращённая вам после частичного исполнения. null, если ордер исполнился полностью |
to_amount | string | Зачисленная сумма в to_currency |
exchange_rate | string | Курс, фактически применённый к этой конвертации — 1 единица from_currency в to_currency (уже включает ценообразование платформы) |
fee_amount | string | Комиссия платформы по этой конвертации, в from_currency или to_currency в зависимости от направления сделки. Уже учтена в exchange_rate — показана для прозрачности |
from_amount_usd | string | null | USD-эквивалент from_amount |
to_amount_usd | string | null | USD-эквивалент to_amount |
processed_at | string (ISO 8601) | null | Когда конвертация завершила исполнение. null, пока она в обработке |
created_at | string (ISO 8601) | Когда был создан конверт-ордер |
Статусы конверта
| Статус | Описание |
|---|---|
pending | Создан, ещё не отправлен на биржу |
processing | Баланс заблокирован, ордер выставлен на биржу |
completed | Полностью исполнен — to_amount зачислен на ваш баланс |
failed | Не удалось исполнить — предварительно списанная сумма возвращена автоматически |
partially_completed | Только для валютных пар без прямого рынка (маршрутизация через промежуточную валюту): первый хоп исполнился, второй — нет. Вам зачислена промежуточная валюта вместо to_currency — сконвертируйте её ещё раз, чтобы достичь исходной цели |
curl -X POST https://api.2328.io/api/v1/convert \
-H "Content-Type: application/json" \
-H "User-Agent: MyShop/1.0 (+https://myshop.example)" \
-H "project: YOUR_PROJECT_UUID" \
-H "sign: YOUR_HMAC_SIGNATURE"Ошибки
При ошибке ответ содержит state: 1 и error_code — общие для /v1/convert/price и /v1/convert:
🔴 422 / 400 · application/json
{
"state": 1,
"error_code": "amount_too_small",
"errors": {
"amount": "Amount is too small for this conversion. Please increase the amount and try again."
}
}error_code | HTTP-статус | Описание |
|---|---|---|
validation_failed | 422 | Неверные или отсутствующие параметры, либо отказ по бизнес-правилу (например, недостаточно баланса) — детали в поле errors |
amount_too_small | 422 | amount меньше минимального торгуемого размера для этой валютной пары |
convert_unavailable | 400 | Конвертацию не удалось исполнить прямо сейчас (недоступны рыночные данные или нет маршрута между двумя валютами) — повторите чуть позже |
internal_error | 400 | Непредвиденная ошибка сервера при обработке запроса |
Автоматическая конвертация входящих платежей
Автоконвертация — настройка проекта для входящих платежей и пополнений статических кошельков. Она задаётся в панели управления мерчанта, а не дополнительными полями запроса /v1/payment. Каждое правило связывает одну или несколько исходных валют с целевой валютой.
После успешной конвертации данные платежа и webhook-уведомления мерчанта могут содержать:
{
"payment_amount": "0.14800000",
"merchant_amount": "0.146520000000000000",
"payer_currency": "XMR",
"convert": {
"to_currency": "USDT",
"commission": "0.09000000",
"rate": "323.21000000",
"amount": "47.262015740000000000"
}
}Эти суммы намеренно относятся к разным этапам обработки:
payment_amount— сумма, обнаруженная в блокчейне, в исходной валюте платежа;merchant_amount— чистая сумма мерчанта в исходной валюте до конвертации;convert.amount— сумма, зачисленная в валютеconvert.to_currency;convert.rateиconvert.commission— фактический результат выполненной конвертации, а не исходные данные для локального пересчёта.
Отсутствие convert — допустимый результат: конвертация могла ещё не завершиться, не быть настроена для этой исходной валюты либо завершиться зачислением в исходной валюте. Не рассчитывайте целевую сумму самостоятельно по /exchange-rates или публичному рыночному курсу.
Сбой автоконвертации и резервный сценарий
Конвертация выполняется после получения платежа в блокчейне. Недоступность рынка, минимальный размер ордера, ограничения точности, тайм-аут биржи или недостаточная исполнимая ликвидность могут задержать конвертацию либо сделать её невозможной.
- Депозиты ниже глобального или проектного минимума не проходят конвертацию и зачисляются в исходной валюте.
- После временного сбоя система может повторить попытку асинхронно.
- Крупные или неликвидные депозиты после исчерпания попыток могут быть зачислены в исходной валюте.
- Поэтому платёж может быть корректно получен, даже если конвертация в целевую валюту не состоялась.
Сначала сохраните подтверждённый платёж, затем определите фактически зачисленную валюту по данным платежа, необязательному блоку convert и балансам мерчанта. Не задерживайте обработку подтверждающего webhook из-за ожидания собственной аналитики или уведомлений.
Приёмочные тесты автоконвертации
Как минимум проверьте: успешную прямую конвертацию; конвертацию через промежуточную валюту или несколько переходов; сумму ниже минимальной; повтор после временного сбоя; зачисление в исходной валюте; недоплату; переплату; дубликат webhook; отсутствие convert; сверку после неоднозначного тайм-аута.
Нестандартные ситуации при ручной конвертации
/v1/convert/priceвозвращает ориентировочный предварительный расчёт; движение рынка может изменить фактический результат исполнения.amount_type: fromфиксирует сумму исходной валюты, аamount_type: toзапрашивает сумму целевой валюты. Не меняйте это значение между показом экрана подтверждения и отправкой запроса.- Если для пары нет прямого рынка, обмен может пройти через промежуточную валюту. Статус
partially_completedозначает, что завершён только один этап и средства находятся в промежуточной валюте. - Если запрос завершился тайм-аутом, сначала выполните сверку и только затем повторяйте операцию: рыночный ордер мог исполниться, даже если HTTP-ответ потерян.
- Статус
failedтребует сверки и не даёт права самостоятельно проводить компенсирующую запись по локальному балансу; учёт списания и возврата ведёт платформа.