Перейти к основному содержимому

TypeScript SDK

У XLADA нет отдельного опубликованного SDK под именем XLADA. Это не мешает работе: API форка идентичен API Remnawave — те же пути, те же схемы запросов и ответов. Поэтому совместимы типы и контракты Remnawave, а HTTP-клиент собирается за несколько строк.

Установка​

Для примеров ниже достаточно стандартного fetch, который есть в Node.js 18+ и в браузере. Если вам привычнее axios:

npm install axios

Официальный SDK Remnawave — @remnawave/backend-contract — содержит только типы и zod-схемы, без HTTP-клиента:

npm install @remnawave/backend-contract

В исходниках панели та же библиотека контрактов лежит в apps/backend/libs/contract (копия для фронтенда — в apps/frontend/vendor/backend-contract) и называется @xlada/backend-contract. В npm она не публикуется: подключайте её как локальную зависимость репозитория ("@xlada/backend-contract": "file:./vendor/backend-contract").

Совпадение версий

Привязывайте версию контракта к версии панели. Контракт и панель развиваются разными циклами, поэтому «последняя» версия типов не всегда описывает именно ваш сервер.

Базовый клиент​

Панель ожидает Authorization: Bearer <token>. Если вы обращаетесь к панели напрямую, из внутренней сети, добавьте заголовки прокси — middleware панели разрывает соединение без X-Forwarded-For и X-Forwarded-Proto: https.

const PANEL_URL = process.env.XLADA_PANEL_URL ?? 'https://panel.example.com';
const API_TOKEN = process.env.XLADA_API_TOKEN ?? '';

async function api<T>(path: string, init: RequestInit = {}): Promise<T> {
const res = await fetch(`${PANEL_URL}${path}`, {
...init,
headers: {
'Content-Type': 'application/json',
Authorization: `Bearer ${API_TOKEN}`,
'X-Forwarded-For': '127.0.0.1',
'X-Forwarded-Proto': 'https',
...init.headers,
},
});

if (!res.ok) {
throw new Error(`${res.status} ${res.statusText}: ${await res.text()}`);
}

return (await res.json()) as T;
}

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

Есть два способа получить токен.

JWT администратора — живёт ограниченное время (JWT_AUTH_LIFETIME, от 12 до 168 часов) и выдаётся методом POST /api/auth/login:

curl -sX POST https://panel.example.com/api/auth/login \
-H 'Content-Type: application/json' \
-d '{"username": "admin", "password": "пароль"}'

Ответ содержит accessToken:

{
"response": {
"accessToken": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
}
}

API-токен — для скриптов и интеграций. Создаётся методом POST /api/tokens (в интерфейсе — Настройки → API Tokens) и передаётся в том же заголовке Authorization:

curl -sX POST https://panel.example.com/api/tokens \
-H "Authorization: Bearer $ACCESS_TOKEN" \
-H 'Content-Type: application/json' \
-d '{"name": "ci", "expiresInDays": 365}'

Готовый токен приходит в поле response.token и показывается один раз. Список доступных областей отдаёт GET /api/tokens/scopes.

Список пользователей​

Постраничный вывод: start — смещение, size — размер страницы (от 1 до 1000, по умолчанию 25).

interface GetUsersResponse {
response: {
users: Array<{
id: number;
username: string;
status: 'ACTIVE' | 'DISABLED' | 'LIMITED' | 'EXPIRED';
shortUuid: string;
expireAt: string;
}>;
total: number;
};
}

const { response } = await api<GetUsersResponse>('/api/users?start=0&size=25');

for (const user of response.users) {
console.log(user.username, user.status, user.expireAt);
}
console.log(`всего: ${response.total}`);

Создание пользователя​

POST /api/users принимает username (3–36 символов, только латиница, цифры, _ и -) и обязательный expireAt в формате ISO 8601.

const created = await api<{ response: { id: number; shortUuid: string } }>(
'/api/users',
{
method: 'POST',
body: JSON.stringify({
username: 'john_doe',
status: 'ACTIVE',
expireAt: '2026-01-17T15:38:45.065Z',
trafficLimitBytes: 0,
trafficLimitStrategy: 'NO_RESET',
}),
},
);

console.log(created.response.shortUuid);

Получение ноды​

Одна нода — по её uuid, список — без параметров:

const { response: node } = await api<{
response: { name: string; address: string; port: number | null; isConnected: boolean };
}>(`/api/nodes/${nodeUuid}`);

console.log(node.name, `${node.address}:${node.port}`, node.isConnected);

Где взять типы​

Полная спецификация — 162 пути и 29 тегов — лежит на странице API Specification и в файле static/openapi.json репозитория панели. Из неё можно сгенерировать .d.ts:

npx openapi-typescript ./openapi.json -o ./src/xlada-api.d.ts
Совет

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

Что дальше​