### Install with npm Source: https://ilmar7786.github.io/marzban-sdk/docs/get-started/installation Install the marzban-sdk package using npm. This is the primary installation command for Node.js projects. ```bash npm install marzban-sdk ``` -------------------------------- ### Deno example Source: https://ilmar7786.github.io/marzban-sdk/docs/integrations/node-bun-deno Deno example using npm:marzban-sdk and Deno.env. Run with deno run and required permissions. ```typescript // main.ts import { createMarzbanSDK } from 'npm:marzban-sdk' const sdk = await createMarzbanSDK({ baseUrl: Deno.env.get('MARZBAN_URL')!, username: Deno.env.get('MARZBAN_USER')!, password: Deno.env.get('MARZBAN_PASS')!, }) const nodes = await sdk.node.getNodes() console.log(`Nodes: ${nodes.length}`) await sdk.destroy() ``` ```bash deno run --allow-net --allow-env main.ts ``` -------------------------------- ### Bun example Source: https://ilmar7786.github.io/marzban-sdk/docs/integrations/node-bun-deno Bun example using Bun.env for environment variables. Run directly with bun run. ```typescript // main.ts — identical code, run directly import { createMarzbanSDK } from 'marzban-sdk' const sdk = await createMarzbanSDK({ baseUrl: Bun.env.MARZBAN_URL!, username: Bun.env.MARZBAN_USER!, password: Bun.env.MARZBAN_PASS!, }) const users = await sdk.user.getUsers() console.log(`Total users: ${users.total}`) await sdk.destroy() ``` ```bash bun run main.ts ``` -------------------------------- ### Install Hono and marzban-sdk Source: https://ilmar7786.github.io/marzban-sdk/docs/webhooks/hono-edge Install the required packages for using Marzban SDK with Hono on edge runtimes. ```bash npm install hono marzban-sdk ``` -------------------------------- ### Install Fastify and marzban-sdk Source: https://ilmar7786.github.io/marzban-sdk/docs/webhooks/fastify Install the required npm packages for using Fastify with the Marzban SDK. ```bash npm install fastify marzban-sdk ``` -------------------------------- ### Install Express and marzban-sdk Source: https://ilmar7786.github.io/marzban-sdk/docs/webhooks/express Run this npm command to install the required packages for using Marzban webhooks with Express. ```bash npm install express marzban-sdk ``` -------------------------------- ### Node.js (TypeScript) example Source: https://ilmar7786.github.io/marzban-sdk/docs/integrations/node-bun-deno Node.js example using createMarzbanSDK with environment variables. Run with tsx or compile with tsc. ```typescript // main.ts import { createMarzbanSDK } from 'marzban-sdk' const sdk = await createMarzbanSDK({ baseUrl: process.env.MARZBAN_URL!, username: process.env.MARZBAN_USER!, password: process.env.MARZBAN_PASS!, }) const stats = await sdk.system.getSystemStats() console.log('Users active:', stats.users_active) await sdk.destroy() ``` ```bash npx tsx main.ts ``` ```bash npx tsc && node dist/main.js ``` -------------------------------- ### Install NestJS dependencies and MarzbanSDK Source: https://ilmar7786.github.io/marzban-sdk/docs/integrations/nestjs Install the required NestJS packages and the MarzbanSDK package. ```bash npm install @nestjs/core @nestjs/common marzban-sdk ``` -------------------------------- ### Full configuration example Source: https://ilmar7786.github.io/marzban-sdk/docs/configuration/config-options Shows all available configuration options, including timeout, retries, authentication on init, logger, and webhook settings. ```typescript import { createMarzbanSDK } from 'marzban-sdk' const sdk = await createMarzbanSDK({ baseUrl: 'https://vpn.example.com', username: 'admin', password: 'secret', timeout: 15_000, // 15 seconds retries: 5, authenticateOnInit: true, logger: { level: 'debug', timestamp: true, }, webhook: { secret: process.env.MARZBAN_WEBHOOK_SECRET, }, }) ``` -------------------------------- ### Prompt with use context7 trigger phrase Source: https://ilmar7786.github.io/marzban-sdk/docs/ai-tools/context7 Example prompt that triggers Context7 to fetch current marzban-sdk documentation. Mention 'use context7' and the library name to get an answer against the current API. ```text Add pagination to sdk.user.getUsers using paginateAll — use context7 for marzban-sdk's current API ``` -------------------------------- ### formatBytes examples Source: https://ilmar7786.github.io/marzban-sdk/docs/utilities/data-sizes Examples of formatting byte numbers to human-readable strings. Supports decimal places and SI units options. ```typescript formatBytes(0) // "0 B" formatBytes(1024) // "1.00 KB" formatBytes(10737418240) // "10.00 GB" formatBytes(10737418240, { decimals: 0 }) // "10 GB" formatBytes(1500000, { decimal: true }) // "1.50 MB" (SI) formatBytes(-2097152) // "-2.00 MB" ``` -------------------------------- ### Wire everything up in app.module.ts Source: https://ilmar7786.github.io/marzban-sdk/docs/webhooks/nestjs Import the MarzbanModule and WebhookController into the root AppModule to complete the setup. ```typescript // app.module.ts import { Module } from '@nestjs/common' import { MarzbanModule } from './marzban/marzban.module' import { WebhookController } from './webhook/webhook.controller' @Module({ imports: [MarzbanModule], controllers: [WebhookController], }) export class AppModule {} ``` -------------------------------- ### Full Fastify webhook example Source: https://ilmar7786.github.io/marzban-sdk/docs/webhooks/fastify Complete Fastify server that creates the SDK, subscribes to user_created events, registers a raw body parser, and handles POST /webhook with signature verification. ```typescript import Fastify from 'fastify' import { createMarzbanSDK, isWebhookSignatureError } from 'marzban-sdk' const app = Fastify() const sdk = await createMarzbanSDK({ baseUrl: process.env.MARZBAN_URL!, username: process.env.MARZBAN_USER!, password: process.env.MARZBAN_PASS!, webhook: { secret: process.env.MARZBAN_WEBHOOK_SECRET, }, }) // Subscribe to events sdk.webhook.on('user_created', payload => { console.log('User created:', payload.user.username) }) // Register a raw body parser for the webhook route app.addContentTypeParser( 'application/json', { parseAs: 'buffer' }, (_req, body, done) => done(null, body) ) app.post('/webhook', async (req, reply) => { try { await sdk.webhook.handleWebhook( req.body as Buffer, // raw Buffer (req.headers['x-signature'] as string) ) reply.send({ ok: true }) } catch (err) { if (isWebhookSignatureError(err)) { reply.code(401).send({ error: 'Invalid signature' }) } else { reply.code(400).send({ error: 'Bad webhook payload' }) } } }) await app.listen({ port: 3000 }) console.log('Fastify webhook server listening on :3000') ``` -------------------------------- ### Quick example: create SDK and list active users Source: https://ilmar7786.github.io/marzban-sdk/docs Shows the first request with marzban-sdk: create an SDK instance with baseUrl, username, and password, then fetch active users and display data and time remaining. Uses formatBytes and humanRemaining utilities. ```typescript import { createMarzbanSDK, formatBytes, humanRemaining } from 'marzban-sdk' const sdk = await createMarzbanSDK({ baseUrl: 'https://vpn.example.com', username: 'admin', password: 'secret', }) // List active users const { users, total } = await sdk.user.getUsers({ status: 'active' }) console.log(`${total} active users`) for (const user of users) { const dataLeft = formatBytes((user.data_limit ?? 0) - user.used_traffic) const timeLeft = user.expire ? humanRemaining(user.expire * 1000) : '∞' console.log(`${user.username} — ${dataLeft} left, expires ${timeLeft}`) } ``` -------------------------------- ### Get core stats with sdk.core.getCoreStats() Source: https://ilmar7786.github.io/marzban-sdk/docs/modules/core Retrieves runtime statistics for the Xray core process. The returned CoreStats object includes version, started, and logs_websocket fields. ```typescript const stats = await sdk.core.getCoreStats() console.log(stats.version) // "1.8.4" console.log(stats.started) // true console.log(stats.logs_websocket) // "/api/core/logs" ``` -------------------------------- ### getHosts() - Get current proxy host configuration Source: https://ilmar7786.github.io/marzban-sdk/docs/modules/system Use to get the current proxy host configuration for all inbound tags, grouped by inbound tag. Returns a Record. The example iterates over the entries and logs each tag, remark, address, and port. ```javascript const hosts = await sdk.system.getHosts() // Returns Record for (const [tag, hostList] of Object.entries(hosts)) { for (const host of hostList) { console.log(tag, host.remark, host.address, host.port) } } ``` -------------------------------- ### Custom logger with Pino Source: https://ilmar7786.github.io/marzban-sdk/docs/configuration/logging Example of using Pino as a custom logger for the SDK. ```javascript import pino from 'pino' import { createMarzbanSDK } from 'marzban-sdk' const logger = pino({ level: 'debug' }) const sdk = await createMarzbanSDK({ // ... logger: { debug: (msg, ctx) => logger.debug({ ctx }, msg), info: (msg, ctx) => logger.info({ ctx }, msg), warn: (msg, ctx) => logger.warn({ ctx }, msg), error: (msg, trace, ctx) => logger.error({ ctx, trace }, msg), }, }) ``` -------------------------------- ### Custom logger with Winston Source: https://ilmar7786.github.io/marzban-sdk/docs/configuration/logging Example of using Winston as a custom logger for the SDK. ```javascript import winston from 'winston' import { createMarzbanSDK } from 'marzban-sdk' const winstonLogger = winston.createLogger({ level: 'info', transports: [new winston.transports.Console()], }) const sdk = await createMarzbanSDK({ // ... logger: { debug: (msg, ctx) => winstonLogger.debug(msg, { context: ctx }), info: (msg, ctx) => winstonLogger.info(msg, { context: ctx }), warn: (msg, ctx) => winstonLogger.warn(msg, { context: ctx }), error: (msg, trace, ctx) => winstonLogger.error(msg, { context: ctx, trace }), }, }) ``` -------------------------------- ### Display usage stats Source: https://ilmar7786.github.io/marzban-sdk/docs/utilities/data-sizes Example of using formatBytes to display user usage statistics. ```typescript import { formatBytes } from 'marzban-sdk' const user = await sdk.user.getUser('alice') const used = formatBytes(user.used_traffic) const limit = user.data_limit ? formatBytes(user.data_limit) : 'Unlimited' const percent = user.data_limit ? ((user.used_traffic / user.data_limit) * 100).toFixed(1) : '—' console.log(`${used} / ${limit} (${percent}%)`) // "3.52 GB / 10.00 GB (35.2%)" ``` -------------------------------- ### Make first request: get users, user, and system stats Source: https://ilmar7786.github.io/marzban-sdk/docs/get-started/quick-start Shows how to use the SDK to fetch paginated users, a single user by username, and system statistics. Every method returns a Promise that resolves to a fully typed response object. ```typescript // Get all users (paginated) const users = await sdk.user.getUsers() console.log(users) // Get a single user by username const user = await sdk.user.getUser('alice') console.log(user.status, user.data_limit) // Get system statistics const stats = await sdk.system.getSystemStats() console.log(`Memory: ${stats.mem_used} / ${stats.mem_total}`) ``` -------------------------------- ### Create a user with a 30-day trial Source: https://ilmar7786.github.io/marzban-sdk/docs/modules/users Use this snippet to create a new user with a 30-day trial period. It sets a 5GB data limit and an expiration date 30 days from now. The example uses `createMarzbanSDK` and `parseSize` from the SDK. ```typescript import { createMarzbanSDK, parseSize } from 'marzban-sdk' const sdk = await createMarzbanSDK({ /* ... */ }) const user = await sdk.user.addUser({ username: 'trial_user', proxies: { vless: {}, vmess: {} }, inbounds: { vless: ['VLESS TCP REALITY'], vmess: ['VMess Websocket'], }, data_limit: parseSize('5GB'), expire: Math.floor(Date.now() / 1000) + 30 * 86400, }) console.log('Subscription:', user.subscription_url) ``` -------------------------------- ### Example of text format output for marzban_users_get Source: https://ilmar7786.github.io/marzban-sdk/docs/mcp-server/response-format Shows the default text format output for a single user, using compact key: value lines. This is cheaper in tokens than a markdown table for a single row. ```text username: alice | status: active | usage: 2.1 GB / 10 GB | expire: 2026-09-01 (18d) ``` -------------------------------- ### Run integration tests for SDK and MCP Source: https://ilmar7786.github.io/marzban-sdk/docs/resources/contributing Starts local services and runs integration tests against a real panel. These tests are not part of the default 'pnpm test' and are not held to the coverage threshold. ```shell pnpm local:up pnpm --filter marzban-sdk test:integration pnpm --filter marzban-mcp test:integration ``` -------------------------------- ### Clone and set up the MarzbanSDK monorepo Source: https://ilmar7786.github.io/marzban-sdk/docs/resources/contributing Clones the repository, installs dependencies with pnpm, then builds and runs the test suite. Requires Node ≥ 24 and pnpm 11 (Corepack fetches the pinned version automatically). ```bash git clone https://github.com/Ilmar7786/marzban-sdk.git cd marzban-sdk pnpm install pnpm build && pnpm test ``` -------------------------------- ### parseSize examples Source: https://ilmar7786.github.io/marzban-sdk/docs/utilities/data-sizes Examples of parsing human-readable size strings into bytes. Supports binary (1024-based) by default, with an option for decimal (SI) units. Invalid input returns 0. ```typescript parseSize('10GB') // 10737418240 (binary, 1024³) parseSize('10 gb') // 10737418240 parseSize('1.5 TB') // 1649267441664 parseSize(1073741824) // 1073741824 (number passthrough) parseSize('500MB', { decimal: true }) // 500000000 (SI units, 1000³) parseSize('invalid') // 0 ``` -------------------------------- ### Create a user with addUser Source: https://ilmar7786.github.io/marzban-sdk/docs/get-started/quick-start Creates a new user with a VLESS proxy, inbound, data limit, and expiration. The example shows how to set a 10 GB data limit and a 30-day expiry. ```typescript import { createMarzbanSDK } from 'marzban-sdk' const sdk = await createMarzbanSDK({ /* ... */ }) const newUser = await sdk.user.addUser({ username: 'alice', proxies: { vless: {} }, inbounds: { vless: ['VLESS TCP REALITY'] }, data_limit: 10 * 1024 ** 3, // 10 GB in bytes expire: Math.floor(Date.now() / 1000) + 30 * 24 * 3600, // 30 days from now }) console.log(newUser.subscription_url) ``` -------------------------------- ### Manage a local Marzban panel with pnpm local scripts Source: https://ilmar7786.github.io/marzban-sdk/docs/resources/contributing Starts a disposable local Marzban panel in Docker, follows its logs, stops it, or stops and wipes its data. Used for trying changes against a real panel and by the integration test suite. ```bash pnpm local:up # start pnpm local:logs # follow logs pnpm local:down # stop pnpm local:reset # stop and wipe data ``` -------------------------------- ### Connect with replay 'all' and 'skip' options Source: https://ilmar7786.github.io/marzban-sdk/docs/realtime/replay Shows two ways to call connectByCore with the replay option: 'all' delivers every line including duplicates, while 'skip' drops replayed messages until a clean one arrives. Both examples use the same onMessage callback that logs each message. ```javascript // See every line, duplicates included await sdk.logs.connectByCore({ onMessage: data => console.log(data), replay: 'all' }) // Drop every replayed message outright, until the first clean one await sdk.logs.connectByCore({ onMessage: data => console.log(data), replay: 'skip' }) ``` -------------------------------- ### getUsersUsage - Get aggregated usage stats across all users Source: https://ilmar7786.github.io/marzban-sdk/docs/modules/users Gets aggregated usage stats across all users. Returns a UsersUsagesResponse. ```javascript const usage = await sdk.user.getUsersUsage({ start: '2024-01-01T00:00:00' }) ``` -------------------------------- ### user_created webhook payload example Source: https://ilmar7786.github.io/marzban-sdk/docs/webhooks/event-types Shows the complete JSON payload for the user_created event, including the base fields and the user and by objects. Use this as a reference for the structure of webhook payloads. ```json { "action": "user_created", "username": "alice", "enqueued_at": 1705312800.0, "send_at": 1705312800.1, "tries": 0, "user": { "username": "alice", "status": "active", "data_limit": 10737418240, "expire": 1707904800, "subscription_url": "https://vpn.example.com/sub/abc123" }, "by": { "username": "admin", "is_sudo": true } } ``` -------------------------------- ### getUserUsage - Get per-node usage stats for a user Source: https://ilmar7786.github.io/marzban-sdk/docs/modules/users Gets per-node usage stats for one user, optionally filtered by time range. Returns a UserUsagesResponse. ```javascript const usage = await sdk.user.getUserUsage('alice', { start: '2024-01-01T00:00:00', end: '2024-01-31T23:59:59', }) ``` -------------------------------- ### Get core config with sdk.core.getCoreConfig() Source: https://ilmar7786.github.io/marzban-sdk/docs/modules/core Retrieves the full current Xray JSON configuration as an untyped object. ```typescript const config = await sdk.core.getCoreConfig() // Returns a raw JSON object — the full Xray config tree console.log(JSON.stringify(config, null, 2)) ``` -------------------------------- ### gbToBytes examples Source: https://ilmar7786.github.io/marzban-sdk/docs/utilities/data-sizes Convert gigabytes to bytes. By default uses binary (1024-based), with an optional decimal (SI) flag. ```typescript gbToBytes(10) // 10737418240 (binary) gbToBytes(10, true) // 10000000000 (decimal/SI) ``` -------------------------------- ### getUser - Fetch a single user by username Source: https://ilmar7786.github.io/marzban-sdk/docs/modules/users Fetches a single user by username. Returns a UserResponse. The example logs the user's status, used traffic, and subscription URL. ```javascript const user = await sdk.user.getUser('alice') console.log(user.status) // 'active' | 'disabled' | ... console.log(user.used_traffic) // bytes consumed console.log(user.subscription_url) ``` -------------------------------- ### getSystemStats() - Retrieve system resource and traffic statistics Source: https://ilmar7786.github.io/marzban-sdk/docs/modules/system Use to fetch overall system resource and traffic statistics. Returns a SystemStats object. The example logs the version, active users, total users, CPU usage, and memory usage. ```javascript const stats = await sdk.system.getSystemStats() console.log(stats.version) console.log(stats.users_active, '/', stats.total_user) console.log(`CPU: ${stats.cpu_usage.toFixed(1)}%`) console.log(`RAM: ${stats.mem_used} / ${stats.mem_total} bytes`) ``` -------------------------------- ### getUsers - List users with filtering and pagination Source: https://ilmar7786.github.io/marzban-sdk/docs/modules/users Lists users with optional filtering and pagination. Returns a UsersResponse. The example shows using offset, limit, status, and sort parameters. ```javascript const result = await sdk.user.getUsers({ offset: 0, limit: 50, status: 'active', sort: 'created_at', }) console.log(result.users) // UserResponse[] console.log(result.total) // number ``` -------------------------------- ### Graceful shutdown Source: https://ilmar7786.github.io/marzban-sdk/docs/integrations/node-bun-deno Graceful shutdown example: starts log streaming and closes all streams on SIGTERM/SIGINT. ```typescript import { createMarzbanSDK } from 'marzban-sdk' const sdk = await createMarzbanSDK({ /* ... */ }) // Start log streaming — the returned handle isn't needed here since // sdk.destroy() below closes every active stream at once await sdk.logs.connectByCore({ onMessage: (data) => process.stdout.write(data), }) // Graceful shutdown on SIGTERM / SIGINT async function shutdown() { console.log('Shutting down...') await sdk.destroy() // closes WebSocket streams process.exit(0) } process.on('SIGTERM', shutdown) process.on('SIGINT', shutdown) ``` -------------------------------- ### Full example with raw body and signature verification Source: https://ilmar7786.github.io/marzban-sdk/docs/webhooks/express Complete Express app using express.raw() to preserve the raw body for signature verification. It subscribes to events, handles 'x-signature' header, and responds with appropriate status codes. Requires environment variables for Marzban credentials and webhook secret. ```javascript import express from 'express' import { createMarzbanSDK, isWebhookSignatureError } from 'marzban-sdk' const app = express() const sdk = await createMarzbanSDK({ baseUrl: process.env.MARZBAN_URL!, username: process.env.MARZBAN_USER!, password: process.env.MARZBAN_PASS!, webhook: { secret: process.env.MARZBAN_WEBHOOK_SECRET, }, }) // Subscribe to events sdk.webhook.on('user_created', payload => { console.log('New user:', payload.user.username) }) sdk.webhook.on('user_limited', payload => { console.log('User reached limit:', payload.username) }) sdk.webhook.on('*', payload => { // Wildcard — fires for every event console.log('Event:', payload.action, payload.username) }) // Important: use express.raw() to preserve the raw body for signature verification app.post( '/webhook', express.raw({ type: 'application/json' }), async (req, res) => { try { await sdk.webhook.handleWebhook( req.body, // Buffer (raw bytes) req.headers['x-signature'] as string ) res.sendStatus(200) } catch (err) { if (isWebhookSignatureError(err)) { res.status(401).json({ error: 'Invalid signature' }) } else { console.error('Webhook error:', err) res.status(400).json({ error: 'Bad request' }) } } } ) app.listen(3000, () => console.log('Webhook server listening on :3000')) ``` -------------------------------- ### getUsersUsage(params?) Source: https://ilmar7786.github.io/marzban-sdk/docs/modules/users Gets aggregated usage stats across all users. Returns a UsersUsagesResponse object. ```APIDOC ## getUsersUsage(params?) ### Description Get aggregated usage stats across all users. ### Method SDK Method ### Endpoint `sdk.user.getUsersUsage(params?)` ### Parameters - **params** (object) - Optional - Query parameters for filtering. - **start** (string) - Optional - Start time in ISO format. - **end** (string) - Optional - End time in ISO format. ### Request Example ```javascript const usage = await sdk.user.getUsersUsage({ start: '2024-01-01T00:00:00' }) ``` ### Response #### Success Response - **UsersUsagesResponse** - The aggregated usage statistics. #### Response Example ```javascript // No explicit example provided ``` ``` -------------------------------- ### humanRemaining usage Source: https://ilmar7786.github.io/marzban-sdk/docs/utilities/datetime Get a compact, human-readable remaining time string. Examples show outputs for various durations, including 'expired' and '< 1s'. ```javascript humanRemaining(Date.now() + 86400 * 1000 * 3) // "3d" humanRemaining(Date.now() + 3600 * 1000 * 2) // "2h" humanRemaining(Date.now() + 60 * 1000 * 90) // "1h 30m" humanRemaining(Date.now() - 1000) // "expired" humanRemaining(Date.now() + 500) // "< 1s" ``` -------------------------------- ### getCoreStats() Source: https://ilmar7786.github.io/marzban-sdk/docs/modules/core Get runtime statistics for the Xray core process. Returns a CoreStats object with version, started status, and logs websocket endpoint. ```APIDOC ## getCoreStats() ### Description Get runtime statistics for the Xray core process. ### Method SDK Method ### Endpoint `sdk.core.getCoreStats()` ### Returns `CoreStats` ### Response Example ``` const stats = await sdk.core.getCoreStats() console.log(stats.version) // "1.8.4" console.log(stats.started) // true console.log(stats.logs_websocket) // "/api/core/logs" ``` ### CoreStats Fields - **version** (string) - Xray core version, e.g. "1.8.4" - **started** (boolean) - true when the Xray process is running - **logs_websocket** (string) - WebSocket endpoint path for core log streaming ``` -------------------------------- ### getInbounds() - List all available inbounds Source: https://ilmar7786.github.io/marzban-sdk/docs/modules/system Use to list all available inbounds configured in Xray core, grouped by protocol. Returns a Record. The example iterates over the entries and logs each protocol and its tags. ```javascript const inbounds = await sdk.system.getInbounds() // Returns Record // e.g. { vless: [...], vmess: [...], trojan: [...] } for (const [protocol, tags] of Object.entries(inbounds)) { console.log(protocol, tags) } ``` -------------------------------- ### addUser - Create a new user Source: https://ilmar7786.github.io/marzban-sdk/docs/modules/users Creates a new user from a UserCreate payload. Returns a UserResponse. The example shows setting a username, proxies, inbounds, data limit, and expiration. ```javascript const user = await sdk.user.addUser({ username: 'alice', proxies: { vless: {} }, inbounds: { vless: ['VLESS TCP REALITY'] }, data_limit: 10 * 1024 ** 3, // 10 GB expire: Math.floor(Date.now() / 1000) + 30 * 86400, }) console.log(user.subscription_url) console.log(user.links) ``` -------------------------------- ### Get per-node usage stats with userGetUsage Source: https://ilmar7786.github.io/marzban-sdk/docs/modules/subscriptions Fetch per-node usage statistics for a subscription, optionally filtered by a date range. The params object can include start and end timestamps. ```typescript const usage = await sdk.subscription.userGetUsage('user-subscription-token', { start: '2024-01-01T00:00:00', end: '2024-01-31T23:59:59', }) ``` -------------------------------- ### getUserUsage(username, params?) Source: https://ilmar7786.github.io/marzban-sdk/docs/modules/users Gets per-node usage stats for one user, optionally filtered by time range. Returns a UserUsagesResponse object. ```APIDOC ## getUserUsage(username, params?) ### Description Get per-node usage stats for one user, optionally filtered by time range. ### Method SDK Method ### Endpoint `sdk.user.getUserUsage(username, params?)` ### Parameters - **username** (string) - Required - The username of the user. - **params** (object) - Optional - Query parameters for filtering. - **start** (string) - Optional - Start time in ISO format. - **end** (string) - Optional - End time in ISO format. ### Request Example ```javascript const usage = await sdk.user.getUserUsage('alice', { start: '2024-01-01T00:00:00', end: '2024-01-31T23:59:59', }) ``` ### Response #### Success Response - **UserUsagesResponse** - The usage statistics for the user. #### Response Example ```javascript // No explicit example provided ``` ``` -------------------------------- ### Minimal configuration Source: https://ilmar7786.github.io/marzban-sdk/docs/configuration/config-options Creates a Marzban SDK instance with the minimum required options: baseUrl, username, and password. ```typescript import { createMarzbanSDK } from 'marzban-sdk' const sdk = await createMarzbanSDK({ baseUrl: 'https://vpn.example.com', username: 'admin', password: 'secret', }) ``` -------------------------------- ### Nodes API Source: https://ilmar7786.github.io/marzban-sdk/docs/modules/nodes Endpoints for managing Marzban worker nodes: list, add, retrieve, modify, get settings, and get usage. ```APIDOC ## [GET] /api/nodes ### Description Retrieves a list of all Marzban worker nodes. ### Method GET ### Endpoint /api/nodes ### Parameters #### Query Parameters - **offset** (number) - Optional - Offset for pagination - **limit** (number) - Optional - Limit for pagination ### Response #### Success Response (200) - **nodes** (array of NodeResponse) - List of nodes #### Response Example { "nodes": [ { "id": 1, "name": "node1", "address": "192.168.1.1", "port": 62050, "api_port": 62051, "usage_coefficient": 1, "status": "connected", "xray_version": "v1.8.0", "message": null } ] } ## [POST] /api/node ### Description Adds a new Marzban worker node. ### Method POST ### Endpoint /api/node ### Parameters #### Request Body - **name** (string) - Required - Display name - **address** (string) - Required - IP address or hostname - **port** (number) - Optional - Xray API port (default: 62050) - **api_port** (number) - Optional - Node gRPC API port (default: 62051) - **usage_coefficient** (number) - Optional - Traffic multiplier (default: 1) - **add_as_new_host** (boolean) - Optional - Auto-create a host entry (default: true) ### Request Example { "name": "node1", "address": "192.168.1.1", "port": 62050, "api_port": 62051, "usage_coefficient": 1, "add_as_new_host": true } ### Response #### Success Response (200) - **NodeResponse** - The created node #### Response Example { "id": 1, "name": "node1", "address": "192.168.1.1", "port": 62050, "api_port": 62051, "usage_coefficient": 1, "status": "connected", "xray_version": "v1.8.0", "message": null } ## [GET] /api/node/{node_id} ### Description Retrieves details of a specific node by its ID. ### Method GET ### Endpoint /api/node/{node_id} ### Parameters #### Path Parameters - **node_id** (number) - Required - Unique node ID ### Response #### Success Response (200) - **NodeResponse** - The node details #### Response Example { "id": 1, "name": "node1", "address": "192.168.1.1", "port": 62050, "api_port": 62051, "usage_coefficient": 1, "status": "connected", "xray_version": "v1.8.0", "message": null } ## [PUT] /api/node/{node_id} ### Description Modifies an existing node. All fields are optional; omitted fields are left unchanged. ### Method PUT ### Endpoint /api/node/{node_id} ### Parameters #### Path Parameters - **node_id** (number) - Required - Unique node ID #### Request Body - **name** (string|null) - Optional - Display name - **address** (string|null) - Optional - IP address or hostname - **port** (number|null) - Optional - Xray API port - **api_port** (number|null) - Optional - Node gRPC API port - **usage_coefficient** (number|null) - Optional - Traffic multiplier - **status** (string|null) - Optional - Force connection state (e.g., 'disabled') ### Request Example { "name": "node1-updated", "status": "disabled" } ### Response #### Success Response (200) - **NodeResponse** - The updated node #### Response Example { "id": 1, "name": "node1-updated", "address": "192.168.1.1", "port": 62050, "api_port": 62051, "usage_coefficient": 1, "status": "disabled", "xray_version": "v1.8.0", "message": null } ## [GET] /api/node/settings ### Description Retrieves the global TLS settings used for node-to-core communication. ### Method GET ### Endpoint /api/node/settings ### Response #### Success Response (200) - **certificate** (string) - TLS certificate - **min_node_version** (string) - Minimum supported node version #### Response Example { "certificate": "-----BEGIN CERTIFICATE-----...", "min_node_version": "v0.2.0" } ## [GET] /api/nodes/usage ### Description Retrieves traffic totals per node over a requested range. ### Method GET ### Endpoint /api/nodes/usage ### Parameters #### Query Parameters - **start** (string) - Required - Start date (ISO format) - **end** (string) - Required - End date (ISO format) ### Response #### Success Response (200) - **usages** (array of NodeUsageResponse) - Per-node traffic entries Each NodeUsageResponse: - **node_id** (number|null) - Node ID; null for aggregated/unassigned traffic - **node_name** (string) - Node display name - **uplink** (number) - Bytes sent (upload) - **downlink** (number) - Bytes received (download) #### Response Example { "usages": [ { "node_id": 1, "node_name": "node1", "uplink": 1024, "downlink": 2048 } ] } ``` -------------------------------- ### Testing with a pre-set token Source: https://ilmar7786.github.io/marzban-sdk/docs/authentication/manual-auth Create an SDK with a preset token for testing. The token is used immediately; authenticateOnInit is false to avoid an initial login. ```typescript const sdk = await createMarzbanSDK({ baseUrl: 'http://localhost:7777', username: 'test', password: 'test', token: 'test-jwt-token', authenticateOnInit: false, }) ``` -------------------------------- ### Get admin usage Source: https://ilmar7786.github.io/marzban-sdk/docs/modules/admins Gets traffic usage attributed to a specific admin's users. Returns total bytes used as a number. ```typescript const usage = await sdk.admin.getAdminUsage('operator', { start: '2024-01-01T00:00:00', end: '2024-01-31T23:59:59', }) ``` -------------------------------- ### Example Conventional Commit messages Source: https://ilmar7786.github.io/marzban-sdk/docs/resources/contributing Commit messages must follow Conventional Commits as enforced by commitlint. These examples cover feat, fix, and docs types. ```text feat: add pagination to getUsers fix: handle missing token in AuthManager docs: add NestJS integration example ``` -------------------------------- ### Marzban service with webhook handlers Source: https://ilmar7786.github.io/marzban-sdk/docs/webhooks/nestjs Create the MarzbanService that initializes the SDK and registers webhook event handlers for user_created and user_limited events. ```typescript // marzban/marzban.service.ts import { Injectable, OnModuleInit } from '@nestjs/common' import { createMarzbanSDK, MarzbanSDK } from 'marzban-sdk' @Injectable() export class MarzbanService implements OnModuleInit { sdk!: MarzbanSDK async onModuleInit() { this.sdk = await createMarzbanSDK({ baseUrl: process.env.MARZBAN_URL!, username: process.env.MARZBAN_USER!, password: process.env.MARZBAN_PASS!, webhook: { secret: process.env.MARZBAN_WEBHOOK_SECRET, }, }) this.sdk.webhook.on('user_created', payload => { console.log('User created:', payload.user.username) }) this.sdk.webhook.on('user_limited', payload => { console.log('User limited:', payload.username) }) } } ``` -------------------------------- ### Bootstrap standard templates on first run Source: https://ilmar7786.github.io/marzban-sdk/docs/modules/user-templates Checks if no templates exist, then creates two standard templates: 'Basic – 5GB / 30d' and 'Pro – Unlimited / 30d'. Uses parseSize to convert human-readable sizes. ```javascript import { parseSize } from 'marzban-sdk' const templates = await sdk.userTemplate.getUserTemplates() if (templates.length === 0) { await sdk.userTemplate.addUserTemplate({ name: 'Basic – 5GB / 30d', data_limit: parseSize('5GB'), expire_duration: 30 * 86400, inbounds: { vless: ['VLESS TCP REALITY'] }, }) await sdk.userTemplate.addUserTemplate({ name: 'Pro – Unlimited / 30d', data_limit: 0, expire_duration: 30 * 86400, inbounds: { vless: ['VLESS TCP REALITY'], vmess: ['VMess Websocket'], }, }) } ``` -------------------------------- ### Route Handler for users API Source: https://ilmar7786.github.io/marzban-sdk/docs/integrations/nextjs Route Handler with GET and POST endpoints. GET fetches up to 50 users, POST creates a user from the request body and returns 201 on success. ```typescript // app/api/users/route.ts import { NextResponse } from 'next/server' import { getSDK } from '@/lib/marzban' export async function GET() { const sdk = await getSDK() const result = await sdk.user.getUsers({ limit: 50 }) return NextResponse.json(result) } export async function POST(req: Request) { const sdk = await getSDK() const body = await req.json() const user = await sdk.user.addUser(body) return NextResponse.json(user, { status: 201 }) } ``` -------------------------------- ### getCurrentAdmin() Source: https://ilmar7786.github.io/marzban-sdk/docs/modules/admins Get the profile of the currently authenticated admin. ```APIDOC ## getCurrentAdmin() ### Description Get the profile of the currently authenticated admin. ### Method SDK Method ### Endpoint `sdk.admin.getCurrentAdmin()` ### Parameters None ### Returns `Admin` ### Example ```typescript const me = await sdk.admin.getCurrentAdmin() console.log(me.username) console.log(me.is_sudo) // true for superadmin console.log(me.telegram_id) ``` ``` -------------------------------- ### Create MarzbanService that initializes SDK Source: https://ilmar7786.github.io/marzban-sdk/docs/integrations/nestjs Service that creates the MarzbanSDK instance on module init, reads configuration from ConfigService, and provides a getter for the SDK. It also destroys the SDK on module destroy. ```typescript // marzban/marzban.service.ts import { Injectable, OnModuleInit, OnModuleDestroy } from '@nestjs/common' import { createMarzbanSDK, MarzbanSDK } from 'marzban-sdk' import { ConfigService } from '@nestjs/config' @Injectable() export class MarzbanService implements OnModuleInit, OnModuleDestroy { private _sdk!: MarzbanSDK constructor(private config: ConfigService) {} async onModuleInit() { this._sdk = await createMarzbanSDK({ baseUrl: this.config.getOrThrow('MARZBAN_URL'), username: this.config.getOrThrow('MARZBAN_USER'), password: this.config.getOrThrow('MARZBAN_PASS'), logger: { level: this.config.get('NODE_ENV') === 'production' ? 'error' : 'info', }, webhook: { secret: this.config.get('MARZBAN_WEBHOOK_SECRET'), }, }) } async onModuleDestroy() { await this._sdk?.destroy() } get sdk(): MarzbanSDK { return this._sdk } } ``` -------------------------------- ### Build, test, and type-check Source: https://ilmar7786.github.io/marzban-sdk/docs/resources/contributing Runs the build, test suite, and type checker. All three must pass before submitting a pull request. ```shell pnpm build pnpm test pnpm types:check ``` -------------------------------- ### getNode(node_id) Source: https://ilmar7786.github.io/marzban-sdk/docs/modules/nodes Gets a single node by ID. Returns a NodeResponse object. ```APIDOC ## getNode(node_id) ### Description Get a single node by ID. ### Method GET ### Endpoint /sdk/node/getNode/{node_id} ### Parameters #### Path Parameters - **node_id** (number) - Required - The ID of the node to retrieve. ### Returns `NodeResponse` ### Example ``` const node = await sdk.node.getNode(1) console.log(node.name) console.log(node.status) // 'connected' | 'connecting' | 'error' | 'disabled' console.log(node.message) // error details when status === 'error' ``` ``` -------------------------------- ### Preview Changelog Commands Source: https://ilmar7786.github.io/marzban-sdk/docs/resources/contributing Use these commands to preview the changelog for a pending version bump before it lands on main. They generate the changelog for the SDK and MCP packages respectively. ```bash pnpm changelog:sdk pnpm changelog:mcp ``` -------------------------------- ### Build a subscription info card Source: https://ilmar7786.github.io/marzban-sdk/docs/modules/subscriptions Common pattern to build a subscription info card using formatBytes and humanRemaining helpers. It fetches subscription info and formats data usage, data limit, and expiry. ```typescript import { formatBytes, humanRemaining } from 'marzban-sdk' const token = req.params.token const info = await sdk.subscription.userSubscriptionInfo(token) return { username: info.username, status: info.status, dataUsed: formatBytes(info.used_traffic), dataLimit: info.data_limit ? formatBytes(info.data_limit) : 'Unlimited', expiry: info.expire ? humanRemaining(info.expire * 1000) : 'Never', } ``` -------------------------------- ### getUserTemplateEndpoint(id) Source: https://ilmar7786.github.io/marzban-sdk/docs/modules/user-templates Gets a single user template by its ID. Returns a UserTemplateResponse object. ```APIDOC ## getUserTemplateEndpoint(id) ### Description Get a single template by ID. ### Parameters - **id** (number) - Required - The ID of the template to retrieve. ### Returns `UserTemplateResponse` ### Example ```js const template = await sdk.userTemplate.getUserTemplateEndpoint(1) console.log(template.name) console.log(template.inbounds) ``` ``` -------------------------------- ### Authentication Lifecycle Diagram Source: https://ilmar7786.github.io/marzban-sdk/docs/authentication/auto-authentication Shows the sequence of operations during SDK initialization and request handling, including token storage and retry logic on 401 responses. ```text createMarzbanSDK() └─► validateConfig() └─► new MarzbanSDK() ← interceptors wired └─► sdk.authorize() └─► POST /api/admin/token └─► token stored in memory └─► returns sdk any sdk.user / sdk.node / ... call └─► request interceptor attaches Bearer token └─► response interceptor └─► 200 → return data └─► 401 → re-authenticate → retry once → return data ``` -------------------------------- ### addHours usage Source: https://ilmar7786.github.io/marzban-sdk/docs/utilities/datetime Shorthand for adding hours to a date. The example converts the result to a Unix timestamp. ```javascript const expiryTimestamp = Math.floor(addHours(new Date(), 24).getTime() / 1000) ``` -------------------------------- ### Custom logger with NestJS Logger Source: https://ilmar7786.github.io/marzban-sdk/docs/configuration/logging Example of using NestJS Logger as a custom logger for the SDK. ```javascript import { Logger as NestLogger } from '@nestjs/common' import { createMarzbanSDK } from 'marzban-sdk' const nestLogger = new NestLogger('MarzbanSDK') const sdk = await createMarzbanSDK({ // ... logger: { debug: (msg, ctx) => nestLogger.debug(msg, ctx), info: (msg, ctx) => nestLogger.log(msg, ctx), warn: (msg, ctx) => nestLogger.warn(msg, ctx), error: (msg, trace, ctx) => nestLogger.error(msg, trace, ctx), }, }) ``` -------------------------------- ### Run SDK tests: unit, watch, and coverage Source: https://ilmar7786.github.io/marzban-sdk/docs/resources/contributing Runs the SDK unit tests once, in watch mode, or with coverage. Coverage must stay at 100% for hand-written code. ```shell pnpm --filter marzban-sdk test # run once pnpm --filter marzban-sdk test:watch # watch mode while developing pnpm --filter marzban-sdk test:coverage # run with a coverage report ``` -------------------------------- ### getAdminUsage(username, params?) Source: https://ilmar7786.github.io/marzban-sdk/docs/modules/admins Get traffic usage attributed to a specific admin's users. ```APIDOC ## getAdminUsage(username, params?) ### Description Get traffic usage attributed to a specific admin's users. ### Method SDK Method ### Endpoint `sdk.admin.getAdminUsage(username, params?)` ### Parameters #### Path Parameters - **username** (string) - Required - Admin username #### Query Parameters - **start** (string) - Optional - Start date in ISO format - **end** (string) - Optional - End date in ISO format ### Returns `number` — total bytes used ### Example ```typescript const usage = await sdk.admin.getAdminUsage('operator', { start: '2024-01-01T00:00:00', end: '2024-01-31T23:59:59', }) ``` ``` -------------------------------- ### Create SDK with pre-existing token and deferred authentication Source: https://ilmar7786.github.io/marzban-sdk/docs/resources/faq Use this to provide a pre-existing token while preventing the SDK from overwriting it. Set authenticateOnInit to false so the token is used until it expires, then the SDK falls back to username/password for renewal. ```javascript const sdk = await createMarzbanSDK({ baseUrl: 'https://panel.example.com', username: 'admin', password: 'secret', token: existingToken, authenticateOnInit: false, }) ``` -------------------------------- ### addDays usage Source: https://ilmar7786.github.io/marzban-sdk/docs/utilities/datetime Shorthand for adding days to a date. The example converts the result to a Unix timestamp for the API. ```javascript const expiry = addDays(new Date(), 30) // Convert to Unix timestamp for the API const unixExpiry = Math.floor(expiry.getTime() / 1000) ``` -------------------------------- ### Get current admin profile Source: https://ilmar7786.github.io/marzban-sdk/docs/modules/admins Retrieves the profile of the currently authenticated admin. Returns an `Admin` object. ```typescript const me = await sdk.admin.getCurrentAdmin() console.log(me.username) console.log(me.is_sudo) // true for superadmin console.log(me.telegram_id) ``` -------------------------------- ### Restart core with sdk.core.restartCore() Source: https://ilmar7786.github.io/marzban-sdk/docs/modules/core Restarts the Xray core without changing its configuration. ```typescript await sdk.core.restartCore() ```