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 и кабинетом мерчанта.
Основные возможности
- Приём платежей в TON и Jetton
- Автоматическое отслеживание транзакций в блокчейне
- Webhook с опциональной HMAC-подписью
- Несколько касс, лимиты, категории
- Вывод средств через Withdraw API
- Статистика и экспорт CSV/HTML
Как это работает
- Создайте кассу и настройте webhook
- Создайте платёж (API или ссылка на страницу оплаты)
- Для каждого платежа выдаётся уникальный TON-адрес — пользователь переводит точную сумму
- После подтверждения баланс кассы обновляется, средства доступны к выводу
- На 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 API | https://pay.baton-token.com/api/backend |
| Withdraw API | https://pay.baton-token.com/api/withdraw |
| Страница оплаты | https://pay.baton-token.com/payment |
Валюта и суммы
- ton / jetton — валюта кассы и платежа
- Минимум обычно 0.01, лимиты задаются в настройках кассы
- Не более 2 десятичных знаков в сумме
Payment API
API для создания платежей и проверки статуса.
Создание платежа
https://pay.baton-token.com/api/backend/create_paymentДля TON на каждый платёж создаётся уникальный адрес (wallet_to_send). Параметр wallet не нужен. После оплаты баланс кассы обновляется. Для Jetton по-прежнему указывается адрес плательщика.
| Параметр | Тип | Обяз. | Описание |
|---|---|---|---|
| cashier_id | integer | Да | ID кассы |
| amount | float | Да | Сумма (≥ min_amount кассы, ≤ max_amount) |
| currency | string | Нет | ton | jetton (иначе из кассы) |
| wallet | string | Нет | Только Jetton: адрес кошелька плательщика |
| payload | string | Нет | Данные для webhook |
| transaction_uuid | string | Нет | UUID для восстановления платежа |
| return_url | string | Нет | Редирект после успешной оплаты |
Пример
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
https://pay.baton-token.com/api/backend/payment_by_uuid/{transaction_uuid}Возвращает данные платежа для восстановления сессии оплаты.
Статус платежа
https://pay.baton-token.com/api/backend/payment_status/{currency}/{payment_id}Статусы: pending, success, error, nohash и др.
Cashier API
Управление платёжными кассами.
Создание кассы
https://pay.baton-token.com/api/backend/create_cashier| Параметр | Тип | Обяз. | Описание |
|---|---|---|---|
| user_id | integer | Да | ID пользователя |
| api_token | string | Да | API токен |
| name | string | Да | Название кассы |
| description | string | Нет | Описание |
| category | string | Нет | Категория (shop, bot, …) |
| webhook_url | string | Рек. | URL для webhook |
| currency | string | Нет | ton | jetton |
| min_amount | float | Нет | Мин. сумма (по умолч. 0.01) |
| max_amount | float | Нет | Макс. сумма |
| jetton_address | string | Усл. | Адрес Jetton-мастера |
Не передаётся в запросе — генерируется сервером, см. ответ
Фрагмент ответа create_cashier:
{
"status": "ok",
"cashier_id": 1,
"cashier": {
"id": 1,
"webhook_url": "https://example.com/hook",
"webhook_secret": "xYz…_auto_generated",
...
}
}Список касс
https://pay.baton-token.com/api/backend/cashiers/{user_id}?api_token=...Информация о кассе
https://pay.baton-token.com/api/backend/cashier/{cashier_id}?user_id=...&api_token=...Только владелец: обязательны query user_id и api_token. В ответе cashier — все поля, включая webhook_secret (для HMAC).
Изменение статуса
https://pay.baton-token.com/api/backend/cashier/{id}/statusСтатусы: active, inactive.
Ротация webhook secret
https://pay.baton-token.com/api/backend/cashier/{cashier_id}/rotate_webhook_secret| Параметр | Тип | Обяз. | Описание |
|---|---|---|---|
| user_id | integer | Да | ID пользователя |
| api_token | string | Да | API токен |
Выпускает новый webhook_secret; старый сразу недействителен. Обновите секрет в коде проверки HMAC на endpoint, который принимает webhook.
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 с сессией).
Удаление кассы
https://pay.baton-token.com/api/backend/cashier/{id}?user_id=...&api_token=...DELETE /cashier/{id}?user_id=…&api_token=… — удаление кассы (только владелец).
Обновление настроек
https://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
Вывод средств с касс.
Вывод средств
https://pay.baton-token.com/api/withdraw/withdraw| Параметр | Тип | Обяз. | Описание |
|---|---|---|---|
| cashier_id | integer | Да | ID кассы |
| amount | float | Да | Сумма (≥ 0.01) |
| wallet | string | Да | Адрес получателя |
| api_token | string | Да | API токен |
Frontend Integration
Платёж через 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" }Нужна помощь? напишите в чат