Settings
Read and write site-level controller settings — the typed per-setting pairs and the generic key-based GetSetting/SetSetting.
UniFi groups site-wide configuration into settings, each identified by a string key
(guest_access, mgmt, usg, …). go-unifi exposes them two ways: a typed pair per setting
for compile-time safety, and a generic key-based pair when you need to be dynamic. Both
operate on the site name ("default").
These examples assume a constructed client c and a ctx — see the
Quickstart.
Typed settings (recommended)
Each setting has a GetSetting<X> / UpdateSetting<X> pair that returns and accepts a concrete
struct — no key strings, no type assertions. Guest access is a typical example:
func exampleGuestAccessSetting(ctx context.Context, c unifi.Client) error {
// Typed pair: no key string, no type assertion — you get *SettingGuestAccess.
ga, err := c.GetSettingGuestAccess(ctx, "default")
if err != nil {
return fmt.Errorf("get guest access setting: %w", err)
}
ga.PortalEnabled = true
ga.PortalCustomized = true
ga.PortalCustomizedSuccessText = "Welcome to the network!"
updated, err := c.UpdateSettingGuestAccess(ctx, "default", ga)
if err != nil {
return fmt.Errorf("update guest access setting: %w", err)
}
fmt.Printf("portal enabled: %v\n", updated.PortalEnabled)
return nil
}The signatures follow a fixed shape for every setting X:
GetSettingX(ctx context.Context, site string) (*SettingX, error)
UpdateSettingX(ctx context.Context, site string, s *SettingX) (*SettingX, error)There is no create or delete — a setting always exists for a site, so you read-modify-write:
fetch the current value, change the fields you care about, and pass it back to UpdateSettingX.
The wrapper sets the Key field for you, so you never touch it.
There are dozens of typed settings (SettingGuestAccess, SettingMgmt, SettingUsg,
SettingCountry, …). Browse the full catalogue, each struct's fields, and its key constant in the
settings reference.
Generic settings
When the key is only known at runtime — or you want to round-trip a setting you don't have a
typed accessor for — use the generic pair. GetSetting returns the lightweight *Setting
envelope and an any holding the concrete fields struct; assert it to the type that matches
the key. SetSetting takes the modified value back.
func exampleGenericSetting(ctx context.Context, c unifi.Client) error {
// Generic pair: GetSetting returns the *Setting envelope plus an `any`
// holding the concrete fields struct for the key. Assert it to use it.
setting, fields, err := c.GetSetting(ctx, "default", unifi.SettingGuestAccessKey)
if err != nil {
return fmt.Errorf("get setting: %w", err)
}
ga, ok := fields.(*unifi.SettingGuestAccess)
if !ok {
return fmt.Errorf("unexpected setting type %T", fields)
}
fmt.Printf("setting %s portal_enabled=%v\n", setting.Key, ga.PortalEnabled)
ga.PortalEnabled = false
result, err := c.SetSetting(ctx, "default", unifi.SettingGuestAccessKey, ga)
if err != nil {
return fmt.Errorf("set setting: %w", err)
}
_ = result // also the concrete fields struct as `any`
return nil
}The generic signatures are:
GetSetting(ctx context.Context, site, key string) (*Setting, any, error)
SetSetting(ctx context.Context, site, key string, reqBody any) (any, error)The any returned by both calls is the same concrete pointer the typed accessor would give
you (here *unifi.SettingGuestAccess) — go-unifi looks up the key in its generated registry and
unmarshals into the right struct. An unknown key yields an error; a key with no matching record
yields unifi.ErrNotFound.
Prefer the typed pair whenever one exists — the generic API hands you an any, so a wrong type
assertion is a runtime bug rather than a compile error. Reach for GetSetting/SetSetting only
when the key is dynamic. Use the exported key constants (e.g. unifi.SettingGuestAccessKey)
rather than hand-typed strings.
Next steps
Wireless
Manage WLANs, AP and WLAN groups, RADIUS profiles, channel plans, and the guest hotspot — including Official-API vouchers and broadcasts.
Feature Flags
Check whether a UniFi controller supports and enables a capability before you rely on it, using IsFeatureEnabled, GetFeature, and ListFeatures.