CryptoPayIn
Документация для разработчиков

Создавайте платежи, которые рассчитываются в блокчейне.

Всё необходимое, чтобы создать платёж, отправить клиента на хостинг-чекаут, отслеживать подтверждения и обрабатывать подписанные webhooks в продакшене.

Базовый URL APIВерсия 1
https://cryptopayin.com/v1
ПротоколREST / JSON
АутентификацияBearer-секрет
РежимТолько продакшен
Введение

Один API, единый хостинг-процесс

CryptoPayIn рассчитывает стоимость заказа в выбранной вами валюте отображения, фиксирует проверенные снапшоты курсов фиат/USD и крипто/USD, выделяет отдельный адрес для депозита и отслеживает поступление платежа через собственные блокчейн-ноды. Внутренний учёт, комиссии и балансы всегда ведутся в USD. Ваш бэкенд сразу получает URL чекаута, а затем — подписанные события жизненного цикла.

Базовый URL/v1
Суммы в фиатеМинимальные единицы ISO
Значения в криптоДесятичные строки
Срок действия по умолчанию30 минут
!

Это боевой API. Здесь нет тестового (sandbox) префикса. Каждое успешное создание выделяет реальный адрес в блокчейне. Для сквозных тестов используйте небольшую сумму в поддерживаемой валюте и храните секретные ключи только на своём сервере.

Как устроена интеграция

1Создайте ключ

Сгенерируйте секрет один раз в Кабинет -> Разработчики.

2Создайте платёж

Отправьте POST-запрос с валютой заказа, суммой и выбранным активом.

3Откройте чекаут

Перенаправьте клиента на полученный хостинг-URL.

4Обработайте событие

Проверьте HMAC и обновите заказ идемпотентно.

Начало работы

Создайте первый платёж

Сгенерируйте ключ API в кабинете мерчанта, сохраните секрет в переменной окружения, а затем создайте платёж со своего бэкенда. В примере используется ETH — его можно протестировать без выбора сети токена.

curl --request POST https://cryptopayin.com/v1/payments \
  --header "Authorization: Bearer $CPI_SECRET_KEY" \
  --header "Content-Type: application/json" \
  --header "Idempotency-Key: order_1042" \
  --data '{
    "amount": 49.99,
    "currency": "USD",
    "asset": "ETH",
    "order_ref": "order_1042",
    "redirect_url": "https://shop.example/orders/1042/paid"
  }'

Используйте ответ

Сохраните id платежа рядом с вашим заказом, а затем перенаправьте клиента на checkout_url. Не вычисляйте сумму в криптовалюте или адрес депозита самостоятельно.

{
  "id": "P-9F27C1E4KD",
  "object": "payment",
  "status": "created",
  "amount": 49.99,
  "amount_decimal": "49.99",
  "amount_minor": 4999,
  "currency": "USD",
  "currency_minor_units": 2,
  "amount_usd": 49.99,
  "amount_usd_cents": 4999,
  "fx_rate_usd": "1.000000000000",
  "fx_source": "fixed:USD",
  "fx_observed_at": "2026-07-17T13:00:00+00:00",
  "fx_discrepancy_bps": 0,
  "asset": "ETH",
  "network": "mainnet",
  "crypto_amount": "0.01388612",
  "crypto_received": "0",
  "deposit_address": "0x71b8c3d4700000000000000000000000000084e2",
  "exchange_rate": "3600.00000000",
  "exchange_rate_currency": "USD",
  "exchange_rate_source": "median:cb,cg,cl",
  "exchange_rate_source_count": 3,
  "exchange_rate_observed_at": "2026-07-17T13:00:00+00:00",
  "exchange_rate_discrepancy_bps": 12,
  "confirmations": 0,
  "confirmations_required": 12,
  "order_ref": "order_1042",
  "checkout_url": "https://cryptopayin.com/i/P-9F27C1E4KD",
  "expires_at": "2026-07-17T13:30:00+00:00",
  "created_at": "2026-07-17T13:00:00+00:00",
  "completed_at": null
}
Учётные данные

Аутентификация

Каждый запрос к API использует секретный ключ в HTTP-заголовке Bearer. Секретные ключи начинаются с csk_live_. Сопутствующее значение cpk_live_ — это публичный идентификатор для вашего кабинета, его нельзя использовать как учётные данные Bearer.

AUTHAuthorization: Bearer csk_live_...Каждая точка входа
Показывается один раз

Исходный секрет возвращается только при создании ключа. CryptoPayIn хранит хеш пароля и индексированный SHA-256-отпечаток для поиска, но никогда — секрет в открытом виде.

Независимые ключи

Создавайте отдельные ключи для каждого приложения или окружения и отзывайте их независимо друг от друга. На аккаунт допускается до 50 активных ключей.

Только на сервере

Никогда не помещайте значение csk_live_ в клиентский JavaScript, в мобильное приложение, в публичный репозиторий или на страницу чекаута.

Область webhook

Точка входа webhook может охватывать весь аккаунт или быть привязана к одному ключу API — это изолирует интеграции друг от друга.

i

Отсутствующий, некорректный, отозванный или неизвестный секрет возвращает 401 unauthorized. Приостановленный или закрытый аккаунт мерчанта отклоняется так же. Действительный ключ, использованный за пределами предоставленных прав доступа, возвращает 403 insufficient_scope.

Безопасные повторы

