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

Полноценный REST API для интеграции всех функций AlfaBit в ваши приложения.

ℹ️
Структура счетов

Основной счёт — главный кошелёк для пополнений, выводов, переводов. Торговый счёт — общий баланс для биржевой торговли; через API на нём доступен стакан USDT/RUB, крипто-обмен по API идёт с основного счёта.

💡
TIP

Для начала создайте API ключи в разделе Консоль разработчика.

Быстрый старт

Начните работу с API за 5 минут. Этот гайд проведёт вас от создания ключа до первой торговой операции.

1

Создайте API ключ

Перейдите в Консоль разработчика → API Keys → Создать ключ. Выберите нужные права доступа и сохраните Secret Key — он показывается только один раз.

2

Настройте подпись запросов

Каждый запрос подписывается HMAC-SHA256. Скопируйте готовый код из раздела Аутентификация (Python / JavaScript) — он работает из коробки.

3

Проверьте подключение

Отправьте первый запрос — получите профиль аккаунта:

GET /api/v1/integration/account/profile
→ Если видите свой email и ID — всё работает!
4

Посмотрите балансы

Убедитесь, что на счёте есть средства для операций:

GET /api/v1/integration/account/wallets
→ Увидите все кошельки с балансами и адресами для пополнения.
5

Сделайте первую операцию

Выберите что хотите сделать и перейдите к нужному разделу:

Архитектура платформы

Прежде чем начать, важно понять как устроена платформа. Это поможет выбрать правильные эндпоинты и избежать ошибок.

Два типа счетов

💰

Основной счёт (Funding)

Основной счёт. Здесь хранятся все ваши средства. С него выполняются: пополнения, выводы, крипто-обмены, переводы, оплата услуг и карт.

Используется большинством операций
📊

Торговый счёт (Trading)

Общий баланс для биржевой торговли — в терминале личного кабинета с него торгуются все пары. Через API на нём сейчас работает стакан USDT/RUB с market и limit ордерами: перед торговлей переведите средства через /funding/transfer/to-trading. Крипто-пары через API обмениваются мгновенным market-свопом с основного счёта (/integration/spot/crypto) — стакан и лимитные ордера для них по API пока недоступны.

Биржевая торговля
💡
О коде валюты

Код валюты в примерах ниже (например RUB или USDT) показан для иллюстрации структуры запроса. Актуальный список поддерживаемых валют для вашей интеграции согласуется отдельно на этапе подключения.

Способы обмена — когда какой использовать?

МодульЧто этоПубличные курсыТорговляПары
Крипто СпотКрипто-рынки — крипто ↔ криптоGET /spot/crypto/tickers
GET /spot/crypto/market-info
Market / Limit ордераBTC/USDT, ETH/USDT
Фиат СпотБиржевой стакан AlfaBit — крипто ↔ фиатGET /spot/fiat/orderbook
GET /spot/fiat/stats
GET /spot/fiat/instruments
Market / Limit ордераUSDT/RUB
КонвертерМгновенный обмен с фиксированным курсомGET /converter/crypto/rate
GET /converter/fiat/rate
Обмен по котировкеBTC → ETH, USDT → RUB
Публичные данные

Каждый из трёх модулей имеет публичные эндпоинты (курсы, тикеры, стакан), доступные без API ключа — для интеграции виджетов, мониторинга цен и аналитики. Торговые операции (ордера, обмен) требуют API ключ с соответствующими правами.

Общий формат ответа

Все ответы API имеют единый формат. Успешные операции возвращают данные в поле data, ошибки — в поле error:

Успешный ответ
{ "success": true, "data": { ... }, "ts": 1706000000 }
Ответ с ошибкой
{ "success": false, "error": { "code": "...", "message": "..." }, "ts": 1706000000 }

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

Все запросы должны быть подписаны HMAC-SHA256 с использованием секретного ключа.

HTTP Headers

HeaderОбязательныйОписание
X-API-KeyОбяз.Публичный ключ pk_live_xxx
X-API-SignatureОбяз.HMAC-SHA256 подпись
X-API-TimestampОбяз.Unix timestamp (секунды)
X-Device-IdОпциональноИдентификатор устройства / fingerprint (антифрод). Если есть — передавайте.
🛡️
Антифрод-логирование операций

Все запросы, создающие операции (депозиты, выводы, переводы, обмены, инвойсы), логируются на нашей стороне: IP источника запроса, User-Agent и X-Device-Id (если передан). Данные используются для безопасности API-ключей и антифрод-скоринга и не влияют на выполнение операций. Для KYC-API чекаута действуют отдельные обязательные поля payer_ip и external_payment_id (см. раздел «KYC-API чекаут»).

Ограничение по IP

Каждому ключу можно задать список разрешённых адресов — в Консоли разработчика, поле «IP Whitelist» при создании ключа или в его настройках. Пока список пуст, ключ принимается с любого адреса. Как только в нём появляется хотя бы одна запись, запросы со всех остальных адресов отклоняются: HTTP 403, код ошибки IP_NOT_ALLOWED.

Принимаются точный адрес (203.0.113.10), подсеть в нотации CIDR (203.0.113.0/24) и IPv6. Запись вида ::ffff:203.0.113.10 считается тем же адресом, что и 203.0.113.10. Несколько значений перечисляются через запятую, очистка поля снимает ограничение. Сверяется внешний адрес, с которого запрос дошёл до платформы, поэтому для сервера за NAT указывайте его внешний IP, а не адрес внутренней сети.

🔒
Проверка IP выполняется до проверки подписи

IP_NOT_ALLOWED приходит и при полностью корректной подписи — если получаете 403 после смены хостинга или добавления нового сервера, сначала проверьте список адресов ключа. Ограничение по IP — самый надёжный способ обезопасить ключ: даже утёкший секрет бесполезен с чужого адреса. Для боевых интеграций указывайте его всегда.

Формула подписи

Formula
message = timestamp + method + path + body
signature = HMAC-SHA256(secret_key, message)

Примеры кода

Python
import hmac, hashlib, time, requests, json

API_KEY = "pk_live_xxxxxxxxxxxxx"
SECRET_KEY = "sk_live_xxxxxxxxxxxxx"
BASE_URL = "https://alfabit.org"

def sign_request(method, path, body=""):
    timestamp = str(int(time.time()))
    message = f"{timestamp}{method.upper()}{path}{body}"
    signature = hmac.new(
        SECRET_KEY.encode(), message.encode(), hashlib.sha256
    ).hexdigest()
    return {
        "X-API-Key": API_KEY,
        "X-API-Signature": signature,
        "X-API-Timestamp": timestamp,
        "Content-Type": "application/json"
    }

# Получить балансы кошельков
path = "/api/v1/integration/account/wallets"
resp = requests.get(f"{BASE_URL}{path}", headers=sign_request("GET", path))
print(resp.json())
# {"success": true, "data": [{"symbol": "USDT", "available": "1250.00", ...}], "ts": 1706000000}

# Создать ордер на крипто обмен
path = "/api/v1/integration/spot/crypto/order"
body = json.dumps({"from_symbol": "USDT", "to_symbol": "BTC", "from_amount": "100"})
resp = requests.post(f"{BASE_URL}{path}", headers=sign_request("POST", path, body), data=body)
print(resp.json())

Лимиты запросов

Лимит запросов настраивается индивидуально для каждого API ключа. Значение задаётся при создании ключа (поле rate_limit_per_minute). При превышении лимита API вернёт ошибку 429.

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

Error Response
{
  "success": false,
  "error": {
    "code": "INVALID_SIGNATURE",
    "message": "Invalid request signature",
    "details": null
  },
  "ts": 1706000000
}
CodeHTTPОписание
INVALID_API_KEY401Неверный API ключ
INVALID_SIGNATURE401Неверная подпись
SIGNATURE_EXPIRED401Timestamp устарел (>5 мин)
API_KEY_EXPIRED401Срок действия ключа истёк
API_KEY_INACTIVE401Ключ отключён владельцем
IP_NOT_ALLOWED403Адрес запроса не входит в список разрешённых IP ключа
PERMISSION_DENIED403Нет доступа
INSUFFICIENT_BALANCE400Недостаточно средств
DEEP_PAGINATION_NOT_SUPPORTED400Слишком глубокая страница ленты транзакций (page × limit > 2000) — сузьте период

Ошибки стакана (Фиатный Спот)

Отказы POST /spot/fiat/order, DELETE /spot/fiat/order/{id} и переводов торгового счёта приходят отдельным кодом, а числа для решения — в details. Пишите логику на code, а не на текст сообщения: message и details.reason_text могут меняться.

Insufficient liquidity (market buy by quote_amount)
{
  "success": false,
  "error": {
    "code": "INSUFFICIENT_LIQUIDITY",
    "message": "Not enough counter liquidity in the orderbook to fill this market order",
    "details": {
      "quote_amount": "3041.770000",
      "quote_currency": "RUB",
      "available_liquidity": "0.654719",
      "base_currency": "USDT",
      "min_order_size": "1.000000",
      "reason": "available_liquidity_below_min_order_size",
      "hint": "Retry later, reduce the order, or place a limit order to wait in the book."
    }
  },
  "ts": 1706000000
}
CodeHTTPОписаниеЧто делать
INSUFFICIENT_LIQUIDITY400Встречной стороны стакана не хватает на ваш рыночный ордер: либо она пуста, либо остатка меньше минимального лота. details: available_liquidity, min_order_size, reason.Повторить позже, уменьшить ордер или поставить лимитный — увеличение ордера тут не помогает.
ORDER_BELOW_MIN_SIZE400Присланный amount меньше минимального лота пары. details.min_order_size.Увеличить amount до min_order_size.
ORDER_ABOVE_MAX_SIZE400Ордер больше максимального для пары. details.max_order_size.Разбить на несколько ордеров.
ORDER_BELOW_MIN_VALUE400Сумма ордера (amount × price) меньше минимальной. details.min_order_value.Увеличить amount или price.
QUOTE_AMOUNT_TOO_SMALL400quote_amount не покрывает даже минимальный лот пары.Увеличить quote_amount, лимиты — в GET /spot/fiat/market-info.
PRICE_OUT_OF_BAND400Лимитная цена слишком далеко от рыночной. details: allowed_price_min, allowed_price_max.Поставить цену внутрь диапазона из details.
PRICE_NOT_ON_TICK400Цена не кратна шагу цены пары. details.price_step.Округлить цену до price_step.
PRICE_REFERENCE_UNAVAILABLE400Нет рыночного ориентира, чтобы проверить лимитную цену.Повторить через несколько секунд.
INSUFFICIENT_BALANCE400Не хватает средств на торговом счёте. details: currency, required, available, account.Пополнить: POST /funding/transfer/to-trading.
BALANCE_LOCK_FAILED400Баланс изменился параллельно с приёмом ордера.Перечитать баланс и повторить с новым Idempotency-Key.
PAIR_NOT_FOUND400Такой пары нет. details.pair.Взять пару из GET /spot/fiat/instruments.
PAIR_NOT_ACTIVE400Пара временно закрыта. details: pair, pair_status.Дождаться статуса active в GET /spot/fiat/instruments.
ORDER_NOT_FOUND404Ордер с таким id не найден.Проверить id в GET /spot/fiat/orders.
ORDER_ACCESS_DENIED403Ордер принадлежит другому аккаунту.Проверить id и API-ключ.
ORDER_NOT_CANCELLABLE400Ордер уже исполнен или отменён. details.order_status.Считать финальное состояние: GET /spot/fiat/order/{id}.
INVALID_ORDER_REQUEST400Некорректное тело запроса. details.field.Сверить поля с документацией.
STOCKBOOK_ERROR4xx / 5xxОтказ, который пока не разложен на код. details: upstream_status, reason_text, upstream_body (устаревшее поле, оставлено для совместимости).Повторить позже; при повторе прислать reason_text в поддержку.
STOCKBOOK_UNAVAILABLE502Торговая система недоступна (сеть/таймаут).Повторить через несколько секунд с тем же Idempotency-Key.

Аккаунт

Профиль пользователя и управление криптовалютными кошельками. Просмотр балансов, создание кошельков и получение депозитных адресов.

Типичный сценарий

При первом подключении начните с GET /account/profile чтобы убедиться, что аутентификация работает. Затем получите список кошельков через GET /account/wallets. Если нужного кошелька нет — создайте его через POST /account/wallets (это также вернёт депозитный адрес).

GET/api/v1/integration/account/wallets

Возвращает список всех кошельков пользователя с балансами и адресами для пополнения. Если кошелёк ещё не создан для валюты — он не будет в списке.

Response
{
  "success": true,
  "data": [
    {
      "symbol": "USDT",
      "is_active": true,
      "balance": "1250.00",
      "available": "1250.00",
      "pending_deposit": "0.00",
      "pending_withdraw": "0.00",
      "balance_usdt": "1250.00",
      "balance_source": "ledger",
      "addresses": [
        { "network": "TRX", "address": "TQn9Y2khEsLJW1ChVWFMSMeRDow5KcbLSE" },
        { "network": "ETH", "address": "0x742d35Cc6634C0532925a3b..." }
      ]
    },
    {
      "symbol": "BTC",
      "is_active": true,
      "balance": "0.05432100",
      "available": "0.05432100",
      "pending_deposit": "0.00",
      "pending_withdraw": "0.00",
      "balance_usdt": "2150.50",
      "balance_source": "ledger",
      "addresses": []
    }
  ],
  "ts": 1706000000
}
GET/api/v1/integration/account/wallets/{symbol}

Возвращает баланс и адреса конкретной валюты. Если кошелёк не найден — вернёт 404.

Response
{
  "success": true,
  "data": {
    "symbol": "USDT",
    "is_active": true,
    "balance": "1250.00",
    "available": "1250.00",
    "pending_deposit": "0.00",
    "pending_withdraw": "0.00",
    "balance_usdt": "1250.00",
    "balance_source": "ledger",
    "addresses": [
      { "network": "TRX", "address": "TQn9Y2khEsLJW1ChVWFMSMeRDow5KcbLSE" }
    ]
  },
  "ts": 1706000000
}
POST/api/v1/integration/account/wallets

Создаёт кошелёк для указанной валюты и сети. Если кошелёк уже существует — вернёт существующий с адресом для пополнения. Используйте для получения депозитного адреса.

Request
{
  "symbol": "USDT",
  "network": "TRX"
}
Response
{
  "success": true,
  "data": {
    "symbol": "USDT",
    "available": "0.00",
    "addresses": [
      { "network": "TRX", "address": "TQn9Y2khEsLJW1ChVWFMSMeRDow5KcbLSE" }
    ]
  },
  "ts": 1706000000
}
GET/api/v1/integration/account/profile

Возвращает информацию о профиле: ID, email, статус KYC, тариф.

Response
{
  "success": true,
  "data": {
    "id": 12345,
    "username": "john_doe",
    "email": "john@example.com",
    "email_verified": null,
    "kyc_status": "verified",
    "tariff": null,
    "sso_client_id": "wallet-web",
    "created_at": "1700000000"
  },
  "ts": 1706000000
}

Пополнения

Пополнение основного счёта криптовалютой и фиатом. Крипто — через депозитные адреса, фиат — через банковский перевод или СБП.

Как пополнить счёт
Крипто-депозит:
  1. Получите депозитный адрес: GET /funding/deposit/crypto/address
  2. Отправьте криптовалюту на полученный адрес из внешнего кошелька
  3. Отслеживайте статус через GET /transactions
Фиатный депозит:
  1. Узнайте доступные методы: GET /funding/deposit/fiat/methods — в ответе code (SBER, TINKOFF, …)
  2. Создайте заявку: POST /funding/deposit/fiat с currency, amount и payment_provider_alias_code из списка методов
  3. Оплатите по invoice_public_url, requisites_qr_code или requisites — это одна и та же ссылка СБП. Если все три ещё null — GET /funding/deposit/fiat/{transaction_id}
💡
Совет

Для крипто-депозита достаточно один раз получить адрес — он не меняется. Сохраните его на своей стороне и повторно используйте.

GET/api/v1/integration/funding/deposit/crypto/address

Получить адрес для пополнения криптовалюты. Если адрес ещё не сгенерирован — он будет создан автоматически. Параметры: symbol (обязательный), network (опциональный).

GET /funding/deposit/crypto/address?symbol=USDT&network=TRX
{
  "success": true,
  "data": {
    "symbol": "USDT",
    "addresses": [
      { "network": "TRX", "address": "TQn9Y2khEsLJW1ChVWFMSMeRDow5KcbLSE" }
    ]
  },
  "ts": 1706000000
}
GET/api/v1/integration/funding/deposit/fiat/methods

Возвращает доступные методы пополнения фиата: банки, СБП и т.д. Параметр currency (по умолчанию RUB).

Response
{
  "success": true,
  "data": {
    "methods": [
      { "code": "SBER", "name": "Сбербанк", "type": "sbp" },
      { "code": "TINKOFF", "name": "Т-Банк", "type": "sbp" },
      { "code": "ALFA", "name": "Альфа-Банк", "type": "sbp" }
    ]
  },
  "ts": 1706000000
}
POST/api/v1/integration/funding/deposit/fiat

Создаёт заявку на пополнение фиата. payment_provider_alias_code берите из GET /funding/deposit/fiat/methods (SBER, TINKOFF, ALFA, …). Внутренние коды каналов передавать не нужно. В ответе invoice_public_url, requisites_qr_code и requisites — одна ссылка СБП для перехода клиента к оплате. Если все три ещё null, повторите GET /funding/deposit/fiat/{transaction_id}. amount — сумма заявки; credited_amount — сколько зачислено на баланс после комиссии; fee — комиссия. Пока факта нет, credited_amount и fee равны null.

Request
{
  "currency": "RUB",
  "amount": "10000",
  "payment_provider_alias_code": "SBER"
}
Response
{
  "success": true,
  "data": {
    "transaction_id": "7ad2bfd0-673f-455a-b75b-95a949a7476a",
    "status": "processing",
    "currency": "RUB",
    "amount": "10000",
    "credited_amount": null,
    "fee": null,
    "payment_provider_alias_code": "SBER",
    "requisites": "https://qr.nspk.ru/...",
    "requisites_qr_code": "https://qr.nspk.ru/...",
    "invoice_public_url": "https://qr.nspk.ru/...",
    "expires_at": "2026-08-14T12:00:00Z",
    "created_at": "2026-08-14T11:00:00Z"
  },
  "ts": 1706000000
}
GET/api/v1/integration/funding/deposit/fiat/{transaction_id}

Статус заявки на пополнение. transaction_id — UUID из POST /funding/deposit/fiat. invoice_public_url, requisites_qr_code и requisites — одна ссылка СБП. status: processing | success | failed. Терминальный исход также приходит вебхуками deposit.confirmed / deposit.failed (data.kind=fiat). Это не invoice.paid: Invoice V2 — отдельный продукт. amount — сумма заявки; credited_amount — фактическое зачисление на баланс после комиссии; fee — комиссия. Сверяйте зачисление по credited_amount, не по amount.

