{"_id":"@avantguardllc/node-ninjaone","name":"@avantguardllc/node-ninjaone","dist-tags":{"latest":"1.1.0"},"versions":{"1.1.0":{"name":"@avantguardllc/node-ninjaone","version":"1.1.0","publishConfig":{"registry":"https://registry.npmjs.org/","access":"public"},"description":"Comprehensive, fully-typed Node.js/TypeScript library for the NinjaOne/NinjaRMM API","main":"./dist/index.cjs","module":"./dist/index.js","types":"./dist/index.d.ts","exports":{".":{"import":{"types":"./dist/index.d.ts","default":"./dist/index.js"},"require":{"types":"./dist/index.d.cts","default":"./dist/index.cjs"}}},"scripts":{"build":"tsup","dev":"tsup --watch","test":"vitest run","test:watch":"vitest","test:coverage":"vitest run --coverage","lint":"eslint src tests --ext .ts","lint:fix":"eslint src tests --ext .ts --fix","typecheck":"tsc --noEmit"},"keywords":["ninjaone","ninjarmm","rmm","msp","api","typescript","remote-monitoring","endpoint-management"],"author":{"name":"Wyre Technology"},"license":"Apache-2.0","repository":{"type":"git","url":"git+https://github.com/wyre-technology/node-ninjaone.git"},"bugs":{"url":"https://github.com/wyre-technology/node-ninjaone/issues"},"homepage":"https://github.com/wyre-technology/node-ninjaone#readme","engines":{"node":">=18.0.0"},"devDependencies":{"@semantic-release/changelog":"^6.0.3","@semantic-release/git":"^10.0.1","@semantic-release/github":"^11.0.1","@types/node":"^20.11.0","@typescript-eslint/eslint-plugin":"^7.0.0","@typescript-eslint/parser":"^7.0.0","@vitest/coverage-v8":"^1.3.0","eslint":"^8.56.0","msw":"^2.1.0","semantic-release":"^24.2.3","tsup":"^8.0.1","typescript":"^5.3.3","vitest":"^1.3.0"},"dependencies":{},"_id":"@avantguardllc/node-ninjaone@1.1.0","_nodeVersion":"20.20.2","_npmVersion":"10.8.2","dist":{"integrity":"sha512-GVFLeQrxyfCMxsKy736zTWMFmvwkQof8tOBaHoILjyzEK02sWcdst9IBu+M9lFtR9wJGqYd2sq/5X+1fU7KuyA==","shasum":"d8dce91425fa8ae341266a985391ee636aceacb1","tarball":"https://registry.npmjs.org/@avantguardllc/node-ninjaone/-/node-ninjaone-1.1.0.tgz","fileCount":10,"unpackedSize":301652,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEQCICnyCBM/4jRKtaZyANzw1x765E29jDVZuW9rC17BM7lRAiBzzri8PvpYK8+8/7XF4KJRGAijoogo8pd999fdJOjlZw=="}]},"_npmUser":{"name":"avantguardllc","email":"appadmin@avantguard.it"},"directories":{},"maintainers":[{"name":"avantguardllc","email":"appadmin@avantguard.it"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/node-ninjaone_1.1.0_1777919541698_0.8750880185409255"},"_hasShrinkwrap":false}},"time":{"created":"2026-05-04T18:32:21.635Z","1.1.0":"2026-05-04T18:32:21.882Z","modified":"2026-05-04T18:32:22.144Z"},"maintainers":[{"name":"avantguardllc","email":"appadmin@avantguard.it"}],"description":"Comprehensive, fully-typed Node.js/TypeScript library for the NinjaOne/NinjaRMM API","homepage":"https://github.com/wyre-technology/node-ninjaone#readme","keywords":["ninjaone","ninjarmm","rmm","msp","api","typescript","remote-monitoring","endpoint-management"],"repository":{"type":"git","url":"git+https://github.com/wyre-technology/node-ninjaone.git"},"author":{"name":"Wyre Technology"},"bugs":{"url":"https://github.com/wyre-technology/node-ninjaone/issues"},"license":"Apache-2.0","readme":"# @asachs01/node-ninjaone\n\nComprehensive, fully-typed Node.js/TypeScript library for the NinjaOne/NinjaRMM API.\n\n## Features\n\n- Full TypeScript support with comprehensive type definitions\n- OAuth 2.0 authentication with automatic token refresh\n- Support for all six regional endpoints (US, EU, Oceania, Canada, US2, Federal)\n- Built-in rate limiting with configurable thresholds\n- Automatic retry logic for rate limits and server errors\n- Clean, intuitive API design\n\n## Installation\n\n```bash\nnpm install @asachs01/node-ninjaone\n```\n\n## Quick Start\n\n```typescript\nimport { NinjaOneClient } from '@asachs01/node-ninjaone';\n\nconst client = new NinjaOneClient({\n  clientId: process.env.NINJAONE_CLIENT_ID!,\n  clientSecret: process.env.NINJAONE_CLIENT_SECRET!,\n  region: 'us', // 'us' | 'eu' | 'oc' | 'ca' | 'us2' | 'fed'\n});\n\n// List organizations\nconst organizations = await client.organizations.list();\nconsole.log(`Found ${organizations.length} organizations`);\n\n// Get devices for an organization\nconst devices = await client.devices.listByOrganization(organizations[0].id);\nconsole.log(`Found ${devices.length} devices`);\n\n// Get active alerts\nconst alerts = await client.alerts.list({ status: 'OPEN' });\nconsole.log(`Found ${alerts.length} open alerts`);\n\n// Create a ticket\nconst ticket = await client.tickets.create({\n  subject: 'Server maintenance required',\n  priority: 'HIGH',\n  organizationId: organizations[0].id,\n});\nconsole.log(`Created ticket: ${ticket.ticketNumber}`);\n```\n\n## Configuration\n\n### Basic Configuration\n\n```typescript\nconst client = new NinjaOneClient({\n  clientId: 'your-client-id',\n  clientSecret: 'your-client-secret',\n  region: 'us', // Optional, defaults to 'us'\n});\n```\n\n### Regional Endpoints\n\nNinjaOne has three regional endpoints:\n\n| Region | Base URL |\n|--------|----------|\n| US (default) | `https://app.ninjarmm.com` |\n| EU | `https://eu.ninjarmm.com` |\n| Oceania | `https://oc.ninjarmm.com` |\n\n```typescript\n// EU region\nconst euClient = new NinjaOneClient({\n  clientId: 'your-client-id',\n  clientSecret: 'your-client-secret',\n  region: 'eu',\n});\n\n// Custom base URL\nconst customClient = new NinjaOneClient({\n  clientId: 'your-client-id',\n  clientSecret: 'your-client-secret',\n  baseUrl: 'https://custom.ninjarmm.example.com',\n});\n```\n\n### OAuth Scopes\n\n```typescript\nconst client = new NinjaOneClient({\n  clientId: 'your-client-id',\n  clientSecret: 'your-client-secret',\n  scopes: ['monitoring', 'management', 'control'], // Default: ['monitoring', 'management']\n});\n```\n\n### Rate Limiting\n\nThe client includes built-in rate limiting with sensible defaults:\n\n```typescript\nconst client = new NinjaOneClient({\n  clientId: 'your-client-id',\n  clientSecret: 'your-client-secret',\n  rateLimit: {\n    enabled: true,           // Enable/disable rate limiting\n    maxRequests: 100,        // Max requests per window\n    windowMs: 60000,         // Window duration (1 minute)\n    throttleThreshold: 0.8,  // Start throttling at 80%\n    retryAfterMs: 5000,      // Retry delay for 429 errors\n    maxRetries: 3,           // Max retry attempts\n  },\n});\n```\n\n## API Reference\n\n### Organizations\n\n```typescript\n// List all organizations\nconst organizations = await client.organizations.list();\n\n// Get a single organization\nconst org = await client.organizations.get(123);\n\n// Get detailed organization info (includes device counts)\nconst detailed = await client.organizations.getDetailed(123);\n\n// Create an organization\nconst newOrg = await client.organizations.create({\n  name: 'New Customer',\n  description: 'Customer description',\n  nodeApprovalMode: 'AUTOMATIC',\n});\n\n// Update an organization\nconst updated = await client.organizations.update(123, {\n  name: 'Updated Name',\n});\n\n// Delete an organization\nawait client.organizations.delete(123);\n```\n\n### Devices\n\n```typescript\n// List all devices\nconst devices = await client.devices.list();\n\n// List devices by organization\nconst orgDevices = await client.devices.listByOrganization(123);\n\n// Get a single device\nconst device = await client.devices.get(456);\n\n// Update a device\nconst updated = await client.devices.update(456, {\n  displayName: 'New Display Name',\n  tags: ['production', 'critical'],\n});\n\n// Reboot a device\nawait client.devices.reboot(456, 'Maintenance window');\n\n// Get device activities\nconst activities = await client.devices.getActivities(456);\n\n// Get Windows services\nconst services = await client.devices.getServices(456);\n\n// Start/stop/restart a service\nawait client.devices.startService(456, 'Spooler');\nawait client.devices.stopService(456, 'Spooler');\nawait client.devices.restartService(456, 'Spooler');\n\n// Get software inventory\nconst software = await client.devices.getSoftware(456);\n\n// Get hardware inventory\nconst inventory = await client.devices.getInventory(456);\n```\n\n### Alerts\n\n```typescript\n// List all alerts\nconst alerts = await client.alerts.list();\n\n// List alerts with filters\nconst criticalAlerts = await client.alerts.list({\n  severity: 'CRITICAL',\n  status: 'OPEN',\n});\n\n// List alerts by device\nconst deviceAlerts = await client.alerts.listByDevice(456);\n\n// List alerts by organization\nconst orgAlerts = await client.alerts.listByOrganization(123);\n\n// Get a single alert\nconst alert = await client.alerts.get('alert-uid-123');\n\n// Delete/acknowledge an alert\nawait client.alerts.delete('alert-uid-123');\n\n// Reset an alert\nawait client.alerts.reset('alert-uid-123');\n```\n\n### Tickets\n\n```typescript\n// List tickets\nconst result = await client.tickets.list();\nconsole.log(`Total tickets: ${result.totalCount}`);\n\n// List with filters\nconst openTickets = await client.tickets.list({\n  status: 'OPEN',\n  priority: 'HIGH',\n});\n\n// Get a single ticket\nconst ticket = await client.tickets.get(789);\n\n// Create a ticket\nconst newTicket = await client.tickets.create({\n  subject: 'Server not responding',\n  description: 'The file server is not responding to pings',\n  priority: 'HIGH',\n  organizationId: 123,\n  deviceId: 456,\n});\n\n// Update a ticket\nconst updated = await client.tickets.update(789, {\n  status: 'IN_PROGRESS',\n  assigneeUid: 'tech-user-uid',\n});\n\n// Get ticket comments\nconst comments = await client.tickets.getComments(789);\n\n// Add a comment\nconst comment = await client.tickets.addComment(789, {\n  body: 'Working on this issue.',\n  internal: false,\n});\n\n// List ticket forms\nconst forms = await client.tickets.listForms();\n```\n\n### Webhooks\n\n```typescript\n// List webhooks\nconst webhooks = await client.webhooks.list();\n\n// Get a single webhook\nconst webhook = await client.webhooks.get(111);\n\n// Create a webhook\nconst newWebhook = await client.webhooks.create({\n  url: 'https://your-server.com/webhook',\n  activityTypes: ['ALERT_TRIGGERED', 'ALERT_RESET', 'DEVICE_ADDED'],\n  isActive: true,\n});\n\n// Update a webhook\nconst updated = await client.webhooks.update(111, {\n  url: 'https://new-server.com/webhook',\n});\n\n// Delete a webhook\nawait client.webhooks.delete(111);\n```\n\n## Error Handling\n\nThe library provides specific error classes for different error conditions:\n\n```typescript\nimport {\n  NinjaOneError,\n  NinjaOneAuthenticationError,\n  NinjaOneForbiddenError,\n  NinjaOneNotFoundError,\n  NinjaOneValidationError,\n  NinjaOneRateLimitError,\n  NinjaOneServerError,\n} from '@asachs01/node-ninjaone';\n\ntry {\n  const device = await client.devices.get(999);\n} catch (error) {\n  if (error instanceof NinjaOneNotFoundError) {\n    console.log('Device not found');\n  } else if (error instanceof NinjaOneAuthenticationError) {\n    console.log('Authentication failed - check credentials');\n  } else if (error instanceof NinjaOneRateLimitError) {\n    console.log(`Rate limited - retry after ${error.retryAfter}ms`);\n  } else if (error instanceof NinjaOneValidationError) {\n    console.log('Validation errors:', error.errors);\n  } else if (error instanceof NinjaOneError) {\n    console.log(`API error: ${error.message} (${error.statusCode})`);\n  }\n}\n```\n\n## TypeScript Support\n\nAll types are exported for use in your TypeScript projects:\n\n```typescript\nimport type {\n  Organization,\n  OrganizationCreateData,\n  Device,\n  DeviceStatus,\n  DeviceNodeClass,\n  Alert,\n  AlertSeverity,\n  Ticket,\n  TicketStatus,\n  TicketPriority,\n  Webhook,\n  WebhookActivityType,\n} from '@asachs01/node-ninjaone';\n```\n\n## Rate Limit Status\n\nYou can check the current rate limit status:\n\n```typescript\nconst status = client.getRateLimitStatus();\nconsole.log(`Remaining requests: ${status.remaining}`);\nconsole.log(`Current rate: ${status.rate * 100}%`);\n```\n\n## License\n\nApache-2.0\n\n## Author\n\nAaron Sachs\n","readmeFilename":"README.md","_rev":"1-f0950a4b78e23bd2949713269ba5732d"}