https://github.com/wyre-technology/node-unitrends
Comprehensive Node.js/TypeScript client library for the Unitrends Backup REST API
https://github.com/wyre-technology/node-unitrends
api-client backup bcdr kaseya msp sdk typescript unitrends
Last synced: 3 days ago
JSON representation
Comprehensive Node.js/TypeScript client library for the Unitrends Backup REST API
- Host: GitHub
- URL: https://github.com/wyre-technology/node-unitrends
- Owner: wyre-technology
- License: apache-2.0
- Created: 2026-05-01T19:51:58.000Z (about 1 month ago)
- Default Branch: main
- Last Pushed: 2026-06-09T01:55:48.000Z (4 days ago)
- Last Synced: 2026-06-09T03:21:30.507Z (4 days ago)
- Topics: api-client, backup, bcdr, kaseya, msp, sdk, typescript, unitrends
- Language: TypeScript
- Size: 763 KB
- Stars: 0
- Watchers: 0
- Forks: 0
- Open Issues: 6
-
Metadata Files:
- Readme: README.md
- Changelog: CHANGELOG.md
- Contributing: CONTRIBUTING.md
- License: LICENSE
- Code of conduct: CODE_OF_CONDUCT.md
Awesome Lists containing this project
README
# @wyre-technology/node-unitrends
Comprehensive, fully-typed Node.js / TypeScript client library for the
Unitrends Backup REST API.
[](LICENSE)
## 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
```bash
npm install @wyre-technology/node-unitrends
```
The package is published to GitHub Packages under the `@wyre-technology` scope.
Add this to a project-local `.npmrc`:
```
@wyre-technology:registry=https://npm.pkg.github.com
```
## Quick start
```typescript
import { UnitrendsClient } from '@wyre-technology/node-unitrends';
const client = new UnitrendsClient({
baseUrl: 'https://backup.example.com/api',
username: process.env.UNITRENDS_USER!,
password: process.env.UNITRENDS_PASS!,
});
// One page at a time
const page = await client.assets.list({ limit: 100 });
console.log(page.total);
// Stream every asset, fetching pages on demand
for await (const asset of client.assets.listAll({ limit: 200 })) {
console.log(asset.id, asset.hostname);
}
```
## Configuration
```typescript
new UnitrendsClient({
baseUrl: 'https://backup.example.com/api', // required
username: '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 ` 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:
```typescript
const client = new UnitrendsClient({
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
| Param | Default | Max |
| ------- | ------- | --- |
| `limit` | 50 | 500 |
| `offset`| 0 | — |
Responses include `total`. Use `listAll()` to iterate all pages automatically.
## API surface
```typescript
client.appliances.list(params) // MSP Console only
client.appliances.listAll(params) // MSP Console only
client.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/restores
client.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
```typescript
import {
UnitrendsError,
UnitrendsAuthenticationError,
UnitrendsForbiddenError,
UnitrendsNotFoundError,
UnitrendsRateLimitError,
UnitrendsServerError,
} from '@wyre-technology/node-unitrends';
try {
await client.assets.get(123);
} catch (err) {
if (err instanceof UnitrendsRateLimitError) {
await new Promise((r) => setTimeout(r, err.retryAfter));
} else if (err instanceof UnitrendsServerError && err.statusCode === 503) {
// Appliance is overloaded — already auto-retried with 30s backoff.
} else {
throw err;
}
}
```
## 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
```bash
npm install
npm test
npm run typecheck
npm run lint
npm run build
```
## License
Apache-2.0