Response
{
  "success": true,
  "data": {
    "transaction_id": "7ad2bfd0-673f-455a-b75b-95a949a7476a",
    "status": "success",
    "currency": "RUB",
    "amount": "6500",
    "credited_amount": "6383",
    "fee": "117",
    "payment_provider_alias_code": "SBER",
    "requisites": "https://qr.nspk.ru/...",
    "requisites_qr_code": "https://qr.nspk.ru/...",
    "invoice_public_url": "https://qr.nspk.ru/...",
    "expires_at": "2026-08-14T12:00:00Z",
    "created_at": "2026-08-14T11:00:00Z"
  },
  "ts": 1706000000
}

Выводы

Вывод средств с основного счёта на внешние адреса и по СБП. Криптовалюта выводится на блокчейн-адрес, фиат (RUB) — по номеру телефона СБП на выбранный банк.

⚠️
Важно

Вывод списывает средства с основного счёта. Убедитесь, что баланс достаточен (GET /account/wallets). Для вывода больших сумм может потребоваться пройти KYC верификацию.

POST/api/v1/integration/funding/withdraw/crypto

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

Request
{
  "symbol": "USDT",
  "amount": "100",
  "address": "TQn9Y2khEsLJW1ChVWFMSMeRDow5KcbLSE",
  "bch_code": "TRX",
  "idempotency_key": "unique-withdraw-key-123"
}
Response
{
  "success": true,
  "data": {
    "transaction_id": "...",
    "symbol": "USDT",
    "amount": "100",
    "fee": "1.0",
    "total": "101.0",
    "address": "TQn9Y2khEsLJW1ChVWFMSMeRDow5KcbLSE",
    "network": "TRX",
    "status": "processing"
  },
  "ts": 1706000000
}

amount — сумма, которая уйдёт получателю. fee — полная комиссия, списываемая сверх amount. total — итоговое списание с баланса (amount + fee). Сверяйте баланс по total, не по amount. withdraw_service_fee из справочника валют — базовая ставка сети; фактический quote приходит в ответе на этот POST. Передавайте idempotency_key: повтор с тем же ключом в течение 24 ч вернёт первую заявку (даже если она уже failed) — для новой попытки нужен новый ключ. Без ключа обрыв ответа + повтор = риск второй выплаты. Терминальный исход — вебхуки withdrawal.processing / .completed / .failed (kind=crypto).

Точность суммы и лимиты сети

Каждая сеть принимает своё число знаков после запятой. У USDT в TRX это 6 знаков, у той же USDT в BSC — 8. Лишние знаки не являются ошибкой: сумма усекается вниз до точности сети, остаток остаётся на вашем балансе. В ответе поле amount содержит фактически принятую сумму — сверяйте её, а не то, что отправили.

Точность, минимум, максимум и доступность вывода по каждой паре монета+сеть отдаёт справочник GET /api/v1/integration/market/currencies — поля withdraw_amount_decimals, min_withdraw_amount, max_withdraw_amount, withdraw_service_fee, is_withdraw_active.

GET/api/v1/integration/funding/withdraw/fiat/banks

Справочник банков для СБП-вывода. Возвращает публичные bank_code (TINKOFF, SBER, …) — передавайте их в POST /withdraw/fiat. Внутренние коды провайдера Pay в API не отдаются.

Response
{
  "success": true,
  "data": {
    "currency": "RUB",
    "banks": [
      { "bank_code": "TINKOFF", "name": "T-Pay" },
      { "bank_code": "SBER", "name": "S-Pay" },
      { "bank_code": "ALFA", "name": "A-Pay" }
    ]
  },
  "ts": 1706000000
}
POST/api/v1/integration/funding/withdraw/fiat

Создаёт заявку на вывод RUB по СБП на телефон получателя. Канал выплаты (provider) резолвится на стороне AlfaBit из назначения профиля — передавать его не нужно. Перед созданием проверяется баланс Ledger (сумма + комиссия).

Request
{
  "currency": "RUB",
  "amount": "500",
  "recipient": "79992122496",
  "bank_code": "TINKOFF",
  "idempotency_key": "unique-fiat-withdraw-key-456"
}
ПолеТипОписание
amountstringСумма к получению (без комиссии), строка
recipientstringТелефон СБП в формате 7XXXXXXXXXX
bank_codestringКод банка из GET /withdraw/fiat/banks
currencystring?Только RUB (по умолчанию RUB)
idempotency_keystring?Ключ идемпотентности, 24 ч. После failed тот же ключ вернёт первую заявку, не создаст новую — нужен новый ключ.
Response
{
  "success": true,
  "data": {
    "transaction_id": "68182a10-9f8a-4c06-a1bf-4d5d66841284",
    "currency": "RUB",
    "amount": "500.00",
    "amount_fact": null,
    "fee": "15.00",
    "total": "515.00",
    "status": "processing",
    "recipient": "7999****96",
    "bank_code": "TINKOFF"
  },
  "ts": 1706000000
}

amount — сумма к получению (без комиссии). fee — комиссия. total — списание с баланса (amount + fee). Баланс проверяется по total до создания заявки. Передавайте idempotency_key: TTL 24 ч; после failed тот же ключ новую выплату не создаст. Терминальный исход — вебхуки withdrawal.completed / withdrawal.failed (kind=fiat); processing у СБП нет.

GET/api/v1/integration/funding/withdraw/fiat/{transaction_id}

Статус фиат-вывода по transaction_id из POST /withdraw/fiat. Терминальный исход также приходит вебхуками withdrawal.completed / withdrawal.failed (data.kind=fiat). События withdrawal.processing у СБП нет — пока заявка в полёте, опрашивайте эту ручку (status: processing | success | failed). amount — к получению; fee — комиссия; total — списание с баланса; amount_fact — фактическая сумма получателю, когда выплата завершена. Банковского референса СБП в ответе нет.

Response
{
  "success": true,
  "data": {
    "transaction_id": "68182a10-9f8a-4c06-a1bf-4d5d66841284",
    "status": "success",
    "currency": "RUB",
    "amount": "500.00",
    "amount_fact": "500.00",
    "fee": "15.00",
    "total": "515.00",
    "bank_code": "TINKOFF",
    "recipient": "7999****96",
    "created_at": 1706000000,
    "updated_at": 1706000120,
    "error": null
  },
  "ts": 1706000120
}

Переводы

Три типа переводов: внутренний (другому пользователю), на торговый счёт и обратно. Внутренние переводы мгновенны и бесплатны.

Когда нужен перевод на торговый счёт?

Если вы хотите торговать на фиатном споте (USDT/RUB стакан), средства должны быть на торговом счёте. Используйте /funding/transfer/to-trading перед торговлей и /funding/transfer/from-trading чтобы вернуть средства обратно после торговли.

Основной счёт→ to-trading →Торговый счёт→ Торговля →Торговый счёт→ from-trading →Основной счёт
POST/api/v1/integration/funding/transfer/internal

Перевод средств другому пользователю по username или ID. Средства списываются с основного счёта отправителя и зачисляются на счёт получателя.

ℹ️
Только криптовалюты

Ручка принимает только криптовалютные символы; отправить RUB через API нельзя. Рублёвый перевод делает сам пользователь в интерфейсе кошелька — вы можете дать ему готовую ссылку с заполненными реквизитами (см. «Ссылка на предзаполненный перевод»). Приход к вам наблюдается одинаково для обеих валют: вебхуком transfer.received и записью в GET /integration/transactions.

Request
{
  "symbol": "USDT",
  "amount": "100",
  "to_username": "john_doe",
  "to_user_id": null,
  "comment": "Payment for services",
  "idempotency_key": "unique-transfer-key-789"
}
Response
{
  "success": true,
  "data": {
    "task_id": "celery-task-id-...",
    "symbol": "USDT",
    "amount": "100",
    "to": "john_doe",
    "status": "processing"
  },
  "ts": 1706000000
}
POST/api/v1/integration/funding/transfer/to-trading

Перевод с основного счёта на торговый счёт. Необходим для торговли на фиатном споте. Принимает символ валюты (USDT или RUB) и сумму.

Request
{
  "currency": "USDT",
  "amount": "1000"
}
Response
{
  "success": true,
  "data": {
    "status": "ok"
  },
  "ts": 1706000000
}
POST/api/v1/integration/funding/transfer/from-trading

Перевод с торгового счёта обратно на основной счёт. Принимает символ валюты (USDT или RUB) и сумму.

Request
{
  "currency": "USDT",
  "amount": "500"
}
Response
{
  "success": true,
  "data": {
    "status": "ok"
  },
  "ts": 1706000000
}

Крипто Спот

Торговля криптовалютными парами. Поддерживаются рыночные (market) и лимитные (limit) ордера. Операции выполняются с основного счёта.

Как купить BTC за USDT — пошагово
  1. Изучите тикеры: GET /spot/crypto/tickers — текущие цены всех пар (публичный, без ключа)
  2. Узнайте детали пары: GET /spot/crypto/market-info?from_symbol=BTC&to_symbol=USDT (публичный, без ключа)
  3. Проверьте доступные пары для торговли: GET /spot/crypto/pairs (требует API ключ)
  4. Создайте ордер: POST /spot/crypto/order с type="market" (мгновенно) или type="limit" (по своей цене)
  5. Отслеживайте статус: GET /spot/crypto/orders
Типы ордеров:
  • market — мгновенное исполнение по текущей рыночной цене. Можно указать from_amount ИЛИ to_amount. Идеально для быстрого обмена.
  • limit — ордер по заданной цене. Исполняется когда рыночная цена достигает указанной. Обязательны from_amount и order_price. Подходит для DCA-стратегий и покупки на просадках.
💡
Когда какой ордер?

Market — когда важна скорость (обмен прямо сейчас). Limit — когда важна цена (хотите купить дешевле текущей). Лимитный ордер можно отменить пока он не исполнен через DELETE /spot/crypto/order/{order_id}.

Публичные данные (без API ключа)

GET/api/v1/integration/spot/crypto/tickers

Текущие тикеры всех крипто пар — цены, bid/ask, объёмы за 24 часа. Данные кешируются и обновляются каждые ~3 минуты. Не требует API ключа.

Параметры запроса

ПараметрТипОписание
symbolstringФильтр по базовому символу: BTC, ETH (опционально)
Response
{
  "success": true,
  "data": [
    {
      "pair": "BTC-USDT",
      "base": "BTC",
      "quote": "USDT",
      "last_price": "97450.50",
      "bid_price": "97448.00",
      "ask_price": "97453.00",
      "volume_24h": "12450000",
      "high_24h": "98100.00",
      "low_24h": "96800.00",
      "price_change_24h": "0.0124"
    }
  ],
  "ts": 1706000000
}
GET/api/v1/integration/spot/crypto/market-info

Подробная информация по конкретной торговой паре: текущий курс, мин/макс суммы, торговые фильтры. Не требует API ключа.

Параметры запроса

ПараметрТипОписание
from_symbol *stringИсходная валюта: BTC
to_symbol *stringЦелевая валюта: USDT
Response
{
  "success": true,
  "data": {
    "symbol": "BTCUSDT",
    "priceTo": "71114.201",
    "priceOut": "69706.098",
    "price": "70410.2",
    "mainSymbol": "BTC",
    "minorSymbol": "USDT",
    "quote_asset_precision": 7,
    "base_asset_precision": 6,
    "step": "0.000001",
    "minValue": "0.000001",
    "min_value_minor": "5",
    "maxValue": "230",
    "max_value_minor": "8000000",
    "limit_price_step": "0.005",
    "price_step": "0.1"
  },
  "ts": 1706000000
}

Торговля (требует API ключ)

GET/api/v1/integration/spot/crypto/pairs

Список доступных торговых пар с лимитами. Требует API ключ с правом can_spot_crypto_read.

Параметры запроса

ПараметрТипОписание
symbolstringФильтр по символу (опционально)
Response
{
  "success": true,
  "data": ["NAKA", "SIGN", "ARKM", "BTC", "ETH", "SOL"],
  "ts": 1706000000
}
GET/api/v1/integration/spot/crypto/pair-info

Информация по паре: текущий курс, минимальная и максимальная сумма обмена.

Параметры запроса

ПараметрТипОписание
from_symbolstringИсходная валюта (обязательно)
to_symbolstringЦелевая валюта (обязательно)
Response
{
  "success": true,
  "data": {
    "symbol": "BTCUSDT",
    "priceTo": "71114.201",
    "priceOut": "69706.098",
    "price": "70410.2",
    "mainSymbol": "BTC",
    "minorSymbol": "USDT",
    "quote_asset_precision": 7,
    "base_asset_precision": 6,
    "step": "0.000001",
    "minValue": "0.000001",
    "min_value_minor": "5",
    "maxValue": "230",
    "max_value_minor": "8000000",
    "limit_price_step": "0.005",
    "price_step": "0.1"
  },
  "ts": 1706000000
}
POST/api/v1/integration/spot/crypto/order

Рыночный ордер (Market)

Мгновенный обмен по текущей рыночной цене. Указывайте from_amount (сколько отдать) ИЛИ to_amount (сколько получить).

Параметры тела запроса

ПолеТипОбязательноОписание
from_symbolstringдаИсходная валюта (например USDT)
to_symbolstringдаЦелевая валюта (например BTC)
from_amountstringда*Сумма в исходной валюте
to_amountstringда*Сумма в целевой валюте
typestringнет"market" (по умолчанию)

* Укажите from_amount ИЛИ to_amount, но не оба.

Request
{
  "from_symbol": "USDT",
  "to_symbol": "BTC",
  "from_amount": "100",
  "type": "market"
}
Response
{
  "success": true,
  "data": {
    "order_id": "550e8400-e29b-41d4-a716-446655440000",
    "from_symbol": "USDT",
    "to_symbol": "BTC",
    "from_amount": "100",
    "to_amount": "0.00231",
    "type": "market",
    "order_price": null,
    "status": "processing"
  },
  "ts": 1706000000
}
POST/api/v1/integration/spot/crypto/order

Лимитный ордер (Limit)

Ордер по указанной цене. Будет исполнен, когда рыночная цена достигнет заданного уровня. Для limit-ордера обязательны from_amount и order_price.

Параметры тела запроса

ПолеТипОбязательноОписание
from_symbolstringдаИсходная валюта (например USDT)
to_symbolstringдаЦелевая валюта (например BTC)
from_amountstringдаСумма в исходной валюте
typestringда"limit"
order_pricestringдаЖелаемая цена исполнения (например "42000.00")
Request
{
  "from_symbol": "USDT",
  "to_symbol": "BTC",
  "from_amount": "500",
  "type": "limit",
  "order_price": "42000.00"
}
Response
{
  "success": true,
  "data": {
    "order_id": "550e8400-e29b-41d4-a716-446655440001",
    "from_symbol": "USDT",
    "to_symbol": "BTC",
    "from_amount": "500",
    "to_amount": null,
    "type": "limit",
    "order_price": "42000.00",
    "status": "processing"
  },
  "ts": 1706000000
}
DELETE/api/v1/integration/spot/crypto/order/{order_id}

Отменить лимитный ордер. Работает только для ордеров с type=limit, которые ещё не исполнены.

Параметры пути

ПараметрТипОписание
order_idstringID ордера из ответа POST /order
Response
{
  "success": true,
  "data": {
    "cancelled": true,
    "order_id": "550e8400-e29b-41d4-a716-446655440001",
    "status": "cancelled"
  },
  "ts": 1706000000
}
Ошибки
// Ордер не найден
{ "success": false, "error": { "code": "ORDER_NOT_FOUND", "message": "Order not found" } }

// Ордер не является лимитным
{ "success": false, "error": { "code": "CANCEL_FAILED", "message": "Not a limit order" } }

// Ордер уже отменён
{ "success": false, "error": { "code": "CANCEL_FAILED", "message": "Order already cancelled" } }
GET/api/v1/integration/spot/crypto/orders

История ордеров на крипто обмен с пагинацией. Включает market и limit ордера.

Параметры запроса

ПараметрТипПо умолчаниюОписание
limitinteger50Кол-во записей (1-100)
pageinteger1Номер страницы
Response
{
  "success": true,
  "data": [
    {
      "order_id": "...",
      "from_symbol": "USDT", "to_symbol": "BTC",
      "from_amount": "100", "to_amount": "0.00231",
      "type": "market",
      "status": "completed", "created_at": "2024-01-15T14:30:00Z"
    },
    {
      "order_id": "...",
      "from_symbol": "USDT", "to_symbol": "ETH",
      "from_amount": "500", "to_amount": null,
      "type": "limit", "order_price": "2100.00",
      "status": "processing", "created_at": "2024-01-15T15:00:00Z"
    }
  ],
  "ts": 1706000000
}

Фиат Спот

Полноценный стакан USDT/RUB с market и limit ордерами. Работает на собственном торговом движке AlfaBit. В отличие от Крипто Спота, здесь вы видите реальный стакан заявок и можете контролировать цену.

⚠️
Торговый счёт — обязательный шаг

Торговля идёт с отдельного торгового баланса. Перед первой сделкой переведите средства:

POST /api/v1/integration/funding/transfer/to-trading
{ "currency": "USDT", "amount": "1000" }
Флоу: купить USDT за рубли по лимитной цене
  1. Переведите RUB на торговый счёт: POST /funding/transfer/to-trading
  2. Проверьте баланс: GET /spot/fiat/balance
  3. Изучите стакан и текущую цену: GET /spot/fiat/orderbook и GET /spot/fiat/stats
  4. Примите ордер: POST /spot/fiat/order — сразу вернётся id (обычно status=new). Не ждите filled в этом ответе.
  5. Отслеживайте fill: GET /spot/fiat/order/{id} / GET /spot/fiat/orders или webhook order.filled
  6. Верните USDT на основной счёт: POST /funding/transfer/from-trading

Публичные данные (без API ключа)

GET/api/v1/integration/spot/fiat/instruments

Список торговых инструментов (пар) и их статусы.

Response
{
  "success": true,
  "data": [
    { "trading_pair": "USDT/RUB", "status": "active", "base": "USDT", "quote": "RUB" }
  ],
  "ts": 1706000000
}
GET/api/v1/integration/spot/fiat/balance

Балансы торгового счёта: USDT и RUB (available, locked).

Response
{
  "success": true,
  "data": {
    "USDT": { "available": "5000.00", "locked": "100.00" },
    "RUB": { "available": "150000.00", "locked": "0.00" }
  },
  "ts": 1706000000
}
GET/api/v1/integration/spot/fiat/orderbook?pair=USDT/RUB&depth=20

Стакан заявок: bids (покупка) и asks (продажа). Параметр depth — глубина стакана (по умолчанию 20).

Response
{
  "success": true,
  "data": {
    "bids": [
      { "price": "92.45", "amount": "5000" },
      { "price": "92.40", "amount": "12000" }
    ],
    "asks": [
      { "price": "92.55", "amount": "3000" },
      { "price": "92.60", "amount": "8000" }
    ]
  },
  "ts": 1706000000
}
GET/api/v1/integration/spot/fiat/trades?pair=USDT/RUB&limit=50