Идемпотентность

При каждом создании платежа отправляйте уникальный Idempotency-Key. Если соединение обрывается после отправки, повторите запрос с идентичным JSON и тем же ключом: CryptoPayIn вернёт исходный платёж вместо выделения нового адреса.

СлучайРезультатHTTP
Первое использованиеСоздаёт и возвращает новый платёж.201
Тот же ключ + тот же JSONВозвращает существующий платёж с Idempotent-Replayed: true.200
Тот же ключ + другой JSONОтклоняет запрос как idempotency_conflict.409

Ключи идемпотентности привязаны к учётным данным API и могут содержать от 1 до 128 букв, цифр, точек, подчёркиваний, двоеточий или дефисов. Хороший выбор — постоянный UUID заказа. Тот же механизм защищает и вывод средств, поэтому повторная попытка вывода никогда не переместит средства дважды.

REST API

Справочник API

API охватывает платежи, платёжные ссылки, магазины, товары, балансы и вывод средств. Ответы возвращаются в формате UTF-8 JSON поверх HTTPS; любое создание или обновление требует Content-Type: application/json. Операции изменения данных контролируются правами доступа вызывающего ключа. CORS для браузера намеренно не поддерживается: вызовы должны выполняться с вашего бэкенда.

GET/v1/assetsСписок доступных активов
GET/v1/currenciesСписок фиатных валют отображения
POST/v1/paymentsСоздание платежа
GET/v1/paymentsСписок и фильтрация платежей
GET/v1/payments/{id}Получение платежа
i

Версия 1 может получать обратно совместимые поля и точки входа. Любое несовместимое изменение контракта будет оформлено через новый базовый путь, а не через незаметное изменение /v1.

Справочник API

Список активов

GET/v1/assetsТребуется Bearer-аутентификация

Используйте эту точку входа как источник достоверных данных для выбора при чекауте. Она возвращает включённые позиции каталога, актуальные независимо проверенные курсы, минимальные суммы в эквиваленте USD и статус готовности ноды и ленты котировок. Позиция может оставаться в списке с available: false, пока нода синхронизируется или её курс не удаётся подтвердить.

curl https://cryptopayin.com/v1/assets \
  --header "Authorization: Bearer $CPI_SECRET_KEY"
{
  "object": "list",
  "data": [{
    "asset": "USDT",
    "network": "TRC20",
    "type": "token",
    "decimals": 6,
    "minimum_amount": 1,
    "currency": "USD",
    "base_confirmations": 19,
    "available": true,
    "rate_usd": "1.00000000",
    "rate_source": "median:cb,cg,cl",
    "rate_source_count": 3,
    "rate_discrepancy_bps": 4,
    "rate_status": "healthy",
    "rate_updated_at": "2026-07-17T13:00:00+00:00"
  }]
}

Идентификаторы каталога и сети

АктивЗначение сетиСокращениеБазовые подтверждения
BTCmainnetBTC2
ETHmainnetETH6
USDTTRC20 / ERC20USDT.TRC2019 / 6
USDCERC20USDC.ERC206
DAIERC20DAI6
SHIBERC20SHIB6
PEPEERC20PEPE6
LTCmainnetLTC6
TRXmainnetTRX19
DOGEmainnetDOGE20
XMRmainnetXMR10
SOLmainnetSOL32
!

Доступность активов может меняться. Не жёстко прописывайте таблицу выше как актуальный список разрешённых активов. Для символов с несколькими сетями, таких как USDT, явно указывайте network или используйте сокращение ASSET.NETWORK.

Справочник API

Список фиатных валют

GET/v1/currenciesТребуется Bearer-аутентификация

Возвращает включённые валюты отображения, их точность по ISO и текущее состояние конвертации в USD. Предлагайте клиенту только строки с available: true. USD является базовой валютой; для всех остальных валют требуется актуальная живая котировка и независимая сверочная проверка. minimum_amount переводит минимальный настроенный порог для включённых активов в эту валюту; выбранный актив может требовать более высокую сумму, поэтому всегда проверяйте и GET /v1/assets.

curl https://cryptopayin.com/v1/currencies \
  --header "Authorization: Bearer $CPI_SECRET_KEY"
{
  "object": "list",
  "accounting_currency": "USD",
  "data": [{
    "currency": "EUR",
    "name": "Euro",
    "symbol": "€",
    "minor_units": 2,
    "available": true,
    "minimum_amount": "0.86",
    "rate_usd": "1.160000000000",
    "rate_source": "coinbase+ecb",
    "rate_source_count": 2,
    "rate_discrepancy_bps": 18,
    "rate_updated_at": "2026-07-17T13:00:00+00:00",
    "rate_reference_at": "2026-07-16T00:00:00+00:00"
  }]
}
i

Если валюта не указана в POST /v1/payments, по-прежнему подразумевается USD — для обратной совместимости. Валюты без дробной части, например JPY, не принимают дробные суммы. Относитесь к минимумам и курсам каталога как к живым данным, а не как к жёстко заданным константам.

Справочник API

Создание платежа

POST/v1/payments120 запросов в минуту на ключ

Создаёт счёт в запрошенной валюте отображения, фиксирует свежие проверенные снапшоты курсов фиат/USD и крипто/USD, вычисляет точную сумму в криптовалюте и привязывает выделенный адрес депозита в блокчейне.

Тело запроса

