API для разработчиков
Принимайте оплату в крипте из любого своего проекта: сайта, магазина, Telegram-бота, бота для стримеров. Вы создаёте платёж одним запросом, отдаёте клиенту ссылку на готовую страницу оплаты, а TipBit сам следит за сетью, подтверждает транзакцию и присылает webhook. Деньги зачисляются на ваш баланс в кабинете — их можно вывести на карту или в крипте.
GET /api/public/api-docs.Аутентификация
Каждый запрос к API подписывается ключом в заголовке X-Api-Key. Ключ
создаётся в кабинете, в разделе «Для разработчиков»:
там же его можно отозвать.
- Полный ключ показывается один раз — сразу после создания. В списке остаётся только префикс.
- Держите ключ в переменных окружения проекта или в секретах хостинга. В браузере и в Git его быть не должно.
- Один ключ — один проект: так проще отозвать доступ, если ключ утёк.
- Отзыв действует сразу: запросы с отозванным ключом получают
401.
GET https://tipbit.click/api/v1/me X-Api-Key: tb_live_xxxxxxxxxxxxxxxxxxxxxxxx Accept: application/json
Быстрый старт
Платёж — это один POST. В ответ приходят ссылка на оплату, адрес, QR и срок действия.
curl -X POST https://tipbit.click/api/v1/payments \
-H "X-Api-Key: $TIPBIT_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"amount": 500,
"currency": "RUB",
"description": "Подписка на месяц",
"externalId": "order-1042",
"callbackUrl": "https://example.com/tipbit/webhook"
}'
// Node.js 22+ — fetch встроен, зависимости не нужны
const API = 'https://tipbit.click/api/v1/payments';
export async function createPayment(order) {
const res = await fetch(API, {
method: 'POST',
headers: {
'X-Api-Key': process.env.TIPBIT_API_KEY,
'Content-Type': 'application/json',
},
body: JSON.stringify({
amount: order.amount,
currency: order.currency || 'RUB',
description: order.title,
externalId: order.id,
callbackUrl: 'https://example.com/tipbit/webhook',
}),
});
if (!res.ok) throw new Error('TipBit: ' + res.status + ' ' + await res.text());
return res.json(); // { id, status, payUrl, address, qrSvg, expiresAt, ... }
}
Как проходит платёж
- Создание. Вы вызываете
POST /api/v1/paymentsи получаетеpayUrl— готовую страницу оплаты, где клиент выбирает сеть и видит QR. - Оплата. Клиент платит по адресу из ответа. Для TON и других сетей с меткой
memoплатформа подставляет её сама — в QR и на странице оплаты. - Подтверждение. Индексер видит транзакцию в сети, ждёт подтверждений и переводит платёж в
paid. - Webhook. На ваш
callbackUrlприходит событие с итоговым статусом и подписью. Ответ 2xx считается доставкой; иначе платформа повторяет попытку. - Зачисление. Сумма (за вычетом комиссии платформы) попадает на ваш баланс в кабинете.
| Статус | Что значит | Что делать |
|---|---|---|
| pending | Платёж создан, оплаты ещё нет | Показать клиенту payUrl и QR |
| processing | Транзакция в сети, ждём подтверждений | Ничего, дождаться webhook |
| paid | Оплата подтверждена и зачислена | Выдать заказ, закрыть заявку |
| expired | Срок действия истёк, оплаты не было | Создать новый платёж |
| cancelled | Платёж отменён вами | Создать новый, если заказ ещё нужен |
GET /api/v1/payments/<id>.Справочник эндпоинтов
Базовый адрес: https://tipbit.click
Готовая страница оплаты
Не нужно рисовать QR и объяснять клиенту, куда переводить: в ответе на создание
платежа есть payUrl — это страница TipBit с суммой, адресом, QR-кодом,
таймером и выбором сети. Её содержимое отдаёт публичная ручка
GET /api/public/pay/<id>: статус, сумма, актив, сеть, адрес, метка,
QR (SVG), срок действия и имя получателя.
- Ссылку можно открыть на телефоне, встроить в Telegram-бот или показать в приложении.
- Страница сама обновляет статус: клиенту не нужно перезагружать её после оплаты.
- Если платёж отменён или просрочен — на странице это видно, повторной оплаты по старому адресу не будет.
Webhook: событие об оплате
Укажите callbackUrl при создании платежа — платформа отправит
POST с JSON, когда статус изменится. Отвечайте 2xx; иначе
попытка повторится. Всегда перепроверяйте подпись: тело запроса можно подделать.
{
"event": "payment.paid",
"id": "pay_8f3a1c9e",
"externalId": "order-1042",
"status": "paid",
"amount": 500,
"currency": "RUB",
"asset": "USDT-TRC20",
"network": "tron",
"amountFiat": 500,
"txid": "0x…",
"paidAt": 1731065400000
}
Проверка подписи — Node.js
import crypto from 'node:crypto';
// Секрет webhook — из кабинета (раздел «Для разработчиков»)
const SECRET = process.env.TIPBIT_WEBHOOK_SECRET;
const HEADER = 'x-tipbit-signature';
export function verifyTipBit(rawBody, headers) {
const got = String(headers[HEADER] || '').trim();
if (!got || !SECRET) return false;
const expected = crypto.createHmac('sha256', SECRET).update(rawBody).digest('hex');
// Сравнение постоянного времени: обычное === утекает по таймингу
const a = Buffer.from(got);
const b = Buffer.from(expected);
return a.length === b.length && crypto.timingSafeEqual(a, b);
}
Проверка подписи — Python
import hmac, hashlib, os
SECRET = os.environ["TIPBIT_WEBHOOK_SECRET"].encode()
HEADER = "x-tipbit-signature"
def verify_tipbit(raw_body: bytes, headers: dict) -> bool:
got = (headers.get(HEADER) or "").strip()
if not got:
return False
expected = hmac.new(SECRET, raw_body, hashlib.sha256).hexdigest()
# compare_digest — сравнение постоянного времени
return hmac.compare_digest(got, expected)
/api/public/api-docs (поле webhook) — если оно отличается от примера, доверяйте ответу сервера: пример выше показывает схему проверки, а не заменяет контракт.Пример: Telegram-бот принимает оплату
Бот на Node.js без зависимостей: команда /buy создаёт платёж и присылает
клиенту ссылку на оплату. Оплата засчитывается по webhook — бот не должен доверять
сообщениям пользователя о том, что он «уже заплатил».
// Node.js 22+, без npm-зависимостей
const TG = 'https://api.telegram.org/bot' + process.env.TG_TOKEN;
const API = 'https://tipbit.click/api/v1/payments';
async function onMessage(msg) {
if (msg.text !== '/buy') return;
const res = await fetch(API, {
method: 'POST',
headers: { 'X-Api-Key': process.env.TIPBIT_API_KEY, 'Content-Type': 'application/json' },
body: JSON.stringify({
amount: 500,
currency: 'RUB',
description: 'Подписка на месяц',
externalId: 'tg-' + msg.from.id + '-' + Date.now(),
callbackUrl: 'https://example.com/tipbit/webhook',
}),
});
const pay = await res.json();
await fetch(TG + '/sendMessage', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
chat_id: msg.chat.id,
text: 'Оплата 500 ₽: ' + pay.payUrl,
disable_web_page_preview: false,
}),
});
}
// long polling: getUpdates → onMessage (полный цикл — 10 строк)
let offset = 0;
for (;;) {
const r = await fetch(TG + '/getUpdates?timeout=30&offset=' + offset).then((x) => x.json());
for (const u of r.result || []) {
offset = u.update_id + 1;
if (u.message) await onMessage(u.message);
}
}
Ошибки
Ошибка всегда приходит JSON-ом: { "error": "текст", "code": "машинный_код" }. Ориентируйтесь на HTTP-статус и поле code, а не на текст.
| HTTP | code | Что значит | Что делать |
|---|---|---|---|
| 400 | invalid_request | Нет поля, неверная сумма или валюта | Проверить тело запроса по справочнику |
| 401 | unauthorized | Ключ не передан, отозван или неверный | Проверить X-Api-Key и не отозван ли ключ |
| 403 | forbidden | Ключ без нужных прав или аккаунт заблокирован | Создать ключ заново / связаться с поддержкой |
| 404 | not_found | Платёж с таким id не найден | Проверить id из ответа на создание |
| 409 | conflict | Платёж уже оплачен или отменён | Не менять финальный статус, создать новый |
| 429 | rate_limited | Слишком много запросов | Подождать и повторить с задержкой |
| 500 | server_error | Внутренняя ошибка (в ответе есть ref) | Повторить позже; ref подскажет поддержке, где искать |
Комиссии и лимиты
- Комиссия платформы удерживается при зачислении платежа. Ставка задаётся администратором по каждому активу, поэтому точное значение — в кабинете и в ответах API, а не в этой странице.
- Минимальная сумма зависит от сети: у разных активов она разная (нужна, чтобы комиссия сети не съела платёж). Запрос с суммой ниже минимума вернёт
400. - Срок действия платежа задаётся параметром
expiresInMinпри создании; после истечения платёж переходит вexpired. - Лимит запросов считается по ключу: при превышении вернётся
429. - Вывод средств — отдельный сценарий кабинета (карта, PayPal/Wise или крипта) с 2FA и подтверждением администратора. API создаёт платежи на приём, а не выводит деньги.
Создайте ключ в кабинете — он показывается один раз, поэтому держите его под рукой.