Authentication
ufi authenticates to your console with a single X-API-KEY header — no OAuth, no
session cookie, no refresh token. The key is resolved from your environment or local storage
on every invocation and sent directly to the Integration API at
https://{host}/proxy/network/integration/v1.
Generate a key in the UniFi UI
Section titled “Generate a key in the UniFi UI”- Open the UniFi Network application.
- Go to Settings → Control Plane → Integrations.
- Click Create API Key, give it a label, and copy the value.
The UI shows the key once. If you close the dialog without copying it, generate a new one.
Store the key with ufi auth login
Section titled “Store the key with ufi auth login”The recommended first-time setup:
# Set the console address (permanent env var or --host on every command):export UNIFI_HOST=https://192.168.1.1
# Pipe the key in — it is validated before being stored:printf %s "$KEY" | ufi auth loginauth login reads the key from stdin, trims whitespace, validates it against GET /info
on your console, then stores the key and host. On success it emits:
{ "ok": true, "console": "https://192.168.1.1", "application_version": "10.4.57", "stored": "keyring"}The stored field tells you whether the key landed in the OS keyring ("keyring") or the
fallback credential file ("file"). Either is fine; see Credential storage
below.
Why validate before storing?
Section titled “Why validate before storing?”auth login hits the live console before saving anything. If the key or host is wrong, you
get a structured error on stderr and nothing is stored — no silent bad-credential state.
Credential precedence
Section titled “Credential precedence”On every invocation, ufi resolves credentials in this order (first match wins):
| Priority | Source | Notes |
|---|---|---|
| 1 | UNIFI_API_KEY env var |
Overrides any stored key |
| 2 | OS keyring | macOS Keychain / Linux Secret Service / Windows Credential Manager |
| 3 | $XDG_CONFIG_HOME/ufi/credentials |
0600 file, JSON; path is ~/.config/ufi/credentials when XDG_CONFIG_HOME is unset |
The host is resolved the same way: --host flag or UNIFI_HOST env var override whatever
auth login stored.
In CI and containers, set UNIFI_API_KEY and UNIFI_HOST directly — no keyring, no file,
no prior auth login step needed:
export UNIFI_HOST=https://192.168.1.1export UNIFI_API_KEY=my-keyufi device list --jsonCredential storage
Section titled “Credential storage”ufi auth login writes to the OS keyring (macOS Keychain, Linux Secret Service via
libsecret, Windows Credential Manager) when one is available. On headless hosts with no
keyring backend, it falls back to a 0600 JSON file at
$XDG_CONFIG_HOME/ufi/credentials (typically ~/.config/ufi/credentials).
The file fallback is intentional — ufi never prompts for a keyring passphrase, which would deadlock a non-interactive agent. The keyring backends used are OS-native only.
ufi doctor and ufi auth status warn if the credential file exists with permissions looser
than 0600:
warning: credential file is group/other readable: /home/you/.config/ufi/credentialsFix it with:
chmod 600 ~/.config/ufi/credentialsufi auth status
Section titled “ufi auth status”Check whether a key is configured and whether it works against the live console:
ufi auth status --jsonExample — key valid:
{ "console": "https://192.168.1.1", "has_local_key": true, "has_cloud_key": false, "source": "keyring", "valid": true, "application_version": "10.4.57"}Example — key stored but console unreachable:
{ "console": "https://192.168.1.1", "has_local_key": true, "has_cloud_key": false, "source": "file", "valid": false, "reason": "connection refused"}Key behaviours to note:
valid: falsewith areasonexits 0 — the key is stored andauth statusran successfully; the connectivity issue is surfaced as data, not a process failure. This lets an agent distinguish “no key at all” from “console temporarily unreachable”.- The stored key is never printed.
auth statusonly reports whether it is present and valid. - If no key is configured at all,
auth statusreturnsAUTH_REQUIRED(exit 4) with a remediation hint — see AUTH_REQUIRED below.
ufi auth logout
Section titled “ufi auth logout”Remove locally stored credentials:
ufi auth logout{ "ok": true, "cleared": true}auth logout removes the key from both the OS keyring and the credential file. It does
not revoke the key on the console — it remains valid until you delete it in
Settings → Control Plane → Integrations → API Keys. If you suspect a key has leaked,
revoke it on the console first, then run auth logout to clean up locally.
ufi auth refresh
Section titled “ufi auth refresh”ufi auth refreshThis is a no-op: UniFi Integration API keys do not expire and have no refresh flow.
{ "ok": true, "refreshed": false}It exists so scripts and agents that call auth refresh as a routine step do not need
a special case for ufi.
AUTH_REQUIRED (exit 4)
Section titled “AUTH_REQUIRED (exit 4)”Any command that needs the API — including auth status when no key is stored — returns a
structured error on stderr and exits 4:
{ "error": "no UniFi API key configured", "code": "AUTH_REQUIRED", "remediation": "run `ufi auth login`, or set UNIFI_API_KEY and --host/UNIFI_HOST"}Exit 4 is distinct and stable, so an agent can branch on it without parsing the message text. See Exit codes for the full table.
Self-signed console certificates
Section titled “Self-signed console certificates”UniFi consoles ship a self-signed TLS certificate. By default, ufi rejects it and exits
with a TLS verification error. Use --insecure or UNIFI_INSECURE=1 to skip verification:
# flag (per-command):ufi device list --insecure --json
# env var (session-wide):export UNIFI_INSECURE=1ufi device list --jsonWhen --insecure is active, ufi warns loudly on every invocation to stderr:
warning: TLS verification disabled (--insecure / UNIFI_INSECURE); the console's identity is not verifiedThis is intentional: --insecure is an escape hatch, not a recommended steady state.
Consider installing your console’s certificate in your system trust store instead.
ufi doctor
Section titled “ufi doctor”Run a full pre-flight diagnostic before doing any real work:
ufi doctor --jsonExample output (all checks passing):
{ "ok": true, "checks": [ { "name": "host", "ok": true, "detail": "https://192.168.1.1" }, { "name": "api_key", "ok": true, "detail": "present (redacted), source=keyring" }, { "name": "connectivity", "ok": true, "detail": "console reachable, key valid, version 10.4.57" } ]}Example output (key missing):
{ "ok": false, "checks": [ { "name": "host", "ok": true, "detail": "https://192.168.1.1" }, { "name": "api_key", "ok": false, "detail": "not set", "fix": "pipe a key to `ufi auth login` or set UNIFI_API_KEY" }, { "name": "connectivity", "ok": false, "detail": "skipped — host/key missing", "fix": "configure host + key first" } ]}When any check fails, ufi doctor exits with CONFIG_ERROR (exit 10) and each failing
check carries a fix field with the next action. When the credential file has loose
permissions, a cred_perms check is added automatically with the chmod 600 fix.
ufi doctor is the fastest path to a working setup — run it whenever you change hosts, rotate
a key, or move to a new machine.
What to do if a key leaks
Section titled “What to do if a key leaks”- Revoke it on the console (Settings → Control Plane → Integrations → API Keys). Local
auth logoutdoes not revoke the key — only the console can do that. - Generate a replacement key.
- Run
ufi auth logoutto clear the old local copy. - Run
printf %s "$NEW_KEY" | ufi auth loginwith the new key. - Run
ufi doctor --jsonto verify the new key works.
Never paste a real key into a GitHub issue. See the SECURITY.md for the private vulnerability reporting process.
Related pages
Section titled “Related pages”- Getting started — install ufi and run the first command.
- Safety model — how
--allow-mutations,--dry-run, and the reviewed-apply flow bound what an agent can do with a valid key. - Flags & environment variables —
UNIFI_HOST,UNIFI_SITE,UNIFI_INSECURE, and other env vars. - Exit codes — the full stable exit-code table, including exit 4
(
AUTH_REQUIRED). - For agents — the full agent contract, including credential handling and
ufi schema.