Лента публичных сделок. Не требует API ключа.

Response
{
  "success": true,
  "data": [
    { "id": "...", "price": "92.50", "amount": "100", "side": "buy", "time": "2024-01-15T14:30:00Z" }
  ],
  "ts": 1706000000
}
GET/api/v1/integration/spot/fiat/stats?pair=USDT/RUB

Статистика за 24 часа: объём, максимум, минимум, последняя цена.

Response
{
  "success": true,
  "data": {
    "pair": "USDT/RUB", "last": "92.50", "high": "93.10",
    "low": "91.80", "volume": "1250000", "change": "+0.5%"
  },
  "ts": 1706000000
}

Торговля (требует API ключ)

POST/api/v1/integration/spot/fiat/order

Принять ордер. Ответ — тот же JSON с id (обычно status=new). Исполнение идёт асинхронно: не ждите filled в этом POST. Смотрите GET /spot/fiat/order/{id}, GET /spot/fiat/orders или webhook order.filled. 4xx (баланс, стакан, лимиты) по-прежнему синхронны — ордер в этом случае не создаётся.

Market Order

Request
{
  "pair": "USDT/RUB",
  "side": "buy",
  "type": "market",
  "amount": "100"
}

Market Order — на сумму в рублях (quote_amount)

Если вы пришли с рублями и не знаете, сколько USDT получится купить — передайте quote_amount (сумма в котируемой валюте, которую готовы потратить) вместо amount. Движок сам подберёт объём базовой валюты по текущему стакану так, чтобы не превысить бюджет. Поддерживается только для market buy. amount и quote_amount взаимоисключающи. Неиспользованный остаток бюджета возвращается; в быстром рынке фактически купленный объём может незначительно отличаться (как у любого market-ордера).

Request
{
  "pair": "USDT/RUB",
  "side": "buy",
  "type": "market",
  "quote_amount": "10000"
}

Limit Order

Request
{
  "pair": "USDT/RUB",
  "side": "sell",
  "type": "limit",
  "amount": "500",
  "price": "93.00"
}
Response
{
  "success": true,
  "data": {
    "order_id": "ord_limit_xyz789",
    "pair": "USDT/RUB",
    "side": "sell",
    "type": "limit",
    "amount": "500",
    "price": "93.00",
    "status": "open"
  },
  "ts": 1706000000
}
DELETE/api/v1/integration/spot/fiat/order/{order_id}

Отменить лимитный ордер по ID. Market ордера отменить нельзя — они исполняются мгновенно.

GET/api/v1/integration/spot/fiat/orders

Список ваших открытых и исполненных ордеров на фиатном споте.

Response
{
  "success": true,
  "data": [
    { "id": "...", "pair": "USDT/RUB", "side": "buy", "type": "limit",
      "price": "92.00", "amount": "100", "filled": "0", "status": "open" }
  ],
  "ts": 1706000000
}
GET/api/v1/integration/spot/fiat/my-trades

Ваши исполненные сделки на фиатном споте.

Response
{
  "success": true,
  "data": [
    { "id": "...", "pair": "USDT/RUB", "side": "buy",
      "price": "92.45", "amount": "100", "fee": "0.1", "time": "2024-01-15T14:30:00Z" }
  ],
  "ts": 1706000000
}

Дополнительные публичные данные

GET/api/v1/integration/spot/fiat/tickers

Сводные тикеры по всем активным парам: цена, bid/ask, объёмы 24ч, изменение. Аналог /spot/crypto/tickers для фиатных пар.

GET/api/v1/integration/spot/fiat/market-info?pair=USDT/RUB

Детальная информация по конкретной паре: текущая цена, спред, мин/макс объёмы, шаги цены и количества, precision.

GET/api/v1/integration/spot/fiat/instruments/{pair}

Подробности одной пары (статус, base/quote, лимиты).

GET/api/v1/integration/spot/fiat/currencies

Справочник валют торгового счёта (USDT, RUB и т.д.) с symbol и precision.

Дополнительные приватные ручки (требуют API ключ)

GET/api/v1/integration/spot/fiat/balance/{symbol}

Торговый баланс по конкретной валюте (например USDT или RUB).

GET/api/v1/integration/spot/fiat/order/{order_id}

Детали одного ордера по ID: статус, заполнение, средняя цена, комиссии.

Response
{
  "success": true,
  "data": {
    "id": "3f1c9a2e-8b7d-4e6a-9c11-2a5f4d7e0b9c",
    "order_number": 10432,
    "user_id": "b2c9e7a1-4f83-4d2a-9e6b-1c0f5a8d3e21",
    "side": "buy",
    "type": "market",
    "price": null,
    "amount": "100",
    "filled": "100",
    "status": "filled",
    "created_at": "2026-07-24T14:28:00.123456",
    "trading_pair": "USDT/RUB",
    "execution_message": "Order executed successfully",
    "avg_execution_price": "92.35",
    "total_fee": "9.235",
    "user_input_price": null,
    "user_input_price_total": "10000",
    "user_input_amount": null,
    "locked_quote_amount": "10000"
  },
  "ts": 1753363680
}

Числовые поля приходят строками (сохранение precision). price и avg_execution_price = null, пока не заданы/ордер не исполнен.

  • id — ID ордера (UUID).
  • order_number — человекочитаемый номер ордера.
  • user_id — внутренний ID пользователя.
  • side — buy или sell.
  • type — market или limit.
  • price — цена лимитного ордера; null для market.
  • amount — объём ордера в базовой валюте (USDT).
  • filled — заполнение — сколько базовой валюты уже исполнено (в единицах amount).
  • status — new / partially_filled / filled / cancelled.
  • created_at — время создания (ISO-8601).
  • trading_pair — торговая пара, напр. USDT/RUB.
  • execution_message — сообщение об исполнении (актуально для market); может быть null.
  • avg_execution_price — средняя цена исполнения; null пока сделок нет.
  • total_fee — суммарная комиссия по ордеру.
  • user_input_price, user_input_price_total, user_input_amount — исходный ввод пользователя (только для отображения). Для market buy с quote_amount поле user_input_price_total содержит заданный бюджет.
  • locked_quote_amount — сколько котируемой валюты (RUB) заблокировано под BUY.
GET/api/v1/integration/spot/fiat/trading/operations

История операций пополнения/вывода торгового счёта с пагинацией. Фильтры: currency_id, operation_type (deposit/withdraw), status (pending/completed/failed).

GET/api/v1/integration/spot/fiat/trading/settings/{symbol}

Лимиты deposit/withdraw и fee_percent для конкретной валюты.

Идемпотентность

Для POST /spot/fiat/order и DELETE /spot/fiat/order/{id} поддерживается заголовок Idempotency-Key (1-128 символов: буквы/цифры/-/_, рекомендуется UUID). Повторный POST с тем же ключом не создаст второй ордер (TTL 24 ч). Для create на retry вернётся актуальный ордер из движка (не застывший снимок accept) — так можно безопасно повторить запрос после обрыва сети и узнать status/filled.

Headers
X-API-Key: pk_live_...
X-API-Signature: ...
X-API-Timestamp: ...
Idempotency-Key: 4b8c8a1e-3f2c-4f3a-9c0d-2b3a4b5c6d7e

WebSockets

Real-time канал для интеграторов. Один WS-сервер для всех топиков: торговые события Spot Fiat, изменения баланса, статус инвойсов, обновления конвертера.

URL
wss://alfabit.org/wallet-web/ws/ws

Аутентификация (auth_api_key)

WS использует упрощённую подпись HMAC-SHA256(secret, timestamp + api_key) — без method/path/body. Допустимое расхождение timestamp ±300 сек.

Пример handshake (JS)
const ws = new WebSocket('wss://alfabit.org/wallet-web/ws/ws');

// 1) handshake
ws.send(JSON.stringify({
  action: 'auth_api_key',
  api_key: 'pk_live_xxxxxxxxxxxx',
  timestamp: '1714210000',
  signature: '<hmac-sha256(secret, timestamp + api_key) hex>',
}));

// 2) subscribe
ws.send(JSON.stringify({
  action: 'subscribe',
  topics: [
    'spot.fiat.balance',
    'spot.fiat.order',
    'spot.fiat.orderbook.USDT/RUB'
  ]
}));
Подпись (Python)
import hashlib, hmac, time
ts = str(int(time.time()))
sig = hmac.new(secret_key.encode(), (ts + api_key).encode(), hashlib.sha256).hexdigest()

Публичные топики (без авторизации)

Стакан, лента сделок, статистика, чарты — индустриальный стандарт.

  • spot.fiat.orderbook.{pair} — Снимок стакана (bids/asks) для пары.
  • spot.fiat.trades.{pair} — Лента сделок для пары.
  • spot.fiat.stats.{pair} — 24ч-статистика для пары.
  • spot.fiat.chart.{symbol}.{resolution} — TradingView-свечи для пары и интервала (1, 5, 15, 30, 60, 240, D, W, M).

Приватные топики (требуют can_spot_fiat_read)

Свои ордера и торговый баланс — фильтруются по profile_id, видны только владельцу API-ключа.

  • spot.fiat.order — Изменения статуса ваших ордеров (created, filled, partially_filled, cancelled).
  • spot.fiat.balance — Изменения торгового баланса.

Реконнект

При обрыве соединения переподключайтесь с экспоненциальным backoff: 1s → 2s → 4s → ... до 30s. После реконнекта повторите auth_api_key и subscribe.

Конвертер

Быстрая конвертация с фиксированным курсом. Поддерживает крипто-крипто и крипто-фиат обмен. В отличие от Спота, конвертер гарантирует цену — вы получите ровно столько, сколько показала котировка.

Как это работает: 2 шага
1. Estimate (котировка)2. Execute (исполнение)

Котировка фиксирует курс на ограниченное время (см. expires_in_seconds в ответе). За это время вызовите /execute с полученным quote_id. Если не успеете — запросите новую котировку.

💡
Конвертер vs Спот — что выбрать?

Конвертер — для разовых операций с гарантированной ценой (отправить клиенту ровно $100 в ETH). Спот — для регулярной торговли и стратегий (DCA, лимитные ордера, большие объёмы).

Крипто конвертер

Курсы и символы доступны без API ключа. Обмен требует авторизацию.

GET/api/v1/integration/converter/crypto/symbols

Список криптовалют доступных для конвертации. Не требует API ключа.

GET/api/v1/integration/converter/crypto/rate?from=BTC&to=ETH

Конечный курс обмена, лимиты и время жизни котировки. Не требует API ключа.

Response
{
  "success": true,
  "data": {
    "from_symbol": "BTC",
    "to_symbol": "ETH",
    "rate": "16.468",
    "min_amount_usdt": "10",
    "max_amount_usdt": "50000",
    "expires_in_seconds": 30
  },
  "ts": 1706000000
}
POST/api/v1/integration/converter/crypto/estimate

Получить фиксированную котировку. Возвращает quote_id, который нужно передать в /execute. Время жизни котировки указано в поле expires_in_seconds.

Request
{
  "from_symbol": "BTC",
  "to_symbol": "ETH",
  "from_amount": "0.5"
}
Response
{
  "success": true,
  "data": {
    "quote_id": "qt_abc123def456",
    "from_symbol": "BTC",
    "to_symbol": "ETH",
    "from_amount": "0.5",
    "to_amount": "8.234",
    "rate": "16.468",
    "expires_in_seconds": 30
  },
  "ts": 1706000000
}
POST/api/v1/integration/converter/crypto/execute

Выполнить конвертацию по ранее полученной котировке. Если котировка истекла — вернёт ошибку. Необязательный idempotency_key (действует 24 ч): повторный запрос с тем же ключом не создаст вторую конвертацию — вернётся тот же результат (защита от retry). Идентичный запрос, ещё выполняющийся, вернёт HTTP 409.

Request
{
  "quote_id": "qt_abc123def456",
  "idempotency_key": "your-unique-key-123"
}
Response
{
  "success": true,
  "data": {
    "uid": "conv_op_abc123",
    "from_symbol": "BTC",
    "to_symbol": "USDT",
    "from_amount": "0.01",
    "to_amount": "704.10",
    "rate": "70410.2",
    "status": "completed"
  },
  "ts": 1706000000
}

Фиат конвертер

Конвертация крипты в фиат и обратно (например USDT → RUB). Курсы доступны без API ключа, обмен требует авторизацию.

GET/api/v1/integration/converter/fiat/currencies

Фиатные валюты, открытые для конвертации прямо сейчас. Не требует API ключа. Читайте его перед запросом курса: набор валют меняется, и запрос с кодом, которого нет в этом ответе, будет отклонён.

Response
{
  "success": true,
  "data": [
    {
      "code": "RUB",
      "name": "Российский рубль",
      "symbol": "₽",
      "decimals": 2,
      "min_amount": "100.00",
      "max_amount": "250000.00"
    }
  ],
  "ts": 1706000000
}
  • decimals — точность суммы в этой валюте. Округляйте по ней, а не по своему формату.
  • min_amount / max_amount — лимиты одной конвертации в фиатных единицах. null означает, что ограничение не задано.
GET/api/v1/integration/converter/fiat/crypto-symbols

Плоский массив символов криптовалют, разрешённых в паре с фиатом. Не требует API ключа. Список длинный и меняется — не зашивайте его в код, запрашивайте и кешируйте у себя.

Response
{
  "success": true,
  "data": ["0G", "1INCH", "AAVE", "ADA", "BTC", "ETH", "USDT", "..."],
  "ts": 1706000000
}
GET/api/v1/integration/converter/fiat/rate?crypto=USDT&fiat=RUB&direction=sell

Текущий курс крипто/фиат. Параметры: crypto (символ), fiat (код), direction (buy/sell).

Response
{
  "success": true,
  "data": {
    "crypto": "USDT", "fiat": "RUB", "direction": "sell",
    "rate": "92.50", "min_amount": "10", "max_amount": "100000"
  },
  "ts": 1706000000
}
POST/api/v1/integration/converter/fiat/estimate

Получить котировку для фиат конвертации.

Request
{
  "crypto_symbol": "USDT",
  "fiat_code": "RUB",
  "direction": "sell",
  "amount": "100"
}
Response
{
  "success": true,
  "data": {
    "quote_id": "qt_fiat_abc123",
    "crypto_symbol": "USDT",
    "fiat_code": "RUB",
    "direction": "sell",
    "crypto_amount": "100",
    "fiat_amount": "9250.00",
    "rate": "92.50",
    "fee": "1.00",
    "expires_at": "2024-01-20T12:35:00Z"
  },
  "ts": 1706000000
}
POST/api/v1/integration/converter/fiat/execute

Выполнить фиат конвертацию по котировке. Тело то же, что у /fiat/estimate (crypto_symbol, fiat_code, direction), сумма в from_amount, плюс quote_id из ответа estimate. Одного quote_id недостаточно — без остальных полей API отвечает 422. Отдельного idempotency_key нет: повтор с тем же quote_id вернёт уже созданную операцию. Котировка прямого обмена живёт 30 секунд. Статус — GET /converter/operations; успех также приходит вебхуком conversion.completed.

Request
{
  "crypto_symbol": "USDT",
  "fiat_code": "RUB",
  "direction": "sell",
  "from_amount": "100",
  "quote_id": "qt_fiat_xyz789"
}
Response
{
  "success": true,
  "data": {
    "uid": "fiat_conv_xyz789",
    "crypto_symbol": "USDT",
    "fiat_code": "RUB",
    "direction": "sell",
    "crypto_amount": "100",
    "fiat_amount": "9250.00",
    "status": "completed"
  },
  "ts": 1706000000
}
GET/api/v1/integration/converter/operations?limit=20

История всех конвертаций (крипто + фиат). Параметр type: crypto или fiat.

Response
{
  "success": true,
  "data": [
    { "uid": "...", "type": "crypto", "from_symbol": "BTC", "to_symbol": "ETH",
      "from_amount": "0.5", "to_amount": "8.234", "status": "completed" }
  ],
  "ts": 1706000000
}

Виртуальные карты

Выпуск и управление виртуальными банковскими картами Visa/Mastercard. Оплачивайте подписки, рекламу и покупки используя криптовалюту.

💳
Типы карт

SHOPPING — для онлайн-покупок. ADVERTISING — для рекламных платформ. Типы и доступные опции зависят от вашего тарифа.

Флоу: выпустить и пополнить карту
  1. Изучите условия: GET /cards/settings (комиссии, лимиты) и GET /cards/meta (регионы, платёжные системы)
  2. Узнайте курс: GET /cards/rate (USDT → USD для расчёта стоимости)
  3. Выпустите карту: POST /cards (amount + payment_method: balance_usdt | onchain_usdt | rub_sbp). Готовая карта появится в GET /cards (для balance_usdt — асинхронно, также придёт webhook card.transaction)
  4. Пополните карту: POST /cards/{card_id}/topup — средства конвертируются в USD
  5. Используйте карту для оплаты и отслеживайте транзакции: GET /cards/{card_id}/transactions
GET/api/v1/integration/cards/settings

Настройки карт: типы, комиссии за выпуск (buy_fee), комиссия пополнения (top_up_fee), обязательное пополнение.

GET/api/v1/integration/cards/meta

Мета-информация: доступные валюты, регионы, платёжные системы (Visa/Mastercard), Apple Pay.

GET/api/v1/integration/cards/rate

Текущий курс USDT/RUB для расчёта стоимости выпуска и пополнения.

GET/api/v1/integration/cards

Список всех карт пользователя: тип, статус, баланс, платёжная система.

POST/api/v1/integration/cards

Выпустить виртуальную карту (book + оплата). amount обязателен. Способ оплаты задаётся в payment_method: balance_usdt (списание с баланса), onchain_usdt (перевод USDT, нужна сеть) или rub_sbp (оплата по СБП). Актуальные region / payment_system / currency смотрите в GET /cards/meta.

Request (с баланса)
{
  "amount": "10",
  "payment_method": "balance_usdt",
  "source_symbol": "USDT",
  "card_type": "SHOPPING",
  "is_apple_pay_available": false
}
Request (СБП / on-chain USDT)
// rub_sbp — в ответе qr/ссылка на оплату
{ "amount": "10", "payment_method": "rub_sbp", "card_type": "SHOPPING" }

// onchain_usdt — в ответе адрес депозита
{ "amount": "10", "payment_method": "onchain_usdt", "onchain_network": "trc20", "card_type": "SHOPPING" }
ПараметрОписание
amountОбязателен. Сумма начального пополнения карты (USD).
payment_methodbalance_usdt, onchain_usdt, rub_sbp
source_symbolАктив списания для balance_usdt (по умолч. USDT).
onchain_networktrc20 | erc20 — обязателен для onchain_usdt.
card_type SHOPPING или ADVERTISING
region / payment_systemОпционально. Актуальные значения из GET /cards/meta (сейчас HK / mastercard). Если не переданы — подбираются автоматически.
idempotency_keyОпционально (uuid4). Защита от дублей выпуска.
ℹ️

