Skip to content

Эндпоинты API v3 ​

Все пути начинаются с /api/v3, каждый запрос требует заголовок X-API-Key и область доступа, указанную рядом с маршрутом. Основы авторизации — в разделе Внешний API.

Пользователи ​

GET /users — список ​

Область: users:read.

ПараметрТипПо умолчаниюЧто делает
limitint, 1..500100размер страницы
offsetint0смещение
statusstring—фильтр по статусу: active, disabled и т. д.
searchstring—поиск по части username, email или uuid
json
[
  {
    "uuid": "a2e...",
    "username": "alice",
    "status": "active",
    "traffic_limit_bytes": 107374182400,
    "used_traffic_bytes": 52013875200,
    "expire_at": "2026-06-01T00:00:00Z",
    "online": true,
    "short_uuid": "AbCdEf123",
    "subscription_url": "https://sub.example.com/AbCdEf123"
  }
]

GET /users/{uuid} — карточка ​

Область: users:read. Вернёт объект пользователя или 404.

short_uuid и subscription_url — идентификатор и ссылка подписки из панели. Ссылка берётся из последнего синка с панелью; пока пользователь не синхронизирован, поле будет null. Ссылка даёт доступ к конфигам, не публикуйте её.

POST /users — создать ​

Область: users:write.

json
{
  "username": "alice",
  "expire_at": "2026-06-01T00:00:00Z",
  "traffic_limit_bytes": 107374182400,
  "traffic_limit_strategy": "MONTH",
  "hwid_device_limit": 3,
  "description": "Создан из CI",
  "telegram_id": 123456789,
  "email": "alice@example.com",
  "tag": "vip",
  "status": "active",
  "external_squad_uuid": "3f2c...",
  "active_internal_squads": ["a1b2...", "c3d4..."]
}

external_squad_uuid и active_internal_squads необязательны; UUID сквадов — из GET /squads/external и GET /squads/internal (см. ниже).

Ответ — 201:

json
{
  "success": true,
  "message": "User alice created",
  "uuid": "a2e...",
  "short_uuid": "AbCdEf123",
  "subscription_url": "https://sub.example.com/AbCdEf123"
}

Пользователь сразу пишется в базу админки, так что GET /users/{uuid} работает без ожидания синка. Если локальная база недоступна, uuid может прийти null — пользователь появится после следующего синка.

Остальные действия ​

ЭндпоинтМетодОбластьЧто делает
/users/{uuid}/enablePOSTusers:writeвключить
/users/{uuid}/disablePOSTusers:writeотключить, можно передать {"reason": "..."}
/users/{uuid}/reset-trafficPOSTusers:writeобнулить счётчики трафика
/users/{uuid}DELETEusers:deleteудалить

Массовые операции ​

Все принимают {"uuids": ["...", "..."]}, до 500 записей за раз.

json
{
  "success": 498,
  "failed": 2,
  "errors": [
    {"uuid": "...", "error": "not found"}
  ]
}
ЭндпоинтОбласть
POST /users/bulk/enablebulk:write
POST /users/bulk/disablebulk:write
POST /users/bulk/deletebulk:write
POST /users/bulk/reset-trafficbulk:write

У массовых операций свой лимит запросов — API_V3_RATE_BULK_PER_MIN, по умолчанию 10 в минуту.

Ноды ​

ЭндпоинтМетодОбластьЧто делает
/nodesGETnodes:readсписок
/nodes/{uuid}GETnodes:readкарточка
/nodes/{uuid}/enablePOSTnodes:writeвключить
/nodes/{uuid}/disablePOSTnodes:writeотключить
/nodes/{uuid}/restartPOSTnodes:writeперезапустить
/nodes/syncPOSTnodes:writeсинхронизировать список нод с панелью
/nodes/{uuid}/agent-token/generatePOSTnodes:tokenсгенерировать (перевыпустить) токен агента
/nodes/{uuid}/agent-token/revokePOSTnodes:tokenотозвать токен агента
json
{
  "uuid": "...",
  "name": "eu-west-1",
  "address": "1.2.3.4",
  "port": 62050,
  "is_disabled": false,
  "is_connected": true,
  "users_online": 42
}

Хосты ​

ЭндпоинтМетодОбласть
/hostsGEThosts:read
/hosts/{uuid}GEThosts:read

Поля повторяют объекты хостов панели Remnawave: uuid, remark, address, port, sni, host, is_disabled, alpn, fingerprint.

Сквады ​

Область: users:read. Списки берутся живьём из панели Remnawave — чтобы взять UUID для external_squad_uuid и active_internal_squads при создании пользователя.

ЭндпоинтМетодЧто отдаёт
/squads/internalGETвнутренние сквады: uuid, name, members_count, inbounds (uuid, tag)
/squads/externalGETвнешние сквады: uuid, name, members_count
json
[
  {
    "uuid": "3f2c...",
    "name": "Standard",
    "members_count": 128,
    "inbounds": [{"uuid": "a1b2...", "tag": "VLESS-Reality"}]
  }
]

