{"id":50735368,"url":"https://github.com/wyre-technology/node-threatlocker","last_synced_at":"2026-06-10T13:01:19.099Z","repository":{"id":355523329,"uuid":"1224882756","full_name":"wyre-technology/node-threatlocker","owner":"wyre-technology","description":"Node.js/TypeScript client library for the ThreatLocker API","archived":false,"fork":false,"pushed_at":"2026-06-09T01:57:59.000Z","size":456,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-06-09T03:22:22.853Z","etag":null,"topics":["api-client","msp","sdk","threatlocker","typescript"],"latest_commit_sha":null,"homepage":null,"language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"other","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/wyre-technology.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-04-29T18:16:58.000Z","updated_at":"2026-06-09T01:58:02.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/wyre-technology/node-threatlocker","commit_stats":null,"previous_names":["wyre-technology/node-threatlocker"],"tags_count":3,"template":false,"template_full_name":null,"purl":"pkg:github/wyre-technology/node-threatlocker","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/wyre-technology%2Fnode-threatlocker","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/wyre-technology%2Fnode-threatlocker/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/wyre-technology%2Fnode-threatlocker/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/wyre-technology%2Fnode-threatlocker/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/wyre-technology","download_url":"https://codeload.github.com/wyre-technology/node-threatlocker/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/wyre-technology%2Fnode-threatlocker/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":34153483,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-06-10T02:00:07.152Z","response_time":89,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["api-client","msp","sdk","threatlocker","typescript"],"created_at":"2026-06-10T13:01:18.059Z","updated_at":"2026-06-10T13:01:19.085Z","avatar_url":"https://github.com/wyre-technology.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# node-threatlocker\n\n[![Build Status](https://github.com/wyre-technology/node-threatlocker/actions/workflows/release.yml/badge.svg)](https://github.com/wyre-technology/node-threatlocker/actions/workflows/release.yml)\n[![License](https://img.shields.io/badge/License-Apache_2.0-blue.svg)](https://opensource.org/licenses/Apache-2.0)\n[![Node.js](https://img.shields.io/badge/node-%3E%3D18.0.0-brightgreen.svg)](https://nodejs.org/)\n\nNode.js client library for the [ThreatLocker](https://www.threatlocker.com) Portal API. Zero production dependencies — uses native `fetch` (Node 18+).\n\n\u003e **Note:** This project is maintained by [Wyre Technology](https://github.com/wyre-technology).\n\n## Features\n\n- **Zero dependencies** — Uses native Node.js `fetch` (18+)\n- **Full TypeScript support** — Complete type definitions\n- **Built-in rate limiting** — Default 10 req/sec, configurable\n- **Error handling** — Structured error types for different scenarios\n- **Multi-tenant support** — Organization scoping with `childOrganizations` flag\n- **Beta environment support** — Configurable base URL\n\n## Installation\n\n```bash\nnpm install @wyre-technology/node-threatlocker\n```\n\n### Registry Configuration\n\nThis package is published to GitHub Packages. Add this to your `.npmrc`:\n\n```\n@wyre-technology:registry=https://npm.pkg.github.com\n//npm.pkg.github.com/:_authToken=YOUR_GITHUB_TOKEN\n```\n\n## Quick Start\n\n```typescript\nimport { ThreatLockerClient } from '@wyre-technology/node-threatlocker';\n\nconst client = new ThreatLockerClient({\n  apiKey: 'your-api-key',\n  organizationId: 'your-org-id', // Optional for multi-tenant scenarios\n});\n\n// List computers\nconst { items: computers } = await client.computers.list({ pageSize: 50 });\n\n// Get computer details\nconst computer = await client.computers.get(123);\n\n// Search approval requests\nconst { items: requests } = await client.approvalRequests.list({\n  status: 'pending',\n  pageSize: 100,\n});\n\n// List computer groups\nconst groups = await client.computerGroups.list({\n  includeAllComputers: true,\n});\n\n// Search audit logs\nconst { items: logs } = await client.auditLog.search({\n  actionType: 'application_blocked',\n  fromDate: '2024-01-01',\n  toDate: '2024-12-31',\n});\n```\n\n## Authentication\n\nThreatLocker uses raw API key authentication. The authorization header format is:\n\n```\nAuthorization: \u003cyour-api-key\u003e\n```\n\nNote: **No `Bearer` prefix** — ThreatLocker expects the raw API key.\n\nFor multi-tenant scenarios, you can provide an `organizationId` which will be sent as an `OrganizationId` header for parent-key access patterns.\n\n## Configuration Options\n\n```typescript\nconst client = new ThreatLockerClient({\n  apiKey: 'required-api-key',\n  organizationId: 'optional-org-id',\n  baseUrl: 'https://betaportalapi.g.threatlocker.com/portalapi', // Optional, defaults to production\n  maxRetries: 3, // Optional, default 3\n  rateLimitPerSecond: 10, // Optional, default 10 req/sec\n});\n```\n\n### Environment Support\n\n- **Production**: `https://portalapi.g.threatlocker.com/portalapi` (default)\n- **Beta**: `https://betaportalapi.g.threatlocker.com/portalapi`\n\n## API Reference\n\n| Resource | Methods | Description |\n|----------|---------|-------------|\n| `computers` | `list()`, `get(id)`, `getCheckins()` | Manage computers and check-ins |\n| `computerGroups` | `list()`, `getDropdown()` | Computer group management |\n| `approvalRequests` | `list()`, `get(id)`, `getPendingCount()`, `getPermitApplication(id)` | Application approval workflow |\n| `auditLog` | `search()`, `get(id)`, `getFileHistory(path)` | Unified audit and action logs |\n| `organizations` | `listChildren()`, `getAuthKey()`, `listForMoveComputers()` | Organization management |\n\n### Multi-Tenant Operations\n\nMost list/search endpoints support the `childOrganizations` flag to include data from child organizations:\n\n```typescript\nconst { items: computers } = await client.computers.list({\n  childOrganizations: true,\n  pageSize: 100,\n});\n```\n\n## Pagination\n\nThreatLocker APIs use POST-based pagination with a request body. All paginated responses return:\n\n```typescript\n{\n  items: T[],           // The actual data array\n  page: number,         // Current page number\n  pageSize: number,     // Items per page\n  total: number,        // Total item count\n  hasMore: boolean      // Whether more pages exist\n}\n```\n\nExample pagination:\n\n```typescript\nlet page = 1;\ndo {\n  const result = await client.computers.list({\n    pageNumber: page,\n    pageSize: 100,\n    childOrganizations: true,\n  });\n  \n  // Process result.items\n  console.log(`Page ${page}: ${result.items.length} computers`);\n  \n  page++;\n} while (result.hasMore);\n```\n\n## Rate Limiting\n\nBuilt-in token bucket rate limiter with configurable limits:\n\n- **Default**: 10 requests/second\n- **Configurable**: Set `rateLimitPerSecond` in client config\n- **Automatic retry**: Rate-limited requests are automatically retried\n\n## Error Handling\n\nStructured error types for different scenarios:\n\n```typescript\nimport { \n  ServiceError, \n  AuthenticationError, \n  ForbiddenError, \n  NotFoundError, \n  ValidationError, \n  RateLimitError, \n  ServerError \n} from '@wyre-technology/node-threatlocker';\n\ntry {\n  await client.computers.get(999999);\n} catch (error) {\n  if (error instanceof AuthenticationError) {\n    console.log('Invalid API key');\n  } else if (error instanceof NotFoundError) {\n    console.log('Computer not found');\n  } else if (error instanceof RateLimitError) {\n    console.log(`Rate limited, retry after ${error.retryAfter} seconds`);\n  }\n}\n```\n\n## Contributing\n\nSee [CONTRIBUTING.md](CONTRIBUTING.md) for development setup and guidelines.\n\n## License\n\nApache 2.0 — Copyright WYRE Technology","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fwyre-technology%2Fnode-threatlocker","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fwyre-technology%2Fnode-threatlocker","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fwyre-technology%2Fnode-threatlocker/lists"}