Для balance_usdt выпуск идёт асинхронно: в ответе — заказ, готовую карту смотрите в GET /cards и через webhook card.transaction. Для rub_sbp/onchain_usdt сначала оплатите по возвращённым реквизитам.

GET/api/v1/integration/cards/{card_id}

Данные карты: номер, CVV, срок действия, статус (ACTIVE, FROZEN, BLOCKED).

Response
{
  "success": true,
  "data": {
    "id": 123, "card_type": "SHOPPING", "status": "ACTIVE",
    "number": "4111 **** **** 1234", "cvc": "***",
    "date_expired": "12/27", "payment_system": "VISA",
    "balance": "150.00", "region": "WW"
  },
  "ts": 1706000000
}
GET/api/v1/integration/cards/{card_id}/balance

Текущий баланс карты в USD.

POST/api/v1/integration/cards/{card_id}/topup

Пополнить карту. Сумма конвертируется в USD. Способ: crypto, fiat_wallet или sbp.

Request
{
  "amount": "50",
  "source_symbol": "USDT",
  "payment_method": "crypto"
}
GET/api/v1/integration/cards/{card_id}/transactions

Транзакции карты: покупки, пополнения, возвраты.

GET/api/v1/integration/cards/transactions/all

Транзакции по ВСЕМ картам пользователя. Можно фильтровать по card_type.

Подарочные карты

Покупка подарочных карт и сертификатов популярных сервисов (Steam, PlayStation, Spotify и др.) за криптовалюту. Код сертификата приходит мгновенно.

Флоу: купить подарочную карту
КаталогОценка ценыПокупкаПолучение кода

Сначала найдите нужный продукт в каталоге, затем узнайте сколько он стоит в крипте через /estimate, и наконец купите через /purchase.

GET/api/v1/integration/giftcards/catalog

Каталог доступных подарочных карт. Поддерживает фильтрацию по категории, поиск по названию и пагинацию.

GET/api/v1/integration/giftcards/categories

Список категорий: Игры, Развлечения, Музыка, Маркетплейсы и др.

Response
{
  "success": true,
  "data": [
    { "id": 1, "title": "Игры", "slug": "games", "is_active": true, "products_count": 42 },
    { "id": 2, "title": "Развлечения", "slug": "entertainment", "is_active": true, "products_count": 18 },
    { "id": 3, "title": "Музыка", "slug": "music", "is_active": true, "products_count": 7 }
  ],
  "ts": 1706000000
}
POST/api/v1/integration/giftcards/estimate

Расчёт стоимости подарочной карты в криптовалюте перед покупкой. Показывает итоговую сумму с учётом комиссии.

Request
{
  "product_id": 123,
  "face_value": 1000,
  "symbol": "USDT"
}
Response
{
  "success": true,
  "data": {
    "product_id": 123,
    "face_value": 1000,
    "crypto_amount": "10.85",
    "symbol": "USDT",
    "fee": "0.15",
    "total": "11.00"
  },
  "ts": 1706000000
}
POST/api/v1/integration/giftcards/purchase

Покупка подарочной карты. Средства списываются с крипто-кошелька. Код сертификата доступен в ответе (GET /giftcards/orders/{order_id}).

Request
{
  "product_id": 123,
  "face_value": 1000,
  "symbol": "USDT",
  "email": "user@example.com"
}
Response
{
  "success": true,
  "data": {
    "order_id": "gc_ord_abc123",
    "product_id": 123,
    "face_value": 1000,
    "crypto_amount": "11.00",
    "symbol": "USDT",
    "status": "processing"
  },
  "ts": 1706000000
}
GET/api/v1/integration/giftcards/orders

История покупок подарочных карт с кодами сертификатов и статусами.

Response
{
  "success": true,
  "data": [
    { "id": "...", "product": "Steam 1000₽", "face_value": 1000,
      "cost_usdt": "11.50", "status": "completed", "code": "XXXX-YYYY-ZZZZ" }
  ],
  "ts": 1706000000
}

Оплата услуг

Каталог услуг для перепродажи: мобильная связь, интернет, игры, ЖКХ и другие сервисы. Вы покупаете услугу со своего баланса AlfaBit (RUB или USDT) и продаёте своему клиенту по своей цене. Наценку считаете и берёте сами — в API её нет.

ℹ️
Как подключить

Каталог и категории доступны без ключа. Оценка, проверка реквизита, оплата и заказы — с API-ключом: can_services_read (чтение) и can_services_pay (списание). В каталоге только подключённые услуги. Если список пуст — напишите в поддержку, витрину откроем.

Флоу: купить услугу и отдать своему клиенту
КаталогОценкаРеквизитОплатаСтатус
  1. GET /services/catalog — покажите своему клиенту доступные услуги. Поля формы берите из inputs; если массив пустой — из required_fields.
  2. POST /services/estimate — сумма к списанию с вашего баланса в RUB или USDT (client_amount / client_currency).
  3. Если requires_check=true или payment_type=REQUISITES — POST /services/check-requisite. Реквизит: поле requisite либо field_values.account / field_values.phone.
  4. POST /services/pay — списывает ваш баланс. Свою цену клиенту выставляете сами. Статус: webhook service_payment.* или GET /services/orders/{id}.
GET/api/v1/integration/services/categories

Список категорий: Мобильная связь, Игры, Интернет, ТВ и др. Не требует API-ключа. Фильтр: country.

GET/api/v1/integration/services/catalog

Каталог услуг с пагинацией. Не требует API-ключа. Фильтры: category (alias), category_id, country, search, page, page_size.

GET/api/v1/integration/services/catalog/{service_id}

Карточка услуги: inputs, required_fields, payment_type, fixed_payment, requires_check, инструкция. Не требует API-ключа.

Response
{
  "success": true,
  "data": {
    "id": 2,
    "name": "MegaCom",
    "category_alias": "mobile",
    "country": "Кыргызская Республика",
    "payment_type": "SIMPLIFIED",
    "fixed_payment": false,
    "requires_check": false,
    "inputs": [
      { "name": "account", "required": true, "title": "Номер", "regexp": "^0\\d{9}$" }
    ],
    "required_fields": []
  },
  "ts": 1706000000
}
POST/api/v1/integration/services/estimate

Расчёт суммы к списанию с вашего баланса. debit_currency: RUB или USDT. Для fixed_payment client_amount можно не передавать — сумму вернёт ответ. Право: can_services_read.

Request
{
  "service_id": 2,
  "debit_currency": "RUB",
  "client_amount": 500
}
Response
{
  "success": true,
  "data": {
    "service_id": 2,
    "service_name": "MegaCom",
    "client_amount": "512.40",
    "client_currency": "RUB",
    "quote_expires_at": "1706000300",
    "payment_type": "SIMPLIFIED",
    "fixed_payment": false,
    "requires_check": false
  },
  "ts": 1706000000
}
POST/api/v1/integration/services/check-requisite

Проверка номера или счёта. Обязательна, если requires_check=true или payment_type=REQUISITES. Реквизит: requisite либо field_values.account / phone. В pay передайте agent_transaction_id и check_snapshot из ответа. Право: can_services_read.

Request
{
  "service_id": 2,
  "debit_currency": "RUB",
  "client_amount": "512.40",
  "field_values": { "account": "0555123456" }
}
Response
{
  "success": true,
  "data": {
    "success": true,
    "agent_transaction_id": "agent-tx-uuid",
    "client_amount": "512.40",
    "client_currency": "RUB",
    "requires_identity": false,
    "check_snapshot": { "agent_transaction_id": "agent-tx-uuid" }
  },
  "ts": 1706000000
}
POST/api/v1/integration/services/pay

Оплата с вашего баланса (RUB или USDT). Передайте quote_expires_at из estimate. Если был check-requisite — agent_transaction_id и check_snapshot. Webhook: service_payment.*. Право: can_services_pay.

Request
{
  "service_id": 2,
  "debit_currency": "RUB",
  "client_amount": "512.40",
  "field_values": { "account": "0555123456" },
  "quote_expires_at": "1706000300"
}
Response
{
  "success": true,
  "data": {
    "id": "550e8400-e29b-41d4-a716-446655440000",
    "service_id": 2,
    "status": "CREATED",
    "status_for_client": "wait",
    "client_amount": "512.40",
    "client_currency": "RUB",
    "requisite": "0555123456"
  },
  "ts": 1706000000
}
GET/api/v1/integration/services/orders

История оплат с вашего профиля. Параметры: limit, offset. Право: can_services_read. Ориентир для витрины — status_for_client: wait, success, failed.

GET/api/v1/integration/services/orders/{order_id}

Детали заказа. Тот же DTO, что в ответе pay. Можно поллить вместо webhook.

Инвойсы — приём платежей

Полноценный инвойсинг для бизнеса: одноразовые счета, постоянные QR/шаблоны для касс, донат-ссылки, открытая сумма, отложенный выбор валюты плательщиком, автоматическое хеджирование, оплата из баланса AlfaBit без сети, встраиваемый Checkout-виджет и webhooks. Подходит для интернет-магазинов, фрилансеров, благотворительности, физических точек продаж и POS-кассы.

ℹ️
API версия — v2

Все ручки инвойсов живут под префиксом /api/v2/integration/invoices/.... v1 эндпоинты выпилены 25.04.2026 — используйте только v2.

Права API-ключа: can_invoices_create для создания/отмены, can_invoices_read для чтения и получения ссылки.

Что умеет

  • Одноразовый инвойс. Фиксированная сумма + TTL до 30 дней. Крипто-счёт в сети создаётся без жёсткой суммы: зачисляется фактически полученное. Переплата — тот же success / invoice.paid с большим amount_received. Недоплата ≥ минимума сети — тоже success / invoice.paid с меньшим amount_received, не expired. expired ставится только если к TTL нет txid (платежа не было). Ниже минимума сети — failed, invoice.paid не уходит.
  • Открытая сумма (донаты). Не передавайте поле amount — плательщик сам впишет её на странице оплаты в пределах глобальных min/max.
  • Отложенный выбор валюты. Не передавайте symbol/bch_code — плательщик выберет монету и сеть на странице. Удобно для маркетплейсов.
  • Постоянный QR (шаблон). Один QR навсегда — каждый платёж порождает отдельный child invoice. Подходит для касс, парикмахерских, донат-страниц.
  • POS-API. Касса бьёт чек по шаблону через POST .../payments с idempotency_key и external_payment_id — повторный POST не создаёт дубль и доставляется обратно в webhook.
  • Хеджирование (автоконвертация). Получили USDT, а нужно хранить в BTC — флаг is_hedging + hedging_symbol сделают автоматический обмен после зачисления.
  • AlfaBit Checkout — оплата из баланса. У плательщика-юзера AlfaBit есть кнопка «Оплатить из AlfaBit». Перевод между балансами происходит мгновенно, без блокчейна и сетевой комиссии (payment_source="alfabit_balance", txid=null).
  • Komшия плательщика (shift_to_payer). Глобальная настройка платформы: либо комиссию вычитаем у получателя, либо увеличиваем сумму к оплате — плательщик платит сверху.
  • Webhooks. События invoice.created / paid / expired / cancelled / refunded / hedged (+ template.deactivated). URL задаётся отдельно через POST /api/v1/integration/webhooks — не в теле создания инвойса. HMAC-подпись, payload как GET /invoices/{invoice_id}.
  • Embed-виджет. AlfaBit Checkout встраивается прямо на ваш сайт через iframe / JS SDK / React / Vue без редиректа покупателя.
Минимальный сценарий за 5 минут
  1. Получите комиссии и лимиты: GET /api/v2/integration/invoices/settings.
  2. Создайте инвойс: POST /api/v2/integration/invoices с заголовком Idempotency-Key (свой UUID на каждый счёт) — получите invoice_id и payment_url. При таймауте повторите запрос с тем же ключом: вернётся тот же счёт, без дубля.
  3. Отправьте payment_url покупателю (ссылка/QR/iframe).
  4. Подпишитесь на webhook invoice.paid (раздел Webhooks).
  5. Опционально, опросите статус: GET /api/v2/integration/invoices/{invoice_id}.

Сценарии использования

Реальные паттерны, которые покрываются текущим API. Каждый сценарий — это связка эндпоинтов и параметров, которые работают на проде.

1. Интернет-магазин — счёт за конкретный заказ

Известна сумма и валюта. Хотите получить ровно её и отслеживать оплату по своему order_id.

POST /api/v2/integration/invoices
{
  "symbol": "USDT",
  "bch_code": "TRX",
  "amount": "100",
  "currency": "USDT",
  "description": "Order #ORD-12345 — iPhone case",
  "life_time_minutes": 30,
  "payment_policy": "all",
  "payer_email": "client@example.com",
  "show_receiver_publicly": false
}

В webhook `invoice.paid` вы получите тот же uid (invoice_id) — найдите его в своей БД по сохранённому маппингу order_id↔invoice_id и закройте заказ.

2. Фрилансер — счёт «оплати как удобно»

Сумма известна (в USDT), но клиенту удобнее заплатить TON или BTC. Дайте плательщику выбрать монету.

POST /api/v2/integration/invoices
{
  "amount": "250",
  "currency": "USDT",
  "description": "Frontend audit — May 2026"
}

Не передаём `symbol` и `bch_code` — на странице оплаты появится выбор монеты/сети. После выбора плательщиком эти поля заполнятся в ответе GET и в webhook.

3. Донаты / чаевые — открытая сумма

Получатель один, плательщиков много, каждый платит сколько хочет. Лучше оформить как постоянный QR (см. сценарий 5).

POST /api/v2/integration/invoices
{
  "symbol": "USDT",
  "bch_code": "TRX",
  "description": "Buy me a coffee ☕"
}

Нет `amount` → инвойс с открытой суммой. Плательщик вводит её в пределах min/max из GET /settings (в USDT-эквиваленте).

4. Получаю USDT — храню в BTC (хеджирование)

POST /api/v2/integration/invoices
{
  "symbol": "USDT",
  "bch_code": "TRX",
  "amount": "1000",
  "is_hedging": true,
  "hedging_symbol": "BTC"
}

После оплаты USDT автоматически конвертируется в BTC по курсу конвертера. В GET /settings виден `hedging_commission_percent` — это доп. комиссия за хеджирование.

Сколько BTC зачислено по факту — поля `hedged_amount` и `hedged_symbol` в GET /api/v2/integration/invoices/{invoice_id}. Конвертация выполняется уже после оплаты, поэтому в момент webhook `invoice.paid` они ещё null; готовый результат приходит отдельным событием `invoice.hedged`.

5. Постоянный QR на стене кафе

Один QR — много оплат. Каждый платёж становится отдельным child-инвойсом со своим адресом и TTL.

POST /api/v2/integration/invoices/v2/permanent
{
  "symbol": "USDT",
  "bch_code": "TRX",
  "description": "Coffee Shop on Tverskaya 7",
  "show_payments_count_publicly": true
}

Возвращается `template_uid` и `payment_url` — печатайте QR из URL. Плательщик с публичной страницы заводит свой child invoice (вводит сумму), оплачивает — приходит webhook `invoice.paid` с `parent_template_uid`. Счётчик `show_payments_count_publicly` показывает плательщикам сколько уже задонатили.

6. POS-касса — выбиваем чек по шаблону

Магазин уже один раз создал шаблон (см. сценарий 5). Теперь касса на каждый чек дёргает POST .../payments с idempotency_key и external_payment_id (свой ID чека).

POST /api/v2/integration/invoices/v2/permanent/{template_uid}/payments
{
  "amount": "12.50",
  "currency": "USDT",
  "description": "Receipt POS-AAA-9876",
  "external_payment_id": "POS-AAA-9876",
  "life_time_minutes": 15,
  "idempotency_key": "pos-aaa-9876-2026-05-15"
}

Повторный POST с тем же `idempotency_key` вернёт ТОТ ЖЕ child — никаких дублей. В webhook `invoice.paid` придёт `external_payment_id` и `parent_template_uid`, чтобы касса автоматически закрыла свой чек.

7. Принимаем только из AlfaBit (закрытое сообщество)

POST /api/v2/integration/invoices
{
  "symbol": "USDT",
  "amount": "10",
  "payment_policy": "alfabit_only"
}

Поле payment_policy: «all» (по умолчанию — обе кнопки), «alfabit_only» (только из баланса AlfaBit), «external_only» (только blockchain — кнопку «Оплатить из AlfaBit» не показываем).

Настройки и комиссии

Один эндпоинт чтобы получить актуальные комиссии, лимиты и доступность фич. Используйте перед созданием инвойса, чтобы валидировать сумму и показать комиссии плательщику.

GET/api/v2/integration/invoices/settings

Требуемое право: can_invoices_read.

Response
{
  "success": true,
  "data": {
    "is_active": true,
    "invoice_commission_percent": "0.5",
    "hedging_commission_percent": "0.5",
    "shift_commission_to_payer": false,
    "is_hedging_enabled": true,
    "min_invoice_amount_usdt": "1",
    "max_invoice_amount_usdt": "10000000",
    "default_lifetime_minutes": 1440,
    "min_lifetime_minutes": 5,
    "max_lifetime_minutes": 43200
  }
}

Поля

ПолеОписание
is_activeИнвойсы v2 включены глобально на платформе.
invoice_commission_percentБазовая комиссия за приём платежа в %.
hedging_commission_percentДополнительная комиссия при is_hedging=true.
shift_commission_to_payertrue — комиссия добавляется к сумме (плательщик платит сверху). false — вычитается из получаемой суммы.
is_hedging_enabledХеджирование доступно (если false — поле is_hedging в POST игнорируется).
min_invoice_amount_usdtМинимальная сумма инвойса в USDT-эквиваленте. Для не-USDT — пересчёт по курсу.
max_invoice_amount_usdtМаксимальная сумма инвойса в USDT-эквиваленте.
default_lifetime_minutesTTL по умолчанию в минутах — если не передаёте life_time_minutes.
min_lifetime_minutesМинимально допустимый TTL.
max_lifetime_minutesМаксимально допустимый TTL (43200 = 30 дней).

Создать инвойс

POST/api/v2/integration/invoices

Право: can_invoices_create. Возвращает payment_url и (если symbol/bch_code заданы) реквизиты для оплаты.

Рекомендуем передавать заголовок Idempotency-Key (приоритетнее body.idempotency_key): 8–36 символов A–Z a–z 0–9 - _, удобнее UUID. Один ключ = один счёт. Повтор с тем же ключом в течение 24 ч возвращает уже созданный инвойс — так безопасно ретраить после таймаута или обрыва. Новый ключ создаёт новый счёт. Если первый запрос ещё не успел сохраниться, повтор может вернуть HTTP 409 — подождите 2–3 секунды и повторите с тем же ключом.

Тело запроса

