npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@avantguardllc/node-ninjaone

v1.1.0

Published

Comprehensive, fully-typed Node.js/TypeScript library for the NinjaOne/NinjaRMM API

Readme

@asachs01/node-ninjaone

Comprehensive, fully-typed Node.js/TypeScript library for the NinjaOne/NinjaRMM API.

Features

  • Full TypeScript support with comprehensive type definitions
  • OAuth 2.0 authentication with automatic token refresh
  • Support for all six regional endpoints (US, EU, Oceania, Canada, US2, Federal)
  • Built-in rate limiting with configurable thresholds
  • Automatic retry logic for rate limits and server errors
  • Clean, intuitive API design

Installation

npm install @asachs01/node-ninjaone

Quick Start

import { NinjaOneClient } from '@asachs01/node-ninjaone';

const client = new NinjaOneClient({
  clientId: process.env.NINJAONE_CLIENT_ID!,
  clientSecret: process.env.NINJAONE_CLIENT_SECRET!,
  region: 'us', // 'us' | 'eu' | 'oc' | 'ca' | 'us2' | 'fed'
});

// List organizations
const organizations = await client.organizations.list();
console.log(`Found ${organizations.length} organizations`);

// Get devices for an organization
const devices = await client.devices.listByOrganization(organizations[0].id);
console.log(`Found ${devices.length} devices`);

// Get active alerts
const alerts = await client.alerts.list({ status: 'OPEN' });
console.log(`Found ${alerts.length} open alerts`);

// Create a ticket
const ticket = await client.tickets.create({
  subject: 'Server maintenance required',
  priority: 'HIGH',
  organizationId: organizations[0].id,
});
console.log(`Created ticket: ${ticket.ticketNumber}`);

Configuration

Basic Configuration

const client = new NinjaOneClient({
  clientId: 'your-client-id',
  clientSecret: 'your-client-secret',
  region: 'us', // Optional, defaults to 'us'
});

Regional Endpoints

NinjaOne has three regional endpoints:

| Region | Base URL | |--------|----------| | US (default) | https://app.ninjarmm.com | | EU | https://eu.ninjarmm.com | | Oceania | https://oc.ninjarmm.com |

// EU region
const euClient = new NinjaOneClient({
  clientId: 'your-client-id',
  clientSecret: 'your-client-secret',
  region: 'eu',
});

// Custom base URL
const customClient = new NinjaOneClient({
  clientId: 'your-client-id',
  clientSecret: 'your-client-secret',
  baseUrl: 'https://custom.ninjarmm.example.com',
});

OAuth Scopes

const client = new NinjaOneClient({
  clientId: 'your-client-id',
  clientSecret: 'your-client-secret',
  scopes: ['monitoring', 'management', 'control'], // Default: ['monitoring', 'management']
});

Rate Limiting

The client includes built-in rate limiting with sensible defaults:

const client = new NinjaOneClient({
  clientId: 'your-client-id',
  clientSecret: 'your-client-secret',
  rateLimit: {
    enabled: true,           // Enable/disable rate limiting
    maxRequests: 100,        // Max requests per window
    windowMs: 60000,         // Window duration (1 minute)
    throttleThreshold: 0.8,  // Start throttling at 80%
    retryAfterMs: 5000,      // Retry delay for 429 errors
    maxRetries: 3,           // Max retry attempts
  },
});

API Reference

Organizations

// List all organizations
const organizations = await client.organizations.list();

// Get a single organization
const org = await client.organizations.get(123);

// Get detailed organization info (includes device counts)
const detailed = await client.organizations.getDetailed(123);

// Create an organization
const newOrg = await client.organizations.create({
  name: 'New Customer',
  description: 'Customer description',
  nodeApprovalMode: 'AUTOMATIC',
});

// Update an organization
const updated = await client.organizations.update(123, {
  name: 'Updated Name',
});

// Delete an organization
await client.organizations.delete(123);

Devices

// List all devices
const devices = await client.devices.list();

// List devices by organization
const orgDevices = await client.devices.listByOrganization(123);

// Get a single device
const device = await client.devices.get(456);

// Update a device
const updated = await client.devices.update(456, {
  displayName: 'New Display Name',
  tags: ['production', 'critical'],
});

