Repository files navigation

@wyre-ai/node-unitrends

Comprehensive, fully-typed Node.js / TypeScript client library for the Unitrends Backup REST API.

License: Apache-2.0

Features

  • Full coverage of the documented endpoints: appliances, assets, jobs (backups + history), recovery points, restores, replication queue, alerts, reports
  • Session-token (POST /api/login) auth with single-flight re-auth on 401
  • Self-signed TLS support (verifyTls: false) for on-prem appliances
  • Page-based pagination via list() + async iterator listAll()
  • Defensive client-side rate limiting tuned for per-appliance limits, with 503 = "appliance overloaded" backoff
  • Typed error hierarchy
  • ESM + CommonJS dual exports, full .d.ts types
  • Zero any in the public API

Install

npm install @wyre-ai/node-unitrends

The package is published to GitHub Packages under the @wyre-ai scope. Add this to a project-local .npmrc:

@wyre-ai:registry=https://npm.pkg.github.com

Quick start

import{UnitrendsClient}from'@wyre-ai/node-unitrends';constclient=newUnitrendsClient({baseUrl: 'https://backup.example.com/api',username: process.env.UNITRENDS_USER!,password: process.env.UNITRENDS_PASS!,});// One page at a timeconstpage=awaitclient.assets.list({limit: 100});console.log(page.total);// Stream every asset, fetching pages on demandforawait(constassetofclient.assets.listAll({limit: 200})){console.log(asset.id,asset.hostname);}

Configuration