ПолеТипОбязательностьОписание
amountчисло или десятичная строкаобязательноЗначение в currency с точностью по ISO для этой валюты. Зафиксированный эквивалент в USD не должен превышать $1,000,000.00; также действуют минимумы по активу.
currencystringнеобязательноВключённая трёхбуквенная валюта из GET /v1/currencies. По умолчанию — USD.
assetstringобязательноСимвол, например ETH, либо сокращение, например USDT.TRC20.
networkstringусловноОбязательно, если символ существует в нескольких сетях. Пример: ERC20.
order_refstringнеобязательноИдентификатор вашего заказа, максимум 128 символов. Возвращается в ответах API и событиях.
customer_emailstringнеобязательноДействительный адрес электронной почты, максимум 190 символов. Сохраняется вместе с записью платежа мерчанта.
redirect_urlstringнеобязательноHTTPS-URL, максимум 255 символов, предлагается после успешного прохождения чекаута.

Поля ответа

ПолеТипОписание
idstringСтабильный идентификатор платежа, начинающийся с P-.
statusstringТекущее состояние жизненного цикла.
amount / amount_decimal / amount_minornumber / string / integerЗапрошенное значение отображения в удобной, точной десятичной форме и в минимальных единицах ISO.
currency / currency_minor_unitsstring / integerЗафиксированная валюта отображения и её точность.
amount_usd / amount_usd_centsnumber / integerНеизменяемое значение внутреннего учёта в USD.
fx_rate_usd / fx_source / fx_observed_atdecimal string / string / ISO 8601Зафиксированный снапшот курса USD за единицу валюты отображения и метаданные для аудита.
asset / networkstringОпределённый актив в блокчейне.
crypto_amountdecimal stringТочная сумма, которую должен отправить клиент. Никогда не разбирайте десятичные значения криптовалют как двоичные числа с плавающей точкой.
crypto_receiveddecimal stringТекущая наблюдаемая сумма на адресе депозита.
deposit_addressstringВыделенный адрес, привязанный к этому платежу.
exchange_ratedecimal stringЗафиксированный курс крипто/USD, использованный для вычисления crypto_amount; это поле сохраняет своё изначальное значение из v1.
exchange_rate_source / exchange_rate_observed_atstring / ISO 8601Неизменяемый снапшот курса криптовалюты для аудита.
confirmationsintegerТекущее число подтверждений сети.
confirmations_requiredintegerПорог для этого платежа. Более высокие суммы в USD могут требовать дополнительных подтверждений.
checkout_urlURLХостинг-счёт для показа клиенту.
expires_atISO 8601Крайний срок для неоплаченного счёта.
completed_atISO 8601 / nullВремя финального расчёта после завершения.

Перед созданием обе живые конвертации проверяются на актуальность, количество источников и расхождение курсов. Если проверка не проходит, создание завершается ошибкой вместо использования устаревшего курса. Сумма в криптовалюте округляется вверх с полезной для актива точностью, поэтому округление никогда не оставляет мерчанта в минусе.

Справочник API

Список платежей

GET/v1/payments240 запросов в минуту на ключ

Возвращает платежи аутентифицированного аккаунта мерчанта, начиная с самых новых. Используйте курсорную пагинацию для сверки и точные фильтры, чтобы найти заказ, не просматривая всю историю.

Параметры запроса

ПараметрПо умолчаниюОписание
limit20Размер страницы от 1 до 100.
starting_afterID платежа, возвращённый как next_cursor предыдущей страницы.
statusТочный статус жизненного цикла, например pending, completed или expired.
order_refТочный номер заказа мерчанта, максимум 128 символов.
curl "https://cryptopayin.com/v1/payments?status=completed&limit=20" \
  --header "Authorization: Bearer $CPI_SECRET_KEY"
{
  "object": "list",
  "data": [{
    "id": "P-9F27C1E4KD",
    "object": "payment",
    "status": "completed",
    "amount": 49.99,
    "currency": "USD",
    "asset": "ETH",
    "network": "mainnet",
    "crypto_amount": "0.01388612",
    "crypto_received": "0.01388612",
    "order_ref": "order_1042",
    "confirmations": 12,
    "confirmations_required": 12,
    "completed_at": "2026-07-17T13:12:42+00:00"
  }],
  "has_more": true,
  "next_cursor": "P-9F27C1E4KD"
}
i

Если has_more равно true, передавайте next_cursor без изменений как starting_after. Неизвестные или повторяющиеся параметры запроса в виде массива отклоняются, а не игнорируются.

Справочник API

Получение платежа

GET/v1/payments/{id}240 запросов в минуту на ключ

Возвращает тот же объект платежа, что и при создании, но с актуальным статусом, полученной суммой, хешем транзакции и числом подтверждений. Ключ может получать только платежи, принадлежащие его аккаунту мерчанта.

curl https://cryptopayin.com/v1/payments/P-9F27C1E4KD \
  --header "Authorization: Bearer $CPI_SECRET_KEY"
i

Обычные обновления заказа должны управляться webhooks. Используйте получение платежа для сверки после тайм-аута, проверки события, отображения страницы статуса на бэкенде или восстановления пропущенных доставок.

Модель состояний

Жизненный цикл платежа

Всегда считайте статус API источником истины. Не делайте вывод о завершении платежа по редиректу браузера или по словам клиента о том, что он заплатил.

