HHelmer/ API
На сайт Получить ключ

API Helmer

Принимайте USDT (BEP-20) на своём сайте. Ваш сервер создаёт платёж запросом к нашему API — мы выдаём адрес приёма, отслеживаем оплату в блокчейне и отправляем подписанный вебхук. Контракт совместим с Heleket: если у вас уже есть интеграция Heleket/Cryptomus — смена базового URL достаточно.

Базовый URL
https://hlm-3112d825.duskyr.com/v1

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

Каждый запрос подписывается. В заголовках передаются merchant (ваш UUID мерчанта) и sign. Подпись считается от СЫРОГО тела запроса:

sign = md5( base64(тело_запроса) + api_key )

UUID мерчанта и API-ключ — в кабинете, раздел «API-ключи». Ключ секретный, не публикуйте его в клиентском коде.

Пример подписи (PHP)

$data = json_encode($payload);
$sign = md5(base64_encode($data) . $apiKey);

$headers = [
    "merchant: " . $merchantUuid,
    "sign: " . $sign,
    "Content-Type: application/json",
];

Пример подписи (Python)

import base64, hashlib, json, httpx

body = json.dumps(payload).encode()
sign = hashlib.md5(base64.b64encode(body) + api_key.encode()).hexdigest()

httpx.post(f"{BASE}/v1/payment", content=body, headers={
    "merchant": merchant_uuid,
    "sign": sign,
    "Content-Type": "application/json",
})

Формат ответа

Успешный ответ: state = 0 и объект/массив result. Все денежные суммы — строками (не числами с плавающей точкой).

{
  "state": 0,
  "result": { ... }
}

Ошибки

При ошибке: state = 1. Доменные ошибки содержат message, ошибки валидации — errors с полями.

{ "state": 1, "message": "Payment not found" }

{ "state": 1, "errors": { "date_from": ["validation.regex"] } }

Создать платёж

POST/v1/payment

Создаёт инвойс и возвращает адрес приёма + ссылку на страницу оплаты. Идемпотентно по order_id: повторный запрос с тем же order_id вернёт существующий инвойс.

Параметры

ПолеТипОписание
amount*stringСумма в валюте currency
currencystringUSD/EUR/RUB (фиат) или USDT. По умолчанию USDT
order_idstringВаш ид заказа (для идемпотентности)
url_callbackstringURL для вебхука о статусе платежа
url_returnstringКуда вернуть покупателя с checkout
url_successstringКуда вернуть после успешной оплаты
additional_datastringПроизвольная метка (вернём в вебхуке)

Запрос

curl https://hlm-3112d825.duskyr.com/v1/payment \
  -X POST \
  -H "merchant: 8b03432e-385b-4670-8d06-064591096795" \
  -H "sign: <md5-подпись>" \
  -H "Content-Type: application/json" \
  -d '{
    "amount": "10.00",
    "currency": "USD",
    "order_id": "ORDER-1024",
    "url_callback": "https://your.site/helmer/callback"
  }'

Ответ

{
  "state": 0,
  "result": {
    "uuid": "231",
    "order_id": "ORDER-1024",
    "amount": "10.00758575",
    "payment_amount": "0.00000000",
    "payer_currency": "USDT",
    "network": "bsc",
    "address": "0x6767d64FA781B73C19F837ee2373A6aaeecb217F",
    "url": "https://hlm-3112d825.duskyr.com/pay/231",
    "payment_status": "check",
    "expired_at": 1689172103,
    "created_at": 1689168503,
    "is_final": false,
    "merchant_amount": "10.00",
    "currency": "USD",
    "rate": "0.9992"
  }
}

Статус платежа

POST/v1/payment/info

Возвращает текущий статус инвойса по uuid или order_id (одно из двух).

curl https://hlm-3112d825.duskyr.com/v1/payment/info \
  -X POST -H "merchant: <uuid>" -H "sign: <sign>" \
  -H "Content-Type: application/json" \
  -d '{ "order_id": "ORDER-1024" }'

История платежей

POST/v1/payment/list

Список инвойсов с cursor-пагинацией. Опциональные фильтры date_from/date_to (формат YYYY-MM-DD HH:mm:ss). Для следующей страницы передайте ?cursor=nextCursor.

curl "https://hlm-3112d825.duskyr.com/v1/payment/list?cursor=<nextCursor>" \
  -X POST -H "merchant: <uuid>" -H "sign: <sign>" \
  -H "Content-Type: application/json" \
  -d '{ "date_from": "2026-07-01 00:00:00" }'
{
  "state": 0,
  "result": {
    "items": [ { "uuid": "231", "order_id": "ORDER-1024", "status": "paid", ... } ],
    "paginate": {
      "count": 15,
      "hasPages": true,
      "nextCursor": "eyJpZCI6MjE2fQ",
      "previousCursor": null,
      "perPage": 15
    }
  }
}

Список сервисов

POST/v1/payment/services

Доступные сети/валюты с лимитами и комиссией. Тело — пустой объект {}.

{
  "state": 0,
  "result": [
    {
      "network": "BSC",
      "currency": "USDT",
      "is_available": true,
      "is_enabled": true,
      "limit": { "min_amount": "0.50000000", "max_amount": "1000000.00000000" },
      "commission": { "fee_amount": "0.00", "percent": "0.00" }
    }
  ]
}

Статусы платежа

СтатусЗначение
checkЖдём оплату
confirm_checkПеревод увиден, ждём подтверждений сети
paidОплачено полностью
wrong_amountОплачено меньше суммы
cancelИстёк срок инвойса

