Приём открыт: 12 монет и токенов в 10 сетях Документация API Статус сетей Поддержка
Подключиться
API v4 и совместимый API v3

Подключение AstraPay

Принимайте пополнения баланса на закреплённый за клиентом адрес. Проект, клиент, счёт и зачисление имеют отдельные идентификаторы.

Адрес API
astrapay.cc/api
Авторизация
Bearer, ключ проекта
Повтор запроса
Idempotency-Key
Курс счёта
30 минут
Комиссия
3%
Подпись уведомлений
HMAC-SHA256
01

Подготовьте проект

  1. Создайте аккаунт и подтвердите emailСоздать аккаунт
  2. Включите 2FA и добавьте проектУкажите HTTPS-адрес, на который будут приходить уведомления.
  3. Подтвердите доменДобавьте TXT-запись, указанную в кабинете, и дождитесь одобрения проекта.
  4. Получите API-ключ и секрет подписи уведомленийХраните их на сервере своего приложения.

Ключ и заголовки

API-ключ передаётся в заголовке Authorization: Bearer …. Запросы, которые создают счёт или меняют адрес, передают ключ идемпотентности Idempotency-Key.

Заголовки запроса
Authorization: Bearer <ключ проекта>
Content-Type: application/json
Idempotency-Key: <ключ операции>

Ключ проекта не следует помещать в JavaScript сайта, Mini App или клиентское приложение. Запросы к API отправляет только ваш сервер.

02

Создайте ссылку на оплату

Передайте сумму в рублях, а валюту и сеть клиент выберет на странице AstraPay. При создании ссылки кошелёк и валютный счёт ещё не выдаются.

POST

https://astrapay.cc/api/v4/checkouts

Тело запроса
external_user_idстрока
Постоянный ID клиента внутри вашего проекта.
rub_amountстрока
Сумма пополнения в рублях, например "1200.00".
POST https://astrapay.cc/api/v4/checkouts
Authorization: Bearer <ключ проекта>
Idempotency-Key: order-123-checkout
Content-Type: application/json

{"external_user_id":"customer-42","rub_amount":"1200.00"}
В ответе checkout_url: откройте эту ссылку клиенту.

Как работает ссылка

  • Не удаляйте фрагмент #token=… и не записывайте ссылку в публичные логи.
  • Повторный запрос с тем же ключом и данными возвращает ту же ссылку.
  • Двойное нажатие при выборе сети возвращает уже выбранные реквизиты.
  • За один платёж выдаётся один валютный счёт. Существующий протокол подписанных зачислений v3 сохраняется.

Заранее выбранная сеть: совместимый API v3

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

POST

https://astrapay.cc/api/v3/customer/quotes

HTTP
POST https://astrapay.cc/api/v3/customer/quotes
Authorization: Bearer <API_KEY>
Content-Type: application/json
Idempotency-Key: topup-customer1042-0001

{
  "external_user_id": "1042",
  "asset_key": "ton_usdt",
  "rub_amount": "1200.00"
}
Зафиксированные условия в ответе
checkout_url
Ссылка для перехода клиента к оплате.
expected_amount
Точная сумма перевода.
deposit_address
Адрес для перевода.
network
Сеть перевода.
expires_at
Срок действия условий.

Курс действует 30 минут, комиссия 3%. Суммы в минимальных единицах приходят строками, чтобы избежать потери точности.

Идентификаторы активов

asset_keyАктив и сеть
ethereum_usdtUSDT, Ethereum ERC20
ethereum_ethETH, Ethereum
ton_usdtUSDT, TON
ton_tonToncoin, TON
litecoin_ltcLTC, Litecoin

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

GET

/api/v3/customer/methodsТекущая доступность способов оплаты

GET

/api/v3/customer/quotes/{quote_id}Исходный счёт, с API-ключом своего проекта

03

Адрес клиента в каждой сети

Монета сети и токен в ней используют один адрес клиента. Адреса разных проектов изолированы.

Ethereum
  • ETH
  • USDT ERC20
Один адрес клиентаEthereum
TON
  • Toncoin
  • USDT TON
Один адрес клиентаTON

Перед каждой оплатой создавайте счёт: именно он фиксирует курс и ожидаемую сумму.

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

Когда платёж направляется на проверку

Если поступление нельзя однозначно связать со счётом, платёж направляется на проверку. Например, когда перевод:

  • пришёл поздно;
  • пришёл частично;
  • совпал с суммой другого неоплаченного счёта.

Зачисление относится к балансу клиента. Распределение баланса по заказам выполняет ваш сервис.

Смена адреса

Смену следует выполнять по явному запросу авторизованного клиента. При незавершённой оплате или спорном поступлении операция отклоняется.

POST

/api/v3/customer/wallets/rotate

HTTP
POST /api/v3/customer/wallets/rotate
Authorization: Bearer <API_KEY>
Idempotency-Key: rotate-customer1042-0001
Content-Type: application/json