created->pending->underpaidorconfirming->completed/overpaid
СтатусЗначениеДействие мерчанта
createdСчёт и адрес выделены; поступление средств пока не обнаружено.Покажите хостинг-чекаут.
pendingОжидание пригодного платежа в блокчейне.Держите заказ открытым.
underpaidПоступившая сумма ниже допустимого мерчантом порога.Попросите плательщика отправить показанный остаток.
confirmingОбнаружена достаточная сумма; ожидание подтверждений.Пока не выполняйте заказ.
completedДостигнуты требуемая сумма и число подтверждений.Выполните заказ ровно один раз.
overpaidПодтверждено больше ожидаемого.Выполните заказ и проверьте излишек.
expiredДо истечения срока не обнаружено подходящего платежа.Создайте новый платёж.
failedСбой при выделении адреса или обработке.Зафиксируйте ошибку и создайте новый платёж.
!

Переводы в блокчейне необратимы, а у CryptoPayIn нет механизма возврата средств — подтверждённый платёж окончателен. Любой добровольный возврат средств клиенту происходит напрямую между вами и клиентом, вне платформы.

Опыт клиента

Хостинг-чекаут

Каждый платёж, созданный через API, включает адаптивный checkout_url. На нём показаны мерчант, запрошенная сумма отображения, зафиксированный эквивалент в USD (если применимо), точная сумма в криптовалюте, адрес депозита, QR-код, предупреждение о сети, обратный отсчёт и прогресс подтверждений в реальном времени.

Курс зафиксирован

Клиент видит тот же crypto_amount, что возвращён API, на протяжении всего окна действия счёта.

Без аккаунта клиента

Плательщику не нужно создавать аккаунт CryptoPayIn или передавать учётные данные.

Статус в реальном времени

Страница безопасно опрашивает статус платежа и последовательно проходит стадии от ожидания к подтверждению и оплате.

Редирект к мерчанту

После успешной оплаты предлагается HTTPS-redirect_url; это не является доказательством платежа.

i

Выполнение заказа должно оставаться на вашем бэкенде. Переход в браузере можно прервать, повторить или подделать; только проверенный webhook или аутентифицированный GET-запрос подтверждают статус платежа.

Учётные данные

Права доступа и области действия

Каждый ключ API имеет фиксированный набор прав доступа, который выбирается при его создании в Кабинет → Разработчики. Каждая точка входа проверяет области действия ключа перед выполнением любой операции; вызов за пределами предоставленных прав возвращает 403 insufficient_scope с заголовком X-Required-Scope, указывающим отсутствующее право. Области действия задаются один раз при создании и не могут быть расширены позже — вместо этого выпустите новый ключ. Ключи, созданные до появления областей действия, сохраняют ровно свои изначальные возможности: payments:read и payments:write.

Область действияПредоставляетТочки входа
payments:readПросмотр списка и получение платежейGET /v1/payments, GET /v1/payments/{id}
payments:writeСоздание хостинг-платежейPOST /v1/payments
links:readПросмотр списка и получение платёжных ссылокGET /v1/links, GET /v1/links/{id}
links:writeСоздание, редактирование, приостановка и удаление платёжных ссылокPOST/PATCH/DELETE /v1/links
shops:readПросмотр списка и получение магазинов и их товаровGET /v1/shops, GET .../products
shops:writeСоздание и редактирование магазинов, товаров и вариантовPOST/PATCH/DELETE /v1/shops и товаров
balance:readЧтение криптобалансов и оценок в USDGET /v1/balance
payouts:readПросмотр списка и получение выводов средствGET /v1/payouts, GET /v1/payouts/{id}
payouts:writeЗапрос вывода средств в блокчейнPOST /v1/payouts
!

payouts:write перемещает средства в блокчейне, и это необратимо. Предоставляйте это право только полностью доверенным ключам, храните такие ключи на сервере и по возможности используйте отдельный ключ для каждого автоматизированного процесса. GET /v1/account показывает области действия вызывающего ключа и лимиты вашего аккаунта.

Машинные покупатели

Чекаут агентов

Каждая активная платёжная ссылка — это ещё и машиночитаемый чекаут: ИИ-агент или любой скрипт может обнаружить её, создать счёт и получить доставку без браузера — и без какого-либо ключа API, потому что это публичные точки входа для покупателя на домене ссылки, а не точки входа мерчанта. Полное описание контракта и рабочий пример: cryptopayin.com/agents.

GEThttps://cryptopaylink.co/pay/{link}.jsonпублично · обнаружение

Возвращает состояние, цену, принимаемые активы и точный контракт входных данных для вызова создания счёта (обязательные поля, схему доставки, варианты).

POSThttps://cryptopaylink.co/pay/{link}/invoiceпублично · поддерживает Idempotency-Key

Создаёт счёт через то же ядро, снапшот цены и лимиты защиты от злоупотреблений, что и хостинг-страница, и возвращает адрес депозита, точную сумму в криптовалюте, URI кошелька и URL квитанции. После этого агент оплачивает в блокчейне с любого контролируемого им кошелька.

GEThttps://cryptopaylink.co/pay/{link}/receipt?p={payment}публично · опрашивайте раз в 5–10 с

Статус и подтверждения в реальном времени; после завершения платежа ответ содержит доставку — ваш текстовый контент, приватный URL или лицензионный ключ, зарезервированный для этого платежа, — а также ваше сообщение об успехе и URL редиректа.

