Интеграция Reseller API: от ключа до первого заказа

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

Содержание 9 разделов
  1. Ключ и базовый адрес
  2. Каталог
  3. Проверка получателя
  4. Заказ в две фазы
  5. Опрос статуса
  6. Где лежит товар
  7. Суммы в nano
  8. Коды ответов
  9. Чек-лист

От ключа до доставленного заказа шесть шагов: ключ, каталог, проверка получателя, создание заказа, оплата и опрос статуса. У каждого шага запрос, ответ и место, где легко ошибиться.

#Ключ и базовый адрес

Ключ выпускается в кабинете после входа через Telegram и показывается один раз. Положите его в переменную окружения: в коде и логах ему не место. Каждый запрос несёт заголовок Authorization: Bearer <ключ>.

Базовый адрес https://hexpay.live. Префиксы /api/reseller и /api/reseller/v1 равнозначны. Для новой интеграции берите версионированный: с выходом v2 он продолжит работать по-старому.

GET /api/reseller/v1/balance
curl https://hexpay.live/api/reseller/v1/balance \
  -H "Authorization: Bearer $HEX_API_KEY"
Ответ 401 значит, что API не принял ключ.

Лимит около 60 запросов в минуту на ключ. На превышение API отвечает 429 с заголовком Retry-After: ждите указанное там время и только потом повторяйте запрос.

#Каталог

Витрину стройте по ответу GET /products: оптовая цена зависит от курса и ваших персональных условий, и своя таблица цен быстро устареет. Поле pricing_mode у позиции говорит, что передавать в заказе, а required_field называет обязательное поле.

Что передавать в заказе по товарам
ТоварproductquantityПолучатель
Telegram Starsstarsчисло звёзд, 50…1 000 000Telegram-юзернейм
Telegram Premiumpremium_3m, premium_6m, premium_12mне передаётсяTelegram-юзернейм
Подарки Telegramgift и gift_id из /giftsне передаётсяTelegram-юзернейм
Подписки на нейросети с ключомneural и code из /neuralне передаётсяне нужен, ключ выдаётся вам
Подписки на нейросети с delivery: redeemneural и code из /neuralтолько 1organization_id аккаунта покупателя в fields
Игровые кодыgame и product_ref из /gamesпакетов кодов, 1…10не нужен, коды выдаются вам

У позиций с delivery: redeem ключа нет: подписку платформа подключает сама на аккаунт покупателя по его organization_id. Какие поля нужны и какие условия аккаунта показать покупателю до оплаты, отдаёт /neural.

Подарочные карты и музыкальные подписки тоже заказываются через свои подкаталоги, по product_ref. Его формат для каждого подкаталога описан в справочнике у метода создания заказа.

#Проверка получателя

GET /check-recipient бесплатен и не трогает депозит. Неверный получатель срывает доставку с кодом recipient_invalid, и проверка до оплаты отсекает такой заказ дешевле всего.

GET /api/reseller/v1/check-recipient
curl -G https://hexpay.live/api/reseller/v1/check-recipient \
  -H "Authorization: Bearer $HEX_API_KEY" \
  --data-urlencode "product=premium_3m" \
  --data-urlencode "username=buyer_username"
status бывает ok, not_found и premium_already. Для neural и game получателя нет, на них метод ответит 400 с error_code: no_recipient.

#Заказ в две фазы

Первый запрос фиксирует цену, второй списывает депозит. Между ними у вас точная сумма, которую можно показать покупателю.

POST /api/reseller/v1/order/create
curl https://hexpay.live/api/reseller/v1/order/create \
  -H "Authorization: Bearer $HEX_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "custom_id": "a4cee2fe-ce8c-448b-bf2c-000000000001",
    "product": "stars",
    "recipient_username": "buyer_username",
    "quantity": 100
  }'
custom_id придумываете вы, удобнее всего UUID. Цена держится до expires_at, потом неоплаченный заказ отменяется, и его создают заново с новым custom_id.
POST /api/reseller/v1/order/pay
curl https://hexpay.live/api/reseller/v1/order/pay \
  -H "Authorization: Bearer $HEX_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"custom_id": "a4cee2fe-ce8c-448b-bf2c-000000000001"}'
Первая оплата отвечает 202: деньги списаны, доставка идёт. Повтор того же запроса отвечает 200 без price_charged_rub, только со статусом. Успехом считайте оба кода. Наличие проверяется дважды: на create и на pay. Если позиция кончилась, пока заказ ждал оплаты, pay ответит 409 с error_code: out_of_stock, депозит не тронут.

#Опрос статуса

Опрашивайте GET /order/{custom_id} до конечного статуса, даже если подключили вебхук. Вебхук может не дойти, и источником истины остаётся опрос.

