APILuxe

VPN Billing API — обёртка над Remnawave. Безлимитный трафик, оплата за период и устройства.

Обзор

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

API_URL    TOKEN

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

Каждый запрос к /subscriptions/* должен содержать заголовок:

X-Token: your_client_token_here

При неверном токене — 401. При отключённом аккаунте — 403.

Rate limit: не более 100 запросов в минуту на токен. При превышении — 429 Too Many Requests.

Endpoints

GET /subscriptions Список подписок

Возвращает все подписки, созданные через токен клиента. Поле is_active показывает статус в Remnawave.

GET /subscriptions
X-Token: your_token_here
import requests

API_URL = "https://api.luxenetwork.top"
TOKEN = "your_token_here"

r = requests.get(
    f"{API_URL}/subscriptions",
    headers={"X-Token": TOKEN}
)
print(r.json())
import asyncio
import httpx

API_URL = "https://api.luxenetwork.top"
TOKEN = "your_token_here"

async def main():
    async with httpx.AsyncClient() as client:
        r = await client.get(
            f"{API_URL}/subscriptions",
            headers={"X-Token": TOKEN}
        )
    print(r.json())

asyncio.run(main())
const API_URL = "https://api.luxenetwork.top";
const TOKEN = "your_token_here";

const r = await fetch(`${API_URL}/subscriptions`, {
  headers: { "X-Token": TOKEN }
});
console.log(await r.json());
Ответ 200
[
  {
    "uuid": "f47ac10b-...",
    "username": "john_doe",
    "devices_limit": 5,
    "extra_devices": 0,
    "extra_devices_cost": 0.0,
    "expire_at": "2025-05-23T10:00:00Z",
    "is_active": true
  }
]
GET /subscriptions/price Расчёт стоимости

Предварительный расчёт без списания баланса.

Query параметры

ПараметрТипОписание
daysintegeroptional30, 90, 180 или 360
devicesintegeroptionalКоличество дополнительных устройств
GET /subscriptions/price?days=90&devices=2
X-Token: your_token_here
import requests

API_URL = "https://api.luxenetwork.top"
TOKEN = "your_token_here"

r = requests.get(
    f"{API_URL}/subscriptions/price",
    params={"days": 90, "devices": 2},
    headers={"X-Token": TOKEN}
)
print(r.json())
import asyncio
import httpx

API_URL = "https://api.luxenetwork.top"
TOKEN = "your_token_here"

async def main():
    async with httpx.AsyncClient() as client:
        r = await client.get(
            f"{API_URL}/subscriptions/price",
            params={"days": 90, "devices": 2},
            headers={"X-Token": TOKEN}
        )
    print(r.json())

asyncio.run(main())
const API_URL = "https://api.luxenetwork.top";
const TOKEN = "your_token_here";

const r = await fetch(
  `${API_URL}/subscriptions/price?days=90&devices=2`,
  { headers: { "X-Token": TOKEN } }
);
console.log(await r.json());
Ответ 200
{
  "days_cost": 400.0,
  "devices_cost": 100.0,
  "total_cost": 500.0,
  "current_balance": 1000.0,
  "balance_after": 500.0
}
POST /subscriptions/create Создать подписку

Создаёт пользователя в Remnawave и списывает баланс. Трафик — безлимитный.

Тело запроса (JSON)

ПолеТипОписание
usernamestringrequiredИмя пользователя (3–50 символов, без пробелов)
daysintegerrequiredТолько: 30, 90, 180, 360
POST /subscriptions/create
X-Token: your_token_here
Content-Type: application/json

{
  "username": "john_doe",
  "days": 30
}
import requests

API_URL = "https://api.luxenetwork.top"
TOKEN = "your_token_here"

r = requests.post(
    f"{API_URL}/subscriptions/create",
    json={"username": "john_doe", "days": 30},
    headers={"X-Token": TOKEN}
)
print(r.json())
import asyncio
import httpx

API_URL = "https://api.luxenetwork.top"
TOKEN = "your_token_here"

async def main():
    async with httpx.AsyncClient() as client:
        r = await client.post(
            f"{API_URL}/subscriptions/create",
            json={"username": "john_doe", "days": 30},
            headers={"X-Token": TOKEN}
        )
    print(r.json())

asyncio.run(main())
const API_URL = "https://api.luxenetwork.top";
const TOKEN = "your_token_here";

const r = await fetch(`${API_URL}/subscriptions/create`, {
  method: "POST",
  headers: { "X-Token": TOKEN, "Content-Type": "application/json" },
  body: JSON.stringify({ username: "john_doe", days: 30 })
});
console.log(await r.json());
Ответ 201
{
  "uuid": "f47ac10b-58cc-...",
  "short_uuid": "f47ac10b",
  "username": "john_doe",
  "subscription_url": "https://...",
  "devices_limit": 1,
  "connected_devices": 0,
  "expire_at": "2025-05-23T10:00:00Z",
  "is_active": true
}
GET /subscriptions/{uuid} Информация о подписке

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

GET /subscriptions/f47ac10b-58cc-...
X-Token: your_token_here
import requests

API_URL = "https://api.luxenetwork.top"
TOKEN = "your_token_here"
UUID = "f47ac10b-58cc-..."

r = requests.get(
    f"{API_URL}/subscriptions/{UUID}",
    headers={"X-Token": TOKEN}
)
print(r.json())
import asyncio
import httpx

API_URL = "https://api.luxenetwork.top"
TOKEN = "your_token_here"
UUID = "f47ac10b-58cc-..."

async def main():
    async with httpx.AsyncClient() as client:
        r = await client.get(
            f"{API_URL}/subscriptions/{UUID}",
            headers={"X-Token": TOKEN}
        )
    print(r.json())

asyncio.run(main())
const API_URL = "https://api.luxenetwork.top";
const TOKEN = "your_token_here";
const UUID = "f47ac10b-58cc-...";

const r = await fetch(`${API_URL}/subscriptions/${UUID}`, {
  headers: { "X-Token": TOKEN }
});
console.log(await r.json());
Ответ 200 — базовая подписка (без доп. устройств)
{
  "uuid": "f47ac10b-58cc-...",
  "short_uuid": "f47ac10b",
  "username": "john_doe",
  "subscription_url": "https://...",
  "devices_limit": 5,
  "connected_devices": 2,
  "extra_devices": 0,
  "extra_devices_cost": 0.0,
  "expire_at": "2025-05-23T10:00:00Z",
  "is_active": true
}
Ответ 200 — с докупленными устройствами
{
  "uuid": "f47ac10b-58cc-...",
  "short_uuid": "f47ac10b",
  "username": "john_doe",
  "subscription_url": "https://...",
  "devices_limit": 8,
  "connected_devices": 6,
  "extra_devices": 3,
  "extra_devices_cost": 150.0,
  "expire_at": "2025-05-23T10:00:00Z",
  "is_active": true
}
extra_devices_cost — надбавка к цене продления за докупленные устройства. При продлении итоговая стоимость = цена периода + extra_devices_cost.
POST /subscriptions/{uuid}/add-devices Докупить устройства

Увеличивает лимит устройств. Стоимость считается по фиксированной цене за каждое устройство.

Тело запроса

ПолеТипОписание
extra_devicesintegerrequiredКоличество добавляемых устройств (мин. 1)
POST /subscriptions/f47ac10b-.../add-devices
X-Token: your_token_here
Content-Type: application/json

{
  "extra_devices": 2
}
import requests

API_URL = "https://api.luxenetwork.top"
TOKEN = "your_token_here"
UUID = "f47ac10b-58cc-..."

r = requests.post(
    f"{API_URL}/subscriptions/{UUID}/add-devices",
    json={"extra_devices": 2},
    headers={"X-Token": TOKEN}
)
print(r.json())
import asyncio
import httpx

API_URL = "https://api.luxenetwork.top"
TOKEN = "your_token_here"
UUID = "f47ac10b-58cc-..."

async def main():
    async with httpx.AsyncClient() as client:
        r = await client.post(
            f"{API_URL}/subscriptions/{UUID}/add-devices",
            json={"extra_devices": 2},
            headers={"X-Token": TOKEN}
        )
    print(r.json())

asyncio.run(main())
const API_URL = "https://api.luxenetwork.top";
const TOKEN = "your_token_here";
const UUID = "f47ac10b-58cc-...";

const r = await fetch(`${API_URL}/subscriptions/${UUID}/add-devices`, {
  method: "POST",
  headers: { "X-Token": TOKEN, "Content-Type": "application/json" },
  body: JSON.stringify({ extra_devices: 2 })
});
console.log(await r.json());
Ответ 200
{
  "uuid": "f47ac10b-...",
  "devices_limit": 3,
  "connected_devices": 1,
  "expire_at": "2025-05-23T10:00:00Z",
  "is_active": true,
  // ... остальные поля
}
POST /subscriptions/{uuid}/extend Продлить подписку

Продлевает срок подписки от текущей даты окончания (или от сегодня, если уже истекла). Стоимость = цена периода + надбавка за каждое докупленное устройство. В ответе поле charged — фактически списанная сумма.

Тело запроса

ПолеТипОписание
daysintegerrequiredТолько: 30, 90, 180, 360
POST /subscriptions/f47ac10b-.../extend
X-Token: your_token_here
Content-Type: application/json

{
  "days": 90
}
import requests

API_URL = "https://api.luxenetwork.top"
TOKEN = "your_token_here"
UUID = "f47ac10b-58cc-..."

r = requests.post(
    f"{API_URL}/subscriptions/{UUID}/extend",
    json={"days": 90},
    headers={"X-Token": TOKEN}
)
print(r.json())
import asyncio
import httpx

API_URL = "https://api.luxenetwork.top"
TOKEN = "your_token_here"
UUID = "f47ac10b-58cc-..."

async def main():
    async with httpx.AsyncClient() as client:
        r = await client.post(
            f"{API_URL}/subscriptions/{UUID}/extend",
            json={"days": 90},
            headers={"X-Token": TOKEN}
        )
    print(r.json())

asyncio.run(main())
const API_URL = "https://api.luxenetwork.top";
const TOKEN = "your_token_here";
const UUID = "f47ac10b-58cc-...";

const r = await fetch(`${API_URL}/subscriptions/${UUID}/extend`, {
  method: "POST",
  headers: { "X-Token": TOKEN, "Content-Type": "application/json" },
  body: JSON.stringify({ days: 90 })
});
console.log(await r.json());
Ответ 200 — базовая подписка (без доп. устройств)
{
  "uuid": "f47ac10b-...",
  "expire_at": "2025-08-21T10:00:00Z",
  "devices_limit": 5,
  "extra_devices": 0,
  "extra_devices_cost": 0.0,
  "charged": 400.0,
  "is_active": true
}
Ответ 200 — с докупленными устройствами (+3 шт.)
{
  "uuid": "f47ac10b-...",
  "expire_at": "2025-08-21T10:00:00Z",
  "devices_limit": 8,
  "extra_devices": 3,
  "extra_devices_cost": 150.0,
  "charged": 550.0,
  "is_active": true
}
charged — итоговая списанная сумма. Равна цене периода плюс extra_devices_cost за каждое докупленное устройство.
POST /subscriptions/{uuid}/reset-devices Сбросить устройства

Очищает список всех подключённых HWID-устройств. Баланс не списывается.

POST /subscriptions/f47ac10b-.../reset-devices
X-Token: your_token_here
import requests

API_URL = "https://api.luxenetwork.top"
TOKEN = "your_token_here"
UUID = "f47ac10b-58cc-..."

r = requests.post(
    f"{API_URL}/subscriptions/{UUID}/reset-devices",
    headers={"X-Token": TOKEN}
)
print(r.json())
import asyncio
import httpx

API_URL = "https://api.luxenetwork.top"
TOKEN = "your_token_here"
UUID = "f47ac10b-58cc-..."

async def main():
    async with httpx.AsyncClient() as client:
        r = await client.post(
            f"{API_URL}/subscriptions/{UUID}/reset-devices",
            headers={"X-Token": TOKEN}
        )
    print(r.json())

asyncio.run(main())
const API_URL = "https://api.luxenetwork.top";
const TOKEN = "your_token_here";
const UUID = "f47ac10b-58cc-...";

const r = await fetch(`${API_URL}/subscriptions/${UUID}/reset-devices`, {
  method: "POST",
  headers: { "X-Token": TOKEN }
});
console.log(await r.json());
Ответ 200
{
  "uuid": "f47ac10b-...",
  "connected_devices": 0,
  "devices_limit": 1,
  "is_active": true,
  // ... остальные поля
}
POST /subscriptions/{uuid}/reset-extra-devices Сброс доп. устройств

Убирает одно докупленное устройство (лимит −1). Минимум — 5 устройств. Повторяй запрос столько раз, сколько устройств нужно убрать. Баланс не возвращается.

POST /subscriptions/f47ac10b-.../reset-extra-devices
X-Token: your_token_here
import requests

API_URL = "https://api.luxenetwork.top"
TOKEN = "your_token_here"
UUID = "f47ac10b-58cc-..."

r = requests.post(
    f"{API_URL}/subscriptions/{UUID}/reset-extra-devices",
    headers={"X-Token": TOKEN}
)
print(r.json())
import asyncio
import httpx

API_URL = "https://api.luxenetwork.top"
TOKEN = "your_token_here"
UUID = "f47ac10b-58cc-..."

async def main():
    async with httpx.AsyncClient() as client:
        r = await client.post(
            f"{API_URL}/subscriptions/{UUID}/reset-extra-devices",
            headers={"X-Token": TOKEN}
        )
    print(r.json())

asyncio.run(main())
const API_URL = "https://api.luxenetwork.top";
const TOKEN = "your_token_here";
const UUID = "f47ac10b-58cc-...";

const r = await fetch(`${API_URL}/subscriptions/${UUID}/reset-extra-devices`, {
  method: "POST",
  headers: { "X-Token": TOKEN }
});
console.log(await r.json());
Ответ 200 — было 8 устройств, стало 7
{
  "uuid": "f47ac10b-...",
  "devices_limit": 7,
  "extra_devices": 2,
  "extra_devices_cost": 100.0,
  "is_active": true
}
Ошибка 400 — нет доп. устройств
{
  "error": "no_extra_devices"
}
POST /subscriptions/{uuid}/remove-device Убрать устройство

Убирает 1 дополнительное устройство. Бесплатно, баланс не возвращается. Только если есть докупленные устройства сверх базовых 5.

POST /subscriptions/f47ac10b-.../remove-device
X-Token: your_token_here
import requests

API_URL = "https://api.luxenetwork.top"
TOKEN = "your_token_here"
UUID = "f47ac10b-58cc-..."

r = requests.post(
    f"{API_URL}/subscriptions/{UUID}/remove-device",
    headers={"X-Token": TOKEN}
)
print(r.json())
import asyncio
import httpx

API_URL = "https://api.luxenetwork.top"
TOKEN = "your_token_here"
UUID = "f47ac10b-58cc-..."

async def main():
    async with httpx.AsyncClient() as client:
        r = await client.post(
            f"{API_URL}/subscriptions/{UUID}/remove-device",
            headers={"X-Token": TOKEN}
        )
    print(r.json())

asyncio.run(main())
const API_URL = "https://api.luxenetwork.top";
const TOKEN = "your_token_here";
const UUID = "f47ac10b-58cc-...";

const r = await fetch(`${API_URL}/subscriptions/${UUID}/remove-device`, {
  method: "POST",
  headers: { "X-Token": TOKEN }
});
console.log(await r.json());
Ответ 200
{
  "uuid": "f47ac10b-...",
  "devices_limit": 6,
  "extra_devices": 1,
  "extra_devices_cost": 50.0,
  // ... остальные поля
}
Ошибка 400 (нет доп. устройств)
{
  "error": "no_extra_devices",
  "message": "Limit is already at default (5)."
}

Коды ошибок

HTTPПричинаПример ответа
401 Токен не найден или не передан {"detail": "Invalid or unknown token"}
402 Недостаточно баланса {"error":"insufficient_balance","required":400,"available":150,"shortage":250}
403 Клиент отключён {"detail": "Client account is disabled"}
422 Ошибка валидации (например, days не из списка) {"detail": [{"msg": "Input should be 30, 90, 180 or 360"}]}
4xx/5xx Ошибка Remnawave API {"detail": "Remna API 404: ..."}