Магазины используют тот же протокол

Витрины реализуют тот же процесс на собственном домене: каталог с актуальными остатками, а затем один вызов, который проверяет корзину, резервирует товар и возвращает счёт.

GEThttps://shopycrypto.com/s/{shop}.jsonпублично · каталог
POSThttps://shopycrypto.com/s/{shop}/orderпублично · корзина → счёт, поддерживает Idempotency-Key
GEThttps://shopycrypto.com/s/{shop}/o/{order}/receipt?p={payment}публично · опрашивайте раз в 5–10 с

Настройки продавца

Чекаут агентов включён по умолчанию и стоит ту же фиксированную комиссию 1%. Отключить его для всего аккаунта можно в Кабинет → Настройки → Общее → ИИ и чекаут агентов: после этого машинные точки входа для ссылок и магазинов будут отвечать 403 agents_disabled, а обычные страницы чекаута для людей продолжат работать. Платежи, созданные агентами, не помечаются никак особо — это обычные платежи в вашем кабинете, webhooks и экспортах.

Ресурсы мерчанта

Магазины

Хостинг-витрина, объединяющая товары на одной брендированной странице. На аккаунт допускается до 10 магазинов. Товары управляются через вложенные точки входа для товаров, описанные ниже.

GET/v1/shopsshops:read
POST/v1/shopsshops:write
GET/v1/shops/{id}shops:read
PATCH/v1/shops/{id}shops:write
DELETE/v1/shops/{id}shops:write

Тело запроса

ПолеТипОбязательностьОписание
namestringобязательно2–80 символов.
taglinestringнеобязательноДо 160 символов.
themestringнеобязательноlight (по умолчанию) или dark.
accentstringнеобязательноHex-акцент из палитры магазина, возвращаемой как accent_palette в GET /v1/shops.
accepted_assetsarray of stringsнеобязательноАктивы по умолчанию для товаров магазина, например ["BTC","LTC","XMR"]. При изменении применяются ко всем товарам.
statusstringнеобязательноТолько PATCH: active или paused.
i

Магазин, отключённый CryptoPayIn по причинам, связанным с политикой платформы, нельзя ни повторно активировать, ни удалить через API — API вернёт admin_disabled (403). Удаление магазина удаляет его товары; прошлые платежи остаются нетронутыми.

Ресурсы мерчанта

Товары & варианты

Товары находятся внутри магазина. Каждый магазин допускает до 50 товаров. Товар может быть цифровым (с мгновенной доставкой) или физическим (со странами доставки) и может иметь до 30 комбинаций вариантов, построенных из 1–3 групп опций.

GET/v1/shops/{shop}/productsshops:read
POST/v1/shops/{shop}/productsshops:write
GET/v1/shops/{shop}/products/{id}shops:read
PATCH/v1/shops/{shop}/products/{id}shops:write
DELETE/v1/shops/{shop}/products/{id}shops:write

Тело запроса

ПолеТипОбязательностьОписание
titlestringобязательно3–120 символов.
description / blurbstringнеобязательноПолное описание и строка для карточки в магазине (≤200 символов).
emojistringнеобязательноОдин эмодзи, отображаемый на карточке товара.
featuredbooleanнеобязательноНе более одного рекомендуемого товара на магазин.
product_typestringнеобязательноdigital (по умолчанию) или physical.
shipping_countriesarray of stringsусловноТолько для физических товаров: коды ISO, например ["FR","BE"], либо ["*"] для доставки по всему миру.
amount_type / currency / amount / min / maxmixedусловноБазовая цена, правила идентичны платёжным ссылкам. Физические товары должны быть fixed.
max_usesintegerнеобязательноОбщий лимит продаж (0 = без ограничений).
delivery_type + delivery_text/url/keysmixedнеобязательноЦифровая доставка для базового товара, те же форматы, что и у платёжных ссылок.
variant_optionsarrayнеобязательно1–3 группы {name, values[]}, в каждой 2–10 значений. Число комбинаций не должно превышать 30.
variantsarrayусловноПо одному объекту на комбинацию (см. ниже). Обязательно и должно быть исчерпывающим при наличии variant_options.
statusstringнеобязательноТолько PATCH: active или paused.

Объект варианта

ПолеТипОписание
optionsarray of stringsПо одному значению на группу опций, в порядке групп, например ["Pro","Lifetime"].
pricenumber or stringЦена варианта в валюте товара.
stockinteger or nullОставшееся количество единиц или null для неограниченного запаса.
delivery_type + delivery_text/url/keysmixedНеобязательное переопределение цифровой доставки для конкретного варианта (по умолчанию inherit). Ключи должны быть уникальны в пределах всего товара.
curl -X POST https://cryptopayin.com/v1/shops/SH-JYRK8TFJ/products \
  -H "Authorization: Bearer $CPI_SECRET_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "title": "Software license",
    "amount": 30,
    "currency": "USD",
    "variant_options": [
      {"name": "Edition", "values": ["Standard", "Pro"]},
      {"name": "Term", "values": ["1 year", "Lifetime"]}
    ],
    "variants": [
      {"options": ["Standard","1 year"], "price": 30, "delivery_type": "keys", "delivery_keys": ["S1Y-1"]},
      {"options": ["Standard","Lifetime"], "price": 79, "stock": 10, "delivery_type": "keys", "delivery_keys": ["SLT-1"]},
      {"options": ["Pro","1 year"], "price": 59, "delivery_type": "keys", "delivery_keys": ["P1Y-1"]},
      {"options": ["Pro","Lifetime"], "price": 149, "stock": 5, "delivery_type": "keys", "delivery_keys": ["PLT-1"]}
    ]
  }'