ПолеТипОписание
symbolstring?Валюта (USDT, BTC, ETH...). Если NULL — плательщик выберет на странице.
bch_codestring?Сеть (TRX, ETH, TON...). Если NULL — выбирает плательщик.
amountstring?Сумма как строка-decimal. NULL = открытая сумма.
currencystring?Валюта суммы. По умолчанию = symbol. Поддерживает USDT/USD как «единицу учёта».
descriptionstring? (≤500)Видно плательщику на странице и в QR-описании.
life_time_minutesint (1..43200)TTL в минутах. По умолчанию 60. Максимум 30 дней.
is_hedgingboolПосле зачисления автоматически конвертировать в hedging_symbol.
hedging_symbolstring?Целевая монета хеджирования (например BTC).
payer_emailstring?Email плательщика (опционально). Подставляется в AlfaBit Checkout; в GET Integration API не возвращается.
payment_policyenumall (default) / alfabit_only / external_only.
show_receiver_publiclybool (default true)Показывать ли имя/email получателя на публичной странице.
idempotency_keystring? (8..36)Ключ идемпотентности в теле. Если передан и заголовок Idempotency-Key — побеждает заголовок.
curl — Idempotency-Key
curl -X POST "https://alfabit.org/api/v2/integration/invoices" \
  -H "X-API-Key: pk_live_..." \
  -H "X-API-Signature: ..." \
  -H "X-API-Timestamp: ..." \
  -H "Idempotency-Key: 4b8c8a1e-3f2c-4f3a-9c0d-2b3a4b5c6d7e" \
  -H "Content-Type: application/json" \
  -d '{"amount":"100","currency":"RUB","payment_policy":"alfabit_only"}'
Request — minimal
{
  "symbol": "USDT",
  "bch_code": "TRX",
  "amount": "100"
}
Request — full
{
  "symbol": "USDT",
  "bch_code": "TRX",
  "amount": "250.50",
  "currency": "USDT",
  "description": "Order #ORD-12345",
  "life_time_minutes": 180,
  "is_hedging": true,
  "hedging_symbol": "BTC",
  "payment_policy": "all",
  "show_receiver_publicly": false,
  "idempotency_key": "4b8c8a1e-3f2c-4f3a-9c0d-2b3a4b5c6d7e"
}
Response
{
  "success": true,
  "data": {
    "invoice_id": "01J7HZ...",
    "status": "wait",
    "symbol": "USDT",
    "network": "TRX",
    "address": "TXa1B2...",
    "memo_tag": null,
    "amount_requested": "250.50",
    "amount_requested_currency": "USDT",
    "amount_to_pay": "250.50",
    "exchange_rate": null,
    "commission": {
      "commission_percent": "0.5",
      "commission_amount": "1.25",
      "is_paid_by_payer": false
    },
    "amount_received": null,
    "txid": null,
    "payment_source": "blockchain",
    "description": "Order #ORD-12345",
    "is_hedging": true,
    "hedging_symbol": "BTC",
    "is_payer_marked_paid": false,
    "payment_url": "https://alfabit.org/en/pub/invoice/order/01J7HZ...",
    "alfabit_payment_policy": "all",
    "is_open_amount": false,
    "show_receiver_publicly": false,
    "created_at": "1747325000",
    "expires_at": "1747335800"
  }
}

Поля symbol/network/address/memo_tag будут NULL, если вы создаёте инвойс с отложенным выбором валюты — заполнятся после того, как плательщик выберет монету и сеть на публичной странице.

Получить детали инвойса

GET/api/v2/integration/invoices/{invoice_id}

Право: can_invoices_read. Тот же DTO, что в POST /invoices. Дополнительно содержит alfabit_payment_route и alfabit_payer_symbol/network — если оплата прошла через AlfaBit Checkout. Для QR+KYC в payer_name приходит ФИО плательщика («И. Иван Иванович») из верификации; если связи нет — поля нет. Для инвойсов с автоконвертацией (is_hedging=true) здесь же лежит её итог: hedged_amount и hedged_symbol — фактически зачисленная сумма и монета. Конвертация идёт после оплаты, поэтому сразу после invoice.paid поля ещё null; момент готовности лучше ловить событием invoice.hedged, а не опросом.

Response — paid via AlfaBit balance
{
  "success": true,
  "data": {
    "invoice_id": "01J7HZ...",
    "status": "success",
    "symbol": "USDT",
    "network": "TRX",
    "address": "TXa1B2...",
    "amount_requested": "250.50",
    "amount_received": "250.50",
    "txid": null,
    "payment_source": "alfabit_balance",
    "alfabit_payment_route": "direct_internal_transfer",
    "alfabit_payer_symbol": "USDT",
    "alfabit_payer_network": "TRX",
    "alfabit_payment_intent_uid": "intent_01J...",
    "is_payer_marked_paid": true,
    "payer_name": "И. Иван Иванович",
    "payment_url": "https://alfabit.org/en/pub/invoice/order/01J7HZ...",
    "show_receiver_publicly": false,
    "created_at": "1747325000",
    "expires_at": "1747335800"
  }
}
⚠️
404 — если инвойс не найден или принадлежит другому пользователю.

Список инвойсов

GET/api/v2/integration/invoices

Право: can_invoices_read. Пагинация курсорная по page/limit. Каждый элемент — тот же объект, что в GET /invoices/{invoice_id}.

Query-параметры

ПараметрТип / диапазонОписание
statusstring?Фильтр: wait / success / failed.
limitint (1..100, default 50)Размер страницы.
pageint (≥1, default 1)Номер страницы.
GET /api/v2/integration/invoices?status=wait&limit=20&page=1
{
  "success": true,
  "data": [ /* массив объектов как в GET /invoices/{invoice_id} */ ],
  "pagination": {
    "total": 137,
    "limit": 20,
    "offset": 0
  }
}

Отменить инвойс

POST/api/v2/integration/invoices/{invoice_id}/cancel

Право: can_invoices_create. Отменить можно только в статусе wait. Переводит инвойс в failed. Если оплата уже получена (success / aml / blocked) — 409 INVALID_STATUS.

Response 200
{
  "success": true,
  "data": { /* тот же объект инвойса со status="failed" */ }
}
Response 409
{
  "success": false,
  "error": {
    "code": "INVALID_STATUS",
    "message": "Cannot cancel invoice in status 'success'"
  }
}

Ссылка на оплату

GET/api/v2/integration/invoices/{invoice_id}/payment-url

Право: can_invoices_read. Ссылка публичная — её можно отдать плательщику. Точно та же URL уже есть в поле payment_url любого ответа GET /invoices/{invoice_id}, эта ручка нужна когда не хочется тащить весь объект.

Response
{
  "success": true,
  "data": {
    "payment_url": "https://alfabit.org/en/pub/invoice/order/01J7HZ..."
  }
}

Постоянный QR / шаблон

Permanent invoice — это «шаблон». Один template_uid живёт вечно, каждая реальная оплата создаёт отдельный child invoice со своим адресом и TTL. Идеально для касс, постоянных QR на стене, donate-ссылок и POS-терминалов.

💡
Шаблон ≠ платёж

Сам шаблон не платёж — webhook invoice.created на него НЕ приходит. События invoice.paid / invoice.expired приходят на каждый child и содержат parent_template_uid + external_payment_id (если передан).

Лимит активных child одного шаблона — поле template_max_active_children в ответе GET шаблона (по умолчанию 100).

Зашить сумму в публичную ссылку/QR: добавьте к payment_url параметры ?amount=500&currency=RUB&fixed=1 — страница оплаты покажет сумму как фиксированную (ценник), плательщик изменить её не сможет. Без параметров — открытая сумма.

Создать шаблон

POST/api/v2/integration/invoices/v2/permanent

Право: can_invoices_create. Создаёт шаблон без разового платёжного ордера и без TTL (живёт пока is_active=true).

Тело запроса

ПолеТипОписание
symbolstring?Целевая валюта получателя. NULL = плательщик выберет на чеке.
bch_codestring?Сеть. Если задана — наследуется в каждый child.
currencystring?Дефолтная валюта суммы для child-чеков.
descriptionstring? (≤500)Публичное описание шаблона (видно всем плательщикам).
life_time_minutesint (1..43200, default 60)Дефолтный TTL для child-чеков.
is_hedgingboolХеджирование наследуется в child-чеки.
hedging_symbolstring?Целевая монета хеджирования.
payment_policyenumall / alfabit_only / external_only.
show_receiver_publiclyboolПоказывать имя/email получателя на странице.
show_payments_count_publiclyboolПоказывать счётчик SUCCESS-чеков на публичной странице.
Response
{
  "success": true,
  "data": {
    "template_uid": "01J8AB...",
    "status": "wait",
    "is_active": true,
    "payment_url": "https://alfabit.org/en/pub/invoice/permanent/01J8AB...",
    "invoice_currency": "USDT",
    "description": "Coffee Shop on Tverskaya 7",
    "payments_total": 0,
    "is_hedging": false,
    "hedging_symbol": null,
    "payment_policy": "all",
    "show_receiver_publicly": true,
    "show_payments_count_publicly": true,
    "template_max_active_children": 100,
    "created_at": "1747325000"
  }
}
GET/api/v2/integration/invoices/v2/permanent/{template_uid}

Текущее состояние шаблона + payments_total (счётчик SUCCESS-child). Право: can_invoices_read.

Выбить чек по шаблону (POS-API)

POST/api/v2/integration/invoices/v2/permanent/{template_uid}/payments

Право: can_invoices_create. Создаёт обычный child invoice с собственным адресом, TTL и ссылкой. Идемпотентно: повторный POST с тем же idempotency_key вернёт ТОТ ЖЕ child.

Тело запроса

ПолеТипОписание
amountstring (обяз.)Сумма чека (decimal-строка > 0).
currencystring?Валюта суммы. NULL — наследуется из шаблона.
life_time_minutesint? (1..43200)TTL чека. NULL = 60.
descriptionstring? (≤500)Видно плательщику на странице чека.
external_payment_idstring? (≤128)Ваш ID чека на стороне POS. Прилетает обратно в webhook invoice.paid / invoice.expired.
idempotency_keystring (8..64, обяз.)Защита от дубля чека. Повторный POST с тем же ключом не создаст второй child.
Response (child invoice)
{
  "success": true,
  "data": {
    "invoice_id": "01J8CD...",
    "status": "wait",
    "symbol": "USDT",
    "network": "TRX",
    "address": "TXa1B2...",
    "amount_requested": "12.50",
    "amount_requested_currency": "USDT",
    "amount_to_pay": "12.50",
    "payment_source": "blockchain",
    "description": "Receipt POS-AAA-9876",
    "payment_url": "https://alfabit.org/en/pub/invoice/order/01J8CD...",
    "alfabit_payment_policy": "all",
    "show_receiver_publicly": true,
    "created_at": "1747326000",
    "expires_at": "1747326900",
    "parent_template_uid": "01J8AB...",
    "external_payment_id": "POS-AAA-9876"
  }
}

Список чеков шаблона

GET/api/v2/integration/invoices/v2/permanent/{template_uid}/payments

Право: can_invoices_read. Все child-чеки данного шаблона с пагинацией. Поддерживает фильтры по status и external_payment_id (точное совпадение).

Query-параметры

ПараметрТип / диапазонОписание
statusstring?wait / success / failed / expired.
external_payment_idstring?Точное совпадение с переданным ранее ID чека.
limitint (1..200, default 50)Размер страницы.
pageint (≥1, default 1)Номер страницы.
Response (item)
{
  "uid": "01J8CD...",
  "status": "success",
  "invoice_amount": "12.50",
  "invoice_currency": "USDT",
  "amount_received": "12.50",
  "symbol": "USDT",
  "bch_code": "TRX",
  "txid": "0x1a2b3c...",
  "public_comment": "Receipt POS-AAA-9876",
  "external_payment_id": "POS-AAA-9876",
  "created_at": "1747326000",
  "finished_at": "1747326200"
}

Статусы и payment_source

📌
Как читать status

Поле status в GET /invoices/{invoice_id} и в webhook data.status — одно и то же. Смотрите таблицу ниже. Не путайте status (состояние счёта) с event (имя webhook-события).

status

ЗначениеЧто значитWebhook event
waitСчёт создан, ждём оплату. TTL ещё не истёк.invoice.created
successОплата получена и зачислена. amount_received — факт прихода; он может быть больше или меньше amount_requested, если сумма ≥ минимума сети.invoice.paid
expiredИстёк TTL и txid пустой: платежа не было. Если ончейн-перевод уже пришёл — счёт не уйдёт в expired.invoice.expired
failedОтмена мерчантом через POST /cancel — либо ончейн-платёж ниже минимума сети / пыль. Технический сбой создания инвойса статуса не даёт: инвойса нет.invoice.cancelled (только cancel; ниже минимума — хука нет, смотрите GET)
refundedПровайдер вернул платёж плательщику (например, несовпадение ФИО на QR+KYC). Деньги мерчанту не зачислялись.invoice.refunded
amlОплата получена, но заморожена AML. Решает саппорт.
blockedБлок по политике безопасности.

Вебхуков invoice.aml / invoice.blocked нет: заморозку AML смотрите опросом GET /api/v2/integration/invoices/{invoice_id}. После invoice.paid со status=success переход в aml / blocked не предусмотрен — AML выполняется до зачисления. Второй перевод на тот же адрес после записанного txid тот же invoice_id повторно не закрывает.

payment_source

ЗначениеЧто значит
blockchainОплата on-chain. Есть txid и сетевая комиссия. По умолчанию для status=wait.
alfabit_balanceОплата с баланса AlfaBit. txid=null. Заполнены alfabit_payment_route / alfabit_payer_symbol / alfabit_payer_network / alfabit_payment_intent_uid.

Webhooks инвойсов

⚠️
URL webhook НЕ передаётся в POST /invoices

Поля callback_url / webhook_url в теле создания инвойса нет и не будет. Адрес задаётся один раз на аккаунт через Integration Webhooks API (или Developer Console → Webhooks). После подписки события по всем вашим инвойсам уходят на этот URL.

1. Как подключить

POST /api/v1/integration/webhooks
{
  "url": "https://your.domain/hooks/alfabit",
  "events": [
    "invoice.created",
    "invoice.paid",
    "invoice.expired",
    "invoice.cancelled",
    "invoice.refunded",
    "invoice.hedged"
  ]
}

Ответ вернёт secret один раз — сохраните его для проверки HMAC (заголовок X-Webhook-Signature). Управление: GET/PATCH/DELETE /api/v1/integration/webhooks/{id}, логи доставки: GET .../webhooks/{id}/logs. Тот же список событий: GET /api/v1/integration/webhooks/events.

2. Формат доставки

HTTP POST на ваш url
Headers:
  Content-Type: application/json
  X-Webhook-Event: invoice.paid
  X-Webhook-Signature: <hmac-sha256 hex>

Body:
{
  "event": "invoice.paid",
  "timestamp": "2026-07-21T11:17:55Z",
  "signature": "<same hmac>",
  "data": { /* см. ниже */ }
}

Подпись считается от конверта {event, timestamp, data} без поля signature, приведённого к каноническому JSON — точный алгоритм и примеры проверки на Python / Node.js см. в разделе Webhooks → «Проверка подписи (HMAC)».

3. События и status в data

eventdata.statusКогда
invoice.createdwaitСразу после успешного POST /api/v2/integration/invoices (и UI). На шаблон permanent НЕ шлётся.
invoice.paidsuccessОплата зачислена (blockchain или AlfaBit balance), в т.ч. child permanent. Сверяйте amount_received: он может отличаться от номинала (переплата или недоплата ≥ минимума сети).
invoice.expiredexpiredИстёк TTL и txid пустой. Недоплата с уже пришедшим платежом сюда не попадает.
invoice.cancelledfailedМерчант вызвал POST /api/v2/integration/invoices/{invoice_id}/cancel.
invoice.refundedrefundedПровайдер вернул платёж плательщику. Деньги мерчанту не зачислялись.
invoice.hedgedsuccessАвтоконвертация (is_hedging) завершена: в data приходят hedged_amount и hedged_symbol — сколько фактически зачислено в целевой монете.
invoice.template.deactivatedДеактивирован шаблон permanent invoice.

Отдельного event invoice.failed нет. Отмену мерчантом отслеживайте по invoice.cancelled, просрочку без платежа — по invoice.expired, возврат провайдера — по invoice.refunded. Платёж ниже минимума сети ставит status=failed без вебхука — смотрите GET. Заморозку AML тоже только GET (status=aml / blocked).

4. Поля data

Пример invoice.paid
{
  "invoice_id": "9b854097-3de2-42aa-9f9c-1c0412058c73",
  "status": "success",
  "symbol": "USDT",
  "network": "BSC",
  "address": "0x9760...",
  "memo_tag": null,
  "amount_requested": "10",
  "amount_requested_currency": "USDT",
  "amount_received": "10",
  "txid": "0x1a2b...",
  "description": null,
  "is_hedging": false,
  "hedging_symbol": null,
  "is_payer_marked_paid": false,
  "payer_name": "И. Иван Иванович",
  "payment_source": "blockchain",
  "payment_url": "https://alfabit.org/en/pub/invoice/order/9b854097-...",
  "created_at": "1784631832.0136988",
  "expires_at": "1784632732.0136988",
  "fee_breakdown": {
    "invoice_fee_mode": "deduct_from_amount",
    "fiat_topup_fee_mode": "payer",
    "currency": "USDT"
  },
  "alfabit_payment_intent_uid": null,
  "alfabit_payment_route": null,
  "alfabit_payer_symbol": null,
  "alfabit_payer_network": null,
  "parent_template_uid": null,
  "external_payment_id": null
}

Поля совпадают с ответом GET /api/v2/integration/invoices/{invoice_id} (data). Для оплаты с баланса AlfaBit: txid=null, payment_source=alfabit_balance, заполнены alfabit_*. Для child permanent: parent_template_uid; external_payment_id — если передавали в POS-API. Для QR+KYC: payer_name — ФИО плательщика («И. Иван Иванович») из верификации; если связи нет — поля нет.

Пример invoice.hedged
{
  "invoice_id": "9b854097-3de2-42aa-9f9c-1c0412058c73",
  "hedged_amount": "0.01324718",
  "hedged_symbol": "BTC"
}

Приходит только для инвойсов с is_hedging=true и только после успешной автоконвертации — то есть уже ПОСЛЕ invoice.paid, отдельным запросом. hedged_amount — фактически зачисленная сумма в hedged_symbol (курс и комиссия хеджирования уже учтены). Те же два поля доступны в GET /api/v2/integration/invoices/{invoice_id}: пока конвертация не завершилась, они null.

KYC-API чекаут (KYC+QR)

Второй, равноправный способ приёма RUB-платежей — целиком через API, без нашей платёжной страницы. Весь UI (форма, загрузка документов, показ QR) — на вашей стороне; плательщик остаётся на вашем сайте. Подходит обменникам и криптопроектам, которым нужен полный контроль над UX.

⚖️
Два флоу — оба поддерживаются

1) Hosted invoice: POST /integration/invoices → payment_url → плательщик оплачивает на нашей странице (KYC на нашей стороне). 2) KYC-API чекаут (эта секция): вы сами собираете документы плательщика, отправляете их нам, получаете QR и показываете его в своём интерфейсе. Какой флоу доступен вашему аккаунту — определяется профилем приёма (назначает AlfaBit).

Флоу

Схема
1. POST /api/v1/integration/checkout/payments
   { amount, payer_phone, payer_ip, external_payment_id, ... }
   → status=kyc_required            (инвойс НЕ создаётся)
2. POST /api/v1/integration/checkout/payers/{phone}/documents
   (multipart: doc_type + file — паспорт главная стр., прописка)
   → kyc_status=pending, processing=true   (это НЕ финальный статус)
3. GET  /api/v1/integration/checkout/payers/{phone}
   опрашивать каждые 1–2 сек, пока processing=true
   → kyc_status=approved + expected_payer_name
   → processing=false и pending / manual_review=true → ручная сверка
     (те же фото заново не отправлять)
   → kyc_status=retry, client_action_required=true → нужны новые документы:
     покажите плательщику retry_comment и вернитесь к шагу 2
4. POST /api/v1/integration/checkout/payments  (обязательно повторно)
   → payment_uid, status=created    (без этого шага QR не будет)
5. GET  /api/v1/integration/checkout/payments/{uid}
   → qr_url / qr_payload            (СБП-реквизиты, когда готовы)
6. Webhook invoice.paid             (оплата прошла, ФИО плательщика совпало)
   или invoice.refunded             (провайдер вернул платёж, например ФИО не совпало)

Телефон в PATH — только цифры, без «+»:
  /payers/79001234567
В JSON-теле payer_phone можно передавать +79001234567 — мы нормализуем.
Вебхука на смену KYC плательщика нет: статус только GET (или повторный POST /payments).
POST/api/v1/integration/checkout/payments

Право: can_invoices_create. Создаёт RUB-платёж. Если профиль приёма требует верификацию плательщика и телефон ещё не approved — вернёт kyc_required: инвойс и QR на этом шаге не создаются. После загрузки документов и GET-статуса approved этот же POST нужно вызвать повторно — иначе QR не появится. payer_phone — ключ верификации: один раз проверенный плательщик далее платит без повторной загрузки документов. Обязательные антифрод-поля: payer_ip (IP конечного плательщика, IPv4/IPv6) и external_payment_id (номер заявки в вашей системе, для сверки — не защищает от дубля). Опционально: payer_user_agent, payer_device_id (fingerprint устройства).

amount — всегда сумма, которую вы получите на баланс. Кто платит нашу комиссию приёма — опциональное поле invoice_fee_mode: deduct_from_amount (по умолчанию, комиссия вычитается из amount при зачислении — как раньше) или payer (сумма в СБП QR увеличивается на комиссию сверху, вы получаете полный amount). Точная ставка и суммы — в ответе ниже (commission_percent, commission_amount, amount_to_pay) и заранее в GET /channels.

Передавайте idempotency_key (8–64 символа), если хотите безопасно ретраить при обрыве связи: повтор с тем же ключом в течение 24 ч не создаст второй платёж — вернётся уже созданный (тот же payment_uid/QR); если исходный запрос ещё выполняется — HTTP 409 IDEMPOTENCY_IN_FLIGHT, повторить с тем же ключом позже. external_payment_id сам по себе от дубля не защищает — это просто ваш ID для сверки. Ключ действует только на сам факт создания платежа: на ответ kyc_required не влияет, и тот же ключ нужно переиспользовать в повторном POST на шаге 4 (после approve плательщика) — так и задумано, платёж создастся один раз.

Request
{
  "amount": "5000.00",
  "external_payment_id": "MM-1234",
  "idempotency_key": "order-mm-1234-attempt-1",
  "description": "Order #1234",
  "payer_phone": "+79001234567",
  "payer_ip": "203.0.113.10",
  "payer_user_agent": "Mozilla/5.0 ...",
  "payer_device_id": "fp_7c9e6679",
  "invoice_fee_mode": "deduct_from_amount"
}
Response (нужен KYC)
{
  "success": true,
  "data": {
    "status": "kyc_required",
    "kyc_required": true,
    "payer_status": "not_started",
    "processing": false,
    "manual_review": false,
    "client_action_required": false,
    "retry_comment": null,
    "required_documents": ["passport_main", "passport_registration"],
    "commission_percent": "1.0",
    "upload_documents_endpoint": "/api/v1/integration/checkout/payers/79001234567/documents",
    "poll_status_endpoint": "/api/v1/integration/checkout/payers/79001234567"
  }
}
Response (платёж создан)
{
  "success": true,
  "data": {
    "payment_uid": "01J8...",
    "external_payment_id": "MM-1234",
    "status": "created",
    "amount": "5000.00",
    "amount_to_pay": "5000.00",
    "currency": "RUB",
    "invoice_fee_mode": "deduct_from_amount",
    "commission_percent": "1.0",
    "commission_amount": "50.00"
  }
}

amount_to_pay — сумма, реально зашитая в СБП QR (то, что должен отправить плательщик). При invoice_fee_mode=payer она больше amount ровно на commission_amount; при deduct_from_amount (как в примере выше) она равна amount, а commission_amount будет вычтен из зачисления.

POST/api/v1/integration/checkout/payers/{phone}/documents

Право: can_invoices_create. Multipart-загрузка документа плательщика: поля doc_type (passport_main | passport_registration | selfie) и file (JPEG/PNG/PDF, до 25 МБ). Рекомендуемые антифрод-поля (form-data): payer_ip, payer_user_agent, payer_device_id.

Ответ приходит сразу после приёма файлов, с processing: true — это не финальный статус. Распознавание идёт в фоне несколько секунд. Финальный статус только GET /payers/{phone} (путь в poll_status_endpoint): пока processing: true — опрашивайте. Когда kyc_status=approved — повторите POST /payments. processing: false при pending / manual_review=true — заявка у оператора, те же файлы заново не отправляйте. А вот при kyc_status=retry загрузка нужна: оператор оставил замечание в retry_comment и ждёт новый комплект — те же самые фото присылать бесполезно. В path телефона «+» не ставьте (иначе + декодируется как пробел): /payers/79001234567, не /payers/+79001234567.

Response
{
  "success": true,
  "data": {
    "phone": "+79001234567",
    "kyc_status": "pending",
    "expected_payer_name": null,
    "low_confidence": false,
    "processing": true,
    "poll_status_endpoint": "/api/v1/integration/checkout/payers/79001234567"
  }
}

Из главной страницы паспорта распознаётся ФИО — после approved верните его плательщику с предупреждением «оплата ожидается именно от {ФИО}»: банк сверит фактического отправителя с паспортом. Имя отдаёт GET /payers/{phone} в поле expected_payer_name — в маскированном виде «И. Иван Иванович» (инициал фамилии + имя + отчество), как принято в СБП. Плательщик по нему узнаёт себя, а полная фамилия наружу не уходит.

Повторная отправка запроса безопасна: тот же файл, загруженный ещё раз под тем же doc_type, не создаёт дубликат документа.

GET/api/v1/integration/checkout/payers/{phone}

Право: can_invoices_read. Статус верификации плательщика по телефону: not_started | pending | retry | approved | rejected. pending — проверяем мы, retry — ждём новые документы от плательщика. Телефон в URL — 11 цифр без «+» (/payers/79001234567). Используйте после загрузки документов (опрос, пока processing=true) и перед повторным POST /payments. Вебхука на смену KYC нет.

processing: true — OCR ещё идёт, статус не финальный, опросите через 1–2 секунды. processing: false и kyc_status=approved — повторите POST /payments, получите QR. processing: false при pending / manual_review=true — автоматическая проверка закончилась, заявка у оператора; это не «зависший OCR». kyc_status=retry и client_action_required=true — к документам есть замечание: сам по себе статус уже не изменится, покажите плательщику текст из retry_comment и загрузите новый комплект (POST /documents).

Response
{
  "success": true,
  "data": {
    "phone": "+79001234567",
    "kyc_status": "approved",
    "verified_at": "2026-07-27T10:39:26.657298+00:00",
    "expected_payer_name": "И. Иван Иванович",
    "required_documents": ["passport_main", "passport_registration"],
    "processing": false,
    "manual_review": false,
    "client_action_required": false,
    "retry_comment": null
  }
}
GET/api/v1/integration/checkout/payments/{uid}

Право: can_invoices_read. Статус платежа + СБП-реквизиты: qr_url (ссылка NSPK) и qr_payload появляются, как только платёжная система их сгенерирует (обычно секунды). Терминальные статусы приходят также webhook’ами invoice.paid / invoice.expired / invoice.refunded. Для QR+KYC оба имени — payer_name и expected_payer_name — приходят в маскированном виде «И. Иван Иванович».

Response
{
  "success": true,
  "data": {
    "payment_uid": "01J8...",
    "status": "success",
    "amount": "5000.00",
    "currency": "RUB",
    "qr_url": "https://qr.nspk.ru/...",
    "qr_payload": "https://qr.nspk.ru/...",
    "expected_payer_name": "И. Иван Иванович",
    "payer_name": "И. Иван Иванович"
  }
}
GET/api/v1/integration/checkout/channels

Право: can_invoices_read. Набор СБП-каналов приёма, назначенных вашему аккаунту (код, название, комиссия). Конкретный канал для платежа можно выбрать полем channel при создании — из своего набора.

Response
{
  "success": true,
  "data": {
    "channels": [
      { "code": "sbp_1", "name": "SBP #1", "fee_percent": 1.0 }
    ],
    "commission_percent": "1.0"
  }
}

commission_percent (верхнего уровня) — эффективная ставка нашей комиссии приёма для вашего аккаунта. Это авторитетное значение для планирования amount/invoice_fee_mode в POST /payments заранее, до создания платежа; fee_percent внутри channels — информативное поле конкретного канала.

Встраиваемый виджет (Embed)

Встраивайте платёжный виджет AlfaBit Checkout прямо на свой сайт — модальное окно, inline-блок или iframe. Юзер не покидает страницу и не редиректится. Аналог Stripe Elements / PayPal Buttons.

Как встроить виджет
  1. Создайте инвойс через POST /api/v2/integration/invoices — получите invoice_id (uid)
  2. Подключите SDK с CDN или через npm @alfabit/checkout-js
  3. Откройте виджет: AlfaBitCheckout.open(uid) или mount(...)
  4. Слушайте события onSuccess / onError или подпишитесь на postMessage

1. Pure iframe (без JS)

Простейший вариант — для статичных лендингов и Telegram-mini-app. Просто <iframe>:

<iframe
  src="https://alfabit.org/{lang}/embed/invoice/order/{uid}?theme=dark&primary=9ee248"
  width="100%"
  height="640"
  frameborder="0"
  allow="payment *; camera; microphone">
</iframe>

2. JS SDK (modal popup)

Кнопка «Оплатить» рядом с товаром — клик открывает модалку:

<script src="https://alfabit.org/checkout/v1/checkout.umd.js"></script>
<button onclick="AlfaBitCheckout.open('{uid}')">Pay</button>

3. Inline-mount

Виджет встраивается в layout сайта, без модалки:

<div id="alfabit-checkout"></div>
<script>
  AlfaBitCheckout.mount('#alfabit-checkout', {
    invoice: '{uid}',
    theme: 'auto',
    primary: '#9ee248',
    locale: 'ru',
    onSuccess: (e) => { window.location = '/thank-you' },
  });
</script>

4. React / Vue

// React
import AlfaBitCheckout from '@alfabit/checkout-js';

<button onClick={() => AlfaBitCheckout.open('{uid}', { theme: 'dark' })}>
  Pay
</button>

События (postMessage)

EventPayloadКогда
alfabit:ready{ invoice_uid, currency, amount }iframe загрузился
alfabit:resize{ height }для inline
alfabit:payment.completed{ invoice_uid, amount, currency }оплачено
alfabit:payment.failed{ invoice_uid, error, message }отклонено
alfabit:payment.cancelled{ invoice_uid }юзер закрыл
alfabit:payment.expired{ invoice_uid }истёк

Параметры виджета

ПараметрТип / DefaultОписание
invoicestring (required)uid инвойса из POST /api/v2/integration/invoices
type'order' | 'permanent' / 'order'Одноразовый или постоянный QR
theme'auto' | 'light' | 'dark' / 'auto'Тема виджета
primaryhex / '#9ee248'Акцентный цвет (6 hex)
locale'ru' | 'en' / 'ru'Язык
heightnumber / 640Высота для inline
onSuccessfunctionКолбэк при успешной оплате
💡
Готовый snippet в один клик

После создания счёта в кошельке в success-modal есть кнопка «Встроить на сайт». Откроется модалка с готовыми snippet'ами для всех 5 платформ (HTML, JS SDK, React, Vue, Telegram), live preview виджета и настройками темы / цвета. Просто скопируйте код.

🔒
Безопасность

Реальные страницы /pub/invoice/* защищены X-Frame-Options: SAMEORIGIN. Виджет загружается с отдельного префикса /embed/invoice/* с CSP frame-ancestors *. SDK фильтрует postMessage по origin (только alfabit.org или ваш baseUrl). primary валидируется regex (6 hex chars), theme/locale — строгий enum. Авторизация юзера для оплаты «с баланса AlfaBit» — через popup-окно SSO, не в самом iframe.

SDK подключается с CDN: https://alfabit.org/checkout/v1/checkout.umd.js или через npm: @alfabit/checkout-js

Travel

Бронирование авиабилетов и отелей за криптовалюту, фиат или со счёта Wallet. API поддерживает полный цикл от поиска до управления заказами.

💳
Способы оплаты

Криптовалюта (USDT, BTC, ETH), фиат (RUB) через инвойс, или мгновенная оплата со счёта Wallet.

🚧
Песочница (Sandbox)

Раздел находится в разработке. Пока используйте Production-окружение для интеграции.

ОкружениеBase URLAPI ключ
Productionhttps://alfabit.orgСоздайте API ключ в Developer Console
🔐
Права API ключа

Чтение данных (поиск, заказы) — can_travel_read. Бронирование и оплата — can_travel_book. Возврат денег — can_travel_refund (для refund-ручек avia/order/refund и cancel оплаченной брони). Старые ключи с can_travel_book автоматически получают и refund-доступ — обратная совместимость не нарушена.

🔁
Идемпотентность (Idempotency-Key)

Все мутирующие endpoint'ы поддерживают заголовок Idempotency-Key. Передавайте уникальный UUID на каждую операцию — повторный запрос с тем же ключом в течение 24 часов вернёт ранее сохранённый ответ без второго списания/брони.

Поддерживается на:

  • Отели: book, pay/crypto, pay/wallet, cancel, create-order, create-order-with-view, create-order-and-select-room, select-room
  • Авиа: book, pay/crypto, pay/wallet, order/{uuid}/cancel, order/{uuid}/refund
Idempotency-Key: 550e8400-e29b-41d4-a716-446655440000

Формат ключа: A-Z, a-z, 0-9, дефис, подчёркивание (1-128 символов). Пробелы, двоеточия и спецсимволы — 400 INVALID_IDEMPOTENCY_KEY.

📡
Webhook-события Travel

Вместо постоянного polling /order/status подпишитесь на события через POST /api/v1/integration/webhooks. Доступные события для отелей:

  • travel.hotel_order.created — создан черновик заказа
  • travel.hotel_order.booked — забронирован у провайдера, ожидает оплаты
  • travel.hotel_order.paid — заказ оплачен
  • travel.hotel_order.confirmed — отель подтвердил бронь
  • travel.hotel_order.cancelled — заказ отменён
  • travel.hotel_order.refunded — возврат средств выполнен
  • travel.hotel_order.failed — ошибка бронирования/оплаты

Для авиа аналогичные события: travel.avia_order.created/booked/paid/cancelled/refunded/failed.

Флоу бронирования (одинаковый для авиа и отелей)
ПоискВыборЗаказБроньОплата

Каждый шаг возвращает данные, необходимые для следующего. Например, search возвращает recommendation_id, который используется в create-order.

Общее

GET/api/v1/integration/travel/rates

Текущие курсы USDT/RUB и USDT/KGS для расчёта стоимости.

Response
{ "success": true, "data": { "usdt_rub": 92.5, "usdt_kgs": 89.1 }, "ts": 1706000000 }

✈️ Авиабилеты

POST/api/v1/integration/travel/avia/search

Поиск авиарейсов с рекомендациями. Укажите сегменты маршрута, количество пассажиров по типам и класс обслуживания. Возвращает recommendation_id, которые используются в /create-order.

Request body
{
  "adt": 1,                               // adults: 1-9
  "chd": 0,                               // children: 0-9
  "inf": 0,                               // infants: 0-9
  "trip_class": "e",                      // e / b / f
  "segments": [                           // массив сегментов (1 = OW, 2 = RT, 3+ = multi-city)
    { "from": "SVO", "to": "LED", "date": "2026-06-15" },
    { "from": "LED", "to": "SVO", "date": "2026-06-20" }
  ],
  "lang": "ru"
}
Response 200 (важные поля)
{
  "success": true,
  "data": {
    "flights": [
      {
        "id": "21DKEASYOWE100...",              // длинный ID рейса
        "recommendation_id": "21DKEASYOWE100...", // алиас на id (для удобства)
        "duration": 185,                         // общая длительность в минутах
        "segments_direction": [
          {
            "direction": 0,
            "segments": [
              {
                "dep": { "city": "Frankfurt", "airport_code": "FRA", "datetime": "15.06.2026 17:35:00", "ts": 1781534100 },
                "arr": { "city": "Istanbul", "airport_code": "SAW", "datetime": "15.06.2026 21:40:00", "ts": 1781548800 },
                "flight_info": { "flight_number": "996", "airline": "Pegasus Airlines", "airline_code": "PC" },
                "baggage": { "is_baggage": false, "baggage_pieces": 0 }
              }
            ]
          }
        ],
        "short_result": {
          "duration": 185,
          "isBaggage": true, "baggageWeight": 20, "baggagePiece": 1,
          "transfers": []
        },
        "price": { /* цены в разных валютах */ },
        "hash": "ce7069..."
      }
    ]
  },
  "ts": 1714063200
}

// Используйте flights[N].recommendation_id (или flights[N].id) для:
//   GET  /avia/fare-families?recommendation_id=...
//   POST /avia/create-order  { recommendation_id, ... }
//   POST /avia/book          { recommendation_id, ... }
GET/api/v1/integration/travel/avia/fare-families?recommendation_id=...&lang=ru

Семейства тарифов для выбранного рейса: багаж, возврат, обмен.

POST/api/v1/integration/travel/avia/create-order

Создать заказ на авиабилеты по выбранной рекомендации.

POST/api/v1/integration/travel/avia/select-tariff

Выбрать тариф (эконом, бизнес и т.д.) для заказа.

POST/api/v1/integration/travel/avia/book

Бронирование рейса с данными пассажиров. РЕКОМЕНДУЕТСЯ передавать Idempotency-Key — повторный запрос не создаст вторую бронь.

