{"_id":"@aybouzaglou/unifi-client","name":"@aybouzaglou/unifi-client","dist-tags":{"latest":"0.1.0"},"versions":{"0.1.0":{"name":"@aybouzaglou/unifi-client","version":"0.1.0","description":"Type-safe TypeScript client for the UniFi Site Manager API and UniFi Network API.","keywords":["unifi","ubiquiti","unifi-network","site-manager","api-client","typescript","network-api"],"license":"MIT","type":"module","packageManager":"pnpm@11.8.0","engines":{"node":">=18.17"},"main":"./dist/index.cjs","module":"./dist/index.js","types":"./dist/index.d.ts","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js","require":"./dist/index.cjs"},"./site-manager":{"types":"./dist/site-manager/index.d.ts","import":"./dist/site-manager/index.js","require":"./dist/site-manager/index.cjs"},"./network":{"types":"./dist/network/index.d.ts","import":"./dist/network/index.js","require":"./dist/network/index.cjs"},"./package.json":"./package.json"},"scripts":{"generate":"openapi-typescript openapi/network.json -o src/network/schema.ts && openapi-typescript openapi/site-manager.json -o src/site-manager/schema.ts","build":"tsup","typecheck":"tsc --noEmit","typecheck:examples":"tsc -p tsconfig.examples.json --noEmit","test":"vitest run","test:coverage":"vitest run --coverage","test:watch":"vitest","verify":"pnpm run typecheck && pnpm run typecheck:examples && pnpm run test && pnpm run test:coverage && pnpm run build","prepublishOnly":"pnpm run verify"},"devDependencies":{"@types/node":"^22.10.2","@vitest/coverage-v8":"2.1.9","openapi-typescript":"^7.5.0","tsup":"^8.3.5","typescript":"^5.7.2","vitest":"^2.1.8"},"optionalDependencies":{"undici":"^6.27.0"},"gitHead":"6af06bc143d2f94eb8a482b74fbbdb983268275c","_id":"@aybouzaglou/unifi-client@0.1.0","_nodeVersion":"24.16.0","_npmVersion":"11.13.0","dist":{"integrity":"sha512-YqhwLxoAqVIusQLfqP6O6vmUrlehCR7OCOiNY0nNFMQz4Mw5IBhfzJLMTzViZOoJLRptdhkOnGA3+YzliNlmbg==","shasum":"b665e8b3c78bd654bf0e32ddd0677a6a908410f0","tarball":"https://registry.npmjs.org/@aybouzaglou/unifi-client/-/unifi-client-0.1.0.tgz","fileCount":26,"unpackedSize":4068590,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEYCIQC1h0QGV6QzCD1h1+KA64kIbN5sEo2vUFQejJm64W/eAgIhAJuRPxl6zr6kGPqdoLnBmtB+x034H0sovoZMMriwmOWG"}]},"_npmUser":{"name":"aybouzaglou","email":"aybouzagloumusic@gmail.com"},"directories":{},"maintainers":[{"name":"aybouzaglou","email":"aybouzagloumusic@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/unifi-client_0.1.0_1782276555659_0.5201605102971947"},"_hasShrinkwrap":false}},"time":{"created":"2026-06-24T04:49:15.542Z","0.1.0":"2026-06-24T04:49:15.878Z","modified":"2026-06-24T04:49:16.054Z"},"maintainers":[{"name":"aybouzaglou","email":"aybouzagloumusic@gmail.com"}],"description":"Type-safe TypeScript client for the UniFi Site Manager API and UniFi Network API.","keywords":["unifi","ubiquiti","unifi-network","site-manager","api-client","typescript","network-api"],"license":"MIT","readme":"# @aybouzaglou/unifi-client\n\nType-safe TypeScript client for the official UniFi Site Manager API and UniFi Network API.\n\n- Types generated from Ubiquiti's official OpenAPI specs.\n- Site Manager and Network APIs in one package.\n- Dual ESM/CJS builds with `.d.ts` declarations.\n- Platform `fetch` by default; optional `undici` dispatcher support for self-signed local-console TLS.\n- Typed error hierarchy with status, code, request id, URL, and retry metadata.\n- `list()` for one page, `listAll()` for async-iterable pagination.\n\n## Install\n\n```bash\npnpm add @aybouzaglou/unifi-client\n# or\nnpm install @aybouzaglou/unifi-client\n# or\nyarn add @aybouzaglou/unifi-client\n```\n\nRequires Node `>=18.17` or another runtime with global `fetch`.\n\nFor local UniFi consoles with self-signed certificates, install the optional TLS helper dependency and set `allowInsecureTLS: true`:\n\n```bash\npnpm add undici\n```\n\n## API Keys\n\n| API | Key location |\n| --- | --- |\n| Site Manager | Sign in at `unifi.ui.com`, then Settings -> API. |\n| Network | Open the Network app on the console, then Settings -> Control Plane -> Integrations. |\n\nBoth APIs authenticate with `X-API-Key`; the client sets the header for you.\n\n## Quick Start\n\n```ts\nimport { UnifiClient } from \"@aybouzaglou/unifi-client\";\n\nconst unifi = new UnifiClient({\n  siteManager: { apiKey: process.env.UNIFI_SM_KEY! },\n  network: {\n    host: \"192.168.1.1\",\n    apiKey: process.env.UNIFI_NET_KEY!,\n    allowInsecureTLS: true,\n  },\n});\n\nconst { data: hosts } = await unifi.siteManager.hosts.list();\n\nconst siteId = await unifi.network.sites.findId(\"default\");\nif (!siteId) throw new Error(\"Default site not found\");\n\nconst clients = await unifi.network.clients.listAll(siteId).collect(100);\n\nconsole.log(hosts, clients);\n```\n\nStandalone imports are available when you only need one API:\n\n```ts\nimport { SiteManagerClient } from \"@aybouzaglou/unifi-client/site-manager\";\nimport { NetworkClient } from \"@aybouzaglou/unifi-client/network\";\n```\n\n## Pagination\n\nEvery list endpoint has two shapes:\n\n- `list(...)` returns one page.\n- `listAll(...)` returns a `Paginator<T>`.\n\n```ts\nconst page = await unifi.network.clients.list(siteId, { limit: 50 });\nconsole.log(page.data, page.totalCount);\n\nconst all = unifi.network.clients.listAll(siteId);\n\nfor await (const client of all) {\n  console.log(client.id);\n}\n\nfor await (const pageItems of unifi.network.clients.listAll(siteId).pages()) {\n  console.log(pageItems.length);\n}\n\nconst first200 = await unifi.network.clients.listAll(siteId).collect(200);\nconst first = await unifi.network.clients.listAll(siteId).first();\n```\n\n## Errors\n\nAll client errors extend `UnifiError`.\n\n| Class | When |\n| --- | --- |\n| `UnifiAuthError` | HTTP 401 or 403 |\n| `UnifiNotFoundError` | HTTP 404 |\n| `UnifiValidationError` | HTTP 400 or 422 |\n| `UnifiConflictError` | HTTP 409 |\n| `UnifiRateLimitError` | HTTP 429, with `retryAfterMs` |\n| `UnifiServerError` | HTTP 5xx |\n| `UnifiConnectionError` | Transport failure |\n| `UnifiTimeoutError` | Request timeout |\n| `UnifiConfigError` | Client misconfiguration |\n\n```ts\nimport {\n  UnifiAuthError,\n  UnifiRateLimitError,\n  isUnifiError,\n} from \"@aybouzaglou/unifi-client\";\n\ntry {\n  await unifi.network.devices.list(siteId);\n} catch (err) {\n  if (err instanceof UnifiRateLimitError) {\n    await new Promise((resolve) => setTimeout(resolve, err.retryAfterMs ?? 1000));\n  } else if (err instanceof UnifiAuthError) {\n    console.error(\"Bad or expired API key\");\n  } else if (isUnifiError(err)) {\n    console.error(`UniFi error ${err.status} (${err.code ?? \"unknown\"}): ${err.url}`);\n  } else {\n    throw err;\n  }\n}\n```\n\n## Local Network TLS\n\nLocal UniFi consoles commonly serve the Network integration API over HTTPS with a self-signed certificate. Node rejects that certificate by default.\n\n```ts\nimport { NetworkClient } from \"@aybouzaglou/unifi-client/network\";\n\nconst net = new NetworkClient({\n  host: \"192.168.1.1\",\n  apiKey: process.env.UNIFI_NET_KEY!,\n  allowInsecureTLS: true,\n});\n```\n\nOnly use `allowInsecureTLS` for consoles you control on trusted networks. For a stricter setup, pass your own `undici` dispatcher or custom `fetch` implementation with pinned trust.\n\n```ts\nimport { Agent } from \"undici\";\nimport { NetworkClient } from \"@aybouzaglou/unifi-client/network\";\n\nconst dispatcher = new Agent({\n  connect: { ca: myConsoleCaPem },\n});\n\nconst net = new NetworkClient({\n  host: \"unifi.example.com\",\n  apiKey: process.env.UNIFI_NET_KEY!,\n  dispatcher,\n});\n```\n\n## Cloud Connector Proxy\n\nWhen you do not have a LAN path to a console, route Network API calls through UniFi's Cloud Connector Proxy:\n\n```ts\nimport { UnifiClient } from \"@aybouzaglou/unifi-client\";\n\nconst unifi = new UnifiClient({\n  siteManager: { apiKey: process.env.UNIFI_CLOUD_KEY! },\n});\n\nconst { data: hosts } = await unifi.siteManager.hosts.list();\nconst remote = unifi.connector(hosts[0]!.id!);\n\nconst siteId = await remote.sites.findId(\"default\");\nif (!siteId) throw new Error(\"Default site not found\");\n\nconst clients = await remote.clients.listAll(siteId).collect(100);\n```\n\nConnector Proxy mode uses your Site Manager key, not a per-console Network key. The target console must support UniFi's connector proxy route.\n\n## Per-request Options\n\nMost methods accept a final options object:\n\n```ts\nawait unifi.network.devices.list(\n  siteId,\n  { limit: 100 },\n  {\n    signal: controller.signal,\n    timeoutMs: 5_000,\n    headers: { \"X-Trace\": \"abc\" },\n    maxRetries: 2,\n  },\n);\n```\n\nRetries apply to transient transport errors, timeouts, HTTP 429, and HTTP 5xx responses. `Retry-After` is honored when the server sends it.\n\n## API Surface\n\nSee [API-SURFACE.md](./API-SURFACE.md) for the method map. The generated OpenAPI types are exported as:\n\n```ts\nimport type {\n  NetworkOperations,\n  SiteManagerOperations,\n} from \"@aybouzaglou/unifi-client\";\n```\n\n## Versioned Specs\n\nThe bundled specs in `openapi/` are the source for generated types:\n\n- Site Manager API `v1.0.0`\n- Network API `v10.3.58`\n\nRegenerate types after replacing either JSON file:\n\n```bash\npnpm run generate\n```\n\n## Development\n\n```bash\npnpm install\npnpm run verify\nnpm pack --dry-run\n```\n\n`pnpm run verify` runs typecheck, example typecheck, tests, coverage, and build.\n\n## License\n\n[MIT](./LICENSE)\n","readmeFilename":"README.md","_rev":"1-80c83c91a80f930cba7aaf2e85ea2ce1"}