From e360546de9f87c6401f136f10ac53c198c354c40 Mon Sep 17 00:00:00 2001 From: ducoterra Date: Sat, 1 Aug 2026 19:07:05 -0400 Subject: [PATCH] init --- .env.example | 15 + .gitea/workflows/build-push.yml | 41 + .gitignore | 16 + .python-version | 1 + .vscode/launch.json | 24 + AGENTS.md | 42 + Containerfile | 23 + README.md | 124 + ip_lookup.py | 24 + main.py | 371 + network_v10.4.57_openapi.json | 13810 ++++++++++++++++++++++++++++++ pyproject.toml | 27 + tests/test_ip_lookup.py | 47 + tests/test_main.py | 226 + tests/test_unifi_firewall.py | 299 + unifi_firewall.py | 334 + uv.lock | 307 + 17 files changed, 15731 insertions(+) create mode 100644 .env.example create mode 100644 .gitea/workflows/build-push.yml create mode 100644 .gitignore create mode 100644 .python-version create mode 100644 .vscode/launch.json create mode 100644 AGENTS.md create mode 100644 Containerfile create mode 100644 README.md create mode 100644 ip_lookup.py create mode 100644 main.py create mode 100644 network_v10.4.57_openapi.json create mode 100644 pyproject.toml create mode 100644 tests/test_ip_lookup.py create mode 100644 tests/test_main.py create mode 100644 tests/test_unifi_firewall.py create mode 100644 unifi_firewall.py create mode 100644 uv.lock diff --git a/.env.example b/.env.example new file mode 100644 index 0000000..b93b942 --- /dev/null +++ b/.env.example @@ -0,0 +1,15 @@ +# UniFi Controller +UNIFI_HOST=https://your-unifi-host +UNIFI_SITE_ID=your-site-id +UNIFI_API_TOKEN=your-api-token +UNIFI_VERIFY_SSL=false + +# Config +CONFIG_FILE=config/rules.yaml +LOG_LEVEL=INFO +DEBUG=false + +# NTFY Notifications (optional) +NTFY_URL= +NTFY_TOPIC= +NTFY_API_KEY= diff --git a/.gitea/workflows/build-push.yml b/.gitea/workflows/build-push.yml new file mode 100644 index 0000000..e2e81c4 --- /dev/null +++ b/.gitea/workflows/build-push.yml @@ -0,0 +1,41 @@ +name: Build and Push Container + +on: + push: + branches: + - main + release: + types: + - published + +jobs: + build-and-push: + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Login to Gitea Container Registry + uses: docker/login-action@v3 + with: + registry: gitea.reeseapps.com + username: ${{ secrets.REGISTRY_USERNAME }} + password: ${{ secrets.REGISTRY_PASSWORD }} + + - name: Extract metadata + id: meta + uses: docker/metadata-action@v5 + with: + images: gitea.reeseapps.com/services/firewall + tags: | + type=raw,value=main,enable=${{ github.ref == 'refs/heads/main' }} + type=ref,event=tag + + - name: Build and push + uses: docker/build-push-action@v6 + with: + context: . + file: ./Containerfile + push: true + tags: ${{ steps.meta.outputs.tags }} + labels: ${{ steps.meta.outputs.labels }} diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..3810e86 --- /dev/null +++ b/.gitignore @@ -0,0 +1,16 @@ +# Python-generated files +__pycache__/ +*.py[oc] +build/ +dist/ +wheels/ +*.egg-info + +# Virtual environments +.venv + +.env + +.pytest_cache/ +.ruff_cache/ +config/ \ No newline at end of file diff --git a/.python-version b/.python-version new file mode 100644 index 0000000..24ee5b1 --- /dev/null +++ b/.python-version @@ -0,0 +1 @@ +3.13 diff --git a/.vscode/launch.json b/.vscode/launch.json new file mode 100644 index 0000000..ad31862 --- /dev/null +++ b/.vscode/launch.json @@ -0,0 +1,24 @@ +{ + // Use IntelliSense to learn about possible attributes. + // Hover to view descriptions of existing attributes. + // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 + "version": "0.2.0", + "configurations": [ + + { + "name": "Python Debugger: Remote Attach", + "type": "debugpy", + "request": "attach", + "connect": { + "host": "localhost", + "port": 5678 + }, + "pathMappings": [ + { + "localRoot": "${workspaceFolder}", + "remoteRoot": "." + } + ] + } + ] +} \ No newline at end of file diff --git a/AGENTS.md b/AGENTS.md new file mode 100644 index 0000000..3efefe2 --- /dev/null +++ b/AGENTS.md @@ -0,0 +1,42 @@ +# AGENTS.md + +## Dev commands (always run all three) + +```bash +uv run pytest -v # 35 tests, all mocked (no live API calls) +uv run ruff check # lint +uv run pyright # strict type checking +``` + +Order matters: fix lint/typecheck errors before touching tests. + +## Architecture + +- `main.py` — entry point: load config → fetch public IPs → process rules → NTFY notify +- `unifi_firewall.py` — UniFi Network API v1 client (TypedDicts match `network_v10.4.57_openapi.json`) +- `ip_lookup.py` — fetches public IPv4/IPv6 via `curl ifconfig.me` +- `config/rules.yaml` — rule definitions (zones, IPs, ports, actions) + +API base: `{UNIFI_HOST}/proxy/network/integration/v1/sites/{UNIFI_SITE_ID}`. Auth: `X-API-Key` header. + +## Env vars + +Required: `UNIFI_HOST`, `UNIFI_SITE_ID`, `UNIFI_API_TOKEN` +Optional: `CONFIG_FILE` (default: `config/rules.yaml`), `UNIFI_VERIFY_SSL`, `LOG_LEVEL`, `DEBUG`, `NTFY_URL`, `NTFY_TOPIC`, `NTFY_API_KEY` + +See `.env.example` for full list. Shared UniFi creds with `../ddns`. + +## Testing + +All tests are unit tests with mocks. No live API calls, no external services needed. + +To run a single file: `uv run pytest tests/test_unifi_firewall.py -v` +To run a single test: `uv run pytest tests/test_unifi_firewall.py::TestBuildPolicyPayload::test_with_dest_ports -v` + +## Containerfile + +Builds with podman, uses uv to sync deps. CMD runs `main.py` as a one-shot. Config is baked in at build time via `COPY config/`. + +## OpenAPI spec + +`network_v10.4.57_openapi.json` is the source of truth for API schemas. TypedDicts in `unifi_firewall.py` must match it. When adding fields, verify against the spec first. diff --git a/Containerfile b/Containerfile new file mode 100644 index 0000000..bb5d9f5 --- /dev/null +++ b/Containerfile @@ -0,0 +1,23 @@ +FROM python:3.13-slim-bookworm + +# The installer requires curl (and certificates) to download the release archive +RUN apt-get update && apt-get install -y --no-install-recommends curl ca-certificates + +# Download the latest installer +ADD https://astral.sh/uv/install.sh /uv-installer.sh + +# Run the installer then remove it +RUN sh /uv-installer.sh && rm /uv-installer.sh + +# Ensure the installed binary is on the `PATH` +ENV PATH="/root/.local/bin/:$PATH" + +# Copy the project into the container (config is mounted at runtime) +COPY pyproject.toml uv.lock main.py unifi_firewall.py ip_lookup.py /app/ + +# Sync the project into a new environment, using the frozen lockfile +WORKDIR /app +RUN uv sync --frozen + +# Run the firewall update script +CMD ["uv", "run", "main.py"] diff --git a/README.md b/README.md new file mode 100644 index 0000000..0538531 --- /dev/null +++ b/README.md @@ -0,0 +1,124 @@ +# UniFi Firewall Updater + +Automatically updates UniFi Dream Machine firewall rules with your current public IPv4 and IPv6 addresses via the UniFi Network API. + +## Overview + +This tool: + +- Fetches your public IPv4 and IPv6 addresses +- Reads firewall rule definitions from a YAML config file +- Creates or updates policies on your UniFi controller to use those addresses +- Optionally sends notifications via NTFY when rules change + +Designed to run as a one-shot script (e.g., via cron or systemd timer) whenever your public IP changes. + +## Quick Start + +1. Copy `.env.example` to `.env` and fill in your UniFi credentials +2. Edit `config/rules.yaml` to define your firewall rules +3. Install dependencies and run: + +```bash +uv sync +uv run main.py +``` + +## Configuration + +### Environment Variables + +| Variable | Required | Description | +| ------------------ | -------- | -------------------------------------------------------- | +| `UNIFI_HOST` | Yes | UniFi controller URL (e.g., `https://10.1.0.1`) | +| `UNIFI_SITE_ID` | Yes | UniFi site ID | +| `UNIFI_API_TOKEN` | Yes | UniFi Network API token | +| `UNIFI_VERIFY_SSL` | No | Verify SSL certificates (default: `false`) | +| `CONFIG_FILE` | No | Path to rules YAML (default: `config/rules.yaml`) | +| `LOG_LEVEL` | No | Log level: DEBUG, INFO, WARNING, ERROR (default: `INFO`) | +| `DEBUG` | No | Attach debugpy on port 5678 (default: `false`) | +| `NTFY_URL` | No | NTFY server URL for notifications | +| `NTFY_TOPIC` | No | NTFY topic to publish to | +| `NTFY_API_KEY` | No | NTFY API key for authentication | + +### Rules YAML + +Each rule defines a firewall policy that will use your public IP as the source: + +```yaml +rules: + - name: "Allow External to Gateway HTTP(S)" + source_zone: "External" + dest_zone: "DMZ" + ip_version: "IPV6" + action: "ALLOW" + allow_return_traffic: true + protocol: "tcp" + dest_ports: [80, 443] + dest_port_ranges: + - start: 8000 + stop: 8080 + logging_enabled: false + enabled: true +``` + +| Field | Required | Description | +| ---------------------- | -------- | ------------------------------------------------ | +| `name` | Yes | Unique policy name | +| `source_zone` | Yes | Source zone name (e.g., `WAN`, `External`) | +| `dest_zone` | Yes | Destination zone name (e.g., `LAN`, `DMZ`) | +| `ip_version` | No | `IPV4` or `IPV6` (default: `IPV4`) | +| `action` | No | `ALLOW`, `BLOCK`, or `REJECT` (default: `ALLOW`) | +| `allow_return_traffic` | No | Allow return traffic (default: `true`) | +| `protocol` | No | Protocol filter (e.g., `tcp`, `udp`) | +| `dest_ports` | No | List of destination ports | +| `dest_port_ranges` | No | List of `{start, stop}` port ranges | +| `logging_enabled` | No | Enable policy logging (default: `false`) | +| `enabled` | No | Enable the policy (default: `true`) | + +## Development + +```bash +uv run pytest -v # Run tests (all mocked, no live API calls) +uv run ruff check # Lint +uv run pyright # Type check (strict mode) +``` + +Run a single test: + +```bash +uv run pytest tests/test_unifi_firewall.py::TestBuildPolicyPayload::test_with_dest_ports -v +``` + +## Container + +Build and run with Podman: + +```bash +podman build -t unifi-firewall . +podman run --env-file .env -v $(pwd)/config:/app/config unifi-firewall +``` + +Config is mounted at runtime via volume. Environment variables are passed at runtime. + +## How It Works + +1. Loads rules from `config/rules.yaml` +2. Fetches public IPv4/IPv6 via `curl ifconfig.me` +3. Lists zones from UniFi to resolve zone names to IDs +4. For each rule: + - Finds existing policy by name + - Skips if IP already matches + - Updates if policy exists with different IP + - Creates if policy does not exist +5. Sends NTFY notification if rules were created, updated, or failed + +## API Details + +Uses UniFi Network API v1 at: + +``` +{UNIFI_HOST}/proxy/network/integration/v1/sites/{UNIFI_SITE_ID} +``` + +Authentication via `X-API-Key` header. See `network_v10.4.57_openapi.json` for the full schema. diff --git a/ip_lookup.py b/ip_lookup.py new file mode 100644 index 0000000..90b3ade --- /dev/null +++ b/ip_lookup.py @@ -0,0 +1,24 @@ +"""Public IP address lookup via ifconfig.me.""" + +import logging +import subprocess + +logger = logging.getLogger(__name__) + + +def get_ipv4() -> str: + """Fetch public IPv4 address from ifconfig.me.""" + logger.debug("Executing: curl -4 ifconfig.me") + result = subprocess.run(["curl", "-4", "ifconfig.me"], capture_output=True, text=True, check=False) + ip = result.stdout.strip() + logger.debug("IPv4 response: %s", ip) + return ip + + +def get_ipv6() -> str: + """Fetch public IPv6 address from ifconfig.me.""" + logger.debug("Executing: curl -6 ifconfig.me") + result = subprocess.run(["curl", "-6", "ifconfig.me"], capture_output=True, text=True, check=False) + ip = result.stdout.strip() + logger.debug("IPv6 response: %s", ip) + return ip diff --git a/main.py b/main.py new file mode 100644 index 0000000..225f221 --- /dev/null +++ b/main.py @@ -0,0 +1,371 @@ +""" +UniFi firewall rule updater. + +Updates UniFi Dream Machine firewall rules with the host machine's public +IPv4 and IPv6 addresses via the UniFi Network API. + +Exported env vars: + UNIFI_HOST - UniFi controller URL (e.g., https://10.1.0.1) + UNIFI_SITE_ID - UniFi site ID + UNIFI_API_TOKEN - UniFi API token + UNIFI_VERIFY_SSL - verify SSL certificates (default: false) + CONFIG_FILE - path to YAML file with firewall rules (default: config/rules.yaml) + LOG_LEVEL - logging level (DEBUG, INFO, WARNING, ERROR; default: INFO) + DEBUG - if true, starts debugpy and waits for a remote debugger connection on port 5678 + NTFY_URL - NTFY notification server URL + NTFY_TOPIC - NTFY topic to send notifications to + NTFY_API_KEY - NTFY API key for authentication +""" + +from __future__ import annotations + +import os +import sys + +import logging +from typing import Literal, TypedDict + +import requests +import yaml +from dotenv import load_dotenv + +from ip_lookup import get_ipv4, get_ipv6 +from unifi_firewall import ( + FirewallZone, + build_policy_payload, + create_policy, + get_session, + get_source_ip_from_policy, + list_policies, + list_zones, + update_policy, +) + +load_dotenv() + +DEBUG = os.getenv("DEBUG", "false").lower() == "true" +if DEBUG: + import debugpy # noqa: T100 + + debugpy.listen(("0.0.0.0", 5678)) # noqa: T100 + print("DEBUG: debugpy listening on 0.0.0.0:5678, waiting for debugger to attach...") + debugpy.wait_for_client() # noqa: T100 + print("DEBUG: debugger attached, resuming execution...") + + +try: + from yaml import CLoader as Loader +except ImportError: + from yaml import Loader # type: ignore[attr-defined] + +log_level = os.getenv("LOG_LEVEL", "INFO").upper() + +logging.basicConfig( + level=log_level, + format="%(asctime)s.%(msecs)03d %(levelname)s %(module)s - %(funcName)s: %(message)s", + datefmt="%Y-%m-%d %H:%M:%S", +) +logger = logging.getLogger(__name__) +logger.setLevel(log_level) + +UNIFI_HOST = os.getenv("UNIFI_HOST") +UNIFI_SITE_ID = os.getenv("UNIFI_SITE_ID") +UNIFI_API_TOKEN = os.getenv("UNIFI_API_TOKEN") +UNIFI_VERIFY_SSL = os.getenv("UNIFI_VERIFY_SSL", "false").lower() == "true" + +CONFIG_FILE = os.getenv("CONFIG_FILE", "config/rules.yaml") + +NTFY_URL = os.getenv("NTFY_URL", "") +NTFY_TOPIC = os.getenv("NTFY_TOPIC", "") +NTFY_API_KEY = os.getenv("NTFY_API_KEY", "") + + +class PortRange(TypedDict): + """Port range definition.""" + + start: int + stop: int + + +class RuleConfig(TypedDict, total=False): + """Firewall rule configuration from YAML.""" + + name: str + source_zone: str + dest_zone: str + ip_version: Literal["IPV4", "IPV6"] + action: Literal["ALLOW", "BLOCK", "REJECT"] + allow_return_traffic: bool + protocol: str | None + dest_ports: list[int] | None + dest_port_ranges: list[PortRange] | None + logging_enabled: bool + enabled: bool + + +class RulesConfig(TypedDict): + """Top-level rules configuration.""" + + rules: list[RuleConfig] + + +class RuleChange(TypedDict): + """Record of a rule change.""" + + rule_name: str + action: Literal["created", "updated", "skipped", "failed"] + ip: str + error: str | None + + +def send_ntfy_notification(title: str, message: str, priority: int = 3) -> None: + """Send an NTFY notification.""" + if not NTFY_URL or not NTFY_TOPIC: + return + try: + headers = { + "Title": title, + "Priority": str(priority), + } + if NTFY_API_KEY: + headers["Authorization"] = f"Bearer {NTFY_API_KEY}" + logger.info("Sending NTFY notification: %s", title) + response = requests.post( + f"{NTFY_URL}/{NTFY_TOPIC}", + data=message.encode(), + headers=headers, + timeout=10, + ) + response.raise_for_status() + logger.info("NTFY notification sent: %s", title) + except requests.RequestException as e: + logger.warning("Failed to send NTFY notification: %s", e) + + +def load_config(path: str) -> list[RuleConfig]: + """Load firewall rules from YAML config file.""" + logger.info("Loading config file: %s", path) + try: + with open(path) as f: + config: RulesConfig = yaml.load(f, Loader) + rules = config.get("rules", []) + logger.debug("Loaded %d rule(s) from config", len(rules)) + return rules + except FileNotFoundError as e: + logger.error("Config file not found: %s", e) + sys.exit(1) + except yaml.YAMLError as e: + logger.error("Failed to parse config file: %s", e) + sys.exit(1) + + +def build_zone_map(zones: list[FirewallZone]) -> dict[str, str]: + """Build a mapping of zone names to zone IDs.""" + zone_map: dict[str, str] = {} + for zone in zones: + zone_map[zone["name"]] = zone["id"] + logger.debug("Zone map: %s", zone_map) + return zone_map + + +def process_rule( + session: requests.Session, + host: str, + site_id: str, + rule: RuleConfig, + zone_map: dict[str, str], + public_ip: str, +) -> RuleChange: + """Process a single firewall rule: create, update, or skip.""" + rule_name = rule.get("name", "unnamed") + ip_version = rule.get("ip_version", "IPV4") + source_zone = rule.get("source_zone", "WAN") + dest_zone = rule.get("dest_zone", "LAN") + + logger.info("=== Processing rule: %s ===", rule_name) + + # Get zone IDs + src_zone_id = zone_map.get(source_zone) + dst_zone_id = zone_map.get(dest_zone) + + if not src_zone_id: + error_msg = f"Source zone '{source_zone}' not found" + logger.error(error_msg) + return {"rule_name": rule_name, "action": "failed", "ip": public_ip, "error": error_msg} + + if not dst_zone_id: + error_msg = f"Destination zone '{dest_zone}' not found" + logger.error(error_msg) + return {"rule_name": rule_name, "action": "failed", "ip": public_ip, "error": error_msg} + + # Find existing policy by name + try: + existing_policies = list_policies(session, host, site_id, name_filter=rule_name) + except Exception as e: # noqa: BLE001 + error_msg = f"Failed to list policies: {e}" + logger.error(error_msg) + return {"rule_name": rule_name, "action": "failed", "ip": public_ip, "error": error_msg} + + existing_policy = existing_policies[0] if existing_policies else None + + # Check if policy exists and IP matches + if existing_policy: + existing_ip = get_source_ip_from_policy(existing_policy) + if existing_ip == public_ip: + logger.info("Rule '%s' already has correct IP (%s), skipping", rule_name, public_ip) + return {"rule_name": rule_name, "action": "skipped", "ip": public_ip, "error": None} + + # Update existing policy + logger.info("Rule '%s' exists with IP %s, updating to %s", rule_name, existing_ip, public_ip) + try: + payload = build_policy_payload( + name=rule_name, + source_ip=public_ip, + ip_version=ip_version, # type: ignore[arg-type] + src_zone_id=src_zone_id, + dst_zone_id=dst_zone_id, + action_type=rule.get("action", "ALLOW"), # type: ignore[arg-type] + allow_return_traffic=rule.get("allow_return_traffic", True), + protocol=rule.get("protocol"), + dest_ports=rule.get("dest_ports"), + dest_port_ranges=rule.get("dest_port_ranges"), # type: ignore[arg-type] + logging_enabled=rule.get("logging_enabled", False), + enabled=rule.get("enabled", True), + ) + update_policy(session, host, site_id, existing_policy["id"], payload) + logger.info("Rule '%s' updated successfully", rule_name) + return {"rule_name": rule_name, "action": "updated", "ip": public_ip, "error": None} + except Exception as e: # noqa: BLE001 + error_msg = f"Failed to update rule: {e}" + logger.error(error_msg) + return {"rule_name": rule_name, "action": "failed", "ip": public_ip, "error": error_msg} + + # Create new policy + logger.info("Rule '%s' does not exist, creating with IP %s", rule_name, public_ip) + try: + payload = build_policy_payload( + name=rule_name, + source_ip=public_ip, + ip_version=ip_version, # type: ignore[arg-type] + src_zone_id=src_zone_id, + dst_zone_id=dst_zone_id, + action_type=rule.get("action", "ALLOW"), # type: ignore[arg-type] + allow_return_traffic=rule.get("allow_return_traffic", True), + protocol=rule.get("protocol"), + dest_ports=rule.get("dest_ports"), + dest_port_ranges=rule.get("dest_port_ranges"), # type: ignore[arg-type] + logging_enabled=rule.get("logging_enabled", False), + enabled=rule.get("enabled", True), + ) + create_policy(session, host, site_id, payload) + logger.info("Rule '%s' created successfully", rule_name) + return {"rule_name": rule_name, "action": "created", "ip": public_ip, "error": None} + except Exception as e: # noqa: BLE001 + error_msg = f"Failed to create rule: {e}" + logger.error(error_msg) + return {"rule_name": rule_name, "action": "failed", "ip": public_ip, "error": error_msg} + + +def main() -> None: + """Main entry point.""" + logger.info("=== UniFi Firewall Update Starting ===") + logger.debug("Log level: %s", log_level) + logger.debug("UNIFI_HOST: %s", UNIFI_HOST) + logger.debug("UNIFI_SITE_ID: %s", UNIFI_SITE_ID) + logger.debug("UNIFI_API_TOKEN: %s", "****" if UNIFI_API_TOKEN else "not set") + logger.debug("UNIFI_VERIFY_SSL: %s", UNIFI_VERIFY_SSL) + logger.debug("CONFIG_FILE: %s", CONFIG_FILE) + + # Validate required env vars + if not all([UNIFI_HOST, UNIFI_SITE_ID, UNIFI_API_TOKEN]): + logger.error("UNIFI_HOST, UNIFI_SITE_ID, and UNIFI_API_TOKEN must be set!") + sys.exit(1) + + assert UNIFI_HOST is not None + assert UNIFI_SITE_ID is not None + assert UNIFI_API_TOKEN is not None + + # Load config + rules = load_config(CONFIG_FILE) + if not rules: + logger.warning("No rules found in config file") + return + + # Fetch public IPs + public_ipv4 = get_ipv4() + if not public_ipv4: + logger.error("Failed to fetch public IPv4 address") + sys.exit(1) + logger.info("Public IPv4: %s", public_ipv4) + + public_ipv6 = get_ipv6() + if not public_ipv6: + logger.error("Failed to fetch public IPv6 address") + sys.exit(1) + logger.info("Public IPv6: %s", public_ipv6) + + # Create session and list zones + session = get_session(UNIFI_HOST, UNIFI_API_TOKEN, UNIFI_VERIFY_SSL) + try: + zones = list_zones(session, UNIFI_HOST, UNIFI_SITE_ID) + except Exception as e: # noqa: BLE001 + logger.error("Failed to list firewall zones: %s", e) + sys.exit(1) + + zone_map = build_zone_map(zones) + + # Process rules + changes: list[RuleChange] = [] + + for rule in rules: + ip_version = rule.get("ip_version", "IPV4") + public_ip = public_ipv4 if ip_version == "IPV4" else public_ipv6 + + if not public_ip: + logger.warning("Skipping rule '%s': no %s address available", rule.get("name"), ip_version) + continue + + change = process_rule(session, UNIFI_HOST, UNIFI_SITE_ID, rule, zone_map, public_ip) + changes.append(change) + + # Summary + created = [c for c in changes if c["action"] == "created"] + updated = [c for c in changes if c["action"] == "updated"] + skipped = [c for c in changes if c["action"] == "skipped"] + failed = [c for c in changes if c["action"] == "failed"] + + logger.info("=== Summary ===") + logger.info("Created: %d", len(created)) + logger.info("Updated: %d", len(updated)) + logger.info("Skipped: %d", len(skipped)) + logger.info("Failed: %d", len(failed)) + + # Build NTFY message + ntfy_lines: list[str] = [] + for c in created: + ntfy_lines.append(f"+ {c['rule_name']}: {c['ip']}") + for c in updated: + ntfy_lines.append(f"~ {c['rule_name']}: {c['ip']}") + for c in failed: + ntfy_lines.append(f"! {c['rule_name']}: {c['error']}") + + if ntfy_lines: + ntfy_message = "\n".join(ntfy_lines) + has_changes = bool(created or updated) + has_failures = bool(failed) + if has_failures: + ntfy_title = "Firewall Update Failed" + ntfy_priority = 4 + elif has_changes: + ntfy_title = "Firewall Rules Updated" + ntfy_priority = 4 + else: + ntfy_title = "Firewall Rules Unchanged" + ntfy_priority = 2 + send_ntfy_notification(ntfy_title, ntfy_message, priority=ntfy_priority) + + logger.info("=== UniFi Firewall Update Complete ===") + + +if __name__ == "__main__": + main() diff --git a/network_v10.4.57_openapi.json b/network_v10.4.57_openapi.json new file mode 100644 index 0000000..3603924 --- /dev/null +++ b/network_v10.4.57_openapi.json @@ -0,0 +1,13810 @@ +{ + "components": { + "schemas": { + "ACL rule": { + "discriminator": { + "mapping": { + "IPV4": "#/components/schemas/IntegrationIpAclRuleDto", + "MAC": "#/components/schemas/IntegrationMacAclRuleDto" + }, + "propertyName": "type" + }, + "properties": { + "action": { + "description": "ACL rule action", + "enum": [ + "ALLOW", + "BLOCK" + ], + "example": "ALLOW|BLOCK", + "type": "string" + }, + "description": { + "description": "ACL rule description", + "type": "string" + }, + "destinationFilter": { + "description": "Traffic destination filter" + }, + "enabled": { + "example": true, + "type": "boolean" + }, + "enforcingDeviceFilter": { + "$ref": "#/components/schemas/ACL rule device filter", + "description": "IDs of the Switch-capable devices used to enforce the ACL rule. When null, the rule will be provisioned to all switches on the site." + }, + "id": { + "format": "uuid", + "type": "string" + }, + "index": { + "description": "ACL rule index. Lower index has higher priority", + "format": "int32", + "minimum": 0, + "type": "integer" + }, + "metadata": { + "$ref": "#/components/schemas/User defined or derived entity metadata", + "description": "Only user-defined rules can be deleted or modified" + }, + "name": { + "description": "ACL rule name", + "minLength": 1, + "type": "string" + }, + "sourceFilter": { + "description": "Traffic source filter" + }, + "type": { + "type": "string" + } + }, + "required": [ + "action", + "enabled", + "id", + "index", + "metadata", + "name", + "type" + ], + "type": "object" + }, + "ACL rule device filter": { + "discriminator": { + "mapping": { + "DEVICES": "#/components/schemas/IntegrationAclRuleDevicesFilterDto" + }, + "propertyName": "type" + }, + "properties": { + "type": { + "type": "string" + } + }, + "required": [ + "type" + ] + }, + "ACL rule ordering": { + "properties": { + "orderedAclRuleIds": { + "items": { + "format": "uuid", + "type": "string" + }, + "type": "array" + } + }, + "required": [ + "orderedAclRuleIds" + ], + "type": "object" + }, + "ACL rule update": { + "discriminator": { + "mapping": { + "IPV4": "#/components/schemas/IntegrationIpAclRuleCreateUpdateDto", + "MAC": "#/components/schemas/IntegrationMacAclRuleCreateUpdateDto" + }, + "propertyName": "type" + }, + "properties": { + "action": { + "description": "ACL rule action", + "enum": [ + "ALLOW", + "BLOCK" + ], + "example": "ALLOW|BLOCK", + "type": "string" + }, + "description": { + "description": "ACL rule description", + "type": "string" + }, + "destinationFilter": { + "description": "Traffic destination filter" + }, + "enabled": { + "example": true, + "type": "boolean" + }, + "enforcingDeviceFilter": { + "$ref": "#/components/schemas/ACL rule device filter", + "description": "IDs of the Switch-capable devices used to enforce the ACL rule. When null, the rule will be provisioned to all switches on the site." + }, + "index": { + "deprecated": true, + "description": "ACL rule index. This property is deprecated and has no effect. Use the dedicated ACL rule reordering endpoint.", + "format": "int32", + "minimum": 0, + "type": "integer" + }, + "name": { + "description": "ACL rule name", + "minLength": 1, + "type": "string" + }, + "sourceFilter": { + "description": "Traffic source filter" + }, + "type": { + "type": "string" + } + }, + "required": [ + "action", + "enabled", + "name", + "type" + ], + "type": "object" + }, + "ACL ruleObject": { + "discriminator": { + "mapping": { + "IPV4": "#/components/schemas/IntegrationIpAclRuleDto", + "MAC": "#/components/schemas/IntegrationMacAclRuleDto" + }, + "propertyName": "type" + }, + "properties": { + "action": { + "description": "ACL rule action", + "enum": [ + "ALLOW", + "BLOCK" + ], + "example": "ALLOW|BLOCK", + "type": "string" + }, + "description": { + "description": "ACL rule description", + "type": "string" + }, + "destinationFilter": { + "description": "Traffic destination filter" + }, + "enabled": { + "example": true, + "type": "boolean" + }, + "enforcingDeviceFilter": { + "$ref": "#/components/schemas/ACL rule device filter", + "description": "IDs of the Switch-capable devices used to enforce the ACL rule. When null, the rule will be provisioned to all switches on the site." + }, + "id": { + "format": "uuid", + "type": "string" + }, + "index": { + "description": "ACL rule index. Lower index has higher priority", + "format": "int32", + "minimum": 0, + "type": "integer" + }, + "metadata": { + "$ref": "#/components/schemas/User defined or derived entity metadata", + "description": "Only user-defined rules can be deleted or modified" + }, + "name": { + "description": "ACL rule name", + "minLength": 1, + "type": "string" + }, + "sourceFilter": { + "description": "Traffic source filter" + }, + "type": { + "type": "string" + } + }, + "required": [ + "action", + "enabled", + "id", + "index", + "metadata", + "name", + "type" + ], + "type": "object" + }, + "Access point feature overview": {}, + "Address IPv4 matching": { + "allOf": [ + { + "$ref": "#/components/schemas/IPv4 matching" + }, + { + "properties": { + "value": { + "description": "IPv4 address", + "example": "192.168.1.5", + "type": "string" + } + }, + "type": "object" + } + ], + "required": [ + "value" + ] + }, + "Address IPv6 matching": { + "allOf": [ + { + "$ref": "#/components/schemas/IPv6 matching" + }, + { + "properties": { + "value": { + "description": "IPv6 address", + "example": "2001:0db8:85a3:0000:0000:8a2e:0370:7334", + "type": "string" + } + }, + "type": "object" + } + ], + "required": [ + "value" + ] + }, + "Address range IPv4 matching": { + "allOf": [ + { + "$ref": "#/components/schemas/IPv4 matching" + }, + { + "properties": { + "start": { + "description": "IPv4 start address", + "example": "192.168.1.10", + "type": "string" + }, + "stop": { + "description": "IPv4 stop address", + "example": "192.168.1.20", + "type": "string" + } + }, + "type": "object" + } + ], + "required": [ + "start", + "stop" + ] + }, + "Adopted device details": { + "properties": { + "adoptedAt": { + "format": "date-time", + "type": "string" + }, + "configurationId": { + "example": "7596498d2f367dc2", + "type": "string" + }, + "features": { + "$ref": "#/components/schemas/Device features" + }, + "firmwareUpdatable": { + "type": "boolean" + }, + "firmwareVersion": { + "example": "6.6.55", + "type": "string" + }, + "id": { + "format": "uuid", + "type": "string" + }, + "interfaces": { + "$ref": "#/components/schemas/Device physical interfaces" + }, + "ipAddress": { + "example": "192.168.1.55", + "type": "string" + }, + "macAddress": { + "example": "94:2a:6f:26:c6:ca", + "type": "string" + }, + "model": { + "example": "UHDIW", + "type": "string" + }, + "name": { + "example": "IW HD", + "type": "string" + }, + "provisionedAt": { + "format": "date-time", + "type": "string" + }, + "state": { + "enum": [ + "ONLINE", + "OFFLINE", + "PENDING_ADOPTION", + "UPDATING", + "GETTING_READY", + "ADOPTING", + "DELETING", + "CONNECTION_INTERRUPTED", + "ISOLATED", + "U5G_INCORRECT_TOPOLOGY" + ], + "type": "string" + }, + "supported": { + "type": "boolean" + }, + "uplink": { + "$ref": "#/components/schemas/Device uplink interface overview" + } + }, + "required": [ + "configurationId", + "features", + "firmwareUpdatable", + "id", + "interfaces", + "ipAddress", + "macAddress", + "model", + "name", + "state", + "supported" + ], + "type": "object" + }, + "Adopted device overview": { + "properties": { + "features": { + "items": { + "enum": [ + "switching", + "accessPoint", + "gateway" + ], + "type": "string" + }, + "type": "array", + "uniqueItems": true + }, + "firmwareUpdatable": { + "type": "boolean" + }, + "firmwareVersion": { + "example": "6.6.55", + "type": "string" + }, + "id": { + "format": "uuid", + "type": "string" + }, + "interfaces": { + "items": { + "enum": [ + "ports", + "radios" + ], + "type": "string" + }, + "type": "array", + "uniqueItems": true + }, + "ipAddress": { + "example": "192.168.1.55", + "type": "string" + }, + "macAddress": { + "example": "94:2a:6f:26:c6:ca", + "type": "string" + }, + "model": { + "example": "UHDIW", + "type": "string" + }, + "name": { + "example": "IW HD", + "type": "string" + }, + "state": { + "enum": [ + "ONLINE", + "OFFLINE", + "PENDING_ADOPTION", + "UPDATING", + "GETTING_READY", + "ADOPTING", + "DELETING", + "CONNECTION_INTERRUPTED", + "ISOLATED", + "U5G_INCORRECT_TOPOLOGY" + ], + "type": "string" + }, + "supported": { + "type": "boolean" + } + }, + "required": [ + "features", + "firmwareUpdatable", + "id", + "interfaces", + "ipAddress", + "macAddress", + "model", + "name", + "state", + "supported" + ], + "type": "object" + }, + "Adopted device overview page": { + "properties": { + "count": { + "example": 10, + "format": "int32", + "type": "integer" + }, + "data": { + "items": { + "$ref": "#/components/schemas/Adopted device overview" + }, + "type": "array" + }, + "limit": { + "example": 25, + "format": "int32", + "type": "integer" + }, + "offset": { + "example": 0, + "format": "int64", + "type": "integer" + }, + "totalCount": { + "example": 1000, + "format": "int64", + "type": "integer" + } + }, + "required": [ + "count", + "data", + "limit", + "offset", + "totalCount" + ], + "type": "object" + }, + "Application info": { + "properties": { + "applicationVersion": { + "example": "9.1.0", + "type": "string" + } + }, + "required": [ + "applicationVersion" + ], + "type": "object" + }, + "Blackout schedule configuration per day": { + "discriminator": { + "mapping": { + "ALL_DAY": "#/components/schemas/IntegrationWifiBlackoutScheduleConfigurationPerAllDayDto", + "TIME_RANGE": "#/components/schemas/IntegrationWifiBlackoutScheduleConfigurationPerDayWithTimeRangeDto" + }, + "propertyName": "type" + }, + "properties": { + "day": { + "enum": [ + "SUN", + "MON", + "TUE", + "WED", + "THU", + "FRI", + "SAT" + ], + "type": "string" + }, + "type": { + "type": "string" + } + }, + "required": [ + "day", + "type" + ], + "type": "object" + }, + "BooleanType": { + "allOf": [ + { + "$ref": "#/components/schemas/ScalarType" + } + ] + }, + "Broadcasting device filter": { + "discriminator": { + "mapping": { + "DEVICES": "#/components/schemas/IntegrationWifiDevicesFilterDto", + "DEVICE_TAGS": "#/components/schemas/IntegrationWifiDeviceTagsFilterDto" + }, + "propertyName": "type" + }, + "properties": { + "type": { + "type": "string" + } + }, + "required": [ + "type" + ] + }, + "Client access overview": { + "example": { + "type": "DEFAULT" + } + }, + "Client action request": { + "discriminator": { + "mapping": { + "AUTHORIZE_GUEST_ACCESS": "#/components/schemas/Guest access authorization request", + "UNAUTHORIZE_GUEST_ACCESS": "#/components/schemas/Guest access unauthorization request" + }, + "propertyName": "action" + }, + "properties": { + "action": { + "type": "string" + } + }, + "required": [ + "action" + ] + }, + "Client action response": { + "discriminator": { + "mapping": { + "AUTHORIZE_GUEST_ACCESS": "#/components/schemas/Guest access authorization response", + "UNAUTHORIZE_GUEST_ACCESS": "#/components/schemas/Guest access unauthorization response" + }, + "propertyName": "action" + }, + "properties": { + "action": { + "type": "string" + } + }, + "required": [ + "action" + ] + }, + "Client details": { + "discriminator": { + "mapping": { + "TELEPORT": "#/components/schemas/Teleport client (connection) details", + "VPN": "#/components/schemas/VPN client (connection) details", + "WIRED": "#/components/schemas/Wired client details", + "WIRELESS": "#/components/schemas/Wireless client details" + }, + "propertyName": "type" + }, + "properties": { + "access": {}, + "connectedAt": { + "format": "date-time", + "type": "string" + }, + "id": { + "format": "uuid", + "type": "string" + }, + "ipAddress": { + "type": "string" + }, + "name": { + "type": "string" + }, + "type": { + "type": "string" + } + }, + "required": [ + "access", + "id", + "name", + "type" + ], + "type": "object" + }, + "Client overview": { + "discriminator": { + "mapping": { + "TELEPORT": "#/components/schemas/Teleport client (connection) overview", + "VPN": "#/components/schemas/VPN client (connection) overview", + "WIRED": "#/components/schemas/Wired client overview", + "WIRELESS": "#/components/schemas/Wireless client overview" + }, + "propertyName": "type" + }, + "properties": { + "access": { + "$ref": "#/components/schemas/Client access overview" + }, + "connectedAt": { + "format": "date-time", + "type": "string" + }, + "id": { + "format": "uuid", + "type": "string" + }, + "ipAddress": { + "type": "string" + }, + "name": { + "type": "string" + }, + "type": { + "type": "string" + } + }, + "required": [ + "access", + "id", + "name", + "type" + ], + "type": "object" + }, + "Client overview page": { + "properties": { + "count": { + "example": 10, + "format": "int32", + "type": "integer" + }, + "data": { + "items": { + "$ref": "#/components/schemas/Client overview" + }, + "type": "array" + }, + "limit": { + "example": 25, + "format": "int32", + "type": "integer" + }, + "offset": { + "example": 0, + "format": "int64", + "type": "integer" + }, + "totalCount": { + "example": 1000, + "format": "int64", + "type": "integer" + } + }, + "required": [ + "count", + "data", + "limit", + "offset", + "totalCount" + ], + "type": "object" + }, + "CompoundFilterExpression": { + "allOf": [ + { + "$ref": "#/components/schemas/FilterExpression" + }, + { + "properties": { + "expressions": { + "items": {}, + "type": "array" + }, + "operator": { + "enum": [ + "AND", + "OR", + "NOT" + ], + "type": "string" + } + }, + "type": "object" + } + ] + }, + "Country Definition": { + "properties": { + "code": { + "description": "The country code in ISO 3166-1 alpha-2 format.", + "example": "CK|FK|KY", + "type": "string" + }, + "name": { + "description": "The country name.", + "example": "Cook Islands|Falkland Islands, Malvinas|Cayman Islands", + "type": "string" + } + }, + "required": [ + "code", + "name" + ], + "type": "object" + }, + "Country definition page": { + "properties": { + "count": { + "example": 10, + "format": "int32", + "type": "integer" + }, + "data": { + "items": { + "$ref": "#/components/schemas/Country Definition" + }, + "type": "array" + }, + "limit": { + "example": 25, + "format": "int32", + "type": "integer" + }, + "offset": { + "example": 0, + "format": "int64", + "type": "integer" + }, + "totalCount": { + "example": 1000, + "format": "int64", + "type": "integer" + } + }, + "required": [ + "count", + "data", + "limit", + "offset", + "totalCount" + ], + "type": "object" + }, + "Create or update DNS policy": { + "discriminator": { + "mapping": { + "AAAA_RECORD": "#/components/schemas/IntegrationDnsAaaaRecordCreateUpdateDto", + "A_RECORD": "#/components/schemas/IntegrationDnsARecordCreateUpdateDto", + "CNAME_RECORD": "#/components/schemas/IntegrationDnsCnameRecordCreateUpdateDto", + "FORWARD_DOMAIN": "#/components/schemas/IntegrationDnsForwardDomainPolicyCreateUpdateDto", + "MX_RECORD": "#/components/schemas/IntegrationDnsMxRecordCreateUpdateDto", + "SRV_RECORD": "#/components/schemas/IntegrationDnsSrvRecordCreateUpdateDto", + "TXT_RECORD": "#/components/schemas/IntegrationDnsTxtRecordCreateUpdateDto" + }, + "propertyName": "type" + }, + "properties": { + "enabled": { + "type": "boolean" + }, + "type": { + "type": "string" + } + }, + "required": [ + "enabled", + "type" + ], + "type": "object" + }, + "Create or update Network": { + "discriminator": { + "mapping": { + "GATEWAY": "#/components/schemas/IntegrationGatewayManagedNetworkCreateUpdateDto", + "SWITCH": "#/components/schemas/IntegrationSwitchManagedNetworkCreateUpdateDto", + "UNMANAGED": "#/components/schemas/IntegrationUnmanagedNetworkCreateUpdateDto" + }, + "propertyName": "management" + }, + "properties": { + "dhcpGuarding": { + "$ref": "#/components/schemas/Network DHCP Guarding", + "description": "DHCP Guarding settings for this Network. If this field is omitted or null, the feature is disabled" + }, + "enabled": { + "type": "boolean" + }, + "management": { + "type": "string" + }, + "name": { + "example": "Default Network", + "type": "string" + }, + "vlanId": { + "description": "VLAN ID. Must be 1 for the default network and >= 2 for additional networks.", + "format": "int32", + "maximum": 4009, + "minimum": 1, + "type": "integer" + } + }, + "required": [ + "enabled", + "management", + "name", + "vlanId" + ], + "type": "object" + }, + "Create or update firewall policy": { + "properties": { + "action": { + "$ref": "#/components/schemas/Firewall policy action" + }, + "connectionStateFilter": { + "description": "Match on firewall connection state. If null, matches all connection states.", + "items": { + "enum": [ + "NEW", + "INVALID", + "ESTABLISHED", + "RELATED" + ], + "type": "string" + }, + "maxItems": 2147483647, + "minItems": 1, + "type": "array", + "uniqueItems": true + }, + "description": { + "example": "A description for my firewall policy", + "type": "string" + }, + "destination": { + "$ref": "#/components/schemas/Firewall policy destination" + }, + "enabled": { + "type": "boolean" + }, + "ipProtocolScope": { + "$ref": "#/components/schemas/Firewall policy IP protocol scope" + }, + "ipsecFilter": { + "description": "Match on traffic encrypted, or not encrypted by IPsec. If null, matches all traffic.", + "enum": [ + "MATCH_ENCRYPTED", + "MATCH_NOT_ENCRYPTED" + ], + "type": "string" + }, + "loggingEnabled": { + "description": "Generate syslog entries when traffic is matched. Such entries are sent to a remote syslog server.", + "type": "boolean" + }, + "name": { + "example": "My firewall policy", + "minLength": 1, + "type": "string" + }, + "schedule": { + "$ref": "#/components/schemas/Firewall schedule" + }, + "source": { + "$ref": "#/components/schemas/Firewall policy source" + } + }, + "required": [ + "action", + "destination", + "enabled", + "ipProtocolScope", + "loggingEnabled", + "name", + "source" + ], + "type": "object" + }, + "Create or update firewall zone": { + "properties": { + "name": { + "description": "Name of a firewall zone", + "example": "Hotspot|My custom zone", + "type": "string" + }, + "networkIds": { + "description": "List of Network IDs", + "items": { + "example": "dfb21062-8ea0-4dca-b1d8-1eb3da00e58b", + "format": "uuid", + "type": "string" + }, + "minItems": 0, + "type": "array" + } + }, + "required": [ + "name", + "networkIds" + ], + "type": "object" + }, + "Create or update traffic matching list": { + "discriminator": { + "mapping": { + "IPV4_ADDRESSES": "#/components/schemas/IntegrationIpV4TrafficMatchingListCreateUpdateDto", + "IPV6_ADDRESSES": "#/components/schemas/IntegrationIpV6TrafficMatchingListCreateUpdateDto", + "PORTS": "#/components/schemas/IntegrationPortTrafficMatchingListCreateUpdateDto" + }, + "propertyName": "type" + }, + "properties": { + "name": { + "example": "Allowed port list|Protected IP list", + "minLength": 1, + "type": "string" + }, + "type": { + "type": "string" + } + }, + "required": [ + "name", + "type" + ], + "type": "object" + }, + "DHCP Configuration for IPv6 Network": { + "properties": { + "ipAddressSuffixRange": { + "$ref": "#/components/schemas/IntegrationIpv6AddressSuffixRangeSelectorDto" + }, + "leaseTimeSeconds": { + "description": "The lease time in seconds for IP addresses in this range.", + "format": "int32", + "maximum": 31536000, + "minimum": 0, + "type": "integer" + } + }, + "required": [ + "ipAddressSuffixRange", + "leaseTimeSeconds" + ], + "type": "object" + }, + "DNS assistance configuration": { + "discriminator": { + "mapping": { + "AUTO": "#/components/schemas/IntegrationWifiDnsAssistanceAutoConfigurationDto", + "MANUAL": "#/components/schemas/IntegrationWifiDnsAssistanceManualConfigurationDto" + }, + "propertyName": "mode" + }, + "properties": { + "mode": { + "type": "string" + } + }, + "required": [ + "mode" + ] + }, + "DNS policy": { + "discriminator": { + "mapping": { + "AAAA_RECORD": "#/components/schemas/IntegrationDnsAaaaRecordDto", + "A_RECORD": "#/components/schemas/IntegrationDnsARecordDto", + "CNAME_RECORD": "#/components/schemas/IntegrationDnsCnameRecordDto", + "FORWARD_DOMAIN": "#/components/schemas/IntegrationDnsForwardDomainPolicyDto", + "MX_RECORD": "#/components/schemas/IntegrationDnsMxRecordDto", + "SRV_RECORD": "#/components/schemas/IntegrationDnsSrvRecordDto", + "TXT_RECORD": "#/components/schemas/IntegrationDnsTxtRecordDto" + }, + "propertyName": "type" + }, + "properties": { + "domain": { + "type": "string" + }, + "enabled": { + "type": "boolean" + }, + "id": { + "format": "uuid", + "type": "string" + }, + "metadata": { + "$ref": "#/components/schemas/User defined entity metadata" + }, + "type": { + "type": "string" + } + }, + "required": [ + "enabled", + "id", + "metadata", + "type" + ], + "type": "object" + }, + "DPI application": { + "properties": { + "id": { + "example": "786435|720973", + "format": "int32", + "type": "integer" + }, + "name": { + "example": "Adobe Express|Zoom", + "type": "string" + } + }, + "required": [ + "id", + "name" + ], + "type": "object" + }, + "DPI application page": { + "properties": { + "count": { + "example": 10, + "format": "int32", + "type": "integer" + }, + "data": { + "items": { + "$ref": "#/components/schemas/DPI application" + }, + "type": "array" + }, + "limit": { + "example": 25, + "format": "int32", + "type": "integer" + }, + "offset": { + "example": 0, + "format": "int64", + "type": "integer" + }, + "totalCount": { + "example": 1000, + "format": "int64", + "type": "integer" + } + }, + "required": [ + "count", + "data", + "limit", + "offset", + "totalCount" + ], + "type": "object" + }, + "DPI category": { + "properties": { + "id": { + "example": "3|5", + "format": "int32", + "type": "integer" + }, + "name": { + "example": "Network protocols|Business tools", + "type": "string" + } + }, + "required": [ + "id", + "name" + ], + "type": "object" + }, + "DPI category page": { + "properties": { + "count": { + "example": 10, + "format": "int32", + "type": "integer" + }, + "data": { + "items": { + "$ref": "#/components/schemas/DPI category" + }, + "type": "array" + }, + "limit": { + "example": 25, + "format": "int32", + "type": "integer" + }, + "offset": { + "example": 0, + "format": "int64", + "type": "integer" + }, + "totalCount": { + "example": 1000, + "format": "int64", + "type": "integer" + } + }, + "required": [ + "count", + "data", + "limit", + "offset", + "totalCount" + ], + "type": "object" + }, + "DecimalType": { + "allOf": [ + { + "$ref": "#/components/schemas/ScalarType" + } + ] + }, + "Default client access details": { + "allOf": [ + { + "$ref": "#/components/schemas/Local client access details" + }, + { + "$ref": "#/components/schemas/VPN client access details" + }, + { + "$ref": "#/components/schemas/Teleport client access details" + } + ] + }, + "Default client access overview": { + "allOf": [ + { + "$ref": "#/components/schemas/Local client access overview" + }, + { + "$ref": "#/components/schemas/VPN client access overview" + }, + { + "$ref": "#/components/schemas/Teleport client access overview" + } + ] + }, + "Derived entity metadata": { + "allOf": [ + { + "$ref": "#/components/schemas/Entity metadata" + } + ] + }, + "Device action request": { + "discriminator": { + "mapping": { + "RESTART": "#/components/schemas/Device restart request" + }, + "propertyName": "action" + }, + "properties": { + "action": { + "type": "string" + } + }, + "required": [ + "action" + ] + }, + "Device features": { + "properties": { + "accessPoint": { + "$ref": "#/components/schemas/Access point feature overview", + "example": {} + }, + "switching": { + "$ref": "#/components/schemas/Switching feature overview" + } + }, + "type": "object" + }, + "Device pending adoption": { + "properties": { + "adoptionTargetSiteIds": { + "items": { + "format": "uuid", + "type": "string" + }, + "type": "array", + "uniqueItems": true + }, + "features": { + "items": { + "enum": [ + "switching", + "accessPoint", + "gateway" + ], + "type": "string" + }, + "type": "array", + "uniqueItems": true + }, + "firmwareUpdatable": { + "type": "boolean" + }, + "firmwareVersion": { + "example": "6.6.55", + "type": "string" + }, + "ipAddress": { + "example": "192.168.1.55", + "type": "string" + }, + "macAddress": { + "example": "94:2a:6f:26:c6:ca", + "type": "string" + }, + "model": { + "example": "UHDIW", + "type": "string" + }, + "state": { + "enum": [ + "ONLINE", + "OFFLINE", + "PENDING_ADOPTION", + "UPDATING", + "GETTING_READY", + "ADOPTING", + "DELETING", + "CONNECTION_INTERRUPTED", + "ISOLATED", + "U5G_INCORRECT_TOPOLOGY" + ], + "type": "string" + }, + "supported": { + "type": "boolean" + } + }, + "required": [ + "adoptionTargetSiteIds", + "features", + "firmwareUpdatable", + "ipAddress", + "macAddress", + "model", + "state", + "supported" + ], + "type": "object" + }, + "Device pending adoption page": { + "properties": { + "count": { + "example": 10, + "format": "int32", + "type": "integer" + }, + "data": { + "items": { + "$ref": "#/components/schemas/Device pending adoption" + }, + "type": "array" + }, + "limit": { + "example": 25, + "format": "int32", + "type": "integer" + }, + "offset": { + "example": 0, + "format": "int64", + "type": "integer" + }, + "totalCount": { + "example": 1000, + "format": "int64", + "type": "integer" + } + }, + "required": [ + "count", + "data", + "limit", + "offset", + "totalCount" + ], + "type": "object" + }, + "Device physical interfaces": { + "properties": { + "ports": { + "items": { + "$ref": "#/components/schemas/Port overview" + }, + "type": "array" + }, + "radios": { + "items": { + "$ref": "#/components/schemas/Wireless radio overview" + }, + "type": "array" + } + }, + "type": "object" + }, + "Device restart request": { + "allOf": [ + { + "$ref": "#/components/schemas/Device action request" + } + ] + }, + "Device tag": { + "properties": { + "deviceIds": { + "items": { + "format": "uuid", + "type": "string" + }, + "minItems": 1, + "type": "array" + }, + "id": { + "format": "uuid", + "type": "string" + }, + "metadata": { + "$ref": "#/components/schemas/User or orchestrated entity metadata" + }, + "name": { + "minLength": 1, + "type": "string" + } + }, + "required": [ + "deviceIds", + "id", + "metadata", + "name" + ], + "type": "object" + }, + "Device uplink interface overview": { + "description": "Uplink interface is device's connection to the parent device in the network topology", + "properties": { + "deviceId": { + "format": "uuid", + "type": "string" + } + }, + "required": [ + "deviceId" + ], + "type": "object" + }, + "Entity metadata": { + "discriminator": { + "mapping": { + "DERIVED": "#/components/schemas/Derived entity metadata", + "ORCHESTRATED": "#/components/schemas/Orchestrated entity metadata", + "SYSTEM_DEFINED": "#/components/schemas/System defined entity metadata", + "USER_DEFINED": "#/components/schemas/User defined entity metadata" + }, + "propertyName": "origin" + }, + "properties": { + "origin": { + "type": "string" + } + }, + "required": [ + "origin" + ] + }, + "Error Message": { + "properties": { + "code": { + "example": "api.authentication.missing-credentials", + "type": "string" + }, + "message": { + "example": "Missing credentials", + "type": "string" + }, + "requestId": { + "description": "In case of Internal Server Error (core = 500), request ID can be used to track down the error in the server log", + "example": "3fa85f64-5717-4562-b3fc-2c963f66afa6", + "format": "uuid", + "type": "string" + }, + "requestPath": { + "example": "/integration/v1/sites/123", + "type": "string" + }, + "statusCode": { + "example": 400, + "format": "int32", + "type": "integer" + }, + "statusName": { + "example": "UNAUTHORIZED", + "type": "string" + }, + "timestamp": { + "example": "2024-11-27T08:13:46.966Z", + "format": "date-time", + "type": "string" + } + }, + "x-tags": "Error Handling" + }, + "FilterExpression": {}, + "FilterPath": { + "properties": { + "depth": { + "format": "int32", + "type": "integer" + }, + "name": { + "type": "string" + }, + "names": { + "items": { + "type": "string" + }, + "type": "array" + }, + "parent": {} + }, + "type": "object" + }, + "FilterableEntity": { + "properties": { + "name": { + "type": "string" + }, + "nestedEntities": { + "additionalProperties": {}, + "type": "object" + }, + "path": { + "$ref": "#/components/schemas/FilterPath" + }, + "properties": { + "additionalProperties": { + "$ref": "#/components/schemas/FilterableProperty" + }, + "type": "object" + } + }, + "type": "object" + }, + "FilterableProperty": { + "properties": { + "name": { + "type": "string" + }, + "path": { + "$ref": "#/components/schemas/FilterPath" + }, + "type": { + "$ref": "#/components/schemas/FilterablePropertyType" + } + }, + "type": "object" + }, + "FilterablePropertyType": { + "properties": { + "allowedFunctions": { + "items": { + "enum": [ + "IS_NULL", + "IS_NOT_NULL", + "EQ", + "NE", + "GT", + "GE", + "LT", + "LE", + "LIKE", + "IN", + "NOT_IN", + "IS_EMPTY", + "CONTAINS", + "CONTAINS_ANY", + "CONTAINS_ALL", + "CONTAINS_EXACTLY" + ], + "type": "string" + }, + "type": "array", + "uniqueItems": true + }, + "supportedFunctions": { + "items": { + "enum": [ + "IS_NULL", + "IS_NOT_NULL", + "EQ", + "NE", + "GT", + "GE", + "LT", + "LE", + "LIKE", + "IN", + "NOT_IN", + "IS_EMPTY", + "CONTAINS", + "CONTAINS_ANY", + "CONTAINS_ALL", + "CONTAINS_EXACTLY" + ], + "type": "string" + }, + "type": "array", + "uniqueItems": true + }, + "valueType": { + "enum": [ + "STRING", + "INTEGER", + "DECIMAL", + "UUID", + "TIMESTAMP", + "BOOLEAN" + ], + "type": "string" + } + }, + "type": "object" + }, + "Firewall policy": { + "properties": { + "action": { + "$ref": "#/components/schemas/Firewall policy action" + }, + "connectionStateFilter": { + "description": "Match on firewall connection state. If null, matches all connection states.", + "items": { + "enum": [ + "NEW", + "INVALID", + "ESTABLISHED", + "RELATED" + ], + "type": "string" + }, + "maxItems": 2147483647, + "minItems": 1, + "type": "array", + "uniqueItems": true + }, + "description": { + "example": "A description for my firewall policy", + "type": "string" + }, + "destination": { + "$ref": "#/components/schemas/Firewall policy destination" + }, + "enabled": { + "type": "boolean" + }, + "id": { + "format": "uuid", + "type": "string" + }, + "index": { + "format": "int32", + "type": "integer" + }, + "ipProtocolScope": { + "$ref": "#/components/schemas/Firewall policy IP protocol scope" + }, + "ipsecFilter": { + "description": "Match on traffic encrypted, or not encrypted by IPsec. If null, matches all traffic.", + "enum": [ + "MATCH_ENCRYPTED", + "MATCH_NOT_ENCRYPTED" + ], + "type": "string" + }, + "loggingEnabled": { + "description": "Generate syslog entries when traffic is matched. Such entries are sent to a remote syslog server.", + "type": "boolean" + }, + "metadata": { + "$ref": "#/components/schemas/User or system defined or derived entity metadata" + }, + "name": { + "example": "My firewall policy", + "type": "string" + }, + "schedule": { + "$ref": "#/components/schemas/Firewall schedule" + }, + "source": { + "$ref": "#/components/schemas/Firewall policy source" + } + }, + "required": [ + "action", + "destination", + "enabled", + "id", + "index", + "ipProtocolScope", + "loggingEnabled", + "metadata", + "name", + "source" + ], + "type": "object" + }, + "Firewall policy IP address filter": { + "description": "Match traffic originating from, or destined to selected IP addresses.", + "discriminator": { + "mapping": { + "IP_ADDRESSES": "#/components/schemas/IntegrationFirewallPolicySpecificIpAddressFilterDto", + "TRAFFIC_MATCHING_LIST": "#/components/schemas/IntegrationFirewallPolicyIpAddressTrafficMatchingListFilterDto" + }, + "propertyName": "type" + }, + "properties": { + "matchOpposite": { + "description": "Match on all IP addresses except the specified ones.", + "type": "boolean" + }, + "type": { + "type": "string" + } + }, + "required": [ + "matchOpposite", + "type" + ], + "type": "object" + }, + "Firewall policy IP protocol scope": { + "description": "Defines rules for matching by IP version and protocol.", + "discriminator": { + "mapping": { + "IPV4": "#/components/schemas/IntegrationFirewallPolicyIpv4ProtocolScopeDto", + "IPV4_AND_IPV6": "#/components/schemas/IntegrationFirewallPolicyIpv4AndIpv6ProtocolScopeDto", + "IPV6": "#/components/schemas/IntegrationFirewallPolicyIpv6ProtocolScopeDto" + }, + "propertyName": "ipVersion" + }, + "properties": { + "ipVersion": { + "type": "string" + } + }, + "required": [ + "ipVersion" + ] + }, + "Firewall policy IPv4 and IPv6 named protocol": { + "description": "Defines rules for matching by protocol name.", + "discriminator": { + "mapping": { + "AH": "#/components/schemas/IntegrationFirewallPolicyIpv4AndIpv6NamedProtocolDefaultDto", + "DCCP": "#/components/schemas/IntegrationFirewallPolicyIpv4AndIpv6NamedProtocolDefaultDto", + "EIGRP": "#/components/schemas/IntegrationFirewallPolicyIpv4AndIpv6NamedProtocolDefaultDto", + "ESP": "#/components/schemas/IntegrationFirewallPolicyIpv4AndIpv6NamedProtocolDefaultDto", + "GRE": "#/components/schemas/IntegrationFirewallPolicyIpv4AndIpv6NamedProtocolDefaultDto", + "IPCOMP": "#/components/schemas/IntegrationFirewallPolicyIpv4AndIpv6NamedProtocolDefaultDto", + "ISIS": "#/components/schemas/IntegrationFirewallPolicyIpv4AndIpv6NamedProtocolDefaultDto", + "L2TP": "#/components/schemas/IntegrationFirewallPolicyIpv4AndIpv6NamedProtocolDefaultDto", + "MANET": "#/components/schemas/IntegrationFirewallPolicyIpv4AndIpv6NamedProtocolDefaultDto", + "MOBILITY_HEADER": "#/components/schemas/IntegrationFirewallPolicyIpv4AndIpv6NamedProtocolDefaultDto", + "MPLS_IN_IP": "#/components/schemas/IntegrationFirewallPolicyIpv4AndIpv6NamedProtocolDefaultDto", + "OSPF": "#/components/schemas/IntegrationFirewallPolicyIpv4AndIpv6NamedProtocolDefaultDto", + "PIM": "#/components/schemas/IntegrationFirewallPolicyIpv4AndIpv6NamedProtocolDefaultDto", + "RSVP": "#/components/schemas/IntegrationFirewallPolicyIpv4AndIpv6NamedProtocolDefaultDto", + "SCTP": "#/components/schemas/IntegrationFirewallPolicyIpv4AndIpv6NamedProtocolDefaultDto", + "SHIM6": "#/components/schemas/IntegrationFirewallPolicyIpv4AndIpv6NamedProtocolDefaultDto", + "TCP": "#/components/schemas/IntegrationFirewallPolicyIpv4AndIpv6NamedProtocolDefaultDto", + "UDP": "#/components/schemas/IntegrationFirewallPolicyIpv4AndIpv6NamedProtocolDefaultDto", + "VRRP": "#/components/schemas/IntegrationFirewallPolicyIpv4AndIpv6NamedProtocolDefaultDto" + }, + "propertyName": "name" + }, + "properties": { + "name": { + "enum": [ + "ah", + "ax.25", + "dccp", + "ddp", + "egp", + "eigrp", + "encap", + "esp", + "etherip", + "fc", + "ggp", + "gre", + "hip", + "hmp", + "icmp", + "icmpv6", + "idpr-cmtp", + "idrp", + "igmp", + "igp", + "ip", + "ipcomp", + "ipencap", + "ipip", + "ipv6", + "ipv6-frag", + "ipv6-nonxt", + "ipv6-opts", + "ipv6-route", + "isis", + "iso-tp4", + "l2tp", + "manet", + "mobility-header", + "mpls-in-ip", + "ospf", + "pim", + "pup", + "rdp", + "rohc", + "rspf", + "rsvp", + "sctp", + "shim6", + "skip", + "st", + "tcp", + "tcp_udp", + "udp", + "udplite", + "vmtp", + "vrrp", + "wesp", + "xns-idp", + "xtp" + ], + "type": "string" + } + }, + "required": [ + "name" + ], + "type": "object" + }, + "Firewall policy IPv4 and IPv6 protocol": { + "description": "Defines protocol matching. If null, matches all protocols.", + "discriminator": { + "mapping": { + "NAMED_PROTOCOL": "#/components/schemas/IntegrationFirewallPolicyIpv4AndIpv6NamedProtocolFilterDto", + "PRESET": "#/components/schemas/IntegrationFirewallPolicyIpv4AndIpv6ProtocolPresetFilterDto", + "PROTOCOL_NUMBER": "#/components/schemas/Firewall policy IPv4 and IPv6 protocol number" + }, + "propertyName": "type" + }, + "properties": { + "type": { + "type": "string" + } + }, + "required": [ + "type" + ] + }, + "Firewall policy IPv4 and IPv6 protocol number": { + "allOf": [ + { + "$ref": "#/components/schemas/Firewall policy IPv4 and IPv6 protocol" + }, + { + "properties": { + "matchOpposite": { + "description": "Match on all protocols except the specified protocol.", + "type": "boolean" + }, + "protocolNumber": { + "description": "Protocol number as defined by IANA.", + "format": "int32", + "maximum": 255, + "minimum": 0, + "type": "integer" + } + }, + "type": "object" + } + ], + "description": "Defines rules for matching by protocol number.", + "required": [ + "matchOpposite", + "protocolNumber" + ] + }, + "Firewall policy IPv4 and IPv6 protocol preset": { + "description": "Defines rules for matching by protocol preset.", + "discriminator": { + "mapping": { + "TCP_UDP": "#/components/schemas/IntegrationFirewallPolicyIpv4AndIpv6ProtocolPresetTcpUdpDto" + }, + "propertyName": "name" + }, + "properties": { + "name": { + "type": "string" + } + }, + "required": [ + "name" + ] + }, + "Firewall policy IPv4 named protocol": { + "description": "Defines rules for matching by protocol name.", + "discriminator": { + "mapping": { + "AH": "#/components/schemas/IntegrationFirewallPolicyIpv4NamedProtocolDefaultDto", + "AX_25": "#/components/schemas/IntegrationFirewallPolicyIpv4NamedProtocolDefaultDto", + "DCCP": "#/components/schemas/IntegrationFirewallPolicyIpv4NamedProtocolDefaultDto", + "DDP": "#/components/schemas/IntegrationFirewallPolicyIpv4NamedProtocolDefaultDto", + "EGP": "#/components/schemas/IntegrationFirewallPolicyIpv4NamedProtocolDefaultDto", + "EIGRP": "#/components/schemas/IntegrationFirewallPolicyIpv4NamedProtocolDefaultDto", + "ENCAP": "#/components/schemas/IntegrationFirewallPolicyIpv4NamedProtocolDefaultDto", + "ESP": "#/components/schemas/IntegrationFirewallPolicyIpv4NamedProtocolDefaultDto", + "ETHERIP": "#/components/schemas/IntegrationFirewallPolicyIpv4NamedProtocolDefaultDto", + "FC": "#/components/schemas/IntegrationFirewallPolicyIpv4NamedProtocolDefaultDto", + "GGP": "#/components/schemas/IntegrationFirewallPolicyIpv4NamedProtocolDefaultDto", + "GRE": "#/components/schemas/IntegrationFirewallPolicyIpv4NamedProtocolDefaultDto", + "HIP": "#/components/schemas/IntegrationFirewallPolicyIpv4NamedProtocolDefaultDto", + "HMP": "#/components/schemas/IntegrationFirewallPolicyIpv4NamedProtocolDefaultDto", + "ICMP": "#/components/schemas/IntegrationFirewallPolicyIpv4NamedProtocolIcmpDto", + "IDPR_CMTP": "#/components/schemas/IntegrationFirewallPolicyIpv4NamedProtocolDefaultDto", + "IDRP": "#/components/schemas/IntegrationFirewallPolicyIpv4NamedProtocolDefaultDto", + "IGMP": "#/components/schemas/IntegrationFirewallPolicyIpv4NamedProtocolDefaultDto", + "IGP": "#/components/schemas/IntegrationFirewallPolicyIpv4NamedProtocolDefaultDto", + "IP": "#/components/schemas/IntegrationFirewallPolicyIpv4NamedProtocolDefaultDto", + "IPCOMP": "#/components/schemas/IntegrationFirewallPolicyIpv4NamedProtocolDefaultDto", + "IPENCAP": "#/components/schemas/IntegrationFirewallPolicyIpv4NamedProtocolDefaultDto", + "IPIP": "#/components/schemas/IntegrationFirewallPolicyIpv4NamedProtocolDefaultDto", + "ISIS": "#/components/schemas/IntegrationFirewallPolicyIpv4NamedProtocolDefaultDto", + "ISO_TP4": "#/components/schemas/IntegrationFirewallPolicyIpv4NamedProtocolDefaultDto", + "L2TP": "#/components/schemas/IntegrationFirewallPolicyIpv4NamedProtocolDefaultDto", + "MANET": "#/components/schemas/IntegrationFirewallPolicyIpv4NamedProtocolDefaultDto", + "MOBILITY_HEADER": "#/components/schemas/IntegrationFirewallPolicyIpv4NamedProtocolDefaultDto", + "MPLS_IN_IP": "#/components/schemas/IntegrationFirewallPolicyIpv4NamedProtocolDefaultDto", + "OSPF": "#/components/schemas/IntegrationFirewallPolicyIpv4NamedProtocolDefaultDto", + "PIM": "#/components/schemas/IntegrationFirewallPolicyIpv4NamedProtocolDefaultDto", + "PUP": "#/components/schemas/IntegrationFirewallPolicyIpv4NamedProtocolDefaultDto", + "RDP": "#/components/schemas/IntegrationFirewallPolicyIpv4NamedProtocolDefaultDto", + "ROHC": "#/components/schemas/IntegrationFirewallPolicyIpv4NamedProtocolDefaultDto", + "RSPF": "#/components/schemas/IntegrationFirewallPolicyIpv4NamedProtocolDefaultDto", + "RSVP": "#/components/schemas/IntegrationFirewallPolicyIpv4NamedProtocolDefaultDto", + "SCTP": "#/components/schemas/IntegrationFirewallPolicyIpv4NamedProtocolDefaultDto", + "SHIM6": "#/components/schemas/IntegrationFirewallPolicyIpv4NamedProtocolDefaultDto", + "SKIP": "#/components/schemas/IntegrationFirewallPolicyIpv4NamedProtocolDefaultDto", + "ST": "#/components/schemas/IntegrationFirewallPolicyIpv4NamedProtocolDefaultDto", + "TCP": "#/components/schemas/IntegrationFirewallPolicyIpv4NamedProtocolDefaultDto", + "UDP": "#/components/schemas/IntegrationFirewallPolicyIpv4NamedProtocolDefaultDto", + "UDPLITE": "#/components/schemas/IntegrationFirewallPolicyIpv4NamedProtocolDefaultDto", + "VMTP": "#/components/schemas/IntegrationFirewallPolicyIpv4NamedProtocolDefaultDto", + "VRRP": "#/components/schemas/IntegrationFirewallPolicyIpv4NamedProtocolDefaultDto", + "WESP": "#/components/schemas/IntegrationFirewallPolicyIpv4NamedProtocolDefaultDto", + "XNS_IDP": "#/components/schemas/IntegrationFirewallPolicyIpv4NamedProtocolDefaultDto", + "XTP": "#/components/schemas/IntegrationFirewallPolicyIpv4NamedProtocolDefaultDto" + }, + "propertyName": "name" + }, + "properties": { + "name": { + "enum": [ + "ah", + "ax.25", + "dccp", + "ddp", + "egp", + "eigrp", + "encap", + "esp", + "etherip", + "fc", + "ggp", + "gre", + "hip", + "hmp", + "icmp", + "icmpv6", + "idpr-cmtp", + "idrp", + "igmp", + "igp", + "ip", + "ipcomp", + "ipencap", + "ipip", + "ipv6", + "ipv6-frag", + "ipv6-nonxt", + "ipv6-opts", + "ipv6-route", + "isis", + "iso-tp4", + "l2tp", + "manet", + "mobility-header", + "mpls-in-ip", + "ospf", + "pim", + "pup", + "rdp", + "rohc", + "rspf", + "rsvp", + "sctp", + "shim6", + "skip", + "st", + "tcp", + "tcp_udp", + "udp", + "udplite", + "vmtp", + "vrrp", + "wesp", + "xns-idp", + "xtp" + ], + "type": "string" + } + }, + "type": "object" + }, + "Firewall policy IPv4 protocol": { + "description": "Defines protocol matching. If null, matches all protocols.", + "discriminator": { + "mapping": { + "NAMED_PROTOCOL": "#/components/schemas/IntegrationFirewallPolicyIpv4NamedProtocolFilterDto", + "PRESET": "#/components/schemas/IntegrationFirewallPolicyIpv4ProtocolPresetFilterDto", + "PROTOCOL_NUMBER": "#/components/schemas/Firewall policy IPv4 protocol number" + }, + "propertyName": "type" + }, + "properties": { + "type": { + "type": "string" + } + }, + "required": [ + "type" + ] + }, + "Firewall policy IPv4 protocol number": { + "allOf": [ + { + "$ref": "#/components/schemas/Firewall policy IPv6 protocol" + }, + { + "properties": { + "matchOpposite": { + "description": "Match on all protocols except the specified protocol.", + "type": "boolean" + }, + "protocolNumber": { + "description": "Protocol number as defined by IANA.", + "format": "int32", + "maximum": 255, + "minimum": 0, + "type": "integer" + } + }, + "type": "object" + } + ], + "description": "Defines rules for matching by protocol number.", + "required": [ + "matchOpposite", + "protocolNumber" + ] + }, + "Firewall policy IPv4 protocol preset": { + "description": "Defines rules for matching by protocol preset.", + "discriminator": { + "mapping": { + "TCP_UDP": "#/components/schemas/IntegrationFirewallPolicyIpv4ProtocolPresetTcpUdpDto" + }, + "propertyName": "name" + }, + "properties": { + "name": { + "type": "string" + } + }, + "required": [ + "name" + ] + }, + "Firewall policy IPv6 interface identifier filter": { + "properties": { + "ipv6Iid": { + "description": "IPv6 Interface Identifier.", + "example": "2001:db8::1/::ffff:ffff:ffff:ffff", + "minLength": 1, + "type": "string" + }, + "matchOpposite": { + "description": "Match on all IPv6 IIDs except the specified one.", + "type": "boolean" + } + }, + "required": [ + "ipv6Iid", + "matchOpposite" + ], + "type": "object" + }, + "Firewall policy IPv6 named protocol": { + "description": "Defines rules for matching by protocol name.", + "discriminator": { + "mapping": { + "AH": "#/components/schemas/IntegrationFirewallPolicyIpv6NamedProtocolDefaultDto", + "DCCP": "#/components/schemas/IntegrationFirewallPolicyIpv6NamedProtocolDefaultDto", + "EIGRP": "#/components/schemas/IntegrationFirewallPolicyIpv6NamedProtocolDefaultDto", + "ESP": "#/components/schemas/IntegrationFirewallPolicyIpv6NamedProtocolDefaultDto", + "GRE": "#/components/schemas/IntegrationFirewallPolicyIpv6NamedProtocolDefaultDto", + "ICMPV6": "#/components/schemas/IntegrationFirewallPolicyIpv6NamedProtocolIcmpv6Dto", + "IPCOMP": "#/components/schemas/IntegrationFirewallPolicyIpv6NamedProtocolDefaultDto", + "IPV6": "#/components/schemas/IntegrationFirewallPolicyIpv6NamedProtocolDefaultDto", + "IPV6_FRAG": "#/components/schemas/IntegrationFirewallPolicyIpv6NamedProtocolDefaultDto", + "IPV6_NONXT": "#/components/schemas/IntegrationFirewallPolicyIpv6NamedProtocolDefaultDto", + "IPV6_OPTS": "#/components/schemas/IntegrationFirewallPolicyIpv6NamedProtocolDefaultDto", + "IPV6_ROUTE": "#/components/schemas/IntegrationFirewallPolicyIpv6NamedProtocolDefaultDto", + "ISIS": "#/components/schemas/IntegrationFirewallPolicyIpv6NamedProtocolDefaultDto", + "L2TP": "#/components/schemas/IntegrationFirewallPolicyIpv6NamedProtocolDefaultDto", + "MANET": "#/components/schemas/IntegrationFirewallPolicyIpv6NamedProtocolDefaultDto", + "MOBILITY_HEADER": "#/components/schemas/IntegrationFirewallPolicyIpv6NamedProtocolDefaultDto", + "MPLS_IN_IP": "#/components/schemas/IntegrationFirewallPolicyIpv6NamedProtocolDefaultDto", + "OSPF": "#/components/schemas/IntegrationFirewallPolicyIpv6NamedProtocolDefaultDto", + "PIM": "#/components/schemas/IntegrationFirewallPolicyIpv6NamedProtocolDefaultDto", + "RSVP": "#/components/schemas/IntegrationFirewallPolicyIpv6NamedProtocolDefaultDto", + "SCTP": "#/components/schemas/IntegrationFirewallPolicyIpv6NamedProtocolDefaultDto", + "SHIM6": "#/components/schemas/IntegrationFirewallPolicyIpv6NamedProtocolDefaultDto", + "TCP": "#/components/schemas/IntegrationFirewallPolicyIpv6NamedProtocolDefaultDto", + "UDP": "#/components/schemas/IntegrationFirewallPolicyIpv6NamedProtocolDefaultDto", + "VRRP": "#/components/schemas/IntegrationFirewallPolicyIpv6NamedProtocolDefaultDto" + }, + "propertyName": "name" + }, + "properties": { + "name": { + "enum": [ + "ah", + "ax.25", + "dccp", + "ddp", + "egp", + "eigrp", + "encap", + "esp", + "etherip", + "fc", + "ggp", + "gre", + "hip", + "hmp", + "icmp", + "icmpv6", + "idpr-cmtp", + "idrp", + "igmp", + "igp", + "ip", + "ipcomp", + "ipencap", + "ipip", + "ipv6", + "ipv6-frag", + "ipv6-nonxt", + "ipv6-opts", + "ipv6-route", + "isis", + "iso-tp4", + "l2tp", + "manet", + "mobility-header", + "mpls-in-ip", + "ospf", + "pim", + "pup", + "rdp", + "rohc", + "rspf", + "rsvp", + "sctp", + "shim6", + "skip", + "st", + "tcp", + "tcp_udp", + "udp", + "udplite", + "vmtp", + "vrrp", + "wesp", + "xns-idp", + "xtp" + ], + "type": "string" + } + }, + "type": "object" + }, + "Firewall policy IPv6 protocol": { + "description": "Defines protocol matching. If null, matches all protocols.", + "discriminator": { + "mapping": { + "NAMED_PROTOCOL": "#/components/schemas/IntegrationFirewallPolicyIpv6NamedProtocolFilterDto", + "PRESET": "#/components/schemas/IntegrationFirewallPolicyIpv6ProtocolPresetFilterDto", + "PROTOCOL_NUMBER": "#/components/schemas/Firewall policy IPv4 protocol number" + }, + "propertyName": "type" + }, + "properties": { + "type": { + "type": "string" + } + }, + "required": [ + "type" + ] + }, + "Firewall policy IPv6 protocol preset": { + "description": "Defines rules for matching by protocol preset.", + "discriminator": { + "mapping": { + "TCP_UDP": "#/components/schemas/IntegrationFirewallPolicyIpv6ProtocolPresetTcpUdpDto" + }, + "propertyName": "name" + }, + "properties": { + "name": { + "type": "string" + } + }, + "required": [ + "name" + ] + }, + "Firewall policy MAC address filter": { + "properties": { + "macAddresses": { + "description": "Array of MAC addresses to match.", + "items": { + "type": "string" + }, + "minItems": 1, + "type": "array", + "uniqueItems": true + } + }, + "required": [ + "macAddresses" + ], + "type": "object" + }, + "Firewall policy VPN server filter": { + "properties": { + "matchOpposite": { + "type": "boolean" + }, + "vpnServerIds": { + "items": { + "format": "uuid", + "type": "string" + }, + "minItems": 1, + "type": "array", + "uniqueItems": true + } + }, + "required": [ + "matchOpposite", + "vpnServerIds" + ], + "type": "object" + }, + "Firewall policy action": { + "description": "Defines action for matched traffic.", + "discriminator": { + "mapping": { + "ALLOW": "#/components/schemas/IntegrationFirewallPolicyActionAllowDto", + "BLOCK": "#/components/schemas/IntegrationFirewallPolicyActionBlockDto", + "REJECT": "#/components/schemas/IntegrationFirewallPolicyActionRejectDto" + }, + "propertyName": "type" + }, + "properties": { + "type": { + "type": "string" + } + }, + "required": [ + "type" + ] + }, + "Firewall policy application category filter": { + "properties": { + "applicationCategoryIds": { + "description": "Array of DPI Category IDs to match.", + "items": { + "format": "int32", + "type": "integer" + }, + "minItems": 1, + "type": "array", + "uniqueItems": true + } + }, + "required": [ + "applicationCategoryIds" + ], + "type": "object" + }, + "Firewall policy application filter": { + "properties": { + "applicationIds": { + "description": "Array of DPI Application IDs to match.", + "items": { + "format": "int32", + "type": "integer" + }, + "maxItems": 100, + "minItems": 1, + "type": "array", + "uniqueItems": true + } + }, + "required": [ + "applicationIds" + ], + "type": "object" + }, + "Firewall policy destination": { + "properties": { + "trafficFilter": { + "$ref": "#/components/schemas/Firewall policy destination traffic filter" + }, + "zoneId": { + "description": "ID of the firewall zone to which the matched traffic is destined.", + "format": "uuid", + "type": "string" + } + }, + "required": [ + "zoneId" + ], + "type": "object" + }, + "Firewall policy destination traffic filter": { + "discriminator": { + "mapping": { + "APPLICATION": "#/components/schemas/IntegrationFirewallPolicyDestinationApplicationFilterDto", + "APPLICATION_CATEGORY": "#/components/schemas/IntegrationFirewallPolicyDestinationApplicationCategoryFilterDto", + "DOMAIN": "#/components/schemas/IntegrationFirewallPolicyDestinationDomainFilterDto", + "IPV6_IID": "#/components/schemas/IntegrationFirewallPolicyDestinationIpv6IidFilterDto", + "IP_ADDRESS": "#/components/schemas/IntegrationFirewallPolicyDestinationIpAddressFilterDto", + "NETWORK": "#/components/schemas/IntegrationFirewallPolicyDestinationNetworkFilterDto", + "PORT": "#/components/schemas/IntegrationFirewallPolicyDestinationPortFilterDto", + "REGION": "#/components/schemas/IntegrationFirewallPolicyDestinationRegionFilterDto", + "SITE_TO_SITE_VPN_TUNNEL": "#/components/schemas/IntegrationFirewallPolicyDestinationSiteToSiteVpnTunnelFilterDto", + "VPN_SERVER": "#/components/schemas/IntegrationFirewallPolicyDestinationVpnServerFilterDto" + }, + "propertyName": "type" + }, + "properties": { + "type": { + "type": "string" + } + }, + "required": [ + "type" + ] + }, + "Firewall policy domain filter": { + "discriminator": { + "mapping": { + "DOMAINS": "#/components/schemas/IntegrationFirewallPolicySpecificDomainFilterDto" + }, + "propertyName": "type" + }, + "properties": { + "type": { + "type": "string" + } + }, + "required": [ + "type" + ] + }, + "Firewall policy network filter": { + "properties": { + "matchOpposite": { + "description": "Match on all Networks except the selected.", + "type": "boolean" + }, + "networkIds": { + "description": "Array of Network IDs to match.", + "items": { + "format": "uuid", + "type": "string" + }, + "minItems": 1, + "type": "array", + "uniqueItems": true + } + }, + "required": [ + "matchOpposite", + "networkIds" + ], + "type": "object" + }, + "Firewall policy page": { + "properties": { + "count": { + "example": 10, + "format": "int32", + "type": "integer" + }, + "data": { + "items": { + "$ref": "#/components/schemas/Firewall policy" + }, + "type": "array" + }, + "limit": { + "example": 25, + "format": "int32", + "type": "integer" + }, + "offset": { + "example": 0, + "format": "int64", + "type": "integer" + }, + "totalCount": { + "example": 1000, + "format": "int64", + "type": "integer" + } + }, + "required": [ + "count", + "data", + "limit", + "offset", + "totalCount" + ], + "type": "object" + }, + "Firewall policy port filter": { + "description": "Defines rules for matching traffic by port.", + "discriminator": { + "mapping": { + "PORTS": "#/components/schemas/IntegrationFirewallPolicyPortValueFilterDto", + "TRAFFIC_MATCHING_LIST": "#/components/schemas/IntegrationFirewallPolicyPortReferenceFilterDto" + }, + "propertyName": "type" + }, + "properties": { + "matchOpposite": { + "description": "Match on all ports except the specified ones.", + "type": "boolean" + }, + "type": { + "type": "string" + } + }, + "required": [ + "matchOpposite", + "type" + ], + "type": "object" + }, + "Firewall policy region filter": { + "properties": { + "regions": { + "description": "Match traffic originating from selected regions. Regions are identified by their ISO 3166-1 alpha-2 country codes.", + "items": { + "enum": [ + "AD", + "AE", + "AF", + "AG", + "AI", + "AL", + "AM", + "AO", + "AQ", + "AR", + "AS", + "AT", + "AU", + "AW", + "AX", + "AZ", + "BA", + "BB", + "BD", + "BE", + "BF", + "BG", + "BH", + "BI", + "BJ", + "BL", + "BM", + "BN", + "BO", + "BQ", + "BR", + "BS", + "BT", + "BW", + "BY", + "BZ", + "CA", + "CC", + "CD", + "CF", + "CG", + "CH", + "CI", + "CK", + "CL", + "CM", + "CN", + "CO", + "CR", + "CU", + "CV", + "CW", + "CX", + "CY", + "CZ", + "DE", + "DJ", + "DK", + "DM", + "DO", + "DZ", + "EC", + "EE", + "EG", + "EH", + "ER", + "ES", + "ET", + "FI", + "FJ", + "FK", + "FM", + "FO", + "FR", + "GA", + "GB", + "GD", + "GE", + "GF", + "GG", + "GH", + "GI", + "GL", + "GM", + "GN", + "GP", + "GQ", + "GR", + "GS", + "GT", + "GU", + "GW", + "GY", + "HK", + "HN", + "HR", + "HT", + "HU", + "ID", + "IE", + "IL", + "IM", + "IN", + "IO", + "IQ", + "IR", + "IS", + "IT", + "JE", + "JM", + "JO", + "JP", + "KE", + "KG", + "KH", + "KI", + "KM", + "KN", + "KP", + "KR", + "KW", + "KY", + "KZ", + "LA", + "LB", + "LC", + "LI", + "LK", + "LR", + "LS", + "LT", + "LU", + "LV", + "LY", + "MA", + "MC", + "MD", + "ME", + "MF", + "MG", + "MH", + "MK", + "ML", + "MM", + "MN", + "MO", + "MP", + "MQ", + "MR", + "MS", + "MT", + "MU", + "MV", + "MW", + "MX", + "MY", + "MZ", + "NA", + "NC", + "NE", + "NF", + "NG", + "NI", + "NL", + "NO", + "NP", + "NR", + "NU", + "NZ", + "OM", + "PA", + "PE", + "PF", + "PG", + "PH", + "PK", + "PL", + "PM", + "PN", + "PR", + "PS", + "PT", + "PW", + "PY", + "QA", + "RE", + "RO", + "RS", + "RU", + "RW", + "SA", + "SB", + "SC", + "SD", + "SE", + "SG", + "SH", + "SI", + "SJ", + "SK", + "SL", + "SM", + "SN", + "SO", + "SR", + "SS", + "ST", + "SV", + "SX", + "SY", + "SZ", + "TC", + "TD", + "TF", + "TG", + "TH", + "TJ", + "TK", + "TL", + "TM", + "TN", + "TO", + "TR", + "TT", + "TV", + "TW", + "TZ", + "UA", + "UG", + "UM", + "US", + "UY", + "UZ", + "VA", + "VC", + "VE", + "VG", + "VI", + "VN", + "VU", + "WF", + "WS", + "XK", + "YE", + "YT", + "ZA", + "ZM", + "ZW" + ], + "type": "string" + }, + "minItems": 1, + "type": "array", + "uniqueItems": true + } + }, + "required": [ + "regions" + ], + "type": "object" + }, + "Firewall policy site-to-site VPN tunnel filter": { + "properties": { + "siteToSiteVpnTunnelId": { + "format": "uuid", + "type": "string" + } + }, + "required": [ + "siteToSiteVpnTunnelId" + ], + "type": "object" + }, + "Firewall policy source": { + "properties": { + "trafficFilter": { + "$ref": "#/components/schemas/Firewall policy source traffic filter" + }, + "zoneId": { + "description": "ID of the firewall zone from which the matched traffic originates.", + "format": "uuid", + "type": "string" + } + }, + "required": [ + "zoneId" + ], + "type": "object" + }, + "Firewall policy source traffic filter": { + "discriminator": { + "mapping": { + "IPV6_IID": "#/components/schemas/IntegrationFirewallPolicySourceIpv6IidFilterDto", + "IP_ADDRESS": "#/components/schemas/IntegrationFirewallPolicySourceIpAddressFilterDto", + "MAC_ADDRESS": "#/components/schemas/IntegrationFirewallPolicySourceMacAddressFilterDto", + "NETWORK": "#/components/schemas/IntegrationFirewallPolicySourceNetworkFilterDto", + "PORT": "#/components/schemas/IntegrationFirewallPolicySourcePortFilterDto", + "REGION": "#/components/schemas/IntegrationFirewallPolicySourceRegionFilterDto", + "SITE_TO_SITE_VPN_TUNNEL": "#/components/schemas/IntegrationFirewallPolicySourceSiteToSiteVpnTunnelFilterDto", + "VPN_SERVER": "#/components/schemas/IntegrationFirewallPolicySourceVpnServerFilterDto" + }, + "propertyName": "type" + }, + "properties": { + "type": { + "type": "string" + } + }, + "required": [ + "type" + ] + }, + "Firewall schedule": { + "description": "Defines date and time when the entity is active. If null, the entity is always active.", + "discriminator": { + "mapping": { + "CUSTOM": "#/components/schemas/IntegrationFirewallScheduleCustomDto", + "EVERY_DAY": "#/components/schemas/IntegrationFirewallScheduleEveryDayDto", + "EVERY_WEEK": "#/components/schemas/IntegrationFirewallScheduleEveryWeekDto", + "ONE_TIME_ONLY": "#/components/schemas/IntegrationFirewallScheduleOneTimeOnlyDto" + }, + "propertyName": "mode" + }, + "properties": { + "mode": { + "type": "string" + } + }, + "required": [ + "mode" + ] + }, + "Firewall schedule time": { + "description": "Defines the time range when the entity is active. If null, the entity is active all day.", + "properties": { + "startTime": { + "description": "Time in HH:MM format. Uses 24-hour clock system. ISO 8601 compliant.", + "example": "21:37", + "type": "string" + }, + "stopTime": { + "description": "Time in HH:MM format. Uses 24-hour clock system. ISO 8601 compliant.", + "example": "21:37", + "type": "string" + } + }, + "required": [ + "startTime", + "stopTime" + ], + "type": "object" + }, + "Firewall zone": { + "properties": { + "id": { + "example": "ffcdb32c-6278-4364-8947-df4f77118df8", + "format": "uuid", + "type": "string" + }, + "metadata": { + "$ref": "#/components/schemas/User or system defined entity metadata", + "description": "System-defined configurable zones support configuring only attached networks" + }, + "name": { + "description": "Name of a firewall zone", + "example": "Hotspot|My custom zone", + "type": "string" + }, + "networkIds": { + "description": "List of Network IDs", + "items": { + "example": "dfb21062-8ea0-4dca-b1d8-1eb3da00e58b", + "format": "uuid", + "type": "string" + }, + "minItems": 0, + "type": "array" + } + }, + "required": [ + "id", + "metadata", + "name", + "networkIds" + ], + "type": "object" + }, + "Firewall zones page": { + "properties": { + "count": { + "example": 10, + "format": "int32", + "type": "integer" + }, + "data": { + "items": { + "$ref": "#/components/schemas/Firewall zone" + }, + "type": "array" + }, + "limit": { + "example": 25, + "format": "int32", + "type": "integer" + }, + "offset": { + "example": 0, + "format": "int64", + "type": "integer" + }, + "totalCount": { + "example": 1000, + "format": "int64", + "type": "integer" + } + }, + "required": [ + "count", + "data", + "limit", + "offset", + "totalCount" + ], + "type": "object" + }, + "Gateway Managed IPv4 Configuration": { + "properties": { + "additionalHostIpSubnets": { + "description": "Additional host IP subnets assigned to this VLAN.", + "items": { + "type": "string" + }, + "maxItems": 64, + "minItems": 1, + "type": "array" + }, + "autoScaleEnabled": { + "description": "Whether the Network can automatically scale its subnet size based on the number of active DHCP leases.", + "type": "boolean" + }, + "dhcpConfiguration": { + "$ref": "#/components/schemas/Gateway Managed IPv4 DHCP Configuration", + "description": "IPv4 DHCP configuration for this network. If this field is omitted or null, DHCP is not working and hosts must get an address statically or from another server in this broadcast domain." + }, + "hostIpAddress": { + "type": "string" + }, + "natOutboundIpAddressConfiguration": { + "description": "List of NAT Outbound Configurations defining which IP addresses are used for NAT translation. This array must contain all WAN interfaces with `static` or `PPPoE` IPv4 connection configuration.", + "items": { + "$ref": "#/components/schemas/WAN NAT Outbound Configuration" + }, + "maxItems": 2147483647, + "minItems": 1, + "type": "array" + }, + "prefixLength": { + "format": "int32", + "maximum": 30, + "minimum": 8, + "type": "integer" + } + }, + "required": [ + "autoScaleEnabled", + "hostIpAddress", + "prefixLength" + ], + "type": "object" + }, + "Gateway Managed IPv4 DHCP Configuration": { + "discriminator": { + "mapping": { + "RELAY": "#/components/schemas/IPv4 DHCP Relay Configuration", + "SERVER": "#/components/schemas/Gateway Managed IPv4 DHCP Server Configuration" + }, + "propertyName": "mode" + }, + "properties": { + "mode": { + "type": "string" + } + }, + "required": [ + "mode" + ] + }, + "Gateway Managed IPv4 DHCP Server Configuration": { + "allOf": [ + { + "$ref": "#/components/schemas/Gateway Managed IPv4 DHCP Configuration" + }, + { + "properties": { + "dnsServerIpAddressesOverride": { + "description": "List of DNS servers assigned to client devices by the DHCP server. If none are specified, they will be selected automatically.", + "items": { + "type": "string" + }, + "maxItems": 4, + "minItems": 1, + "type": "array" + }, + "domainName": { + "description": "Domain name that can be used to access network in the browser.", + "type": "string" + }, + "gatewayIpAddressOverride": { + "description": "Gateway IP address provided to DHCP clients. If null, the default gateway will be assigned.", + "type": "string" + }, + "ipAddressRange": { + "$ref": "#/components/schemas/IP address range" + }, + "leaseTimeSeconds": { + "description": "The lease time in seconds for addresses in this range.", + "format": "int32", + "maximum": 31536000, + "minimum": 0, + "type": "integer" + }, + "ntpServerIpAddresses": { + "description": "Network Time Protocol (NTP) server IP addresses.", + "items": { + "type": "string" + }, + "maxItems": 2, + "minItems": 1, + "type": "array" + }, + "option43Value": { + "description": "Custom DHCP option (43) — the value MUST be the UniFi Network application's host IP address.", + "type": "string" + }, + "pingConflictDetectionEnabled": { + "type": "boolean" + }, + "pxeConfiguration": { + "$ref": "#/components/schemas/PXE Configuration", + "description": "Pre execution environment configuration for network boot" + }, + "tftpServerAddress": { + "description": "Trivial File Transfer Protocol (TFTP) server address — accepts a hostname, URL or IP address.", + "type": "string" + }, + "timeOffsetSeconds": { + "description": "Time offset in seconds from UTC.", + "format": "int32", + "maximum": 86400, + "minimum": -86400, + "type": "integer" + }, + "winsServerIpAddresses": { + "description": "Windows Internet Name Service (WINS) server IP addresses.", + "items": { + "type": "string" + }, + "maxItems": 2, + "minItems": 1, + "type": "array" + }, + "wpadUrl": { + "description": "Web Proxy Auto-Discovery (WPAD) URL.", + "type": "string" + } + }, + "type": "object" + } + ], + "required": [ + "ipAddressRange", + "leaseTimeSeconds", + "pingConflictDetectionEnabled" + ] + }, + "Gateway managed network details": { + "allOf": [ + { + "$ref": "#/components/schemas/Network details" + }, + { + "properties": { + "cellularBackupEnabled": { + "description": "Whether this network is allowed to use cellular data when WAN connection(s) are down.", + "type": "boolean" + }, + "internetAccessEnabled": { + "description": "Whether the internet access is allowed for the device on this network.", + "type": "boolean" + }, + "ipv4Configuration": { + "$ref": "#/components/schemas/Gateway Managed IPv4 Configuration", + "description": "Details about IPv4 configuration for this Network." + }, + "ipv6Configuration": { + "$ref": "#/components/schemas/Network IPv6 Configuration", + "description": "Details about IPv6 configuration for this Network. If this field is omitted or null then IPv6 is not configured on this Network." + }, + "isolationEnabled": { + "description": "Whether this network is isolated from all other networks.", + "type": "boolean" + }, + "mdnsForwardingEnabled": { + "description": "Whether this network should participate in mDNS traffic forwarding.", + "type": "boolean" + }, + "zoneId": { + "description": "Firewall zone ID associated with this Network.", + "format": "uuid", + "type": "string" + } + }, + "type": "object" + } + ], + "required": [ + "cellularBackupEnabled", + "default", + "enabled", + "id", + "internetAccessEnabled", + "ipv4Configuration", + "isolationEnabled", + "mdnsForwardingEnabled", + "metadata", + "name", + "vlanId" + ] + }, + "Gateway managed network overview": { + "allOf": [ + { + "$ref": "#/components/schemas/Network overview" + }, + { + "properties": { + "zoneId": { + "format": "uuid", + "type": "string" + } + }, + "type": "object" + } + ], + "required": [ + "default", + "enabled", + "id", + "metadata", + "name", + "vlanId" + ] + }, + "Guest access authorization request": { + "allOf": [ + { + "$ref": "#/components/schemas/Client action request" + }, + { + "properties": { + "dataUsageLimitMBytes": { + "description": "(Optional) data usage limit in megabytes", + "format": "int64", + "maximum": 1048576, + "minimum": 1, + "type": "integer" + }, + "rxRateLimitKbps": { + "description": "(Optional) download rate limit in kilobits per second", + "format": "int64", + "maximum": 100000, + "minimum": 2, + "type": "integer" + }, + "timeLimitMinutes": { + "description": "(Optional) how long (in minutes) the guest will be authorized to access the network.\nIf not specified, the default limit is used from the site settings", + "format": "int64", + "maximum": 1000000, + "minimum": 1, + "type": "integer" + }, + "txRateLimitKbps": { + "description": "(Optional) upload rate limit in kilobits per second", + "format": "int64", + "maximum": 100000, + "minimum": 2, + "type": "integer" + } + }, + "type": "object" + } + ], + "description": "Authorizes network access to a guest client. Client must be a guest.\nThis action cancels existing active authorization (if exists), creates a new one with new limits\nand resets guest traffic counters." + }, + "Guest access authorization response": { + "allOf": [ + { + "$ref": "#/components/schemas/Client action response" + }, + { + "properties": { + "grantedAuthorization": { + "$ref": "#/components/schemas/Guest authorization details", + "description": "Granted guest authorization" + }, + "revokedAuthorization": { + "$ref": "#/components/schemas/Guest authorization details", + "description": "(Optional) Revoked authorization in case the guest was already authorized at the time of this request" + } + }, + "type": "object" + } + ], + "required": [ + "grantedAuthorization" + ] + }, + "Guest access details": { + "allOf": [ + { + "$ref": "#/components/schemas/Local client access details" + }, + { + "properties": { + "authorization": { + "$ref": "#/components/schemas/Guest authorization details" + }, + "authorized": { + "type": "boolean" + } + }, + "type": "object" + } + ], + "required": [ + "authorized" + ] + }, + "Guest access overview": { + "allOf": [ + { + "$ref": "#/components/schemas/Local client access overview" + }, + { + "properties": { + "authorized": { + "type": "boolean" + } + }, + "type": "object" + } + ], + "required": [ + "authorized" + ] + }, + "Guest access unauthorization request": { + "allOf": [ + { + "$ref": "#/components/schemas/Client action request" + } + ], + "description": "Unauthorizes network access and disconnects a guest client." + }, + "Guest access unauthorization response": { + "allOf": [ + { + "$ref": "#/components/schemas/Client action response" + }, + { + "properties": { + "revokedAuthorization": { + "$ref": "#/components/schemas/Guest authorization details", + "description": "Revoked guest authorization" + } + }, + "type": "object" + } + ], + "required": [ + "revokedAuthorization" + ] + }, + "Guest authorization details": { + "properties": { + "authorizationMethod": { + "description": "Guest authorization method (API, Voucher etc)", + "enum": [ + "VOUCHER", + "API", + "OTHER" + ], + "type": "string" + }, + "authorizedAt": { + "description": "Timestamp when the guest has been authorized", + "format": "date-time", + "type": "string" + }, + "dataUsageLimitMBytes": { + "description": "(Optional) data usage limit in megabytes", + "example": 1024, + "format": "int64", + "type": "integer" + }, + "expiresAt": { + "description": "Timestamp when the guest will get automatically unauthorized", + "format": "date-time", + "type": "string" + }, + "rxRateLimitKbps": { + "description": "(Optional) download rate limit in kilobits per second", + "example": 1000, + "format": "int64", + "type": "integer" + }, + "txRateLimitKbps": { + "description": "(Optional) upload rate limit in kilobits per second", + "example": 1000, + "format": "int64", + "type": "integer" + }, + "usage": { + "$ref": "#/components/schemas/Guest authorization usage details" + } + }, + "required": [ + "authorizationMethod", + "authorizedAt", + "expiresAt" + ], + "type": "object" + }, + "Guest authorization usage details": { + "properties": { + "bytes": { + "format": "int64", + "type": "integer" + }, + "durationSec": { + "format": "int64", + "type": "integer" + }, + "rxBytes": { + "format": "int64", + "type": "integer" + }, + "txBytes": { + "format": "int64", + "type": "integer" + } + }, + "required": [ + "bytes", + "durationSec", + "rxBytes", + "txBytes" + ], + "type": "object" + }, + "Hotspot voucher creation request": { + "properties": { + "authorizedGuestLimit": { + "description": "(Optional) limit for how many different guests can use the same voucher to authorize network access", + "example": 1, + "format": "int64", + "minimum": 1, + "type": "integer" + }, + "count": { + "default": 1, + "description": "Number of vouchers to generate", + "format": "int32", + "maximum": 1000, + "minimum": 1, + "type": "integer" + }, + "dataUsageLimitMBytes": { + "description": "(Optional) data usage limit in megabytes", + "format": "int64", + "maximum": 1048576, + "minimum": 1, + "type": "integer" + }, + "name": { + "description": "Voucher note, duplicated across all generated vouchers", + "minLength": 1, + "type": "string" + }, + "rxRateLimitKbps": { + "description": "(Optional) download rate limit in kilobits per second", + "format": "int64", + "maximum": 100000, + "minimum": 2, + "type": "integer" + }, + "timeLimitMinutes": { + "description": "How long (in minutes) the voucher will provide access to the network since authorization of the first guest.\nSubsequently connected guests, if allowed, will share the same expiration time.", + "format": "int64", + "maximum": 1000000, + "minimum": 1, + "type": "integer" + }, + "txRateLimitKbps": { + "description": "(Optional) upload rate limit in kilobits per second", + "format": "int64", + "maximum": 100000, + "minimum": 2, + "type": "integer" + } + }, + "required": [ + "name", + "timeLimitMinutes" + ], + "type": "object" + }, + "Hotspot voucher detail page": { + "properties": { + "count": { + "example": 10, + "format": "int32", + "type": "integer" + }, + "data": { + "items": { + "$ref": "#/components/schemas/Hotspot voucher details" + }, + "type": "array" + }, + "limit": { + "example": 25, + "format": "int32", + "type": "integer" + }, + "offset": { + "example": 0, + "format": "int64", + "type": "integer" + }, + "totalCount": { + "example": 1000, + "format": "int64", + "type": "integer" + } + }, + "required": [ + "count", + "data", + "limit", + "offset", + "totalCount" + ], + "type": "object" + }, + "Hotspot voucher details": { + "properties": { + "activatedAt": { + "description": "(Optional) timestamp when the voucher has been activated (authorization time of the first guest)", + "format": "date-time", + "type": "string" + }, + "authorizedGuestCount": { + "description": "For how many guests the voucher has been used to authorize network access", + "example": 0, + "format": "int64", + "type": "integer" + }, + "authorizedGuestLimit": { + "description": "(Optional) limit for how many different guests can use the same voucher to authorize network access", + "example": 1, + "format": "int64", + "type": "integer" + }, + "code": { + "description": "Secret code to active the voucher using the Hotspot portal", + "example": 4861409510, + "type": "string" + }, + "createdAt": { + "format": "date-time", + "type": "string" + }, + "dataUsageLimitMBytes": { + "description": "(Optional) data usage limit in megabytes", + "example": 1024, + "format": "int64", + "type": "integer" + }, + "expired": { + "description": "Whether the voucher has been expired and can no longer be used to authorize network access", + "type": "boolean" + }, + "expiresAt": { + "description": "(Optional) timestamp when the voucher will become expired. All guests using the voucher will be unauthorized from network access", + "format": "date-time", + "type": "string" + }, + "id": { + "format": "uuid", + "type": "string" + }, + "name": { + "description": "Voucher note, may contain duplicate values across multiple vouchers", + "example": "hotel-guest", + "type": "string" + }, + "rxRateLimitKbps": { + "description": "(Optional) download rate limit in kilobits per second", + "example": 1000, + "format": "int64", + "type": "integer" + }, + "timeLimitMinutes": { + "description": "How long (in minutes) the voucher will provide access to the network since authorization of the first guest.\nSubsequently connected guests, if allowed, will share the same expiration time.", + "example": 1440, + "format": "int64", + "type": "integer" + }, + "txRateLimitKbps": { + "description": "(Optional) upload rate limit in kilobits per second", + "example": 1000, + "format": "int64", + "type": "integer" + } + }, + "required": [ + "authorizedGuestCount", + "code", + "createdAt", + "expired", + "id", + "name", + "timeLimitMinutes" + ], + "type": "object" + }, + "IP ACL rule endpoint": { + "discriminator": { + "mapping": { + "IP_ADDRESSES_OR_SUBNETS": "#/components/schemas/IntegrationIpAclRuleSubnetEndpointFilterDto", + "NETWORKS": "#/components/schemas/IntegrationIpAclRuleNetworkEndpointFilterDto", + "PORTS": "#/components/schemas/IntegrationIpAclRulePortEndpointFilterDto" + }, + "propertyName": "type" + }, + "properties": { + "type": { + "type": "string" + } + }, + "required": [ + "type" + ] + }, + "IP Address selector": { + "allOf": [ + { + "$ref": "#/components/schemas/IP address selector" + }, + { + "properties": { + "value": { + "type": "string" + } + }, + "type": "object" + } + ], + "required": [ + "value" + ] + }, + "IP address range": { + "properties": { + "start": { + "type": "string" + }, + "stop": { + "type": "string" + } + }, + "required": [ + "start", + "stop" + ], + "type": "object" + }, + "IP address range selector": { + "allOf": [ + { + "$ref": "#/components/schemas/IP address selector" + }, + { + "properties": { + "start": { + "type": "string" + }, + "stop": { + "type": "string" + } + }, + "type": "object" + } + ], + "required": [ + "start", + "stop" + ] + }, + "IP address selector": { + "discriminator": { + "mapping": { + "IP_ADDRESS": "#/components/schemas/IP Address selector", + "IP_ADDRESS_RANGE": "#/components/schemas/IP address range selector" + }, + "propertyName": "type" + }, + "properties": { + "type": { + "type": "string" + } + }, + "required": [ + "type" + ] + }, + "IP matching": { + "discriminator": { + "mapping": { + "IP_ADDRESS": "#/components/schemas/IntegrationFirewallPolicyIpMatchingIpAddressDto", + "IP_ADDRESS_RANGE": "#/components/schemas/IntegrationFirewallPolicyIpMatchingRangeDto", + "SUBNET": "#/components/schemas/IntegrationFirewallPolicyIpMatchingSubnetDto" + }, + "propertyName": "type" + }, + "properties": { + "type": { + "type": "string" + } + }, + "required": [ + "type" + ] + }, + "IPv4 DHCP Relay Configuration": { + "allOf": [ + { + "$ref": "#/components/schemas/Gateway Managed IPv4 DHCP Configuration" + }, + { + "properties": { + "dhcpServerIpAddresses": { + "description": "DHCP Server IP addresses", + "items": { + "type": "string" + }, + "minItems": 1, + "type": "array" + } + }, + "type": "object" + }, + { + "$ref": "#/components/schemas/Switch Managed IPv4 DHCP Configuration" + } + ], + "required": [ + "dhcpServerIpAddresses" + ] + }, + "IPv4 DHCP Server Configuration": { + "allOf": [ + { + "$ref": "#/components/schemas/Switch Managed IPv4 DHCP Configuration" + }, + { + "properties": { + "dnsServerIpAddressesOverride": { + "description": "List of DNS servers assigned to client devices by the DHCP server. If none are specified, they will be selected automatically.", + "items": { + "type": "string" + }, + "maxItems": 4, + "minItems": 1, + "type": "array" + }, + "domainName": { + "description": "Domain name that can be used to access network in the browser.", + "type": "string" + }, + "gatewayIpAddressOverride": { + "description": "Gateway IP address provided to DHCP clients. If null, the default gateway will be assigned.", + "type": "string" + }, + "ipAddressRange": { + "$ref": "#/components/schemas/IP address range" + }, + "leaseTimeSeconds": { + "description": "The lease time in seconds for addresses in this range.", + "format": "int32", + "maximum": 31536000, + "minimum": 0, + "type": "integer" + } + }, + "type": "object" + } + ], + "required": [ + "ipAddressRange", + "leaseTimeSeconds" + ] + }, + "IPv4 matching": { + "discriminator": { + "mapping": { + "IP_ADDRESS": "#/components/schemas/Address IPv4 matching", + "IP_ADDRESS_RANGE": "#/components/schemas/Address range IPv4 matching", + "SUBNET": "#/components/schemas/Subnet IPv4 matching" + }, + "propertyName": "type" + }, + "properties": { + "type": { + "type": "string" + } + }, + "required": [ + "type" + ] + }, + "IPv6 Client Address Assignment": { + "properties": { + "dhcpConfiguration": { + "$ref": "#/components/schemas/DHCP Configuration for IPv6 Network", + "description": "IPv6 DHCP configuration for this network. At least one addressing method must be active: either enable SLAAC or provide DHCP configuration. If this field is null, SLAAC must be enabled." + }, + "slaacEnabled": { + "description": "Allows devices to obtain IPv6 addresses via SLAAC (Stateless Address Autoconfiguration) without DHCPv6. At least one addressing method must be active: either enable SLAAC or provide DHCP configuration.", + "type": "boolean" + } + }, + "required": [ + "slaacEnabled" + ], + "type": "object" + }, + "IPv6 Static Configuration": { + "allOf": [ + { + "$ref": "#/components/schemas/Network IPv6 Configuration" + }, + { + "properties": { + "hostIpAddress": { + "description": "The static IPv6 address assigned to this Network.", + "type": "string" + }, + "prefixLength": { + "format": "int32", + "maximum": 127, + "minimum": 64, + "type": "integer" + } + }, + "type": "object" + } + ], + "required": [ + "clientAddressAssignment", + "hostIpAddress", + "prefixLength" + ] + }, + "IPv6 matching": { + "discriminator": { + "mapping": { + "IP_ADDRESS": "#/components/schemas/Address IPv6 matching", + "SUBNET": "#/components/schemas/Subnet IPv6 matching" + }, + "propertyName": "type" + }, + "properties": { + "type": { + "type": "string" + } + }, + "required": [ + "type" + ] + }, + "IntegerType": { + "allOf": [ + { + "$ref": "#/components/schemas/ScalarType" + } + ] + }, + "Integration blackout schedule configuration": { + "properties": { + "days": { + "items": { + "$ref": "#/components/schemas/Blackout schedule configuration per day" + }, + "minItems": 1, + "type": "array" + } + }, + "required": [ + "days" + ], + "type": "object" + }, + "IntegrationAclRuleDevicesFilterDto": { + "allOf": [ + { + "$ref": "#/components/schemas/ACL rule device filter" + }, + { + "properties": { + "deviceIds": { + "description": "List of Switch capable device IDs to which the ACL rule will be provisioned.", + "items": { + "format": "uuid", + "type": "string" + }, + "minItems": 1, + "type": "array", + "uniqueItems": true + } + }, + "type": "object" + } + ], + "required": [ + "deviceIds" + ] + }, + "IntegrationAclRulePageDto": { + "properties": { + "count": { + "example": 10, + "format": "int32", + "type": "integer" + }, + "data": { + "items": { + "$ref": "#/components/schemas/ACL ruleObject" + }, + "type": "array" + }, + "limit": { + "example": 25, + "format": "int32", + "type": "integer" + }, + "offset": { + "example": 0, + "format": "int64", + "type": "integer" + }, + "totalCount": { + "example": 1000, + "format": "int64", + "type": "integer" + } + }, + "required": [ + "count", + "data", + "limit", + "offset", + "totalCount" + ], + "type": "object" + }, + "IntegrationDerivedSiteToSiteTunnelMetadata": { + "allOf": [ + { + "$ref": "#/components/schemas/Site-to-site VPN tunnel metadata" + }, + { + "properties": { + "source": { + "enum": [ + "SDWAN" + ], + "type": "string" + } + }, + "type": "object" + } + ], + "required": [ + "source" + ] + }, + "IntegrationDeviceAdoptionRequestDto": { + "properties": { + "ignoreDeviceLimit": { + "type": "boolean" + }, + "macAddress": { + "type": "string" + } + }, + "required": [ + "ignoreDeviceLimit", + "macAddress" + ], + "type": "object" + }, + "IntegrationDeviceTagPageDto": { + "properties": { + "count": { + "example": 10, + "format": "int32", + "type": "integer" + }, + "data": { + "items": { + "$ref": "#/components/schemas/Device tag" + }, + "type": "array" + }, + "limit": { + "example": 25, + "format": "int32", + "type": "integer" + }, + "offset": { + "example": 0, + "format": "int64", + "type": "integer" + }, + "totalCount": { + "example": 1000, + "format": "int64", + "type": "integer" + } + }, + "required": [ + "count", + "data", + "limit", + "offset", + "totalCount" + ], + "type": "object" + }, + "IntegrationDnsARecordCreateUpdateDto": { + "allOf": [ + { + "$ref": "#/components/schemas/Create or update DNS policy" + }, + { + "properties": { + "domain": { + "example": "example.com", + "maxLength": 127, + "minLength": 1, + "type": "string" + }, + "ipv4Address": { + "example": "192.168.1.10", + "type": "string" + }, + "ttlSeconds": { + "description": "Time to live in seconds.", + "example": 14400, + "format": "int32", + "maximum": 86400, + "minimum": 0, + "type": "integer" + } + }, + "type": "object" + } + ], + "required": [ + "domain", + "enabled", + "ipv4Address", + "ttlSeconds" + ] + }, + "IntegrationDnsARecordDto": { + "allOf": [ + { + "$ref": "#/components/schemas/DNS policy" + }, + { + "properties": { + "domain": { + "example": "example.com", + "maxLength": 127, + "minLength": 1, + "type": "string" + }, + "ipv4Address": { + "example": "192.168.1.10", + "type": "string" + }, + "ttlSeconds": { + "description": "Time to live in seconds.", + "example": 14400, + "format": "int32", + "maximum": 86400, + "minimum": 0, + "type": "integer" + } + }, + "type": "object" + } + ], + "required": [ + "domain", + "enabled", + "id", + "ipv4Address", + "metadata", + "ttlSeconds" + ] + }, + "IntegrationDnsAaaaRecordCreateUpdateDto": { + "allOf": [ + { + "$ref": "#/components/schemas/Create or update DNS policy" + }, + { + "properties": { + "domain": { + "example": "example.com", + "maxLength": 127, + "minLength": 1, + "type": "string" + }, + "ipv6Address": { + "example": "cafe::babe", + "type": "string" + }, + "ttlSeconds": { + "description": "Time to live in seconds.", + "example": 14400, + "format": "int32", + "maximum": 86400, + "minimum": 0, + "type": "integer" + } + }, + "type": "object" + } + ], + "required": [ + "domain", + "enabled", + "ipv6Address", + "ttlSeconds" + ] + }, + "IntegrationDnsAaaaRecordDto": { + "allOf": [ + { + "$ref": "#/components/schemas/DNS policy" + }, + { + "properties": { + "domain": { + "example": "example.com", + "maxLength": 127, + "minLength": 1, + "type": "string" + }, + "ipv6Address": { + "example": "cafe::babe", + "type": "string" + }, + "ttlSeconds": { + "description": "Time to live in seconds.", + "example": 14400, + "format": "int32", + "maximum": 86400, + "minimum": 0, + "type": "integer" + } + }, + "type": "object" + } + ], + "required": [ + "domain", + "enabled", + "id", + "ipv6Address", + "metadata", + "ttlSeconds" + ] + }, + "IntegrationDnsCnameRecordCreateUpdateDto": { + "allOf": [ + { + "$ref": "#/components/schemas/Create or update DNS policy" + }, + { + "properties": { + "domain": { + "example": "example.com", + "maxLength": 127, + "minLength": 1, + "type": "string" + }, + "targetDomain": { + "example": "target.example.com", + "maxLength": 127, + "minLength": 1, + "type": "string" + }, + "ttlSeconds": { + "description": "Time to live in seconds.", + "example": 14400, + "format": "int32", + "maximum": 604800, + "minimum": 0, + "type": "integer" + } + }, + "type": "object" + } + ], + "required": [ + "domain", + "enabled", + "targetDomain", + "ttlSeconds" + ] + }, + "IntegrationDnsCnameRecordDto": { + "allOf": [ + { + "$ref": "#/components/schemas/DNS policy" + }, + { + "properties": { + "domain": { + "example": "example.com", + "maxLength": 127, + "minLength": 1, + "type": "string" + }, + "targetDomain": { + "example": "target.example.com", + "maxLength": 127, + "minLength": 1, + "type": "string" + }, + "ttlSeconds": { + "description": "Time to live in seconds.", + "example": 14400, + "format": "int32", + "maximum": 604800, + "minimum": 0, + "type": "integer" + } + }, + "type": "object" + } + ], + "required": [ + "domain", + "enabled", + "id", + "metadata", + "targetDomain", + "ttlSeconds" + ] + }, + "IntegrationDnsForwardDomainPolicyCreateUpdateDto": { + "allOf": [ + { + "$ref": "#/components/schemas/Create or update DNS policy" + }, + { + "properties": { + "domain": { + "example": "example.com", + "maxLength": 127, + "minLength": 1, + "type": "string" + }, + "ipAddress": { + "description": "IP address of the DNS Server that the DNS query is forwarded to.", + "example": "8.8.4.4|2001:4860:4860::8844", + "type": "string" + } + }, + "type": "object" + } + ], + "required": [ + "domain", + "enabled", + "ipAddress" + ] + }, + "IntegrationDnsForwardDomainPolicyDto": { + "allOf": [ + { + "$ref": "#/components/schemas/DNS policy" + }, + { + "properties": { + "domain": { + "example": "example.com", + "maxLength": 127, + "minLength": 1, + "type": "string" + }, + "ipAddress": { + "description": "IP address of the DNS Server that the DNS query is forwarded to.", + "example": "8.8.4.4|2001:4860:4860::8844", + "type": "string" + } + }, + "type": "object" + } + ], + "required": [ + "domain", + "enabled", + "id", + "ipAddress", + "metadata" + ] + }, + "IntegrationDnsMxRecordCreateUpdateDto": { + "allOf": [ + { + "$ref": "#/components/schemas/Create or update DNS policy" + }, + { + "properties": { + "domain": { + "example": "example.com", + "maxLength": 127, + "minLength": 1, + "type": "string" + }, + "mailServerDomain": { + "example": "mail.example.com", + "maxLength": 127, + "minLength": 1, + "type": "string" + }, + "priority": { + "description": "Priority. A lower number is preferred.", + "example": 255, + "format": "int32", + "maximum": 65535, + "minimum": 0, + "type": "integer" + } + }, + "type": "object" + } + ], + "required": [ + "domain", + "enabled", + "mailServerDomain", + "priority" + ] + }, + "IntegrationDnsMxRecordDto": { + "allOf": [ + { + "$ref": "#/components/schemas/DNS policy" + }, + { + "properties": { + "domain": { + "example": "example.com", + "maxLength": 127, + "minLength": 1, + "type": "string" + }, + "mailServerDomain": { + "example": "mail.example.com", + "maxLength": 127, + "minLength": 1, + "type": "string" + }, + "priority": { + "description": "Priority. A lower number is preferred.", + "example": 255, + "format": "int32", + "maximum": 65535, + "minimum": 0, + "type": "integer" + } + }, + "type": "object" + } + ], + "required": [ + "domain", + "enabled", + "id", + "mailServerDomain", + "metadata", + "priority" + ] + }, + "IntegrationDnsPolicyPageDto": { + "properties": { + "count": { + "example": 10, + "format": "int32", + "type": "integer" + }, + "data": { + "items": { + "$ref": "#/components/schemas/DNS policy" + }, + "type": "array" + }, + "limit": { + "example": 25, + "format": "int32", + "type": "integer" + }, + "offset": { + "example": 0, + "format": "int64", + "type": "integer" + }, + "totalCount": { + "example": 1000, + "format": "int64", + "type": "integer" + } + }, + "required": [ + "count", + "data", + "limit", + "offset", + "totalCount" + ], + "type": "object" + }, + "IntegrationDnsSrvRecordCreateUpdateDto": { + "allOf": [ + { + "$ref": "#/components/schemas/Create or update DNS policy" + }, + { + "properties": { + "domain": { + "example": "example.com", + "maxLength": 127, + "minLength": 1, + "type": "string" + }, + "port": { + "format": "int32", + "maximum": 65535, + "minimum": 0, + "type": "integer" + }, + "priority": { + "description": "Priority. A lower number is preferred.", + "example": 255, + "format": "int32", + "maximum": 65535, + "minimum": 0, + "type": "integer" + }, + "protocol": { + "description": "Protocol used by the service.", + "example": "_tcp", + "type": "string" + }, + "serverDomain": { + "description": "Domain of the server that is running the service.", + "example": "server.example.com", + "maxLength": 127, + "minLength": 1, + "type": "string" + }, + "service": { + "description": "Service associated with this SRV record.", + "example": "_ldap", + "type": "string" + }, + "weight": { + "description": "Weight. A relative value applicable for records with the same priority. A lower number is preferred.", + "example": 128, + "format": "int32", + "maximum": 65535, + "minimum": 0, + "type": "integer" + } + }, + "type": "object" + } + ], + "required": [ + "domain", + "enabled", + "port", + "priority", + "protocol", + "serverDomain", + "service", + "weight" + ] + }, + "IntegrationDnsSrvRecordDto": { + "allOf": [ + { + "$ref": "#/components/schemas/DNS policy" + }, + { + "properties": { + "domain": { + "example": "example.com", + "maxLength": 127, + "minLength": 1, + "type": "string" + }, + "port": { + "format": "int32", + "maximum": 65535, + "minimum": 0, + "type": "integer" + }, + "priority": { + "description": "Priority. A lower number is preferred.", + "example": 255, + "format": "int32", + "maximum": 65535, + "minimum": 0, + "type": "integer" + }, + "protocol": { + "description": "Protocol used by the service.", + "example": "_tcp", + "type": "string" + }, + "serverDomain": { + "description": "Domain of the server that is running the service.", + "example": "server.example.com", + "maxLength": 127, + "minLength": 1, + "type": "string" + }, + "service": { + "description": "Service associated with this SRV record.", + "example": "_ldap", + "type": "string" + }, + "weight": { + "description": "Weight. A relative value applicable for records with the same priority. A lower number is preferred.", + "example": 128, + "format": "int32", + "maximum": 65535, + "minimum": 0, + "type": "integer" + } + }, + "type": "object" + } + ], + "required": [ + "domain", + "enabled", + "id", + "metadata", + "port", + "priority", + "protocol", + "serverDomain", + "service", + "weight" + ] + }, + "IntegrationDnsTxtRecordCreateUpdateDto": { + "allOf": [ + { + "$ref": "#/components/schemas/Create or update DNS policy" + }, + { + "properties": { + "domain": { + "example": "example.com", + "maxLength": 127, + "minLength": 1, + "type": "string" + }, + "text": { + "description": "The text value associated with this TXT DNS record. Text can contain up to four 255-character strings. Lines containing commas must be enclosed in double quotes (\").", + "example": "This is an example value of a TXT DNS Record.", + "maxLength": 1024, + "minLength": 1, + "type": "string" + } + }, + "type": "object" + } + ], + "required": [ + "domain", + "enabled", + "text" + ] + }, + "IntegrationDnsTxtRecordDto": { + "allOf": [ + { + "$ref": "#/components/schemas/DNS policy" + }, + { + "properties": { + "domain": { + "example": "example.com", + "maxLength": 127, + "minLength": 1, + "type": "string" + }, + "text": { + "description": "The text value associated with this TXT DNS record. Text can contain up to four 255-character strings. Lines containing commas must be enclosed in double quotes (\").", + "example": "This is an example value of a TXT DNS Record.", + "maxLength": 1024, + "minLength": 1, + "type": "string" + } + }, + "type": "object" + } + ], + "required": [ + "domain", + "enabled", + "id", + "metadata", + "text" + ] + }, + "IntegrationFirewallPolicyActionAllowDto": { + "allOf": [ + { + "$ref": "#/components/schemas/Firewall policy action" + }, + { + "properties": { + "allowReturnTraffic": { + "description": "Creates a derived policy for the mirrored firewall zone pair to automatically allow the return traffic.", + "type": "boolean" + } + }, + "type": "object" + } + ], + "required": [ + "allowReturnTraffic" + ] + }, + "IntegrationFirewallPolicyActionBlockDto": { + "allOf": [ + { + "$ref": "#/components/schemas/Firewall policy action" + } + ] + }, + "IntegrationFirewallPolicyActionRejectDto": { + "allOf": [ + { + "$ref": "#/components/schemas/Firewall policy action" + } + ] + }, + "IntegrationFirewallPolicyDestinationApplicationCategoryFilterDto": { + "allOf": [ + { + "$ref": "#/components/schemas/Firewall policy destination traffic filter" + }, + { + "properties": { + "applicationCategoryFilter": { + "$ref": "#/components/schemas/Firewall policy application category filter", + "description": "Match destination traffic by DPI application categories." + }, + "portFilter": { + "$ref": "#/components/schemas/Firewall policy port filter", + "description": "Match destination traffic additionally by ports. If null, match all ports." + } + }, + "type": "object" + } + ], + "required": [ + "applicationCategoryFilter" + ] + }, + "IntegrationFirewallPolicyDestinationApplicationFilterDto": { + "allOf": [ + { + "$ref": "#/components/schemas/Firewall policy destination traffic filter" + }, + { + "properties": { + "applicationFilter": { + "$ref": "#/components/schemas/Firewall policy application filter", + "description": "Match destination traffic by DPI applications." + }, + "portFilter": { + "$ref": "#/components/schemas/Firewall policy port filter", + "description": "Match destination traffic additionally by ports. If null, match all ports." + } + }, + "type": "object" + } + ], + "required": [ + "applicationFilter" + ] + }, + "IntegrationFirewallPolicyDestinationDomainFilterDto": { + "allOf": [ + { + "$ref": "#/components/schemas/Firewall policy destination traffic filter" + }, + { + "properties": { + "domainFilter": { + "$ref": "#/components/schemas/Firewall policy domain filter", + "description": "Match destination traffic by domains." + }, + "portFilter": { + "$ref": "#/components/schemas/Firewall policy port filter", + "description": "Match destination traffic additionally by ports. If null, match all ports." + } + }, + "type": "object" + } + ], + "required": [ + "domainFilter" + ] + }, + "IntegrationFirewallPolicyDestinationIpAddressFilterDto": { + "allOf": [ + { + "$ref": "#/components/schemas/Firewall policy destination traffic filter" + }, + { + "properties": { + "ipAddressFilter": { + "$ref": "#/components/schemas/Firewall policy IP address filter", + "description": "Match destination traffic by IP addresses." + }, + "portFilter": { + "$ref": "#/components/schemas/Firewall policy port filter", + "description": "Match destination traffic additionally by ports. If null, match all ports." + } + }, + "type": "object" + } + ], + "required": [ + "ipAddressFilter" + ] + }, + "IntegrationFirewallPolicyDestinationIpv6IidFilterDto": { + "allOf": [ + { + "$ref": "#/components/schemas/Firewall policy destination traffic filter" + }, + { + "properties": { + "ipv6IidFilter": { + "$ref": "#/components/schemas/Firewall policy IPv6 interface identifier filter", + "description": "Match destination traffic by IPv6 interface identifier." + }, + "portFilter": { + "$ref": "#/components/schemas/Firewall policy port filter", + "description": "Match destination traffic additionally by ports. If null, match all ports." + } + }, + "type": "object" + } + ], + "required": [ + "ipv6IidFilter" + ] + }, + "IntegrationFirewallPolicyDestinationNetworkFilterDto": { + "allOf": [ + { + "$ref": "#/components/schemas/Firewall policy destination traffic filter" + }, + { + "properties": { + "networkFilter": { + "$ref": "#/components/schemas/Firewall policy network filter", + "description": "Match destination traffic by networks." + }, + "portFilter": { + "$ref": "#/components/schemas/Firewall policy port filter", + "description": "Match destination traffic additionally by ports. If null, match all ports." + } + }, + "type": "object" + } + ], + "required": [ + "networkFilter" + ] + }, + "IntegrationFirewallPolicyDestinationPortFilterDto": { + "allOf": [ + { + "$ref": "#/components/schemas/Firewall policy destination traffic filter" + }, + { + "properties": { + "portFilter": { + "$ref": "#/components/schemas/Firewall policy port filter", + "description": "Match destination traffic by ports." + } + }, + "type": "object" + } + ], + "required": [ + "portFilter" + ] + }, + "IntegrationFirewallPolicyDestinationRegionFilterDto": { + "allOf": [ + { + "$ref": "#/components/schemas/Firewall policy destination traffic filter" + }, + { + "properties": { + "portFilter": { + "$ref": "#/components/schemas/Firewall policy port filter", + "description": "Match destination traffic additionally by ports. If null, match all ports." + }, + "regionFilter": { + "$ref": "#/components/schemas/Firewall policy region filter", + "description": "Match destination traffic by regions." + } + }, + "type": "object" + } + ], + "required": [ + "regionFilter" + ] + }, + "IntegrationFirewallPolicyDestinationSiteToSiteVpnTunnelFilterDto": { + "allOf": [ + { + "$ref": "#/components/schemas/Firewall policy destination traffic filter" + }, + { + "properties": { + "portFilter": { + "$ref": "#/components/schemas/Firewall policy port filter", + "description": "Match destination traffic additionally by ports. If null, match all ports." + }, + "siteToSiteVpnTunnelFilter": { + "$ref": "#/components/schemas/Firewall policy site-to-site VPN tunnel filter", + "description": "Match destination traffic by site-to-site VPN tunnel." + } + }, + "type": "object" + } + ], + "required": [ + "siteToSiteVpnTunnelFilter" + ] + }, + "IntegrationFirewallPolicyDestinationVpnServerFilterDto": { + "allOf": [ + { + "$ref": "#/components/schemas/Firewall policy destination traffic filter" + }, + { + "properties": { + "portFilter": { + "$ref": "#/components/schemas/Firewall policy port filter", + "description": "Match destination traffic additionally by ports. If null, match all ports." + }, + "vpnServerFilter": { + "$ref": "#/components/schemas/Firewall policy VPN server filter", + "description": "Match destination traffic by VPN servers." + } + }, + "type": "object" + } + ], + "required": [ + "vpnServerFilter" + ] + }, + "IntegrationFirewallPolicyIpAddressTrafficMatchingListFilterDto": { + "allOf": [ + { + "$ref": "#/components/schemas/Firewall policy IP address filter" + }, + { + "properties": { + "trafficMatchingListId": { + "description": "ID of Traffic Matching List containing IP addresses to match.", + "format": "uuid", + "type": "string" + } + }, + "type": "object" + } + ], + "required": [ + "matchOpposite", + "trafficMatchingListId" + ] + }, + "IntegrationFirewallPolicyIpMatchingIpAddressDto": { + "allOf": [ + { + "$ref": "#/components/schemas/IP matching" + }, + { + "properties": { + "value": { + "description": "IP address to match.", + "type": "string" + } + }, + "type": "object" + } + ], + "required": [ + "value" + ] + }, + "IntegrationFirewallPolicyIpMatchingRangeDto": { + "allOf": [ + { + "$ref": "#/components/schemas/IP matching" + }, + { + "properties": { + "start": { + "description": "First IP address from range to match.", + "type": "string" + }, + "stop": { + "description": "Last IP address from range to match.", + "type": "string" + } + }, + "type": "object" + } + ], + "required": [ + "start", + "stop" + ] + }, + "IntegrationFirewallPolicyIpMatchingSubnetDto": { + "allOf": [ + { + "$ref": "#/components/schemas/IP matching" + }, + { + "properties": { + "value": { + "description": "IP subnet in CIDR notation to match.", + "type": "string" + } + }, + "type": "object" + } + ], + "required": [ + "value" + ] + }, + "IntegrationFirewallPolicyIpv4AndIpv6NamedProtocolDefaultDto": { + "allOf": [ + { + "$ref": "#/components/schemas/Firewall policy IPv4 and IPv6 named protocol" + } + ], + "required": [ + "name" + ] + }, + "IntegrationFirewallPolicyIpv4AndIpv6NamedProtocolFilterDto": { + "allOf": [ + { + "$ref": "#/components/schemas/Firewall policy IPv4 and IPv6 protocol" + }, + { + "properties": { + "matchOpposite": { + "description": "Match on all protocols except the specified protocol.", + "type": "boolean" + }, + "protocol": { + "$ref": "#/components/schemas/Firewall policy IPv4 and IPv6 named protocol" + } + }, + "type": "object" + } + ], + "required": [ + "matchOpposite", + "protocol" + ] + }, + "IntegrationFirewallPolicyIpv4AndIpv6ProtocolPresetFilterDto": { + "allOf": [ + { + "$ref": "#/components/schemas/Firewall policy IPv4 and IPv6 protocol" + }, + { + "properties": { + "preset": { + "$ref": "#/components/schemas/Firewall policy IPv4 and IPv6 protocol preset" + } + }, + "type": "object" + } + ], + "required": [ + "preset" + ] + }, + "IntegrationFirewallPolicyIpv4AndIpv6ProtocolPresetTcpUdpDto": { + "allOf": [ + { + "$ref": "#/components/schemas/Firewall policy IPv4 and IPv6 protocol preset" + } + ] + }, + "IntegrationFirewallPolicyIpv4AndIpv6ProtocolScopeDto": { + "allOf": [ + { + "$ref": "#/components/schemas/Firewall policy IP protocol scope" + }, + { + "properties": { + "protocolFilter": { + "$ref": "#/components/schemas/Firewall policy IPv4 and IPv6 protocol" + } + }, + "type": "object" + } + ] + }, + "IntegrationFirewallPolicyIpv4NamedProtocolDefaultDto": { + "allOf": [ + { + "$ref": "#/components/schemas/Firewall policy IPv4 named protocol" + } + ] + }, + "IntegrationFirewallPolicyIpv4NamedProtocolFilterDto": { + "allOf": [ + { + "$ref": "#/components/schemas/Firewall policy IPv4 protocol" + }, + { + "properties": { + "matchOpposite": { + "description": "Match on all protocols except the specified protocol.", + "type": "boolean" + }, + "protocol": { + "$ref": "#/components/schemas/Firewall policy IPv4 named protocol" + } + }, + "type": "object" + } + ], + "required": [ + "matchOpposite", + "protocol" + ] + }, + "IntegrationFirewallPolicyIpv4NamedProtocolIcmpDto": { + "allOf": [ + { + "$ref": "#/components/schemas/Firewall policy IPv4 named protocol" + }, + { + "properties": { + "typenameFilter": { + "description": "Match specific type of ICMP traffic. If null, matches all types.", + "enum": [ + "ADDRESS_MASK_REPLY", + "ADDRESS_MASK_REQUEST", + "COMMUNICATION_PROHIBITED", + "DESTINATION_UNREACHABLE", + "ECHO_REPLY", + "ECHO_REQUEST", + "FRAGMENTATION_NEEDED", + "HOST_PRECEDENCE_VIOLATION", + "HOST_PROHIBITED", + "HOST_REDIRECT", + "HOST_UNKNOWN", + "HOST_UNREACHABLE", + "IP_HEADER_BAD", + "NETWORK_PROHIBITED", + "NETWORK_REDIRECT", + "NETWORK_UNKNOWN", + "NETWORK_UNREACHABLE", + "PARAMETER_PROBLEM", + "PORT_UNREACHABLE", + "PRECEDENCE_CUTOFF", + "PROTOCOL_UNREACHABLE", + "REDIRECT", + "REQUIRED_OPTION_MISSING", + "ROUTER_ADVERTISEMENT", + "ROUTER_SOLICITATION", + "SOURCE_QUENCH", + "SOURCE_ROUTE_FAILED", + "TIME_EXCEEDED", + "TIMESTAMP_REPLY", + "TIMESTAMP_REQUEST", + "TOS_HOST_REDIRECT", + "TOS_HOST_UNREACHABLE", + "TOS_NETWORK_REDIRECT", + "TOS_NETWORK_UNREACHABLE", + "TTL_ZERO_DURING_REASSEMBLY", + "TTL_ZERO_DURING_TRANSIT" + ], + "type": "string" + } + }, + "type": "object" + } + ] + }, + "IntegrationFirewallPolicyIpv4ProtocolPresetFilterDto": { + "allOf": [ + { + "$ref": "#/components/schemas/Firewall policy IPv4 protocol" + }, + { + "properties": { + "preset": { + "$ref": "#/components/schemas/Firewall policy IPv4 protocol preset" + } + }, + "type": "object" + } + ], + "required": [ + "preset" + ] + }, + "IntegrationFirewallPolicyIpv4ProtocolPresetTcpUdpDto": { + "allOf": [ + { + "$ref": "#/components/schemas/Firewall policy IPv4 protocol preset" + } + ] + }, + "IntegrationFirewallPolicyIpv4ProtocolScopeDto": { + "allOf": [ + { + "$ref": "#/components/schemas/Firewall policy IP protocol scope" + }, + { + "properties": { + "protocolFilter": { + "$ref": "#/components/schemas/Firewall policy IPv4 protocol" + } + }, + "type": "object" + } + ] + }, + "IntegrationFirewallPolicyIpv6NamedProtocolDefaultDto": { + "allOf": [ + { + "$ref": "#/components/schemas/Firewall policy IPv6 named protocol" + } + ] + }, + "IntegrationFirewallPolicyIpv6NamedProtocolFilterDto": { + "allOf": [ + { + "$ref": "#/components/schemas/Firewall policy IPv6 protocol" + }, + { + "properties": { + "matchOpposite": { + "description": "Match on all protocols except the specified protocol.", + "type": "boolean" + }, + "protocol": { + "$ref": "#/components/schemas/Firewall policy IPv6 named protocol" + } + }, + "type": "object" + } + ], + "required": [ + "matchOpposite", + "protocol" + ] + }, + "IntegrationFirewallPolicyIpv6NamedProtocolIcmpv6Dto": { + "allOf": [ + { + "$ref": "#/components/schemas/Firewall policy IPv6 named protocol" + }, + { + "properties": { + "typenameFilter": { + "description": "Match specific type of ICMPv6 traffic. If null, matches all types.", + "enum": [ + "ADDRESS_UNREACHABLE", + "BAD_HEADER", + "BEYOND_SCOPE", + "COMMUNICATION_PROHIBITED", + "DESTINATION_UNREACHABLE", + "ECHO_REPLY", + "ECHO_REQUEST", + "FAILED_POLICY", + "NEIGHBOR_ADVERTISEMENT", + "NEIGHBOR_SOLICITATION", + "NO_ROUTE", + "PACKET_TOO_BIG", + "PARAMETER_PROBLEM", + "PORT_UNREACHABLE", + "REDIRECT", + "REJECT_ROUTE", + "ROUTER_ADVERTISEMENT", + "ROUTER_SOLICITATION", + "TIME_EXCEEDED", + "TTL_ZERO_DURING_REASSEMBLY", + "TTL_ZERO_DURING_TRANSIT", + "UNKNOWN_HEADER_TYPE", + "UNKNOWN_OPTION" + ], + "type": "string" + } + }, + "type": "object" + } + ] + }, + "IntegrationFirewallPolicyIpv6ProtocolPresetFilterDto": { + "allOf": [ + { + "$ref": "#/components/schemas/Firewall policy IPv6 protocol" + }, + { + "properties": { + "preset": { + "$ref": "#/components/schemas/Firewall policy IPv6 protocol preset" + } + }, + "type": "object" + } + ], + "required": [ + "preset" + ] + }, + "IntegrationFirewallPolicyIpv6ProtocolPresetTcpUdpDto": { + "allOf": [ + { + "$ref": "#/components/schemas/Firewall policy IPv6 protocol preset" + } + ] + }, + "IntegrationFirewallPolicyIpv6ProtocolScopeDto": { + "allOf": [ + { + "$ref": "#/components/schemas/Firewall policy IP protocol scope" + }, + { + "properties": { + "protocolFilter": { + "$ref": "#/components/schemas/Firewall policy IPv6 protocol" + } + }, + "type": "object" + } + ] + }, + "IntegrationFirewallPolicyOrderingDto": { + "properties": { + "orderedFirewallPolicyIds": { + "$ref": "#/components/schemas/Ordered firewall policy IDs" + } + }, + "required": [ + "orderedFirewallPolicyIds" + ], + "type": "object" + }, + "IntegrationFirewallPolicyPortReferenceFilterDto": { + "allOf": [ + { + "$ref": "#/components/schemas/Firewall policy port filter" + }, + { + "properties": { + "trafficMatchingListId": { + "description": "ID of Traffic Matching List containing ports to match.", + "format": "uuid", + "type": "string" + } + }, + "type": "object" + } + ], + "required": [ + "matchOpposite", + "trafficMatchingListId" + ] + }, + "IntegrationFirewallPolicyPortValueFilterDto": { + "allOf": [ + { + "$ref": "#/components/schemas/Firewall policy port filter" + }, + { + "properties": { + "items": { + "description": "List of ports or port ranges to match.", + "items": { + "$ref": "#/components/schemas/Port matching" + }, + "minItems": 1, + "type": "array", + "uniqueItems": true + } + }, + "type": "object" + } + ], + "required": [ + "items", + "matchOpposite" + ] + }, + "IntegrationFirewallPolicySourceIpAddressFilterDto": { + "allOf": [ + { + "$ref": "#/components/schemas/Firewall policy source traffic filter" + }, + { + "properties": { + "ipAddressFilter": { + "$ref": "#/components/schemas/Firewall policy IP address filter", + "description": "Match source traffic by IP addresses" + }, + "macAddressFilter": { + "description": "Match source traffic additionally by a MAC address. If null, match all MAC addresses.", + "type": "string" + }, + "portFilter": { + "$ref": "#/components/schemas/Firewall policy port filter", + "description": "Match source traffic additionally by ports. If null, match all ports." + } + }, + "type": "object" + } + ], + "required": [ + "ipAddressFilter" + ] + }, + "IntegrationFirewallPolicySourceIpv6IidFilterDto": { + "allOf": [ + { + "$ref": "#/components/schemas/Firewall policy source traffic filter" + }, + { + "properties": { + "ipv6IidFilter": { + "$ref": "#/components/schemas/Firewall policy IPv6 interface identifier filter", + "description": "Match source traffic by IPv6 interface identifier" + }, + "macAddressFilter": { + "description": "Match source traffic additionally by a MAC address. If null, match all MAC addresses.", + "type": "string" + }, + "portFilter": { + "$ref": "#/components/schemas/Firewall policy port filter", + "description": "Match source traffic additionally by ports. If null, match all ports." + } + }, + "type": "object" + } + ], + "required": [ + "ipv6IidFilter" + ] + }, + "IntegrationFirewallPolicySourceMacAddressFilterDto": { + "allOf": [ + { + "$ref": "#/components/schemas/Firewall policy source traffic filter" + }, + { + "properties": { + "macAddressFilter": { + "$ref": "#/components/schemas/Firewall policy MAC address filter", + "description": "Match source traffic by MAC addresses." + }, + "portFilter": { + "$ref": "#/components/schemas/Firewall policy port filter", + "description": "Match source traffic additionally by ports. If null, match all ports." + } + }, + "type": "object" + } + ], + "required": [ + "macAddressFilter" + ] + }, + "IntegrationFirewallPolicySourceNetworkFilterDto": { + "allOf": [ + { + "$ref": "#/components/schemas/Firewall policy source traffic filter" + }, + { + "properties": { + "macAddressFilter": { + "description": "Match source traffic additionally by a MAC address. If null, match all MAC addresses.", + "type": "string" + }, + "networkFilter": { + "$ref": "#/components/schemas/Firewall policy network filter", + "description": "Match source traffic by networks." + }, + "portFilter": { + "$ref": "#/components/schemas/Firewall policy port filter", + "description": "Match source traffic additionally by ports. If null, match all ports." + } + }, + "type": "object" + } + ], + "required": [ + "networkFilter" + ] + }, + "IntegrationFirewallPolicySourcePortFilterDto": { + "allOf": [ + { + "$ref": "#/components/schemas/Firewall policy source traffic filter" + }, + { + "properties": { + "portFilter": { + "$ref": "#/components/schemas/Firewall policy port filter", + "description": "Match source traffic by ports." + } + }, + "type": "object" + } + ], + "required": [ + "portFilter" + ] + }, + "IntegrationFirewallPolicySourceRegionFilterDto": { + "allOf": [ + { + "$ref": "#/components/schemas/Firewall policy source traffic filter" + }, + { + "properties": { + "portFilter": { + "$ref": "#/components/schemas/Firewall policy port filter", + "description": "Match source traffic additionally by ports. If null, match all ports." + }, + "regionFilter": { + "$ref": "#/components/schemas/Firewall policy region filter", + "description": "Match source traffic by regions." + } + }, + "type": "object" + } + ], + "required": [ + "regionFilter" + ] + }, + "IntegrationFirewallPolicySourceSiteToSiteVpnTunnelFilterDto": { + "allOf": [ + { + "$ref": "#/components/schemas/Firewall policy source traffic filter" + }, + { + "properties": { + "portFilter": { + "$ref": "#/components/schemas/Firewall policy port filter", + "description": "Match source traffic additionally by ports. If null, match all ports." + }, + "siteToSiteVpnTunnelFilter": { + "$ref": "#/components/schemas/Firewall policy site-to-site VPN tunnel filter", + "description": "Match source traffic by site-to-site VPN tunnel." + } + }, + "type": "object" + } + ], + "required": [ + "siteToSiteVpnTunnelFilter" + ] + }, + "IntegrationFirewallPolicySourceVpnServerFilterDto": { + "allOf": [ + { + "$ref": "#/components/schemas/Firewall policy source traffic filter" + }, + { + "properties": { + "portFilter": { + "$ref": "#/components/schemas/Firewall policy port filter", + "description": "Match source traffic additionally by ports. If null, match all ports." + }, + "vpnServerFilter": { + "$ref": "#/components/schemas/Firewall policy VPN server filter", + "description": "Match source traffic by VPN servers." + } + }, + "type": "object" + } + ], + "required": [ + "vpnServerFilter" + ] + }, + "IntegrationFirewallPolicySpecificDomainFilterDto": { + "allOf": [ + { + "$ref": "#/components/schemas/Firewall policy domain filter" + }, + { + "properties": { + "domains": { + "description": "List of domains to match.", + "items": { + "type": "string" + }, + "minItems": 1, + "type": "array", + "uniqueItems": true + } + }, + "type": "object" + } + ], + "required": [ + "domains" + ] + }, + "IntegrationFirewallPolicySpecificIpAddressFilterDto": { + "allOf": [ + { + "$ref": "#/components/schemas/Firewall policy IP address filter" + }, + { + "properties": { + "items": { + "description": "List of IP addresses, IP address ranges, or IP subnets to match.", + "items": { + "$ref": "#/components/schemas/IP matching" + }, + "minItems": 1, + "type": "array", + "uniqueItems": true + } + }, + "type": "object" + } + ], + "required": [ + "items", + "matchOpposite" + ] + }, + "IntegrationFirewallScheduleCustomDto": { + "allOf": [ + { + "$ref": "#/components/schemas/Firewall schedule" + }, + { + "properties": { + "repeatOnDays": { + "items": { + "enum": [ + "MONDAY", + "TUESDAY", + "WEDNESDAY", + "THURSDAY", + "FRIDAY", + "SATURDAY", + "SUNDAY" + ], + "type": "string" + }, + "minItems": 1, + "type": "array", + "uniqueItems": true + }, + "startDate": { + "description": "Date in YYYY-MM-DD format. ISO 8601 compliant.", + "example": "2025-12-31", + "format": "date", + "type": "string" + }, + "stopDate": { + "description": "Date in YYYY-MM-DD format. ISO 8601 compliant.", + "example": "2025-12-31", + "format": "date", + "type": "string" + }, + "timeFilter": { + "$ref": "#/components/schemas/Firewall schedule time" + } + }, + "type": "object" + } + ], + "required": [ + "repeatOnDays", + "startDate", + "stopDate" + ] + }, + "IntegrationFirewallScheduleEveryDayDto": { + "allOf": [ + { + "$ref": "#/components/schemas/Firewall schedule" + }, + { + "properties": { + "timeFilter": { + "$ref": "#/components/schemas/Firewall schedule time" + } + }, + "type": "object" + } + ], + "required": [ + "timeFilter" + ] + }, + "IntegrationFirewallScheduleEveryWeekDto": { + "allOf": [ + { + "$ref": "#/components/schemas/Firewall schedule" + }, + { + "properties": { + "repeatOnDays": { + "items": { + "enum": [ + "MONDAY", + "TUESDAY", + "WEDNESDAY", + "THURSDAY", + "FRIDAY", + "SATURDAY", + "SUNDAY" + ], + "type": "string" + }, + "minItems": 1, + "type": "array", + "uniqueItems": true + }, + "timeFilter": { + "$ref": "#/components/schemas/Firewall schedule time" + } + }, + "type": "object" + } + ], + "required": [ + "repeatOnDays" + ] + }, + "IntegrationFirewallScheduleOneTimeOnlyDto": { + "allOf": [ + { + "$ref": "#/components/schemas/Firewall schedule" + }, + { + "properties": { + "date": { + "description": "Date in YYYY-MM-DD format. ISO 8601 compliant.", + "example": "2025-12-31", + "format": "date", + "type": "string" + }, + "timeFilter": { + "$ref": "#/components/schemas/Firewall schedule time" + } + }, + "type": "object" + } + ], + "required": [ + "date", + "timeFilter" + ] + }, + "IntegrationGatewayManagedNetworkCreateUpdateDto": { + "allOf": [ + { + "$ref": "#/components/schemas/Create or update Network" + }, + { + "properties": { + "cellularBackupEnabled": { + "description": "Whether this network is allowed to use cellular data when WAN connection(s) are down.", + "type": "boolean" + }, + "internetAccessEnabled": { + "description": "Whether the internet access is allowed for the device on this network.", + "type": "boolean" + }, + "ipv4Configuration": { + "$ref": "#/components/schemas/Gateway Managed IPv4 Configuration", + "description": "Details about IPv4 configuration for this Network." + }, + "ipv6Configuration": { + "$ref": "#/components/schemas/Network IPv6 Configuration", + "description": "Details about IPv6 configuration for this Network. If this field is omitted or null then IPv6 is not configured on this Network." + }, + "isolationEnabled": { + "description": "Whether this network is isolated from all other networks.", + "type": "boolean" + }, + "mdnsForwardingEnabled": { + "description": "Whether this network should participate in mDNS traffic forwarding. If null, the default from the site mDNS setting is used.", + "type": "boolean" + }, + "zoneId": { + "description": "Firewall zone ID associated with this Network.", + "format": "uuid", + "type": "string" + } + }, + "type": "object" + } + ], + "required": [ + "cellularBackupEnabled", + "enabled", + "internetAccessEnabled", + "ipv4Configuration", + "isolationEnabled", + "name", + "vlanId" + ] + }, + "IntegrationIotOptimizedWifiBroadcastCreateUpdateDto": { + "allOf": [ + { + "$ref": "#/components/schemas/Wifi broadcast create or update" + } + ], + "required": [ + "channel2gLockedTo6", + "clientIsolationEnabled", + "dtimPeriod2gLockedTo3", + "enabled", + "hideName", + "multicastToUnicastConversionEnabled", + "name", + "securityConfiguration", + "uapsdEnabled" + ] + }, + "IntegrationIotOptimizedWifiBroadcastDetailDto": { + "allOf": [ + { + "$ref": "#/components/schemas/Wifi broadcast details" + } + ], + "required": [ + "channel2gLockedTo6", + "clientIsolationEnabled", + "dtimPeriod2gLockedTo3", + "enabled", + "hideName", + "id", + "metadata", + "multicastToUnicastConversionEnabled", + "name", + "securityConfiguration", + "uapsdEnabled" + ] + }, + "IntegrationIotOptimizedWifiBroadcastOverviewDto": { + "allOf": [ + { + "$ref": "#/components/schemas/Wifi broadcast overview" + } + ], + "required": [ + "enabled", + "id", + "metadata", + "name", + "securityConfiguration" + ] + }, + "IntegrationIpAclRuleCreateUpdateDto": { + "allOf": [ + { + "$ref": "#/components/schemas/ACL rule update" + }, + { + "properties": { + "destinationFilter": { + "$ref": "#/components/schemas/IP ACL rule endpoint", + "description": "Traffic destination filter" + }, + "protocolFilter": { + "description": "Protocols this ACL rule will be applied to. When null, the rule will be applied to all protocols.", + "items": { + "enum": [ + "TCP", + "UDP" + ], + "type": "string" + }, + "maxItems": 2147483647, + "minItems": 1, + "type": "array", + "uniqueItems": true + }, + "sourceFilter": { + "$ref": "#/components/schemas/IP ACL rule endpoint", + "description": "Traffic source filter" + } + }, + "type": "object" + } + ], + "required": [ + "action", + "enabled", + "name" + ] + }, + "IntegrationIpAclRuleDto": { + "allOf": [ + { + "$ref": "#/components/schemas/ACL rule" + }, + { + "properties": { + "destinationFilter": { + "$ref": "#/components/schemas/IP ACL rule endpoint", + "description": "Traffic destination filter" + }, + "protocolFilter": { + "description": "Protocols this ACL rule will be applied to. When null, the rule will be applied to all protocols.", + "items": { + "enum": [ + "TCP", + "UDP" + ], + "type": "string" + }, + "maxItems": 2147483647, + "minItems": 1, + "type": "array", + "uniqueItems": true + }, + "sourceFilter": { + "$ref": "#/components/schemas/IP ACL rule endpoint", + "description": "Traffic source filter" + } + }, + "type": "object" + }, + { + "$ref": "#/components/schemas/ACL ruleObject" + } + ], + "required": [ + "action", + "enabled", + "id", + "index", + "metadata", + "name" + ] + }, + "IntegrationIpAclRuleNetworkEndpointFilterDto": { + "allOf": [ + { + "$ref": "#/components/schemas/IP ACL rule endpoint" + }, + { + "properties": { + "networkIds": { + "description": "Network IDs", + "items": { + "format": "uuid", + "type": "string" + }, + "minItems": 1, + "type": "array", + "uniqueItems": true + }, + "portFilter": { + "description": "Ports this ACL rule will be applied to. If null, the rule will be applied to all ports.", + "items": { + "format": "int32", + "maximum": 65535, + "minimum": 1, + "type": "integer" + }, + "maxItems": 2147483647, + "maximum": 65535, + "minItems": 1, + "minimum": 1, + "type": "array", + "uniqueItems": true + } + }, + "type": "object" + } + ], + "required": [ + "networkIds" + ] + }, + "IntegrationIpAclRulePortEndpointFilterDto": { + "allOf": [ + { + "$ref": "#/components/schemas/IP ACL rule endpoint" + }, + { + "properties": { + "portFilter": { + "description": "Ports this ACL rule will be applied to.", + "items": { + "format": "int32", + "maximum": 65535, + "minimum": 1, + "type": "integer" + }, + "maximum": 65535, + "minItems": 1, + "minimum": 1, + "type": "array", + "uniqueItems": true + } + }, + "type": "object" + } + ], + "required": [ + "portFilter" + ] + }, + "IntegrationIpAclRuleSubnetEndpointFilterDto": { + "allOf": [ + { + "$ref": "#/components/schemas/IP ACL rule endpoint" + }, + { + "properties": { + "ipAddressesOrSubnets": { + "description": "IP addresses or subnets", + "items": { + "minLength": 1, + "type": "string" + }, + "minItems": 1, + "type": "array" + }, + "portFilter": { + "description": "Ports this ACL rule will be applied to. If null, all the rule will be applied to all ports.", + "items": { + "format": "int32", + "maximum": 65535, + "minimum": 1, + "type": "integer" + }, + "maxItems": 2147483647, + "maximum": 65535, + "minItems": 1, + "minimum": 1, + "type": "array", + "uniqueItems": true + } + }, + "type": "object" + } + ], + "required": [ + "ipAddressesOrSubnets" + ] + }, + "IntegrationIpV4TrafficMatchingListCreateUpdateDto": { + "allOf": [ + { + "$ref": "#/components/schemas/Create or update traffic matching list" + }, + { + "properties": { + "items": { + "items": { + "$ref": "#/components/schemas/IPv4 matching" + }, + "minItems": 1, + "type": "array" + } + }, + "type": "object" + } + ], + "required": [ + "items", + "name" + ] + }, + "IntegrationIpV4TrafficMatchingListDto": { + "allOf": [ + { + "$ref": "#/components/schemas/Traffic matching list" + }, + { + "properties": { + "items": { + "items": { + "$ref": "#/components/schemas/IPv4 matching" + }, + "minItems": 1, + "type": "array" + } + }, + "type": "object" + } + ], + "required": [ + "id", + "items", + "name" + ] + }, + "IntegrationIpV6TrafficMatchingListCreateUpdateDto": { + "allOf": [ + { + "$ref": "#/components/schemas/Create or update traffic matching list" + }, + { + "properties": { + "items": { + "items": { + "$ref": "#/components/schemas/IPv6 matching" + }, + "minItems": 1, + "type": "array" + } + }, + "type": "object" + } + ], + "required": [ + "items", + "name" + ] + }, + "IntegrationIpV6TrafficMatchingListDto": { + "allOf": [ + { + "$ref": "#/components/schemas/Traffic matching list" + }, + { + "properties": { + "items": { + "items": { + "$ref": "#/components/schemas/IPv6 matching" + }, + "minItems": 1, + "type": "array" + } + }, + "type": "object" + } + ], + "required": [ + "id", + "items", + "name" + ] + }, + "IntegrationIpv6AddressSuffixRangeSelectorDto": { + "properties": { + "start": { + "description": "Start suffix of the DHCPv6 address pool.", + "type": "string" + }, + "stop": { + "description": "End suffix of the DHCPv6 address pool.", + "type": "string" + } + }, + "required": [ + "start", + "stop" + ], + "type": "object" + }, + "IntegrationL2tpServerOverviewDto": { + "allOf": [ + { + "$ref": "#/components/schemas/VPN server overview" + } + ], + "required": [ + "enabled", + "id", + "metadata", + "name" + ] + }, + "IntegrationLagMemberDto": { + "properties": { + "deviceId": { + "format": "uuid", + "type": "string" + }, + "portIdxs": { + "items": { + "format": "int32", + "type": "integer" + }, + "type": "array" + } + }, + "required": [ + "deviceId", + "portIdxs" + ], + "type": "object" + }, + "IntegrationLagPageDto": { + "properties": { + "count": { + "example": 10, + "format": "int32", + "type": "integer" + }, + "data": { + "items": { + "$ref": "#/components/schemas/LAG details" + }, + "type": "array" + }, + "limit": { + "example": 25, + "format": "int32", + "type": "integer" + }, + "offset": { + "example": 0, + "format": "int64", + "type": "integer" + }, + "totalCount": { + "example": 1000, + "format": "int64", + "type": "integer" + } + }, + "required": [ + "count", + "data", + "limit", + "offset", + "totalCount" + ], + "type": "object" + }, + "IntegrationLocalLagGlobalDto": { + "allOf": [ + { + "$ref": "#/components/schemas/LAG details" + } + ], + "required": [ + "id", + "members", + "metadata" + ] + }, + "IntegrationLocalLagLocalDto": { + "properties": { + "id": { + "format": "uuid", + "type": "string" + }, + "metadata": { + "$ref": "#/components/schemas/User defined entity metadata" + }, + "portIdxs": { + "items": { + "format": "int32", + "type": "integer" + }, + "minItems": 1, + "type": "array" + } + }, + "required": [ + "id", + "metadata", + "portIdxs" + ], + "type": "object" + }, + "IntegrationMacAclRuleCreateUpdateDto": { + "allOf": [ + { + "$ref": "#/components/schemas/ACL rule update" + }, + { + "properties": { + "destinationFilter": { + "$ref": "#/components/schemas/MAC ACL rule endpoint", + "description": "Traffic destination filter" + }, + "networkIdFilter": { + "description": "Network ID to which this ACL rule applies", + "format": "uuid", + "type": "string" + }, + "sourceFilter": { + "$ref": "#/components/schemas/MAC ACL rule endpoint", + "description": "Traffic source filter" + } + }, + "type": "object" + } + ], + "required": [ + "action", + "enabled", + "name", + "networkIdFilter" + ] + }, + "IntegrationMacAclRuleDto": { + "allOf": [ + { + "$ref": "#/components/schemas/ACL rule" + }, + { + "properties": { + "destinationFilter": { + "$ref": "#/components/schemas/MAC ACL rule endpoint", + "description": "Traffic destination filter" + }, + "networkIdFilter": { + "description": "Network ID to which this ACL rule applies", + "format": "uuid", + "type": "string" + }, + "sourceFilter": { + "$ref": "#/components/schemas/MAC ACL rule endpoint", + "description": "Traffic source filter" + } + }, + "type": "object" + }, + { + "$ref": "#/components/schemas/ACL ruleObject" + } + ], + "required": [ + "action", + "enabled", + "id", + "index", + "metadata", + "name", + "networkIdFilter" + ] + }, + "IntegrationMacAclRuleMacAddressEndpointFilterDto": { + "allOf": [ + { + "$ref": "#/components/schemas/MAC ACL rule endpoint" + }, + { + "properties": { + "macAddresses": { + "description": "Source/destination MAC addresses this ACL rule will apply to.", + "items": { + "type": "string" + }, + "minItems": 1, + "type": "array" + }, + "prefixLength": { + "description": "MAC address prefix length. When null, full MAC address(-es) will be used.", + "format": "int32", + "maximum": 48, + "minimum": 1, + "type": "integer" + } + }, + "type": "object" + } + ], + "required": [ + "macAddresses" + ] + }, + "IntegrationMcLagDomainDto": { + "properties": { + "id": { + "format": "uuid", + "type": "string" + }, + "lags": { + "items": { + "$ref": "#/components/schemas/IntegrationMcLagLocalDto" + }, + "type": "array" + }, + "metadata": { + "$ref": "#/components/schemas/User defined entity metadata" + }, + "name": { + "type": "string" + }, + "peers": { + "items": { + "$ref": "#/components/schemas/IntegrationMcLagPeerDto" + }, + "type": "array" + } + }, + "required": [ + "id", + "lags", + "metadata", + "name", + "peers" + ], + "type": "object" + }, + "IntegrationMcLagDomainDtoPageDto": { + "properties": { + "count": { + "example": 10, + "format": "int32", + "type": "integer" + }, + "data": { + "items": { + "$ref": "#/components/schemas/IntegrationMcLagDomainDto" + }, + "type": "array" + }, + "limit": { + "example": 25, + "format": "int32", + "type": "integer" + }, + "offset": { + "example": 0, + "format": "int64", + "type": "integer" + }, + "totalCount": { + "example": 1000, + "format": "int64", + "type": "integer" + } + }, + "required": [ + "count", + "data", + "limit", + "offset", + "totalCount" + ], + "type": "object" + }, + "IntegrationMcLagGlobalDto": { + "allOf": [ + { + "$ref": "#/components/schemas/LAG details" + }, + { + "properties": { + "mcLagDomainId": { + "format": "uuid", + "type": "string" + } + }, + "type": "object" + } + ], + "required": [ + "id", + "mcLagDomainId", + "members", + "metadata" + ] + }, + "IntegrationMcLagLocalDto": { + "properties": { + "id": { + "format": "uuid", + "type": "string" + }, + "members": { + "items": { + "$ref": "#/components/schemas/IntegrationLagMemberDto" + }, + "type": "array" + }, + "metadata": { + "$ref": "#/components/schemas/User defined entity metadata" + } + }, + "required": [ + "id", + "members", + "metadata" + ], + "type": "object" + }, + "IntegrationMcLagPeerDto": { + "properties": { + "deviceId": { + "format": "uuid", + "type": "string" + }, + "linkPortIdxs": { + "items": { + "format": "int32", + "type": "integer" + }, + "minItems": 1, + "type": "array" + }, + "role": { + "enum": [ + "TOP", + "BOTTOM" + ], + "type": "string" + } + }, + "required": [ + "deviceId", + "linkPortIdxs", + "role" + ], + "type": "object" + }, + "IntegrationOpenVpnServerOverviewDto": { + "allOf": [ + { + "$ref": "#/components/schemas/VPN server overview" + } + ], + "required": [ + "enabled", + "id", + "metadata", + "name" + ] + }, + "IntegrationPortTrafficMatchingListCreateUpdateDto": { + "allOf": [ + { + "$ref": "#/components/schemas/Create or update traffic matching list" + }, + { + "properties": { + "items": { + "items": { + "$ref": "#/components/schemas/Port matching" + }, + "minItems": 1, + "type": "array" + } + }, + "type": "object" + } + ], + "required": [ + "items", + "name" + ] + }, + "IntegrationPortTrafficMatchingListDto": { + "allOf": [ + { + "$ref": "#/components/schemas/Traffic matching list" + }, + { + "properties": { + "items": { + "items": { + "$ref": "#/components/schemas/Port matching" + }, + "minItems": 1, + "type": "array" + } + }, + "type": "object" + } + ], + "required": [ + "id", + "items", + "name" + ] + }, + "IntegrationPptpServerOverviewDto": { + "allOf": [ + { + "$ref": "#/components/schemas/VPN server overview" + } + ], + "required": [ + "enabled", + "id", + "metadata", + "name" + ] + }, + "IntegrationSiteToSiteIpsecTunnelOverviewDto": { + "allOf": [ + { + "$ref": "#/components/schemas/Site-to-site VPN tunnel overview" + } + ], + "required": [ + "id", + "metadata", + "name" + ] + }, + "IntegrationSiteToSiteOpenVpnTunnelOverviewDto": { + "allOf": [ + { + "$ref": "#/components/schemas/Site-to-site VPN tunnel overview" + } + ], + "required": [ + "id", + "metadata", + "name" + ] + }, + "IntegrationSiteToSiteVpnTunnelOverviewPageDto": { + "properties": { + "count": { + "example": 10, + "format": "int32", + "type": "integer" + }, + "data": { + "items": { + "$ref": "#/components/schemas/Site-to-site VPN tunnel overview" + }, + "type": "array" + }, + "limit": { + "example": 25, + "format": "int32", + "type": "integer" + }, + "offset": { + "example": 0, + "format": "int64", + "type": "integer" + }, + "totalCount": { + "example": 1000, + "format": "int64", + "type": "integer" + } + }, + "required": [ + "count", + "data", + "limit", + "offset", + "totalCount" + ], + "type": "object" + }, + "IntegrationSiteToSiteWireguardTunnelOverviewDto": { + "allOf": [ + { + "$ref": "#/components/schemas/Site-to-site VPN tunnel overview" + } + ], + "required": [ + "id", + "metadata", + "name" + ] + }, + "IntegrationStandardWifiBroadcastCreateUpdateDto": { + "allOf": [ + { + "$ref": "#/components/schemas/Wifi broadcast create or update" + }, + { + "properties": { + "advertiseDeviceName": { + "description": "Indicates whether the device name is advertised in beacon frames.", + "type": "boolean" + }, + "arpProxyEnabled": { + "type": "boolean" + }, + "bandSteeringEnabled": { + "type": "boolean" + }, + "broadcastingFrequenciesGHz": { + "example": [ + 2.4, + 5 + ], + "items": { + "enum": [ + 2.4, + 5, + 6 + ], + "type": "number" + }, + "maxItems": 2147483647, + "minItems": 1, + "type": "array", + "uniqueItems": true + }, + "bssTransitionEnabled": { + "type": "boolean" + }, + "dnsAssistanceConfiguration": { + "$ref": "#/components/schemas/DNS assistance configuration" + }, + "dtimPeriodByFrequencyGHzOverride": { + "$ref": "#/components/schemas/IntegrationWifiDtimPeriodConfigurationDto" + }, + "handoffSuggestionsConfiguration": { + "$ref": "#/components/schemas/IntegrationWifiHandoffSuggestionsConfigurationDto", + "description": "Suggests low-signal clients to roam to a better access point. If null, then it is disabled." + }, + "hotspotConfiguration": { + "$ref": "#/components/schemas/Wifi hotspot configuration" + }, + "mloEnabled": { + "type": "boolean" + } + }, + "type": "object" + } + ], + "required": [ + "advertiseDeviceName", + "arpProxyEnabled", + "broadcastingFrequenciesGHz", + "bssTransitionEnabled", + "channel2gLockedTo6", + "clientIsolationEnabled", + "dtimPeriod2gLockedTo3", + "enabled", + "hideName", + "multicastToUnicastConversionEnabled", + "name", + "securityConfiguration", + "uapsdEnabled" + ] + }, + "IntegrationStandardWifiBroadcastDetailDto": { + "allOf": [ + { + "$ref": "#/components/schemas/Wifi broadcast details" + }, + { + "properties": { + "advertiseDeviceName": { + "description": "Indicates whether the device name is advertised in beacon frames.", + "type": "boolean" + }, + "arpProxyEnabled": { + "type": "boolean" + }, + "bandSteeringEnabled": { + "type": "boolean" + }, + "broadcastingFrequenciesGHz": { + "example": [ + 2.4, + 5 + ], + "items": { + "enum": [ + 2.4, + 5, + 6 + ], + "type": "number" + }, + "maxItems": 2147483647, + "minItems": 1, + "type": "array", + "uniqueItems": true + }, + "bssTransitionEnabled": { + "type": "boolean" + }, + "dnsAssistanceConfiguration": { + "$ref": "#/components/schemas/DNS assistance configuration" + }, + "dtimPeriodByFrequencyGHzOverride": { + "$ref": "#/components/schemas/IntegrationWifiDtimPeriodConfigurationDto" + }, + "handoffSuggestionsConfiguration": { + "$ref": "#/components/schemas/IntegrationWifiHandoffSuggestionsConfigurationDto", + "description": "Suggests low-signal clients to roam to a better access point. If null, then it is disabled." + }, + "hotspotConfiguration": { + "$ref": "#/components/schemas/Wifi hotspot configuration" + }, + "mloEnabled": { + "type": "boolean" + } + }, + "type": "object" + } + ], + "required": [ + "advertiseDeviceName", + "arpProxyEnabled", + "broadcastingFrequenciesGHz", + "bssTransitionEnabled", + "channel2gLockedTo6", + "clientIsolationEnabled", + "dtimPeriod2gLockedTo3", + "enabled", + "hideName", + "id", + "metadata", + "multicastToUnicastConversionEnabled", + "name", + "securityConfiguration", + "uapsdEnabled" + ] + }, + "IntegrationStandardWifiBroadcastOverviewDto": { + "allOf": [ + { + "$ref": "#/components/schemas/Wifi broadcast overview" + }, + { + "properties": { + "broadcastingFrequenciesGHz": { + "items": { + "enum": [ + 2.4, + 5, + 6 + ], + "type": "number" + }, + "maxItems": 2147483647, + "minItems": 1, + "type": "array", + "uniqueItems": true + }, + "hotspotConfiguration": { + "$ref": "#/components/schemas/IntegrationWifiHotspotConfigurationOverviewDto" + } + }, + "type": "object" + } + ], + "required": [ + "broadcastingFrequenciesGHz", + "enabled", + "id", + "metadata", + "name", + "securityConfiguration" + ] + }, + "IntegrationSwitchManagedNetworkCreateUpdateDto": { + "allOf": [ + { + "$ref": "#/components/schemas/Create or update Network" + }, + { + "properties": { + "cellularBackupEnabled": { + "description": "Whether this network is allowed to use cellular data when WAN connection(s) are down.", + "type": "boolean" + }, + "deviceId": { + "description": "ID of the L3 switching capable device that manages this network.", + "format": "uuid", + "type": "string" + }, + "ipv4Configuration": { + "$ref": "#/components/schemas/Switch Managed IPv4 Configuration", + "description": "Details about IPv4 configuration for this Network." + }, + "isolationEnabled": { + "description": "Whether this network is isolated from all other networks.", + "type": "boolean" + } + }, + "type": "object" + } + ], + "required": [ + "cellularBackupEnabled", + "deviceId", + "enabled", + "ipv4Configuration", + "isolationEnabled", + "name", + "vlanId" + ] + }, + "IntegrationSwitchStackDto": { + "properties": { + "id": { + "format": "uuid", + "type": "string" + }, + "lags": { + "items": { + "$ref": "#/components/schemas/IntegrationSwitchStackLagLocalDto" + }, + "type": "array" + }, + "members": { + "items": { + "$ref": "#/components/schemas/IntegrationSwitchStackMemberDto" + }, + "minItems": 2, + "type": "array" + }, + "metadata": { + "$ref": "#/components/schemas/User defined entity metadata" + }, + "name": { + "type": "string" + } + }, + "required": [ + "id", + "lags", + "members", + "metadata", + "name" + ], + "type": "object" + }, + "IntegrationSwitchStackDtoPageDto": { + "properties": { + "count": { + "example": 10, + "format": "int32", + "type": "integer" + }, + "data": { + "items": { + "$ref": "#/components/schemas/IntegrationSwitchStackDto" + }, + "type": "array" + }, + "limit": { + "example": 25, + "format": "int32", + "type": "integer" + }, + "offset": { + "example": 0, + "format": "int64", + "type": "integer" + }, + "totalCount": { + "example": 1000, + "format": "int64", + "type": "integer" + } + }, + "required": [ + "count", + "data", + "limit", + "offset", + "totalCount" + ], + "type": "object" + }, + "IntegrationSwitchStackLagGlobalDto": { + "allOf": [ + { + "$ref": "#/components/schemas/LAG details" + }, + { + "properties": { + "switchStackId": { + "format": "uuid", + "type": "string" + } + }, + "type": "object" + } + ], + "required": [ + "id", + "members", + "metadata", + "switchStackId" + ] + }, + "IntegrationSwitchStackLagLocalDto": { + "properties": { + "id": { + "format": "uuid", + "type": "string" + }, + "members": { + "items": { + "$ref": "#/components/schemas/IntegrationLagMemberDto" + }, + "minItems": 1, + "type": "array" + }, + "metadata": { + "$ref": "#/components/schemas/User defined entity metadata" + } + }, + "required": [ + "id", + "members", + "metadata" + ], + "type": "object" + }, + "IntegrationSwitchStackMemberDto": { + "properties": { + "deviceId": { + "format": "uuid", + "type": "string" + } + }, + "required": [ + "deviceId" + ], + "type": "object" + }, + "IntegrationUidVpnServerOverviewDto": { + "allOf": [ + { + "$ref": "#/components/schemas/VPN server overview" + } + ], + "required": [ + "enabled", + "id", + "metadata", + "name" + ] + }, + "IntegrationUnmanagedNetworkCreateUpdateDto": { + "allOf": [ + { + "$ref": "#/components/schemas/Create or update Network" + } + ], + "required": [ + "enabled", + "name", + "vlanId" + ] + }, + "IntegrationVoucherCreationResultDto": { + "properties": { + "vouchers": { + "items": { + "$ref": "#/components/schemas/Hotspot voucher details" + }, + "type": "array" + } + }, + "type": "object" + }, + "IntegrationVpnServerOverviewPageDto": { + "properties": { + "count": { + "example": 10, + "format": "int32", + "type": "integer" + }, + "data": { + "items": { + "$ref": "#/components/schemas/VPN server overview" + }, + "type": "array" + }, + "limit": { + "example": 25, + "format": "int32", + "type": "integer" + }, + "offset": { + "example": 0, + "format": "int64", + "type": "integer" + }, + "totalCount": { + "example": 1000, + "format": "int64", + "type": "integer" + } + }, + "required": [ + "count", + "data", + "limit", + "offset", + "totalCount" + ], + "type": "object" + }, + "IntegrationWifiBasicDataRateConfigurationDto": { + "properties": { + "5": { + "enum": [ + "6000", + "9000", + "12000", + "24000" + ], + "example": 6000, + "format": "int32", + "type": "integer" + }, + "2.4": { + "enum": [ + "1000", + "2000", + "5500", + "6000", + "9000", + "11000", + "12000", + "24000" + ], + "example": 2000, + "format": "int32", + "type": "integer" + } + }, + "required": [ + "2.4", + "5" + ], + "type": "object" + }, + "IntegrationWifiBlackoutScheduleConfigurationPerAllDayDto": { + "allOf": [ + { + "$ref": "#/components/schemas/Blackout schedule configuration per day" + } + ], + "required": [ + "day" + ] + }, + "IntegrationWifiBlackoutScheduleConfigurationPerDayWithTimeRangeDto": { + "allOf": [ + { + "$ref": "#/components/schemas/Blackout schedule configuration per day" + }, + { + "properties": { + "timeRanges": { + "items": { + "$ref": "#/components/schemas/IntegrationWifiBlackoutScheduleConfigurationTimeRangeDto" + }, + "minItems": 1, + "type": "array" + } + }, + "type": "object" + } + ], + "required": [ + "day", + "timeRanges" + ] + }, + "IntegrationWifiBlackoutScheduleConfigurationTimeRangeDto": { + "properties": { + "endTime": { + "description": "End time in 24-hour format (HH:mm)", + "type": "string" + }, + "startTime": { + "description": "Start time in 24-hour format (HH:mm)", + "type": "string" + } + }, + "required": [ + "endTime", + "startTime" + ], + "type": "object" + }, + "IntegrationWifiBroadcastPageDto": { + "properties": { + "count": { + "example": 10, + "format": "int32", + "type": "integer" + }, + "data": { + "items": { + "$ref": "#/components/schemas/Wifi broadcast overview" + }, + "type": "array" + }, + "limit": { + "example": 25, + "format": "int32", + "type": "integer" + }, + "offset": { + "example": 0, + "format": "int64", + "type": "integer" + }, + "totalCount": { + "example": 1000, + "format": "int64", + "type": "integer" + } + }, + "required": [ + "count", + "data", + "limit", + "offset", + "totalCount" + ], + "type": "object" + }, + "IntegrationWifiCaptivePortalConfigurationDetailDto": { + "allOf": [ + { + "$ref": "#/components/schemas/Wifi hotspot configuration" + } + ] + }, + "IntegrationWifiClientFilteringPolicyDto": { + "properties": { + "action": { + "enum": [ + "ALLOW", + "BLOCK" + ], + "type": "string" + }, + "macAddressFilter": { + "items": { + "type": "string" + }, + "maxItems": 512, + "minItems": 0, + "type": "array", + "uniqueItems": true + } + }, + "required": [ + "action", + "macAddressFilter" + ], + "type": "object" + }, + "IntegrationWifiDerivedNasIdDto": { + "allOf": [ + { + "$ref": "#/components/schemas/Wifi Radius NAS ID configuration" + }, + { + "properties": { + "source": { + "enum": [ + "DEVICE_MAC_ADDRESS", + "DEVICE_NAME", + "SITE_NAME", + "BSSID" + ], + "type": "string" + } + }, + "type": "object" + } + ], + "required": [ + "source" + ] + }, + "IntegrationWifiDeviceTagsFilterDto": { + "allOf": [ + { + "$ref": "#/components/schemas/Broadcasting device filter" + }, + { + "properties": { + "deviceTagIds": { + "items": { + "format": "uuid", + "type": "string" + }, + "minItems": 1, + "type": "array", + "uniqueItems": true + } + }, + "type": "object" + } + ], + "required": [ + "deviceTagIds" + ] + }, + "IntegrationWifiDevicesFilterDto": { + "allOf": [ + { + "$ref": "#/components/schemas/Broadcasting device filter" + }, + { + "properties": { + "deviceIds": { + "description": "List of Access Point capable device IDs to which the WiFi broadcast applies.", + "items": { + "format": "uuid", + "type": "string" + }, + "minItems": 1, + "type": "array", + "uniqueItems": true + } + }, + "type": "object" + } + ], + "required": [ + "deviceIds" + ] + }, + "IntegrationWifiDnsAssistanceAutoConfigurationDto": { + "allOf": [ + { + "$ref": "#/components/schemas/DNS assistance configuration" + } + ] + }, + "IntegrationWifiDnsAssistanceManualConfigurationDto": { + "allOf": [ + { + "$ref": "#/components/schemas/DNS assistance configuration" + }, + { + "properties": { + "servers": { + "items": { + "description": "Failover DNS servers", + "type": "string" + }, + "maxItems": 2, + "minItems": 0, + "type": "array" + } + }, + "type": "object" + } + ], + "required": [ + "servers" + ] + }, + "IntegrationWifiDtimPeriodConfigurationDto": { + "properties": { + "5": { + "format": "int32", + "maximum": 255, + "minimum": 1, + "type": "integer" + }, + "6": { + "format": "int32", + "maximum": 255, + "minimum": 1, + "type": "integer" + }, + "2.4": { + "description": "DTIM period for 2.4GHz band must be 3 when dtimPeriod2gLockedTo3 is enabled.", + "format": "int32", + "maximum": 255, + "minimum": 1, + "type": "integer" + } + }, + "required": [ + "2.4", + "5", + "6" + ], + "type": "object" + }, + "IntegrationWifiEnterpriseRadiusConfigurationDto": { + "properties": { + "macAuthenticationConfiguration": { + "$ref": "#/components/schemas/IntegrationWifiRadiusMacAuthenticationConfigurationDto" + }, + "nasId": { + "$ref": "#/components/schemas/Wifi Radius NAS ID configuration" + }, + "profileId": { + "format": "uuid", + "type": "string" + } + }, + "required": [ + "nasId", + "profileId" + ], + "type": "object" + }, + "IntegrationWifiHandoffSuggestionsConfigurationDto": { + "properties": { + "band5GHzRssiThreshold": { + "description": "RSSI threshold (dBm) for the 5 GHz band. If null, then it is disabled.", + "format": "int32", + "maximum": -60, + "minimum": -80, + "type": "integer" + }, + "band6GHzRssiThreshold": { + "description": "RSSI threshold (dBm) for the 6 GHz band. If null, then it is disabled.", + "format": "int32", + "maximum": -70, + "minimum": -90, + "type": "integer" + } + }, + "type": "object" + }, + "IntegrationWifiHotspotConfigurationOverviewDto": { + "properties": { + "type": { + "enum": [ + "CAPTIVE_PORTAL", + "PASSPOINT" + ], + "type": "string" + } + }, + "required": [ + "type" + ], + "type": "object" + }, + "IntegrationWifiMdnsProxyAllowPolicyDto": { + "allOf": [ + { + "$ref": "#/components/schemas/mDNS proxy policy" + }, + { + "properties": { + "bridgingNetworkIds": { + "items": { + "format": "uuid", + "type": "string" + }, + "maxItems": 2147483647, + "minItems": 1, + "type": "array", + "uniqueItems": true + }, + "serviceFilter": { + "items": { + "$ref": "#/components/schemas/mDNS service" + }, + "maxItems": 2147483647, + "minItems": 1, + "type": "array" + } + }, + "type": "object" + } + ] + }, + "IntegrationWifiMdnsProxyAutoConfigurationDto": { + "allOf": [ + { + "$ref": "#/components/schemas/mDNS filtering configuration" + } + ] + }, + "IntegrationWifiMdnsProxyBlockPolicyDto": { + "allOf": [ + { + "$ref": "#/components/schemas/mDNS proxy policy" + } + ] + }, + "IntegrationWifiMdnsProxyCustomConfigurationDto": { + "allOf": [ + { + "$ref": "#/components/schemas/mDNS filtering configuration" + }, + { + "properties": { + "policies": { + "items": { + "$ref": "#/components/schemas/mDNS proxy policy" + }, + "minItems": 1, + "type": "array" + } + }, + "type": "object" + } + ], + "required": [ + "policies" + ] + }, + "IntegrationWifiMdnsProxyCustomServiceDto": { + "allOf": [ + { + "$ref": "#/components/schemas/mDNS service" + }, + { + "properties": { + "name": { + "minLength": 1, + "type": "string" + }, + "typeDomain": { + "minLength": 1, + "type": "string" + } + }, + "type": "object" + } + ], + "required": [ + "name", + "typeDomain" + ] + }, + "IntegrationWifiMdnsProxyPredefinedServiceDto": { + "allOf": [ + { + "$ref": "#/components/schemas/mDNS service" + }, + { + "properties": { + "name": { + "enum": [ + "AMAZON_DEVICES", + "ANDROID_TV_REMOTE", + "APPLE_AIR_DROP", + "APPLE_AIR_PLAY", + "APPLE_FILE_SHARING", + "APPLE_ICHAT", + "APPLE_ITUNES", + "AQARA", + "BOSE", + "DNS_SERVICE_DISCOVERY", + "FTP_SERVERS", + "GOOGLE_CHROMECAST", + "HOMEKIT", + "MATTER_NETWORK", + "PHILIPS_HUE", + "PRINTERS", + "ROKU", + "SCANNERS", + "SONOS", + "SPOTIFY_CONNECT", + "SSH_SERVERS", + "TIME_CAPSULE", + "WEB_SERVERS", + "WINDOWS_FILE_SHARING_SAMBA" + ], + "type": "string" + } + }, + "type": "object" + } + ], + "required": [ + "name" + ] + }, + "IntegrationWifiMulticastFilteringAllowPolicyDto": { + "allOf": [ + { + "$ref": "#/components/schemas/Multicast filtering policy" + }, + { + "properties": { + "sourceMacAddressFilter": { + "description": "List of multicast source MAC addresses allowed. Multicast traffic from gateways is always allowed.", + "items": { + "type": "string" + }, + "maxItems": 256, + "minItems": 0, + "type": "array", + "uniqueItems": true + } + }, + "type": "object" + } + ], + "required": [ + "sourceMacAddressFilter" + ] + }, + "IntegrationWifiMulticastFilteringBlockPolicyDto": { + "allOf": [ + { + "$ref": "#/components/schemas/Multicast filtering policy" + } + ] + }, + "IntegrationWifiNativeNetworkDto": { + "allOf": [ + { + "$ref": "#/components/schemas/Wifi network reference" + } + ] + }, + "IntegrationWifiNonEnterpriseRadiusConfigurationDto": { + "properties": { + "macAuthenticationConfiguration": { + "$ref": "#/components/schemas/IntegrationWifiRadiusMacAuthenticationConfigurationDto" + }, + "nasId": { + "$ref": "#/components/schemas/Wifi Radius NAS ID configuration" + }, + "profileId": { + "format": "uuid", + "type": "string" + } + }, + "required": [ + "macAuthenticationConfiguration", + "nasId", + "profileId" + ], + "type": "object" + }, + "IntegrationWifiOpenSecurityConfigurationDetailDto": { + "allOf": [ + { + "$ref": "#/components/schemas/Wifi security configuration detailObject" + }, + { + "properties": { + "encryption": { + "description": "Encryption mode for open security. If null, plain open with no encryption.", + "enum": [ + "ENHANCED_OPEN", + "ENHANCED_OPEN_WITH_TRANSITION" + ], + "type": "string" + }, + "radiusConfiguration": { + "$ref": "#/components/schemas/IntegrationWifiNonEnterpriseRadiusConfigurationDto" + } + }, + "type": "object" + } + ] + }, + "IntegrationWifiOpenSecurityConfigurationOverviewDto": { + "allOf": [ + { + "$ref": "#/components/schemas/Wifi security configuration overview" + } + ] + }, + "IntegrationWifiPasspointConfigurationDetailDto": { + "allOf": [ + { + "$ref": "#/components/schemas/Wifi hotspot configuration" + } + ] + }, + "IntegrationWifiPresharedKeyDto": { + "properties": { + "network": { + "$ref": "#/components/schemas/Wifi network reference" + }, + "passphrase": { + "type": "string" + } + }, + "required": [ + "network", + "passphrase" + ], + "type": "object" + }, + "IntegrationWifiRadiusMacAuthenticationConfigurationDto": { + "properties": { + "macAddressFormat": { + "enum": [ + "UPPERCASE_NOT_SEPARATED", + "UPPERCASE_DASH_SEPARATED", + "UPPERCASE_COLON_SEPARATED", + "LOWERCASE_NOT_SEPARATED", + "LOWERCASE_COLON_SEPARATED", + "LOWERCASE_DASH_SEPARATED" + ], + "type": "string" + } + }, + "required": [ + "macAddressFormat" + ], + "type": "object" + }, + "IntegrationWifiSaeConfigurationDto": { + "properties": { + "anticloggingThresholdSeconds": { + "format": "int32", + "maximum": 60, + "minimum": 1, + "type": "integer" + }, + "syncTimeSeconds": { + "format": "int32", + "maximum": 60, + "minimum": 1, + "type": "integer" + } + }, + "required": [ + "anticloggingThresholdSeconds", + "syncTimeSeconds" + ], + "type": "object" + }, + "IntegrationWifiSpecificNetworkDto": { + "allOf": [ + { + "$ref": "#/components/schemas/Wifi network reference" + }, + { + "properties": { + "networkId": { + "format": "uuid", + "type": "string" + } + }, + "type": "object" + } + ], + "required": [ + "networkId" + ] + }, + "IntegrationWifiUserDefinedNasIdDto": { + "allOf": [ + { + "$ref": "#/components/schemas/Wifi Radius NAS ID configuration" + }, + { + "properties": { + "value": { + "type": "string" + } + }, + "type": "object" + } + ], + "required": [ + "value" + ] + }, + "IntegrationWifiWpa2EnterpriseSecurityConfigurationDetailDto": { + "allOf": [ + { + "$ref": "#/components/schemas/Wifi security configuration detailObject" + }, + { + "properties": { + "coaEnabled": { + "description": "Indicates whether Change of Authorization (COA) is enabled", + "type": "boolean" + }, + "fastRoamingEnabled": { + "description": "Fast roaming enabled flag. This feature is not available for IoT configuration.", + "type": "boolean" + }, + "groupRekeyIntervalSeconds": { + "description": "Group rekey interval in seconds. Sets how often connected device groups are assigned a new key. If null, then it is disabled. This feature is not available for IoT configuration.", + "format": "int32", + "maximum": 86400, + "minimum": 1, + "type": "integer" + }, + "pmfMode": { + "description": "Protected Management Frames mode. If null, then it is disabled. This feature is not available for IoT configuration.", + "enum": [ + "REQUIRED", + "OPTIONAL" + ], + "type": "string" + }, + "radiusConfiguration": { + "$ref": "#/components/schemas/IntegrationWifiEnterpriseRadiusConfigurationDto" + } + }, + "type": "object" + } + ], + "required": [ + "coaEnabled", + "radiusConfiguration" + ] + }, + "IntegrationWifiWpa2EnterpriseSecurityConfigurationOverviewDto": { + "allOf": [ + { + "$ref": "#/components/schemas/Wifi security configuration overview" + } + ] + }, + "IntegrationWifiWpa2PersonalSecurityConfigurationDetailDto": { + "allOf": [ + { + "$ref": "#/components/schemas/Wifi security configuration detailObject" + }, + { + "properties": { + "fastRoamingEnabled": { + "description": "Fast roaming enabled flag. This feature is not available for IoT configuration.", + "type": "boolean" + }, + "groupRekeyIntervalSeconds": { + "description": "Group rekey interval in seconds. Sets how often connected device groups are assigned a new key. If null, then it is disabled. This feature is not available for IoT configuration.", + "format": "int32", + "maximum": 86400, + "minimum": 1, + "type": "integer" + }, + "passphrase": { + "maxLength": 63, + "minLength": 8, + "type": "string" + }, + "pmfMode": { + "description": "Protected Management Frames mode. If null, then it is disabled. This feature is not available for IoT configuration.", + "enum": [ + "REQUIRED", + "OPTIONAL" + ], + "type": "string" + }, + "presharedKeys": { + "items": { + "$ref": "#/components/schemas/IntegrationWifiPresharedKeyDto" + }, + "maxItems": 2147483647, + "minItems": 1, + "type": "array" + }, + "radiusConfiguration": { + "$ref": "#/components/schemas/IntegrationWifiNonEnterpriseRadiusConfigurationDto" + } + }, + "type": "object" + } + ] + }, + "IntegrationWifiWpa2PersonalSecurityConfigurationOverviewDto": { + "allOf": [ + { + "$ref": "#/components/schemas/Wifi security configuration overview" + }, + { + "properties": { + "presharedKeyNetworkIds": { + "items": { + "$ref": "#/components/schemas/Wifi network reference" + }, + "type": "array" + } + }, + "type": "object" + } + ] + }, + "IntegrationWifiWpa2Wpa3EnterpriseSecurityConfigurationDetailDto": { + "allOf": [ + { + "$ref": "#/components/schemas/Wifi security configuration detailObject" + }, + { + "properties": { + "coaEnabled": { + "description": "Indicates whether Change of Authorization (COA) is enabled", + "type": "boolean" + }, + "fastRoamingEnabled": { + "description": "Fast roaming enabled flag. This feature is not available for IoT configuration.", + "type": "boolean" + }, + "groupRekeyIntervalSeconds": { + "description": "Group rekey interval in seconds. Sets how often connected device groups are assigned a new key. If null, then it is disabled. This feature is not available for IoT configuration.", + "format": "int32", + "maximum": 86400, + "minimum": 1, + "type": "integer" + }, + "pmfMode": { + "description": "Protected Management Frames mode. If null, then it is disabled. This feature is not available for IoT configuration.", + "enum": [ + "REQUIRED", + "OPTIONAL" + ], + "type": "string" + }, + "radiusConfiguration": { + "$ref": "#/components/schemas/IntegrationWifiEnterpriseRadiusConfigurationDto" + }, + "wpa3FastRoamingEnabled": { + "description": "WPA3 fast roaming can be enabled only if the default fast roaming is enabled", + "type": "boolean" + } + }, + "type": "object" + } + ], + "required": [ + "coaEnabled", + "pmfMode", + "radiusConfiguration", + "wpa3FastRoamingEnabled" + ] + }, + "IntegrationWifiWpa2Wpa3EnterpriseSecurityConfigurationOverviewDto": { + "allOf": [ + { + "$ref": "#/components/schemas/Wifi security configuration overview" + } + ] + }, + "IntegrationWifiWpa2Wpa3PersonalSecurityConfigurationDetailDto": { + "allOf": [ + { + "$ref": "#/components/schemas/Wifi security configuration detailObject" + }, + { + "properties": { + "fastRoamingEnabled": { + "description": "Fast roaming enabled flag. This feature is not available for IoT configuration.", + "type": "boolean" + }, + "groupRekeyIntervalSeconds": { + "description": "Group rekey interval in seconds. Sets how often connected device groups are assigned a new key. If null, then it is disabled. This feature is not available for IoT configuration.", + "format": "int32", + "maximum": 86400, + "minimum": 1, + "type": "integer" + }, + "passphrase": { + "maxLength": 63, + "minLength": 8, + "type": "string" + }, + "pmfMode": { + "description": "Protected Management Frames mode. If null, then it is disabled. This feature is not available for IoT configuration.", + "enum": [ + "REQUIRED", + "OPTIONAL" + ], + "type": "string" + }, + "radiusConfiguration": { + "$ref": "#/components/schemas/IntegrationWifiNonEnterpriseRadiusConfigurationDto" + }, + "saeConfiguration": { + "$ref": "#/components/schemas/IntegrationWifiSaeConfigurationDto", + "description": "Configuration for SAE (Simultaneous Authentication of Equals)." + }, + "wpa3FastRoamingEnabled": { + "description": "WPA3 fast roaming can be enabled only if the default fast roaming is enabled", + "type": "boolean" + } + }, + "type": "object" + } + ], + "required": [ + "passphrase", + "pmfMode", + "saeConfiguration", + "wpa3FastRoamingEnabled" + ] + }, + "IntegrationWifiWpa2Wpa3PersonalSecurityConfigurationOverviewDto": { + "allOf": [ + { + "$ref": "#/components/schemas/Wifi security configuration overview" + } + ] + }, + "IntegrationWifiWpa3EnterpriseSecurityConfigurationDetailDto": { + "allOf": [ + { + "$ref": "#/components/schemas/Wifi security configuration detailObject" + }, + { + "properties": { + "coaEnabled": { + "description": "Indicates whether Change of Authorization (COA) is enabled", + "type": "boolean" + }, + "fastRoamingEnabled": { + "description": "Fast roaming enabled flag. This feature is not available for IoT configuration.", + "type": "boolean" + }, + "groupRekeyIntervalSeconds": { + "description": "Group rekey interval in seconds. Sets how often connected device groups are assigned a new key. If null, then it is disabled. This feature is not available for IoT configuration.", + "format": "int32", + "maximum": 86400, + "minimum": 1, + "type": "integer" + }, + "radiusConfiguration": { + "$ref": "#/components/schemas/IntegrationWifiEnterpriseRadiusConfigurationDto" + }, + "securityMode": { + "enum": [ + "DEFAULT", + "HIGH_SECURITY_192_BIT" + ], + "type": "string" + } + }, + "type": "object" + } + ], + "required": [ + "coaEnabled", + "radiusConfiguration", + "securityMode" + ] + }, + "IntegrationWifiWpa3EnterpriseSecurityConfigurationOverviewDto": { + "allOf": [ + { + "$ref": "#/components/schemas/Wifi security configuration overview" + } + ] + }, + "IntegrationWifiWpa3PersonalSecurityConfigurationDetailDto": { + "allOf": [ + { + "$ref": "#/components/schemas/Wifi security configuration detailObject" + }, + { + "properties": { + "fastRoamingEnabled": { + "description": "Fast roaming enabled flag. This feature is not available for IoT configuration.", + "type": "boolean" + }, + "groupRekeyIntervalSeconds": { + "description": "Group rekey interval in seconds. Sets how often connected device groups are assigned a new key. If null, then it is disabled. This feature is not available for IoT configuration.", + "format": "int32", + "maximum": 86400, + "minimum": 1, + "type": "integer" + }, + "passphrase": { + "maxLength": 63, + "minLength": 8, + "type": "string" + }, + "radiusConfiguration": { + "$ref": "#/components/schemas/IntegrationWifiNonEnterpriseRadiusConfigurationDto" + }, + "saeConfiguration": { + "$ref": "#/components/schemas/IntegrationWifiSaeConfigurationDto", + "description": "Configuration for SAE (Simultaneous Authentication of Equals)." + } + }, + "type": "object" + } + ], + "required": [ + "passphrase", + "saeConfiguration" + ] + }, + "IntegrationWifiWpa3PersonalSecurityConfigurationOverviewDto": { + "allOf": [ + { + "$ref": "#/components/schemas/Wifi security configuration overview" + } + ] + }, + "IntegrationWireguardServerOverviewDto": { + "allOf": [ + { + "$ref": "#/components/schemas/VPN server overview" + } + ], + "required": [ + "enabled", + "id", + "metadata", + "name" + ] + }, + "LAG details": { + "discriminator": { + "mapping": { + "LOCAL": "#/components/schemas/IntegrationLocalLagGlobalDto", + "MULTI_CHASSIS": "#/components/schemas/IntegrationMcLagGlobalDto", + "SWITCH_STACK": "#/components/schemas/IntegrationSwitchStackLagGlobalDto" + }, + "propertyName": "type" + }, + "properties": { + "id": { + "format": "uuid", + "type": "string" + }, + "members": { + "items": { + "$ref": "#/components/schemas/IntegrationLagMemberDto" + }, + "type": "array" + }, + "metadata": { + "$ref": "#/components/schemas/User defined entity metadata" + }, + "type": { + "type": "string" + } + }, + "required": [ + "id", + "members", + "metadata", + "type" + ], + "type": "object" + }, + "Latest statistics for a device": { + "properties": { + "cpuUtilizationPct": { + "format": "double", + "type": "number" + }, + "interfaces": { + "$ref": "#/components/schemas/Latest statistics for device interfaces" + }, + "lastHeartbeatAt": { + "format": "date-time", + "type": "string" + }, + "loadAverage15Min": { + "format": "double", + "type": "number" + }, + "loadAverage1Min": { + "format": "double", + "type": "number" + }, + "loadAverage5Min": { + "format": "double", + "type": "number" + }, + "memoryUtilizationPct": { + "format": "double", + "type": "number" + }, + "nextHeartbeatAt": { + "format": "date-time", + "type": "string" + }, + "uplink": { + "$ref": "#/components/schemas/Latest statistics for a device uplink interface" + }, + "uptimeSec": { + "format": "int64", + "type": "integer" + } + }, + "required": [ + "interfaces" + ], + "type": "object" + }, + "Latest statistics for a device uplink interface": { + "properties": { + "rxRateBps": { + "format": "int64", + "type": "integer" + }, + "txRateBps": { + "format": "int64", + "type": "integer" + } + }, + "type": "object" + }, + "Latest statistics for device interfaces": { + "properties": { + "radios": { + "items": { + "$ref": "#/components/schemas/Latest statistics for wireless radio" + }, + "type": "array" + } + }, + "type": "object" + }, + "Latest statistics for wireless radio": { + "properties": { + "frequencyGHz": { + "enum": [ + 2.4, + 5, + 6, + 60 + ], + "type": "number" + }, + "txRetriesPct": { + "format": "double", + "type": "number" + } + }, + "required": [ + "frequencyGHz" + ], + "type": "object" + }, + "Local client access details": { + "description": "Represents the type of network access and/or any applicable authorization status the client is using.\n\n- **Wired clients** may have direct access without additional authorization.\n- **Wireless clients** can be connected via a protected network or an open network\n that may require additional authorization (e.g., a guest portal).\n- **VPN clients** may have different authorization mechanisms.\n\nCurrently, the only two supported access types are `GUEST` (used for wired and wireless guest clients)\nand `DEFAULT` (a placeholder, which might be refined in the future releases, used for all other clients).\n\nFiltering is possible by `access.type`, for example `access.type.eq('GUEST')` to list guest clients.", + "discriminator": { + "mapping": { + "DEFAULT": "#/components/schemas/Default client access details", + "GUEST": "#/components/schemas/Guest access details" + }, + "propertyName": "type" + }, + "properties": { + "type": { + "type": "string" + } + }, + "required": [ + "type" + ] + }, + "Local client access overview": { + "description": "Represents the type of network access and/or any applicable authorization status the client is using.\n\n- **Wired clients** may have direct access without additional authorization.\n- **Wireless clients** can be connected via a protected network or an open network\n that may require additional authorization (e.g., a guest portal).\n- **VPN clients** may have different authorization mechanisms.\n\nCurrently, the only two supported access types are `GUEST` (used for wired and wireless guest clients)\nand `DEFAULT` (a placeholder, which might be refined in the future releases, used for all other clients).\n\nFiltering is possible by `access.type`, for example `access.type.eq('GUEST')` to list guest clients.", + "discriminator": { + "mapping": { + "DEFAULT": "#/components/schemas/Default client access overview", + "GUEST": "#/components/schemas/Guest access overview" + }, + "propertyName": "type" + }, + "properties": { + "type": { + "type": "string" + } + }, + "required": [ + "type" + ] + }, + "MAC ACL rule endpoint": { + "discriminator": { + "mapping": { + "MAC_ADDRESSES": "#/components/schemas/IntegrationMacAclRuleMacAddressEndpointFilterDto" + }, + "propertyName": "type" + }, + "properties": { + "type": { + "type": "string" + } + }, + "required": [ + "type" + ] + }, + "Multicast filtering policy": { + "discriminator": { + "mapping": { + "ALLOW": "#/components/schemas/IntegrationWifiMulticastFilteringAllowPolicyDto", + "BLOCK": "#/components/schemas/IntegrationWifiMulticastFilteringBlockPolicyDto" + }, + "propertyName": "action" + }, + "properties": { + "action": { + "type": "string" + } + }, + "required": [ + "action" + ] + }, + "NAT Outbound Auto Configuration": { + "allOf": [ + { + "$ref": "#/components/schemas/WAN NAT Outbound Configuration" + }, + { + "properties": { + "ipAddressSelectionMode": { + "description": "IP address selection mode which determines how the IP address will be selected from the group of IP addresses to translate the traffic on network using NAT.", + "enum": [ + "MAIN", + "ALL" + ], + "type": "string" + } + }, + "type": "object" + } + ], + "required": [ + "ipAddressSelectionMode", + "wanInterfaceId" + ] + }, + "NAT Outbound Static Configuration": { + "allOf": [ + { + "$ref": "#/components/schemas/WAN NAT Outbound Configuration" + }, + { + "properties": { + "ipAddressSelectors": { + "description": "List of IP addresses or address ranges which determines which IP addresses will be used to translate the traffic on network using NAT.", + "items": { + "$ref": "#/components/schemas/IP address selector" + }, + "minItems": 1, + "type": "array" + } + }, + "type": "object" + } + ], + "required": [ + "ipAddressSelectors", + "wanInterfaceId" + ] + }, + "Network DHCP Guarding": { + "description": "Details about DHCP Guarding settings for this Network.", + "properties": { + "trustedDhcpServerIpAddresses": { + "description": "List of trusted DHCP server IP addresses.", + "items": { + "type": "string" + }, + "minItems": 1, + "type": "array" + } + }, + "required": [ + "trustedDhcpServerIpAddresses" + ], + "type": "object" + }, + "Network IPv6 Configuration": { + "discriminator": { + "mapping": { + "PREFIX_DELEGATION": "#/components/schemas/Prefix delegation IPv6 Configuration", + "STATIC": "#/components/schemas/IPv6 Static Configuration" + }, + "propertyName": "interfaceType" + }, + "properties": { + "additionalHostIpSubnets": { + "description": "Additional host IP subnets assigned to this VLAN.", + "items": { + "type": "string" + }, + "maxItems": 4, + "minItems": 1, + "type": "array" + }, + "clientAddressAssignment": { + "$ref": "#/components/schemas/IPv6 Client Address Assignment", + "description": "Client Address Assignment" + }, + "dnsServerIpAddressesOverride": { + "description": "The IPv6 DNS server addresses assigned to this Network. If none are specified, they will be selected automatically.", + "items": { + "type": "string" + }, + "maxItems": 4, + "minItems": 1, + "type": "array" + }, + "interfaceType": { + "type": "string" + }, + "routerAdvertisement": { + "$ref": "#/components/schemas/Router advertisement Configuration", + "description": "Router advertisement. Without it, hosts will not autoconfigure addresses and will lack a default route even with DHCPv6." + } + }, + "required": [ + "clientAddressAssignment", + "interfaceType" + ], + "type": "object" + }, + "Network details": { + "discriminator": { + "mapping": { + "GATEWAY": "#/components/schemas/Gateway managed network details", + "SWITCH": "#/components/schemas/Switch managed network details", + "UNMANAGED": "#/components/schemas/Unmanaged network details" + }, + "propertyName": "management" + }, + "properties": { + "default": { + "type": "boolean" + }, + "dhcpGuarding": { + "$ref": "#/components/schemas/Network DHCP Guarding", + "description": "DHCP Guarding settings for this Network. If this field is omitted or null, the feature is disabled" + }, + "enabled": { + "type": "boolean" + }, + "id": { + "format": "uuid", + "type": "string" + }, + "management": { + "type": "string" + }, + "metadata": { + "$ref": "#/components/schemas/User or system defined or orchestrated entity metadata", + "description": "Orchestrated or System-defined configurable network support" + }, + "name": { + "example": "Default Network", + "minLength": 1, + "type": "string" + }, + "vlanId": { + "description": "VLAN ID. Must be 1 for the default network and >= 2 for additional networks.", + "format": "int32", + "maximum": 4009, + "minimum": 1, + "type": "integer" + } + }, + "required": [ + "default", + "enabled", + "id", + "management", + "metadata", + "name", + "vlanId" + ], + "type": "object" + }, + "Network overview": { + "discriminator": { + "mapping": { + "GATEWAY": "#/components/schemas/Gateway managed network overview", + "SWITCH": "#/components/schemas/Switch managed network overview", + "UNMANAGED": "#/components/schemas/Unmanaged network overview" + }, + "propertyName": "management" + }, + "properties": { + "default": { + "type": "boolean" + }, + "enabled": { + "type": "boolean" + }, + "id": { + "format": "uuid", + "type": "string" + }, + "management": { + "type": "string" + }, + "metadata": { + "$ref": "#/components/schemas/User or system defined or orchestrated entity metadata", + "description": "Orchestrated or System-defined configurable network support" + }, + "name": { + "example": "Default Network", + "type": "string" + }, + "vlanId": { + "description": "VLAN ID. Must be 1 for the default network and >= 2 for additional networks.", + "format": "int32", + "maximum": 4009, + "minimum": 1, + "type": "integer" + } + }, + "required": [ + "default", + "enabled", + "id", + "management", + "metadata", + "name", + "vlanId" + ], + "type": "object" + }, + "Network overview page": { + "properties": { + "count": { + "example": 10, + "format": "int32", + "type": "integer" + }, + "data": { + "items": { + "$ref": "#/components/schemas/Network overview" + }, + "type": "array" + }, + "limit": { + "example": 25, + "format": "int32", + "type": "integer" + }, + "offset": { + "example": 0, + "format": "int64", + "type": "integer" + }, + "totalCount": { + "example": 1000, + "format": "int64", + "type": "integer" + } + }, + "required": [ + "count", + "data", + "limit", + "offset", + "totalCount" + ], + "type": "object" + }, + "Network reference detail": { + "properties": { + "referenceId": { + "format": "uuid", + "type": "string" + } + }, + "required": [ + "referenceId" + ], + "type": "object" + }, + "Network reference resource": { + "properties": { + "referenceCount": { + "description": "Number of references of this type", + "format": "int32", + "minimum": 1, + "type": "integer" + }, + "references": { + "description": "List of references, present only if resourceType has API model defined", + "items": { + "$ref": "#/components/schemas/Network reference detail" + }, + "type": "array" + }, + "resourceType": { + "enum": [ + "CLIENT", + "DEVICE", + "STATIC_ROUTE", + "OSPF_ROUTE", + "NEXT_AI", + "WIFI", + "NAT_RULE", + "SD_WAN" + ], + "type": "string" + } + }, + "required": [ + "referenceCount", + "resourceType" + ], + "type": "object" + }, + "Network references": { + "properties": { + "referenceResources": { + "description": "List of network reference resources", + "items": { + "$ref": "#/components/schemas/Network reference resource" + }, + "type": "array" + } + }, + "required": [ + "referenceResources" + ], + "type": "object" + }, + "NotFilterExpression": { + "allOf": [ + { + "$ref": "#/components/schemas/FilterExpression" + }, + { + "properties": { + "expression": {} + }, + "type": "object" + } + ] + }, + "Number port matching": { + "allOf": [ + { + "$ref": "#/components/schemas/Port matching" + }, + { + "properties": { + "value": { + "description": "Port number", + "example": "80|443|8080", + "format": "int32", + "maximum": 65535, + "minimum": 1, + "type": "integer" + } + }, + "type": "object" + } + ], + "required": [ + "value" + ] + }, + "Number range port matching": { + "allOf": [ + { + "$ref": "#/components/schemas/Port matching" + }, + { + "properties": { + "start": { + "description": "Start port number", + "example": "80|443|8080", + "format": "int32", + "maximum": 65535, + "minimum": 1, + "type": "integer" + }, + "stop": { + "description": "Stop port number", + "example": "80|443|8080", + "format": "int32", + "maximum": 65535, + "minimum": 1, + "type": "integer" + } + }, + "type": "object" + } + ], + "required": [ + "start", + "stop" + ] + }, + "Orchestrated entity metadata": { + "allOf": [ + { + "$ref": "#/components/schemas/Entity metadata" + } + ] + }, + "Ordered firewall policy IDs": { + "properties": { + "afterSystemDefined": { + "items": { + "format": "uuid", + "type": "string" + }, + "type": "array" + }, + "beforeSystemDefined": { + "items": { + "format": "uuid", + "type": "string" + }, + "type": "array" + } + }, + "required": [ + "afterSystemDefined", + "beforeSystemDefined" + ], + "type": "object" + }, + "PXE Configuration": { + "properties": { + "filename": { + "minLength": 1, + "type": "string" + }, + "serverIpAddress": { + "type": "string" + } + }, + "required": [ + "filename", + "serverIpAddress" + ], + "type": "object" + }, + "Patch firewall policy": { + "properties": { + "loggingEnabled": { + "type": "boolean" + } + }, + "type": "object" + }, + "Port PoE overview": { + "properties": { + "enabled": { + "description": "Whether the PoE feature is enabled on the port", + "type": "boolean" + }, + "standard": { + "enum": [ + "802.3af", + "802.3at", + "802.3bt" + ], + "example": "802.3bt", + "type": "string" + }, + "state": { + "description": "Whether the port currently supplies power to the (connected) device.", + "enum": [ + "UP", + "DOWN", + "LIMITED", + "UNKNOWN" + ], + "type": "string" + }, + "type": { + "enum": [ + "1", + "2", + "3", + "4" + ], + "example": 3, + "format": "int32", + "type": "integer" + } + }, + "required": [ + "enabled", + "standard", + "state", + "type" + ], + "type": "object" + }, + "Port PoE power-cycle request": { + "allOf": [ + { + "$ref": "#/components/schemas/Port action request" + } + ] + }, + "Port action request": { + "discriminator": { + "mapping": { + "POWER_CYCLE": "#/components/schemas/Port PoE power-cycle request" + }, + "propertyName": "action" + }, + "properties": { + "action": { + "type": "string" + } + }, + "required": [ + "action" + ] + }, + "Port matching": { + "discriminator": { + "mapping": { + "PORT_NUMBER": "#/components/schemas/Number port matching", + "PORT_NUMBER_RANGE": "#/components/schemas/Number range port matching" + }, + "propertyName": "type" + }, + "properties": { + "type": { + "type": "string" + } + }, + "required": [ + "type" + ] + }, + "Port overview": { + "properties": { + "connector": { + "enum": [ + "RJ45", + "SFP", + "SFPPLUS", + "SFP28", + "QSFP28" + ], + "type": "string" + }, + "idx": { + "example": 1, + "format": "int32", + "minimum": 1, + "type": "integer" + }, + "maxSpeedMbps": { + "example": 10000, + "format": "int32", + "type": "integer" + }, + "poe": { + "$ref": "#/components/schemas/Port PoE overview" + }, + "speedMbps": { + "example": 1000, + "format": "int32", + "type": "integer" + }, + "state": { + "enum": [ + "UP", + "DOWN", + "UNKNOWN" + ], + "type": "string" + } + }, + "required": [ + "connector", + "idx", + "maxSpeedMbps", + "state" + ], + "type": "object" + }, + "Prefix delegation IPv6 Configuration": { + "allOf": [ + { + "$ref": "#/components/schemas/Network IPv6 Configuration" + }, + { + "properties": { + "prefixDelegationWanInterfaceId": { + "description": "ID of the WAN interface from which the prefix is delegated.", + "format": "uuid", + "type": "string" + } + }, + "type": "object" + } + ], + "required": [ + "clientAddressAssignment", + "prefixDelegationWanInterfaceId" + ] + }, + "PropertyFilterExpression": { + "allOf": [ + { + "$ref": "#/components/schemas/FilterExpression" + }, + { + "properties": { + "arguments": { + "items": {}, + "type": "array" + }, + "entity": { + "$ref": "#/components/schemas/FilterableEntity" + }, + "function": { + "enum": [ + "IS_NULL", + "IS_NOT_NULL", + "EQ", + "NE", + "GT", + "GE", + "LT", + "LE", + "LIKE", + "IN", + "NOT_IN", + "IS_EMPTY", + "CONTAINS", + "CONTAINS_ANY", + "CONTAINS_ALL", + "CONTAINS_EXACTLY" + ], + "type": "string" + }, + "property": { + "$ref": "#/components/schemas/FilterableProperty" + } + }, + "type": "object" + } + ] + }, + "Radius Profile Overview": { + "properties": { + "id": { + "format": "uuid", + "type": "string" + }, + "metadata": { + "$ref": "#/components/schemas/User or system defined or derived entity metadata" + }, + "name": { + "minLength": 1, + "type": "string" + } + }, + "required": [ + "id", + "metadata", + "name" + ], + "type": "object" + }, + "Radius Profile Overview Page": { + "properties": { + "count": { + "example": 10, + "format": "int32", + "type": "integer" + }, + "data": { + "items": { + "$ref": "#/components/schemas/Radius Profile Overview" + }, + "type": "array" + }, + "limit": { + "example": 25, + "format": "int32", + "type": "integer" + }, + "offset": { + "example": 0, + "format": "int64", + "type": "integer" + }, + "totalCount": { + "example": 1000, + "format": "int64", + "type": "integer" + } + }, + "required": [ + "count", + "data", + "limit", + "offset", + "totalCount" + ], + "type": "object" + }, + "Router advertisement Configuration": { + "properties": { + "priority": { + "description": "Router advertisement priority.", + "enum": [ + "LOW", + "MEDIUM", + "HIGH" + ], + "type": "string" + } + }, + "required": [ + "priority" + ], + "type": "object" + }, + "ScalarType": { + "allOf": [ + { + "$ref": "#/components/schemas/FilterablePropertyType" + } + ] + }, + "SetType": { + "allOf": [ + { + "$ref": "#/components/schemas/FilterablePropertyType" + } + ] + }, + "Site overview": { + "properties": { + "id": { + "format": "uuid", + "type": "string" + }, + "internalReference": { + "description": "Internal unique name of the site used in older APIs", + "type": "string" + }, + "name": { + "type": "string" + } + }, + "required": [ + "id", + "internalReference", + "name" + ], + "type": "object" + }, + "Site overview page": { + "properties": { + "count": { + "example": 10, + "format": "int32", + "type": "integer" + }, + "data": { + "items": { + "$ref": "#/components/schemas/Site overview" + }, + "type": "array" + }, + "limit": { + "example": 25, + "format": "int32", + "type": "integer" + }, + "offset": { + "example": 0, + "format": "int64", + "type": "integer" + }, + "totalCount": { + "example": 1000, + "format": "int64", + "type": "integer" + } + }, + "required": [ + "count", + "data", + "limit", + "offset", + "totalCount" + ], + "type": "object" + }, + "Site-to-site VPN tunnel metadata": { + "discriminator": { + "mapping": { + "DERIVED": "#/components/schemas/IntegrationDerivedSiteToSiteTunnelMetadata", + "USER_DEFINED": "#/components/schemas/User defined entity metadata" + }, + "propertyName": "origin" + }, + "properties": { + "origin": { + "type": "string" + } + }, + "required": [ + "origin" + ] + }, + "Site-to-site VPN tunnel overview": { + "discriminator": { + "mapping": { + "IPSEC": "#/components/schemas/IntegrationSiteToSiteIpsecTunnelOverviewDto", + "OPENVPN": "#/components/schemas/IntegrationSiteToSiteOpenVpnTunnelOverviewDto", + "WIREGUARD": "#/components/schemas/IntegrationSiteToSiteWireguardTunnelOverviewDto" + }, + "propertyName": "type" + }, + "properties": { + "id": { + "format": "uuid", + "type": "string" + }, + "metadata": { + "$ref": "#/components/schemas/Site-to-site VPN tunnel metadata" + }, + "name": { + "type": "string" + }, + "type": { + "type": "string" + } + }, + "required": [ + "id", + "metadata", + "name", + "type" + ], + "type": "object" + }, + "StringType": { + "allOf": [ + { + "$ref": "#/components/schemas/ScalarType" + } + ] + }, + "Subnet IPv4 matching": { + "allOf": [ + { + "$ref": "#/components/schemas/IPv4 matching" + }, + { + "properties": { + "value": { + "description": "IPv4 subnet in CIDR notation", + "example": "192.168.1.0/24", + "type": "string" + } + }, + "type": "object" + } + ], + "required": [ + "value" + ] + }, + "Subnet IPv6 matching": { + "allOf": [ + { + "$ref": "#/components/schemas/IPv6 matching" + }, + { + "properties": { + "value": { + "description": "IPv6 subnet in CIDR notation", + "example": "2001:db8:1:0::/64", + "type": "string" + } + }, + "type": "object" + } + ], + "required": [ + "value" + ] + }, + "Switch Managed IPv4 Configuration": { + "properties": { + "additionalHostIpSubnets": { + "description": "Additional host IP subnets assigned to this VLAN.", + "items": { + "type": "string" + }, + "maxItems": 64, + "minItems": 1, + "type": "array" + }, + "autoScaleEnabled": { + "description": "Whether the Network can automatically scale its subnet size based on the number of active DHCP leases.", + "type": "boolean" + }, + "dhcpConfiguration": { + "$ref": "#/components/schemas/Switch Managed IPv4 DHCP Configuration", + "description": "IPv4 DHCP configuration for this network. If this field is omitted or null, DHCP is not working and hosts must get an address statically or from another server in this broadcast domain." + }, + "hostIpAddress": { + "type": "string" + }, + "prefixLength": { + "format": "int32", + "maximum": 30, + "minimum": 8, + "type": "integer" + } + }, + "required": [ + "autoScaleEnabled", + "hostIpAddress", + "prefixLength" + ], + "type": "object" + }, + "Switch Managed IPv4 DHCP Configuration": { + "discriminator": { + "mapping": { + "RELAY": "#/components/schemas/IPv4 DHCP Relay Configuration", + "SERVER": "#/components/schemas/IPv4 DHCP Server Configuration" + }, + "propertyName": "mode" + }, + "properties": { + "mode": { + "type": "string" + } + }, + "required": [ + "mode" + ] + }, + "Switch managed network details": { + "allOf": [ + { + "$ref": "#/components/schemas/Network details" + }, + { + "properties": { + "cellularBackupEnabled": { + "description": "Whether this network is allowed to use cellular data when WAN connection(s) are down.", + "type": "boolean" + }, + "deviceId": { + "description": "ID of the L3 switching capable device that manages this network.", + "format": "uuid", + "type": "string" + }, + "ipv4Configuration": { + "$ref": "#/components/schemas/Switch Managed IPv4 Configuration", + "description": "Details about IPv4 configuration for this Network." + }, + "isolationEnabled": { + "description": "Whether this network is isolated from all other networks.", + "type": "boolean" + } + }, + "type": "object" + } + ], + "required": [ + "cellularBackupEnabled", + "default", + "deviceId", + "enabled", + "id", + "ipv4Configuration", + "isolationEnabled", + "metadata", + "name", + "vlanId" + ] + }, + "Switch managed network overview": { + "allOf": [ + { + "$ref": "#/components/schemas/Network overview" + }, + { + "properties": { + "deviceId": { + "description": "ID of the switch this Network is managed by.", + "example": "550e8400-e29b-41d4-a716-446655440000", + "format": "uuid", + "type": "string" + } + }, + "type": "object" + } + ], + "required": [ + "default", + "deviceId", + "enabled", + "id", + "metadata", + "name", + "vlanId" + ] + }, + "Switching feature overview": { + "properties": { + "lags": { + "items": { + "$ref": "#/components/schemas/IntegrationLocalLagLocalDto" + }, + "type": "array" + } + }, + "required": [ + "lags" + ], + "type": "object" + }, + "System defined entity metadata": { + "allOf": [ + { + "$ref": "#/components/schemas/Entity metadata" + } + ] + }, + "Teleport client (connection) details": { + "properties": { + "access": { + "$ref": "#/components/schemas/Teleport client access details" + }, + "connectedAt": { + "format": "date-time", + "type": "string" + }, + "id": { + "format": "uuid", + "type": "string" + }, + "ipAddress": { + "type": "string" + }, + "name": { + "type": "string" + } + }, + "required": [ + "access", + "id", + "name" + ], + "type": "object" + }, + "Teleport client (connection) overview": { + "allOf": [ + { + "$ref": "#/components/schemas/Client overview" + }, + { + "properties": { + "access": { + "$ref": "#/components/schemas/Teleport client access overview" + } + }, + "type": "object" + } + ], + "required": [ + "access", + "id", + "name" + ] + }, + "Teleport client access details": { + "description": "Represents the type of network access and/or any applicable authorization status the client is using.\n\n- **Wired clients** may have direct access without additional authorization.\n- **Wireless clients** can be connected via a protected network or an open network\n that may require additional authorization (e.g., a guest portal).\n- **VPN clients** may have different authorization mechanisms.\n\nCurrently, the only two supported access types are `GUEST` (used for wired and wireless guest clients)\nand `DEFAULT` (a placeholder, which might be refined in the future releases, used for all other clients).\n\nFiltering is possible by `access.type`, for example `access.type.eq('GUEST')` to list guest clients.", + "discriminator": { + "mapping": { + "DEFAULT": "#/components/schemas/Default client access details" + }, + "propertyName": "type" + }, + "properties": { + "type": { + "type": "string" + } + }, + "required": [ + "type" + ] + }, + "Teleport client access overview": { + "description": "Represents the type of network access and/or any applicable authorization status the client is using.\n\n- **Wired clients** may have direct access without additional authorization.\n- **Wireless clients** can be connected via a protected network or an open network\n that may require additional authorization (e.g., a guest portal).\n- **VPN clients** may have different authorization mechanisms.\n\nCurrently, the only two supported access types are `GUEST` (used for wired and wireless guest clients)\nand `DEFAULT` (a placeholder, which might be refined in the future releases, used for all other clients).\n\nFiltering is possible by `access.type`, for example `access.type.eq('GUEST')` to list guest clients.", + "discriminator": { + "mapping": { + "DEFAULT": "#/components/schemas/Default client access overview" + }, + "propertyName": "type" + }, + "properties": { + "type": { + "type": "string" + } + }, + "required": [ + "type" + ] + }, + "TimestampType": { + "allOf": [ + { + "$ref": "#/components/schemas/ScalarType" + } + ] + }, + "Traffic matching list": { + "discriminator": { + "mapping": { + "IPV4_ADDRESSES": "#/components/schemas/IntegrationIpV4TrafficMatchingListDto", + "IPV6_ADDRESSES": "#/components/schemas/IntegrationIpV6TrafficMatchingListDto", + "PORTS": "#/components/schemas/IntegrationPortTrafficMatchingListDto" + }, + "propertyName": "type" + }, + "properties": { + "id": { + "example": "ffcdb32c-6278-4364-8947-df4f77118df8", + "format": "uuid", + "type": "string" + }, + "name": { + "example": "Allowed port list|Protected IP list", + "minLength": 1, + "type": "string" + }, + "type": { + "type": "string" + } + }, + "required": [ + "id", + "name", + "type" + ], + "type": "object" + }, + "Traffic matching lists page": { + "properties": { + "count": { + "example": 10, + "format": "int32", + "type": "integer" + }, + "data": { + "items": { + "$ref": "#/components/schemas/Traffic matching list" + }, + "type": "array" + }, + "limit": { + "example": 25, + "format": "int32", + "type": "integer" + }, + "offset": { + "example": 0, + "format": "int64", + "type": "integer" + }, + "totalCount": { + "example": 1000, + "format": "int64", + "type": "integer" + } + }, + "required": [ + "count", + "data", + "limit", + "offset", + "totalCount" + ], + "type": "object" + }, + "UUIDType": { + "allOf": [ + { + "$ref": "#/components/schemas/ScalarType" + } + ] + }, + "Unmanaged network details": { + "allOf": [ + { + "$ref": "#/components/schemas/Network details" + } + ], + "required": [ + "default", + "enabled", + "id", + "metadata", + "name", + "vlanId" + ] + }, + "Unmanaged network overview": { + "allOf": [ + { + "$ref": "#/components/schemas/Network overview" + } + ], + "required": [ + "default", + "enabled", + "id", + "metadata", + "name", + "vlanId" + ] + }, + "User defined entity metadata": { + "allOf": [ + { + "$ref": "#/components/schemas/Entity metadata" + }, + { + "$ref": "#/components/schemas/User or system defined entity metadata" + }, + { + "$ref": "#/components/schemas/User defined or derived entity metadata" + }, + { + "$ref": "#/components/schemas/User or system defined or orchestrated entity metadata" + }, + { + "$ref": "#/components/schemas/User or orchestrated entity metadata" + }, + { + "$ref": "#/components/schemas/User or derived or orchestrated entity metadata" + }, + { + "$ref": "#/components/schemas/Site-to-site VPN tunnel metadata" + } + ] + }, + "User defined or derived entity metadata": { + "discriminator": { + "mapping": { + "DERIVED": "#/components/schemas/Derived entity metadata", + "USER_DEFINED": "#/components/schemas/User defined entity metadata" + }, + "propertyName": "origin" + }, + "properties": { + "origin": { + "type": "string" + } + }, + "required": [ + "origin" + ] + }, + "User or derived or orchestrated entity metadata": { + "discriminator": { + "mapping": { + "DERIVED": "#/components/schemas/Derived entity metadata", + "ORCHESTRATED": "#/components/schemas/Orchestrated entity metadata", + "USER_DEFINED": "#/components/schemas/User defined entity metadata" + }, + "propertyName": "origin" + }, + "properties": { + "origin": { + "type": "string" + } + }, + "required": [ + "origin" + ] + }, + "User or orchestrated entity metadata": { + "discriminator": { + "mapping": { + "ORCHESTRATED": "#/components/schemas/Orchestrated entity metadata", + "USER_DEFINED": "#/components/schemas/User defined entity metadata" + }, + "propertyName": "origin" + }, + "properties": { + "origin": { + "type": "string" + } + }, + "required": [ + "origin" + ] + }, + "User or system defined entity metadata": { + "discriminator": { + "mapping": { + "SYSTEM_DEFINED": "#/components/schemas/System defined entity metadata", + "USER_DEFINED": "#/components/schemas/User defined entity metadata" + }, + "propertyName": "origin" + }, + "properties": { + "origin": { + "type": "string" + } + }, + "required": [ + "origin" + ] + }, + "User or system defined or derived entity metadata": { + "discriminator": { + "mapping": { + "DERIVED": "#/components/schemas/Derived entity metadata", + "SYSTEM_DEFINED": "#/components/schemas/System defined entity metadata", + "USER_DEFINED": "#/components/schemas/User defined entity metadata" + }, + "propertyName": "origin" + }, + "properties": { + "origin": { + "type": "string" + } + }, + "required": [ + "origin" + ] + }, + "User or system defined or orchestrated entity metadata": { + "discriminator": { + "mapping": { + "ORCHESTRATED": "#/components/schemas/Orchestrated entity metadata", + "SYSTEM_DEFINED": "#/components/schemas/System defined entity metadata", + "USER_DEFINED": "#/components/schemas/User defined entity metadata" + }, + "propertyName": "origin" + }, + "properties": { + "origin": { + "type": "string" + } + }, + "required": [ + "origin" + ] + }, + "VPN client (connection) details": { + "allOf": [ + { + "$ref": "#/components/schemas/Client details" + }, + { + "properties": { + "access": { + "$ref": "#/components/schemas/VPN client access details" + } + }, + "type": "object" + } + ], + "required": [ + "access", + "id", + "name" + ] + }, + "VPN client (connection) overview": { + "allOf": [ + { + "$ref": "#/components/schemas/Client overview" + }, + { + "properties": { + "access": { + "$ref": "#/components/schemas/VPN client access overview" + } + }, + "type": "object" + } + ], + "required": [ + "access", + "id", + "name" + ] + }, + "VPN client access details": { + "description": "Represents the type of network access and/or any applicable authorization status the client is using.\n\n- **Wired clients** may have direct access without additional authorization.\n- **Wireless clients** can be connected via a protected network or an open network\n that may require additional authorization (e.g., a guest portal).\n- **VPN clients** may have different authorization mechanisms.\n\nCurrently, the only two supported access types are `GUEST` (used for wired and wireless guest clients)\nand `DEFAULT` (a placeholder, which might be refined in the future releases, used for all other clients).\n\nFiltering is possible by `access.type`, for example `access.type.eq('GUEST')` to list guest clients.", + "discriminator": { + "mapping": { + "DEFAULT": "#/components/schemas/Default client access details" + }, + "propertyName": "type" + }, + "properties": { + "type": { + "type": "string" + } + }, + "required": [ + "type" + ] + }, + "VPN client access overview": { + "description": "Represents the type of network access and/or any applicable authorization status the client is using.\n\n- **Wired clients** may have direct access without additional authorization.\n- **Wireless clients** can be connected via a protected network or an open network\n that may require additional authorization (e.g., a guest portal).\n- **VPN clients** may have different authorization mechanisms.\n\nCurrently, the only two supported access types are `GUEST` (used for wired and wireless guest clients)\nand `DEFAULT` (a placeholder, which might be refined in the future releases, used for all other clients).\n\nFiltering is possible by `access.type`, for example `access.type.eq('GUEST')` to list guest clients.", + "discriminator": { + "mapping": { + "DEFAULT": "#/components/schemas/Default client access overview" + }, + "propertyName": "type" + }, + "properties": { + "type": { + "type": "string" + } + }, + "required": [ + "type" + ] + }, + "VPN server overview": { + "discriminator": { + "mapping": { + "L2TP": "#/components/schemas/IntegrationL2tpServerOverviewDto", + "OPENVPN": "#/components/schemas/IntegrationOpenVpnServerOverviewDto", + "PPTP": "#/components/schemas/IntegrationPptpServerOverviewDto", + "UID": "#/components/schemas/IntegrationUidVpnServerOverviewDto", + "WIREGUARD": "#/components/schemas/IntegrationWireguardServerOverviewDto" + }, + "propertyName": "type" + }, + "properties": { + "enabled": { + "type": "boolean" + }, + "id": { + "format": "uuid", + "type": "string" + }, + "metadata": { + "$ref": "#/components/schemas/User defined or derived entity metadata" + }, + "name": { + "type": "string" + }, + "type": { + "type": "string" + } + }, + "required": [ + "enabled", + "id", + "metadata", + "name", + "type" + ], + "type": "object" + }, + "Voucher deletion results": { + "properties": { + "vouchersDeleted": { + "format": "int64", + "type": "integer" + } + }, + "type": "object" + }, + "WAN NAT Outbound Configuration": { + "discriminator": { + "mapping": { + "AUTO": "#/components/schemas/NAT Outbound Auto Configuration", + "STATIC": "#/components/schemas/NAT Outbound Static Configuration" + }, + "propertyName": "type" + }, + "properties": { + "type": { + "type": "string" + }, + "wanInterfaceId": { + "format": "uuid", + "type": "string" + } + }, + "required": [ + "type", + "wanInterfaceId" + ], + "type": "object" + }, + "WAN overview": { + "properties": { + "id": { + "format": "uuid", + "type": "string" + }, + "name": { + "example": "Internet 1", + "type": "string" + } + }, + "required": [ + "id", + "name" + ], + "type": "object" + }, + "WAN overview page": { + "properties": { + "count": { + "example": 10, + "format": "int32", + "type": "integer" + }, + "data": { + "items": { + "$ref": "#/components/schemas/WAN overview" + }, + "type": "array" + }, + "limit": { + "example": 25, + "format": "int32", + "type": "integer" + }, + "offset": { + "example": 0, + "format": "int64", + "type": "integer" + }, + "totalCount": { + "example": 1000, + "format": "int64", + "type": "integer" + } + }, + "required": [ + "count", + "data", + "limit", + "offset", + "totalCount" + ], + "type": "object" + }, + "Wifi Radius NAS ID configuration": { + "discriminator": { + "mapping": { + "DERIVED": "#/components/schemas/IntegrationWifiDerivedNasIdDto", + "USER_DEFINED": "#/components/schemas/IntegrationWifiUserDefinedNasIdDto" + }, + "propertyName": "type" + }, + "properties": { + "type": { + "type": "string" + } + }, + "required": [ + "type" + ] + }, + "Wifi broadcast create or update": { + "discriminator": { + "mapping": { + "IOT_OPTIMIZED": "#/components/schemas/IntegrationIotOptimizedWifiBroadcastCreateUpdateDto", + "STANDARD": "#/components/schemas/IntegrationStandardWifiBroadcastCreateUpdateDto" + }, + "propertyName": "type" + }, + "properties": { + "basicDataRateKbpsByFrequencyGHz": { + "$ref": "#/components/schemas/IntegrationWifiBasicDataRateConfigurationDto" + }, + "blackoutScheduleConfiguration": { + "$ref": "#/components/schemas/Integration blackout schedule configuration" + }, + "broadcastingDeviceFilter": { + "$ref": "#/components/schemas/Broadcasting device filter", + "description": "Defines the custom scope of devices that will broadcast this WiFi network. If null, the WiFi network will be broadcast by all Access Point capable devices." + }, + "channel2gLockedTo6": { + "default": false, + "description": "Locks 2.4GHz radio channel to 6 on all broadcasting devices", + "type": "boolean" + }, + "clientFilteringPolicy": { + "$ref": "#/components/schemas/IntegrationWifiClientFilteringPolicyDto", + "description": "Client connection filtering policy. Allow/restrict access to the WiFi network based on client device MAC addresses." + }, + "clientIsolationEnabled": { + "type": "boolean" + }, + "dtimPeriod2gLockedTo3": { + "default": false, + "description": "Locks DTIM period to 3 for 2.4GHz radio", + "type": "boolean" + }, + "enabled": { + "type": "boolean" + }, + "hideName": { + "type": "boolean" + }, + "mdnsProxyConfiguration": { + "$ref": "#/components/schemas/mDNS filtering configuration" + }, + "multicastFilteringPolicy": { + "$ref": "#/components/schemas/Multicast filtering policy" + }, + "multicastToUnicastConversionEnabled": { + "type": "boolean" + }, + "name": { + "type": "string" + }, + "network": { + "$ref": "#/components/schemas/Wifi network reference" + }, + "securityConfiguration": { + "$ref": "#/components/schemas/Wifi security configuration detailObject" + }, + "type": { + "type": "string" + }, + "uapsdEnabled": { + "description": "Indicates whether Unscheduled Automatic Power Save Delivery (U-APSD) is enabled", + "type": "boolean" + } + }, + "required": [ + "channel2gLockedTo6", + "clientIsolationEnabled", + "dtimPeriod2gLockedTo3", + "enabled", + "hideName", + "multicastToUnicastConversionEnabled", + "name", + "securityConfiguration", + "type", + "uapsdEnabled" + ], + "type": "object" + }, + "Wifi broadcast details": { + "discriminator": { + "mapping": { + "IOT_OPTIMIZED": "#/components/schemas/IntegrationIotOptimizedWifiBroadcastDetailDto", + "STANDARD": "#/components/schemas/IntegrationStandardWifiBroadcastDetailDto" + }, + "propertyName": "type" + }, + "properties": { + "basicDataRateKbpsByFrequencyGHz": { + "$ref": "#/components/schemas/IntegrationWifiBasicDataRateConfigurationDto" + }, + "blackoutScheduleConfiguration": { + "$ref": "#/components/schemas/Integration blackout schedule configuration" + }, + "broadcastingDeviceFilter": { + "$ref": "#/components/schemas/Broadcasting device filter", + "description": "Defines the custom scope of devices that will broadcast this WiFi network. If null, the WiFi network will be broadcast by all Access Point capable devices." + }, + "channel2gLockedTo6": { + "description": "Locks 2.4GHz radio channel to 6 on all broadcasting devices", + "type": "boolean" + }, + "clientFilteringPolicy": { + "$ref": "#/components/schemas/IntegrationWifiClientFilteringPolicyDto", + "description": "Client connection filtering policy. Allow/restrict access to the WiFi network based on client device MAC addresses." + }, + "clientIsolationEnabled": { + "type": "boolean" + }, + "dtimPeriod2gLockedTo3": { + "description": "Locks DTIM period to 3 for 2.4GHz radio", + "type": "boolean" + }, + "enabled": { + "type": "boolean" + }, + "hideName": { + "type": "boolean" + }, + "id": { + "format": "uuid", + "type": "string" + }, + "mdnsProxyConfiguration": { + "$ref": "#/components/schemas/mDNS filtering configuration" + }, + "metadata": { + "$ref": "#/components/schemas/User or derived or orchestrated entity metadata" + }, + "multicastFilteringPolicy": { + "$ref": "#/components/schemas/Multicast filtering policy" + }, + "multicastToUnicastConversionEnabled": { + "type": "boolean" + }, + "name": { + "type": "string" + }, + "network": { + "$ref": "#/components/schemas/Wifi network reference" + }, + "securityConfiguration": { + "$ref": "#/components/schemas/Wifi security configuration detailObject" + }, + "type": { + "type": "string" + }, + "uapsdEnabled": { + "description": "Indicates whether Unscheduled Automatic Power Save Delivery (U-APSD) is enabled", + "type": "boolean" + } + }, + "required": [ + "channel2gLockedTo6", + "clientIsolationEnabled", + "dtimPeriod2gLockedTo3", + "enabled", + "hideName", + "id", + "metadata", + "multicastToUnicastConversionEnabled", + "name", + "securityConfiguration", + "type", + "uapsdEnabled" + ], + "type": "object" + }, + "Wifi broadcast overview": { + "discriminator": { + "mapping": { + "IOT_OPTIMIZED": "#/components/schemas/IntegrationIotOptimizedWifiBroadcastOverviewDto", + "STANDARD": "#/components/schemas/IntegrationStandardWifiBroadcastOverviewDto" + }, + "propertyName": "type" + }, + "properties": { + "broadcastingDeviceFilter": { + "$ref": "#/components/schemas/Broadcasting device filter", + "description": "Defines the custom scope of devices that will broadcast this WiFi network. If null, the WiFi network will be broadcast by all Access Point capable devices." + }, + "enabled": { + "type": "boolean" + }, + "id": { + "format": "uuid", + "type": "string" + }, + "metadata": { + "$ref": "#/components/schemas/User or derived or orchestrated entity metadata" + }, + "name": { + "type": "string" + }, + "network": { + "$ref": "#/components/schemas/Wifi network reference" + }, + "securityConfiguration": { + "$ref": "#/components/schemas/Wifi security configuration overview" + }, + "type": { + "type": "string" + } + }, + "required": [ + "enabled", + "id", + "metadata", + "name", + "securityConfiguration", + "type" + ], + "type": "object" + }, + "Wifi hotspot configuration": { + "discriminator": { + "mapping": { + "CAPTIVE_PORTAL": "#/components/schemas/IntegrationWifiCaptivePortalConfigurationDetailDto", + "PASSPOINT": "#/components/schemas/IntegrationWifiPasspointConfigurationDetailDto" + }, + "propertyName": "type" + }, + "properties": { + "type": { + "type": "string" + } + }, + "required": [ + "type" + ] + }, + "Wifi network reference": { + "discriminator": { + "mapping": { + "NATIVE": "#/components/schemas/IntegrationWifiNativeNetworkDto", + "SPECIFIC": "#/components/schemas/IntegrationWifiSpecificNetworkDto" + }, + "propertyName": "type" + }, + "properties": { + "type": { + "type": "string" + } + }, + "required": [ + "type" + ] + }, + "Wifi security configuration detailObject": { + "discriminator": { + "mapping": { + "OPEN": "#/components/schemas/IntegrationWifiOpenSecurityConfigurationDetailDto", + "WPA2_ENTERPRISE": "#/components/schemas/IntegrationWifiWpa2EnterpriseSecurityConfigurationDetailDto", + "WPA2_PERSONAL": "#/components/schemas/IntegrationWifiWpa2PersonalSecurityConfigurationDetailDto", + "WPA2_WPA3_ENTERPRISE": "#/components/schemas/IntegrationWifiWpa2Wpa3EnterpriseSecurityConfigurationDetailDto", + "WPA2_WPA3_PERSONAL": "#/components/schemas/IntegrationWifiWpa2Wpa3PersonalSecurityConfigurationDetailDto", + "WPA3_ENTERPRISE": "#/components/schemas/IntegrationWifiWpa3EnterpriseSecurityConfigurationDetailDto", + "WPA3_PERSONAL": "#/components/schemas/IntegrationWifiWpa3PersonalSecurityConfigurationDetailDto" + }, + "propertyName": "type" + }, + "properties": { + "radiusConfiguration": {}, + "type": { + "type": "string" + } + }, + "required": [ + "type" + ], + "type": "object" + }, + "Wifi security configuration overview": { + "discriminator": { + "mapping": { + "OPEN": "#/components/schemas/IntegrationWifiOpenSecurityConfigurationOverviewDto", + "WPA2_ENTERPRISE": "#/components/schemas/IntegrationWifiWpa2EnterpriseSecurityConfigurationOverviewDto", + "WPA2_PERSONAL": "#/components/schemas/IntegrationWifiWpa2PersonalSecurityConfigurationOverviewDto", + "WPA2_WPA3_ENTERPRISE": "#/components/schemas/IntegrationWifiWpa2Wpa3EnterpriseSecurityConfigurationOverviewDto", + "WPA2_WPA3_PERSONAL": "#/components/schemas/IntegrationWifiWpa2Wpa3PersonalSecurityConfigurationOverviewDto", + "WPA3_ENTERPRISE": "#/components/schemas/IntegrationWifiWpa3EnterpriseSecurityConfigurationOverviewDto", + "WPA3_PERSONAL": "#/components/schemas/IntegrationWifiWpa3PersonalSecurityConfigurationOverviewDto" + }, + "propertyName": "type" + }, + "properties": { + "type": { + "type": "string" + } + }, + "required": [ + "type" + ] + }, + "Wired client details": { + "allOf": [ + { + "$ref": "#/components/schemas/Client details" + }, + { + "properties": { + "access": { + "$ref": "#/components/schemas/Local client access details" + }, + "macAddress": { + "type": "string" + }, + "uplinkDeviceId": { + "format": "uuid", + "type": "string" + } + }, + "type": "object" + } + ], + "required": [ + "access", + "id", + "macAddress", + "name", + "uplinkDeviceId" + ] + }, + "Wired client overview": { + "allOf": [ + { + "$ref": "#/components/schemas/Client overview" + }, + { + "properties": { + "access": { + "$ref": "#/components/schemas/Local client access overview" + }, + "macAddress": { + "type": "string" + }, + "uplinkDeviceId": { + "format": "uuid", + "type": "string" + } + }, + "type": "object" + } + ], + "required": [ + "access", + "id", + "macAddress", + "name", + "uplinkDeviceId" + ] + }, + "Wireless client details": { + "allOf": [ + { + "$ref": "#/components/schemas/Client details" + }, + { + "properties": { + "access": { + "$ref": "#/components/schemas/Local client access details" + }, + "macAddress": { + "type": "string" + }, + "uplinkDeviceId": { + "format": "uuid", + "type": "string" + } + }, + "type": "object" + } + ], + "required": [ + "access", + "id", + "macAddress", + "name", + "uplinkDeviceId" + ] + }, + "Wireless client overview": { + "allOf": [ + { + "$ref": "#/components/schemas/Client overview" + }, + { + "properties": { + "access": { + "$ref": "#/components/schemas/Local client access overview" + }, + "macAddress": { + "type": "string" + }, + "uplinkDeviceId": { + "format": "uuid", + "type": "string" + } + }, + "type": "object" + } + ], + "required": [ + "access", + "id", + "macAddress", + "name", + "uplinkDeviceId" + ] + }, + "Wireless radio overview": { + "properties": { + "channel": { + "example": 36, + "format": "int32", + "type": "integer" + }, + "channelWidthMHz": { + "example": 40, + "format": "int32", + "type": "integer" + }, + "frequencyGHz": { + "enum": [ + 2.4, + 5, + 6, + 60 + ], + "type": "number" + }, + "wlanStandard": { + "enum": [ + "802.11a", + "802.11b", + "802.11g", + "802.11n", + "802.11ac", + "802.11ax", + "802.11be" + ], + "type": "string" + } + }, + "required": [ + "channelWidthMHz", + "frequencyGHz", + "wlanStandard" + ], + "type": "object" + }, + "mDNS filtering configuration": { + "discriminator": { + "mapping": { + "AUTO": "#/components/schemas/IntegrationWifiMdnsProxyAutoConfigurationDto", + "CUSTOM": "#/components/schemas/IntegrationWifiMdnsProxyCustomConfigurationDto" + }, + "propertyName": "mode" + }, + "properties": { + "mode": { + "type": "string" + } + }, + "required": [ + "mode" + ] + }, + "mDNS proxy policy": { + "discriminator": { + "mapping": { + "ALLOW": "#/components/schemas/IntegrationWifiMdnsProxyAllowPolicyDto", + "BLOCK": "#/components/schemas/IntegrationWifiMdnsProxyBlockPolicyDto" + }, + "propertyName": "action" + }, + "properties": { + "action": { + "type": "string" + }, + "deviceFilter": { + "$ref": "#/components/schemas/Broadcasting device filter", + "description": "Defines the custom scope of devices that will filter Mdns. If null, the mDNS filtering will be added to all Access Point capable devices." + } + }, + "required": [ + "action" + ], + "type": "object" + }, + "mDNS service": { + "discriminator": { + "mapping": { + "CUSTOM": "#/components/schemas/IntegrationWifiMdnsProxyCustomServiceDto", + "PREDEFINED": "#/components/schemas/IntegrationWifiMdnsProxyPredefinedServiceDto" + }, + "propertyName": "type" + }, + "properties": { + "type": { + "type": "string" + } + }, + "required": [ + "type" + ] + } + } + }, + "info": { + "description": "", + "license": {}, + "title": "UniFi Network API", + "version": "10.4.57" + }, + "openapi": "3.1.0", + "paths": { + "/v1/countries": { + "get": { + "description": "Returns ISO-standard country codes and names,\nused for region-based configuration or regulatory compliance.\n\n
\nFilterable properties (click to expand)\n\n|Name|Type|Allowed functions|\n|-|-|-|\n|`code`|`STRING`|`eq` `ne` `in` `notIn`|\n|`name`|`STRING`|`eq` `ne` `in` `notIn` `like`|\n
", + "operationId": "getCountries", + "parameters": [ + { + "in": "query", + "name": "offset", + "required": false, + "schema": { + "default": 0, + "format": "int32", + "minimum": 0, + "type": "integer" + } + }, + { + "in": "query", + "name": "limit", + "required": false, + "schema": { + "default": 25, + "format": "int32", + "maximum": 200, + "minimum": 0, + "type": "integer" + } + }, + { + "in": "query", + "name": "filter", + "required": false, + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Country definition page" + } + } + }, + "description": "OK" + } + }, + "summary": "List Countries", + "tags": [ + "Supporting Resources" + ] + } + }, + "/v1/dpi/applications": { + "get": { + "description": "Lists DPI-recognized applications grouped under categories. Useful for firewall or traffic analytics integration.\n\n
\nFilterable properties (click to expand)\n\n|Name|Type|Allowed functions|\n|-|-|-|\n|`id`|`INTEGER`|`eq` `ne` `in` `notIn`|\n|`name`|`STRING`|`eq` `ne` `in` `notIn` `like`|\n
", + "operationId": "getDpiApplications", + "parameters": [ + { + "in": "query", + "name": "offset", + "required": false, + "schema": { + "default": 0, + "format": "int32", + "minimum": 0, + "type": "integer" + } + }, + { + "in": "query", + "name": "limit", + "required": false, + "schema": { + "default": 25, + "format": "int32", + "maximum": 200, + "minimum": 0, + "type": "integer" + } + }, + { + "in": "query", + "name": "filter", + "required": false, + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/DPI application page" + } + } + }, + "description": "OK" + } + }, + "summary": "List DPI Applications", + "tags": [ + "Supporting Resources" + ] + } + }, + "/v1/dpi/categories": { + "get": { + "description": "Returns predefined Deep Packet Inspection (DPI) application categories used for traffic identification and filtering.\n\n
\nFilterable properties (click to expand)\n\n|Name|Type|Allowed functions|\n|-|-|-|\n|`id`|`INTEGER`|`eq` `ne` `in` `notIn`|\n|`name`|`STRING`|`eq` `ne` `in` `notIn` `like`|\n
", + "operationId": "getDpiApplicationCategories", + "parameters": [ + { + "in": "query", + "name": "offset", + "required": false, + "schema": { + "default": 0, + "format": "int32", + "minimum": 0, + "type": "integer" + } + }, + { + "in": "query", + "name": "limit", + "required": false, + "schema": { + "default": 25, + "format": "int32", + "maximum": 200, + "minimum": 0, + "type": "integer" + } + }, + { + "in": "query", + "name": "filter", + "required": false, + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/DPI category page" + } + } + }, + "description": "OK" + } + }, + "summary": "List DPI Application Categories", + "tags": [ + "Supporting Resources" + ] + } + }, + "/v1/info": { + "get": { + "description": "Retrieve general information about the UniFi Network application.", + "operationId": "getInfo", + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Application info" + } + } + }, + "description": "OK" + } + }, + "summary": "Get Application Info", + "tags": [ + "Application Info" + ] + } + }, + "/v1/pending-devices": { + "get": { + "description": "Retrieve a paginated list of devices pending adoption, including basic device information.\n\n
\nFilterable properties (click to expand)\n\n|Name|Type|Allowed functions|\n|-|-|-|\n|`macAddress`|`STRING`|`eq` `ne` `in` `notIn`|\n|`ipAddress`|`STRING`|`eq` `ne` `in` `notIn`|\n|`model`|`STRING`|`eq` `ne` `in` `notIn`|\n|`state`|`STRING`|`eq` `ne` `in` `notIn`|\n|`supported`|`BOOLEAN`|`eq` `ne`|\n|`firmwareVersion`|`STRING`|`isNull` `isNotNull` `eq` `ne` `gt` `ge` `lt` `le` `like` `in` `notIn`|\n|`firmwareUpdatable`|`BOOLEAN`|`eq` `ne`|\n|`features`|`SET(STRING)`|`isEmpty` `contains` `containsAny` `containsAll` `containsExactly`|\n
", + "operationId": "getPendingDevicePage", + "parameters": [ + { + "in": "query", + "name": "offset", + "required": false, + "schema": { + "default": 0, + "format": "int32", + "minimum": 0, + "type": "integer" + } + }, + { + "in": "query", + "name": "limit", + "required": false, + "schema": { + "default": 25, + "format": "int32", + "maximum": 200, + "minimum": 0, + "type": "integer" + } + }, + { + "in": "query", + "name": "filter", + "required": false, + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Device pending adoption page" + } + } + }, + "description": "OK" + } + }, + "summary": "List Devices Pending Adoption", + "tags": [ + "UniFi Devices" + ] + } + }, + "/v1/sites": { + "get": { + "description": "Retrieve a paginated list of local sites managed by this Network application.\nSite ID is required for other UniFi Network API calls.\n\n
\nFilterable properties (click to expand)\n\n|Name|Type|Allowed functions|\n|-|-|-|\n|`id`|`UUID`|`eq` `ne` `in` `notIn`|\n|`internalReference`|`STRING`|`eq` `ne` `in` `notIn`|\n|`name`|`STRING`|`eq` `ne` `in` `notIn`|\n
", + "operationId": "getSiteOverviewPage", + "parameters": [ + { + "in": "query", + "name": "offset", + "required": false, + "schema": { + "default": 0, + "format": "int32", + "minimum": 0, + "type": "integer" + } + }, + { + "in": "query", + "name": "limit", + "required": false, + "schema": { + "default": 25, + "format": "int32", + "maximum": 200, + "minimum": 0, + "type": "integer" + } + }, + { + "in": "query", + "name": "filter", + "required": false, + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Site overview page" + } + } + }, + "description": "OK" + } + }, + "summary": "List Local Sites", + "tags": [ + "Sites" + ] + } + }, + "/v1/sites/{siteId}/acl-rules": { + "get": { + "description": "Retrieve a paginated list of all ACL rules on a site.\n\n
\nFilterable properties (click to expand)\n\n|Name|Type|Allowed functions|\n|-|-|-|\n|`type`|`STRING`|`eq` `ne` `in` `notIn`|\n|`id`|`UUID`|`eq` `ne` `in` `notIn`|\n|`enabled`|`BOOLEAN`|`eq` `ne`|\n|`name`|`STRING`|`eq` `ne` `in` `notIn` `like`|\n|`description`|`STRING`|`isNull` `isNotNull` `eq` `ne` `in` `notIn` `like`|\n|`action`|`STRING`|`eq` `ne` `in` `notIn`|\n|`index`|`INTEGER`|`eq` `ne` `gt` `ge` `lt` `le` `in` `notIn`|\n|`protocolFilter`|`SET(STRING)`|`isNull` `isNotNull` `contains` `containsAny` `containsAll` `containsExactly`|\n|`networkId`|`UUID`|`isNull` `isNotNull` `eq` `ne` `in` `notIn`|\n|`enforcingDeviceFilter.deviceIds`|`SET(UUID)`|`isNull` `isNotNull` `contains` `containsAny` `containsAll` `containsExactly`|\n|`metadata.origin`|`STRING`|`eq` `ne` `in` `notIn`|\n|`sourceFilter.type`|`STRING`|`isNull` `isNotNull` `eq` `ne` `in` `notIn`|\n|`sourceFilter.ipAddressesOrSubnets`|`SET(STRING)`|`contains` `containsAny` `containsAll` `containsExactly`|\n|`sourceFilter.portFilter`|`SET(INTEGER)`|`isNull` `isNotNull` `contains` `containsAny` `containsAll` `containsExactly`|\n|`sourceFilter.networkIds`|`SET(UUID)`|`contains` `containsAny` `containsAll` `containsExactly`|\n|`sourceFilter.macAddresses`|`SET(STRING)`|`contains` `containsAny` `containsAll` `containsExactly`|\n|`sourceFilter.prefixLength`|`INTEGER`|`isNull` `isNotNull` `eq` `ne` `gt` `ge` `lt` `le` `in` `notIn`|\n|`destinationFilter.type`|`STRING`|`isNull` `isNotNull` `eq` `ne` `in` `notIn`|\n|`destinationFilter.ipAddressesOrSubnets`|`SET(STRING)`|`contains` `containsAny` `containsAll` `containsExactly`|\n|`destinationFilter.portFilter`|`SET(INTEGER)`|`isNull` `isNotNull` `contains` `containsAny` `containsAll` `containsExactly`|\n|`destinationFilter.networkIds`|`SET(UUID)`|`contains` `containsAny` `containsAll` `containsExactly`|\n|`destinationFilter.macAddresses`|`SET(STRING)`|`contains` `containsAny` `containsAll` `containsExactly`|\n|`destinationFilter.prefixLength`|`INTEGER`|`isNull` `isNotNull` `eq` `ne` `gt` `ge` `lt` `le` `in` `notIn`|\n
", + "operationId": "getAclRulePage", + "parameters": [ + { + "in": "query", + "name": "offset", + "required": false, + "schema": { + "default": 0, + "format": "int32", + "minimum": 0, + "type": "integer" + } + }, + { + "in": "query", + "name": "limit", + "required": false, + "schema": { + "default": 25, + "format": "int32", + "maximum": 200, + "minimum": 0, + "type": "integer" + } + }, + { + "in": "query", + "name": "filter", + "required": false, + "schema": { + "type": "string" + } + }, + { + "in": "path", + "name": "siteId", + "required": true, + "schema": { + "format": "uuid", + "type": "string" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/IntegrationAclRulePageDto" + } + } + }, + "description": "OK" + } + }, + "summary": "List ACL Rules", + "tags": [ + "Access Control (ACL Rules)" + ] + }, + "post": { + "description": "Create a new user defined ACL rule on a site.", + "operationId": "createAclRule", + "parameters": [ + { + "in": "path", + "name": "siteId", + "required": true, + "schema": { + "format": "uuid", + "type": "string" + } + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ACL rule update" + } + } + }, + "required": true + }, + "responses": { + "201": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ACL rule" + } + } + }, + "description": "Created" + } + }, + "summary": "Create ACL Rule", + "tags": [ + "Access Control (ACL Rules)" + ] + } + }, + "/v1/sites/{siteId}/acl-rules/ordering": { + "get": { + "description": "Retrieve user-defined ACL rule ordering on a site.", + "operationId": "getAclRuleOrdering", + "parameters": [ + { + "in": "path", + "name": "siteId", + "required": true, + "schema": { + "format": "uuid", + "type": "string" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ACL rule ordering" + } + } + }, + "description": "OK" + } + }, + "summary": "Get User-Defined ACL Rule Ordering", + "tags": [ + "Access Control (ACL Rules)" + ] + }, + "put": { + "description": "Reorder user-defined ACL rules on a site.", + "operationId": "updateAclRuleOrdering", + "parameters": [ + { + "in": "path", + "name": "siteId", + "required": true, + "schema": { + "format": "uuid", + "type": "string" + } + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ACL rule ordering" + } + } + }, + "required": true + }, + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ACL rule ordering" + } + } + }, + "description": "OK" + } + }, + "summary": "Reorder User-Defined ACL Rules", + "tags": [ + "Access Control (ACL Rules)" + ] + } + }, + "/v1/sites/{siteId}/acl-rules/{aclRuleId}": { + "delete": { + "description": "Delete an existing user defined ACL rule on a site.", + "operationId": "deleteAclRule", + "parameters": [ + { + "in": "path", + "name": "aclRuleId", + "required": true, + "schema": { + "format": "uuid", + "type": "string" + } + }, + { + "in": "path", + "name": "siteId", + "required": true, + "schema": { + "format": "uuid", + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "OK" + } + }, + "summary": "Delete ACL Rule", + "tags": [ + "Access Control (ACL Rules)" + ] + }, + "get": { + "operationId": "getAclRule", + "parameters": [ + { + "in": "path", + "name": "aclRuleId", + "required": true, + "schema": { + "format": "uuid", + "type": "string" + } + }, + { + "in": "path", + "name": "siteId", + "required": true, + "schema": { + "format": "uuid", + "type": "string" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ACL rule" + } + } + }, + "description": "OK" + } + }, + "summary": "Get ACL Rule", + "tags": [ + "Access Control (ACL Rules)" + ] + }, + "put": { + "description": "Update an existing user defined ACL rule on a site.", + "operationId": "updateAclRule", + "parameters": [ + { + "in": "path", + "name": "aclRuleId", + "required": true, + "schema": { + "format": "uuid", + "type": "string" + } + }, + { + "in": "path", + "name": "siteId", + "required": true, + "schema": { + "format": "uuid", + "type": "string" + } + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ACL rule update" + } + } + }, + "required": true + }, + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ACL rule" + } + } + }, + "description": "OK" + } + }, + "summary": "Update ACL Rule", + "tags": [ + "Access Control (ACL Rules)" + ] + } + }, + "/v1/sites/{siteId}/clients": { + "get": { + "description": "Retrieve a paginated list of all connected clients on a site, including physical devices (computers, smartphones) and active VPN connections.\n\n
\nFilterable properties (click to expand)\n\n|Name|Type|Allowed functions|\n|-|-|-|\n|`id`|`UUID`|`eq` `ne` `in` `notIn`|\n|`type`|`STRING`|`eq` `ne` `in` `notIn`|\n|`macAddress`|`STRING`|`isNull` `isNotNull` `eq` `ne` `in` `notIn`|\n|`ipAddress`|`STRING`|`isNull` `isNotNull` `eq` `ne` `in` `notIn`|\n|`connectedAt`|`TIMESTAMP`|`isNull` `isNotNull` `eq` `ne` `gt` `ge` `lt` `le`|\n|`access.type`|`STRING`|`eq` `ne` `in` `notIn`|\n|`access.authorized`|`BOOLEAN`|`isNull` `isNotNull` `eq` `ne`|\n
", + "operationId": "getConnectedClientOverviewPage", + "parameters": [ + { + "in": "query", + "name": "offset", + "required": false, + "schema": { + "default": 0, + "format": "int32", + "minimum": 0, + "type": "integer" + } + }, + { + "in": "query", + "name": "limit", + "required": false, + "schema": { + "default": 25, + "format": "int32", + "maximum": 200, + "minimum": 0, + "type": "integer" + } + }, + { + "in": "query", + "name": "filter", + "required": false, + "schema": { + "type": "string" + } + }, + { + "in": "path", + "name": "siteId", + "required": true, + "schema": { + "format": "uuid", + "type": "string" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Client overview page" + } + } + }, + "description": "OK" + } + }, + "summary": "List Connected Clients", + "tags": [ + "Clients" + ] + } + }, + "/v1/sites/{siteId}/clients/{clientId}": { + "get": { + "description": "Retrieve detailed information about a specific connected client, including name, IP address, MAC address, connection type and access information.", + "operationId": "getConnectedClientDetails", + "parameters": [ + { + "in": "path", + "name": "clientId", + "required": true, + "schema": { + "format": "uuid", + "type": "string" + } + }, + { + "in": "path", + "name": "siteId", + "required": true, + "schema": { + "format": "uuid", + "type": "string" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Client details" + } + } + }, + "description": "OK" + } + }, + "summary": "Get Connected Client Details", + "tags": [ + "Clients" + ] + } + }, + "/v1/sites/{siteId}/clients/{clientId}/actions": { + "post": { + "description": "Perform an action on a specific connected client. The request body must include the action name and any applicable input arguments.", + "operationId": "executeConnectedClientAction", + "parameters": [ + { + "in": "path", + "name": "clientId", + "required": true, + "schema": { + "format": "uuid", + "type": "string" + } + }, + { + "in": "path", + "name": "siteId", + "required": true, + "schema": { + "format": "uuid", + "type": "string" + } + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Client action request" + } + } + }, + "required": true + }, + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Client action response" + } + } + }, + "description": "OK" + } + }, + "summary": "Execute Client Action", + "tags": [ + "Clients" + ] + } + }, + "/v1/sites/{siteId}/device-tags": { + "get": { + "description": "Returns all device tags defined within a site, which can be used for WiFi Broadcast assignments.\n\n
\nFilterable properties (click to expand)\n\n|Name|Type|Allowed functions|\n|-|-|-|\n|`id`|`UUID`|`eq` `ne` `in` `notIn`|\n|`name`|`STRING`|`eq` `ne` `in` `notIn` `like`|\n|`deviceIds`|`SET(UUID)`|`contains` `containsAny` `containsAll` `containsExactly`|\n
", + "operationId": "getDeviceTagPage", + "parameters": [ + { + "in": "query", + "name": "offset", + "required": false, + "schema": { + "default": 0, + "format": "int32", + "minimum": 0, + "type": "integer" + } + }, + { + "in": "query", + "name": "limit", + "required": false, + "schema": { + "default": 25, + "format": "int32", + "maximum": 200, + "minimum": 0, + "type": "integer" + } + }, + { + "in": "query", + "name": "filter", + "required": false, + "schema": { + "$ref": "#/components/schemas/FilterExpression" + } + }, + { + "in": "path", + "name": "siteId", + "required": true, + "schema": { + "format": "uuid", + "type": "string" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/IntegrationDeviceTagPageDto" + } + } + }, + "description": "OK" + } + }, + "summary": "List Device Tags", + "tags": [ + "Supporting Resources" + ] + } + }, + "/v1/sites/{siteId}/devices": { + "get": { + "description": "Retrieve a paginated list of all adopted devices on a site, including basic device information.\n\n
\nFilterable properties (click to expand)\n\n|Name|Type|Allowed functions|\n|-|-|-|\n|`id`|`UUID`|`eq` `ne` `in` `notIn`|\n|`macAddress`|`STRING`|`eq` `ne` `in` `notIn`|\n|`ipAddress`|`STRING`|`eq` `ne` `in` `notIn`|\n|`name`|`STRING`|`eq` `ne` `in` `notIn` `like`|\n|`model`|`STRING`|`eq` `ne` `in` `notIn`|\n|`state`|`STRING`|`eq` `ne` `in` `notIn`|\n|`supported`|`BOOLEAN`|`eq` `ne`|\n|`firmwareVersion`|`STRING`|`isNull` `isNotNull` `eq` `ne` `gt` `ge` `lt` `le` `like` `in` `notIn`|\n|`firmwareUpdatable`|`BOOLEAN`|`eq` `ne`|\n|`features`|`SET(STRING)`|`isEmpty` `contains` `containsAny` `containsAll` `containsExactly`|\n|`interfaces`|`SET(STRING)`|`isEmpty` `contains` `containsAny` `containsAll` `containsExactly`|\n
", + "operationId": "getAdoptedDeviceOverviewPage", + "parameters": [ + { + "in": "query", + "name": "offset", + "required": false, + "schema": { + "default": 0, + "format": "int32", + "minimum": 0, + "type": "integer" + } + }, + { + "in": "query", + "name": "limit", + "required": false, + "schema": { + "default": 25, + "format": "int32", + "maximum": 200, + "minimum": 0, + "type": "integer" + } + }, + { + "in": "query", + "name": "filter", + "required": false, + "schema": { + "type": "string" + } + }, + { + "in": "path", + "name": "siteId", + "required": true, + "schema": { + "format": "uuid", + "type": "string" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Adopted device overview page" + } + } + }, + "description": "OK" + } + }, + "summary": "List Adopted Devices", + "tags": [ + "UniFi Devices" + ] + }, + "post": { + "description": "Adopt a device to a site.", + "operationId": "adoptDevice", + "parameters": [ + { + "in": "path", + "name": "siteId", + "required": true, + "schema": { + "format": "uuid", + "type": "string" + } + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/IntegrationDeviceAdoptionRequestDto" + } + } + }, + "required": true + }, + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Adopted device details" + } + } + }, + "description": "OK" + } + }, + "summary": "Adopt Devices", + "tags": [ + "UniFi Devices" + ] + } + }, + "/v1/sites/{siteId}/devices/{deviceId}": { + "delete": { + "description": "Removes (unadopts) an adopted device from the site. If the device is online, it will be reset to factory defaults.", + "operationId": "removeDevice", + "parameters": [ + { + "in": "path", + "name": "siteId", + "required": true, + "schema": { + "format": "uuid", + "type": "string" + } + }, + { + "in": "path", + "name": "deviceId", + "required": true, + "schema": { + "format": "uuid", + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "OK" + } + }, + "summary": "Remove (Unadopt) Device", + "tags": [ + "UniFi Devices" + ] + }, + "get": { + "description": "Retrieve detailed information about a specific adopted device, including firmware versioning, uplink state, details about device features and interfaces (ports, radios) and other key attributes.", + "operationId": "getAdoptedDeviceDetails", + "parameters": [ + { + "in": "path", + "name": "siteId", + "required": true, + "schema": { + "format": "uuid", + "type": "string" + } + }, + { + "in": "path", + "name": "deviceId", + "required": true, + "schema": { + "format": "uuid", + "type": "string" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Adopted device details" + } + } + }, + "description": "OK" + } + }, + "summary": "Get Adopted Device Details", + "tags": [ + "UniFi Devices" + ] + } + }, + "/v1/sites/{siteId}/devices/{deviceId}/actions": { + "post": { + "description": "Perform an action on an specific adopted device. The request body must include the action name and any applicable input arguments.", + "operationId": "executeAdoptedDeviceAction", + "parameters": [ + { + "in": "path", + "name": "siteId", + "required": true, + "schema": { + "format": "uuid", + "type": "string" + } + }, + { + "in": "path", + "name": "deviceId", + "required": true, + "schema": { + "format": "uuid", + "type": "string" + } + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Device action request" + } + } + }, + "required": true + }, + "responses": { + "200": { + "description": "OK" + } + }, + "summary": "Execute Adopted Device Action", + "tags": [ + "UniFi Devices" + ] + } + }, + "/v1/sites/{siteId}/devices/{deviceId}/interfaces/ports/{portIdx}/actions": { + "post": { + "description": "Perform an action on a specific device port. The request body must include the action name and any applicable input arguments.", + "operationId": "executePortAction", + "parameters": [ + { + "in": "path", + "name": "portIdx", + "required": true, + "schema": { + "format": "int32", + "type": "integer" + } + }, + { + "in": "path", + "name": "siteId", + "required": true, + "schema": { + "format": "uuid", + "type": "string" + } + }, + { + "in": "path", + "name": "deviceId", + "required": true, + "schema": { + "format": "uuid", + "type": "string" + } + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Port action request" + } + } + }, + "required": true + }, + "responses": { + "200": { + "description": "OK" + } + }, + "summary": "Execute Port Action", + "tags": [ + "UniFi Devices" + ] + } + }, + "/v1/sites/{siteId}/devices/{deviceId}/statistics/latest": { + "get": { + "description": "Retrieve the latest real-time statistics of a specific adopted device, such as uptime, data transmission rates, CPU and memory utilization.", + "operationId": "getAdoptedDeviceLatestStatistics", + "parameters": [ + { + "in": "path", + "name": "siteId", + "required": true, + "schema": { + "format": "uuid", + "type": "string" + } + }, + { + "in": "path", + "name": "deviceId", + "required": true, + "schema": { + "format": "uuid", + "type": "string" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Latest statistics for a device" + } + } + }, + "description": "OK" + } + }, + "summary": "Get Latest Adopted Device Statistics", + "tags": [ + "UniFi Devices" + ] + } + }, + "/v1/sites/{siteId}/dns/policies": { + "get": { + "description": "Retrieve a paginated list of all DNS policies on a site.\n\n
\nFilterable properties (click to expand)\n\n|Name|Type|Allowed functions|\n|-|-|-|\n|`type`|`STRING`|`eq` `ne` `in` `notIn`|\n|`id`|`UUID`|`eq` `ne` `in` `notIn`|\n|`enabled`|`BOOLEAN`|`eq` `ne`|\n|`domain`|`STRING`|`eq` `ne` `in` `notIn` `like`|\n|`ipv4Address`|`STRING`|`eq` `ne` `in` `notIn` `like`|\n|`ipv6Address`|`STRING`|`eq` `ne` `in` `notIn` `like`|\n|`targetDomain`|`STRING`|`eq` `ne` `in` `notIn` `like`|\n|`mailServerDomain`|`STRING`|`eq` `ne` `in` `notIn` `like`|\n|`text`|`STRING`|`eq` `ne` `in` `notIn` `like`|\n|`serverDomain`|`STRING`|`eq` `ne` `in` `notIn` `like`|\n|`ipAddress`|`STRING`|`eq` `ne` `in` `notIn` `like`|\n|`ttlSeconds`|`INTEGER`|`eq` `ne` `gt` `ge` `lt` `le` `in` `notIn`|\n|`priority`|`INTEGER`|`eq` `ne` `gt` `ge` `lt` `le` `in` `notIn`|\n|`service`|`STRING`|`eq` `ne` `in` `notIn`|\n|`protocol`|`STRING`|`eq` `ne` `in` `notIn`|\n|`port`|`INTEGER`|`eq` `ne` `gt` `ge` `lt` `le` `in` `notIn`|\n|`weight`|`INTEGER`|`eq` `ne` `gt` `ge` `lt` `le` `in` `notIn`|\n
", + "operationId": "getDnsPolicyPage", + "parameters": [ + { + "in": "query", + "name": "offset", + "required": false, + "schema": { + "default": 0, + "format": "int32", + "minimum": 0, + "type": "integer" + } + }, + { + "in": "query", + "name": "limit", + "required": false, + "schema": { + "default": 25, + "format": "int32", + "maximum": 200, + "minimum": 0, + "type": "integer" + } + }, + { + "in": "query", + "name": "filter", + "required": false, + "schema": { + "type": "string" + } + }, + { + "in": "path", + "name": "siteId", + "required": true, + "schema": { + "format": "uuid", + "type": "string" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/IntegrationDnsPolicyPageDto" + } + } + }, + "description": "OK" + } + }, + "summary": "List DNS Policies", + "tags": [ + "DNS Policies" + ] + }, + "post": { + "description": "Create a new DNS policy on a site.", + "operationId": "createDnsPolicy", + "parameters": [ + { + "in": "path", + "name": "siteId", + "required": true, + "schema": { + "format": "uuid", + "type": "string" + } + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Create or update DNS policy" + } + } + }, + "required": true + }, + "responses": { + "201": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/DNS policy" + } + } + }, + "description": "Created" + } + }, + "summary": "Create DNS Policy", + "tags": [ + "DNS Policies" + ] + } + }, + "/v1/sites/{siteId}/dns/policies/{dnsPolicyId}": { + "delete": { + "description": "Delete an existing DNS policy on a site.", + "operationId": "deleteDnsPolicy", + "parameters": [ + { + "in": "path", + "name": "dnsPolicyId", + "required": true, + "schema": { + "format": "uuid", + "type": "string" + } + }, + { + "in": "path", + "name": "siteId", + "required": true, + "schema": { + "format": "uuid", + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "OK" + } + }, + "summary": "Delete DNS Policy", + "tags": [ + "DNS Policies" + ] + }, + "get": { + "description": "Retrieve specific DNS policy.", + "operationId": "getDnsPolicy", + "parameters": [ + { + "in": "path", + "name": "dnsPolicyId", + "required": true, + "schema": { + "format": "uuid", + "type": "string" + } + }, + { + "in": "path", + "name": "siteId", + "required": true, + "schema": { + "format": "uuid", + "type": "string" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/DNS policy" + } + } + }, + "description": "OK" + } + }, + "summary": "Get DNS Policy", + "tags": [ + "DNS Policies" + ] + }, + "put": { + "description": "Update an existing DNS policy on a site.", + "operationId": "updateDnsPolicy", + "parameters": [ + { + "in": "path", + "name": "dnsPolicyId", + "required": true, + "schema": { + "format": "uuid", + "type": "string" + } + }, + { + "in": "path", + "name": "siteId", + "required": true, + "schema": { + "format": "uuid", + "type": "string" + } + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Create or update DNS policy" + } + } + }, + "required": true + }, + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/DNS policy" + } + } + }, + "description": "OK" + } + }, + "summary": "Update DNS Policy", + "tags": [ + "DNS Policies" + ] + } + }, + "/v1/sites/{siteId}/firewall/policies": { + "get": { + "description": "Retrieve a list of all firewall policies on a site.\n\n
\nFilterable properties (click to expand)\n\n|Name|Type|Allowed functions|\n|-|-|-|\n|`id`|`UUID`|`eq` `ne` `in` `notIn`|\n|`name`|`STRING`|`eq` `ne` `in` `notIn` `like`|\n|`source.zoneId`|`UUID`|`eq` `ne` `in` `notIn`|\n|`destination.zoneId`|`UUID`|`eq` `ne` `in` `notIn`|\n|`metadata.origin`|`STRING`|`eq` `ne` `in` `notIn`|\n
", + "operationId": "getFirewallPolicies", + "parameters": [ + { + "in": "query", + "name": "offset", + "required": false, + "schema": { + "default": 0, + "format": "int32", + "minimum": 0, + "type": "integer" + } + }, + { + "in": "query", + "name": "limit", + "required": false, + "schema": { + "default": 25, + "format": "int32", + "maximum": 200, + "minimum": 0, + "type": "integer" + } + }, + { + "in": "query", + "name": "filter", + "required": false, + "schema": { + "type": "string" + } + }, + { + "in": "path", + "name": "siteId", + "required": true, + "schema": { + "format": "uuid", + "type": "string" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Firewall policy page" + } + } + }, + "description": "OK" + } + }, + "summary": "List Firewall Policies", + "tags": [ + "Firewall" + ] + }, + "post": { + "description": "Create a new firewall policy on a site.", + "operationId": "createFirewallPolicy", + "parameters": [ + { + "in": "path", + "name": "siteId", + "required": true, + "schema": { + "format": "uuid", + "type": "string" + } + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Create or update firewall policy" + } + } + }, + "required": true + }, + "responses": { + "201": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Firewall policy" + } + } + }, + "description": "Created" + } + }, + "summary": "Create Firewall Policy", + "tags": [ + "Firewall" + ] + } + }, + "/v1/sites/{siteId}/firewall/policies/ordering": { + "get": { + "description": "Retrieve user-defined firewall policy ordering for a specific source/destination zone pair.", + "operationId": "getFirewallPolicyOrdering", + "parameters": [ + { + "in": "query", + "name": "sourceFirewallZoneId", + "required": true, + "schema": { + "format": "uuid", + "type": "string" + } + }, + { + "in": "query", + "name": "destinationFirewallZoneId", + "required": true, + "schema": { + "format": "uuid", + "type": "string" + } + }, + { + "in": "path", + "name": "siteId", + "required": true, + "schema": { + "format": "uuid", + "type": "string" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/IntegrationFirewallPolicyOrderingDto" + } + } + }, + "description": "OK" + } + }, + "summary": "Get User-Defined Firewall Policy Ordering", + "tags": [ + "Firewall" + ] + }, + "put": { + "description": "Reorder user-defined firewall policies for a specific source/destination zone pair.", + "operationId": "updateFirewallPolicyOrdering", + "parameters": [ + { + "in": "query", + "name": "sourceFirewallZoneId", + "required": true, + "schema": { + "format": "uuid", + "type": "string" + } + }, + { + "in": "query", + "name": "destinationFirewallZoneId", + "required": true, + "schema": { + "format": "uuid", + "type": "string" + } + }, + { + "in": "path", + "name": "siteId", + "required": true, + "schema": { + "format": "uuid", + "type": "string" + } + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/IntegrationFirewallPolicyOrderingDto" + } + } + }, + "required": true + }, + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/IntegrationFirewallPolicyOrderingDto" + } + } + }, + "description": "OK" + } + }, + "summary": "Reorder User-Defined Firewall Policies", + "tags": [ + "Firewall" + ] + } + }, + "/v1/sites/{siteId}/firewall/policies/{firewallPolicyId}": { + "delete": { + "description": "Delete an existing firewall policy on a site.", + "operationId": "deleteFirewallPolicy", + "parameters": [ + { + "in": "path", + "name": "firewallPolicyId", + "required": true, + "schema": { + "format": "uuid", + "type": "string" + } + }, + { + "in": "path", + "name": "siteId", + "required": true, + "schema": { + "format": "uuid", + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "OK" + } + }, + "summary": "Delete Firewall Policy", + "tags": [ + "Firewall" + ] + }, + "get": { + "description": "Retrieve specific firewall policy.", + "operationId": "getFirewallPolicy", + "parameters": [ + { + "in": "path", + "name": "firewallPolicyId", + "required": true, + "schema": { + "format": "uuid", + "type": "string" + } + }, + { + "in": "path", + "name": "siteId", + "required": true, + "schema": { + "format": "uuid", + "type": "string" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Firewall policy" + } + } + }, + "description": "OK" + } + }, + "summary": "Get Firewall Policy", + "tags": [ + "Firewall" + ] + }, + "patch": { + "description": "Patch an existing firewall policy on a site.", + "operationId": "patchFirewallPolicy", + "parameters": [ + { + "in": "path", + "name": "firewallPolicyId", + "required": true, + "schema": { + "format": "uuid", + "type": "string" + } + }, + { + "in": "path", + "name": "siteId", + "required": true, + "schema": { + "format": "uuid", + "type": "string" + } + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Patch firewall policy" + } + } + }, + "required": true + }, + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Firewall policy" + } + } + }, + "description": "OK" + } + }, + "summary": "Patch Firewall Policy", + "tags": [ + "Firewall" + ] + }, + "put": { + "description": "Update an existing firewall policy on a site.", + "operationId": "updateFirewallPolicy", + "parameters": [ + { + "in": "path", + "name": "firewallPolicyId", + "required": true, + "schema": { + "format": "uuid", + "type": "string" + } + }, + { + "in": "path", + "name": "siteId", + "required": true, + "schema": { + "format": "uuid", + "type": "string" + } + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Create or update firewall policy" + } + } + }, + "required": true + }, + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Firewall policy" + } + } + }, + "description": "OK" + } + }, + "summary": "Update Firewall Policy", + "tags": [ + "Firewall" + ] + } + }, + "/v1/sites/{siteId}/firewall/zones": { + "get": { + "description": "Retrieve a list of all firewall zones on a site.\n\n
\nFilterable properties (click to expand)\n\n|Name|Type|Allowed functions|\n|-|-|-|\n|`id`|`UUID`|`eq` `ne` `in` `notIn`|\n|`name`|`STRING`|`eq` `ne` `in` `notIn` `like`|\n|`metadata.origin`|`STRING`|`eq` `ne` `in` `notIn`|\n|`metadata.configurable`|`BOOLEAN`|`eq` `ne` `isNull` `isNotNull`|\n
", + "operationId": "getFirewallZones", + "parameters": [ + { + "in": "query", + "name": "offset", + "required": false, + "schema": { + "default": 0, + "format": "int32", + "minimum": 0, + "type": "integer" + } + }, + { + "in": "query", + "name": "limit", + "required": false, + "schema": { + "default": 25, + "format": "int32", + "maximum": 200, + "minimum": 0, + "type": "integer" + } + }, + { + "in": "query", + "name": "filter", + "required": false, + "schema": { + "type": "string" + } + }, + { + "in": "path", + "name": "siteId", + "required": true, + "schema": { + "format": "uuid", + "type": "string" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Firewall zones page" + } + } + }, + "description": "OK" + } + }, + "summary": "List Firewall Zones", + "tags": [ + "Firewall" + ] + }, + "post": { + "description": "Create a new custom firewall zone on a site.", + "operationId": "createFirewallZone", + "parameters": [ + { + "in": "path", + "name": "siteId", + "required": true, + "schema": { + "format": "uuid", + "type": "string" + } + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Create or update firewall zone" + } + } + }, + "required": true + }, + "responses": { + "201": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Firewall zone" + } + } + }, + "description": "Created" + } + }, + "summary": "Create Custom Firewall Zone", + "tags": [ + "Firewall" + ] + } + }, + "/v1/sites/{siteId}/firewall/zones/{firewallZoneId}": { + "delete": { + "description": "Delete a custom firewall zone from a site.", + "operationId": "deleteFirewallZone", + "parameters": [ + { + "in": "path", + "name": "firewallZoneId", + "required": true, + "schema": { + "format": "uuid", + "type": "string" + } + }, + { + "in": "path", + "name": "siteId", + "required": true, + "schema": { + "format": "uuid", + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "OK" + } + }, + "summary": "Delete Custom Firewall Zone", + "tags": [ + "Firewall" + ] + }, + "get": { + "description": "Get a firewall zone on a site.", + "operationId": "getFirewallZone", + "parameters": [ + { + "in": "path", + "name": "firewallZoneId", + "required": true, + "schema": { + "format": "uuid", + "type": "string" + } + }, + { + "in": "path", + "name": "siteId", + "required": true, + "schema": { + "format": "uuid", + "type": "string" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Firewall zone" + } + } + }, + "description": "OK" + } + }, + "summary": "Get Firewall Zone", + "tags": [ + "Firewall" + ] + }, + "put": { + "description": "Update a firewall zone on a site.", + "operationId": "updateFirewallZone", + "parameters": [ + { + "in": "path", + "name": "firewallZoneId", + "required": true, + "schema": { + "format": "uuid", + "type": "string" + } + }, + { + "in": "path", + "name": "siteId", + "required": true, + "schema": { + "format": "uuid", + "type": "string" + } + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Create or update firewall zone" + } + } + }, + "required": true + }, + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Firewall zone" + } + } + }, + "description": "OK" + } + }, + "summary": "Update Firewall Zone", + "tags": [ + "Firewall" + ] + } + }, + "/v1/sites/{siteId}/hotspot/vouchers": { + "delete": { + "description": "Remove Hotspot vouchers based on the specified filter criteria.\n\n
\nFilterable properties (click to expand)\n\n|Name|Type|Allowed functions|\n|-|-|-|\n|`id`|`UUID`|`eq` `ne` `in` `notIn`|\n|`createdAt`|`TIMESTAMP`|`eq` `ne` `gt` `ge` `lt` `le`|\n|`name`|`STRING`|`eq` `ne` `in` `notIn` `like`|\n|`code`|`STRING`|`eq` `ne` `in` `notIn`|\n|`authorizedGuestLimit`|`INTEGER`|`isNull` `isNotNull` `eq` `ne` `gt` `ge` `lt` `le`|\n|`authorizedGuestCount`|`INTEGER`|`eq` `ne` `gt` `ge` `lt` `le`|\n|`activatedAt`|`TIMESTAMP`|`eq` `ne` `gt` `ge` `lt` `le`|\n|`expiresAt`|`TIMESTAMP`|`eq` `ne` `gt` `ge` `lt` `le`|\n|`expired`|`BOOLEAN`|`eq` `ne`|\n|`timeLimitMinutes`|`INTEGER`|`eq` `ne` `gt` `ge` `lt` `le`|\n|`dataUsageLimitMBytes`|`INTEGER`|`isNull` `isNotNull` `eq` `ne` `gt` `ge` `lt` `le`|\n|`rxRateLimitKbps`|`INTEGER`|`isNull` `isNotNull` `eq` `ne` `gt` `ge` `lt` `le`|\n|`txRateLimitKbps`|`INTEGER`|`isNull` `isNotNull` `eq` `ne` `gt` `ge` `lt` `le`|\n
", + "operationId": "deleteVouchers", + "parameters": [ + { + "in": "query", + "name": "filter", + "required": true, + "schema": { + "type": "string" + } + }, + { + "in": "path", + "name": "siteId", + "required": true, + "schema": { + "format": "uuid", + "type": "string" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Voucher deletion results" + } + } + }, + "description": "OK" + } + }, + "summary": "Delete Vouchers", + "tags": [ + "Hotspot" + ] + }, + "get": { + "description": "Retrieve a paginated list of Hotspot vouchers.\n\n
\nFilterable properties (click to expand)\n\n|Name|Type|Allowed functions|\n|-|-|-|\n|`id`|`UUID`|`eq` `ne` `in` `notIn`|\n|`createdAt`|`TIMESTAMP`|`eq` `ne` `gt` `ge` `lt` `le`|\n|`name`|`STRING`|`eq` `ne` `in` `notIn` `like`|\n|`code`|`STRING`|`eq` `ne` `in` `notIn`|\n|`authorizedGuestLimit`|`INTEGER`|`isNull` `isNotNull` `eq` `ne` `gt` `ge` `lt` `le`|\n|`authorizedGuestCount`|`INTEGER`|`eq` `ne` `gt` `ge` `lt` `le`|\n|`activatedAt`|`TIMESTAMP`|`eq` `ne` `gt` `ge` `lt` `le`|\n|`expiresAt`|`TIMESTAMP`|`eq` `ne` `gt` `ge` `lt` `le`|\n|`expired`|`BOOLEAN`|`eq` `ne`|\n|`timeLimitMinutes`|`INTEGER`|`eq` `ne` `gt` `ge` `lt` `le`|\n|`dataUsageLimitMBytes`|`INTEGER`|`isNull` `isNotNull` `eq` `ne` `gt` `ge` `lt` `le`|\n|`rxRateLimitKbps`|`INTEGER`|`isNull` `isNotNull` `eq` `ne` `gt` `ge` `lt` `le`|\n|`txRateLimitKbps`|`INTEGER`|`isNull` `isNotNull` `eq` `ne` `gt` `ge` `lt` `le`|\n
", + "operationId": "getVouchers", + "parameters": [ + { + "in": "query", + "name": "offset", + "required": false, + "schema": { + "default": 0, + "format": "int32", + "minimum": 0, + "type": "integer" + } + }, + { + "in": "query", + "name": "limit", + "required": false, + "schema": { + "default": 100, + "format": "int32", + "maximum": 1000, + "minimum": 0, + "type": "integer" + } + }, + { + "in": "query", + "name": "filter", + "required": false, + "schema": { + "type": "string" + } + }, + { + "in": "path", + "name": "siteId", + "required": true, + "schema": { + "format": "uuid", + "type": "string" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Hotspot voucher detail page" + } + } + }, + "description": "OK" + } + }, + "summary": "List Vouchers", + "tags": [ + "Hotspot" + ] + }, + "post": { + "description": "Create one or more Hotspot vouchers.", + "operationId": "createVouchers", + "parameters": [ + { + "in": "path", + "name": "siteId", + "required": true, + "schema": { + "format": "uuid", + "type": "string" + } + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Hotspot voucher creation request" + } + } + }, + "required": true + }, + "responses": { + "201": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/IntegrationVoucherCreationResultDto" + } + } + }, + "description": "Created" + } + }, + "summary": "Generate Vouchers", + "tags": [ + "Hotspot" + ] + } + }, + "/v1/sites/{siteId}/hotspot/vouchers/{voucherId}": { + "delete": { + "description": "Remove a specific Hotspot voucher.", + "operationId": "deleteVoucher", + "parameters": [ + { + "in": "path", + "name": "voucherId", + "required": true, + "schema": { + "format": "uuid", + "type": "string" + } + }, + { + "in": "path", + "name": "siteId", + "required": true, + "schema": { + "format": "uuid", + "type": "string" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Voucher deletion results" + } + } + }, + "description": "OK" + } + }, + "summary": "Delete Voucher", + "tags": [ + "Hotspot" + ] + }, + "get": { + "description": "Retrieve details of a specific Hotspot voucher.", + "operationId": "getVoucher", + "parameters": [ + { + "in": "path", + "name": "voucherId", + "required": true, + "schema": { + "format": "uuid", + "type": "string" + } + }, + { + "in": "path", + "name": "siteId", + "required": true, + "schema": { + "format": "uuid", + "type": "string" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Hotspot voucher details" + } + } + }, + "description": "OK" + } + }, + "summary": "Get Voucher Details", + "tags": [ + "Hotspot" + ] + } + }, + "/v1/sites/{siteId}/networks": { + "get": { + "description": "Retrieve a paginated list of all Networks on a site.\n\n
\nFilterable properties (click to expand)\n\n|Name|Type|Allowed functions|\n|-|-|-|\n|`management`|`STRING`|`eq` `ne` `in` `notIn`|\n|`id`|`UUID`|`eq` `ne` `in` `notIn`|\n|`name`|`STRING`|`eq` `ne` `in` `notIn` `like`|\n|`enabled`|`BOOLEAN`|`eq` `ne`|\n|`vlanId`|`INTEGER`|`eq` `ne` `gt` `ge` `lt` `le` `in` `notIn`|\n|`deviceId`|`UUID`|`eq` `ne` `in` `notIn` `isNull` `isNotNull`|\n|`metadata.origin`|`STRING`|`eq` `ne` `in` `notIn`|\n
", + "operationId": "getNetworksOverviewPage", + "parameters": [ + { + "in": "query", + "name": "offset", + "required": false, + "schema": { + "default": 0, + "format": "int32", + "minimum": 0, + "type": "integer" + } + }, + { + "in": "query", + "name": "limit", + "required": false, + "schema": { + "default": 25, + "format": "int32", + "maximum": 200, + "minimum": 0, + "type": "integer" + } + }, + { + "in": "query", + "name": "filter", + "required": false, + "schema": { + "type": "string" + } + }, + { + "in": "path", + "name": "siteId", + "required": true, + "schema": { + "format": "uuid", + "type": "string" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Network overview page" + } + } + }, + "description": "OK" + } + }, + "summary": "List Networks", + "tags": [ + "Networks" + ] + }, + "post": { + "description": "Create a new network on a site.", + "operationId": "createNetwork", + "parameters": [ + { + "in": "path", + "name": "siteId", + "required": true, + "schema": { + "format": "uuid", + "type": "string" + } + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Create or update Network" + } + } + }, + "required": true + }, + "responses": { + "201": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Network details" + } + } + }, + "description": "Created" + } + }, + "summary": "Create Network", + "tags": [ + "Networks" + ] + } + }, + "/v1/sites/{siteId}/networks/{networkId}": { + "delete": { + "description": "Delete an existing network on a site.", + "operationId": "deleteNetwork", + "parameters": [ + { + "in": "path", + "name": "networkId", + "required": true, + "schema": { + "format": "uuid", + "type": "string" + } + }, + { + "in": "query", + "name": "force", + "required": false, + "schema": { + "default": false, + "type": "boolean" + } + }, + { + "in": "path", + "name": "siteId", + "required": true, + "schema": { + "format": "uuid", + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "OK" + } + }, + "summary": "Delete Network", + "tags": [ + "Networks" + ] + }, + "get": { + "description": "Retrieve detailed information about a specific network.", + "operationId": "getNetworkDetails", + "parameters": [ + { + "in": "path", + "name": "networkId", + "required": true, + "schema": { + "format": "uuid", + "type": "string" + } + }, + { + "in": "path", + "name": "siteId", + "required": true, + "schema": { + "format": "uuid", + "type": "string" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Network details" + } + } + }, + "description": "OK" + } + }, + "summary": "Get Network Details", + "tags": [ + "Networks" + ] + }, + "put": { + "description": "Update an existing network on a site.", + "operationId": "updateNetwork", + "parameters": [ + { + "in": "path", + "name": "networkId", + "required": true, + "schema": { + "format": "uuid", + "type": "string" + } + }, + { + "in": "path", + "name": "siteId", + "required": true, + "schema": { + "format": "uuid", + "type": "string" + } + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Create or update Network" + } + } + }, + "required": true + }, + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Network details" + } + } + }, + "description": "OK" + } + }, + "summary": "Update Network", + "tags": [ + "Networks" + ] + } + }, + "/v1/sites/{siteId}/networks/{networkId}/references": { + "get": { + "description": "Retrieve references to a specific network.", + "operationId": "getNetworkReferences", + "parameters": [ + { + "in": "path", + "name": "networkId", + "required": true, + "schema": { + "format": "uuid", + "type": "string" + } + }, + { + "in": "path", + "name": "siteId", + "required": true, + "schema": { + "format": "uuid", + "type": "string" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Network references" + } + } + }, + "description": "OK" + } + }, + "summary": "Get Network References", + "tags": [ + "Networks" + ] + } + }, + "/v1/sites/{siteId}/radius/profiles": { + "get": { + "description": "Returns available RADIUS authentication profiles, including configuration origin metadata.\n\n
\nFilterable properties (click to expand)\n\n|Name|Type|Allowed functions|\n|-|-|-|\n|`id`|`UUID`|`eq` `ne` `in` `notIn`|\n|`name`|`STRING`|`eq` `ne` `in` `notIn` `like`|\n|`metadata.origin`|`STRING`|`eq` `ne` `in` `notIn`|\n
", + "operationId": "getRadiusProfileOverviewPage", + "parameters": [ + { + "in": "query", + "name": "offset", + "required": false, + "schema": { + "default": 0, + "format": "int32", + "minimum": 0, + "type": "integer" + } + }, + { + "in": "query", + "name": "limit", + "required": false, + "schema": { + "default": 25, + "format": "int32", + "maximum": 200, + "minimum": 0, + "type": "integer" + } + }, + { + "in": "query", + "name": "filter", + "required": false, + "schema": { + "type": "string" + } + }, + { + "in": "path", + "name": "siteId", + "required": true, + "schema": { + "format": "uuid", + "type": "string" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Radius Profile Overview Page" + } + } + }, + "description": "OK" + } + }, + "summary": "List Radius Profiles", + "tags": [ + "Supporting Resources" + ] + } + }, + "/v1/sites/{siteId}/switching/lags": { + "get": { + "description": "Retrieve a paginated list of all LAGs (Link Aggregation Groups) on a site.\n\n
\nFilterable properties (click to expand)\n\n|Name|Type|Allowed functions|\n|-|-|-|\n|`id`|`UUID`|`eq` `ne` `in` `notIn`|\n|`type`|`STRING`|`eq` `ne` `in` `notIn`|\n|`switchStackId`|`UUID`|`eq` `ne` `in` `notIn` `isNull` `isNotNull`|\n|`mcLagDomainId`|`UUID`|`eq` `ne` `in` `notIn` `isNull` `isNotNull`|\n|`members.deviceId`|`SET(UUID)`|`contains` `containsAny` `containsAll` `containsExactly`|\n|`members.portIdxs`|`SET(INTEGER)`|`contains` `containsAny` `containsAll` `containsExactly`|\n|`metadata.origin`|`STRING`|`eq` `ne` `in` `notIn`|\n
", + "operationId": "getLagPage", + "parameters": [ + { + "in": "query", + "name": "offset", + "required": false, + "schema": { + "default": 0, + "format": "int32", + "minimum": 0, + "type": "integer" + } + }, + { + "in": "query", + "name": "limit", + "required": false, + "schema": { + "default": 25, + "format": "int32", + "maximum": 200, + "minimum": 0, + "type": "integer" + } + }, + { + "in": "query", + "name": "filter", + "required": false, + "schema": { + "type": "string" + } + }, + { + "in": "path", + "name": "siteId", + "required": true, + "schema": { + "format": "uuid", + "type": "string" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/IntegrationLagPageDto" + } + } + }, + "description": "OK" + } + }, + "summary": "List LAGs", + "tags": [ + "Switching" + ] + } + }, + "/v1/sites/{siteId}/switching/lags/{lagId}": { + "get": { + "description": "Retrieve LAG details.", + "operationId": "getLag", + "parameters": [ + { + "in": "path", + "name": "lagId", + "required": true, + "schema": { + "format": "uuid", + "type": "string" + } + }, + { + "in": "path", + "name": "siteId", + "required": true, + "schema": { + "format": "uuid", + "type": "string" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/LAG details" + } + } + }, + "description": "OK" + } + }, + "summary": "Get LAG Details", + "tags": [ + "Switching" + ] + } + }, + "/v1/sites/{siteId}/switching/mc-lag-domains": { + "get": { + "description": "Retrieve a paginated list of all MC-LAG Domains on a site.\n\n
\nFilterable properties (click to expand)\n\n|Name|Type|Allowed functions|\n|-|-|-|\n|`id`|`UUID`|`eq` `ne` `in` `notIn`|\n|`name`|`STRING`|`eq` `ne` `in` `notIn` `like`|\n|`peers.deviceId`|`SET(UUID)`|`contains` `containsAny` `containsAll` `containsExactly`|\n|`metadata.origin`|`STRING`|`eq` `ne` `in` `notIn`|\n
", + "operationId": "getMcLagDomainPage", + "parameters": [ + { + "in": "query", + "name": "offset", + "required": false, + "schema": { + "default": 0, + "format": "int32", + "minimum": 0, + "type": "integer" + } + }, + { + "in": "query", + "name": "limit", + "required": false, + "schema": { + "default": 25, + "format": "int32", + "maximum": 200, + "minimum": 0, + "type": "integer" + } + }, + { + "in": "query", + "name": "filter", + "required": false, + "schema": { + "type": "string" + } + }, + { + "in": "path", + "name": "siteId", + "required": true, + "schema": { + "format": "uuid", + "type": "string" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/IntegrationMcLagDomainDtoPageDto" + } + } + }, + "description": "OK" + } + }, + "summary": "List MC-LAG Domains", + "tags": [ + "Switching" + ] + } + }, + "/v1/sites/{siteId}/switching/mc-lag-domains/{mcLagDomainId}": { + "get": { + "description": "Retrieve MC-LAG Domain details.", + "operationId": "getMcLagDomain", + "parameters": [ + { + "in": "path", + "name": "mcLagDomainId", + "required": true, + "schema": { + "format": "uuid", + "type": "string" + } + }, + { + "in": "path", + "name": "siteId", + "required": true, + "schema": { + "format": "uuid", + "type": "string" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/IntegrationMcLagDomainDto" + } + } + }, + "description": "OK" + } + }, + "summary": "Get MC-LAG Domain", + "tags": [ + "Switching" + ] + } + }, + "/v1/sites/{siteId}/switching/switch-stacks": { + "get": { + "description": "Retrieve a paginated list of all Switch Stacks on a site.\n\n
\nFilterable properties (click to expand)\n\n|Name|Type|Allowed functions|\n|-|-|-|\n|`id`|`UUID`|`eq` `ne` `in` `notIn`|\n|`name`|`STRING`|`eq` `ne` `in` `notIn` `like`|\n|`members.deviceId`|`SET(UUID)`|`contains` `containsAny` `containsAll` `containsExactly`|\n|`metadata.origin`|`STRING`|`eq` `ne` `in` `notIn`|\n
", + "operationId": "getSwitchStackPage", + "parameters": [ + { + "in": "query", + "name": "offset", + "required": false, + "schema": { + "default": 0, + "format": "int32", + "minimum": 0, + "type": "integer" + } + }, + { + "in": "query", + "name": "limit", + "required": false, + "schema": { + "default": 25, + "format": "int32", + "maximum": 200, + "minimum": 0, + "type": "integer" + } + }, + { + "in": "query", + "name": "filter", + "required": false, + "schema": { + "type": "string" + } + }, + { + "in": "path", + "name": "siteId", + "required": true, + "schema": { + "format": "uuid", + "type": "string" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/IntegrationSwitchStackDtoPageDto" + } + } + }, + "description": "OK" + } + }, + "summary": "List Switch Stacks", + "tags": [ + "Switching" + ] + } + }, + "/v1/sites/{siteId}/switching/switch-stacks/{switchStackId}": { + "get": { + "description": "Retrieve Switch Stack details.", + "operationId": "getSwitchStack", + "parameters": [ + { + "in": "path", + "name": "switchStackId", + "required": true, + "schema": { + "format": "uuid", + "type": "string" + } + }, + { + "in": "path", + "name": "siteId", + "required": true, + "schema": { + "format": "uuid", + "type": "string" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/IntegrationSwitchStackDto" + } + } + }, + "description": "OK" + } + }, + "summary": "Get Switch Stack", + "tags": [ + "Switching" + ] + } + }, + "/v1/sites/{siteId}/traffic-matching-lists": { + "get": { + "description": "Retrieve all traffic matching lists on a site.\n\n
\nFilterable properties (click to expand)\n\n|Name|Type|Allowed functions|\n|-|-|-|\n|`id`|`UUID`|`eq` `ne` `in` `notIn`|\n|`name`|`STRING`|`eq` `ne` `in` `notIn` `like`|\n
", + "operationId": "getTrafficMatchingLists", + "parameters": [ + { + "in": "query", + "name": "offset", + "required": false, + "schema": { + "default": 0, + "format": "int32", + "minimum": 0, + "type": "integer" + } + }, + { + "in": "query", + "name": "limit", + "required": false, + "schema": { + "default": 25, + "format": "int32", + "maximum": 200, + "minimum": 0, + "type": "integer" + } + }, + { + "in": "query", + "name": "filter", + "required": false, + "schema": { + "type": "string" + } + }, + { + "in": "path", + "name": "siteId", + "required": true, + "schema": { + "format": "uuid", + "type": "string" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Traffic matching lists page" + } + } + }, + "description": "OK" + } + }, + "summary": "List Traffic Matching Lists", + "tags": [ + "Traffic Matching Lists" + ] + }, + "post": { + "description": "Create a new traffic matching list on a site.", + "operationId": "createTrafficMatchingList", + "parameters": [ + { + "in": "path", + "name": "siteId", + "required": true, + "schema": { + "format": "uuid", + "type": "string" + } + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Create or update traffic matching list" + } + } + }, + "required": true + }, + "responses": { + "201": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Traffic matching list" + } + } + }, + "description": "Created" + } + }, + "summary": "Create Traffic Matching List", + "tags": [ + "Traffic Matching Lists" + ] + } + }, + "/v1/sites/{siteId}/traffic-matching-lists/{trafficMatchingListId}": { + "delete": { + "description": "Delete an exist traffic matching list on a site.", + "operationId": "deleteTrafficMatchingList", + "parameters": [ + { + "in": "path", + "name": "trafficMatchingListId", + "required": true, + "schema": { + "format": "uuid", + "type": "string" + } + }, + { + "in": "path", + "name": "siteId", + "required": true, + "schema": { + "format": "uuid", + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "OK" + } + }, + "summary": "Delete Traffic Matching List", + "tags": [ + "Traffic Matching Lists" + ] + }, + "get": { + "description": "Get an exist traffic matching list on a site.", + "operationId": "getTrafficMatchingList", + "parameters": [ + { + "in": "path", + "name": "trafficMatchingListId", + "required": true, + "schema": { + "format": "uuid", + "type": "string" + } + }, + { + "in": "path", + "name": "siteId", + "required": true, + "schema": { + "format": "uuid", + "type": "string" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Traffic matching list" + } + } + }, + "description": "OK" + } + }, + "summary": "Get Traffic Matching List", + "tags": [ + "Traffic Matching Lists" + ] + }, + "put": { + "description": "Update an exist traffic matching list on a site.", + "operationId": "updateTrafficMatchingList", + "parameters": [ + { + "in": "path", + "name": "trafficMatchingListId", + "required": true, + "schema": { + "format": "uuid", + "type": "string" + } + }, + { + "in": "path", + "name": "siteId", + "required": true, + "schema": { + "format": "uuid", + "type": "string" + } + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Create or update traffic matching list" + } + } + }, + "required": true + }, + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Traffic matching list" + } + } + }, + "description": "OK" + } + }, + "summary": "Update Traffic Matching List", + "tags": [ + "Traffic Matching Lists" + ] + } + }, + "/v1/sites/{siteId}/vpn/servers": { + "get": { + "description": "Retrieve a paginated list of all VPN servers on a site.\n\n
\nFilterable properties (click to expand)\n\n|Name|Type|Allowed functions|\n|-|-|-|\n|`type`|`STRING`|`eq` `ne` `in` `notIn`|\n|`id`|`UUID`|`eq` `ne` `in` `notIn`|\n|`name`|`STRING`|`eq` `ne` `in` `notIn` `like`|\n|`enabled`|`BOOLEAN`|`eq` `ne`|\n|`metadata.origin`|`STRING`|`eq` `ne` `in` `notIn`|\n
", + "operationId": "getVpnServerPage", + "parameters": [ + { + "in": "query", + "name": "offset", + "required": false, + "schema": { + "default": 0, + "format": "int32", + "minimum": 0, + "type": "integer" + } + }, + { + "in": "query", + "name": "limit", + "required": false, + "schema": { + "default": 25, + "format": "int32", + "maximum": 200, + "minimum": 0, + "type": "integer" + } + }, + { + "in": "query", + "name": "filter", + "required": false, + "schema": { + "type": "string" + } + }, + { + "in": "path", + "name": "siteId", + "required": true, + "schema": { + "format": "uuid", + "type": "string" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/IntegrationVpnServerOverviewPageDto" + } + } + }, + "description": "OK" + } + }, + "summary": "List VPN Servers", + "tags": [ + "Supporting Resources" + ] + } + }, + "/v1/sites/{siteId}/vpn/site-to-site-tunnels": { + "get": { + "description": "Retrieve a paginated list of all site-to-site VPN tunnels on a site.\n\n
\nFilterable properties (click to expand)\n\n|Name|Type|Allowed functions|\n|-|-|-|\n|`type`|`STRING`|`eq` `ne` `in` `notIn`|\n|`id`|`UUID`|`eq` `ne` `in` `notIn`|\n|`name`|`STRING`|`eq` `ne` `in` `notIn` `like`|\n|`metadata.origin`|`STRING`|`eq` `ne` `in` `notIn`|\n|`metadata.source`|`STRING`|`eq` `ne` `in` `notIn` `isNull` `isNotNull`|\n
", + "operationId": "getSiteToSiteVpnTunnelPage", + "parameters": [ + { + "in": "query", + "name": "offset", + "required": false, + "schema": { + "default": 0, + "format": "int32", + "minimum": 0, + "type": "integer" + } + }, + { + "in": "query", + "name": "limit", + "required": false, + "schema": { + "default": 25, + "format": "int32", + "maximum": 200, + "minimum": 0, + "type": "integer" + } + }, + { + "in": "query", + "name": "filter", + "required": false, + "schema": { + "type": "string" + } + }, + { + "in": "path", + "name": "siteId", + "required": true, + "schema": { + "format": "uuid", + "type": "string" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/IntegrationSiteToSiteVpnTunnelOverviewPageDto" + } + } + }, + "description": "OK" + } + }, + "summary": "List Site-To-Site VPN Tunnels", + "tags": [ + "Supporting Resources" + ] + } + }, + "/v1/sites/{siteId}/wans": { + "get": { + "description": "Returns available WAN interface definitions for a given site,\nincluding identifiers and names. Useful for network and NAT configuration.", + "operationId": "getWansOverviewPage", + "parameters": [ + { + "in": "query", + "name": "offset", + "required": false, + "schema": { + "default": 0, + "format": "int32", + "minimum": 0, + "type": "integer" + } + }, + { + "in": "query", + "name": "limit", + "required": false, + "schema": { + "default": 25, + "format": "int32", + "maximum": 200, + "minimum": 0, + "type": "integer" + } + }, + { + "in": "path", + "name": "siteId", + "required": true, + "schema": { + "format": "uuid", + "type": "string" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/WAN overview page" + } + } + }, + "description": "OK" + } + }, + "summary": "List WAN Interfaces", + "tags": [ + "Supporting Resources" + ] + } + }, + "/v1/sites/{siteId}/wifi/broadcasts": { + "get": { + "description": "Retrieve a paginated list of all Wifi Broadcasts on a site.\n\n
\nFilterable properties (click to expand)\n\n|Name|Type|Allowed functions|\n|-|-|-|\n|`type`|`STRING`|`eq` `ne` `in` `notIn`|\n|`id`|`UUID`|`eq` `ne` `in` `notIn`|\n|`enabled`|`BOOLEAN`|`eq` `ne`|\n|`name`|`STRING`|`eq` `ne` `in` `notIn` `like`|\n|`broadcastingFrequenciesGHz`|`SET(DECIMAL)`|`contains` `containsAny` `containsAll` `containsExactly`|\n|`metadata.origin`|`STRING`|`eq` `ne` `in` `notIn`|\n|`network.type`|`STRING`|`eq` `ne` `in` `notIn` `isNull` `isNotNull`|\n|`network.networkId`|`UUID`|`eq` `ne` `in` `notIn`|\n|`securityConfiguration.type`|`STRING`|`eq` `ne` `in` `notIn`|\n|`broadcastingDeviceFilter.type`|`STRING`|`eq` `ne` `in` `notIn` `isNull` `isNotNull`|\n|`broadcastingDeviceFilter.deviceIds`|`SET(UUID)`|`contains` `containsAny` `containsAll` `containsExactly`|\n|`broadcastingDeviceFilter.deviceTagIds`|`SET(UUID)`|`contains` `containsAny` `containsAll` `containsExactly`|\n|`hotspotConfiguration.type`|`STRING`|`eq` `ne` `in` `notIn`|\n
", + "operationId": "getWifiBroadcastPage", + "parameters": [ + { + "in": "query", + "name": "offset", + "required": false, + "schema": { + "default": 0, + "format": "int32", + "minimum": 0, + "type": "integer" + } + }, + { + "in": "query", + "name": "limit", + "required": false, + "schema": { + "default": 25, + "format": "int32", + "maximum": 200, + "minimum": 0, + "type": "integer" + } + }, + { + "in": "query", + "name": "filter", + "required": false, + "schema": { + "type": "string" + } + }, + { + "in": "path", + "name": "siteId", + "required": true, + "schema": { + "format": "uuid", + "type": "string" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/IntegrationWifiBroadcastPageDto" + } + } + }, + "description": "OK" + } + }, + "summary": "List Wifi Broadcasts", + "tags": [ + "WiFi Broadcasts" + ] + }, + "post": { + "description": "Create a new Wifi Broadcast on the specified site.", + "operationId": "createWifiBroadcast", + "parameters": [ + { + "in": "path", + "name": "siteId", + "required": true, + "schema": { + "format": "uuid", + "type": "string" + } + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Wifi broadcast create or update" + } + } + }, + "required": true + }, + "responses": { + "201": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Wifi broadcast details" + } + } + }, + "description": "Created" + } + }, + "summary": "Create Wifi Broadcast", + "tags": [ + "WiFi Broadcasts" + ] + } + }, + "/v1/sites/{siteId}/wifi/broadcasts/{wifiBroadcastId}": { + "delete": { + "description": "Delete an existing Wifi Broadcast from the specified site.", + "operationId": "deleteWifiBroadcast", + "parameters": [ + { + "in": "path", + "name": "wifiBroadcastId", + "required": true, + "schema": { + "format": "uuid", + "type": "string" + } + }, + { + "in": "query", + "name": "force", + "required": false, + "schema": { + "default": false, + "type": "boolean" + } + }, + { + "in": "path", + "name": "siteId", + "required": true, + "schema": { + "format": "uuid", + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "OK" + } + }, + "summary": "Delete Wifi Broadcast", + "tags": [ + "WiFi Broadcasts" + ] + }, + "get": { + "description": "Retrieve detailed information about a specific Wifi.", + "operationId": "getWifiBroadcastDetails", + "parameters": [ + { + "in": "path", + "name": "wifiBroadcastId", + "required": true, + "schema": { + "format": "uuid", + "type": "string" + } + }, + { + "in": "path", + "name": "siteId", + "required": true, + "schema": { + "format": "uuid", + "type": "string" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Wifi broadcast details" + } + } + }, + "description": "OK" + } + }, + "summary": "Get Wifi Broadcast Details", + "tags": [ + "WiFi Broadcasts" + ] + }, + "put": { + "description": "Update an existing Wifi Broadcast on the specified site.", + "operationId": "updateWifiBroadcast", + "parameters": [ + { + "in": "path", + "name": "wifiBroadcastId", + "required": true, + "schema": { + "format": "uuid", + "type": "string" + } + }, + { + "in": "path", + "name": "siteId", + "required": true, + "schema": { + "format": "uuid", + "type": "string" + } + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Wifi broadcast create or update" + } + } + }, + "required": true + }, + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Wifi broadcast details" + } + } + }, + "description": "OK" + } + }, + "summary": "Update Wifi Broadcast", + "tags": [ + "WiFi Broadcasts" + ] + } + } + }, + "servers": [ + { + "url": "https://api.ui.com/v1/connector/consoles/{consoleId}/proxy/network/integration", + "description": "UniFi API Cloud Connector", + "variables": { + "consoleId": { + "default": "942A6FF664C0000000000964970E0000000009E710560000000068A9873F:9999999999", + "description": "ID of the console to proxy requests to" + } + } + }, + { + "url": "https://{consoleIP}/proxy/network/integration", + "description": "Local Console", + "variables": { + "consoleIP": { + "default": "192.168.0.1", + "description": "IP address of the console on the local network" + } + } + } + ], + "tags": [ + { + "description": "Returns general details about the UniFi Network application,\nincluding version and runtime metadata. Useful for integration validation.", + "name": "Application Info" + }, + { + "description": "Endpoints for listing and managing UniFi sites within a local Network application.\nSite ID is required for most other API requests.", + "name": "Sites" + }, + { + "description": "Endpoints to list, inspect, and interact with UniFi devices, including adopted and pending devices.\nProvides device stats, port control, and actions.", + "name": "UniFi Devices" + }, + { + "description": "Endpoints for viewing and managing connected clients (wired, wireless, VPN, and guest).\nSupports actions such as authorizing or unauthorizing guest access.", + "name": "Clients" + }, + { + "description": "Endpoints for creating, updating, deleting, and inspecting network configurations\nincluding VLANs, DHCP, NAT, and IPv4/IPv6 settings.", + "name": "Networks" + }, + { + "description": "Endpoints to create, update, or remove WiFi networks (SSIDs).\nSupports configuration of security, band steering, multicast filtering, and captive portals.", + "name": "WiFi Broadcasts" + }, + { + "description": "Endpoints for managing guest access via Hotspot vouchers — create, list, or revoke vouchers\nand track their usage and expiration.", + "name": "Hotspot" + }, + { + "description": "Endpoints for managing custom firewall zones and policies within a site.\nDefine or update network segmentation and security boundaries.", + "name": "Firewall" + }, + { + "description": "Endpoints for creating, listing, and managing ACL (Access Control List) rule\nthat enforce traffic filtering across devices and networks.", + "name": "Access Control (ACL Rules)" + }, + { + "description": "Endpoints for managing switching features like Switch Stacking and LAG.", + "name": "Switching" + }, + { + "description": "Endpoints for managing DNS Policies within a site.", + "name": "DNS Policies" + }, + { + "description": "Endpoints for managing port and IP address lists used across firewall policy configurations.", + "name": "Traffic Matching Lists" + }, + { + "description": "Contains read-only reference endpoints used to retrieve supporting data\nsuch as WAN interfaces, DPI categories, country codes, RADIUS profiles, and device tags.", + "name": "Supporting Resources" + } + ] +} \ No newline at end of file diff --git a/pyproject.toml b/pyproject.toml new file mode 100644 index 0000000..577f7b7 --- /dev/null +++ b/pyproject.toml @@ -0,0 +1,27 @@ +[project] +name = "firewall" +version = "0.1.0" +description = "Add your description here" +readme = "README.md" +requires-python = ">=3.13" +dependencies = [ + "requests>=2.34.2", + "pytest>=8.0.0", + "pyyaml>=6.0.0", + "python-dotenv>=1.0.0", + "debugpy>=1.8.0", +] + +[tool.pytest.ini_options] +pythonpath = ["."] + +[tool.pyright] +typeCheckingMode = "strict" +extraPaths = ["/var/home/ducoterra/.local/lib/python3.14/site-packages"] + +[dependency-groups] +dev = [ + "debugpy>=1.8.21", + "pyright>=1.1.411", + "ruff>=0.16.1", +] diff --git a/tests/test_ip_lookup.py b/tests/test_ip_lookup.py new file mode 100644 index 0000000..1801964 --- /dev/null +++ b/tests/test_ip_lookup.py @@ -0,0 +1,47 @@ +"""Tests for ip_lookup module.""" + +from unittest.mock import MagicMock, patch + +from ip_lookup import get_ipv4, get_ipv6 + + +class TestGetIpv4: + def test_returns_stripped_ip(self) -> None: + mock_result = MagicMock() + mock_result.stdout = " 1.2.3.4 \n" + + with patch("ip_lookup.subprocess.run", return_value=mock_result) as mock_run: + ip = get_ipv4() + + assert ip == "1.2.3.4" + mock_run.assert_called_once_with(["curl", "-4", "ifconfig.me"], capture_output=True, text=True, check=False) + + def test_empty_response(self) -> None: + mock_result = MagicMock() + mock_result.stdout = "" + + with patch("ip_lookup.subprocess.run", return_value=mock_result): + ip = get_ipv4() + + assert ip == "" + + +class TestGetIpv6: + def test_returns_stripped_ip(self) -> None: + mock_result = MagicMock() + mock_result.stdout = " 2001:db8::1 \n" + + with patch("ip_lookup.subprocess.run", return_value=mock_result) as mock_run: + ip = get_ipv6() + + assert ip == "2001:db8::1" + mock_run.assert_called_once_with(["curl", "-6", "ifconfig.me"], capture_output=True, text=True, check=False) + + def test_empty_response(self) -> None: + mock_result = MagicMock() + mock_result.stdout = "" + + with patch("ip_lookup.subprocess.run", return_value=mock_result): + ip = get_ipv6() + + assert ip == "" diff --git a/tests/test_main.py b/tests/test_main.py new file mode 100644 index 0000000..3248657 --- /dev/null +++ b/tests/test_main.py @@ -0,0 +1,226 @@ +"""Tests for main module.""" + +from __future__ import annotations + +from pathlib import Path +from unittest.mock import MagicMock, patch + +from main import ( + RuleConfig, + build_zone_map, + load_config, + process_rule, + send_ntfy_notification, +) +from unifi_firewall import FirewallZone + + +class TestBuildZoneMap: + def test_builds_map_from_zones(self) -> None: + zones: list[FirewallZone] = [ + {"id": "zone-wan", "name": "WAN", "networkIds": [], "metadata": {}}, + {"id": "zone-lan", "name": "LAN", "networkIds": [], "metadata": {}}, + ] + + zone_map = build_zone_map(zones) + + assert zone_map == {"WAN": "zone-wan", "LAN": "zone-lan"} + + def test_empty_zones(self) -> None: + zone_map = build_zone_map([]) + assert zone_map == {} + + +class TestLoadConfig: + def test_loads_valid_config(self, tmp_path: Path) -> None: + config_file = tmp_path / "rules.yaml" + config_file.write_text( + """ +rules: + - name: "Test Rule" + source_zone: "WAN" + dest_zone: "LAN" + ip_version: "IPV4" + action: "ALLOW" +""" + ) + + rules = load_config(str(config_file)) + + assert len(rules) == 1 + assert rules[0].get("name") == "Test Rule" + + def test_exits_on_missing_file(self) -> None: + with patch("sys.exit") as mock_exit: + load_config("/nonexistent/rules.yaml") + mock_exit.assert_called_once_with(1) + + def test_exits_on_invalid_yaml(self, tmp_path: Path) -> None: + config_file = tmp_path / "rules.yaml" + config_file.write_text("invalid: yaml: content: [") + + with patch("sys.exit") as mock_exit: + load_config(str(config_file)) + mock_exit.assert_called_once_with(1) + + +class TestSendNtfyNotification: + def test_sends_notification(self) -> None: + mock_response = MagicMock() + mock_response.raise_for_status = MagicMock() + + with ( + patch("main.NTFY_URL", "https://ntfy.sh"), + patch("main.NTFY_TOPIC", "test"), + patch("main.NTFY_API_KEY", "test-key"), + patch("main.requests.post", return_value=mock_response) as mock_post, + ): + send_ntfy_notification("Title", "Message", priority=4) + + mock_post.assert_called_once() + call_kwargs = mock_post.call_args + assert call_kwargs[0][0] == "https://ntfy.sh/test" + assert call_kwargs[1]["data"] == b"Message" + assert call_kwargs[1]["headers"]["Title"] == "Title" + assert call_kwargs[1]["headers"]["Priority"] == "4" + + def test_skips_when_no_url(self) -> None: + with ( + patch("main.NTFY_URL", ""), + patch("main.requests.post") as mock_post, + ): + send_ntfy_notification("Title", "Message") + mock_post.assert_not_called() + + def test_handles_request_error(self) -> None: + import requests as req + + with ( + patch("main.NTFY_URL", "https://ntfy.sh"), + patch("main.NTFY_TOPIC", "test"), + patch("main.requests.post", side_effect=req.RequestException("timeout")), + ): + # Should not raise, only log warning + send_ntfy_notification("Title", "Message") + + +class TestProcessRule: + def test_creates_new_rule(self) -> None: + mock_session = MagicMock() + mock_session.get.return_value = MagicMock(json=MagicMock(return_value={"data": []}), raise_for_status=MagicMock()) + mock_session.post.return_value = MagicMock( + json=MagicMock(return_value={"id": "new-id", "name": "Test Rule"}), + raise_for_status=MagicMock(), + ) + + rule: RuleConfig = { + "name": "Test Rule", + "source_zone": "WAN", + "dest_zone": "LAN", + "ip_version": "IPV4", + "action": "ALLOW", + } + zone_map = {"WAN": "wan-id", "LAN": "lan-id"} + + change = process_rule(mock_session, "https://unifi.local", "site-1", rule, zone_map, "1.2.3.4") + + assert change["action"] == "created" + assert change["rule_name"] == "Test Rule" + assert change["error"] is None + + def test_skips_rule_with_matching_ip(self) -> None: + mock_session = MagicMock() + existing_policy = { + "id": "pol-1", + "name": "Test Rule", + "source": { + "zoneId": "wan-id", + "trafficFilter": { + "type": "IP_ADDRESS", + "ipAddressFilter": { + "type": "IP_ADDRESSES", + "items": [{"type": "IP_ADDRESS", "value": "1.2.3.4"}], + }, + }, + }, + } + mock_session.get.return_value = MagicMock(json=MagicMock(return_value={"data": [existing_policy]}), raise_for_status=MagicMock()) + + rule: RuleConfig = { + "name": "Test Rule", + "source_zone": "WAN", + "dest_zone": "LAN", + "ip_version": "IPV4", + } + zone_map = {"WAN": "wan-id", "LAN": "lan-id"} + + change = process_rule(mock_session, "https://unifi.local", "site-1", rule, zone_map, "1.2.3.4") + + assert change["action"] == "skipped" + mock_session.put.assert_not_called() + mock_session.post.assert_not_called() + + def test_updates_rule_with_different_ip(self) -> None: + mock_session = MagicMock() + existing_policy = { + "id": "pol-1", + "name": "Test Rule", + "source": { + "zoneId": "wan-id", + "trafficFilter": { + "type": "IP_ADDRESS", + "ipAddressFilter": { + "type": "IP_ADDRESSES", + "items": [{"type": "IP_ADDRESS", "value": "5.6.7.8"}], + }, + }, + }, + } + mock_session.get.return_value = MagicMock(json=MagicMock(return_value={"data": [existing_policy]}), raise_for_status=MagicMock()) + mock_session.put.return_value = MagicMock(json=MagicMock(return_value={"id": "pol-1"}), raise_for_status=MagicMock()) + + rule: RuleConfig = { + "name": "Test Rule", + "source_zone": "WAN", + "dest_zone": "LAN", + "ip_version": "IPV4", + } + zone_map = {"WAN": "wan-id", "LAN": "lan-id"} + + change = process_rule(mock_session, "https://unifi.local", "site-1", rule, zone_map, "1.2.3.4") + + assert change["action"] == "updated" + mock_session.put.assert_called_once() + + def test_fails_on_missing_source_zone(self) -> None: + mock_session = MagicMock() + + rule: RuleConfig = { + "name": "Test Rule", + "source_zone": "UNKNOWN", + "dest_zone": "LAN", + "ip_version": "IPV4", + } + zone_map = {"LAN": "lan-id"} + + change = process_rule(mock_session, "https://unifi.local", "site-1", rule, zone_map, "1.2.3.4") + + assert change["action"] == "failed" + assert "Source zone" in (change["error"] or "") + + def test_fails_on_api_error(self) -> None: + mock_session = MagicMock() + mock_session.get.side_effect = Exception("Connection error") + + rule: RuleConfig = { + "name": "Test Rule", + "source_zone": "WAN", + "dest_zone": "LAN", + "ip_version": "IPV4", + } + zone_map = {"WAN": "wan-id", "LAN": "lan-id"} + + change = process_rule(mock_session, "https://unifi.local", "site-1", rule, zone_map, "1.2.3.4") + + assert change["action"] == "failed" + assert "Failed to list policies" in (change["error"] or "") diff --git a/tests/test_unifi_firewall.py b/tests/test_unifi_firewall.py new file mode 100644 index 0000000..25a6228 --- /dev/null +++ b/tests/test_unifi_firewall.py @@ -0,0 +1,299 @@ +"""Tests for unifi_firewall module.""" + +from __future__ import annotations + +from typing import Any +from unittest.mock import MagicMock + +from unifi_firewall import ( + FirewallPolicyCreatePayload, + build_policy_payload, + create_policy, + get_policy, + get_session, + get_source_ip_from_policy, + list_policies, + list_zones, + update_policy, +) + + +class MockHttpError(Exception): + """Mock HTTP error for testing.""" + + +class MockResponse: + def __init__(self, json_data: Any, status_code: int = 200) -> None: + self.json_data = json_data + self.status_code = status_code + + def json(self) -> Any: + return self.json_data + + def raise_for_status(self) -> None: + if self.status_code >= 400: + raise MockHttpError(f"HTTP {self.status_code}") + + +class TestGetSession: + def test_creates_session_with_headers(self) -> None: + session = get_session("https://unifi.local", "test-token", True) + + assert session.headers["X-API-Key"] == "test-token" + assert session.headers["Content-Type"] == "application/json" + assert session.verify is True + + def test_verify_ssl_false(self) -> None: + session = get_session("https://unifi.local", "test-token", False) + + assert session.verify is False + + +class TestListZones: + def test_returns_zones_from_data_key(self) -> None: + mock_session = MagicMock() + mock_session.get.return_value = MockResponse({"data": [{"id": "zone-1", "name": "WAN", "networkIds": [], "metadata": {}}]}) + + zones = list_zones(mock_session, "https://unifi.local", "site-1") + + assert len(zones) == 1 + assert zones[0]["name"] == "WAN" + mock_session.get.assert_called_once_with("https://unifi.local/proxy/network/integration/v1/sites/site-1/firewall/zones") + + def test_returns_zones_as_list(self) -> None: + mock_session = MagicMock() + mock_session.get.return_value = MockResponse([{"id": "zone-1", "name": "LAN", "networkIds": [], "metadata": {}}]) + + zones = list_zones(mock_session, "https://unifi.local", "site-1") + + assert len(zones) == 1 + assert zones[0]["name"] == "LAN" + + +class TestListPolicies: + def test_returns_policies_without_filter(self) -> None: + mock_session = MagicMock() + mock_session.get.return_value = MockResponse({"data": []}) + + policies = list_policies(mock_session, "https://unifi.local", "site-1") + + assert policies == [] + mock_session.get.assert_called_once_with("https://unifi.local/proxy/network/integration/v1/sites/site-1/firewall/policies", params={}) + + def test_returns_policies_with_name_filter(self) -> None: + mock_session = MagicMock() + mock_session.get.return_value = MockResponse({"data": []}) + + policies = list_policies(mock_session, "https://unifi.local", "site-1", name_filter="Test Rule") + + assert policies == [] + call_args = mock_session.get.call_args + assert call_args[1]["params"]["filter"] == "name.like('Test Rule')" + + +class TestGetPolicy: + def test_returns_single_policy(self) -> None: + mock_session = MagicMock() + policy_data = {"id": "pol-1", "name": "Test", "source": {"zoneId": "z1", "trafficFilter": None}, "destination": {"zoneId": "z2", "trafficFilter": None}, "action": {"type": "ALLOW", "allowReturnTraffic": True}, "ipProtocolScope": {"ipVersion": "IPV4"}, "enabled": True, "loggingEnabled": False, "index": 0, "metadata": {}} + mock_session.get.return_value = MockResponse(policy_data) + + policy = get_policy(mock_session, "https://unifi.local", "site-1", "pol-1") + + assert policy["id"] == "pol-1" + mock_session.get.assert_called_once_with("https://unifi.local/proxy/network/integration/v1/sites/site-1/firewall/policies/pol-1") + + +class TestCreatePolicy: + def test_creates_policy(self) -> None: + mock_session = MagicMock() + result = {"id": "new-pol", "name": "New Rule", "source": {"zoneId": "z1", "trafficFilter": None}, "destination": {"zoneId": "z2", "trafficFilter": None}, "action": {"type": "ALLOW", "allowReturnTraffic": True}, "ipProtocolScope": {"ipVersion": "IPV4"}, "enabled": True, "loggingEnabled": False, "index": 0, "metadata": {}} + mock_session.post.return_value = MockResponse(result, status_code=201) + + payload: FirewallPolicyCreatePayload = build_policy_payload( + name="New Rule", + source_ip="1.2.3.4", + ip_version="IPV4", + src_zone_id="z1", + dst_zone_id="z2", + action_type="ALLOW", + ) + policy = create_policy(mock_session, "https://unifi.local", "site-1", payload) + + assert policy["id"] == "new-pol" + mock_session.post.assert_called_once() + + +class TestUpdatePolicy: + def test_updates_policy(self) -> None: + mock_session = MagicMock() + result = {"id": "pol-1", "name": "Updated Rule", "source": {"zoneId": "z1", "trafficFilter": None}, "destination": {"zoneId": "z2", "trafficFilter": None}, "action": {"type": "ALLOW", "allowReturnTraffic": True}, "ipProtocolScope": {"ipVersion": "IPV4"}, "enabled": True, "loggingEnabled": False, "index": 0, "metadata": {}} + mock_session.put.return_value = MockResponse(result) + + payload: FirewallPolicyCreatePayload = build_policy_payload( + name="Updated Rule", + source_ip="5.6.7.8", + ip_version="IPV4", + src_zone_id="z1", + dst_zone_id="z2", + action_type="ALLOW", + ) + policy = update_policy(mock_session, "https://unifi.local", "site-1", "pol-1", payload) + + assert policy["id"] == "pol-1" + mock_session.put.assert_called_once() + + +class TestBuildPolicyPayload: + def test_basic_allow_ipv4(self) -> None: + payload = build_policy_payload( + name="Test Rule", + source_ip="1.2.3.4", + ip_version="IPV4", + src_zone_id="wan-zone", + dst_zone_id="lan-zone", + action_type="ALLOW", + ) + + assert payload["name"] == "Test Rule" + assert payload["source"]["zoneId"] == "wan-zone" + assert payload["destination"]["zoneId"] == "lan-zone" + assert payload["action"]["type"] == "ALLOW" + assert payload["action"]["allowReturnTraffic"] is True + assert payload["ipProtocolScope"]["ipVersion"] == "IPV4" + assert payload["enabled"] is True + assert payload["loggingEnabled"] is False + + # Check source IP filter + tf = payload["source"]["trafficFilter"] + assert tf is not None + assert tf["type"] == "IP_ADDRESS" + assert tf["ipAddressFilter"]["type"] == "IP_ADDRESSES" + assert tf["ipAddressFilter"]["items"][0]["value"] == "1.2.3.4" + + def test_with_dest_ports(self) -> None: + payload = build_policy_payload( + name="Test Rule", + source_ip="1.2.3.4", + ip_version="IPV4", + src_zone_id="wan-zone", + dst_zone_id="lan-zone", + action_type="ALLOW", + dest_ports=[22, 80, 443], + ) + + dest_tf = payload["destination"]["trafficFilter"] + assert dest_tf is not None + assert dest_tf["type"] == "PORT" + port_filter = dest_tf["portFilter"] + assert port_filter is not None + assert port_filter["type"] == "PORTS" + assert len(port_filter["items"]) == 3 + assert port_filter["items"][0] == {"type": "PORT_NUMBER", "value": 22} + + def test_with_port_ranges(self) -> None: + payload = build_policy_payload( + name="Test Rule", + source_ip="1.2.3.4", + ip_version="IPV4", + src_zone_id="wan-zone", + dst_zone_id="lan-zone", + action_type="ALLOW", + dest_port_ranges=[{"start": 8000, "stop": 9000}], + ) + + dest_tf = payload["destination"]["trafficFilter"] + assert dest_tf is not None + assert dest_tf["type"] == "PORT" + port_filter = dest_tf["portFilter"] + assert port_filter is not None + assert port_filter["items"][0] == {"type": "PORT_NUMBER_RANGE", "start": 8000, "stop": 9000} + + def test_with_protocol(self) -> None: + payload = build_policy_payload( + name="Test Rule", + source_ip="1.2.3.4", + ip_version="IPV6", + src_zone_id="wan-zone", + dst_zone_id="lan-zone", + action_type="ALLOW", + protocol="tcp", + ) + + assert payload["ipProtocolScope"]["ipVersion"] == "IPV6" + pf = payload["ipProtocolScope"]["protocolFilter"] + assert pf is not None + assert pf["protocol"] == {"name": "TCP"} + + def test_block_action(self) -> None: + payload = build_policy_payload( + name="Block Rule", + source_ip="5.6.7.8", + ip_version="IPV4", + src_zone_id="wan-zone", + dst_zone_id="lan-zone", + action_type="BLOCK", + ) + + assert payload["action"]["type"] == "BLOCK" + assert "allowReturnTraffic" not in payload["action"] + + +class TestGetSourceIpFromPolicy: + def test_extracts_ip_from_policy(self) -> None: + policy: dict[str, Any] = { + "id": "pol-1", + "name": "Test", + "source": { + "zoneId": "wan-zone", + "trafficFilter": { + "type": "IP_ADDRESS", + "ipAddressFilter": { + "type": "IP_ADDRESSES", + "items": [{"type": "IP_ADDRESS", "value": "1.2.3.4"}], + }, + }, + }, + "destination": {"zoneId": "lan-zone", "trafficFilter": None}, + "action": {"type": "ALLOW", "allowReturnTraffic": True}, + "ipProtocolScope": {"ipVersion": "IPV4"}, + "enabled": True, + "loggingEnabled": False, + "index": 0, + "metadata": {}, + } + + ip = get_source_ip_from_policy(policy) # type: ignore[arg-type] + assert ip == "1.2.3.4" + + def test_returns_none_no_traffic_filter(self) -> None: + policy: dict[str, Any] = { + "source": {"zoneId": "wan-zone", "trafficFilter": None}, + } + + ip = get_source_ip_from_policy(policy) # type: ignore[arg-type] + assert ip is None + + def test_returns_none_wrong_filter_type(self) -> None: + policy: dict[str, Any] = { + "source": { + "zoneId": "wan-zone", + "trafficFilter": {"type": "NETWORK"}, + }, + } + + ip = get_source_ip_from_policy(policy) # type: ignore[arg-type] + assert ip is None + + def test_returns_none_empty_items(self) -> None: + policy: dict[str, Any] = { + "source": { + "zoneId": "wan-zone", + "trafficFilter": { + "type": "IP_ADDRESS", + "ipAddressFilter": {"type": "IP_ADDRESSES", "items": []}, + }, + }, + } + + ip = get_source_ip_from_policy(policy) # type: ignore[arg-type] + assert ip is None diff --git a/unifi_firewall.py b/unifi_firewall.py new file mode 100644 index 0000000..6621f4a --- /dev/null +++ b/unifi_firewall.py @@ -0,0 +1,334 @@ +"""UniFi Network API client for firewall policy management.""" + +from __future__ import annotations + +import logging +from typing import Any, Literal, TypedDict, cast + +import requests + +logger = logging.getLogger(__name__) + + +# ========== Response TypedDicts ========== + + +class FirewallZone(TypedDict): + """Firewall zone from GET /firewall/zones.""" + + id: str + name: str + networkIds: list[str] + metadata: dict[str, Any] + + +class FirewallPolicySource(TypedDict): + """Firewall policy source.""" + + zoneId: str + trafficFilter: dict[str, Any] | None + + +class FirewallPolicyDestination(TypedDict): + """Firewall policy destination.""" + + zoneId: str + trafficFilter: dict[str, Any] | None + + +class FirewallPolicyActionAllowDto(TypedDict): + """Allow action for firewall policy.""" + + type: Literal["ALLOW"] + allowReturnTraffic: bool + + +class FirewallPolicyActionBlockDto(TypedDict): + """Block action for firewall policy.""" + + type: Literal["BLOCK"] + + +class FirewallPolicyActionRejectDto(TypedDict): + """Reject action for firewall policy.""" + + type: Literal["REJECT"] + + +FirewallPolicyAction = FirewallPolicyActionAllowDto | FirewallPolicyActionBlockDto | FirewallPolicyActionRejectDto + + +class FirewallPolicyIpv4ProtocolScopeDto(TypedDict): + """IPv4 protocol scope for firewall policy.""" + + ipVersion: Literal["IPV4"] + protocolFilter: dict[str, Any] | None + + +class FirewallPolicyIpv6ProtocolScopeDto(TypedDict): + """IPv6 protocol scope for firewall policy.""" + + ipVersion: Literal["IPV6"] + protocolFilter: dict[str, Any] | None + + +FirewallPolicyIpProtocolScope = FirewallPolicyIpv4ProtocolScopeDto | FirewallPolicyIpv6ProtocolScopeDto + + +class FirewallPolicy(TypedDict): + """Firewall policy from GET /firewall/policies.""" + + id: str + name: str + source: FirewallPolicySource + destination: FirewallPolicyDestination + action: FirewallPolicyAction + ipProtocolScope: FirewallPolicyIpProtocolScope + enabled: bool + loggingEnabled: bool + index: int + metadata: dict[str, Any] + description: str | None + connectionStateFilter: list[str] | None + ipsecFilter: str | None + schedule: dict[str, Any] | None + + +# ========== Request TypedDicts ========== + + +class FirewallPolicyCreatePayload(TypedDict): + """Payload for POST/PUT /firewall/policies.""" + + name: str + source: FirewallPolicySource + destination: FirewallPolicyDestination + action: FirewallPolicyAction + ipProtocolScope: FirewallPolicyIpProtocolScope + enabled: bool + loggingEnabled: bool + description: str | None + connectionStateFilter: list[str] | None + ipsecFilter: str | None + schedule: dict[str, Any] | None + + +# ========== Session helper ========== + + +def get_session(host: str, api_token: str, verify_ssl: bool) -> requests.Session: + """Create an authenticated requests session for the UniFi API.""" + session = requests.Session() + session.headers.update( + { + "X-API-Key": api_token, + "Content-Type": "application/json", + } + ) + session.verify = verify_ssl + return session + + +# ========== API functions ========== + + +def _api_url(host: str, site_id: str, path: str) -> str: + """Build full API URL.""" + return f"{host}/proxy/network/integration/v1/sites/{site_id}{path}" + + +def list_zones(session: requests.Session, host: str, site_id: str) -> list[FirewallZone]: + """List all firewall zones.""" + url = _api_url(host, site_id, "/firewall/zones") + logger.debug("Listing firewall zones from %s", url) + response = session.get(url) + response.raise_for_status() + data = response.json() + return data.get("data", data) if isinstance(data, dict) else data # type: ignore[no-any-return] + + +def list_policies(session: requests.Session, host: str, site_id: str, name_filter: str | None = None) -> list[FirewallPolicy]: + """List firewall policies, optionally filtered by name.""" + url = _api_url(host, site_id, "/firewall/policies") + params: dict[str, str] = {} + if name_filter: + params["filter"] = f'name.like(\'{name_filter}\')' + logger.debug("Listing firewall policies from %s (filter=%s)", url, params.get("filter")) + response = session.get(url, params=params) + response.raise_for_status() + data = response.json() + return data.get("data", data) if isinstance(data, dict) else data # type: ignore[no-any-return] + + +def get_policy(session: requests.Session, host: str, site_id: str, policy_id: str) -> FirewallPolicy: + """Get a single firewall policy by ID.""" + url = _api_url(host, site_id, f"/firewall/policies/{policy_id}") + logger.debug("Getting firewall policy %s from %s", policy_id, url) + response = session.get(url) + response.raise_for_status() + return response.json() + + +def create_policy(session: requests.Session, host: str, site_id: str, payload: FirewallPolicyCreatePayload) -> FirewallPolicy: + """Create a new firewall policy.""" + url = _api_url(host, site_id, "/firewall/policies") + logger.debug("Creating firewall policy '%s' at %s", payload["name"], url) + response = session.post(url, json=cast(dict[str, Any], payload)) + response.raise_for_status() + return response.json() + + +def update_policy(session: requests.Session, host: str, site_id: str, policy_id: str, payload: FirewallPolicyCreatePayload) -> FirewallPolicy: + """Update an existing firewall policy (full replace).""" + url = _api_url(host, site_id, f"/firewall/policies/{policy_id}") + logger.debug("Updating firewall policy %s at %s", policy_id, url) + response = session.put(url, json=cast(dict[str, Any], payload)) + response.raise_for_status() + return response.json() + + +# ========== Payload builder ========== + + +def build_policy_payload( + name: str, + source_ip: str, + ip_version: Literal["IPV4", "IPV6"], + src_zone_id: str, + dst_zone_id: str, + action_type: Literal["ALLOW", "BLOCK", "REJECT"], + allow_return_traffic: bool = True, + protocol: str | None = None, + dest_ports: list[int] | None = None, + dest_port_ranges: list[dict[str, int]] | None = None, + logging_enabled: bool = False, + enabled: bool = True, + description: str | None = None, +) -> FirewallPolicyCreatePayload: + """Build a full firewall policy payload from rule configuration.""" + # Build source with IP filter + source: FirewallPolicySource = { + "zoneId": src_zone_id, + "trafficFilter": { + "type": "IP_ADDRESS", + "ipAddressFilter": { + "type": "IP_ADDRESSES", + "matchOpposite": False, + "items": [{"type": "IP_ADDRESS", "value": source_ip}], + }, + "portFilter": None, + }, + } + + # Build destination with optional port filter + dest_port_items: list[dict[str, Any]] = [] + if dest_ports: + dest_port_items.extend({"type": "PORT_NUMBER", "value": p} for p in dest_ports) + if dest_port_ranges: + dest_port_items.extend( + {"type": "PORT_NUMBER_RANGE", "start": r["start"], "stop": r["stop"]} for r in dest_port_ranges + ) + + dest_port_filter: dict[str, Any] | None = None + if dest_port_items: + dest_port_filter = { + "type": "PORTS", + "matchOpposite": False, + "items": dest_port_items, + } + + destination: FirewallPolicyDestination = { + "zoneId": dst_zone_id, + "trafficFilter": ( + { + "type": "PORT", + "portFilter": dest_port_filter, + } + if dest_port_filter + else None + ), + } + + # Build action + if action_type == "ALLOW": + action: FirewallPolicyAction = {"type": "ALLOW", "allowReturnTraffic": allow_return_traffic} + elif action_type == "BLOCK": + action = {"type": "BLOCK"} + else: + action = {"type": "REJECT"} + + # Build protocol scope + protocol_filter: dict[str, Any] | None = None + if protocol: + protocol_filter = { + "type": "NAMED_PROTOCOL", + "matchOpposite": False, + "protocol": { + "name": protocol.upper(), + }, + } + + if ip_version == "IPV4": + ip_protocol_scope: FirewallPolicyIpProtocolScope = { + "ipVersion": "IPV4", + "protocolFilter": protocol_filter, + } + else: + ip_protocol_scope = { + "ipVersion": "IPV6", + "protocolFilter": protocol_filter, + } + + return { + "name": name, + "source": source, + "destination": destination, + "action": action, + "ipProtocolScope": ip_protocol_scope, + "enabled": enabled, + "loggingEnabled": logging_enabled, + "description": description, + "connectionStateFilter": None, + "ipsecFilter": None, + "schedule": None, + } + + +# ========== IP extraction ========== + + +def get_source_ip_from_policy(policy: FirewallPolicy) -> str | None: + """Extract the source IP address from a firewall policy.""" + source = policy.get("source") + if not source: + return None + + traffic_filter = source.get("trafficFilter") + if not traffic_filter: + return None + + tf_type: str | None = traffic_filter.get("type") + if tf_type != "IP_ADDRESS": + return None + + ip_filter: dict[str, Any] | None = traffic_filter.get("ipAddressFilter") + if not ip_filter: + return None + + ip_filter_type: str | None = ip_filter.get("type") + if ip_filter_type != "IP_ADDRESSES": + return None + + items: list[Any] | None = ip_filter.get("items") + if not items or len(items) == 0: + return None + + first_item: dict[str, Any] | None = cast(dict[str, Any], items[0]) if isinstance(items[0], dict) else None + if not first_item: + return None + + if first_item.get("type") != "IP_ADDRESS": + return None + + value: str | None = first_item.get("value") if isinstance(first_item.get("value"), str) else None + return value diff --git a/uv.lock b/uv.lock new file mode 100644 index 0000000..8417543 --- /dev/null +++ b/uv.lock @@ -0,0 +1,307 @@ +version = 1 +revision = 3 +requires-python = ">=3.13" + +[[package]] +name = "certifi" +version = "2026.7.22" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/a3/c2/24167ea9858356b47a87a50d39908bfdb72ceeefe0041586e704e5376b3a/certifi-2026.7.22.tar.gz", hash = "sha256:741e2c3b351ddf169a738da9f2c048608ff7f2c5cc02f1ebc6b118bb090d5d55", size = 138112, upload-time = "2026-07-22T03:35:12.644Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/0b/a7/71ac2cff56fec219ed242bb11b8efb69fcc4bec75db06fb7bfe35de520e6/certifi-2026.7.22-py3-none-any.whl", hash = "sha256:62f22742b58a1a33014a2b6b706588a8d7e2a88ae7bd1a6ebe8c992928483775", size = 136983, upload-time = "2026-07-22T03:35:11.276Z" }, +] + +[[package]] +name = "charset-normalizer" +version = "3.4.9" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/bd/2a/23f34ec9d04624958e137efdc394888716353190e75f25dd22c7a2c7a8aa/charset_normalizer-3.4.9.tar.gz", hash = "sha256:673611bbd43f0810bec0b0f028ddeaaa501190339cac411f347ac76917c3ae7b", size = 152439, upload-time = "2026-07-07T14:34:58.454Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/b2/06/97ec2aeae780b31d742b6352218b43841a6871e2564578ca522dce4a45c3/charset_normalizer-3.4.9-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:440eede837960000d74978f0eba527be106b5b9aee0daf779d395276ed0b0614", size = 317688, upload-time = "2026-07-07T14:33:35.408Z" }, + { url = "https://files.pythonhosted.org/packages/d0/39/8ff066c672434225f8d25f8b739f992af250944392173dcc88362681c9bf/charset_normalizer-3.4.9-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:21e764fd1e70b6a3e205a0e46f3051701f98a8cb3fad66eeb80e48bb502f8698", size = 214982, upload-time = "2026-07-07T14:33:36.996Z" }, + { url = "https://files.pythonhosted.org/packages/92/8f/3a47a3667c83c2df9483d91644c6c107de3bf8874aa1793da9d3012eb986/charset_normalizer-3.4.9-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:e4fd89cc178bced6ad29cb3e6dd4aa63fa5017c3524dbd0b25998fb64a87cc8b", size = 236460, upload-time = "2026-07-07T14:33:38.536Z" }, + { url = "https://files.pythonhosted.org/packages/f1/60/b22cdbee7e4013dab8b0d7647fc6181120fbbbc8f7025c226d15bd5a47fc/charset_normalizer-3.4.9-cp313-cp313-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:bd47ba7fc3ca94896759ea0109775132d3e7ab921fbf54038e1bab2e46c313c9", size = 232003, upload-time = "2026-07-07T14:33:40.059Z" }, + { url = "https://files.pythonhosted.org/packages/ea/f8/72eb13dcabe7257035cea8aefd922caad2f110d252bf9f67c4c2ca763aee/charset_normalizer-3.4.9-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:84fd18bcc17526fc2b3c1af7d2b9217d32c9c04448c16ec693b9b4f1985c3d33", size = 223149, upload-time = "2026-07-07T14:33:41.631Z" }, + { url = "https://files.pythonhosted.org/packages/b0/3e/faee8f9de92b14ee1198e9163252bb15efee7301b31256a3b6d9ebfdd0dd/charset_normalizer-3.4.9-cp313-cp313-manylinux_2_31_armv7l.whl", hash = "sha256:5b10cd92fc5c498b35a8635df6d5a100207f88b63a4dc1de7ef9a548e1e2cd63", size = 207901, upload-time = "2026-07-07T14:33:43.209Z" }, + { url = "https://files.pythonhosted.org/packages/3a/25/45f30093ae27dd7b92a793b61882a38685f993700113ca36e0c9c14965e1/charset_normalizer-3.4.9-cp313-cp313-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:a4fbdde9dd4a9ce5fd52c2b3a347bb50cc89483ef783f1cb00d408c13f7a96c0", size = 219176, upload-time = "2026-07-07T14:33:44.725Z" }, + { url = "https://files.pythonhosted.org/packages/48/18/c8f397329c35e32f6a837e488986f4ae03bd2abebc453b48714991630c2f/charset_normalizer-3.4.9-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:416c229f77e5ea25b3dfd4b582f8d73d7e43c22320302b9ab128a2d3a0b38efe", size = 217356, upload-time = "2026-07-07T14:33:46.192Z" }, + { url = "https://files.pythonhosted.org/packages/86/7e/5ce0bba863470fd1902d5e5843968951bddf38abe4742fc97116ef4598b3/charset_normalizer-3.4.9-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:75286256590a6320cf106a0d28970d3560aad9ee09aa7b34fb40524792436d35", size = 209614, upload-time = "2026-07-07T14:33:47.705Z" }, + { url = "https://files.pythonhosted.org/packages/6c/ef/2473d3c4d869155be4af1191111d59c4d5c4e0173026f7e85b176e23bf65/charset_normalizer-3.4.9-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:69b157c5d3292bcd443faca052f3096f637f1e074b98212a933c074ae23dc3b8", size = 224991, upload-time = "2026-07-07T14:33:49.238Z" }, + { url = "https://files.pythonhosted.org/packages/d0/a3/53ddae3db108a088156aa8ddfafd411ebbc1340f48c5573f697b27f69a39/charset_normalizer-3.4.9-cp313-cp313-win32.whl", hash = "sha256:51307f5c71007673a2bf8232ad973483d281e74cb99c8c5a990af1eefa6277d9", size = 150622, upload-time = "2026-07-07T14:33:50.711Z" }, + { url = "https://files.pythonhosted.org/packages/e8/ef/6953a77c7cf2c2ff9998e6f575ab3e380119f100223381565a4f94c1f836/charset_normalizer-3.4.9-cp313-cp313-win_amd64.whl", hash = "sha256:fe2c7201c642b7c308f1675355ad7ff7b66acfe3541625efe5a3ad38f29d6115", size = 161947, upload-time = "2026-07-07T14:33:52.197Z" }, + { url = "https://files.pythonhosted.org/packages/6e/fb/d560d1d1555debbfe7849d9cac6145c1b537709d79576bf22557ed803b82/charset_normalizer-3.4.9-cp313-cp313-win_arm64.whl", hash = "sha256:611057cc5d5c0afc743ba8be6bd828c17e0aaa8643f9d0a9b9bb7dea80eb8012", size = 152594, upload-time = "2026-07-07T14:33:53.486Z" }, + { url = "https://files.pythonhosted.org/packages/7e/8d/496817fa0944239ecae662dd57ea765cfeaec6a735f9f025d4b7b72e7143/charset_normalizer-3.4.9-cp314-cp314-macosx_10_15_universal2.whl", hash = "sha256:0327fcd59a935777d83410750c50600ee9571af2846f71ce40f25b13da1ef380", size = 317253, upload-time = "2026-07-07T14:33:54.994Z" }, + { url = "https://files.pythonhosted.org/packages/2b/f9/ef4a69ea338ad3c0deceea0f5f7d2380ae8b52132b06d652cb0d2cd86706/charset_normalizer-3.4.9-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:8a79d9f4d8001473a30c163556b3c3bfebec837495a412dde78b51672f6134f9", size = 215898, upload-time = "2026-07-07T14:33:56.334Z" }, + { url = "https://files.pythonhosted.org/packages/8c/e7/5ddfd76fc061eb52de219658a4aa431cbacadf0a0219c8854f00da50d289/charset_normalizer-3.4.9-cp314-cp314-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:33bdcc2a32c0a0e861f60841a512c8acc658c87c2ac59d89e3a46dacf7d866e4", size = 236718, upload-time = "2026-07-07T14:33:57.9Z" }, + { url = "https://files.pythonhosted.org/packages/49/ba/768fa3f36048d81c477a0ce61f813bc1454d80917ccfe550abd9f44f5e24/charset_normalizer-3.4.9-cp314-cp314-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:f840ed6d8ecba8255df8c42b87fadeda98ddfc6eeec05e2dc66e26d46dd6f58a", size = 232519, upload-time = "2026-07-07T14:33:59.811Z" }, + { url = "https://files.pythonhosted.org/packages/f4/c4/b3e049d2aa3766180c78507110543d9d50894cc97f57de543f1be521dcdc/charset_normalizer-3.4.9-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:c25fe15c70c59eb7c5ce8c06a1f3fa1da0ecc5ea1e7a5922c40fd2fa9b0d5046", size = 223143, upload-time = "2026-07-07T14:34:01.517Z" }, + { url = "https://files.pythonhosted.org/packages/19/79/55c32d06d76ae4feafe053f061f3e3ab70bcf19f4007797ce8c3efda7830/charset_normalizer-3.4.9-cp314-cp314-manylinux_2_31_armv7l.whl", hash = "sha256:f7fb7d750cfa0a070d2c24e831fd3481019a60dd317ea2b39acbcebc08b6ed81", size = 206742, upload-time = "2026-07-07T14:34:03.04Z" }, + { url = "https://files.pythonhosted.org/packages/10/e0/47c079dd82d217c807479cd59ffd30af56307ea31c108b75758970459ad3/charset_normalizer-3.4.9-cp314-cp314-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:4d1c96a7a18b9690a4d46df09e3e3382406ae3213727cd1019ebade1c4a81917", size = 219191, upload-time = "2026-07-07T14:34:04.657Z" }, + { url = "https://files.pythonhosted.org/packages/42/ab/b9bc2e77d6b44a7e46ef62ec5cac1c9a6ba7b9135a5d560f002696ec9995/charset_normalizer-3.4.9-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:a4cfde78a9f2880208d16a93b795726a3017d5977e08d1e162a7a31322479c41", size = 218328, upload-time = "2026-07-07T14:34:06.115Z" }, + { url = "https://files.pythonhosted.org/packages/f1/78/c9c71d599f5aa2d42bcdd35cbbd46d7f535351a57e40ff7d8e5a7e219401/charset_normalizer-3.4.9-cp314-cp314-musllinux_1_2_armv7l.whl", hash = "sha256:d4d6fcde76f94f5cb9e43e9e9a61f16dacefd228cbbf6f1a09bd9b219a92f1a1", size = 207406, upload-time = "2026-07-07T14:34:07.554Z" }, + { url = "https://files.pythonhosted.org/packages/f6/39/c914445c321a845097ce4f6ac7de9a18228a77b766272125a1ce00d851eb/charset_normalizer-3.4.9-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:898f0e9068ca27d37f8e83a5b962821df851532e6c4a7d615c1c033f9da6eedf", size = 225157, upload-time = "2026-07-07T14:34:09.061Z" }, + { url = "https://files.pythonhosted.org/packages/9b/f2/c0d4b8508565a36bc5c624e88ed297f5b0b1095011034d7f5b83a69908b5/charset_normalizer-3.4.9-cp314-cp314-win32.whl", hash = "sha256:c1c948747b03be832dceed96ca815cef7360de9aa19d37c730f8e3f6101aca48", size = 151095, upload-time = "2026-07-07T14:34:10.901Z" }, + { url = "https://files.pythonhosted.org/packages/49/fd/a1d26144398c67486422a72bf5812cda22cb4ccfcd95a290fb41ceb4b8e2/charset_normalizer-3.4.9-cp314-cp314-win_amd64.whl", hash = "sha256:16b65ea0f2465b6fb52aa22de5eca612aa964ddfec00a912e26f4656cbef890b", size = 162796, upload-time = "2026-07-07T14:34:12.47Z" }, + { url = "https://files.pythonhosted.org/packages/20/95/d75e82f8ce9fd323ebf059c16c9aadefb22a1ecde13b7840b35835e4886c/charset_normalizer-3.4.9-cp314-cp314-win_arm64.whl", hash = "sha256:40a126142a56b2dfc0aacbad1de8310cbf60da7656db0e6b16eebd48e3e93519", size = 153334, upload-time = "2026-07-07T14:34:14.044Z" }, + { url = "https://files.pythonhosted.org/packages/00/5e/17398df3a139985ba9d11ed072531986f408c8fca952835ef1ab1820c02b/charset_normalizer-3.4.9-cp314-cp314t-macosx_10_15_universal2.whl", hash = "sha256:609b3ba8fcc0fb5ab7af00719d0fb6ad0cb518e48e7712d12fd68f1327951198", size = 338848, upload-time = "2026-07-07T14:34:15.688Z" }, + { url = "https://files.pythonhosted.org/packages/cd/91/7253a32e86b7e1d1239b1b36ba6dd0f021a21107ab33054b53119cc083b9/charset_normalizer-3.4.9-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:51447e9aa2684679af07ca5021c3db526e0284347ebf4ffcec1154c3350cfe32", size = 223022, upload-time = "2026-07-07T14:34:17.248Z" }, + { url = "https://files.pythonhosted.org/packages/cb/32/2e64bd2be10e89c61e57ebe6a93fd98ae88eb7ebe414b5121f22c96c69eb/charset_normalizer-3.4.9-cp314-cp314t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:cc1b0fff8ead343dae06305f954eb8468ba0ec1a97881f42489d198e4ce3c632", size = 241590, upload-time = "2026-07-07T14:34:18.813Z" }, + { url = "https://files.pythonhosted.org/packages/3d/ef/d96ec496cfea0c21db43b0ad03891308b02388d054cc902cf0e5a1ad6a88/charset_normalizer-3.4.9-cp314-cp314t-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:fa36ec09ef71d158186bc79e359ff5fdd6e7996fe8ab638f00d6b93139ba4fcf", size = 239584, upload-time = "2026-07-07T14:34:20.52Z" }, + { url = "https://files.pythonhosted.org/packages/d4/ce/9af95f7876194bd7a14e3dfe4a4de2e0bff02666a3910d72beafd06cc297/charset_normalizer-3.4.9-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:df115d4d83168fdf2cae48ef1ff6d1cb4c466364e30861b37121de0f3bf1b990", size = 230224, upload-time = "2026-07-07T14:34:22.189Z" }, + { url = "https://files.pythonhosted.org/packages/52/94/af74dde74a3996bd959c350709bfe50e297823d70a8c1cbd54b838880863/charset_normalizer-3.4.9-cp314-cp314t-manylinux_2_31_armv7l.whl", hash = "sha256:f86c6358749bd4fda175388691e3ba8c46e24c5347d0afd20f9b7edfc9faf07d", size = 212667, upload-time = "2026-07-07T14:34:23.857Z" }, + { url = "https://files.pythonhosted.org/packages/ee/f0/f1c4fe746c395922961b5916ed1d7d6e7d4c84851d19ed43cc89980ec953/charset_normalizer-3.4.9-cp314-cp314t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:32286a2c8d167e897177b673176c1e3e00d4057caf5d2b64eef9a3666b03018e", size = 227179, upload-time = "2026-07-07T14:34:25.586Z" }, + { url = "https://files.pythonhosted.org/packages/e4/56/6c745619ac397e8871e2bcd3cea1eec86b877488f33888b3aef5c3ed506e/charset_normalizer-3.4.9-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:83aed2c10721ddd90f68140685391b50811a880af20654c59af6b6c66c40513c", size = 225372, upload-time = "2026-07-07T14:34:27.212Z" }, + { url = "https://files.pythonhosted.org/packages/78/ad/98aae8630ac71f16711968e38a5acfecce41b778bf2f0312851020f565a8/charset_normalizer-3.4.9-cp314-cp314t-musllinux_1_2_armv7l.whl", hash = "sha256:cd6c3d4b783c556fa00bf540854e42f135e2f256abd29669fcd0da0f2dec79c2", size = 215222, upload-time = "2026-07-07T14:34:28.774Z" }, + { url = "https://files.pythonhosted.org/packages/f7/40/9593d54209765207a7f11073c06494c1721e4ca4a0a426c597679bf7f91e/charset_normalizer-3.4.9-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:ee2f2a527e3c1a6e6411eb4209642e138b544a2d72fe5d0d76daf77b24063534", size = 231958, upload-time = "2026-07-07T14:34:30.345Z" }, + { url = "https://files.pythonhosted.org/packages/b1/27/693ee5e8a18191eb38647360c51cd505013e2bd3b366aa43fd5344c21e3c/charset_normalizer-3.4.9-cp314-cp314t-win32.whl", hash = "sha256:0d861473f743244d349b50f850d10eb87aeb22bbdcc8e64f79273c94af5a8226", size = 155580, upload-time = "2026-07-07T14:34:31.884Z" }, + { url = "https://files.pythonhosted.org/packages/80/3f/bd97d3d9c613013d07cb7733d299385b41df37f0471310f5a73dc359f0b8/charset_normalizer-3.4.9-cp314-cp314t-win_amd64.whl", hash = "sha256:9b8e0f3107e2200b76f6054de99016eac3ee6762713587b36baaa7e4bd2ae177", size = 167620, upload-time = "2026-07-07T14:34:33.438Z" }, + { url = "https://files.pythonhosted.org/packages/3d/c6/eee9dca4439b1061f76373f06ea855678cc4a64c1c3c90b50e479edbb8eb/charset_normalizer-3.4.9-cp314-cp314t-win_arm64.whl", hash = "sha256:19ac87f93086ce37b86e098888555c4b4bc48102279bae3350098c0ed664b501", size = 158037, upload-time = "2026-07-07T14:34:35.018Z" }, + { url = "https://files.pythonhosted.org/packages/98/2b/f97f1c193fb855c345d678f5077d6926034db0722df74c8f057020e05a25/charset_normalizer-3.4.9-py3-none-any.whl", hash = "sha256:68e5f26a1ad57ded6d1cfb85331d1c1a195314756471d97758c48498bb4dcdf5", size = 64538, upload-time = "2026-07-07T14:34:56.993Z" }, +] + +[[package]] +name = "colorama" +version = "0.4.6" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/d8/53/6f443c9a4a8358a93a6792e2acffb9d9d5cb0a5cfd8802644b7b1c9a02e4/colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44", size = 27697, upload-time = "2022-10-25T02:36:22.414Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/d1/d6/3965ed04c63042e047cb6a3e6ed1a63a35087b6a609aa3a15ed8ac56c221/colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6", size = 25335, upload-time = "2022-10-25T02:36:20.889Z" }, +] + +[[package]] +name = "debugpy" +version = "1.8.21" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/f2/aa/12037145b7a56eaa5b29b41872f7a21b538e807e13f32c4d3c46e59be084/debugpy-1.8.21.tar.gz", hash = "sha256:a3c53278e84c94e11bd87c53970ec391d1a67396c8b22609fcac576520e611a6", size = 1697577, upload-time = "2026-06-01T19:30:35.156Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/77/6b/d817e1f8cc77aa055d37fba092e0febfdff40fe652d8d53d4cd7a86ad98d/debugpy-1.8.21-cp313-cp313-macosx_15_0_universal2.whl", hash = "sha256:13678151fc401e2d68c9880b91e28714f797d40422994572b24560ef80910a88", size = 2477398, upload-time = "2026-06-01T19:30:57.644Z" }, + { url = "https://files.pythonhosted.org/packages/48/57/412421516afc3055fa577516f00beec3d663f9b0ab330639547ae6c57720/debugpy-1.8.21-cp313-cp313-manylinux_2_34_x86_64.whl", hash = "sha256:ecbd158386c31ffe71d46f72d44d56e66331ab9b16cad649156d514368f23ab2", size = 3962096, upload-time = "2026-06-01T19:30:59.235Z" }, + { url = "https://files.pythonhosted.org/packages/c1/62/2c616337cf6ba7b07ebbc97f02c6c945a8e2f76b365e33ee809c32ee36d1/debugpy-1.8.21-cp313-cp313-win32.whl", hash = "sha256:2c2ae706dec41d99a9ca1f7ebc987a83e65578363be6f6b3ac9067504917fae1", size = 5336288, upload-time = "2026-06-01T19:31:00.79Z" }, + { url = "https://files.pythonhosted.org/packages/f8/99/9175103392f84c4b1bf7622888cdc68da07f0ff7d9e581266428f6776033/debugpy-1.8.21-cp313-cp313-win_amd64.whl", hash = "sha256:aa648733047443eb1d07682c4ef287d36a54507b643ffdf38b09a3ef002c72a0", size = 5376567, upload-time = "2026-06-01T19:31:02.56Z" }, + { url = "https://files.pythonhosted.org/packages/ce/3d/f4bbb323a548bfab2af3d6b4ffd9bf22636e55956a1285d317a1de643aad/debugpy-1.8.21-cp314-cp314-macosx_15_0_universal2.whl", hash = "sha256:9bb2a685287a2ac9b181cde89edcec64845cb51de7faaa75badb9a698bc24782", size = 2477209, upload-time = "2026-06-01T19:31:04.157Z" }, + { url = "https://files.pythonhosted.org/packages/8c/2d/6e7ec524984a1702777868de49a4c53202bddac2a432a76a093469587750/debugpy-1.8.21-cp314-cp314-manylinux_2_34_x86_64.whl", hash = "sha256:3d6922439bf33fd38a3e2c447869ebc7b97da5cd3d329ff1ef9bc06c4903437e", size = 3927115, upload-time = "2026-06-01T19:31:05.863Z" }, + { url = "https://files.pythonhosted.org/packages/97/47/d1aa6d64005a98a9144647d99306b419396f9ad7bf1d73c119e17a81fb4d/debugpy-1.8.21-cp314-cp314-win32.whl", hash = "sha256:15d4963bd5ffa48f0da0947fd06757fa7621945048a14ad7705431566d3c0e7c", size = 5336724, upload-time = "2026-06-01T19:31:07.711Z" }, + { url = "https://files.pythonhosted.org/packages/5f/67/b905b90d163af11878c1af8abafa4a25206335e112e284e413454543a6da/debugpy-1.8.21-cp314-cp314-win_amd64.whl", hash = "sha256:fe0744a12353406de0ae8ccff0d0a4a666f00801a3db8fd04e7a5f761cd520e8", size = 5373803, upload-time = "2026-06-01T19:31:09.469Z" }, + { url = "https://files.pythonhosted.org/packages/95/51/67e7cf11a53e40694f720457d5b3a1cdaaa3d5a9a633e482f225456b93ff/debugpy-1.8.21-py2.py3-none-any.whl", hash = "sha256:b1e37d333663c8851516a47364ef473da127f9caebe4417e6df6f5825a7e9a92", size = 5352888, upload-time = "2026-06-01T19:31:25.186Z" }, +] + +[[package]] +name = "firewall" +version = "0.1.0" +source = { virtual = "." } +dependencies = [ + { name = "debugpy" }, + { name = "pytest" }, + { name = "python-dotenv" }, + { name = "pyyaml" }, + { name = "requests" }, +] + +[package.dev-dependencies] +dev = [ + { name = "debugpy" }, + { name = "pyright" }, + { name = "ruff" }, +] + +[package.metadata] +requires-dist = [ + { name = "debugpy", specifier = ">=1.8.0" }, + { name = "pytest", specifier = ">=8.0.0" }, + { name = "python-dotenv", specifier = ">=1.0.0" }, + { name = "pyyaml", specifier = ">=6.0.0" }, + { name = "requests", specifier = ">=2.34.2" }, +] + +[package.metadata.requires-dev] +dev = [ + { name = "debugpy", specifier = ">=1.8.21" }, + { name = "pyright", specifier = ">=1.1.411" }, + { name = "ruff", specifier = ">=0.16.1" }, +] + +[[package]] +name = "idna" +version = "3.18" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/cd/63/9496c57188a2ee585e0f1db071d75089a11e98aa86eb99d9d7618fc1edce/idna-3.18.tar.gz", hash = "sha256:ffb385a7e039654cef1ab9ef32c6fafe283c0c0467bba1d9029738ce4a14a848", size = 196711, upload-time = "2026-06-02T14:34:07.794Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/1e/5e/d4e9f1a599fb8e573b7b87160658329fbf28d19eac2718f51fc3def3aa5a/idna-3.18-py3-none-any.whl", hash = "sha256:7f952cbe720b688055e3f87de14f5c3e5fdaa8bc3928985c4077ca689de849a2", size = 65455, upload-time = "2026-06-02T14:34:06.319Z" }, +] + +[[package]] +name = "iniconfig" +version = "2.3.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/72/34/14ca021ce8e5dfedc35312d08ba8bf51fdd999c576889fc2c24cb97f4f10/iniconfig-2.3.0.tar.gz", hash = "sha256:c76315c77db068650d49c5b56314774a7804df16fee4402c1f19d6d15d8c4730", size = 20503, upload-time = "2025-10-18T21:55:43.219Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/cb/b1/3846dd7f199d53cb17f49cba7e651e9ce294d8497c8c150530ed11865bb8/iniconfig-2.3.0-py3-none-any.whl", hash = "sha256:f631c04d2c48c52b84d0d0549c99ff3859c98df65b3101406327ecc7d53fbf12", size = 7484, upload-time = "2025-10-18T21:55:41.639Z" }, +] + +[[package]] +name = "nodeenv" +version = "1.10.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/24/bf/d1bda4f6168e0b2e9e5958945e01910052158313224ada5ce1fb2e1113b8/nodeenv-1.10.0.tar.gz", hash = "sha256:996c191ad80897d076bdfba80a41994c2b47c68e224c542b48feba42ba00f8bb", size = 55611, upload-time = "2025-12-20T14:08:54.006Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/88/b2/d0896bdcdc8d28a7fc5717c305f1a861c26e18c05047949fb371034d98bd/nodeenv-1.10.0-py2.py3-none-any.whl", hash = "sha256:5bb13e3eed2923615535339b3c620e76779af4cb4c6a90deccc9e36b274d3827", size = 23438, upload-time = "2025-12-20T14:08:52.782Z" }, +] + +[[package]] +name = "packaging" +version = "26.2" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/d7/f1/e7a6dd94a8d4a5626c03e4e99c87f241ba9e350cd9e6d75123f992427270/packaging-26.2.tar.gz", hash = "sha256:ff452ff5a3e828ce110190feff1178bb1f2ea2281fa2075aadb987c2fb221661", size = 228134, upload-time = "2026-04-24T20:15:23.917Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/df/b2/87e62e8c3e2f4b32e5fe99e0b86d576da1312593b39f47d8ceef365e95ed/packaging-26.2-py3-none-any.whl", hash = "sha256:5fc45236b9446107ff2415ce77c807cee2862cb6fac22b8a73826d0693b0980e", size = 100195, upload-time = "2026-04-24T20:15:22.081Z" }, +] + +[[package]] +name = "pluggy" +version = "1.6.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/f9/e2/3e91f31a7d2b083fe6ef3fa267035b518369d9511ffab804f839851d2779/pluggy-1.6.0.tar.gz", hash = "sha256:7dcc130b76258d33b90f61b658791dede3486c3e6bfb003ee5c9bfb396dd22f3", size = 69412, upload-time = "2025-05-15T12:30:07.975Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/54/20/4d324d65cc6d9205fabedc306948156824eb9f0ee1633355a8f7ec5c66bf/pluggy-1.6.0-py3-none-any.whl", hash = "sha256:e920276dd6813095e9377c0bc5566d94c932c33b27a3e3945d8389c374dd4746", size = 20538, upload-time = "2025-05-15T12:30:06.134Z" }, +] + +[[package]] +name = "pygments" +version = "2.20.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/c3/b2/bc9c9196916376152d655522fdcebac55e66de6603a76a02bca1b6414f6c/pygments-2.20.0.tar.gz", hash = "sha256:6757cd03768053ff99f3039c1a36d6c0aa0b263438fcab17520b30a303a82b5f", size = 4955991, upload-time = "2026-03-29T13:29:33.898Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/f4/7e/a72dd26f3b0f4f2bf1dd8923c85f7ceb43172af56d63c7383eb62b332364/pygments-2.20.0-py3-none-any.whl", hash = "sha256:81a9e26dd42fd28a23a2d169d86d7ac03b46e2f8b59ed4698fb4785f946d0176", size = 1231151, upload-time = "2026-03-29T13:29:30.038Z" }, +] + +[[package]] +name = "pyright" +version = "1.1.411" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "nodeenv" }, + { name = "typing-extensions" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/7e/ab/265f7dc69d28113ebba19092e57b075f41543b2ed048429c5f56e2b88eac/pyright-1.1.411.tar.gz", hash = "sha256:d885a0551f2e763b089a02702174e7f4ba77548cddabc972ab86d1f7f1b0f998", size = 4112861, upload-time = "2026-06-25T02:14:06.37Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/0a/49/385be530a6a5b78d1cbcd5c2e38debc8959a2fc6bdb716f4e581002979fc/pyright-1.1.411-py3-none-any.whl", hash = "sha256:dc7c72a8e2700c55baa127554040e067041ea53ccfd50bf96308cc4291c7d5d9", size = 6181526, upload-time = "2026-06-25T02:14:04.691Z" }, +] + +[[package]] +name = "pytest" +version = "9.1.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "colorama", marker = "sys_platform == 'win32'" }, + { name = "iniconfig" }, + { name = "packaging" }, + { name = "pluggy" }, + { name = "pygments" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/e4/47/b9efed96c114afcfa3c9d3fe98a76a1d14c74a9e266d397cf6eb64be5e01/pytest-9.1.1.tar.gz", hash = "sha256:1088fbde8f2b49d95a549a195707afa7a76a3ce9bcadc26b6d71f0ffda5fe313", size = 1636369, upload-time = "2026-06-19T10:58:32.857Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/24/25/1de2678b631f5a49215c6c96fff41ba892b0a34df68d6d80292b1b48aa7f/pytest-9.1.1-py3-none-any.whl", hash = "sha256:37a86b45efb9a47a61a36449063e8e18d0cab3161329fc099eb21783169c4f0c", size = 386536, upload-time = "2026-06-19T10:58:31.347Z" }, +] + +[[package]] +name = "python-dotenv" +version = "1.2.2" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/82/ed/0301aeeac3e5353ef3d94b6ec08bbcabd04a72018415dcb29e588514bba8/python_dotenv-1.2.2.tar.gz", hash = "sha256:2c371a91fbd7ba082c2c1dc1f8bf89ca22564a087c2c287cd9b662adde799cf3", size = 50135, upload-time = "2026-03-01T16:00:26.196Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/0b/d7/1959b9648791274998a9c3526f6d0ec8fd2233e4d4acce81bbae76b44b2a/python_dotenv-1.2.2-py3-none-any.whl", hash = "sha256:1d8214789a24de455a8b8bd8ae6fe3c6b69a5e3d64aa8a8e5d68e694bbcb285a", size = 22101, upload-time = "2026-03-01T16:00:25.09Z" }, +] + +[[package]] +name = "pyyaml" +version = "6.0.3" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/05/8e/961c0007c59b8dd7729d542c61a4d537767a59645b82a0b521206e1e25c2/pyyaml-6.0.3.tar.gz", hash = "sha256:d76623373421df22fb4cf8817020cbb7ef15c725b9d5e45f17e189bfc384190f", size = 130960, upload-time = "2025-09-25T21:33:16.546Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/d1/11/0fd08f8192109f7169db964b5707a2f1e8b745d4e239b784a5a1dd80d1db/pyyaml-6.0.3-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:8da9669d359f02c0b91ccc01cac4a67f16afec0dac22c2ad09f46bee0697eba8", size = 181669, upload-time = "2025-09-25T21:32:23.673Z" }, + { url = "https://files.pythonhosted.org/packages/b1/16/95309993f1d3748cd644e02e38b75d50cbc0d9561d21f390a76242ce073f/pyyaml-6.0.3-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:2283a07e2c21a2aa78d9c4442724ec1eb15f5e42a723b99cb3d822d48f5f7ad1", size = 173252, upload-time = "2025-09-25T21:32:25.149Z" }, + { url = "https://files.pythonhosted.org/packages/50/31/b20f376d3f810b9b2371e72ef5adb33879b25edb7a6d072cb7ca0c486398/pyyaml-6.0.3-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ee2922902c45ae8ccada2c5b501ab86c36525b883eff4255313a253a3160861c", size = 767081, upload-time = "2025-09-25T21:32:26.575Z" }, + { url = "https://files.pythonhosted.org/packages/49/1e/a55ca81e949270d5d4432fbbd19dfea5321eda7c41a849d443dc92fd1ff7/pyyaml-6.0.3-cp313-cp313-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:a33284e20b78bd4a18c8c2282d549d10bc8408a2a7ff57653c0cf0b9be0afce5", size = 841159, upload-time = "2025-09-25T21:32:27.727Z" }, + { url = "https://files.pythonhosted.org/packages/74/27/e5b8f34d02d9995b80abcef563ea1f8b56d20134d8f4e5e81733b1feceb2/pyyaml-6.0.3-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:0f29edc409a6392443abf94b9cf89ce99889a1dd5376d94316ae5145dfedd5d6", size = 801626, upload-time = "2025-09-25T21:32:28.878Z" }, + { url = "https://files.pythonhosted.org/packages/f9/11/ba845c23988798f40e52ba45f34849aa8a1f2d4af4b798588010792ebad6/pyyaml-6.0.3-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:f7057c9a337546edc7973c0d3ba84ddcdf0daa14533c2065749c9075001090e6", size = 753613, upload-time = "2025-09-25T21:32:30.178Z" }, + { url = "https://files.pythonhosted.org/packages/3d/e0/7966e1a7bfc0a45bf0a7fb6b98ea03fc9b8d84fa7f2229e9659680b69ee3/pyyaml-6.0.3-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:eda16858a3cab07b80edaf74336ece1f986ba330fdb8ee0d6c0d68fe82bc96be", size = 794115, upload-time = "2025-09-25T21:32:31.353Z" }, + { url = "https://files.pythonhosted.org/packages/de/94/980b50a6531b3019e45ddeada0626d45fa85cbe22300844a7983285bed3b/pyyaml-6.0.3-cp313-cp313-win32.whl", hash = "sha256:d0eae10f8159e8fdad514efdc92d74fd8d682c933a6dd088030f3834bc8e6b26", size = 137427, upload-time = "2025-09-25T21:32:32.58Z" }, + { url = "https://files.pythonhosted.org/packages/97/c9/39d5b874e8b28845e4ec2202b5da735d0199dbe5b8fb85f91398814a9a46/pyyaml-6.0.3-cp313-cp313-win_amd64.whl", hash = "sha256:79005a0d97d5ddabfeeea4cf676af11e647e41d81c9a7722a193022accdb6b7c", size = 154090, upload-time = "2025-09-25T21:32:33.659Z" }, + { url = "https://files.pythonhosted.org/packages/73/e8/2bdf3ca2090f68bb3d75b44da7bbc71843b19c9f2b9cb9b0f4ab7a5a4329/pyyaml-6.0.3-cp313-cp313-win_arm64.whl", hash = "sha256:5498cd1645aa724a7c71c8f378eb29ebe23da2fc0d7a08071d89469bf1d2defb", size = 140246, upload-time = "2025-09-25T21:32:34.663Z" }, + { url = "https://files.pythonhosted.org/packages/9d/8c/f4bd7f6465179953d3ac9bc44ac1a8a3e6122cf8ada906b4f96c60172d43/pyyaml-6.0.3-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:8d1fab6bb153a416f9aeb4b8763bc0f22a5586065f86f7664fc23339fc1c1fac", size = 181814, upload-time = "2025-09-25T21:32:35.712Z" }, + { url = "https://files.pythonhosted.org/packages/bd/9c/4d95bb87eb2063d20db7b60faa3840c1b18025517ae857371c4dd55a6b3a/pyyaml-6.0.3-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:34d5fcd24b8445fadc33f9cf348c1047101756fd760b4dacb5c3e99755703310", size = 173809, upload-time = "2025-09-25T21:32:36.789Z" }, + { url = "https://files.pythonhosted.org/packages/92/b5/47e807c2623074914e29dabd16cbbdd4bf5e9b2db9f8090fa64411fc5382/pyyaml-6.0.3-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:501a031947e3a9025ed4405a168e6ef5ae3126c59f90ce0cd6f2bfc477be31b7", size = 766454, upload-time = "2025-09-25T21:32:37.966Z" }, + { url = "https://files.pythonhosted.org/packages/02/9e/e5e9b168be58564121efb3de6859c452fccde0ab093d8438905899a3a483/pyyaml-6.0.3-cp314-cp314-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:b3bc83488de33889877a0f2543ade9f70c67d66d9ebb4ac959502e12de895788", size = 836355, upload-time = "2025-09-25T21:32:39.178Z" }, + { url = "https://files.pythonhosted.org/packages/88/f9/16491d7ed2a919954993e48aa941b200f38040928474c9e85ea9e64222c3/pyyaml-6.0.3-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:c458b6d084f9b935061bc36216e8a69a7e293a2f1e68bf956dcd9e6cbcd143f5", size = 794175, upload-time = "2025-09-25T21:32:40.865Z" }, + { url = "https://files.pythonhosted.org/packages/dd/3f/5989debef34dc6397317802b527dbbafb2b4760878a53d4166579111411e/pyyaml-6.0.3-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:7c6610def4f163542a622a73fb39f534f8c101d690126992300bf3207eab9764", size = 755228, upload-time = "2025-09-25T21:32:42.084Z" }, + { url = "https://files.pythonhosted.org/packages/d7/ce/af88a49043cd2e265be63d083fc75b27b6ed062f5f9fd6cdc223ad62f03e/pyyaml-6.0.3-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:5190d403f121660ce8d1d2c1bb2ef1bd05b5f68533fc5c2ea899bd15f4399b35", size = 789194, upload-time = "2025-09-25T21:32:43.362Z" }, + { url = "https://files.pythonhosted.org/packages/23/20/bb6982b26a40bb43951265ba29d4c246ef0ff59c9fdcdf0ed04e0687de4d/pyyaml-6.0.3-cp314-cp314-win_amd64.whl", hash = "sha256:4a2e8cebe2ff6ab7d1050ecd59c25d4c8bd7e6f400f5f82b96557ac0abafd0ac", size = 156429, upload-time = "2025-09-25T21:32:57.844Z" }, + { url = "https://files.pythonhosted.org/packages/f4/f4/a4541072bb9422c8a883ab55255f918fa378ecf083f5b85e87fc2b4eda1b/pyyaml-6.0.3-cp314-cp314-win_arm64.whl", hash = "sha256:93dda82c9c22deb0a405ea4dc5f2d0cda384168e466364dec6255b293923b2f3", size = 143912, upload-time = "2025-09-25T21:32:59.247Z" }, + { url = "https://files.pythonhosted.org/packages/7c/f9/07dd09ae774e4616edf6cda684ee78f97777bdd15847253637a6f052a62f/pyyaml-6.0.3-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:02893d100e99e03eda1c8fd5c441d8c60103fd175728e23e431db1b589cf5ab3", size = 189108, upload-time = "2025-09-25T21:32:44.377Z" }, + { url = "https://files.pythonhosted.org/packages/4e/78/8d08c9fb7ce09ad8c38ad533c1191cf27f7ae1effe5bb9400a46d9437fcf/pyyaml-6.0.3-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:c1ff362665ae507275af2853520967820d9124984e0f7466736aea23d8611fba", size = 183641, upload-time = "2025-09-25T21:32:45.407Z" }, + { url = "https://files.pythonhosted.org/packages/7b/5b/3babb19104a46945cf816d047db2788bcaf8c94527a805610b0289a01c6b/pyyaml-6.0.3-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:6adc77889b628398debc7b65c073bcb99c4a0237b248cacaf3fe8a557563ef6c", size = 831901, upload-time = "2025-09-25T21:32:48.83Z" }, + { url = "https://files.pythonhosted.org/packages/8b/cc/dff0684d8dc44da4d22a13f35f073d558c268780ce3c6ba1b87055bb0b87/pyyaml-6.0.3-cp314-cp314t-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:a80cb027f6b349846a3bf6d73b5e95e782175e52f22108cfa17876aaeff93702", size = 861132, upload-time = "2025-09-25T21:32:50.149Z" }, + { url = "https://files.pythonhosted.org/packages/b1/5e/f77dc6b9036943e285ba76b49e118d9ea929885becb0a29ba8a7c75e29fe/pyyaml-6.0.3-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:00c4bdeba853cc34e7dd471f16b4114f4162dc03e6b7afcc2128711f0eca823c", size = 839261, upload-time = "2025-09-25T21:32:51.808Z" }, + { url = "https://files.pythonhosted.org/packages/ce/88/a9db1376aa2a228197c58b37302f284b5617f56a5d959fd1763fb1675ce6/pyyaml-6.0.3-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:66e1674c3ef6f541c35191caae2d429b967b99e02040f5ba928632d9a7f0f065", size = 805272, upload-time = "2025-09-25T21:32:52.941Z" }, + { url = "https://files.pythonhosted.org/packages/da/92/1446574745d74df0c92e6aa4a7b0b3130706a4142b2d1a5869f2eaa423c6/pyyaml-6.0.3-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:16249ee61e95f858e83976573de0f5b2893b3677ba71c9dd36b9cf8be9ac6d65", size = 829923, upload-time = "2025-09-25T21:32:54.537Z" }, + { url = "https://files.pythonhosted.org/packages/f0/7a/1c7270340330e575b92f397352af856a8c06f230aa3e76f86b39d01b416a/pyyaml-6.0.3-cp314-cp314t-win_amd64.whl", hash = "sha256:4ad1906908f2f5ae4e5a8ddfce73c320c2a1429ec52eafd27138b7f1cbe341c9", size = 174062, upload-time = "2025-09-25T21:32:55.767Z" }, + { url = "https://files.pythonhosted.org/packages/f1/12/de94a39c2ef588c7e6455cfbe7343d3b2dc9d6b6b2f40c4c6565744c873d/pyyaml-6.0.3-cp314-cp314t-win_arm64.whl", hash = "sha256:ebc55a14a21cb14062aa4162f906cd962b28e2e9ea38f9b4391244cd8de4ae0b", size = 149341, upload-time = "2025-09-25T21:32:56.828Z" }, +] + +[[package]] +name = "requests" +version = "2.34.2" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "certifi" }, + { name = "charset-normalizer" }, + { name = "idna" }, + { name = "urllib3" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/ac/c3/e2a2b89f2d3e2179abd6d00ebd70bff6273f37fb3e0cc209f48b39d00cbf/requests-2.34.2.tar.gz", hash = "sha256:f288924cae4e29463698d6d60bc6a4da69c89185ad1e0bcc4104f584e960b9ed", size = 142856, upload-time = "2026-05-14T19:25:27.735Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/a0/f4/c67b0b3f1b9245e8d266f0f112c500d50e5b4e83cb6f3b71b6528104182a/requests-2.34.2-py3-none-any.whl", hash = "sha256:2a0d60c172f83ac6ab31e4554906c0f3b3588d37b5cb939b1c061f4907e278e0", size = 73075, upload-time = "2026-05-14T19:25:26.443Z" }, +] + +[[package]] +name = "ruff" +version = "0.16.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/70/25/7113f6d5498888c5fb7db34081cba7d5971c4cb1bfb26819966eee68f003/ruff-0.16.1.tar.gz", hash = "sha256:fedad7c801dabd3fb9741d76aca39246e6ddd9ca446a015875207bf19f1e6bc7", size = 4877500, upload-time = "2026-07-30T19:37:01.379Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/1b/bd/694da69368e0973de65df2ddc73ab18d43c469d5963d9b150911de6bc513/ruff-0.16.1-py3-none-linux_armv6l.whl", hash = "sha256:58edb313b88f0c5460a26adf5f39a37a3be789494a15e3e411e35fa78b89f9a0", size = 10839126, upload-time = "2026-07-30T19:36:13.697Z" }, + { url = "https://files.pythonhosted.org/packages/3f/f0/b626e5d5bd0dd9576263658ef12885e2288afd1029a48e26ffed65ec1ac1/ruff-0.16.1-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:fde5a99e2f97479af66edd6622c6d5a2a7592c77cf4153d9e4428f5eeb55b60c", size = 11070253, upload-time = "2026-07-30T19:36:17.14Z" }, + { url = "https://files.pythonhosted.org/packages/83/63/f40acfb6b35b88623e71684942b552c3edd96035f5d98f313815f7b277de/ruff-0.16.1-py3-none-macosx_11_0_arm64.whl", hash = "sha256:e0d4c20532fca4f7fa609369161d968dd28f65d83dabbd61d8e9c7edbf7001f6", size = 10561425, upload-time = "2026-07-30T19:36:20.04Z" }, + { url = "https://files.pythonhosted.org/packages/aa/dd/14ec0e9c2b4d315547dd38765004b4863e354e1b52cb308272215d9f6f6d/ruff-0.16.1-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:30affbcedf59ad5703d9c91f82266e02b47739f797e1a7b6e158e5526a6dae38", size = 10948879, upload-time = "2026-07-30T19:36:22.476Z" }, + { url = "https://files.pythonhosted.org/packages/33/e9/9d870cbae575030fdef595f04b4b97573c525b5497cce4f4498cf2f85446/ruff-0.16.1-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:24e9c631573cbca9d20f1283f8f479b2afa4a8503504822bd71a293889f16743", size = 10643691, upload-time = "2026-07-30T19:36:24.914Z" }, + { url = "https://files.pythonhosted.org/packages/c4/09/12743d544e2173f53ecd27217c65f90d2bc0f8424a66a60339e56bbc0457/ruff-0.16.1-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b41bdd48fb420987a9b5212e4957c26ad4abce401fa9ea9d4d85843727945f4f", size = 11435354, upload-time = "2026-07-30T19:36:28.447Z" }, + { url = "https://files.pythonhosted.org/packages/7f/89/a1652b2daee52083c9554a6333b678a8b01d0400f976827bb87857f9449a/ruff-0.16.1-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b0d1e1393b7648079e13669de1c1f4fde06d4583e84d8fd5c1551e0a77a2aa75", size = 12259033, upload-time = "2026-07-30T19:36:31.326Z" }, + { url = "https://files.pythonhosted.org/packages/16/96/ecdcb8c54ee7b123b487f807eb014e6e019155a0b81dfb669acd52f28ce3/ruff-0.16.1-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:07bf434b1c95f4e093be4532068ef4fcf00924eb2ade8796075980902d6fd54a", size = 11667981, upload-time = "2026-07-30T19:36:34.394Z" }, + { url = "https://files.pythonhosted.org/packages/cd/90/c52e12e0d862e9572f2a33aa227409143520abe53111e9a6babbac7b4af8/ruff-0.16.1-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:39897739f112253ee4fdd2e8aa9a4f9ded99fb2be367d5f31dfa4ded6025584c", size = 11468183, upload-time = "2026-07-30T19:36:37.339Z" }, + { url = "https://files.pythonhosted.org/packages/2c/6b/4ffb7ad1d83eb16cf8cbb3c8815d3f11c88460fd162d4b372a2059be1c2a/ruff-0.16.1-py3-none-manylinux_2_31_riscv64.whl", hash = "sha256:82ae3c0c0d74daf17b968a10b7b3bb3ef297ab7de0c1f749646b25e690ccb150", size = 11470071, upload-time = "2026-07-30T19:36:39.91Z" }, + { url = "https://files.pythonhosted.org/packages/9c/72/32ae7db4c0b5e32ab611787caa19d1546800676d79f7483b7100a3561bf4/ruff-0.16.1-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:4d5f2ed10f8242d83fc08d521301089364e3375375705356f20c0e31606ef3ef", size = 10919503, upload-time = "2026-07-30T19:36:42.65Z" }, + { url = "https://files.pythonhosted.org/packages/f7/ca/3d901ba6ad6fc38da39c3448fc6c59ac945679293a17c3ceb6d6c1cba13e/ruff-0.16.1-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:a4665b309891f83f3e3c25447935f1213e9abbd4b5640af7a1f2def9f8d413c1", size = 10649861, upload-time = "2026-07-30T19:36:45.18Z" }, + { url = "https://files.pythonhosted.org/packages/92/79/894ef1ced26552d5f8c9cf6d85b0687840e1128c55aeab7b9c2d54a0d880/ruff-0.16.1-py3-none-musllinux_1_2_i686.whl", hash = "sha256:26e9ca5c9bc3971f20d3cf18a957f52ffd6a5f6564ff15c4912a144dcac22494", size = 11148137, upload-time = "2026-07-30T19:36:47.936Z" }, + { url = "https://files.pythonhosted.org/packages/2d/69/3609a09fa1cb46cc28b762363e440a354204e5dff01bd0c8d7437874d6b9/ruff-0.16.1-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:67e1e1e3fa4f0c82f0e36d4cd61e661f6e7a6196cb1aa92fe0828fa7b8f257cd", size = 11559211, upload-time = "2026-07-30T19:36:50.448Z" }, + { url = "https://files.pythonhosted.org/packages/fc/8a/fb22af2fd78a736e241fabf67e30ce1799a64244026377a49e133af90762/ruff-0.16.1-py3-none-win32.whl", hash = "sha256:d31765e131295b8445caf301e3e8a85b34d1b9b211b4109b7ba457888b051806", size = 10838258, upload-time = "2026-07-30T19:36:53.298Z" }, + { url = "https://files.pythonhosted.org/packages/d4/35/e57fd9fb5d423961df087a00b12d42c0a830288dc2f3b45ecca299158b4f/ruff-0.16.1-py3-none-win_amd64.whl", hash = "sha256:09b05e8b90c2cb06ad63464350e7a45e8e44a2dfe52072ebfba6666ca8d3f596", size = 11961111, upload-time = "2026-07-30T19:36:56.107Z" }, + { url = "https://files.pythonhosted.org/packages/cb/46/240ea004bf6dc4feb40e9832f2205a476a47dd5b8a3f8211a5fc5f95e20e/ruff-0.16.1-py3-none-win_arm64.whl", hash = "sha256:dbaadaac38c70239f056d306b7476f246b0bf000fa6b3876402acbf5b227eaf8", size = 11309414, upload-time = "2026-07-30T19:36:58.79Z" }, +] + +[[package]] +name = "typing-extensions" +version = "4.16.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/f6/cc/6253133b5bb138fc3306cebfbda2c520f545d36b5be2c7255cc528bb45d6/typing_extensions-4.16.0.tar.gz", hash = "sha256:dc983d19a509c94dba722ee6abd33940f7c05a89e243c47e907eb4db6f1a43e5", size = 113555, upload-time = "2026-07-02T08:40:05.92Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/49/d3/b8441a820a491ddfc024b0b0cf0393375b75ea13866d9c66727e54c2fc80/typing_extensions-4.16.0-py3-none-any.whl", hash = "sha256:481caa481374e813c1b176ada14e97f1f67a4539ce9cfeb3f350d78d6370c2e8", size = 45571, upload-time = "2026-07-02T08:40:04.659Z" }, +] + +[[package]] +name = "urllib3" +version = "2.7.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/53/0c/06f8b233b8fd13b9e5ee11424ef85419ba0d8ba0b3138bf360be2ff56953/urllib3-2.7.0.tar.gz", hash = "sha256:231e0ec3b63ceb14667c67be60f2f2c40a518cb38b03af60abc813da26505f4c", size = 433602, upload-time = "2026-05-07T16:13:18.596Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/7f/3e/5db95bcf282c52709639744ca2a8b149baccf648e39c8cc87553df9eae0c/urllib3-2.7.0-py3-none-any.whl", hash = "sha256:9fb4c81ebbb1ce9531cce37674bbc6f1360472bc18ca9a553ede278ef7276897", size = 131087, upload-time = "2026-05-07T16:13:17.151Z" }, +]