i

PATCH сохраняет существующие заказы и уже доставленные ключи. Чтобы изменить цены или остатки, отправьте заново соответствующий массив variants; опущенные комбинации приостанавливаются, если по ним есть заказы, иначе удаляются. Товар может содержать не более 10,000 активных лицензионных ключей суммарно по базовому товару и вариантам, и каждый ключ должен быть уникален в пределах товара.

Ресурсы мерчанта

Баланс

GET/v1/balancebalance:read

Возвращает ваши расчётные балансы по каждому активу с приблизительной оценкой в USD и комиссией сети, взимаемой при выводе. Внутренний учёт всегда ведётся в USD; балансы формируются из завершённых платежей за вычетом комиссии мерчанта.

{
  "object": "list",
  "accounting_currency": "USD",
  "minimum_payout_usd": 25,
  "data": [{
    "asset": "USDT",
    "network": "TRC20",
    "amount": "99.099",
    "usd_estimate": 99.02,
    "payout_network_fee": "2.445463"
  }]
}
i

usd_estimate равно null, когда проверенный живой курс временно недоступен; сам баланс при этом остаётся точным. Используйте эти значения для принятия решений о выводе средств, а не для итогового учёта.

Ресурсы мерчанта

Вывод средств

Переводит расчётную криптовалюту на внешний кошелёк. Вывод средств необратим, поэтому эта точка входа применяет те же меры защиты, что и кабинет: корректный адрес назначения для актива, проверенный живой курс, минимум по аккаунту, достаточный баланс с учётом комиссии сети и двухфакторное подтверждение, если на аккаунте включена 2FA.

GET/v1/payoutspayouts:read
POST/v1/payoutspayouts:write · 30 / мин / ключ
GET/v1/payouts/{id}payouts:read

Тело запроса

ПолеТипОбязательностьОписание
assetstringобязательноСимвол или сокращение, например LTC или USDT.TRC20.
networkstringусловноОбязательно, если символ существует в нескольких сетях.
amountnumber or stringобязательноСумма к отправке без учёта комиссии сети, с точностью данного актива. Её эквивалент в USD должен соответствовать минимуму аккаунта.
addressstringобязательноАдрес назначения, проверяется по сети соответствующего актива.
notestringнеобязательноВаша собственная пометка, до 255 символов.
totp_codestringусловноТекущий 6-значный код или код восстановления. Обязателен, если на аккаунте включена 2FA.
curl -X POST https://cryptopayin.com/v1/payouts \
  -H "Authorization: Bearer $CPI_SECRET_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: withdraw-2026-07-19-01" \
  -d '{
    "asset": "USDT.TRC20",
    "amount": "50",
    "address": "TR7NHqjeKQxGTCi8q8ZY4pL8otSzgjLj6t",
    "note": "weekly settlement"
  }'
{
  "id": "W-EM64ZCJB",
  "object": "payout",
  "status": "requested",
  "asset": "USDT",
  "network": "TRC20",
  "amount": "50",
  "fee": "2.445463",
  "total_debited": "52.445463",
  "address": "TR7NHqjeKQxGTCi8q8ZY4pL8otSzgjLj6t",
  "txid": null,
  "confirmations": 0,
  "created_at": "2026-07-19T19:10:00+00:00"
}

Жизненный цикл статуса

СтатусЗначение
requestedЗарезервировано из вашего баланса; ожидает проверки оператором или автоматического одобрения.
approved / processingОдобрено и поставлено в очередь на отправку исполнителем.
sentОтправлено в блокчейн; заполняется поле txid.
confirmedДостигнуты необходимые подтверждения. Финальный статус.
failedНе удалось отправить; failure_message объясняет причину, средства возвращаются на баланс.
cancelledОтменено до отправки в блокчейн; зарезервированный баланс возвращается.

Отправляйте Idempotency-Key, чтобы повторная попытка из-за сетевого сбоя никогда не создала второй вывод: тот же ключ с тем же телом запроса возвращает исходный вывод (Idempotent-Replayed: true); тот же ключ с другим телом возвращает 409 idempotency_conflict. Код 2FA намеренно исключён из отпечатка идемпотентности, чтобы меняющийся код не вызывал ложный конфликт. Резервирование списывает средства с баланса немедленно; при отклонённом или отменённом выводе средства возвращаются.

Ресурсы мерчанта

Аккаунт

GET/v1/accountлюбой действительный ключ

Возвращает профиль вашего аккаунта, области действия вызывающего ключа, комиссию платформы и все актуальные лимиты — полезно для самонастраивающейся интеграции или предварительной проверки.

{
  "object": "account",
  "id": "MC67T3PHQZ",
  "fee_bps": 100,
  "fee_percent": 1,
  "default_currency": "USD",
  "two_factor_enabled": false,
  "api_key": {"label": "production", "scopes": ["payments:read","payments:write"]},
  "limits": {
    "shops": {"used": 1, "max": 10},
    "payment_links": {"used": 0, "max": 50},
    "products_per_shop_max": 50,
    "variant_combinations_per_product_max": 30,
    "license_keys_per_product_max": 10000,
    "active_api_keys_max": 50,
    "checkout_fields_per_link_max": 5
  },
  "minimum_payout_usd": 25
}
События между серверами

