BatonPay/Документация API

Payment · Cashier · Withdraw · Webhook

BatonPay API

Полное руководство по интеграции: Payment API, кассы, webhook и вывод средств в TON и Jetton.

Payment API

https://pay.baton-token.com/api/backend

Withdraw API

https://pay.baton-token.com/api/withdraw

Версия: 1.0 · Формат: JSON

Введение

BatonPay — приём платежей в TON и Jetton с webhook и кабинетом мерчанта.

System architecture

Основные возможности

  • Приём платежей в TON и Jetton
  • Автоматическое отслеживание транзакций в блокчейне
  • Webhook с опциональной HMAC-подписью
  • Несколько касс, лимиты, категории
  • Вывод средств через Withdraw API
  • Статистика и экспорт CSV/HTML

Как это работает

  1. Создайте кассу и настройте webhook
  2. Создайте платёж (API или ссылка на страницу оплаты)
  3. Для каждого платежа выдаётся уникальный TON-адрес — пользователь переводит точную сумму
  4. После подтверждения баланс кассы обновляется, средства доступны к выводу
  5. На webhook кассы приходит уведомление о статусе

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

API-токен выдаётся после регистрации. В кабинете: дашборд → блок «API токен» (нужен пароль для показа). Токен нужен для касс, выводов и чтения данных касс. Webhook secret — в настройках конкретной кассы.

Данные кассы (включая webhook_secret) отдаются только при передаче user_id и api_token владельца в query или теле запроса.

В теле запроса (POST/PUT):

{
  "user_id": 1,
  "api_token": "your_api_token",
  "name": "My cashier"
}

В query (GET):

GET https://pay.baton-token.com/api/backend/cashiers/1?api_token=your_api_token

Базовый URL

СервисURL
Payment APIhttps://pay.baton-token.com/api/backend
Withdraw APIhttps://pay.baton-token.com/api/withdraw
Страница оплатыhttps://pay.baton-token.com/payment

Валюта и суммы

  • ton / jetton — валюта кассы и платежа
  • Минимум обычно 0.01, лимиты задаются в настройках кассы
  • Не более 2 десятичных знаков в сумме

Payment API

API для создания платежей и проверки статуса.

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

POSThttps://pay.baton-token.com/api/backend/create_payment

Для TON на каждый платёж создаётся уникальный адрес (wallet_to_send). Параметр wallet не нужен. После оплаты баланс кассы обновляется. Для Jetton по-прежнему указывается адрес плательщика.

ПараметрТипОбяз.Описание
cashier_idintegerДаID кассы
amountfloatДаСумма (≥ min_amount кассы, ≤ max_amount)
currencystringНетton | jetton (иначе из кассы)
walletstringНетТолько Jetton: адрес кошелька плательщика
payloadstringНетДанные для webhook
transaction_uuidstringНетUUID для восстановления платежа
return_urlstringНетРедирект после успешной оплаты

Пример

import requests

r = requests.post("https://pay.baton-token.com/api/backend/create_payment", json={
    "cashier_id": 1,
    "amount": 10.5,
    "currency": "ton",
    "payload": "order_id=12345",
    "return_url": "https://example.com/success"
})
print(r.json())

Ответ (успех)

{
  "status": "ok",
  "payment_id": 123,
  "transaction_uuid": "550e8400-e29b-41d4-a716-446655440000",
  "currency": "ton",
  "amount": 10.5,
  "wallet_to_send": "UQ...",
  "return_url": "https://example.com/success",
  "time_recorded": 1704067200000
}

Получение по UUID

GEThttps://pay.baton-token.com/api/backend/payment_by_uuid/{transaction_uuid}

Возвращает данные платежа для восстановления сессии оплаты.

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

GEThttps://pay.baton-token.com/api/backend/payment_status/{currency}/{payment_id}

Статусы: pending, success, error, nohash и др.

Cashier API

Управление платёжными кассами.

Создание кассы

POSThttps://pay.baton-token.com/api/backend/create_cashier
ПараметрТипОбяз.Описание
user_idintegerДаID пользователя
api_tokenstringДаAPI токен
namestringДаНазвание кассы
descriptionstringНетОписание
categorystringНетКатегория (shop, bot, …)
webhook_urlstringРек.URL для webhook
currencystringНетton | jetton
min_amountfloatНетМин. сумма (по умолч. 0.01)
max_amountfloatНетМакс. сумма
jetton_addressstringУсл.Адрес Jetton-мастера

Не передаётся в запросе — генерируется сервером, см. ответ

Фрагмент ответа create_cashier:

{
  "status": "ok",
  "cashier_id": 1,
  "cashier": {
    "id": 1,
    "webhook_url": "https://example.com/hook",
    "webhook_secret": "xYz…_auto_generated",
    ...
  }
}

Список касс

GEThttps://pay.baton-token.com/api/backend/cashiers/{user_id}?api_token=...

Информация о кассе

GEThttps://pay.baton-token.com/api/backend/cashier/{cashier_id}?user_id=...&api_token=...

Только владелец: обязательны query user_id и api_token. В ответе cashier — все поля, включая webhook_secret (для HMAC).

Изменение статуса

POSThttps://pay.baton-token.com/api/backend/cashier/{id}/status

Статусы: active, inactive.

Ротация webhook secret