newUnitrendsClient({baseUrl: 'https://backup.example.com/api',// requiredusername: 'admin',password: '...',// Talking to an aggregating MSP Console rather than a single appliance.// When true, asset operations REQUIRE an applianceId.mspConsole: false,// On-prem appliances often ship with self-signed certs.// Disable verification ONLY on trusted internal networks.verifyTls: true,// Optional — tune client-side rate limiting (defaults shown).rateLimit: {enabled: true,maxRequests: 60,windowMs: 60_000,throttleThreshold: 0.8,retryAfterMs: 5_000,maxRetries: 3,applianceOverloadBackoffMs: 30_000,},});

Authentication

The SDK calls POST /api/login with { username, password }, captures the returned token + expires, and sends Authorization: Bearer <token> on all subsequent requests. Tokens have a 60-minute idle (sliding) timeout.

If a request fails with 401 mid-session, the SDK invalidates the cached token, re-authenticates once under a single-flight lock (concurrent callers share one in-flight login), and retries the request.

Self-signed certificates

Many on-prem Unitrends Backup appliances use a self-signed TLS certificate. Set verifyTls: false to disable certificate validation:

constclient=newUnitrendsClient({baseUrl: 'https://backup.internal/api',username: '...',password: '...',verifyTls: false,});

Security: disabling certificate verification removes the only protection against man-in-the-middle attacks. Only do this on trusted internal networks. Prefer installing the appliance's CA into your system trust store.

Pagination

ParamDefaultMax
limit50500
offset0

Responses include total. Use listAll() to iterate all pages automatically.

API surface

client.appliances.list(params)// MSP Console onlyclient.appliances.listAll(params)// MSP Console onlyclient.assets.list({applianceId?,limit?,offset? })client.assets.listAll({applianceId?,limit?,offset? })client.assets.get(assetId,applianceId?)client.jobs.listBackups({applianceId?, ... })client.jobs.listAllBackups({applianceId?, ... })client.jobs.listHistory({applianceId?, ... })client.jobs.listAllHistory({applianceId?, ... })client.recoveryPoints.list({assetId?,applianceId?, ... })client.recoveryPoints.listAll({assetId?,applianceId?, ... })client.restores.queue({ recoveryPointId,applianceId?, ... })// POST /api/restoresclient.restores.get(restoreId)client.replication.listQueue(params)client.replication.listAllQueue(params)client.alerts.list(params)client.alerts.listAll(params)client.reports.successRate({applianceId?,startTime?,endTime? })

Error handling

import{UnitrendsError,UnitrendsAuthenticationError,UnitrendsForbiddenError,UnitrendsNotFoundError,UnitrendsRateLimitError,UnitrendsServerError,}from'@wyre-ai/node-unitrends';try{awaitclient.assets.get(123);}catch(err){if(errinstanceofUnitrendsRateLimitError){awaitnewPromise((r)=>setTimeout(r,err.retryAfter));}elseif(errinstanceofUnitrendsServerError&&err.statusCode===503){// Appliance is overloaded — already auto-retried with 30s backoff.}else{throwerr;}}

Gotchas

  • Asset IDs are appliance-scoped. Asset 123 on appliance A is NOT the same record as asset 123 on appliance B. The Asset type carries applianceId for this reason. When mspConsole: true the SDK enforces that asset operations include applianceId.
  • MSP Console exposes a subset of endpoints. Asset-level operations like restores.queue(...) typically must target the owning appliance directly.
  • Job status ≠ "data is recoverable". A job can have status: 'success' while its resulting recovery point has verifyState: 'failed'. The Job type exposes both fields.
  • Self-signed certs. See above — verifyTls: false disables MITM protection; use only on trusted networks.

Development

npm install
npm test
npm run typecheck
npm run lint
npm run build

License

Apache-2.0

About

Comprehensive Node.js/TypeScript client library for the Unitrends Backup REST API

Topics

Resources

Code of conduct

Contributing

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Add copy buttons to all
 blocks\n(function() {\n function addCopyButtons() {\n document.querySelectorAll('pre code').forEach(function(codeBlock) {\n if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;\n codeBlock.parentElement.setAttribute('data-copy-added', 'true');\n \n var btn = document.createElement('button');\n btn.textContent = 'Copy';\n btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';\n btn.onmouseover = function() { this.style.opacity = '1'; };\n btn.onmouseout = function() { this.style.opacity = '0.7'; };\n btn.onclick = function() {\n navigator.clipboard.writeText(codeBlock.textContent).then(function() {\n btn.textContent = 'Copied!';\n setTimeout(function() { btn.textContent = 'Copy'; }, 1500);\n });\n };\n codeBlock.parentElement.style.position = 'relative';\n codeBlock.parentElement.appendChild(btn);\n });\n }\n \n addCopyButtons();\n \n // Re-run on dynamic content\n var observer = new MutationObserver(addCopyButtons);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Add Copy Buttons to Code Blocks");
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
Skip to content

Repository files navigation

@wyre-ai/node-unitrends

Comprehensive, fully-typed Node.js / TypeScript client library for the Unitrends Backup REST API.

License: Apache-2.0

Features

  • Full coverage of the documented endpoints: appliances, assets, jobs (backups + history), recovery points, restores, replication queue, alerts, reports
  • Session-token (POST /api/login) auth with single-flight re-auth on 401
  • Self-signed TLS support (verifyTls: false) for on-prem appliances
  • Page-based pagination via list() + async iterator listAll()
  • Defensive client-side rate limiting tuned for per-appliance limits, with 503 = "appliance overloaded" backoff
  • Typed error hierarchy
  • ESM + CommonJS dual exports, full .d.ts types
  • Zero any in the public API

Install

npm install @wyre-ai/node-unitrends

The package is published to GitHub Packages under the @wyre-ai scope. Add this to a project-local .npmrc:

@wyre-ai:registry=https://npm.pkg.github.com

Quick start

import{UnitrendsClient}from'@wyre-ai/node-unitrends';constclient=newUnitrendsClient({baseUrl: 'https://backup.example.com/api',username: process.env.UNITRENDS_USER!,password: process.env.UNITRENDS_PASS!,});// One page at a timeconstpage=awaitclient.assets.list({limit: 100});console.log(page.total);// Stream every asset, fetching pages on demandforawait(constassetofclient.assets.listAll({limit: 200})){console.log(asset.id,asset.hostname);}

Configuration

newUnitrendsClient({baseUrl: 'https://backup.example.com/api',// requiredusername: 'admin',password: '...',// Talking to an aggregating MSP Console rather than a single appliance.// When true, asset operations REQUIRE an applianceId.mspConsole: false,// On-prem appliances often ship with self-signed certs.// Disable verification ONLY on trusted internal networks.verifyTls: true,// Optional — tune client-side rate limiting (defaults shown).rateLimit: {enabled: true,maxRequests: 60,windowMs: 60_000,throttleThreshold: 0.8,retryAfterMs: 5_000,maxRetries: 3,applianceOverloadBackoffMs: 30_000,},});

Authentication

The SDK calls POST /api/login with { username, password }, captures the returned token + expires, and sends Authorization: Bearer <token> on all subsequent requests. Tokens have a 60-minute idle (sliding) timeout.

If a request fails with 401 mid-session, the SDK invalidates the cached token, re-authenticates once under a single-flight lock (concurrent callers share one in-flight login), and retries the request.

Self-signed certificates

Many on-prem Unitrends Backup appliances use a self-signed TLS certificate. Set verifyTls: false to disable certificate validation:

constclient=newUnitrendsClient({baseUrl: 'https://backup.internal/api',username: '...',password: '...',verifyTls: false,});

Security: disabling certificate verification removes the only protection against man-in-the-middle attacks. Only do this on trusted internal networks. Prefer installing the appliance's CA into your system trust store.

Pagination

ParamDefaultMax
limit50500
offset0

Responses include total. Use listAll() to iterate all pages automatically.

API surface

client.appliances.list(params)// MSP Console onlyclient.appliances.listAll(params)// MSP Console onlyclient.assets.list({applianceId?,limit?,offset? })client.assets.listAll({applianceId?,limit?,offset? })client.assets.get(assetId,applianceId?)client.jobs.listBackups({applianceId?, ... })client.jobs.listAllBackups({applianceId?, ... })client.jobs.listHistory({applianceId?, ... })client.jobs.listAllHistory({applianceId?, ... })client.recoveryPoints.list({assetId?,applianceId?, ... })client.recoveryPoints.listAll({assetId?,applianceId?, ... })client.restores.queue({ recoveryPointId,applianceId?, ... })// POST /api/restoresclient.restores.get(restoreId)client.replication.listQueue(params)client.replication.listAllQueue(params)client.alerts.list(params)client.alerts.listAll(params)client.reports.successRate({applianceId?,startTime?,endTime? })

Error handling

import{UnitrendsError,UnitrendsAuthenticationError,UnitrendsForbiddenError,UnitrendsNotFoundError,UnitrendsRateLimitError,UnitrendsServerError,}from'@wyre-ai/node-unitrends';try{awaitclient.assets.get(123);}catch(err){if(errinstanceofUnitrendsRateLimitError){awaitnewPromise((r)=>setTimeout(r,err.retryAfter));}elseif(errinstanceofUnitrendsServerError&&err.statusCode===503){// Appliance is overloaded — already auto-retried with 30s backoff.}else{throwerr;}}

Gotchas

  • Asset IDs are appliance-scoped. Asset 123 on appliance A is NOT the same record as asset 123 on appliance B. The Asset type carries applianceId for this reason. When mspConsole: true the SDK enforces that asset operations include applianceId.
  • MSP Console exposes a subset of endpoints. Asset-level operations like restores.queue(...) typically must target the owning appliance directly.
  • Job status ≠ "data is recoverable". A job can have status: 'success' while its resulting recovery point has verifyState: 'failed'. The Job type exposes both fields.
  • Self-signed certs. See above — verifyTls: false disables MITM protection; use only on trusted networks.

Development

npm install
npm test
npm run typecheck
npm run lint
npm run build

License

Apache-2.0

About

Comprehensive Node.js/TypeScript client library for the Unitrends Backup REST API

Topics

Resources

Code of conduct

Contributing

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Force GitHub README to respect dark mode\n(function() {\n var style = document.createElement('style');\n style.textContent = '\n .markdown-body {\n color-scheme: dark light;\n }\n .markdown-body pre { background: #161b22 !important; }\n .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; }\n .markdown-body table th, .markdown-body table td { border-color: #30363d !important; }\n .markdown-body img { background: #0d1117; }\n .markdown-body blockquote { border-left-color: #8b949e; }\n .markdown-body hr { border-color: #30363d; }\n ';\n document.head.appendChild(style);\n})();", "GitHub Dark Mode README Fix"); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Repository files navigation

@wyre-ai/node-unitrends

Comprehensive, fully-typed Node.js / TypeScript client library for the Unitrends Backup REST API.

License: Apache-2.0

Features

  • Full coverage of the documented endpoints: appliances, assets, jobs (backups + history), recovery points, restores, replication queue, alerts, reports
  • Session-token (POST /api/login) auth with single-flight re-auth on 401
  • Self-signed TLS support (verifyTls: false) for on-prem appliances
  • Page-based pagination via list() + async iterator listAll()
  • Defensive client-side rate limiting tuned for per-appliance limits, with 503 = "appliance overloaded" backoff
  • Typed error hierarchy
  • ESM + CommonJS dual exports, full .d.ts types
  • Zero any in the public API

Install

npm install @wyre-ai/node-unitrends

The package is published to GitHub Packages under the @wyre-ai scope. Add this to a project-local .npmrc:

@wyre-ai:registry=https://npm.pkg.github.com

Quick start

import{UnitrendsClient}from'@wyre-ai/node-unitrends';constclient=newUnitrendsClient({baseUrl: 'https://backup.example.com/api',username: process.env.UNITRENDS_USER!,password: process.env.UNITRENDS_PASS!,});// One page at a timeconstpage=awaitclient.assets.list({limit: 100});console.log(page.total);// Stream every asset, fetching pages on demandforawait(constassetofclient.assets.listAll({limit: 200})){console.log(asset.id,asset.hostname);}

Configuration

newUnitrendsClient({baseUrl: 'https://backup.example.com/api',// requiredusername: 'admin',password: '...',// Talking to an aggregating MSP Console rather than a single appliance.// When true, asset operations REQUIRE an applianceId.mspConsole: false,// On-prem appliances often ship with self-signed certs.// Disable verification ONLY on trusted internal networks.verifyTls: true,// Optional — tune client-side rate limiting (defaults shown).rateLimit: {enabled: true,maxRequests: 60,windowMs: 60_000,throttleThreshold: 0.8,retryAfterMs: 5_000,maxRetries: 3,applianceOverloadBackoffMs: 30_000,},});

Authentication

The SDK calls POST /api/login with { username, password }, captures the returned token + expires, and sends Authorization: Bearer <token> on all subsequent requests. Tokens have a 60-minute idle (sliding) timeout.

If a request fails with 401 mid-session, the SDK invalidates the cached token, re-authenticates once under a single-flight lock (concurrent callers share one in-flight login), and retries the request.

Self-signed certificates

Many on-prem Unitrends Backup appliances use a self-signed TLS certificate. Set verifyTls: false to disable certificate validation:

constclient=newUnitrendsClient({baseUrl: 'https://backup.internal/api',username: '...',password: '...',verifyTls: false,});

Security: disabling certificate verification removes the only protection against man-in-the-middle attacks. Only do this on trusted internal networks. Prefer installing the appliance's CA into your system trust store.

Pagination

ParamDefaultMax
limit50500
offset0

Responses include total. Use listAll() to iterate all pages automatically.

API surface

client.appliances.list(params)// MSP Console onlyclient.appliances.listAll(params)// MSP Console onlyclient.assets.list({applianceId?,limit?,offset? })client.assets.listAll({applianceId?,limit?,offset? })client.assets.get(assetId,applianceId?)client.jobs.listBackups({applianceId?, ... })client.jobs.listAllBackups({applianceId?, ... })client.jobs.listHistory({applianceId?, ... })client.jobs.listAllHistory({applianceId?, ... })client.recoveryPoints.list({assetId?,applianceId?, ... })client.recoveryPoints.listAll({assetId?,applianceId?, ... })client.restores.queue({ recoveryPointId,applianceId?, ... })// POST /api/restoresclient.restores.get(restoreId)client.replication.listQueue(params)client.replication.listAllQueue(params)client.alerts.list(params)client.alerts.listAll(params)client.reports.successRate({applianceId?,startTime?,endTime? })

Error handling

import{UnitrendsError,UnitrendsAuthenticationError,UnitrendsForbiddenError,UnitrendsNotFoundError,UnitrendsRateLimitError,UnitrendsServerError,}from'@wyre-ai/node-unitrends';try{awaitclient.assets.get(123);}catch(err){if(errinstanceofUnitrendsRateLimitError){awaitnewPromise((r)=>setTimeout(r,err.retryAfter));}elseif(errinstanceofUnitrendsServerError&&err.statusCode===503){// Appliance is overloaded — already auto-retried with 30s backoff.}else{throwerr;}}

Gotchas

  • Asset IDs are appliance-scoped. Asset 123 on appliance A is NOT the same record as asset 123 on appliance B. The Asset type carries applianceId for this reason. When mspConsole: true the SDK enforces that asset operations include applianceId.
  • MSP Console exposes a subset of endpoints. Asset-level operations like restores.queue(...) typically must target the owning appliance directly.
  • Job status ≠ "data is recoverable". A job can have status: 'success' while its resulting recovery point has verifyState: 'failed'. The Job type exposes both fields.
  • Self-signed certs. See above — verifyTls: false disables MITM protection; use only on trusted networks.

Development

npm install
npm test
npm run typecheck
npm run lint
npm run build

License

Apache-2.0

About

Comprehensive Node.js/TypeScript client library for the Unitrends Backup REST API

Topics

Resources

Code of conduct

Contributing

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Highlight search terms from Google/DuckDuckGo/Bing referrer\n(function() {\n var ref = document.referrer;\n var terms = [];\n \n if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) {\n var url = new URL(ref);\n var q = url.searchParams.get('q') || url.searchParams.get('p');\n if (q) {\n terms = q.split(/\\s+/).filter(function(t) { return t.length > 2; });\n }\n }\n \n if (terms.length === 0) return;\n \n var style = document.createElement('style');\n style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }';\n document.head.appendChild(style);\n \n function highlight(node) {\n if (node.nodeType === 3) { // text node\n var text = node.textContent;\n var found = false;\n terms.forEach(function(term) {\n var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\') + ')', 'gi');\n if (regex.test(text)) {\n found = true;\n var frag = document.createDocumentFragment();\n var parts = text.split(regex);\n parts.forEach(function(part, i) {\n if (i % 2 === 0) {\n frag.appendChild(document.createTextNode(part));\n } else {\n var span = document.createElement('span');\n span.className = 'userscript-highlight';\n span.textContent = part;\n frag.appendChild(span);\n }\n });\n node.parentNode.replaceChild(frag, node);\n }\n });\n } else if (node.nodeType === 1 && node.childNodes) { // element\n var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT'];\n if (!skipTags.includes(node.tagName)) {\n Array.from(node.childNodes).forEach(highlight);\n }\n }\n }\n \n highlight(document.body);\n \n // Re-highlight on dynamic content\n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1 || node.nodeType === 3) highlight(node);\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Highlight Search Terms"); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Repository files navigation

@wyre-ai/node-unitrends

Comprehensive, fully-typed Node.js / TypeScript client library for the Unitrends Backup REST API.

License: Apache-2.0

Features

  • Full coverage of the documented endpoints: appliances, assets, jobs (backups + history), recovery points, restores, replication queue, alerts, reports
  • Session-token (POST /api/login) auth with single-flight re-auth on 401
  • Self-signed TLS support (verifyTls: false) for on-prem appliances
  • Page-based pagination via list() + async iterator listAll()
  • Defensive client-side rate limiting tuned for per-appliance limits, with 503 = "appliance overloaded" backoff
  • Typed error hierarchy
  • ESM + CommonJS dual exports, full .d.ts types
  • Zero any in the public API

Install

npm install @wyre-ai/node-unitrends

The package is published to GitHub Packages under the @wyre-ai scope. Add this to a project-local .npmrc:

@wyre-ai:registry=https://npm.pkg.github.com

Quick start

import{UnitrendsClient}from'@wyre-ai/node-unitrends';constclient=newUnitrendsClient({baseUrl: 'https://backup.example.com/api',username: process.env.UNITRENDS_USER!,password: process.env.UNITRENDS_PASS!,});// One page at a timeconstpage=awaitclient.assets.list({limit: 100});console.log(page.total);// Stream every asset, fetching pages on demandforawait(constassetofclient.assets.listAll({limit: 200})){console.log(asset.id,asset.hostname);}

Configuration

newUnitrendsClient({baseUrl: 'https://backup.example.com/api',// requiredusername: 'admin',password: '...',// Talking to an aggregating MSP Console rather than a single appliance.// When true, asset operations REQUIRE an applianceId.mspConsole: false,// On-prem appliances often ship with self-signed certs.// Disable verification ONLY on trusted internal networks.verifyTls: true,// Optional — tune client-side rate limiting (defaults shown).rateLimit: {enabled: true,maxRequests: 60,windowMs: 60_000,throttleThreshold: 0.8,retryAfterMs: 5_000,maxRetries: 3,applianceOverloadBackoffMs: 30_000,},});

Authentication

The SDK calls POST /api/login with { username, password }, captures the returned token + expires, and sends Authorization: Bearer <token> on all subsequent requests. Tokens have a 60-minute idle (sliding) timeout.

If a request fails with 401 mid-session, the SDK invalidates the cached token, re-authenticates once under a single-flight lock (concurrent callers share one in-flight login), and retries the request.

Self-signed certificates

Many on-prem Unitrends Backup appliances use a self-signed TLS certificate. Set verifyTls: false to disable certificate validation:

constclient=newUnitrendsClient({baseUrl: 'https://backup.internal/api',username: '...',password: '...',verifyTls: false,});

Security: disabling certificate verification removes the only protection against man-in-the-middle attacks. Only do this on trusted internal networks. Prefer installing the appliance's CA into your system trust store.

Pagination

ParamDefaultMax
limit50500
offset0

Responses include total. Use listAll() to iterate all pages automatically.

API surface

client.appliances.list(params)// MSP Console onlyclient.appliances.listAll(params)// MSP Console onlyclient.assets.list({applianceId?,limit?,offset? })client.assets.listAll({applianceId?,limit?,offset? })client.assets.get(assetId,applianceId?)client.jobs.listBackups({applianceId?, ... })client.jobs.listAllBackups({applianceId?, ... })client.jobs.listHistory({applianceId?, ... })client.jobs.listAllHistory({applianceId?, ... })client.recoveryPoints.list({assetId?,applianceId?, ... })client.recoveryPoints.listAll({assetId?,applianceId?, ... })client.restores.queue({ recoveryPointId,applianceId?, ... })// POST /api/restoresclient.restores.get(restoreId)client.replication.listQueue(params)client.replication.listAllQueue(params)client.alerts.list(params)client.alerts.listAll(params)client.reports.successRate({applianceId?,startTime?,endTime? })

Error handling

import{UnitrendsError,UnitrendsAuthenticationError,UnitrendsForbiddenError,UnitrendsNotFoundError,UnitrendsRateLimitError,UnitrendsServerError,}from'@wyre-ai/node-unitrends';try{awaitclient.assets.get(123);}catch(err){if(errinstanceofUnitrendsRateLimitError){awaitnewPromise((r)=>setTimeout(r,err.retryAfter));}elseif(errinstanceofUnitrendsServerError&&err.statusCode===503){// Appliance is overloaded — already auto-retried with 30s backoff.}else{throwerr;}}

Gotchas

  • Asset IDs are appliance-scoped. Asset 123 on appliance A is NOT the same record as asset 123 on appliance B. The Asset type carries applianceId for this reason. When mspConsole: true the SDK enforces that asset operations include applianceId.
  • MSP Console exposes a subset of endpoints. Asset-level operations like restores.queue(...) typically must target the owning appliance directly.
  • Job status ≠ "data is recoverable". A job can have status: 'success' while its resulting recovery point has verifyState: 'failed'. The Job type exposes both fields.
  • Self-signed certs. See above — verifyTls: false disables MITM protection; use only on trusted networks.

Development

npm install
npm test
npm run typecheck
npm run lint
npm run build

License

Apache-2.0

About

Comprehensive Node.js/TypeScript client library for the Unitrends Backup REST API

Topics

Resources

Code of conduct

Contributing

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Strip utm_, fbclid, gclid, etc. from all links on page\n(function() {\n var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content',\n 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid',\n 'ref', 'ref_src', 'source', 'medium', 'campaign'];\n \n function cleanUrl(url) {\n try {\n var u = new URL(url, window.location.origin);\n var changed = false;\n trackingParams.forEach(function(p) {\n if (u.searchParams.has(p)) {\n u.searchParams.delete(p);\n changed = true;\n }\n });\n return changed ? u.toString() : url;\n } catch (e) {\n return url;\n }\n }\n \n function cleanLinks() {\n document.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n \n cleanLinks();\n \n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1) {\n if (node.tagName === 'A') cleanLinks();\n node.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Remove Tracking Parameters from Links"); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + '
Skip to content

Repository files navigation

@wyre-ai/node-unitrends

Comprehensive, fully-typed Node.js / TypeScript client library for the Unitrends Backup REST API.

License: Apache-2.0

Features

  • Full coverage of the documented endpoints: appliances, assets, jobs (backups + history), recovery points, restores, replication queue, alerts, reports
  • Session-token (POST /api/login) auth with single-flight re-auth on 401
  • Self-signed TLS support (verifyTls: false) for on-prem appliances
  • Page-based pagination via list() + async iterator listAll()
  • Defensive client-side rate limiting tuned for per-appliance limits, with 503 = "appliance overloaded" backoff
  • Typed error hierarchy
  • ESM + CommonJS dual exports, full .d.ts types
  • Zero any in the public API

Install

npm install @wyre-ai/node-unitrends

The package is published to GitHub Packages under the @wyre-ai scope. Add this to a project-local .npmrc:

@wyre-ai:registry=https://npm.pkg.github.com

Quick start

import{UnitrendsClient}from'@wyre-ai/node-unitrends';constclient=newUnitrendsClient({baseUrl: 'https://backup.example.com/api',username: process.env.UNITRENDS_USER!,password: process.env.UNITRENDS_PASS!,});// One page at a timeconstpage=awaitclient.assets.list({limit: 100});console.log(page.total);// Stream every asset, fetching pages on demandforawait(constassetofclient.assets.listAll({limit: 200})){console.log(asset.id,asset.hostname);}

Configuration

newUnitrendsClient({baseUrl: 'https://backup.example.com/api',// requiredusername: 'admin',password: '...',// Talking to an aggregating MSP Console rather than a single appliance.// When true, asset operations REQUIRE an applianceId.mspConsole: false,// On-prem appliances often ship with self-signed certs.// Disable verification ONLY on trusted internal networks.verifyTls: true,// Optional — tune client-side rate limiting (defaults shown).rateLimit: {enabled: true,maxRequests: 60,windowMs: 60_000,throttleThreshold: 0.8,retryAfterMs: 5_000,maxRetries: 3,applianceOverloadBackoffMs: 30_000,},});

Authentication

The SDK calls POST /api/login with { username, password }, captures the returned token + expires, and sends Authorization: Bearer <token> on all subsequent requests. Tokens have a 60-minute idle (sliding) timeout.

If a request fails with 401 mid-session, the SDK invalidates the cached token, re-authenticates once under a single-flight lock (concurrent callers share one in-flight login), and retries the request.

Self-signed certificates

Many on-prem Unitrends Backup appliances use a self-signed TLS certificate. Set verifyTls: false to disable certificate validation:

constclient=newUnitrendsClient({baseUrl: 'https://backup.internal/api',username: '...',password: '...',verifyTls: false,});

Security: disabling certificate verification removes the only protection against man-in-the-middle attacks. Only do this on trusted internal networks. Prefer installing the appliance's CA into your system trust store.

Pagination

ParamDefaultMax
limit50500
offset0

Responses include total. Use listAll() to iterate all pages automatically.

API surface

client.appliances.list(params)// MSP Console onlyclient.appliances.listAll(params)// MSP Console onlyclient.assets.list({applianceId?,limit?,offset? })client.assets.listAll({applianceId?,limit?,offset? })client.assets.get(assetId,applianceId?)client.jobs.listBackups({applianceId?, ... })client.jobs.listAllBackups({applianceId?, ... })client.jobs.listHistory({applianceId?, ... })client.jobs.listAllHistory({applianceId?, ... })client.recoveryPoints.list({assetId?,applianceId?, ... })client.recoveryPoints.listAll({assetId?,applianceId?, ... })client.restores.queue({ recoveryPointId,applianceId?, ... })// POST /api/restoresclient.restores.get(restoreId)client.replication.listQueue(params)client.replication.listAllQueue(params)client.alerts.list(params)client.alerts.listAll(params)client.reports.successRate({applianceId?,startTime?,endTime? })

Error handling

import{UnitrendsError,UnitrendsAuthenticationError,UnitrendsForbiddenError,UnitrendsNotFoundError,UnitrendsRateLimitError,UnitrendsServerError,}from'@wyre-ai/node-unitrends';try{awaitclient.assets.get(123);}catch(err){if(errinstanceofUnitrendsRateLimitError){awaitnewPromise((r)=>setTimeout(r,err.retryAfter));}elseif(errinstanceofUnitrendsServerError&&err.statusCode===503){// Appliance is overloaded — already auto-retried with 30s backoff.}else{throwerr;}}

Gotchas

  • Asset IDs are appliance-scoped. Asset 123 on appliance A is NOT the same record as asset 123 on appliance B. The Asset type carries applianceId for this reason. When mspConsole: true the SDK enforces that asset operations include applianceId.
  • MSP Console exposes a subset of endpoints. Asset-level operations like restores.queue(...) typically must target the owning appliance directly.
  • Job status ≠ "data is recoverable". A job can have status: 'success' while its resulting recovery point has verifyState: 'failed'. The Job type exposes both fields.
  • Self-signed certs. See above — verifyTls: false disables MITM protection; use only on trusted networks.

Development

npm install
npm test
npm run typecheck
npm run lint
npm run build

License

Apache-2.0

About

Comprehensive Node.js/TypeScript client library for the Unitrends Backup REST API

Topics

Resources

Code of conduct

Contributing

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Auto-enable theater mode on YouTube\n(function() {\n function tryTheater() {\n var btn = document.querySelector('button[aria-label=\"Theater mode\"], ytd-player #player button[title=\"Theater mode\"]');\n if (btn && !btn.classList.contains('activated')) {\n btn.click();\n }\n }\n \n // Try immediately\n tryTheater();\n \n // Try after navigation (SPA)\n var lastUrl = location.href;\n setInterval(function() {\n if (location.href !== lastUrl) {\n lastUrl = location.href;\n setTimeout(tryTheater, 500);\n }\n }, 1000);\n \n // Also try on player load\n var observer = new MutationObserver(tryTheater);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "YouTube Theater Mode Default"); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Repository files navigation

@wyre-ai/node-unitrends

Comprehensive, fully-typed Node.js / TypeScript client library for the Unitrends Backup REST API.

License: Apache-2.0

Features

  • Full coverage of the documented endpoints: appliances, assets, jobs (backups + history), recovery points, restores, replication queue, alerts, reports
  • Session-token (POST /api/login) auth with single-flight re-auth on 401
  • Self-signed TLS support (verifyTls: false) for on-prem appliances
  • Page-based pagination via list() + async iterator listAll()
  • Defensive client-side rate limiting tuned for per-appliance limits, with 503 = "appliance overloaded" backoff
  • Typed error hierarchy
  • ESM + CommonJS dual exports, full .d.ts types
  • Zero any in the public API

Install

npm install @wyre-ai/node-unitrends

The package is published to GitHub Packages under the @wyre-ai scope. Add this to a project-local .npmrc:

@wyre-ai:registry=https://npm.pkg.github.com

Quick start

import{UnitrendsClient}from'@wyre-ai/node-unitrends';constclient=newUnitrendsClient({baseUrl: 'https://backup.example.com/api',username: process.env.UNITRENDS_USER!,password: process.env.UNITRENDS_PASS!,});// One page at a timeconstpage=awaitclient.assets.list({limit: 100});console.log(page.total);// Stream every asset, fetching pages on demandforawait(constassetofclient.assets.listAll({limit: 200})){console.log(asset.id,asset.hostname);}

Configuration

newUnitrendsClient({baseUrl: 'https://backup.example.com/api',// requiredusername: 'admin',password: '...',// Talking to an aggregating MSP Console rather than a single appliance.// When true, asset operations REQUIRE an applianceId.mspConsole: false,// On-prem appliances often ship with self-signed certs.// Disable verification ONLY on trusted internal networks.verifyTls: true,// Optional — tune client-side rate limiting (defaults shown).rateLimit: {enabled: true,maxRequests: 60,windowMs: 60_000,throttleThreshold: 0.8,retryAfterMs: 5_000,maxRetries: 3,applianceOverloadBackoffMs: 30_000,},});

Authentication

The SDK calls POST /api/login with { username, password }, captures the returned token + expires, and sends Authorization: Bearer <token> on all subsequent requests. Tokens have a 60-minute idle (sliding) timeout.

If a request fails with 401 mid-session, the SDK invalidates the cached token, re-authenticates once under a single-flight lock (concurrent callers share one in-flight login), and retries the request.

Self-signed certificates

Many on-prem Unitrends Backup appliances use a self-signed TLS certificate. Set verifyTls: false to disable certificate validation:

constclient=newUnitrendsClient({baseUrl: 'https://backup.internal/api',username: '...',password: '...',verifyTls: false,});

Security: disabling certificate verification removes the only protection against man-in-the-middle attacks. Only do this on trusted internal networks. Prefer installing the appliance's CA into your system trust store.

Pagination

ParamDefaultMax
limit50500
offset0

Responses include total. Use listAll() to iterate all pages automatically.

API surface

client.appliances.list(params)// MSP Console onlyclient.appliances.listAll(params)// MSP Console onlyclient.assets.list({applianceId?,limit?,offset? })client.assets.listAll({applianceId?,limit?,offset? })client.assets.get(assetId,applianceId?)client.jobs.listBackups({applianceId?, ... })client.jobs.listAllBackups({applianceId?, ... })client.jobs.listHistory({applianceId?, ... })client.jobs.listAllHistory({applianceId?, ... })client.recoveryPoints.list({assetId?,applianceId?, ... })client.recoveryPoints.listAll({assetId?,applianceId?, ... })client.restores.queue({ recoveryPointId,applianceId?, ... })// POST /api/restoresclient.restores.get(restoreId)client.replication.listQueue(params)client.replication.listAllQueue(params)client.alerts.list(params)client.alerts.listAll(params)client.reports.successRate({applianceId?,startTime?,endTime? })

Error handling

import{UnitrendsError,UnitrendsAuthenticationError,UnitrendsForbiddenError,UnitrendsNotFoundError,UnitrendsRateLimitError,UnitrendsServerError,}from'@wyre-ai/node-unitrends';try{awaitclient.assets.get(123);}catch(err){if(errinstanceofUnitrendsRateLimitError){awaitnewPromise((r)=>setTimeout(r,err.retryAfter));}elseif(errinstanceofUnitrendsServerError&&err.statusCode===503){// Appliance is overloaded — already auto-retried with 30s backoff.}else{throwerr;}}

Gotchas

  • Asset IDs are appliance-scoped. Asset 123 on appliance A is NOT the same record as asset 123 on appliance B. The Asset type carries applianceId for this reason. When mspConsole: true the SDK enforces that asset operations include applianceId.
  • MSP Console exposes a subset of endpoints. Asset-level operations like restores.queue(...) typically must target the owning appliance directly.
  • Job status ≠ "data is recoverable". A job can have status: 'success' while its resulting recovery point has verifyState: 'failed'. The Job type exposes both fields.
  • Self-signed certs. See above — verifyTls: false disables MITM protection; use only on trusted networks.

Development

npm install
npm test
npm run typecheck
npm run lint
npm run build

License

Apache-2.0

About

Comprehensive Node.js/TypeScript client library for the Unitrends Backup REST API

Topics

Resources

Code of conduct

Contributing

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Remove or un-stick sticky/fixed headers that block content\n(function() {\n function unstick() {\n document.querySelectorAll('header, nav, [role=\"banner\"], .header, .navbar, .sticky, .fixed-top, [style*=\"position: fixed\"], [style*=\"position:sticky\"]').forEach(function(el) {\n if (el.style.position === 'fixed' || el.style.position === 'sticky' || \n getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') {\n el.style.position = 'static';\n el.style.top = 'auto';\n el.style.zIndex = 'auto';\n }\n });\n }\n \n unstick();\n \n var observer = new MutationObserver(unstick);\n observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] });\n})();", "Kill Sticky Headers"); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Repository files navigation

@wyre-ai/node-unitrends

Comprehensive, fully-typed Node.js / TypeScript client library for the Unitrends Backup REST API.

License: Apache-2.0

Features

  • Full coverage of the documented endpoints: appliances, assets, jobs (backups + history), recovery points, restores, replication queue, alerts, reports
  • Session-token (POST /api/login) auth with single-flight re-auth on 401
  • Self-signed TLS support (verifyTls: false) for on-prem appliances
  • Page-based pagination via list() + async iterator listAll()
  • Defensive client-side rate limiting tuned for per-appliance limits, with 503 = "appliance overloaded" backoff
  • Typed error hierarchy
  • ESM + CommonJS dual exports, full .d.ts types
  • Zero any in the public API

Install

npm install @wyre-ai/node-unitrends

The package is published to GitHub Packages under the @wyre-ai scope. Add this to a project-local .npmrc:

@wyre-ai:registry=https://npm.pkg.github.com

Quick start

import{UnitrendsClient}from'@wyre-ai/node-unitrends';constclient=newUnitrendsClient({baseUrl: 'https://backup.example.com/api',username: process.env.UNITRENDS_USER!,password: process.env.UNITRENDS_PASS!,});// One page at a timeconstpage=awaitclient.assets.list({limit: 100});console.log(page.total);// Stream every asset, fetching pages on demandforawait(constassetofclient.assets.listAll({limit: 200})){console.log(asset.id,asset.hostname);}

Configuration

newUnitrendsClient({baseUrl: 'https://backup.example.com/api',// requiredusername: 'admin',password: '...',// Talking to an aggregating MSP Console rather than a single appliance.// When true, asset operations REQUIRE an applianceId.mspConsole: false,// On-prem appliances often ship with self-signed certs.// Disable verification ONLY on trusted internal networks.verifyTls: true,// Optional — tune client-side rate limiting (defaults shown).rateLimit: {enabled: true,maxRequests: 60,windowMs: 60_000,throttleThreshold: 0.8,retryAfterMs: 5_000,maxRetries: 3,applianceOverloadBackoffMs: 30_000,},});

Authentication

The SDK calls POST /api/login with { username, password }, captures the returned token + expires, and sends Authorization: Bearer <token> on all subsequent requests. Tokens have a 60-minute idle (sliding) timeout.

If a request fails with 401 mid-session, the SDK invalidates the cached token, re-authenticates once under a single-flight lock (concurrent callers share one in-flight login), and retries the request.

Self-signed certificates

Many on-prem Unitrends Backup appliances use a self-signed TLS certificate. Set verifyTls: false to disable certificate validation:

constclient=newUnitrendsClient({baseUrl: 'https://backup.internal/api',username: '...',password: '...',verifyTls: false,});

Security: disabling certificate verification removes the only protection against man-in-the-middle attacks. Only do this on trusted internal networks. Prefer installing the appliance's CA into your system trust store.

Pagination

ParamDefaultMax
limit50500
offset0

Responses include total. Use listAll() to iterate all pages automatically.

API surface

client.appliances.list(params)// MSP Console onlyclient.appliances.listAll(params)// MSP Console onlyclient.assets.list({applianceId?,limit?,offset? })client.assets.listAll({applianceId?,limit?,offset? })client.assets.get(assetId,applianceId?)client.jobs.listBackups({applianceId?, ... })client.jobs.listAllBackups({applianceId?, ... })client.jobs.listHistory({applianceId?, ... })client.jobs.listAllHistory({applianceId?, ... })client.recoveryPoints.list({assetId?,applianceId?, ... })client.recoveryPoints.listAll({assetId?,applianceId?, ... })client.restores.queue({ recoveryPointId,applianceId?, ... })// POST /api/restoresclient.restores.get(restoreId)client.replication.listQueue(params)client.replication.listAllQueue(params)client.alerts.list(params)client.alerts.listAll(params)client.reports.successRate({applianceId?,startTime?,endTime? })

Error handling

import{UnitrendsError,UnitrendsAuthenticationError,UnitrendsForbiddenError,UnitrendsNotFoundError,UnitrendsRateLimitError,UnitrendsServerError,}from'@wyre-ai/node-unitrends';try{awaitclient.assets.get(123);}catch(err){if(errinstanceofUnitrendsRateLimitError){awaitnewPromise((r)=>setTimeout(r,err.retryAfter));}elseif(errinstanceofUnitrendsServerError&&err.statusCode===503){// Appliance is overloaded — already auto-retried with 30s backoff.}else{throwerr;}}

Gotchas

  • Asset IDs are appliance-scoped. Asset 123 on appliance A is NOT the same record as asset 123 on appliance B. The Asset type carries applianceId for this reason. When mspConsole: true the SDK enforces that asset operations include applianceId.
  • MSP Console exposes a subset of endpoints. Asset-level operations like restores.queue(...) typically must target the owning appliance directly.
  • Job status ≠ "data is recoverable". A job can have status: 'success' while its resulting recovery point has verifyState: 'failed'. The Job type exposes both fields.
  • Self-signed certs. See above — verifyTls: false disables MITM protection; use only on trusted networks.

Development

npm install
npm test
npm run typecheck
npm run lint
npm run build

License

Apache-2.0

About

Comprehensive Node.js/TypeScript client library for the Unitrends Backup REST API

Topics

Resources

Code of conduct

Contributing

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Universal Dark Mode - works on any site\n(function() {\n var enabled = true;\n \n function applyDarkMode() {\n if (!enabled) return;\n \n // Create style element if it doesn't exist\n var style = document.getElementById('universal-dark-mode-style');\n if (!style) {\n style = document.createElement('style');\n style.id = 'universal-dark-mode-style';\n document.head.appendChild(style);\n }\n \n // Dark mode CSS - inverts colors but preserves images/video\n style.textContent = '\n /* Invert everything except media */\n html {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #1a1a2e !important;\n }\n \n /* Restore images, videos, iframes, canvas */\n img, video, iframe, canvas, svg, picture, [style*=\"background-image\"] {\n filter: invert(1) hue-rotate(180deg) !important;\n }\n \n /* Preserve specific elements that should not be inverted */\n .no-dark-mode, .no-dark-mode *,\n [data-theme=\"light\"], [data-theme=\"light\"],\n .ace_editor, .ace_editor *,\n .CodeMirror, .CodeMirror *,\n .monaco-editor, .monaco-editor *,\n .markdown-body pre, .markdown-body pre *,\n .highlight, .highlight *,\n pre code, pre code * {\n filter: none !important;\n }\n \n /* Fix common UI elements */\n .modal, .popup, .dropdown-menu, .tooltip, .popover {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #2d2d44 !important;\n border-color: #444 !important;\n }\n \n /* Scrollbars */\n ::-webkit-scrollbar { background: #1a1a2e !important; }\n ::-webkit-scrollbar-thumb { background: #444 !important; }\n ::-webkit-scrollbar-thumb:hover { background: #555 !important; }\n \n /* Selection */\n ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ';\n }\n \n function removeDarkMode() {\n var style = document.getElementById('universal-dark-mode-style');\n if (style) style.remove();\n }\n \n // Toggle with Alt+Shift+D\n document.addEventListener('keydown', function(e) {\n if (e.altKey && e.shiftKey && e.key === 'D') {\n e.preventDefault();\n enabled = !enabled;\n if (enabled) {\n applyDarkMode();\n console.log('[Universal Dark Mode] Enabled');\n } else {\n removeDarkMode();\n console.log('[Universal Dark Mode] Disabled');\n }\n }\n });\n \n // Apply on load\n applyDarkMode();\n \n // Re-apply on dynamic content\n var observer = new MutationObserver(function(mutations) {\n if (enabled && !document.getElementById('universal-dark-mode-style')) {\n applyDarkMode();\n }\n });\n observer.observe(document.head, { childList: true });\n \n console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle');\n})();", "Universal Dark Mode"); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })();
Skip to content

Repository files navigation

@wyre-ai/node-unitrends

Comprehensive, fully-typed Node.js / TypeScript client library for the Unitrends Backup REST API.

License: Apache-2.0

Features

  • Full coverage of the documented endpoints: appliances, assets, jobs (backups + history), recovery points, restores, replication queue, alerts, reports
  • Session-token (POST /api/login) auth with single-flight re-auth on 401
  • Self-signed TLS support (verifyTls: false) for on-prem appliances
  • Page-based pagination via list() + async iterator listAll()
  • Defensive client-side rate limiting tuned for per-appliance limits, with 503 = "appliance overloaded" backoff
  • Typed error hierarchy
  • ESM + CommonJS dual exports, full .d.ts types
  • Zero any in the public API

Install

npm install @wyre-ai/node-unitrends

The package is published to GitHub Packages under the @wyre-ai scope. Add this to a project-local .npmrc:

@wyre-ai:registry=https://npm.pkg.github.com

Quick start

import{UnitrendsClient}from'@wyre-ai/node-unitrends';constclient=newUnitrendsClient({baseUrl: 'https://backup.example.com/api',username: process.env.UNITRENDS_USER!,password: process.env.UNITRENDS_PASS!,});// One page at a timeconstpage=awaitclient.assets.list({limit: 100});console.log(page.total);// Stream every asset, fetching pages on demandforawait(constassetofclient.assets.listAll({limit: 200})){console.log(asset.id,asset.hostname);}

Configuration

newUnitrendsClient({baseUrl: 'https://backup.example.com/api',// requiredusername: 'admin',password: '...',// Talking to an aggregating MSP Console rather than a single appliance.// When true, asset operations REQUIRE an applianceId.mspConsole: false,// On-prem appliances often ship with self-signed certs.// Disable verification ONLY on trusted internal networks.verifyTls: true,// Optional — tune client-side rate limiting (defaults shown).rateLimit: {enabled: true,maxRequests: 60,windowMs: 60_000,throttleThreshold: 0.8,retryAfterMs: 5_000,maxRetries: 3,applianceOverloadBackoffMs: 30_000,},});

Authentication

The SDK calls POST /api/login with { username, password }, captures the returned token + expires, and sends Authorization: Bearer <token> on all subsequent requests. Tokens have a 60-minute idle (sliding) timeout.

If a request fails with 401 mid-session, the SDK invalidates the cached token, re-authenticates once under a single-flight lock (concurrent callers share one in-flight login), and retries the request.

Self-signed certificates

Many on-prem Unitrends Backup appliances use a self-signed TLS certificate. Set verifyTls: false to disable certificate validation:

constclient=newUnitrendsClient({baseUrl: 'https://backup.internal/api',username: '...',password: '...',verifyTls: false,});

Security: disabling certificate verification removes the only protection against man-in-the-middle attacks. Only do this on trusted internal networks. Prefer installing the appliance's CA into your system trust store.

Pagination

ParamDefaultMax
limit50500
offset0

Responses include total. Use listAll() to iterate all pages automatically.

API surface

client.appliances.list(params)// MSP Console onlyclient.appliances.listAll(params)// MSP Console onlyclient.assets.list({applianceId?,limit?,offset? })client.assets.listAll({applianceId?,limit?,offset? })client.assets.get(assetId,applianceId?)client.jobs.listBackups({applianceId?, ... })client.jobs.listAllBackups({applianceId?, ... })client.jobs.listHistory({applianceId?, ... })client.jobs.listAllHistory({applianceId?, ... })client.recoveryPoints.list({assetId?,applianceId?, ... })client.recoveryPoints.listAll({assetId?,applianceId?, ... })client.restores.queue({ recoveryPointId,applianceId?, ... })// POST /api/restoresclient.restores.get(restoreId)client.replication.listQueue(params)client.replication.listAllQueue(params)client.alerts.list(params)client.alerts.listAll(params)client.reports.successRate({applianceId?,startTime?,endTime? })

Error handling

import{UnitrendsError,UnitrendsAuthenticationError,UnitrendsForbiddenError,UnitrendsNotFoundError,UnitrendsRateLimitError,UnitrendsServerError,}from'@wyre-ai/node-unitrends';try{awaitclient.assets.get(123);}catch(err){if(errinstanceofUnitrendsRateLimitError){awaitnewPromise((r)=>setTimeout(r,err.retryAfter));}elseif(errinstanceofUnitrendsServerError&&err.statusCode===503){// Appliance is overloaded — already auto-retried with 30s backoff.}else{throwerr;}}

Gotchas

  • Asset IDs are appliance-scoped. Asset 123 on appliance A is NOT the same record as asset 123 on appliance B. The Asset type carries applianceId for this reason. When mspConsole: true the SDK enforces that asset operations include applianceId.
  • MSP Console exposes a subset of endpoints. Asset-level operations like restores.queue(...) typically must target the owning appliance directly.
  • Job status ≠ "data is recoverable". A job can have status: 'success' while its resulting recovery point has verifyState: 'failed'. The Job type exposes both fields.
  • Self-signed certs. See above — verifyTls: false disables MITM protection; use only on trusted networks.

Development

npm install
npm test
npm run typecheck
npm run lint
npm run build

License

Apache-2.0

About

Comprehensive Node.js/TypeScript client library for the Unitrends Backup REST API

Topics

Resources

Code of conduct

Contributing

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages