BazVey API v1
HTTP-интерфейс в формате JSON, на котором работает сайт BazVey. Здесь описаны все методы, которые сейчас доступны: авторизация, профиль, тест по правилам и каталог.
Адрес сервера
BASE_URL
Аутентификация
Используется сессионная cookie bazaa_session (HttpOnly, SameSite=Lax). Она выставляется после успешного входа (/api/verify-code, /api/tg/webapp, /api/register), живёт, пока вы не выйдете, и продлевается при каждом заходе. В браузере достаточно credentials: "include", в скриптах — передавать cookie вручную. Персональных API-ключей для сторонних сервисов пока нет.
Формат запросов
Тело POST-запросов — JSON в UTF-8 с заголовком Content-Type: application/json, размером до 400 КБ. Время передаётся в unix-секундах. Все ответы, кроме /health, — JSON.
Ошибки
При ошибке поле ok равно false, а error содержит понятное описание на русском.
400 | Некорректные данные запроса или неверный код. |
401 | Нужно войти в аккаунт либо не пройдена проверка подписи Telegram. |
409 | Конфликт: никнейм занят или аккаунт уже существует. |
413 | Слишком большое тело запроса. |
429 | Превышены лимиты. Если есть поле retry_after, повторите через столько секунд. |
502 / 503 | Внешний сервис (почта, Telegram-бот) временно недоступен. |
Лимиты
Код на одну почту можно запрашивать раз в 60 секунд, на ввод кода даётся 5 попыток, а число запросов кода с одного IP в час ограничено.
Авторизация
Вход без паролей: по коду из Telegram-бота, по коду из письма или автоматически из Telegram Mini App. После успешного входа сервер выставляет cookie bazaa_session. Если аккаунта ещё нет, ответ содержит signup_token, который нужно обменять на аккаунт через /api/register.
Начать вход через Telegram
/api/tg/startСоздаёт одноразовую ссылку на бота. Пользователь открывает её, нажимает Start, бот присылает 6-значный код. Код затем передаётся в /api/verify-code вместе с login_id. Ссылка действует 10 минут.
Ответы
- 200Ссылка создана
- 429Слишком много запросов с вашего IP
- 503Бот ещё запускается
Ссылка создана
{
"ok": true,
"login_id": "k3J9x0QmZb1T",
"url": "https://t.me/bazaa_bot?start=k3J9x0QmZb1T"
}Слишком много запросов с вашего IP
{
"ok": false,
"error": "Слишком много запросов. Попробуйте позже"
}Бот ещё запускается
{
"ok": false,
"error": "Бот ещё запускается или недоступен. Повторите через несколько секунд"
}Отправить код на почту
/api/send-codeОтправляет 6-значный код на электронную почту. Код действует 10 минут, повторно его можно запросить не раньше чем через 60 секунд.
Параметры тела запроса
emailstring | обязательно Адрес электронной почты, до 254 символов. |
Ответы
- 200Код отправлен
- 400Некорректный адрес
- 429Код уже отправлен или превышен лимит
- 502Не удалось отправить письмо
Код отправлен
{
"ok": true,
"resend_in": 60
}Некорректный адрес
{
"ok": false,
"error": "Введите корректный адрес почты"
}Код уже отправлен или превышен лимит
{
"ok": false,
"error": "Код уже отправлен. Повторите через 42 с",
"retry_after": 42
}Не удалось отправить письмо
{
"ok": false,
"error": "Не удалось отправить письмо. Попробуйте позже"
}Подтвердить код и войти
/api/verify-codeПроверяет код. Передайте либо login_id (вход через Telegram), либо email (вход по почте). Если аккаунт существует, выставляется cookie bazaa_session и возвращается user. Если нет — возвращается signup_token (действует 15 минут) для вызова /api/register. На код даётся 5 попыток.
Параметры тела запроса
codestring | обязательно 6-значный код. Нецифровые символы игнорируются. |
login_idstring | необязательно Идентификатор из /api/tg/start. Нужен для входа через Telegram. |
emailstring | необязательно Почта, на которую отправлялся код. Нужна для входа по почте. |
Ответы
- 200Вход выполнен (аккаунт существует)
- 200Нужна регистрация
- 400Неверный или просроченный код
- 429Слишком много попыток
Вход выполнен (аккаунт существует)
{
"ok": true,
"registered": true,
"user": {
"username": "Alex_77",
"avatar": "",
"email": "tg:123456789",
"created": 1767225600,
"bio": "",
"privacy": "show",
"rename_days": 0,
"rules_ok": false,
"has_phone": false,
"banner": "",
"has_password": false,
"twofa": false,
"notify_tg": true,
"notify_email": true
}
}Нужна регистрация
{
"ok": true,
"registered": false,
"signup_token": "Zq1c…",
"suggested": "Alex_77"
}Неверный или просроченный код
{
"ok": false,
"error": "Неверный код. Осталось попыток: 4"
}Слишком много попыток
{
"ok": false,
"error": "Слишком много попыток. Запросите новый код"
}Автоматический вход из Telegram Mini App
/api/tg/webappВход без ввода кода внутри Telegram Mini App. Сервер проверяет подпись initData, поэтому подделать запрос нельзя. Ответ такой же, как у /api/verify-code.
Параметры тела запроса
init_datastring | обязательно Значение Telegram.WebApp.initData. |
Ответы
- 200Вход выполнен или нужна регистрация
- 401Подпись не прошла проверку
Вход выполнен или нужна регистрация
{
"ok": true,
"registered": false,
"signup_token": "Zq1c…",
"suggested": "Alex_77"
}Подпись не прошла проверку
{
"ok": false,
"error": "Не удалось подтвердить Telegram"
}Создать аккаунт
/api/registerЗавершает регистрацию после подтверждения кода. После успеха выставляется cookie bazaa_session.
Параметры тела запроса
signup_tokenstring | обязательно Токен из ответа /api/verify-code или /api/tg/webapp. |
usernamestring | обязательно Никнейм: 3–20 символов, только латинские буквы (A–Z), цифры и символы _ . -. |
avatarstring | необязательно Аватар как data-URL (JPEG, PNG, WebP), до 200 000 символов. |
Ответы
- 200Аккаунт создан
- 400Некорректный никнейм или токен устарел
- 409Никнейм занят или аккаунт уже существует
Аккаунт создан
{
"ok": true,
"user": {
"username": "Alex_77",
"avatar": "",
"email": "tg:123456789",
"created": 1767225600,
"bio": "",
"privacy": "show",
"rename_days": 0,
"rules_ok": false,
"has_phone": false,
"banner": "",
"has_password": false,
"twofa": false,
"notify_tg": true,
"notify_email": true
}
}Некорректный никнейм или токен устарел
{
"ok": false,
"code": "token_expired",
"error": "Время регистрации истекло. Запросите код заново"
}Никнейм занят или аккаунт уже существует
{
"ok": false,
"error": "Этот никнейм уже занят"
}Выйти из аккаунта
/api/logoutЗавершает текущую сессию и сбрасывает cookie.
Ответы
- 200Сессия завершена
Сессия завершена
{
"ok": true
}Вход по паролю
/api/login-passwordЛогин — никнейм, Telegram @юзернейм или почта. Если включена 2FA, вместо входа возвращается twofa_token для /api/login-2fa.
Параметры тела запроса
loginstring | обязательно Никнейм, юзернейм или почта. |
passwordstring | обязательно Пароль. |
Ответы
- 200Вход выполнен
- 200Нужен код 2FA
- 400Неверные данные
- 429Слишком много попыток
Вход выполнен
{
"ok": true,
"registered": true,
"user": {
"username": "Alex_77",
"avatar": "",
"email": "tg:123456789",
"created": 1767225600,
"bio": "",
"privacy": "show",
"rename_days": 0,
"rules_ok": false,
"has_phone": false,
"banner": "",
"has_password": false,
"twofa": false,
"notify_tg": true,
"notify_email": true
}
}Нужен код 2FA
{
"ok": true,
"need_2fa": true,
"twofa_token": "Qw3r…"
}Неверные данные
{
"ok": false,
"error": "Неверный логин или пароль"
}Слишком много попыток
{
"ok": false,
"error": "Слишком много попыток. Попробуйте позже"
}Подтвердить вход кодом 2FA
/api/login-2faЗавершает вход, если предыдущий шаг вернул need_2fa. Токен действует 5 минут, на него даётся 5 попыток.
Параметры тела запроса
twofa_tokenstring | обязательно Токен из ответа предыдущего шага. |
codestring | обязательно 6-значный код из приложения. |
Ответы
- 200Вход выполнен
- 400Неверный код или время вышло
Вход выполнен
{
"ok": true,
"registered": true,
"user": {
"username": "Alex_77",
"avatar": "",
"email": "tg:123456789",
"created": 1767225600,
"bio": "",
"privacy": "show",
"rename_days": 0,
"rules_ok": false,
"has_phone": false,
"banner": "",
"has_password": false,
"twofa": false,
"notify_tg": true,
"notify_email": true
}
}Неверный код или время вышло
{
"ok": false,
"error": "Неверный код из приложения"
}Профиль
Данные текущего пользователя, редактирование профиля и привязка телефона. Все методы работают от имени владельца сессии.
Текущий пользователь
/api/meВозвращает профиль владельца сессии. Если вход не выполнен, user равен null. Сессия продлевается при каждом обращении.
Ответы
- 200Профиль пользователя
- 200Гость
Профиль пользователя
{
"ok": true,
"user": {
"username": "Alex_77",
"avatar": "",
"email": "tg:123456789",
"created": 1767225600,
"bio": "",
"privacy": "show",
"rename_days": 0,
"rules_ok": false,
"has_phone": false,
"banner": "",
"has_password": false,
"twofa": false,
"notify_tg": true,
"notify_email": true
}
}Гость
{
"ok": true,
"user": null
}Изменить профиль
/api/profileОбновляет только переданные поля. Никнейм можно менять раз в 30 дней.
Параметры тела запроса
usernamestring | необязательно Новый никнейм, 3–20 символов. |
avatarstring | необязательно Аватар как data-URL либо пустая строка, чтобы удалить. |
bannerstring | необязательно Баннер как data-URL (JPEG, PNG, WebP) либо пустая строка, чтобы удалить. |
biostring | необязательно «Обо мне», обрезается до 200 символов. |
privacystring | необязательно show, hide или hide_all. |
Ответы
- 200Профиль обновлён
- 400Ошибка в данных или рано менять никнейм
- 401Нужно войти
- 409Никнейм занят
Профиль обновлён
{
"ok": true,
"user": {
"username": "Alex_77",
"avatar": "",
"email": "tg:123456789",
"created": 1767225600,
"bio": "Продаю игровую валюту",
"privacy": "show",
"rename_days": 0,
"rules_ok": false,
"has_phone": false,
"banner": "",
"has_password": false,
"twofa": false,
"notify_tg": true,
"notify_email": true
}
}Ошибка в данных или рано менять никнейм
{
"ok": false,
"error": "Никнейм можно менять раз в 30 дней. Осталось дней: 12"
}Нужно войти
{
"ok": false,
"error": "Войдите в аккаунт"
}Никнейм занят
{
"ok": false,
"error": "Этот никнейм уже занят"
}Пароль и 2FA
/api/securityУправление паролем и двухфакторной защитой. Действия: set_password (пароль от 8 символов; при смене нужен old, при включённой 2FA — code), twofa_start (выдаёт секрет и ссылку otpauth:// для приложения-аутентификатора), twofa_enable (подтверждение кодом) и twofa_disable (нужен код).
Параметры тела запроса
actionstring | обязательно set_password, twofa_start, twofa_enable или twofa_disable. |
passwordstring | необязательно Новый пароль. Для set_password. |
oldstring | необязательно Текущий пароль, если он уже установлен. |
codestring | необязательно 6-значный код из приложения. Для twofa_enable, twofa_disable и смены пароля при включённой 2FA. |
Ответы
- 200Готово
- 400Ошибка в данных
- 401Нужно войти
Готово
{
"ok": true,
"secret": "JBSWY3DPEHPK3PXP",
"uri": "otpauth://totp/BazVey:Alex_77?secret=JBSWY3DPEHPK3PXP&issuer=BazVey"
}Ошибка в данных
{
"ok": false,
"error": "Неверный код"
}Нужно войти
{
"ok": false,
"error": "Войдите в аккаунт"
}Ссылка для привязки телефона
/api/phone-linkВозвращает ссылку на Telegram-бота. После нажатия Start бот просит поделиться контактом и привязывает номер к профилю. Проверить результат можно через has_phone в /api/me.
Ответы
- 200Ссылка получена
- 200Бот недоступен
Ссылка получена
{
"ok": true,
"url": "https://t.me/bazaa_bot?start=phone"
}Бот недоступен
{
"ok": false,
"url": ""
}Правила
Мини-тест, который нужно пройти один раз, чтобы принять правила площадки. Верные ответы хранятся только на сервере.
Тест по правилам
/api/rules-quizОдин метод с тремя действиями. start выдаёт 4 вопроса без ответов (в новой попытке вопросы другие). answer проверяет ответ на вопрос по порядку. finish подводит итог: правила принимаются, только если все 4 ответа верны. Если правила уже приняты, возвращается done: true.
Параметры тела запроса
actionstring | обязательно start, answer или finish. |
iinteger | необязательно Номер вопроса (с нуля). Только для answer. |
ointeger | необязательно Номер выбранного варианта (с нуля). Только для answer. |
Ответы
- 200start: вопросы выданы
- 200answer: ответ проверен
- 200finish: тест пройден
- 200finish: есть ошибки
- 400Нарушен порядок вопросов
- 401Нужно войти
start: вопросы выданы
{
"ok": true,
"questions": [
{
"q": "Покупатель предлагает <b>оплатить заказ напрямую</b>…",
"o": [
"Да, если он сам предложил.",
"Нет, только через BazVey."
]
}
]
}answer: ответ проверен
{
"ok": true,
"correct": true,
"right": 1
}finish: тест пройден
{
"ok": true,
"passed": true,
"user": {
"username": "Alex_77",
"avatar": "",
"email": "tg:123456789",
"created": 1767225600,
"bio": "",
"privacy": "show",
"rename_days": 0,
"rules_ok": true,
"has_phone": false,
"banner": "",
"has_password": false,
"twofa": false,
"notify_tg": true,
"notify_email": true
}
}finish: есть ошибки
{
"ok": true,
"passed": false,
"errors": 1
}Нарушен порядок вопросов
{
"ok": false,
"error": "Начните тест заново"
}Нужно войти
{
"ok": false,
"error": "Войдите в аккаунт"
}Каталог
Публичные данные каталога. Авторизация не нужна.
Список игр
/api/gamesВсе игры и приложения каталога. Каждый элемент — пара [название, slug]; страница игры доступна по адресу /<slug>.
Ответы
- 200Список игр
Список игр
{
"games": [
[
"Roblox",
"roblox"
],
[
"Minecraft",
"minecraft"
],
[
"Dota 2",
"dota-2"
]
]
}Создать предложение
/api/offersРазмещает предложение продавца в категории. Нужен вход, принятые правила (rules_ok) и подтверждённый номер телефона (has_phone), иначе ответ 403 с code: "phone".
Параметры тела запроса
gamestring | обязательно Slug игры, например telegram. |
catstring | обязательно Slug категории, например stars. |
amtinteger | необязательно Тип предложения (количество) для категорий с фиксированными пакетами. |
modestring | необязательно username или gift — способ получения (для звёзд). |
titlestring | необязательно Название предложения, 3–80 символов (для категорий без пакетов). |
descriptionstring | обязательно Подробное описание, 10–2500 символов. |
pricenumber | обязательно Цена за единицу в рублях. |
stockinteger | обязательно Наличие, единиц. |
imagesarray | необязательно До 3 картинок в виде data-URL (JPEG, PNG). |
autoboolean | необязательно Автоматизированная доставка. |
activeboolean | необязательно Показывать предложение в каталоге. |
Ответы
- 200Предложение создано
- 400Ошибка в данных
- 401Нужно войти
- 403Правила не приняты
Предложение создано
{
"ok": true,
"id": 1
}Ошибка в данных
{
"ok": false,
"error": "Подробное описание: от 10 до 2500 символов"
}Нужно войти
{
"ok": false,
"error": "Войдите в аккаунт"
}Правила не приняты
{
"ok": false,
"code": "rules",
"error": "Сначала примите правила и пройдите тест"
}Служебное
Проверка работоспособности сервера.
Проверка сервера
/healthВозвращает текст ok, если сервер работает.
Ответы
- 200Сервер работает
Сервер работает
ok
Модели
User
Объект пользователя, который возвращают /api/me, /api/profile и методы входа.
Поля
usernamestring | обязательно Никнейм на сайте, 3–20 символов. |
avatarstring | обязательно Аватар в виде data-URL (JPEG, PNG или WebP) либо пустая строка. |
bannerstring | обязательно Баннер профиля в виде data-URL (до 300 000 символов) либо пустая строка. |
emailstring | обязательно Внутренний идентификатор входа: tg:<id> для Telegram или адрес почты. |
createdinteger | обязательно Время регистрации, unix-время в секундах. |
biostring | обязательно Текст «Обо мне», до 200 символов. |
privacystring | обязательно Приватность предложений: show, hide или hide_all. |
rename_daysinteger | обязательно Сколько дней осталось до следующей смены никнейма (0 — менять можно). |
rules_okboolean | обязательно true, если пользователь прошёл тест и принял правила. |
has_phoneboolean | обязательно true, если к профилю привязан телефон. |
has_passwordboolean | обязательно true, если установлен пароль для входа. |
twofaboolean | обязательно true, если включена двухфакторная аутентификация (TOTP). |
notify_tgboolean | обязательно Оповещения в Telegram включены. |
notify_emailboolean | обязательно Оповещения на почту включены. |
Пример
{
"username": "Alex_77",
"avatar": "",
"email": "tg:123456789",
"created": 1767225600,
"bio": "",
"privacy": "show",
"rename_days": 0,
"rules_ok": false,
"has_phone": false,
"banner": "",
"has_password": false,
"twofa": false,
"notify_tg": true,
"notify_email": true
}