{
  "external_user_id": "1042",
  "network": "ton",
  "previous_wallet_id": "<текущий wallet_id>",
  "confirm_retire_previous": true
}

Ответ содержит новый wallet_id и поколение адреса, а сам адрес появится в следующем зафиксированном счёте. Старый адрес остаётся связан с тем же клиентом и продолжает отслеживаться.

04

Подтвердите зачисление

О зачислении ваш сервер узнаёт из подписанного события и отвечает подписанной квитанцией.

customer_balance.creditedпротокол 3
  • credit_id
  • quote_id
  • customer_id
  • merchant_id
  • wallet_id
  • rub_kopecks
  • payload_hash
  • параметры перевода и сети

Проверка подписи

Проверьте подпись по исходным байтам HTTP-тела. Время в X-AstraPay-Timestamp должно отличаться от текущего не более чем на 300 секунд, X-AstraPay-Delivery-Id содержит UUID. Подпись: HMAC-SHA256 от трёх строк.

Подпись
timestamp + "\n" + delivery_id + "\n" + sha256(raw_body).hexdigest()
Заголовки уведомления
X-AstraPay-Signature: <HMAC-SHA256, hex>
X-AstraPay-Timestamp: <Unix timestamp>
X-AstraPay-Delivery-Id: <UUID>
import hashlib, hmac, time, uuid

def _sign(secret: str, ts: str, delivery_id: str, body: bytes) -> str:
    message = ts + "\n" + delivery_id + "\n" + hashlib.sha256(body).hexdigest()
    return hmac.new(secret.encode(), message.encode(), hashlib.sha256).hexdigest()

def verify(raw_body: bytes, headers, secret: str) -> bool:
    ts = headers["X-AstraPay-Timestamp"]
    delivery_id = headers["X-AstraPay-Delivery-Id"]
    if abs(time.time() - int(ts)) > 300:
        return False
    uuid.UUID(delivery_id)  # ValueError, если это не UUID
    expected = _sign(secret, ts, delivery_id, raw_body)
    return hmac.compare_digest(expected, headers["X-AstraPay-Signature"])

def receipt_headers(body: bytes, delivery_id: str, secret: str) -> dict:
    ts = str(int(time.time()))
    return {
        "X-AstraPay-Signature": _sign(secret, ts, delivery_id, body),
        "X-AstraPay-Timestamp": ts,
        "X-AstraPay-Delivery-Id": delivery_id,
    }
Пример проверки по формуле выше. Секрет подписи берётся из кабинета и хранится только на сервере.

Обработка и квитанция

  1. Одна транзакция в вашей базеПроверьте уникальность credit_id, привязку клиента и проекта, добавьте rub_kopecks на баланс и сохраните квитанцию.
  2. Повтор не меняет балансПри повторе верните ту же квитанцию. При несовпадении тела для уже известного credit_id остановите обработку для проверки.
  3. Ответ: HTTP 200 и подписанная квитанцияПодпишите байты тела квитанции тем же секретом и теми же заголовками. Delivery-Id должен совпасть с текущим входящим запросом.
Квитанция
{
  "protocol_version": 3,
  "status": "credited",
  "receipt_id": "<постоянный ID вашей квитанции>",
  "credit_id": "<из события>",
  "quote_id": "<из события>",
  "customer_id": "<из события>",
  "merchant_id": "<из события>",
  "wallet_id": "<из события>",
  "rub_kopecks": "<точная строка из события>",
  "payload_hash": "<из события>"
}

Одного HTTP 200 без корректной подписанной квитанции недостаточно. После потери ответа шлюз повторяет доставку с тем же credit_id.

В production принимайте только ожидаемые environment=mainnet, test_mode=false, сеть и контракт. События старых протоколов обрабатываются отдельно: не преобразуйте исторические счета в новый формат.

05

Состояния и ошибки

Ответ
Действие интеграции
401 / 403
Проверьте ключ, полномочия проекта или сессию. Не создавайте новый платёж автоматически.
409
Проверьте активный счёт, незавершённый перевод или повтор ключа с другими данными.
409customer_quote_amount_ambiguous
Не удалось безопасно различить новый и прежний расчёт. Проверьте состояние исходной ссылки и не отправляйте повторную оплату. Новый выбор сети или новая попытка допустимы только после подтверждения шлюзом, что прежние реквизиты не выдавались.
422
Исправьте формат и сумму запроса.
429
Сделайте паузу перед повтором.
503
Сеть или проверка временно недоступна. Повторяйте исходный запрос с прежним Idempotency-Key.

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

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

manual_reviewexpireddetected

Не исполняйте заказ только по скриншоту перевода, хешу транзакции или факту открытия страницы оплаты. Основание для зачисления: подписанное событие customer_balance.credited.

Подключите проект и получите ключи

Создайте аккаунт, включите 2FA и подтвердите домен. Ключ API и секрет подписи появятся в кабинете после одобрения проекта.