Панель недоступна — 503.

Нарушения ​

GET /violations — список ​

Область: violations:read. Свежие сверху.

ПараметрТипПо умолчаниюЧто делает
limitint, 1..500100размер страницы
offsetint0смещение
user_uuidstring—по конкретному пользователю
telegram_idint—по Telegram-идентификатору клиента
min_scorefloat—нижняя граница скоринга
recommended_actionstring—hard_block, temp_block, monitor
resolvedbool—true — решение принято, false — открытые
date_from, date_toISO datetime—границы по времени обнаружения
json
[
  {
    "id": 9123,
    "user_uuid": "...",
    "username": "alice",
    "score": 87.5,
    "confidence": 0.9,
    "recommended_action": "hard_block",
    "action_taken": null,
    "reasons": ["4 одновременных подключения из 3 стран"],
    "ip_addresses": ["1.2.3.4"],
    "countries": ["RU", "NL"],
    "detected_at": "2026-06-07T11:50:00+00:00",
    "notified_at": null
  }
]

notified_at — когда клиенту отправили предупреждение по этому нарушению; null — не предупреждали.

GET /violations/summary — вердикт по клиенту ​

Область: violations:read. Отвечает на один вопрос: можно ли доверять этому человеку. Нужна интеграциям, которые принимают решение — выдавать ли триал, промокод, продление — и которым незачем разбирать список нарушений.

ПараметрТипПо умолчаниюЧто делает
telegram_idint—клиент по Telegram-идентификатору
user_uuidstring—клиент по UUID панели
window_daysint, 1..36530за какой срок считаем

Нужен telegram_id или user_uuid, иначе 422.

json
{
  "user_uuid": "...",
  "telegram_id": 366945364,
  "window_days": 30,
  "level": "warned",
  "violations": 2,
  "max_score": 74.0,
  "last_detected_at": "2026-09-20T10:00:00+00:00",
  "last_action": null,
  "whitelisted": false,
  "notice": {
    "violation_id": 9123,
    "kind": "device",
    "subject": "Подписка используется с нескольких устройств",
    "body": "Мы заметили…",
    "sent_at": "2026-09-20T10:05:00+00:00"
  }
}

notice — последнее предупреждение, которое клиент действительно получил: тема и текст ровно в том виде, в каком ушли, даже если шаблон потом поправили; null, если не предупреждали. body — простой текст для показа как есть: разметка Telegram снята, у ссылок адрес в скобках. kind — вид нарушения, по шаблону которого писали: default, temporal, geo, asn, profile, device, hwid, user_agent, torrent, traffic_rate.

level — три значения: clean (нарушений за окно нет либо человек в белом списке), warned (нарушения есть, мер не принимали), limited (по последнему нарушению применили блокировку или ограничение скорости).

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

GET /violations/{id} — карточка ​

Область: violations:read. Отдаёт полную раскладку по анализаторам (temporal_score, geo_score, asn_score, profile_score, device_score, hwid_score, user_agent_score), собранные свидетельства (cities, asn_types, os_list, client_list), флаги (impossible_travel, is_mobile, is_datacenter, is_vpn) и разбор (action_taken, action_taken_at, admin_comment).

Обращение во внешнюю поддержку ​

POST /support-events ​

Область: enforcement:support. Бот или helpdesk сообщает, что клиент написал в поддержку. Если для его нарушения ждёт отложенный шаг с включённой проверкой поддержки, при наступлении срока шаг будет пропущен с причиной support_contacted.

Заголовок Idempotency-Key обязателен и должен быть уникальным для события в пределах API-ключа. Повтор с тем же значением безопасно возвращает 202 и duplicate: true.

json
{
  "source": "telegram-support",
  "kind": "customer_message",
  "occurred_at": "2026-09-26T10:30:00Z",
  "user": { "telegram_id": 123456789 },
  "ticket_id": "ticket-42",
  "metadata": { "queue": "billing" }
}

В user нужен хотя бы один идентификатор: user_uuid, telegram_id, email или username. Если передано несколько, все должны указывать на одного пользователя. Ответы: 404 — пользователь не найден, 409 — идентификатор неоднозначен, 422 — некорректный запрос или время события более чем на пять минут в будущем.

Для отдельного Telegram-бота обычно достаточно telegram_id. Событие хранится в Admin; внешней системе не нужен доступ к базе или тикетам Bedolaga.

Статистика ​

GET /stats, область stats:read:

json
{
  "users_total": 3450,
  "users_active": 2980,
  "users_disabled": 370,
  "users_online": 512,
  "nodes_total": 12,
  "nodes_online": 11,
  "traffic_total_bytes": 48934567890123
}

Общие правила ​

  • Время всегда в ISO 8601 и в UTC
  • Трафик — в байтах, без пересчёта в мегабайты
  • uuid — идентификаторы панели Remnawave, не путайте с внутренними id
  • Неизвестные поля на входе игнорируются, на выходе не появляются: модели строгие

AGPL-3.0 с исключением для плагинов