Баланс

POST/v1/balance

Баланс мерчанта. Тело — пустой объект {}.

{
  "state": 0,
  "result": [
    { "balance": { "merchant": [ { "uuid": "<merchant-uuid>", "balance": "125.40000000", "currency_code": "USDT" } ], "user": [] } }
  ]
}

Курс валют

GET/v1/exchange-rate/{currency}/list

Текущий курс валюты к USD. Публичный метод (без подписи).

curl https://hlm-3112d825.duskyr.com/v1/exchange-rate/USDT/list
{
  "state": 0,
  "result": [ { "from": "USDT", "to": "USD", "course": "0.99920700" } ]
}

Формат вебхука

При смене статуса мы отправляем POST на url_callback (или на общий webhook-URL мерчанта). Тело — JSON с деталями платежа. Тип события дублируется в поле type и в заголовке X-Helmer-Event. Поле event_id (и заголовок X-Helmer-Event-Id) используйте для дедупликации — сеть ненадёжна, один вебхук может прийти несколько раз.

Заголовки

X-Helmer-Signature: sha256=2b0f...e4a1
X-Helmer-Timestamp: 1689172103
X-Helmer-Event: payment
X-Helmer-Event-Id: 8b03432e-2f4c-4b0e-9a1d-6f0e5c1b7a90
Content-Type: application/json

Тело

{
  "type": "payment",
  "event_id": "8b03432e-2f4c-4b0e-9a1d-6f0e5c1b7a90",
  "uuid": "231",
  "order_id": "ORDER-1024",
  "amount": "10.00758575",
  "payment_amount": "10.00758575",
  "payment_amount_usd": "10.00",
  "merchant_amount": "10.00758575",
  "commission": "0",
  "is_final": true,
  "status": "paid",
  "from": "0xPayerAddress...",
  "txid": "0xTransactionHash...",
  "network": "bsc",
  "currency": "USD",
  "payer_currency": "USDT",
  "address": "0x6767d64FA781B73C19F837ee2373A6aaeecb217F",
  "additional_data": null
}

Ваш сервер должен ответить 200 OK. При другом ответе/таймауте мы повторяем доставку по расписанию (0, 1, 5, 15, 60, 180, 360, 720 мин от события).

Проверка подписи (HMAC-SHA256)

Подпись вебхука — в заголовке X-Helmer-Signature в виде sha256=<hex>. Считается как HMAC-SHA256 по строке «timestamp.body» ключом webhook_secret (секрет вебхука из кабинета, раздел «Вебхуки»; ротация секрета реально меняет подпись). timestamp — в заголовке X-Helmer-Timestamp (unix-секунды).

signature = HMAC_SHA256( webhook_secret, timestamp + "." + raw_body )

Возьмите сырое тело запроса и заголовок X-Helmer-Timestamp, соберите строку «{timestamp}.{body}», посчитайте HMAC-SHA256 своим webhook_secret и сравните с подписью из заголовка (константное по времени сравнение). Отвергайте вебхуки, где X-Helmer-Timestamp старше ~5 минут (защита от replay).

Пример проверки (PHP)

$secret    = getenv("HELMER_WEBHOOK_SECRET");
$body      = file_get_contents("php://input");
$timestamp = $_SERVER["HTTP_X_HELMER_TIMESTAMP"] ?? "";
$header    = $_SERVER["HTTP_X_HELMER_SIGNATURE"] ?? "";

$expected = hash_hmac("sha256", $timestamp . "." . $body, $secret);
$given    = preg_replace("/^sha256=/", "", $header);

if (!hash_equals($expected, $given)) { http_response_code(400); exit; }
if (abs(time() - (int)$timestamp) > 300) { http_response_code(400); exit; }

http_response_code(200);

Пример проверки (Python)

import hashlib, hmac, time

def verify(headers, raw_body: bytes, secret: str) -> bool:
    ts  = headers.get("X-Helmer-Timestamp", "")
    got = headers.get("X-Helmer-Signature", "").removeprefix("sha256=")
    expected = hmac.new(
        secret.encode(), f"{ts}.".encode() + raw_body, hashlib.sha256
    ).hexdigest()
    if not hmac.compare_digest(expected, got):
        return False
    return abs(int(time.time()) - int(ts)) <= 300

Тест вебхука

POST/v1/test-webhook/payment

Отправляет тестовый вебхук на указанный URL, чтобы вы проверили приём и валидацию подписи. В БД ничего не сохраняется. Если передать uuid/order_id — данные возьмутся из реального инвойса.

curl https://hlm-3112d825.duskyr.com/v1/test-webhook/payment \
  -X POST -H "merchant: <uuid>" -H "sign: <sign>" \
  -H "Content-Type: application/json" \
  -d '{
    "url_callback": "https://your.site/helmer/callback",
    "currency": "USDT",
    "network": "bsc",
    "status": "paid"
  }'

Повторная отправка вебхука

POST/v1/payment/resend

Повторно отправляет вебхук по финализированному инвойсу (paid / wrong_amount). Требуется, чтобы при создании был указан url_callback. Лимит — 10 пересылок на инвойс.

curl https://hlm-3112d825.duskyr.com/v1/payment/resend \
  -X POST -H "merchant: <uuid>" -H "sign: <sign>" \
  -H "Content-Type: application/json" \
  -d '{ "order_id": "ORDER-1024" }'
Готовы подключиться?

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

Получить API-ключ