Платёжный API v2
Создайте платёж на своём сервере, отправьте покупателя на страницу оплаты и отметьте заказ оплаченным, когда Coino Live подтвердит платёж в сети.
Быстрый старт
1. Создайте API-ключ для своего шлюза в панели, в разделе «Разработчикам». 2. Создайте платёж на сумму заказа. 3. Перенаправьте покупателя на полученный checkout_url. 4. Когда придёт вебхук (или покупатель вернётся), снова прочитайте платёж и отправляйте заказ, когда статус станет "paid".
curl https://coino.live/api/v2/payments \
-H "Authorization: Bearer ck_live_..." \
-H "Idempotency-Key: order-1001" \
-H "Content-Type: application/json" \
-d '{"amount": "25.00", "currency": "EUR", "order_id": "1001",
"success_url": "https://shop.example/thanks",
"notify_url": "https://shop.example/coino-webhook"}'
Аутентификация
Передавайте секретный ключ в заголовке Authorization каждого запроса. Ключ принадлежит одному шлюзу и видит только его платежи. Храните ключ на сервере: никогда не размещайте его в браузере, приложении или публичном репозитории. Если ключ утёк, отзовите его в панели и создайте новый.
Authorization: Bearer ck_live_...
Базовый URL: https://coino.live/api/v2
Все суммы — десятичные строки (не числа), всё время — ISO 8601 в UTC, каждый ответ — JSON с результатом в "data".
Создать платёж
Цены могут быть в USD или в любой валюте из GET /currencies; другие валюты пересчитываются в USD по текущему курсу при создании платежа. Покупатель выбирает монету и сеть на странице оплаты.
| Поле | Описание |
|---|---|
amount | Обязательно. Не более 2 знаков после запятой, например "25.00". Минимум 1 USD (или эквивалент). |
currency | Трёхбуквенный код; если не указан — USD. |
order_id | Номер вашего заказа, до 128 символов. Виден вам, по нему можно искать через GET /payments. |
description | Показывается покупателю на странице оплаты, до 500 символов. |
customer_email | Необязательный email покупателя. |
success_url, cancel_url | Куда страница оплаты возвращает покупателя. Возврат на success_url не доказывает оплату. |
notify_url | Адрес вебхука для этого платежа (только https). Заменяет адрес вебхука из настроек шлюза. |
metadata | Ваши собственные данные ключ/значение, до 20 ключей и 4 КБ. Возвращаются без изменений. |
asset | Необязательный код монеты из GET /assets (например "usdt-tron"), чтобы пропустить выбор монеты. |
expires_in | Сколько минут у покупателя на оплату, от 15 до 10080. По умолчанию 1440 (сутки). |
Отправляйте уникальный ключ для каждой попытки заказа (до 128 букв, цифр и символов -_:.). Повторный запрос с тем же ключом возвращает тот же платёж, а не создаёт второй, поэтому повтор после таймаута или двойного клика безопасен. Используйте новый ключ, если сумма изменилась или прошлый платёж истёк.
Ответ (201 при создании, 200 для повторного ключа) — объект платежа ниже.
Объект платежа
{
"data": {
"id": "01m62ewd502p9774d6trd7rhr7",
"status": "paid",
"amount": "22.32",
"currency": "USD",
"requested_amount": "20.00",
"requested_currency": "EUR",
"exchange_rate_usd": "1.115926958947",
"received_usd": "22.32",
"remaining_usd": "0.00",
"order_id": "943",
"description": "Order #943",
"customer_email": "[email protected]",
"metadata": {"cart": "abc"},
"checkout_url": "https://coino.live/pay/01m62ewd502p9774d6trd7rhr7",
"success_url": "https://shop.example/thanks",
"cancel_url": "https://shop.example/cart",
"asset": null,
"quote": {
"asset": "usdc-ethereum", "symbol": "USDC", "network": "Ethereum",
"address": "0x8e2e…61bc", "amount": "22.330545",
"network_fee": "0.000001", "rate_usd": "0.9995", "expires_at": "…"
},
"deposits": [{
"asset": "usdc-ethereum", "symbol": "USDC", "network": "Ethereum",
"tx_hash": "0xf13d…1439", "explorer_url": "https://etherscan.io/tx/0xf13d…1439",
"amount": "22.330545", "network_fee": "0.000001",
"platform_fee": "0.223305", "net": "22.107239",
"usd_value": "22.32", "credited_at": "…"
}],
"expires_at": "…", "paid_at": "…", "created_at": "…"
}
}
amount и currency — сколько покупатель платит в USD; requested_amount и requested_currency — что запросили вы. quote — монета, адрес и сумма, которые сейчас видит покупатель; deposits перечисляет все полученные транзакции с удержанной комиссией и суммой, зачисленной на ваш баланс (net).
| Статус | Значение | Что делать |
|---|---|---|
open | Ожидается оплата покупателем. | Пока ничего. |
confirming | Транзакция замечена и ждёт подтверждений сети. | Покажите «платёж получен, подтверждается». Пока не отправляйте. |
partially_paid | Пришло меньше суммы. Страница оплаты просит доплатить остаток (remaining_usd). | Подождите: покупатель ещё может доплатить. |
paid | Полностью оплачен и подтверждён. Окончательно. | Отметьте заказ оплаченным и отправьте. |
expired | Время вышло. Если received_usd больше нуля, эта часть на вашем балансе. | Отмените заказ или урегулируйте оплаченную часть с покупателем. |
cancelled | Отменён вами до поступления оплаты. Окончательно. | Ничего. |
Платёж, очень близкий к сумме, считается оплаченным, чтобы округление кошельков не оставляло заказы открытыми.
Чтение и отмена платежей
Читайте платёж заново всякий раз, когда нужно его текущее состояние: после вебхука, при возврате покупателя или из задачи по расписанию. Неизвестные ID и платежи других шлюзов отвечают 404.
GET · /payments?status=paid&order_id=1001&cursor=…Список ваших платежей, сначала новые, по 50 на страницу. Оба фильтра необязательны. meta.next_cursor и meta.prev_cursor листают результаты.
POST · /payments/{id}/cancelОтменяет открытый платёж, по которому ничего не поступило, например когда покупатель очистил корзину. Платежи с поступлением отменить нельзя (422).
Вебхуки
Coino Live отправляет POST на notify_url (или на адрес вебхука шлюза) при каждой смене статуса платежа. Вебхуки отправляются, только если у шлюза есть секрет подписи: создайте его в настройках шлюза.
POST /coino-webhook
X-Coino-Event: payment.paid
X-Coino-Delivery: 01m62f23xhkz39ahqv4h64ttfk
X-Coino-Signature: t=1761696953,v1=5f2c…
{"id": "01m62f23xhkz39ahqv4h64ttfk", "event": "payment.paid",
"created_at": "…", "data": { …the payment object… }}
| Событие | Когда |
|---|---|
payment.confirming, payment.partially_paid, payment.paid, payment.expired, payment.cancelled | Платёж перешёл в этот статус. |
custody.deposit.detected, custody.deposit.credited | Поступление пользователя кастоди замечено, затем зачислено. |
withdrawal.<status> | Статус API-вывода изменился. |
Проверяйте подпись: вычислите HMAC-SHA256 от "<t>.<raw body>" с вашим секретом подписи, сравните с v1 за постоянное время и отклоняйте метки времени старше пяти минут.
// PHP
$header = $_SERVER['HTTP_X_COINO_SIGNATURE'] ?? '';
$body = file_get_contents('php://input');
parse_str(str_replace(',', '&', $header), $sig);
$ok = isset($sig['t'], $sig['v1'])
&& abs(time() - (int) $sig['t']) <= 300
&& hash_equals(hash_hmac('sha256', $sig['t'] . '.' . $body, $secret), $sig['v1']);
// Node.js
const [t, v1] = header.split(',').map(p => p.split('=')[1]);
const expected = crypto.createHmac('sha256', secret).update(`${t}.${rawBody}`).digest('hex');
const ok = Math.abs(Date.now() / 1000 - t) <= 300
&& crypto.timingSafeEqual(Buffer.from(expected), Buffer.from(v1));
# Python
t, v1 = (p.split('=', 1)[1] for p in header.split(','))
expected = hmac.new(secret.encode(), f'{t}.{raw_body}'.encode(), 'sha256').hexdigest()
ok = abs(time.time() - int(t)) <= 300 and hmac.compare_digest(expected, v1)
Прежде чем отметить заказ оплаченным, прочитайте платёж через GET /payments/{id} и проверьте статус, сумму и ваш order_id. Ответьте любым статусом 2xx в течение 10 секунд. Неудачные доставки повторяются через 1, 5, 30, 120, 360, 720 и 1440 минут; редиректы не выполняются. Одно событие может прийти несколько раз, поэтому обрабатывайте его идемпотентно.
Валюты, монеты и балансы
GET · /currenciesВалюты, в которых можно выставить платёж, с их стоимостью в USD: {"code": "EUR", "usd_per_unit": "1.09"}. Скрывайте криптооплату, если валюты вашего магазина нет в списке.
GET · /assetsМонеты, которыми покупатели могут платить сейчас: code (например "usdt-tron"), symbol, name, network, decimals и price_usd.
GET · /balancesБаланс вашего аккаунта по каждой монете за вычетом комиссий: asset, symbol, network, balance и usd_value (null, пока нет курса).
Кастоди-аккаунты
Для приложений с аккаунтами пользователей: каждый пользователь получает постоянные адреса для пополнения, а поступления зачисляются на его баланс в вашем шлюзе.
| Запрос | Описание |
|---|---|
POST /custody/users | Создать пользователя (external_id обязателен; name, email, metadata необязательны). Тот же external_id возвращает существующего пользователя. |
GET /custody/users?external_id=… | Список пользователей, по 50 на страницу. |
GET /custody/users/{id} | Адреса (с монетами, которые принимает каждый) и балансы. |
GET /custody/users/{id}/deposits | Зачисленные поступления, сначала новые, с next_cursor. |
POST /custody/users/{id}/transfers | Переводит баланс пользователя в одном активе на ваш основной баланс (весь, если amount не указан). Необязательный reference позволяет безопасно повторить запрос. |
Вывод средств
Выплата с вашего баланса на адрес: asset, amount и address обязательны; custody_user списывает средства с баланса кастодиального пользователя; reference (уникальный в пределах шлюза) позволяет безопасно повторить запрос. По умолчанию выключено: включите выводы через API в настройках шлюза, где также задаются дневной лимит в USD и IP-адреса серверов, которым разрешён вызов (оба эндпоинта отвечают только этим IP). Reference, повторно использованный для другого вывода, отклоняется с кодом 409. Крупные выводы могут ожидать проверки.
GET · /withdrawals/{id}Статус: pending_review, approved, processing, broadcast, completed, rejected (см. error), cancelled или failed. tx_hash появляется после отправки.
Ошибки и лимиты
| HTTP | Значение |
|---|---|
| 401 | Ключ отсутствует, неверен или отозван, либо шлюз приостановлен. |
| 404 | Не найдено (или принадлежит другому шлюзу). |
| 422 | Запрос отклонён: "message" объясняет причину, "errors" называет поля. |
| 429 | Слишком много запросов: 120 в минуту на ключ. Подождите и повторите. |
| 5xx | Временная проблема на нашей стороне. Повторите с тем же Idempotency-Key. |
{"message": "The minimum payment is 1.00 USD."}
{"message": "amount must be a decimal string with at most 2 decimals, e.g. \"25.00\".",
"errors": {"amount": ["amount must be a decimal string with at most 2 decimals, e.g. \"25.00\"."]}}
Библиотеки для разработчиков
Официальные библиотеки для этого API, без зависимостей. Они проверяют подписи вебхуков, выдают понятную ошибку при каждом отказе и повторяют запрос после сетевой ошибки, только когда повтор безопасен.
| Язык | Версия | Требования | |
|---|---|---|---|
| PHP | 1.0.0 | PHP 8.1+ with cURL | Скачать |
| Node.js | 1.0.0 | Node.js 18+, TypeScript types included | Скачать |
| Python | 1.0.0 | Python 3.8+ | Скачать |
// PHP
$coino = new \CoinoLive\Client('ck_live_...');
$payment = $coino->payments->create(['amount' => '25.00', 'currency' => 'EUR', 'order_id' => '1001']);
// Node.js
const coino = new CoinoLive('ck_live_...');
const payment = await coino.payments.create({ amount: '25.00', currency: 'EUR', order_id: '1001' });
# Python
coino = coinolive.Client("ck_live_...")
payment = coino.payments.create(amount="25.00", currency="EUR", order_id="1001")
В каждой загрузке есть README со всеми вызовами, обработкой вебхуков и классами ошибок.
Интеграции с платформами
Готовые плагины на основе этого API. Установите плагин, вставьте API-ключ и включите его: заказы обновляются автоматически, а каждый плагин показывает ваш баланс и платежи в своей админке.
| Платформа | Версия | Требования | |
|---|---|---|---|
| WooCommerce | 1.1.0 | WordPress 6.2+, WooCommerce 7.6+, PHP 7.4+ | Скачать |
| WHMCS | 1.0.0 | WHMCS 8.0+, PHP 7.4+ | Скачать |
| OpenCart 4 | 1.0.0 | OpenCart 4.0.2+, PHP 8.0+ | Скачать |
| Shopware 6 | 1.0.0 | Shopware 6.6.5+ or 6.7, PHP 8.2+ | Скачать |
| PrestaShop | 1.0.0 | PrestaShop 8.0+ or 9, PHP 7.2+ | Скачать |
| Easy Digital Downloads | 1.0.0 | Easy Digital Downloads 3, WordPress 6.7+, PHP 8.0+ | Скачать |
| GiveWP | 1.0.0 | GiveWP 3+, WordPress 6.6+, PHP 7.4+ | Скачать |
Другие платформы: используйте API напрямую, как описано выше.