go-unifi

UniFi API (OpenAPI)

Overview of the Official UniFi Network API (integration/v1) — base path, API-key auth, the filter DSL, and the error model.

This section renders the Official UniFi Network API — the controller's own OpenAPI document (integration/v1, spec version 10.1.85) — endpoint by endpoint. go-unifi calls this surface for you through c.Official(); the pages here are the canonical HTTP-level reference, and each one shows the equivalent Go call.

Each UniFi application exposes these endpoints locally, per site, for analytics and control of that application. For high-level insight across all your sites instead, see the separate UniFi Site Manager API.

Base path

The OpenAPI document declares its server as /integration and versions every path under /v1 (e.g. /v1/sites/{siteId}/networks). On a UniFi OS controller the integration API is mounted under /proxy/network, so the full runtime base path is:

/proxy/network/integration/v1

You never assemble these paths yourself — the official wrappers build them from the site UUID and resource IDs.

Authentication

Every request authenticates with an API key, sent in the X-Api-Key HTTP header (exact casing). Generate one from the Integrations section of your UniFi application. go-unifi attaches it automatically from ClientConfig.APIKey — see Authentication.

API-key auth requires controller 9.0.114 or newer; the Official API surface specifically requires 10.1.78 or newer. Username/password auth is not supported.

Filtering

Some GET and DELETE list endpoints accept a filter query parameter for server-side querying. Each endpoint that supports it documents its filterable properties. In Go, set official.ListOptions.Filter (or pass the filter argument to a …All iterator); the string is forwarded verbatim.

filter.go
package main

import (
	"context"
	"log"

	"github.com/filipowm/go-unifi/v2/unifi"
	"github.com/filipowm/go-unifi/v2/unifi/official"
)

func main() {
	ctx := context.Background()
	c, err := unifi.NewClient(&unifi.ClientConfig{URL: "https://unifi.example.com", APIKey: "your-api-key"})
	if err != nil {
		log.Fatal(err)
	}
	siteID, err := c.Official().Sites().ResolveID(ctx, "default")
	if err != nil {
		log.Fatal(err)
	}

	page, err := c.Official().Clients().ListConnectedPage(ctx, siteID, &official.ListOptions{
		Filter: "and(type.eq('WIRELESS'), access.authorized.eq(true))",
	})
	if err != nil {
		log.Fatal(err)
	}
	log.Printf("%d matching clients", page.Count)
}

Syntax

The filter DSL is URL-safe and has three kinds of expression:

  1. Property expressions<property>.<function>(<args>), e.g. id.eq(123), name.isNotNull(), createdAt.in(2025-01-01, 2025-01-05).
  2. Compound expressions — combine with and(...) / or(...), e.g. and(name.isNull(), createdAt.gt(2025-01-01)).
  3. Negationnot(<expression>), e.g. not(name.like('guest*')).

Property types

TypeExampleSyntax
STRING'Hello, ''World''!'Wrap in single quotes; escape a quote by doubling it.
INTEGER123Must start with a digit.
DECIMAL123.321Digit-leading; may include a ..
TIMESTAMP2025-01-29T12:39:11ZISO 8601 date or date-time.
BOOLEANtrue, false
UUID550e8400-e29b-41d4-a716-446655440000Standard 8-4-4-4-12 form.
SET(...)[1, 2, 3]A set of unique values.

Functions

FunctionArgsMeaningTypes
isNull / isNotNull0(not) nullall
eq / ne1(not) equalsSTRING, INTEGER, DECIMAL, TIMESTAMP, BOOLEAN, UUID
gt / ge / lt / le1ordering comparisonsSTRING, INTEGER, DECIMAL, TIMESTAMP, UUID
like1pattern matchSTRING
in / notIn1+(not) one ofSTRING, INTEGER, DECIMAL, TIMESTAMP, UUID
isEmpty0empty setSET
contains1set membershipSET
containsAny / containsAll / containsExactly1+set membershipSET

In a like pattern, . matches a single character, * matches any number of characters, and \ escapes a literal . or * — e.g. name.like('guest*') matches guest1 and guest100.

Error model

Failed requests return a standard JSON error body:

{
  "statusCode": 401,
  "statusName": "UNAUTHORIZED",
  "code": "api.authentication.missing-credentials",
  "message": "Missing credentials",
  "timestamp": "2024-11-27T08:13:46.966Z",
  "requestPath": "/integration/v1/sites/123",
  "requestId": "3fa85f64-5717-4562-b3fc-2c963f66afa6"
}

code is a stable machine-readable identifier; statusName mirrors the HTTP status; and on a 500, requestId lets you correlate the failure with the controller's server log. With go-unifi's default transport these surface as *unifi.ServerError, so errors.Is(err, unifi.ErrNotFound) detects 404s and errors.As exposes the structured fields.

Endpoints

The pages in this section are grouped by API tag — Application Info, Sites, UniFi Devices, Clients, Networks, WiFi Broadcasts, Hotspot, Firewall, Access Control (ACL Rules), DNS Policies, Traffic Matching Lists, and Supporting Resources — and listed in the sidebar. Every operation page documents its HTTP method, path, parameters, and schemas, alongside the matching c.Official() Go call.

On this page