Request body
{
  "order_uuid": "550e8400-e29b-41d4-a716-446655440000",
  "recommendation_id": "REC_12345",        // ОБЯЗАТЕЛЬНО. Если выбирали тариф — nonUpgradedId /
                                           // upgradeId из /avia/fare-families, иначе тот же id,
                                           // что в /avia/create-order
  "client_email": "user@example.com",
  "client_phone": "+79001234567",
  "passengers": [
    {
      "first_name": "IVAN",                // КАК В ПАСПОРТЕ — латиницей для международных рейсов
      "last_name": "IVANOV",
      "type": "adt",                       // adt / chd / inf
      "birth_date": "1990-01-15",          // YYYY-MM-DD
      "document_type": "passport",         // passport / national_id / birth_certificate (для inf)
      "document_number": "1234567890",
      "document_expire": "2030-01-15",
      "citizenship": "RU",
      "sex": "M"                           // M / F
    }
  ],
  "lang": "ru"
}
Header (рекомендуется)
Idempotency-Key: 550e8400-e29b-41d4-a716-446655440000
Response 200
{
  "success": true,
  "data": {
    "order_uuid": "550e8400-e29b-41d4-a716-446655440000",
    "billing_number": "BN-AVIA-2026-78901",
    "status": "booked",
    "ticket_time_limit": "2026-04-25T22:00:00Z"   // до этого времени надо оплатить
  },
  "ts": 1714063200
}
POST/api/v1/integration/travel/avia/pay/crypto

Оплата криптой/фиатом через инвойс. Возвращает адрес/QR для оплаты. Поддерживает Idempotency-Key.

Request body
{
  "order_uuid": "550e8400-e29b-41d4-a716-446655440000",
  "currency_in_code": "USDT_TRC20"   // USDT_TRC20 / BTC / ETH / RUB / ...
}
Response 200
{
  "success": true,
  "data": {
    "invoice_id": "INV-AVIA-12345",
    "deposit_address": "TQn9Y2khEsLJW1ChVWFMSMeRDow5KcbLSE",
    "qr_code_url": "https://...",
    "amount": "95.50",
    "currency": "USDT_TRC20",
    "expires_at": "2026-04-25T22:00:00Z"
  },
  "ts": 1714063200
}
POST/api/v1/integration/travel/avia/pay/wallet

Мгновенная оплата со счёта Wallet. Средства списываются сразу. КРИТИЧНО передавать Idempotency-Key — иначе повторный запрос спишет дважды.

Request body
{
  "order_uuid": "550e8400-e29b-41d4-a716-446655440000",
  "currency": "USDT"
}
Header (КРИТИЧНО)
Idempotency-Key: 550e8400-e29b-41d4-a716-446655440000
Response 200
{
  "success": true,
  "data": {
    "order_uuid": "550e8400-e29b-41d4-a716-446655440000",
    "status": "paid",
    "paid_at": "2026-04-25T20:05:00Z",
    "amount_charged": "95.50",
    "currency": "USDT",
    "balance_after": "1054.50",
    "ticket_status": "issued"           // issued / pending / failed
  },
  "ts": 1714063200
}
GET/api/v1/integration/travel/avia/wallet/balance?currency=USDT

Баланс Wallet для оплаты авиабилетов.

GET/api/v1/integration/travel/avia/orders

Все ваши заказы на авиабилеты.

GET/api/v1/integration/travel/avia/order/{order_uuid}

Детали заказа: маршрут, пассажиры, статус, стоимость.

GET/api/v1/integration/travel/avia/order/{order_uuid}/status

Статус заказа: created, booked, pay_waiting, ticketed, cancelled, refunded.

GET/api/v1/integration/travel/avia/order/{order_uuid}/pdf

Скачать PDF маршрутной квитанции / электронного билета.

POST/api/v1/integration/travel/avia/order/{order_uuid}/cancel

Отмена бронирования авиабилета.

POST/api/v1/integration/travel/avia/order/{order_uuid}/refund

Возврат средств за авиабилет (добровольный или вынужденный).

GET/api/v1/integration/travel/avia/passengers

Сохранённые пассажиры для быстрого бронирования.

🏨 Отели

Справочники

GET/api/v1/integration/travel/hotels/destination?part=Mosc&lang=ru

Автокомплит городов и регионов для поиска отелей.

GET/api/v1/integration/travel/hotels/cities/search?q=Mosc&limit=15

Поиск канонических городов по нашему словарю (быстрый, не идёт к провайдеру). Это отдельный справочник: его hotel_city_id НЕ подходит для поля city в поиске отелей — там нужен id из /hotels/destination.

GET/api/v1/integration/travel/hotels/avia-bridge?hotel_id=12345

Связка «отель → IATA города → аэропорты рядом» — для кросс-продажи авиабилетов после выбора отеля.

Поиск

POST/api/v1/integration/travel/hotels/search

Синхронный поиск отелей по городу, датам и количеству гостей. Может занимать 30-60 сек. Для UX рекомендуется /search/async.

Request body
{
  "city": "7000546",                  // числовой id из /hotels/destination.
                                      // НЕ название города и НЕ hotel_city_id из /hotels/cities/search
  "check_in": "15.05.2026",           // строго dd.mm.yyyy — с точками, иначе 400
  "check_out": "20.05.2026",
  "adults": 2,                        // 1-6
  "children": [{ "child_age": 5 }],   // optional
  "lang": "ru"
}
Response 200
{
  "success": true,
  "data": {
    "search": { "city": "7000546", "check_in": "15.05.2026", ... },
    "hotels": [
      {
        "id": "12345",
        "name": "Hotel Example",
        "stars": 4,
        "city": "Москва",
        "country": "Россия",
        "address": "...",
        "photos": [{ "url": "...", "thumb": "...", "is_default": true }],
        "rooms": [...],
        "hs": "search-hash-for-view"
      }
    ],
    "is_completed": true
  },
  "ts": 1714063200
}
POST/api/v1/integration/travel/hotels/search/async

Асинхронный поиск с Redis-кэшем и gzip-стримом. Возвращает первую порцию + agent_hash для polling. Рекомендуется для UX с прогрессивной загрузкой.

Request
{
  "city": "7000546",                  // числовой id из /hotels/destination
  "check_in": "15.05.2026",           // строго dd.mm.yyyy
  "check_out": "20.05.2026",
  "adults": 2,
  "children": [],
  "lang": "ru"
}
GET/api/v1/integration/travel/hotels/search/async-by-hash?search_hash=...&search_params_hash=...&lang=ru

Polling асинхронного поиска. Дёргайте, пока в ответе не придёт is_completed: true. Тело отдаётся gzip-стримом.

POST/api/v1/integration/travel/hotels/search/create-hash

Низкоуровнево: создать только agent_hash без запуска поиска. Обычно достаточно /search/async.

POST/api/v1/integration/travel/hotels/search/by-ids

Поиск предложений по списку известных hotel_ids — для избранного, истории просмотров.

POST/api/v1/integration/travel/hotels/search/view

Доступные номера в конкретном отеле с ценами и условиями отмены.

Request body
{
  "hotel_id": "12345",
  "check_in": "15-05-2026",           // dd-mm-yyyy
  "check_out": "20-05-2026",
  "adults": 2,
  "children": [{ "child_age": 5 }],
  "lang": "ru"
}
Response 200 (важные поля)
{
  "success": true,
  "data": {
    "hs": "eyJob3RlbF9pZCI6IjQxODUzMyIsImhzIjpudWxsLCJjaGVja19pbiI6...",
                                        // передавайте строку как есть в /check-rate и /book.
                                        // Это base64 параметров просмотра; при поиске по hotel_id
                                        // внутри лежит "hs": null — это нормально, не блокирует бронь
    "hotel": {
      "id": "12345",
      "name": "Hotel Example",
      "rooms": [
        {
          "id": "149e71dd-3257-43e3-8f06-9bb51208a270",  // UUID, внутренний ключ.
                                             // НЕ передавайте его в rate_id — провайдер его не знает
          "identifier": "418533..roomOnly..Улучшенный..19082026..835828f9..30,30",
                                             // ЭТО и есть идентификатор тарифа:
                                             // → recommendation_id в /select-room
                                             // → rate_id в /check-rate и /book
          "name": "Standard Double",
          "type": "DBL",
          "price": 12500.00,                 // в валюте провайдера
          "totalAmount": 12500.00,
          "mealType": "BB",                  // BB / HB / FB / AI
          "isFreeCancellation": true,
          "freeCancellationBefore": "...",
          "is_non_refundable": false,
          "cancelationRules": [...],         // → cancellation_policy_rules для /book
          "available_count": 3
        }
      ]
    }
  },
  "ts": 1714063200
}
GET/api/v1/integration/travel/hotels/search/view-by-hash?hotel_id=...&hs=...&lang=ru

Быстрый просмотр номеров по hs из шага поиска (без повторного запроса /view).

GET/api/v1/integration/travel/hotels/hotel/{hotel_id}?lang=ru

Данные об отеле: описание, фото, рейтинг, удобства.

POST/api/v1/integration/travel/hotels/check-rate

Финальная проверка цены и правил отмены ОБЯЗАТЕЛЬНО перед /book. Если цена/правила изменились — покажите пользователю и попросите подтвердить новые условия.

Request body (поля из /search/view)
{
  "hs": "rooms-search-hash",
  "hotel_id": "12345",
  "rate_id": "418533..roomOnly..Улучшенный..19082026..835828f9..30,30",   // rooms[].identifier
  "price": 12500.00,
  "is_not_refundable": false,
  "free_cancellation_before": "2026-05-13T12:00:00+00:00",
  "cancellation_policy_rules": [
    {
      "isPossible": true,
      "amount": 0,
      "UTCDateFrom": "2026-04-25T00:00:00+00:00",
      "UTCDateTo": "2026-05-13T12:00:00+00:00"
    }
  ],
  "lang": "ru"
}
Response 200
{
  "success": true,
  "data": {
    "rate_id": "ROOM_ID",
    "check_price_changes": {
      "old": { "totalAmount": 12500, "price": 12500 },
      "new": { "totalAmount": 12500, "price": 12500 }
    },
    "cancellation_policy_rules_changes": {
      "old": [...],
      "new": [...]
    }
  },
  "ts": 1714063200
}

Заказ и бронирование

POST/api/v1/integration/travel/hotels/create-order

Создать пустой черновик заказа на отель. Поддерживает Idempotency-Key.

Request body
{
  "order_uuid": "550e8400-e29b-41d4-a716-446655440000",  // сгенерируйте UUID v4
  "hotel_id": "12345",
  "search_hash": "rooms-search-hash",   // optional, hs из /view
  "hotel_name": "Hotel Example",        // для отображения
  "lang": "ru"
}
Response 200
{
  "success": true,
  "data": {
    "order_uuid": "550e8400-e29b-41d4-a716-446655440000",
    "order_id": 78901,
    "status": "created",
    "datetime": "2026-04-25T20:00:00Z"
  },
  "ts": 1714063200
}
POST/api/v1/integration/travel/hotels/create-order-with-view

Атомарно: создать заказ + сразу получить view отеля (номера, цены) одним запросом. Удобно для сценария «выбрали отель по названию» — без поиска и /view.

Request body
{
  "order_uuid": "550e8400-e29b-41d4-a716-446655440000",
  "view": {
    "hotel_id": "12345",
    "check_in": "15-05-2026",
    "check_out": "20-05-2026",
    "adults": 2,
    "children": [],
    "lang": "ru"
  }
}
Response 200
{
  "success": true,
  "data": {
    "order": { "order_uuid": "...", "order_id": 78901, "status": "created" },
    "view": { /* такой же формат, как у /search/view */ }
  },
  "ts": 1714063200
}
POST/api/v1/integration/travel/hotels/select-room

Выбрать конкретный номер и тариф в существующем заказе.

Request body
{
  "order_uuid": "550e8400-e29b-41d4-a716-446655440000",
  "recommendation_id": "ROOM_IDENTIFIER",   // identifier из /view → rooms[].identifier
  "payload": "{\"...full room JSON from /view...\"}"   // payload номера, как пришёл из /view
}
Response 200
{
  "success": true,
  "data": {
    "order_uuid": "550e8400-e29b-41d4-a716-446655440000",
    "status": "room_selected"
  },
  "ts": 1714063200
}
POST/api/v1/integration/travel/hotels/create-order-and-select-room

Атомарно: создать заказ + сразу выбрать номер. Если выбор номера упал — заказ удаляется автоматически (без черновиков). Самый удобный путь, если уже знаете отель и номер.

Request body (объединяет поля create-order + select-room)
{
  "order_uuid": "550e8400-e29b-41d4-a716-446655440000",
  "hotel_id": "12345",
  "search_hash": "rooms-search-hash",
  "hotel_name": "Hotel Example",
  "lang": "ru",
  "recommendation_id": "ROOM_IDENTIFIER",
  "payload": "{\"...room JSON...\"}"
}
Response 200
{
  "success": true,
  "data": {
    "order_uuid": "550e8400-e29b-41d4-a716-446655440000",
    "order_id": 78901,
    "status": "room_selected",
    "myagent_price": 12500.00,
    "alfabit_price": 13125.00            // включая нашу маржу
  },
  "ts": 1714063200
}
POST/api/v1/integration/travel/hotels/book

Финальное бронирование с гостями, контактами и согласованными правилами отмены. Перед вызовом ОБЯЗАТЕЛЬНО /check-rate. Рекомендуется передавать Idempotency-Key — повторный сетевой запрос не создаст вторую бронь.

Request body
{
  "order_uuid": "550e8400-e29b-41d4-a716-446655440000",
  "client_email": "user@example.com",
  "client_phone": "+79001234567",
  "guests": [
    { "first_name": "Ivan", "last_name": "Ivanov", "type": "adt" },
    { "first_name": "Anna", "last_name": "Ivanova", "type": "chd", "age": 5 }  // age обязателен для chd/inf
  ],
  "hs": "rooms-search-hash",
  "hotel_id": "12345",
  "hotel_name": "Hotel Example",
  "rate_id": "418533..roomOnly..Улучшенный..19082026..835828f9..30,30",
                                       // тот же rooms[].identifier, что в /select-room и /check-rate
  "price": 12500.00,                   // из /check-rate
  "is_not_refundable": false,
  "free_cancellation_before": "2026-05-13T12:00:00+00:00",
  "cancellation_policy_rules": [        // из /check-rate
    {
      "isPossible": true,
      "amount": 0,
      "UTCDateFrom": "2026-04-25T00:00:00+00:00",
      "UTCDateTo": "2026-05-13T12:00:00+00:00"
    }
  ],
  "lang": "ru"
}
Header (рекомендуется)
Idempotency-Key: 550e8400-e29b-41d4-a716-446655440000
Response 200
{
  "success": true,
  "data": {
    "order_uuid": "550e8400-e29b-41d4-a716-446655440000",
    "billing_number": "BN-2026-78901",
    "status": "booked"               // booked / failed
  },
  "ts": 1714063200
}

Оплата

POST/api/v1/integration/travel/hotels/pay/crypto

Создаёт инвойс на оплату заказа криптой или фиатом. Возвращает адрес кошелька, QR-код и время жизни инвойса. Поддерживает Idempotency-Key.

Request body
{
  "order_uuid": "550e8400-e29b-41d4-a716-446655440000",
  "currency_in_code": "USDT_TRC20",   // USDT_TRC20 / BTC / ETH / RUB / ...
  "use_miles": false,
  "miles_to_redeem": null              // если use_miles=true
}
Response 200
{
  "success": true,
  "data": {
    "invoice_id": "INV-12345",
    "order_uuid": "550e8400-e29b-41d4-a716-446655440000",
    "currency": "USDT_TRC20",
    "amount": "100.00",
    "deposit_address": "TQn9Y2khEsLJW1ChVWFMSMeRDow5KcbLSE",
    "qr_code_url": "https://...",
    "expires_at": "2026-04-25T21:00:00Z",
    "status": "pending"
  },
  "ts": 1714063200
}
POST/api/v1/integration/travel/hotels/pay/wallet

Мгновенная оплата отеля со счёта Wallet (списание с баланса). КРИТИЧНО передавать Idempotency-Key — иначе повторный запрос спишет средства дважды.

Request body
{
  "order_uuid": "550e8400-e29b-41d4-a716-446655440000",
  "currency": "USDT",                  // валюта баланса
  "use_miles": false,
  "miles_to_redeem": null
}
Header (КРИТИЧНО)
Idempotency-Key: 550e8400-e29b-41d4-a716-446655440000
Response 200
{
  "success": true,
  "data": {
    "order_uuid": "550e8400-e29b-41d4-a716-446655440000",
    "status": "paid",
    "paid_at": "2026-04-25T20:05:00Z",
    "amount_charged": "100.00",
    "currency": "USDT",
    "balance_after": "1150.00"
  },
  "ts": 1714063200
}
GET/api/v1/integration/travel/hotels/wallet/balance?currency=USDT

Баланс Wallet для оплаты отеля. Используйте перед /pay/wallet чтобы убедиться, что средств достаточно.

Query params
currency=USDT     // USDT / BTC / ETH / RUB
Response 200
{
  "success": true,
  "data": {
    "user_id": "sso-id-of-user",
    "currency": "USDT",
    "balance": "1250.00"
  },
  "ts": 1714063200
}

Мили (программа лояльности)

GET/api/v1/integration/travel/hotels/miles/preview?order_uuid=...

Сколько миль можно списать с конкретного заказа (с учётом лимитов и баланса).

GET/api/v1/integration/travel/hotels/miles/balance

Баланс программы лояльности и публичные настройки начисления.

Управление заказами

GET/api/v1/integration/travel/hotels/orders

Все ваши заказы на отели.

GET/api/v1/integration/travel/hotels/order/{order_uuid}

Детали заказа отеля: номер, даты, гости, стоимость, ваучер.

Response 200
{
  "success": true,
  "data": {
    "order_id": 78901,
    "status": "paid",
    "expire": "2026-04-25T21:00:00Z",
    "guests": [
      { "first_name": "Ivan", "last_name": "Ivanov", "type": "adt" },
      { "first_name": "Anna", "last_name": "Ivanova", "type": "chd", "age": 5 }
    ],
    "hotel": { /* такой же формат, как у /search/view */ },
    "price": 12500.00,
    "billing_number": "BN-2026-78901",
    "receipt": "https://...voucher.pdf",
    "client_email": "user@example.com"
  },
  "ts": 1714063200
}
GET/api/v1/integration/travel/hotels/order/{order_uuid}/status

Статус заказа отеля. Возможные значения: created, room_selected, booked, paid, confirmed, cancelled, refunded, failed.

Response 200
{
  "success": true,
  "data": {
    "order_uuid": "550e8400-e29b-41d4-a716-446655440000",
    "status": "paid",
    "updated_at": "2026-04-25T20:05:00Z"
  },
  "ts": 1714063200
}
POST/api/v1/integration/travel/hotels/order/{order_uuid}/cancel

Отмена бронирования отеля. Тело запроса опционально. Если бронь оплачена и отмена влечёт возврат денег — также требуется can_travel_refund. Поддерживает Idempotency-Key.

