import json import os import httpx from dotenv import load_dotenv load_dotenv() HOST = os.environ["HOST"] BASE = f"https://{HOST}/proxy/protect/integration/v1" PRIVATE_BASE = f"https://{HOST}/proxy/protect/api" HEADERS = {"X-API-Key": os.environ["API_KEY"]} USERNAME = os.environ["UNIFI_USERNAME"] PASSWORD = os.environ["UNIFI_PASSWORD"] CAMERA_NAME = "G6 Pro 360" def main(): with httpx.Client(headers=HEADERS, verify=False) as client: cameras = client.get(f"{BASE}/cameras").raise_for_status().json() camera = next(c for c in cameras if CAMERA_NAME in c["name"]) print("=== Camera (integration API) ===") data = client.get(f"{BASE}/cameras/{camera['id']}").raise_for_status().json() print(json.dumps(data, indent=2)) print("\n=== Sensors ===") sensors = client.get(f"{BASE}/sensors").raise_for_status().json() print(json.dumps(sensors, indent=2)) # Accept-Encoding must be suppressed at request level — server returns 403 when present with httpx.Client(verify=False, http2=True) as client: res = client.post( f"https://{HOST}/api/auth/login", content=f'{{"username":"{USERNAME}","password":"{PASSWORD}","rememberMe":false}}'.encode(), headers={"Content-Type": "application/json", "Accept-Encoding": ""}, ) res.raise_for_status() print("\n=== Camera (private API) ===") data = client.get(f"{PRIVATE_BASE}/cameras/{camera['id']}").raise_for_status().json() print(json.dumps(data, indent=2)) if __name__ == "__main__": main()