// Reboot a device
await client.devices.reboot(456, 'Maintenance window');

// Get device activities
const activities = await client.devices.getActivities(456);

// Get Windows services
const services = await client.devices.getServices(456);

// Start/stop/restart a service
await client.devices.startService(456, 'Spooler');
await client.devices.stopService(456, 'Spooler');
await client.devices.restartService(456, 'Spooler');

// Get software inventory
const software = await client.devices.getSoftware(456);

// Get hardware inventory
const inventory = await client.devices.getInventory(456);

Alerts

// List all alerts
const alerts = await client.alerts.list();

// List alerts with filters
const criticalAlerts = await client.alerts.list({
  severity: 'CRITICAL',
  status: 'OPEN',
});

// List alerts by device
const deviceAlerts = await client.alerts.listByDevice(456);

// List alerts by organization
const orgAlerts = await client.alerts.listByOrganization(123);

// Get a single alert
const alert = await client.alerts.get('alert-uid-123');

// Delete/acknowledge an alert
await client.alerts.delete('alert-uid-123');

// Reset an alert
await client.alerts.reset('alert-uid-123');

Tickets

// List tickets
const result = await client.tickets.list();
console.log(`Total tickets: ${result.totalCount}`);

// List with filters
const openTickets = await client.tickets.list({
  status: 'OPEN',
  priority: 'HIGH',
});

// Get a single ticket
const ticket = await client.tickets.get(789);

// Create a ticket
const newTicket = await client.tickets.create({
  subject: 'Server not responding',
  description: 'The file server is not responding to pings',
  priority: 'HIGH',
  organizationId: 123,
  deviceId: 456,
});

// Update a ticket
const updated = await client.tickets.update(789, {
  status: 'IN_PROGRESS',
  assigneeUid: 'tech-user-uid',
});

// Get ticket comments
const comments = await client.tickets.getComments(789);

// Add a comment
const comment = await client.tickets.addComment(789, {
  body: 'Working on this issue.',
  internal: false,
});

// List ticket forms
const forms = await client.tickets.listForms();

Webhooks

// List webhooks
const webhooks = await client.webhooks.list();

// Get a single webhook
const webhook = await client.webhooks.get(111);

// Create a webhook
const newWebhook = await client.webhooks.create({
  url: 'https://your-server.com/webhook',
  activityTypes: ['ALERT_TRIGGERED', 'ALERT_RESET', 'DEVICE_ADDED'],
  isActive: true,
});

// Update a webhook
const updated = await client.webhooks.update(111, {
  url: 'https://new-server.com/webhook',
});

// Delete a webhook
await client.webhooks.delete(111);

Error Handling

The library provides specific error classes for different error conditions:

import {
  NinjaOneError,
  NinjaOneAuthenticationError,
  NinjaOneForbiddenError,
  NinjaOneNotFoundError,
  NinjaOneValidationError,
  NinjaOneRateLimitError,
  NinjaOneServerError,
} from '@asachs01/node-ninjaone';

try {
  const device = await client.devices.get(999);
} catch (error) {
  if (error instanceof NinjaOneNotFoundError) {
    console.log('Device not found');
  } else if (error instanceof NinjaOneAuthenticationError) {
    console.log('Authentication failed - check credentials');
  } else if (error instanceof NinjaOneRateLimitError) {
    console.log(`Rate limited - retry after ${error.retryAfter}ms`);
  } else if (error instanceof NinjaOneValidationError) {
    console.log('Validation errors:', error.errors);
  } else if (error instanceof NinjaOneError) {
    console.log(`API error: ${error.message} (${error.statusCode})`);
  }
}

TypeScript Support

All types are exported for use in your TypeScript projects:

import type {
  Organization,
  OrganizationCreateData,
  Device,
  DeviceStatus,
  DeviceNodeClass,
  Alert,
  AlertSeverity,
  Ticket,
  TicketStatus,
  TicketPriority,
  Webhook,
  WebhookActivityType,
} from '@asachs01/node-ninjaone';

Rate Limit Status

You can check the current rate limit status:

const status = client.getRateLimitStatus();
console.log(`Remaining requests: ${status.remaining}`);
console.log(`Current rate: ${status.rate * 100}%`);

License

Apache-2.0

Author

Aaron Sachs