Comprehensive, fully-typed Node.js / TypeScript client library for the Kaseya VSA REST API.
- Full coverage of core VSA resources: agents, audit, patches, procedures, alarms, tickets, organizations, machine groups
- Two authentication modes: legacy local users (two-step token exchange) and Kaseya One SSO
- Automatic token caching with single-flight refresh on 401
- OData pagination via async iterators (
$top,$skip,$filter,$orderby) - Token-bucket rate limiting tuned for VSA's defensive defaults
- Typed error hierarchy including
KaseyaVsaApplicationErrorfor HTTP 200 + non-zeroResponseCode - ESM and CommonJS dual exports, full
.d.tstypes - Zero
anyin the public API
npm install @wyre-technology/node-kaseya-vsaThe 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
VSA is per-tenant: each MSP has a private base URL such as
https://vsa.example-msp.com/api/v1.0. There is no shared default; you must
provide the baseUrl.
import { KaseyaVsaClient } from '@wyre-technology/node-kaseya-vsa';
// Local user (legacy) auth
const client = new KaseyaVsaClient({
baseUrl: 'https://vsa.example-msp.com/api/v1.0',
username: process.env.VSA_USER!,
password: process.env.VSA_PASS!,
});
// Or Kaseya One SSO
const ssoClient = new KaseyaVsaClient({
baseUrl: 'https://vsa.example-msp.com',
kaseyaOneToken: process.env.KASEYA_ONE_TOKEN!,
});
// Iterate every agent, fetching pages on demand
for await (const agent of client.agents.listAll({ top: 500 })) {
console.log(agent.AgentId, agent.ComputerName);
}The SDK builds the Authorization: Basic header automatically:
- Generate a 20-character random nonce.
- Compute
SHA-256( SHA-256(password+username) + nonce )→pass2. - Compute
SHA-1( SHA-1(password+username) + nonce )→pass1. - Send
Basic user=<u>,pass2=<sha256>,pass1=<sha1>,rand2=<nonce>toGET /auth. - Use the returned
Result.TokenasAuthorization: Bearer <token>on every subsequent call.
When a kaseyaOneToken is provided, the SDK uses GET /auth/sso with that
token as a bearer. The response shape and refresh behavior are identical.
- Tokens default to ~15-minute lifetime (
Token-Expires-Inis honored if returned). - Refreshes happen ~5 minutes before expiry.
- On 401 from any non-auth call, the SDK invalidates the cache, single-flights the re-auth (so concurrent in-flight requests share one refresh), and retries the original request once.
VSA list endpoints use OData $top / $skip:
| Param | Default | Max |
|---|---|---|
$top |
100 | 1000 |
$skip |
0 | — |
$filter |
none | — |
$orderby |
none | — |
Both single-page and async-iterator helpers are exposed:
// Single page
const page = await client.agents.list({ top: 100 });
// Auto-paging iterator
for await (const agent of client.agents.listAll({ filter: "Online eq true" })) {
// ...
}client.agents.list({ top, skip, filter, orderby })
client.agents.listAll(params)
client.agents.get(agentId)
client.audit.listSoftware(agentId)
client.audit.getHardware(agentId)
client.patches.getStatus(agentId)
client.patches.deployNow(agentId)
client.procedures.list(agentId)
client.procedures.runNow(agentId, procId)
client.alarms.list({ filter: "AlarmState eq 'Open'" })
client.alarms.listAll(params)
client.tickets.list(params) // 404s if Service Desk module disabled
client.tickets.listAll(params)
client.tickets.get(ticketId)
client.organizations.list(params)
client.machineGroups.list(params)The SDK never lets the raw VSA envelope leak to the caller; it unwraps to the
Result field automatically and throws KaseyaVsaApplicationError when the
envelope reports failure (ResponseCode != 0 or non-null Error) on an
otherwise-successful HTTP 200.
import {
KaseyaVsaError,
KaseyaVsaAuthenticationError,
KaseyaVsaApplicationError,
KaseyaVsaForbiddenError,
KaseyaVsaNotFoundError,
KaseyaVsaRateLimitError,
KaseyaVsaServerError,
} from '@wyre-technology/node-kaseya-vsa';
try {
await client.agents.get('123');
} catch (err) {
if (err instanceof KaseyaVsaRateLimitError) {
await new Promise((r) => setTimeout(r, err.retryAfter));
} else if (err instanceof KaseyaVsaApplicationError) {
console.error('VSA app error', err.responseCode, err.response);
} else {
throw err;
}
}- Trailing slashes. VSA redirects
/api/v1.0/agents→/agents/(HTTP 301), and Node'sfetchstrips theAuthorizationheader on cross-origin redirect. The SDK normalizes every path to its trailing-slash form before sending so the redirect never fires. - Concurrent token refresh. Multiple in-flight requests racing on a 401 would each try to re-auth. The SDK wraps re-auth in a single-flight mutex.
- Tenant URL forms. Both
https://vsa.example.comandhttps://vsa.example.com/api/v1.0are accepted and normalized. - HTTP 200 +
ResponseCode != 0. Treated as a business-logic failure and raised asKaseyaVsaApplicationErrorwith VSA'sErrorfield as the message. - Service Desk 404. When the SD module is not enabled on the tenant, ticket
endpoints return 404. The SDK surfaces this as a friendly
KaseyaVsaNotFoundErrormentioning the SD module.
npm install
npm test
npm run typecheck
npm run lint
npm run buildApache-2.0