diff --git a/src/Services/UnifiApiClient.php b/src/Services/UnifiApiClient.php index af7a34f..d997136 100644 --- a/src/Services/UnifiApiClient.php +++ b/src/Services/UnifiApiClient.php @@ -625,8 +625,14 @@ class UnifiApiClient $http = $this->buildRequest(); } - // Try multiple URL patterns + // Endpoints, in preferred order: + // 1. UniFi OS Integration API — the one X-API-Key keys are issued for + // (response shape: [{ id, internalReference, name }]) + // 2. Legacy /proxy/network/api/self/sites — session-cookie API on + // UniFi OS consoles (response: [{ name, desc, ... }]) + // 3. Legacy /api/self/sites — standalone controller (no /proxy prefix) $paths = [ + '/proxy/network/integration/v1/sites', '/proxy/network/api/self/sites', '/api/self/sites', ]; @@ -645,11 +651,28 @@ class UnifiApiClient } $data = $response->json('data', $response->json()); - if (is_array($data) && ! empty($data) && isset($data[0]['name'])) { + if (! is_array($data) || empty($data)) { + $lastError = "No sites in response from {$path}"; + continue; + } + + // Integration API rows have `internalReference` (== legacy + // site slug) and `name` (human-readable). Normalize to + // the legacy {name, desc} shape so downstream code that + // builds URLs with the site slug keeps working. + if (isset($data[0]['internalReference'])) { + $data = array_map(fn ($s) => [ + 'name' => $s['internalReference'] ?? 'default', + 'desc' => $s['name'] ?? $s['internalReference'] ?? 'Default', + ], $data); + } + + if (isset($data[0]['name'])) { Log::debug('unifi.sites_found', ['path' => $path, 'count' => count($data)]); return $data; } - $lastError = "No sites in response from {$path}"; + + $lastError = "Unexpected response shape from {$path}"; } else { $lastError = "HTTP {$response->status()} on {$path}"; }