POSThttps://pay.baton-token.com/api/backend/cashier/{cashier_id}/rotate_webhook_secret
ПараметрТипОбяз.Описание
user_idintegerДаID пользователя
api_tokenstringДаAPI токен

Выпускает новый webhook_secret; старый сразу недействителен. Обновите секрет в коде проверки HMAC на endpoint, который принимает webhook.

Рекомендуется для всех касс, созданных до закрытия публичного доступа к GET /cashier/{id}. В кабинете: кнопка «Сменить webhook secret».
POST https://pay.baton-token.com/api/backend/cashier/1/rotate_webhook_secret?user_id=1&api_token=TOKEN

{
  "status": "ok",
  "message": "Webhook secret rotated",
  "webhook_secret": "new_secret_value",
  "cashier": { ... }
}

В веб-кабинете: касса → вкладка «Настройки» или обзор Webhook → «Сменить webhook secret» (POST /api/cashiers/rotate-webhook с сессией).

Удаление кассы

DELETEhttps://pay.baton-token.com/api/backend/cashier/{id}?user_id=...&api_token=...

DELETE /cashier/{id}?user_id=…&api_token=… — удаление кассы (только владелец).

Обновление настроек

PUThttps://pay.baton-token.com/api/backend/cashier/{id}

Обновление name, description, category, min/max_amount, webhook_url, jetton_address.

PUT https://pay.baton-token.com/api/backend/cashier/1
Content-Type: application/json

{
  "user_id": 1,
  "api_token": "TOKEN",
  "name": "New name",
  "webhook_url": "https://example.com/hook"
}

Withdraw API

Вывод средств с касс.

Withdrawal

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

POSThttps://pay.baton-token.com/api/withdraw/withdraw
ПараметрТипОбяз.Описание
cashier_idintegerДаID кассы
amountfloatДаСумма (≥ 0.01)
walletstringДаАдрес получателя
api_tokenstringДаAPI токен
Поля: cashier_id, amount, wallet, api_token. user_id в теле не нужен — определяется по кассе. Баланс кассы должен покрывать сумму; для TON с сети удерживается комиссия (~0.007 TON). Для Jetton нужен TON на комиссию.

Frontend Integration

TON

Платёж через URL

https://pay.baton-token.com/payment?cashier_id=1&amount=10.50&payload=order_123&return_url=https://your-site.com/done

Страница создаёт платёж, показывает уникальный адрес и QR, таймер 20 минут и опрос статуса. Кошелёк плательщика указывать не нужно (TON).

Параметры: cashier_id и amount (обяз.), payload (в webhook), return_url (редирект), transaction_uuid (восстановить сессию).

Webhook уведомления

POST на webhook_url кассы при смене статуса:

{
  "payment_id": 123,
  "status": "success",
  "currency": "ton",
  "payload": "order_id=12345"
}

HMAC подпись

Секрет webhook_secret создаётся при создании кассы. Просмотр: кабинет → касса → «Настройки» или GET /cashier/{id}?user_id=…&api_token=…. Ротация: POST /cashier/{id}/rotate_webhook_secret (или кнопка в кабинете). После смены секрета обновите проверку HMAC на своём сервере. Подпись в заголовке X-Webhook-Signature: sha256=…; без заголовка HMAC не проверяется.

Проверка: заголовок X-Webhook-Signature: sha256=… — HMAC-SHA256 от сырого тела запроса (JSON с отсортированными ключами и без пробелов, как в примере). Подписывается именно то тело, которое приходит в POST.

import hmac, hashlib, json

def verify(body: str, header: str, secret: str) -> bool:
    payload = json.loads(body)
    canonical = json.dumps(payload, sort_keys=True, separators=(',', ':'))
    expected = hmac.new(secret.encode(), canonical.encode(), hashlib.sha256).hexdigest()
    received = header.replace('sha256=', '')
    return hmac.compare_digest(expected, received)

Проверка статуса с фронтенда

const res = await fetch(
  `https://pay.baton-token.com/api/backend/payment_status/ton/${paymentId}?t=${Date.now()}`
);
const data = await res.json();

Примеры

Python

import requests

API = "https://pay.baton-token.com/api/backend"
TOKEN = "your_token"
UID = 1

pay = requests.post(f"{API}/create_payment", json={
    "cashier_id": 1, "amount": 1.0
}).json()

st = requests.get(f"{API}/payment_status/ton/{pay['payment_id']}").json()
print(st)

PHP

<?php
$ch = curl_init('https://pay.baton-token.com/api/backend/create_payment');
curl_setopt_array($ch, [
  CURLOPT_POST => true,
  CURLOPT_RETURNTRANSFER => true,
  CURLOPT_HTTPHEADER => ['Content-Type: application/json'],
  CURLOPT_POSTFIELDS => json_encode([
    'cashier_id' => 1,
    'amount' => 1.0,
  ]),
]);
echo curl_exec($ch);

JavaScript

const res = await fetch('https://pay.baton-token.com/api/backend/create_payment', {
  method: 'POST',
  headers: { 'Content-Type': 'application/json' },
  body: JSON.stringify({
    cashier_id: 1,
    amount: 1.0,
  }),
});
console.log(await res.json());

Обработка ошибок

КодОписание
200Успех
400Неверные параметры
401Неверный API токен
403Нет доступа к ресурсу
404Не найдено
500Ошибка сервера
{ "detail": "Amount is less than minimum: 0.01" }

Нужна помощь? напишите в чат