Webhooks

Добавьте до 10 публичных HTTPS-точек входа в Кабинет -> Разработчики. Каждая точка входа получает собственный секрет подписи whsec_..., который показывается один раз. Она может прослушивать весь аккаунт или быть привязана к конкретному активному ключу API; точки входа, привязанные к ключу, получают только платежи, созданные этим ключом.

Проверяйте перед разбором

CryptoPayIn подписывает точное необработанное тело запроса с помощью секрета точки входа. Версия 1 подписывает timestamp + "." + raw_body. Отклоняйте устаревшие метки времени, прежде чем принять событие.

import crypto from "node:crypto";

const timestamp = req.headers["x-cpi-timestamp"];
const signature = req.headers["x-cpi-signature"];
const rawBody = req.rawBody; // Buffer captured before JSON parsing

if (Math.abs(Date.now() / 1000 - Number(timestamp)) > 300) {
  throw new Error("stale webhook");
}
const expected = "sha256=" + crypto
  .createHmac("sha256", process.env.CPI_WEBHOOK_SECRET)
  .update(Buffer.concat([Buffer.from(`${timestamp}.`), rawBody]))
  .digest("hex");
const valid = crypto.timingSafeEqual(Buffer.from(expected), Buffer.from(signature));
if (!valid) throw new Error("invalid webhook signature");

Заголовки доставки

ЗаголовокПримерНазначение
Content-Typeapplication/jsonТело в формате UTF-8 JSON.
X-CPI-Timestamp1784293200Unix-время (секунды), включённое в подписываемое сообщение.
X-CPI-Signaturesha256=...HMAC-SHA256 в hex-формате.
X-CPI-Signature-Versionv1Версия схемы подписи.
X-CPI-Event-Idevt_a12b...Стабильный логический ID события; одинаков при повторных попытках.
X-CPI-Delivery-Id1842Стабильный ID записи о доставке для точки входа.

Полезная нагрузка платежа

{
  "event_id": "evt_a12b34c56d78e90f12345678",
  "event": "payment.completed",
  "id": "P-9F27C1E4KD",
  "status": "completed",
  "order_ref": "order_1042",
  "amount": 49.99,
  "amount_decimal": "49.99",
  "amount_minor": 4999,
  "currency_minor_units": 2,
  "currency": "USD",
  "amount_usd": 49.99,
  "amount_usd_cents": 4999,
  "fx_rate_usd": "1.000000000000",
  "fx_source": "fixed:USD",
  "fx_observed_at": "2026-07-17T13:00:00Z",
  "fx_discrepancy_bps": 0,
  "exchange_rate": "3600.00000000",
  "exchange_rate_currency": "USD",
  "exchange_rate_source": "median:cb,cg,cl",
  "exchange_rate_source_count": 3,
  "exchange_rate_observed_at": "2026-07-17T13:00:00Z",
  "exchange_rate_discrepancy_bps": 12,
  "asset": "ETH",
  "network": "mainnet",
  "crypto_amount": "0.01388612",
  "crypto_received": "0.01388612",
  "txid": "0x9d81...75af",
  "confirmations": 12,
  "confirmations_required": 12,
  "deposit_address": "0x71b8c3d4700000000000000000000000000084e2",
  "sent_at": "2026-07-17T13:12:42Z"
}

Повторные попытки и безопасность точки входа

Возвращайте любой 2xx

Доставка считается успешной при HTTP 200-299. Выполняйте затратные операции асинхронно и отвечайте быстро.

Всего шесть попыток

Точное тело запроса и ID события сохраняются; при сбое повтор происходит примерно через 1 минуту, 5 минут, 30 минут, 2 часа и 6 часов.

Без редиректов

Ответы 3xx не обрабатываются. Регистрируйте сразу конечный HTTPS-URL.

Только публичные адреса

Частные, локальные (loopback), link-local и зарезервированные IP-адреса заблокированы; каждый DNS-ответ проверяется, а соединение закрепляется (pinning).

!

Доставка гарантируется как минимум один раз. Сделайте свой обработчик идемпотентным: записывайте event_id с ограничением уникальности перед выполнением заказа. При сверке неожиданного события получайте объект через API.

Webhooks

Справочник событий

payment.completedОжидаемая сумма подтверждена.
payment.overpaidПодтверждено больше ожидаемого.
payment.underpaidОбнаружено поступление ниже допустимого порога.
payment.expiredИстекло окно для неоплаченного счёта.
payment.failedСбой при создании или обработке платежа.
payout.sentВывод отправлен в блокчейн.
payout.confirmedВывод достиг нужных подтверждений.
payout.failedВывод не удалось завершить.
webhook.testРучная проверка соединения.

Формат события вывода средств

{
  "event_id": "evt_b98c76d54e32a10f87654321",
  "event": "payout.sent",
  "id": "W-8J2K7M4RQP",
  "status": "sent",
  "asset": "ETH",
  "network": "mainnet",
  "amount": "0.25",
  "fee": "0.00081768",
  "address": "0x84f2...9bc1",
  "txid": "0xa1c4...07ee",
  "confirmations": 0,
  "note": "weekly treasury",
  "sent_at": "2026-07-17T14:08:31Z"
}
Надёжность

