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

@aybouzaglou/unifi-client

v0.1.0

Published

Type-safe TypeScript client for the UniFi Site Manager API and UniFi Network API.

Readme

@aybouzaglou/unifi-client

Type-safe TypeScript client for the official UniFi Site Manager API and UniFi Network API.

  • Types generated from Ubiquiti's official OpenAPI specs.
  • Site Manager and Network APIs in one package.
  • Dual ESM/CJS builds with .d.ts declarations.
  • Platform fetch by default; optional undici dispatcher support for self-signed local-console TLS.
  • Typed error hierarchy with status, code, request id, URL, and retry metadata.
  • list() for one page, listAll() for async-iterable pagination.

Install

pnpm add @aybouzaglou/unifi-client
# or
npm install @aybouzaglou/unifi-client
# or
yarn add @aybouzaglou/unifi-client

Requires Node >=18.17 or another runtime with global fetch.

For local UniFi consoles with self-signed certificates, install the optional TLS helper dependency and set allowInsecureTLS: true:

pnpm add undici

API Keys

| API | Key location | | --- | --- | | Site Manager | Sign in at unifi.ui.com, then Settings -> API. | | Network | Open the Network app on the console, then Settings -> Control Plane -> Integrations. |

Both APIs authenticate with X-API-Key; the client sets the header for you.

Quick Start

import { UnifiClient } from "@aybouzaglou/unifi-client";

const unifi = new UnifiClient({
  siteManager: { apiKey: process.env.UNIFI_SM_KEY! },
  network: {
    host: "192.168.1.1",
    apiKey: process.env.UNIFI_NET_KEY!,
    allowInsecureTLS: true,
  },
});

const { data: hosts } = await unifi.siteManager.hosts.list();

const siteId = await unifi.network.sites.findId("default");
if (!siteId) throw new Error("Default site not found");

const clients = await unifi.network.clients.listAll(siteId).collect(100);

console.log(hosts, clients);

Standalone imports are available when you only need one API:

import { SiteManagerClient } from "@aybouzaglou/unifi-client/site-manager";
import { NetworkClient } from "@aybouzaglou/unifi-client/network";

Pagination

Every list endpoint has two shapes:

  • list(...) returns one page.
  • listAll(...) returns a Paginator<T>.
const page = await unifi.network.clients.list(siteId, { limit: 50 });
console.log(page.data, page.totalCount);

const all = unifi.network.clients.listAll(siteId);

for await (const client of all) {
  console.log(client.id);
}

for await (const pageItems of unifi.network.clients.listAll(siteId).pages()) {
  console.log(pageItems.length);
}

const first200 = await unifi.network.clients.listAll(siteId).collect(200);
const first = await unifi.network.clients.listAll(siteId).first();

Errors

All client errors extend UnifiError.

| Class | When | | --- | --- | | UnifiAuthError | HTTP 401 or 403 | | UnifiNotFoundError | HTTP 404 | | UnifiValidationError | HTTP 400 or 422 | | UnifiConflictError | HTTP 409 | | UnifiRateLimitError | HTTP 429, with retryAfterMs | | UnifiServerError | HTTP 5xx | | UnifiConnectionError | Transport failure | | UnifiTimeoutError | Request timeout | | UnifiConfigError | Client misconfiguration |

import {
  UnifiAuthError,
  UnifiRateLimitError,
  isUnifiError,
} from "@aybouzaglou/unifi-client";

try {
  await unifi.network.devices.list(siteId);
} catch (err) {
  if (err instanceof UnifiRateLimitError) {
    await new Promise((resolve) => setTimeout(resolve, err.retryAfterMs ?? 1000));
  } else if (err instanceof UnifiAuthError) {
    console.error("Bad or expired API key");
  } else if (isUnifiError(err)) {
    console.error(`UniFi error ${err.status} (${err.code ?? "unknown"}): ${err.url}`);
  } else {
    throw err;
  }
}

Local Network TLS

Local UniFi consoles commonly serve the Network integration API over HTTPS with a self-signed certificate. Node rejects that certificate by default.

import { NetworkClient } from "@aybouzaglou/unifi-client/network";

const net = new NetworkClient({
  host: "192.168.1.1",
  apiKey: process.env.UNIFI_NET_KEY!,
  allowInsecureTLS: true,
});

Only 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.

import { Agent } from "undici";
import { NetworkClient } from "@aybouzaglou/unifi-client/network";

const dispatcher = new Agent({
  connect: { ca: myConsoleCaPem },
});

const net = new NetworkClient({
  host: "unifi.example.com",
  apiKey: process.env.UNIFI_NET_KEY!,
  dispatcher,
});

Cloud Connector Proxy

When you do not have a LAN path to a console, route Network API calls through UniFi's Cloud Connector Proxy:

import { UnifiClient } from "@aybouzaglou/unifi-client";

const unifi = new UnifiClient({
  siteManager: { apiKey: process.env.UNIFI_CLOUD_KEY! },
});

const { data: hosts } = await unifi.siteManager.hosts.list();
const remote = unifi.connector(hosts[0]!.id!);

const siteId = await remote.sites.findId("default");
if (!siteId) throw new Error("Default site not found");

const clients = await remote.clients.listAll(siteId).collect(100);

Connector Proxy mode uses your Site Manager key, not a per-console Network key. The target console must support UniFi's connector proxy route.

Per-request Options

Most methods accept a final options object:

await unifi.network.devices.list(
  siteId,
  { limit: 100 },
  {
    signal: controller.signal,
    timeoutMs: 5_000,
    headers: { "X-Trace": "abc" },
    maxRetries: 2,
  },
);

Retries apply to transient transport errors, timeouts, HTTP 429, and HTTP 5xx responses. Retry-After is honored when the server sends it.

API Surface

See API-SURFACE.md for the method map. The generated OpenAPI types are exported as:

import type {
  NetworkOperations,
  SiteManagerOperations,
} from "@aybouzaglou/unifi-client";

Versioned Specs

The bundled specs in openapi/ are the source for generated types:

  • Site Manager API v1.0.0
  • Network API v10.3.58

Regenerate types after replacing either JSON file:

pnpm run generate

Development

pnpm install
pnpm run verify
npm pack --dry-run

pnpm run verify runs typecheck, example typecheck, tests, coverage, and build.

License

MIT