Request body (опционально)
{
  "reason": "hotel_other_reason",        // optional
  "reason_comment": "Изменились планы"   // обязателен только если reason='hotel_other_reason'
}
Response 200
{
  "success": true,
  "data": {
    "order_uuid": "550e8400-e29b-41d4-a716-446655440000",
    "status": "cancelled",
    "refund_amount": "12500.00",         // если был paid
    "refund_currency": "RUB"
  },
  "ts": 1714063200
}
GET/api/v1/integration/travel/hotels/guests

Сохранённые гости для быстрого бронирования.

Webhooks

Единая система вебхуков для всех продуктов. URL задаётся один раз на аккаунт (не в теле операций). После подписки события по кошельку, торговле, картам, инвойсам, оплате услуг и Travel уходят на ваш URL.

Source of truth — GET /api/v1/integration/webhooks/events

Всегда сверяйте имена событий с этим эндпоинтом — он возвращает актуальный каталог. Таблица ниже совпадает с ним 1:1. Точки — часть имени (например service_payment.created, card.transaction), НЕ маска service.payment.*.

POST/api/v1/integration/webhooks

Создать подписку: передайте url и массив events (имена из таблицы ниже). В ответе один раз вернётся secret — сохраните его для проверки HMAC.

Request
{
  "url": "https://your-domain.com/webhook",
  "events": [
    "invoice.paid",
    "card.transaction",
    "service_payment.confirmed",
    "travel.avia_order.paid"
  ]
}

Управление: GET / PATCH / DELETE /api/v1/integration/webhooks/{id}. Изменить набор событий — PATCH с новым events. Логи доставки: GET .../webhooks/{id}/logs.

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

Каждый запрос содержит заголовки X-Webhook-Event (имя события) и X-Webhook-Signature (HMAC-SHA256 hex на secret вашей подписки — том, что вернулся один раз при создании вебхука, не на API secret). То же значение дублируется в поле signature внутри тела: сверяйте с любым из двух.

Headers
X-Webhook-Event: invoice.paid
X-Webhook-Signature: <hmac-sha256 hex>
Content-Type: application/json

Подписывается конверт события {event, timestamp, data} БЕЗ поля signature, приведённый к каноническому JSON. Хешировать сырое тело запроса нельзя: signature в него уже добавлена, а порядок ключей не совпадает с каноническим. Распарсите тело, уберите signature и сериализуйте заново.

Formula
message   = canonical_json({"event": ..., "timestamp": ..., "data": {...}})
signature = HMAC-SHA256(webhook_secret, message) → hex
Правила canonical_json
  • Поле signature исключено из подписываемого объекта.
  • Ключи отсортированы по алфавиту рекурсивно — включая ключи внутри data. На верхнем уровне порядок получается data, event, timestamp.
  • Разделители без пробелов: "," и ":".
  • Не-ASCII символы экранируются как \uXXXX (эквивалент json.dumps с ensure_ascii=True).
Python
import hashlib, hmac, json

WEBHOOK_SECRET = "your_webhook_secret"

def verify(body: dict) -> bool:
    received = body.get("signature", "")
    payload = {k: v for k, v in body.items() if k != "signature"}
    message = json.dumps(payload, separators=(",", ":"), sort_keys=True)
    expected = hmac.new(
        WEBHOOK_SECRET.encode(), message.encode(), hashlib.sha256
    ).hexdigest()
    return hmac.compare_digest(expected, received)
⚠️
Частые причины «подпись не сходится»
  • Хешируется сырое тело запроса как есть — порядок ключей в нём не отсортирован.
  • Хешируется только объект data — подписывается весь конверт, вместе с event и timestamp.
  • Поле signature осталось внутри подписываемого объекта.
  • JSON сериализован с пробелами после "," и ":".
  • Взят secret от API-ключей вместо secret вебхука.

Полный каталог событий

EventОписание
Кошелёк
deposit.pendingПополнение обнаружено в сети (только крипта)
deposit.confirmedПополнение подтверждено и зачислено (крипта и рубли)
deposit.failedРублёвое пополнение не прошло или возвращено
withdrawal.processingВывод принят и обрабатывается (только крипта; у СБП этого события нет)
withdrawal.completedВывод завершён (крипта и рубли)
withdrawal.failedВывод не удался, средства возвращены (крипта и рубли)
transfer.receivedПолучен внутренний перевод
conversion.completedКонвертация выполнена
Торговля (Spot)
order.createdОрдер создан
order.filledОрдер полностью исполнен
order.partially_filledОрдер частично исполнен
order.cancelledОрдер отменён
trade.executedСделка исполнена (fill по ордеру)
trading.deposit.completedПополнение торгового счёта (Spot Fiat)
trading.withdraw.completedВывод с торгового счёта (Spot Fiat)
trading.balance.updatedОбновление торгового баланса (Spot Fiat)
Инвойсы
invoice.createdИнвойс создан
invoice.paidИнвойс оплачен
invoice.expiredИстёк TTL, txid пустой (платежа не было). Недоплата с пришедшим платежом сюда не попадает
invoice.cancelledИнвойс отменён мерчантом
invoice.refundedПровайдер вернул платёж плательщику
invoice.hedgedАвтоконвертация инвойса завершена, средства зачислены в целевой монете
invoice.template.deactivatedДеактивирован шаблон permanent-инвойса
Карты
card.transactionТранзакция по карте (в т.ч. выпуск/пополнение)
Оплата услуг
service_payment.createdПлатёж за услугу создан
service_payment.confirmedПлатёж за услугу подтверждён
service_payment.failedПлатёж за услугу не удался
service_payment.cancelledПлатёж за услугу отменён
Travel — Отели
travel.hotel_order.createdЧерновик заказа отеля создан
travel.hotel_order.bookedОтель забронирован (ожидает оплаты)
travel.hotel_order.paidЗаказ отеля оплачен
travel.hotel_order.confirmedБронь отеля подтверждена (финал)
travel.hotel_order.cancelledЗаказ отеля отменён
travel.hotel_order.refundedВозврат по заказу отеля
travel.hotel_order.failedОшибка заказа отеля
Travel — Авиа
travel.avia_order.createdЧерновик авиазаказа создан
travel.avia_order.bookedБилет забронирован (ожидает оплаты)
travel.avia_order.paidАвиазаказ оплачен (билет выписан)
travel.avia_order.cancelledАвиазаказ отменён
travel.avia_order.refundedВозврат по авиазаказу
travel.avia_order.failedОшибка авиазаказа

Отдельного события giftcard.* НЕТ — статус покупки подарочной карты отслеживайте через GET /giftcards/orders. Маски вида service.payment.* / card.* не поддерживаются: подписывайтесь на точные имена из таблицы.

Пополнения и выплаты: крипта и рубли в одних событиях

События deposit.confirmed, withdrawal.completed и withdrawal.failed приходят и по криптовалютным операциям, и по рублёвым заявкам СБП. Наборы полей у них разные, поэтому в data есть признак kind: crypto или fiat. Событие deposit.failed бывает только фиатным. withdrawal.processing и deposit.pending — только крипта: у СБП промежуточного вебхука нет, пока заявка в полёте опрашивайте GET /funding/deposit/fiat/{id} или GET /funding/withdraw/fiat/{id}.

Payload — deposit.confirmed (kind: fiat)
{
  "event": "deposit.confirmed",
  "timestamp": "2026-08-28T09:14:02Z",
  "data": {
    "kind": "fiat",
    "transaction_id": "6a2a0425-d681-4b8c-9792-4ce15d46ef0c",
    "status": "success",
    "currency": "RUB",
    "amount": "10000.00",
    "credited_amount": "9820.00",
    "fee": "180.00",
    "payment_provider_alias_code": "SBER",
    "error": null,
    "error_code": null
  },
  "signature": "..."
}
Payload — withdrawal.failed (kind: fiat)
{
  "event": "withdrawal.failed",
  "timestamp": "2026-08-28T09:41:55Z",
  "data": {
    "kind": "fiat",
    "transaction_id": "6f05ad6f-6cd2-47f9-880b-87ed1b58abdc",
    "status": "failed",
    "currency": "RUB",
    "amount": "500.00",
    "amount_fact": "0.00",
    "fee": "10.00",
    "total": "510.00",
    "bank_code": "GAZPROM",
    "recipient": "7900****67",
    "error": "Проведение операции невозможно",
    "error_code": "generic_refund"
  },
  "signature": "..."
}
ПолеОписание
kindcrypto или fiat. Различайте направление по нему, а не по наличию отдельных ключей.
transaction_idТот же идентификатор, что вернул POST на создание заявки и что принимают GET /funding/deposit/fiat/{id} и GET /funding/withdraw/fiat/{id}. Дедуплицируйте повторные доставки по нему.
credited_amountФакт зачисления рублей. null, если рубли не зачислялись — например у счёта под конвертацию: там зачисленную криптовалюту приносит conversion.completed.
amount_factСумма, фактически ушедшая получателю. У отказа 0.00.
error / error_codeПричина отказа и её код. Заполняются только у терминального отказа; если причины нет — null, вместо повтора слова failed.
recipientРеквизиты получателя в маскированном виде — так же, как в ответе GET-ручки вывода.

Событие отправляется только по терминальному исходу заявки: промежуточные статусы вебхуком не дублируются. Суммы приходят в копейках — тем же форматом, что отдают GET-ручки приёма и вывода.

transfer.received

Приход внутреннего перевода на ваш баланс. Формат одинаковый для криптовалют и рублей.

Payload
{
  "event": "transfer.received",
  "timestamp": "2026-07-30T10:37:15Z",
  "data": {
    "transfer_id": "2b8bc516-e49a-40eb-b8c1-1a0fa02c2cfe",
    "transaction_uid": "2b8bc516-e49a-40eb-b8c1-1a0fa02c2cfe",
    "symbol": "RUB",
    "amount": "3872.01",
    "status": "credited",
    "user_comment": "AB-7K3QF9XM",
    "sender_profile_id": 904016,
    "sender_email": "payer@example.com",
    "recipient_profile_id": 7504,
    "method": null
  },
  "signature": "..."
}
ПолеОписание
transfer_idИдентификатор перевода. Совпадает с transaction_uid и с uid операции в GET /integration/transactions — по нему же дедуплицируйте повторные доставки.
statusВсегда credited: событие отправляется только после фактического зачисления, средства уже доступны получателю.
user_commentКомментарий отправителя (до 500 символов), null если не заполнен.
sender_emailEmail отправителя, null если у профиля его нет.
methodСпособ адресации крипто-перевода (tg / email / phone). Для рублёвых переводов всегда null — способ не сохраняется.

Повторная доставка НЕ байт-идентична: при ретрае timestamp пересчитывается, а значит меняется и signature. Объект data при этом тот же. Дедуплицируйте по transfer_id, а не по хешу тела.

Ответ, отличный от 2xx, и таймаут (10 сек) приводят к повтору: всего 3 попытки — сразу, через 30 секунд и через 2 минуты.

Ссылка на предзаполненный перевод

Ссылка открывает форму внутреннего перевода уже заполненной. Отправку она не выполняет: получателя проверяет платформа, сумму — правила поля, а подтверждение нажимает сам пользователь.

URL
https://alfabit.org/ru/user/transfer?to=user%40example.com&method=email&symbol=USDT&amount=25&comment=Order%20A-1042
ПараметрОписание
toПолучатель: email, @telegram_username или телефон в формате +71234567890.
methodemail, telegram_username или phone. Можно не указывать — способ определится по формату to.
symbolМонета перевода, например USDT или RUB. Если не указана, пользователь выбирает её сам.
amountСумма без разделителей разрядов, точка как десятичный разделитель. Значение подставляется в поле и проходит обычную проверку баланса и лимитов.
commentКомментарий отправителя, до 140 символов. Дойдёт до получателя в истории и в вебхуке transfer.received как user_comment.

Все параметры необязательны, некорректные молча игнорируются — форма просто откроется с пустым полем. Ссылка требует авторизации: неавторизованный пользователь сначала попадёт на вход, а после него — на заполненную форму.

Справочник валют и сетей

Единый источник правды по монетам и сетям: точность суммы, лимиты, комиссии и доступность операций. Читайте его перед выводом и перед выставлением счёта — параметры различаются от сети к сети и меняются без предупреждения (сеть могут временно закрыть на стороне блокчейна).

GET/api/v1/integration/market/currencies

Массив записей — по одной на пару монета+сеть. Не требует API ключа.

Response
{
  "success": true,
  "data": [
    {
      "symbol": "USDT",
      "bch_code": "TRX",
      "withdraw_amount_decimals": "6",
      "min_withdraw_amount": "3",
      "max_withdraw_amount": "150000",
      "withdraw_service_fee": "2.5",
      "is_withdraw_active": true,
      "is_deposit_active": true,
      "min_deposit_amount": "1",
      "is_memo_tag_required": false,
      "net_confirmations": 20
    },
    {
      "symbol": "USDT",
      "bch_code": "BSC",
      "withdraw_amount_decimals": "8",
      "min_withdraw_amount": "10",
      "max_withdraw_amount": "150000",
      "withdraw_service_fee": "1.2",
      "is_withdraw_active": true
    }
  ],
  "ts": 1706000000
}
  • symbol + bch_code — монета и сеть. Эту же пару передавайте в вывод и в счёт.
  • withdraw_amount_decimals — сколько знаков после запятой принимает сеть на выводе. Лишние знаки усекаются вниз.
  • min_withdraw_amount / max_withdraw_amount — лимиты одной заявки на вывод в этой сети.
  • withdraw_service_fee — комиссия за вывод в единицах монеты.
  • is_withdraw_active / is_deposit_active — открыты ли операции в этой сети прямо сейчас.
  • is_memo_tag_required — нужен ли memo/tag получателю (XRP, TON и подобные).

Ответ большой — кешируйте его у себя и обновляйте раз в несколько минут, а не перед каждой операцией.

GET/api/v1/integration/market/rates

Стоимость монет в USDT — по одной записи на символ. Не требует API ключа.

Response
{
  "success": true,
  "data": [
    { "symbol": "USDT", "rate_usdt": "1" },
    { "symbol": "BTC", "rate_usdt": "78635.6" },
    { "symbol": "ETH", "rate_usdt": "2470.64" },
    { "symbol": "TRX", "rate_usdt": "0.3438" }
  ],
  "ts": 1706000000
}
📊
Это справочные котировки, а не цена сделки

Значения годятся для витрины, оценки портфеля и предварительного расчёта. Цену, по которой пройдёт операция, возвращает котировка конкретного продукта — /converter/crypto/estimate или /converter/fiat/estimate: она учитывает направление, объём и комиссию и действует ограниченное время. Не считайте сумму к списанию по rate_usdt.

Тарифы и комиссии

Информация о текущем тарифном плане и ставках комиссий для всех типов операций.

GET/api/v1/integration/market/tariffs

Тарифная сетка: комиссии за вывод, обмен, пополнение карт и другие операции. Не требует API ключа.

Response
{
  "tariff": "standard",
  "fees": {
    "withdraw_btc": "0.0001",
    "withdraw_usdt_trc20": "1",
    "exchange_fee": "0.1%",
    "card_topup_fee": "2%"
  }
}

Транзакции

Единая история всех операций: пополнения, выводы, переводы, обмены, покупки. В один фид сведены и криптовалютные операции, и рублёвые — различить их можно по полю source.

GET/api/v1/integration/transactions

Все транзакции с фильтрами по валюте и периоду. Поддерживает пагинацию и поиск.

ParameterTypeОписание
symbolstringФильтр по валюте (USDT, BTC, RUB). Значение RUB оставляет в фиде только рублёвые операции, любая другая валюта — только криптовалютные.
limitnumberКоличество записей (default: 50, max: 100)
pagenumberНомер страницы (default: 1)
start_periodnumberНачало периода (Unix timestamp)
end_periodnumberКонец периода (Unix timestamp)
search_termstringПоиск по транзакциям
Response
{
  "success": true,
  "data": {
    "page": 1,
    "limit": 50,
    "count": 156,
    "results": [
      {
        "source": "fiat",
        "uid": "0f3c1a7e-1b9d-4f2a-9c11-6a0d5e7b8c34",
        "type": "deposit",
        "symbol": "RUB",
        "amount": "5000.00",
        "status_for_client": "success",
        "is_final_state": true,
        "method": null,
        "fee": "0.0",
        "sender_id": 7504,
        "receiver_id": 9001,
        "user_comment": "order-12345",
        "sender": { "email": "client@example.com", "telegram_username": null },
        "receiver": { "email": "shop@example.com", "telegram_username": null },
        "created_at": 1753812345.0
      },
      {
        "source": "crypto",
        "uid": "a1b2c3d4-...",
        "type": "deposit",
        "symbol": "USDT",
        "amount": "500.00",
        "status_for_client": "success",
        "is_final_state": true,
        "method": "email",
        "created_at": 1753810000.0
      }
    ]
  },
  "ts": 1706000000
}

Поля записи

ПолеОписание
source"crypto" — криптовалютная операция, "fiat" — рублёвая.
uidИдентификатор операции. Для внутреннего перевода совпадает с transfer_id из вебхука transfer.received — используйте его как ключ идемпотентности.
typeТип с точки зрения владельца ключа: входящая операция — deposit, исходящая — withdraw. Внутренний перевод разворачивается по роли: у получателя это deposit.
status_for_clientwait | success | failed | blocked | aml.
is_final_stateСтатус окончателен. Пока false — состояние ещё может измениться, зачислять рано.
methodСпособ адресации перевода (email, telegram, phone). У рублёвых операций всегда null — поле оставлено для единообразия разбора.
sender / receiverУчастники перевода (email, telegram_username). Именно по sender.email сверяется плательщик.
user_commentКомментарий отправителя — удобно просить клиента указать в нём номер заказа.
created_atВремя создания, Unix timestamp (число, не строка).
ℹ️
Приём оплат внутренним переводом

Чтобы принимать пополнения переводом внутри AlfaBit, подпишитесь на вебхук transfer.received — он приходит только по факту зачисления и содержит transfer_id, сумму, sender_email и комментарий отправителя. Этот фид используйте как резервный канал сверки: фильтруйте записи с type = deposit и is_final_state = true, дедуплицируйте по uid.

Глубокая пагинация объединённого фида ограничена: page × limit не должно превышать 2000, иначе вернётся 400 DEEP_PAGINATION_NOT_SUPPORTED. Для выгрузки истории сужайте период через start_period / end_period.

GET/api/v1/integration/transactions/{transaction_id}

Детали конкретной транзакции: сумма, статус, комиссия, дата, участники. В transaction_id передаётся uid из фида (он же transfer_id вебхука); ручка ищет операцию и среди криптовалютных, и среди рублёвых.

Response
{
  "success": true,
  "data": {
    "source": "fiat",
    "uid": "0f3c1a7e-1b9d-4f2a-9c11-6a0d5e7b8c34",
    "type": "deposit",
    "symbol": "RUB",
    "amount": "5000.00",
    "status_for_client": "success",
    "is_final_state": true,
    "fee": "0.0",
    "sender_id": 7504,
    "receiver_id": 9001,
    "user_comment": "order-12345",
    "created_at": 1753812345.0
  },
  "ts": 1706000000
}