Ошибки и лимиты запросов

Ошибки всегда используют единый JSON-конверт. Ветвите логику по error.type; текст сообщения для человека может улучшаться без изменения версии. При обращении в поддержку указывайте error.request_id или соответствующий заголовок ответа X-Request-Id.

{
  "error": {
    "type": "ambiguous_asset",
    "message": "specify network (e.g. USDT.ERC20 or USDT.TRC20)",
    "request_id": "b942e21f8dca4b06b8672eb9"
  }
}
HTTPТипичные типыЗначение
400invalid_request, unknown_parameterНекорректный JSON, параметры запроса или заголовок идемпотентности.
401unauthorizedОтсутствующие, недействительные или неактивные учётные данные/аккаунт.
403insufficient_scope, admin_disabledДействительный ключ без нужного права доступа (см. X-Required-Scope), либо ресурс, заблокированный администратором.
404not_foundНеизвестная точка входа либо ресурс за пределами этого аккаунта мерчанта.
405method_not_allowedИспользуйте метод, указанный в заголовке Allow.
409idempotency_conflictКлюч использован повторно с другим JSON.
413request_too_largeТело JSON превышает 64 KiB.
415unsupported_media_typeТело POST-запроса не объявлено как application/json.
422invalid, limit, invalid_amount, below_minimum, bad_address, 2fa_required, unsupported_assetКорректно оформленный запрос не прошёл детерминированную валидацию либо достиг лимита ресурса.
429rate_limitedДождитесь Retry-After.
500server_errorНепредвиденный сбой; можно безопасно повторить запрос с тем же ключом идемпотентности.
503maintenance, temporarily_unavailable, asset_unavailable, no_rate, price_stale, fiat_rate_unavailable, fiat_rate_stale, derive_failedВременный сбой платформы, ноды, курса или выделения адреса. Устаревшая конвертация никогда не подставляется.

Текущие лимиты

КатегорияЛимитОкно
Защитный лимит Nginx на IP10 запросов/секунду, всплеск до 30Непрерывно
Лимит для неаутентифицированного IP300 запросов60 секунд
POST /v1/payments, links, shops, products120 запросов на ключ API60 секунд
POST /v1/payouts30 запросов на ключ API60 секунд
GET-точки входа240 запросов на ключ API60 секунд

Лимиты аккаунта

РесурсЛимит
Магазинов на аккаунт10
Платёжных ссылок на аккаунт50
Товаров на магазин50
Комбинаций вариантов на товар30
Лицензионных ключей на товар / ссылку10,000
Вопросов при чекауте на ссылку5
Активных ключей API на аккаунт50

Актуальное использование относительно этих лимитов можно посмотреть в GET /v1/account.

Успешные ответы, ограниченные на уровне приложения, содержат заголовки X-RateLimit-Limit, X-RateLimit-Remaining и X-RateLimit-Reset. Повторяйте 429, 500 и 503 с экспоненциальной задержкой и джиттером. Для POST всегда используйте тот же исходный Idempotency-Key и идентичный JSON.

Безопасность в продакшене

Безопасность интеграции

Храните секреты API в менеджере секретов

Загружайте их во время выполнения; никогда не записывайте полное значение в логи и не сохраняйте в системе контроля версий.

Вызывайте API со своего бэкенда

Браузер или мобильное приложение не могут безопасно хранить секрет мерчанта.

Проверяйте необработанное тело webhook

Перед разбором JSON проверяйте актуальность метки времени и сравнивайте подпись за постоянное время.

Делайте выполнение заказа идемпотентным

Записывайте обработанные события/заказы транзакционно, чтобы повторные попытки никогда не приводили к двойной отправке.

Доверяйте финальному статусу API, а не редиректам

Запрашивайте платёж, если событие неожиданно или ваше локальное состояние расходится с ним.

Ротация ключей с перекрытием

Создайте новый ключ, разверните его, убедитесь в корректности трафика и только потом удалите старый ключ.

!

Доступ к аккаунту контролируется невосстанавливаемым 16-значным ключом мерчанта, дополнительно защищаемым TOTP по желанию. Храните и ключ доступа мерчанта, и секреты API с той же осторожностью, что и учётные данные от кошелька.

Запуск

Чек-лист перед запуском

1
Создайте отдельный боевой ключ API

Не используйте повторно личную копию ключа разработчика в разных сервисах.

2
Запросите оба актуальных каталога

Используйте GET /v1/assets и GET /v1/currencies; отображайте только записи, которые присутствуют и available: true.

3
Добавьте и протестируйте свою точку входа webhook

Сохраните секрет подписи один раз; проверяйте метку времени и подпись, а затем дедуплицируйте по стабильному ID события.

4
Используйте ключ идемпотентности для каждого заказа

Проверьте повторную отправку дубликата и убедитесь, что существует только один ID платежа.

5
Протестируйте сбои курсов, недоплату и истечение срока

Состояние вашего заказа должно оставаться корректным при устаревших фиатных курсах, недоступных активах, задержке подтверждений и любом нештатном сценарии.

6
Сверяйте данные ежедневно

Сравнивайте свои заказы со статусами платежей в API, логами webhook и реестром мерчанта.

Готовы к интеграции?

Создайте аккаунт за несколько секунд, сгенерируйте ключ и держите этот справочник рядом с кодом.

Создать аккаунт