MarzbanSDK
Authentication

Manual Auth & Tokens

Disable auto-auth, call authorize() manually, or supply an existing JWT token.

Sometimes you need to control exactly when authentication happens — for example in test environments, serverless cold-starts, or when you already have a valid token from another source.

Disable auto-auth

Set authenticateOnInit: false to skip the login call during SDK construction:

import { createMarzbanSDK } from 'marzban-sdk'

const sdk = await createMarzbanSDK({
  baseUrl: 'https://vpn.example.com',
  username: 'admin',
  password: 'secret',
  authenticateOnInit: false,
})

// SDK is ready but NOT authenticated yet.
// API calls will fail until you authorize().

Call authorize() manually

await sdk.authorize()

// Now safe to make API calls
const users = await sdk.user.getUsers()

authorize() is idempotent with respect to concurrency — if a login is already in progress, it returns the same Promise instead of issuing a second request.

Supply an existing token

If you already have a JWT (from a previous session, a shared auth service, etc.), pass it via token:

const sdk = await createMarzbanSDK({
  baseUrl: 'https://vpn.example.com',
  username: 'admin',
  password: 'secret',        // still required for automatic re-auth on token expiry
  token: 'eyJhbGciOi...',
  authenticateOnInit: false,
})

The SDK will use the provided token immediately. If the token expires and a 401 is received, it falls back to username + password to get a fresh one.

Read the current token

const token = await sdk.getAuthToken()

This method waits for any in-flight authentication before returning, making it safe to call from multiple places concurrently.

Patterns

Lazy authentication (serverless)

// Module-level singleton — not authenticated yet
const sdk = await createMarzbanSDK({
  baseUrl: process.env.MARZBAN_URL!,
  username: process.env.MARZBAN_USER!,
  password: process.env.MARZBAN_PASS!,
  authenticateOnInit: false,
})

export async function handler() {
  // First request triggers auth; subsequent requests reuse the token.
  return sdk.user.getUsers()
}

Testing with a pre-set token

const sdk = await createMarzbanSDK({
  baseUrl: 'http://localhost:7777',
  username: 'test',
  password: 'test',
  token: 'test-jwt-token',
  authenticateOnInit: false,
})

Re-authenticate explicitly

// Force a fresh token (e.g. after a password change)
await sdk.authorize()
const freshToken = await sdk.getAuthToken()

Error handling

import { isAuthError, isAuthTokenError } from 'marzban-sdk'

try {
  await sdk.authorize()
} catch (err) {
  if (isAuthTokenError(err)) {
    // Server returned 200 but no access_token in the body
    console.error('Token retrieval failed:', err.code) // "AUTH_TOKEN_FAILED"
  } else if (isAuthError(err)) {
    // Login request failed (wrong credentials, network error, etc.)
    console.error('Auth failed:', err.message)
  }
}

On this page