Статусы заказа
statusЧто значитКонечный
createdцена зафиксирована, депозит не списаннет
pendingоплачен, ждёт доставкинет
processingдоставляетсянет
deliveredдоставленда
failedдоставка не удалась, депозит возвращёнда
cancelledистёк неоплаченным или отменён вручнуюда, обрабатывайте как failed
rejectedна оплате не хватило депозита, списания не былода
poll_order.py
import os
import time

import requests

API = "https://hexpay.live/api/reseller/v1"
HEADERS = {"Authorization": f"Bearer {os.environ['HEX_API_KEY']}"}
FINAL = {"delivered", "failed", "cancelled", "rejected"}


def wait_order(custom_id: str, pause: int = 5) -> dict:
    while True:
        r = requests.get(f"{API}/order/{custom_id}", headers=HEADERS, timeout=15)
        if r.status_code == 429:
            time.sleep(int(r.headers.get("Retry-After", pause)))
            continue
        r.raise_for_status()
        order = r.json()
        if order["status"] in FINAL:
            return order
        time.sleep(pause)

Верхней границы по времени в цикле нет намеренно. У асинхронных товаров доставка идёт минутами и часами, а иногда ждёт действия покупателя. Для них приходят поля delivery_state, action_required и eta_seconds, а свой таймаут превратил бы живой заказ в возврат денег за товар, который ещё придёт.

Пауза 5 секунд на один заказ это 12 запросов в минуту из 60. Если в доставке одновременно десяток заказов, опрашивайте их одним проходом и с паузой длиннее.

#Где лежит товар

Результат приходит в delivered_payload. У звёзд, Premium и подарков там подтверждение: товар ушёл получателю сам. У нейросетей с ключом в поле key лежит сам товар, рядом приходит activation_guide с инструкцией. У позиций с delivery: redeem там только activated: true: подписка уже на аккаунте покупателя. У игровых кодов это массив codes. Ключ и коды вы передаёте покупателю сами.

GET /api/reseller/v1/order/{custom_id}
{
  "success": true,
  "custom_id": "a4cee2fe-ce8c-448b-bf2c-000000000001",
  "status": "delivered",
  "product": "stars",
  "recipient": "buyer_username",
  "quantity": 100,
  "price_quoted_nano": 132070,
  "price_charged_nano": 132070,
  "delivered_payload": {
    "tx_hash": "37ada9160f7870a33fc8"
  },
  "refunded": false,
  "created_at": "2026-08-21T12:00:00Z",
  "completed_at": "2026-08-21T12:00:41Z"
}
Ответ сокращён до полей доставленного заказа звёзд.

Если поставщик выдал меньше кодов, чем заказано, статус остаётся delivered, а разница возвращается на депозит. Количество для покупателя берите из delivered_payload.delivered_quantity: в quantity лежит то, что вы заказали.

#Суммы в nano

У каждой суммы два поля: *_rub для показа и *_nano для арифметики, где 1 ₽ = 1000 nano. Складывайте total_to_pay_nano, price_charged_nano и refund_amount_nano в целых и округляйте один раз на выводе. С float копейки разойдутся с балансом уже на второй сотне заказов.

#Коды ответов

Коды ответов при создании и оплате заказа
HTTPГдеЧто значит
400createошибка валидации, например invalid_quantity или invalid_order_data
401все методыAPI не принял ключ
402payне хватило депозита, заказ в статусе rejected, списания не было
404pay, /order/{custom_id}заказ не найден
409createпозиции нет в наличии, заказ не создан
409payзаказ отменён или отклонён, либо позиция кончилась (out_of_stock), депозит не тронут
429все методылимит запросов, ждите Retry-After
503createтовар временно недоступен

У заказа в failed есть машиночитаемый error_code. Ветвитесь по нему, а не по тексту error_message. Полная таблица кодов с пометкой, вернулись ли деньги и стоит ли повторять, есть в статье про идемпотентность и вебхуки.

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

Если код за вас пишет нейросеть, отдайте ей бриф из справочника, раздел «Для ИИ-агента». Что ещё вписать в задание, чтобы она не списала депозит дважды, написано в статье про интеграцию руками агента.

#Чек-лист

Следующий шаг

Первый заказ на минимальную сумму

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

Читать дальше

Идемпотентность, вебхуки и ретраи: как не потерять деньги

Что делать с таймаутом, повтором и вебхуком, чтобы не списать депозит дважды.

API · DigitalИнтеграция5 мин
Интеграция платного API руками нейросети: что дать агенту и где он сожжёт депозит

Если код пишет агент: что дать ему на входе и что проверить.

APIИнтеграция3 мин
API для продажи Telegram Stars и Premium: кому это нужно

Нужен ли вам API или хватит магазина в боте.

API · DigitalЗапуск3 мин
Собираем анонимную аналитику посещений. Подробнее