openapi: 3.0.0
servers:
  - url: //192.168.2.1/
    description: SPR API server
info:
  description: >
    # Introduction

    The API service exists for communication between service containers and to
    support

    external requests from the web front end or CLI tools.


    The internal APIs run over unix sockets and rely on filesystem namespaces
    for authentication.


    Currently there are four internal APIs:

    - Support for the [wifid service accepting stations](#tag/unix_wifid)

    - Support for dynamic networking configuration with [DHCP](#tag/unix_dhcpd)

    - [Wireguard](#tag/unix_wireguard)

    - DHCP [Tiny Subnets](#tag/tinysubnets_plugin)


    The external API runs over port `:80` or can optionally be configured to run
    over SSL on port `:443`.


    [ ⇨ View the code](https://github.com/spr-networks/super/tree/main/api)


    # Authentication


    ### Configuration

    On the device, the following files contain credentials for access.

    - `config/auth/auth_users.json` is a JSON file with a dictionary for
    username, password pairs

    - `configs/auth/auth_tokens.json` is a JSON file with a list of
    authentication tokens

    - `configs/auth/otp_settings.json` is a JSON file with OTP user
    configuration.


    ### OTP Notes

    - Certain privileged operations require a valid OTP JWT. The OTP code is
    there to provide additional security hardening.

    - A user can also require OTP codes for all operations.

    - The default period is 1 hour for the JWT and can be customized


    <SecurityDefinitions />


    # API Plugins

    API extensions operate through a reverse proxy into a unix socket. They
    allow for hosting

    extensions to the API on the same web origin while running in a different
    process or container.


    Extensions are configured in ```configs/base/api.json```


    This example shows the mapping of unix://state/dns/dns_block_plugin to 
    http://APIHOST/plugins/dns/block/


    ```json

    {
      "Plugins" : [{
        "Name": "dns block extension",
        "URI": "dns/block",
        "UnixPath": "/state/dns/dns_block_plugin"
      }]
    }

    ```


    See the API documentation for plugins [here](#tag/plugins)
  version: 1.1.13
  title: Secure Programmable Router API
  contact:
    name: SPR contact
    url: https://www.supernetworks.org
  x-logo:
    url: https://www.supernetworks.org/pages/img/logo.png
    altText: SPR logo
tags:
  - name: device
    x-displayName: Devices
    description: Manage Device Wifi Authentication and Network Access
  - name: group
    x-displayName: Groups
    description: Groups are used to manage device connectivity and firewall rules
  - name: policy
    x-displayName: Policies
    description: Policies manage device connectivity and firewall rules
  - name: psk
    x-displayName: PSK
    description: Manage Device Passphrases
  - name: traffic
    x-displayName: Network Traffic
    description: Device traffic information
  - name: network
    x-displayName: Network Information
    description: Operations about Network, NFTable, IP Address information
  - name: firewall
    x-displayName: Firewall
    description: Operations for forwarding rules and blocking
  - name: hostapd
    x-displayName: Hostapd
    description: Operations about hostapd
  - name: plugins
    x-displayName: Plugins
    description: Operations about plugins
  - name: dnsblock
    x-displayName: DNS Block
    description: CoreDNS Block plugin
  - name: dnslog
    x-displayName: DNS Log
    description: CoreDNS Log plugin
  - name: wireguard
    x-displayName: Wireguard
    description: Wireguard plugin
  - name: lookup
    x-displayName: Lookup
    description: Lookup plugin for ASN & OUI information
  - name: dyndns
    x-displayName: Dynamic DNS
    description: Dynamic DNS Record Updater
  - name: tokens
    x-displayName: Tokens
    description: Api Tokens
  - name: alerts
    x-displayName: Alerts
    description: Alerts
  - name: psk_model
    x-displayName: PSK
    description: >
      <SchemaDefinition schemaRef="#/components/schemas/PSKEntry"
      exampleRef="#/components/examples/PSKEntry" />
  - name: device_model
    x-displayName: Device
    description: >
      <SchemaDefinition schemaRef="#/components/schemas/DeviceEntry"
      exampleRef="#/components/examples/DeviceEntry" />
  - name: group_model
    x-displayName: Group
    description: >
      <SchemaDefinition schemaRef="#/components/schemas/GroupEntry"
      exampleRef="#/components/examples/GroupEntry" />
  - name: plugin_model
    x-displayName: Plugin
    description: >
      <SchemaDefinition schemaRef="#/components/schemas/PluginEntry"
      exampleRef="#/components/examples/PluginEntry" />
  - name: unix_wifid
    x-displayName: Wifid
    description: Listens for requests on ```unix:///state/wifi/apisock```
  - name: unix_dhcpd
    x-displayName: dhcpd
    description: Listens for requests on ```unix:///state/dhcp/apisock```
  - name: unix_wireguard
    x-displayName: wireguard
    description: Listens for requests on ```unix:///state/plugins/wireguard/apisock```
  - name: unix_superd
    x-displayName: Superd
    description: Listens for requests on ```unix:///state/plugins/superd/socket```
  - name: tinysubnets
    x-displayName: tinysubnets
    description: Listens for requests on ```unix:///state/dhcp/tinysubnets_plugin```
  - name: general
    x-displayName: Misc
    description: Misc information
  - name: releases
    x-displayName: Releases
    description: Manage SPR Release Channel and Version
  - name: plus
    x-displayName: PLUS
    description: PLUS features
  - name: uplink
    x-displayName: Uplink
    description: Configure outbound interfaces
  - name: link
    x-displayName: Link
    description: Configure LAN interfaces
  - name: otp
    x-displayName: OTP
    description: One Time Password Authentication
  - name: mesh-node
    x-displayName: Mesh Node APIs
    description: >-
      The mesh extension lets users grow the network with multiple SPR Access
      Points
  - name: mesh-common
    x-displayName: Mesh Common APIs
    description: >-
      The mesh extension lets users grow the network with multiple SPR Access
      Points
  - name: mesh-parent
    x-displayName: Mesh Main Router APIs
    description: >-
      The mesh extension lets users grow the network with multiple SPR Access
      Points
  - name: wan
    x-displayName: Internet Health
    description: WAN uplink health monitoring, outages, speed tests and failover
  - name: parentalcontrols
    x-displayName: Parental Controls
    description: Personas, schedules and daily time limits
  - name: themes
    x-displayName: Themes
    description: Custom UI themes and appearance
x-tagGroups:
  - name: Web API
    tags:
      - device
      - group
      - network
      - firewall
      - traffic
      - psk
      - hostapd
      - uplink
      - link
      - general
      - releases
      - plugins
      - tokens
      - alerts
      - otp
      - plus
      - wan
      - parentalcontrols
      - themes
  - name: Standard Plugin APIs
    tags:
      - dnsblock
      - dnslog
      - wireguard
      - lookup
      - dyndns
  - name: Mesh Extension APIs
    tags:
      - mesh-common
      - mesh-parent
      - mesh-node
  - name: Internal Unix Socket APIs
    tags:
      - unix_wifid
      - unix_dhcpd
      - unix_wireguard
      - unix_superd
      - tinysubnets
  - name: Object Types
    tags:
      - device_model
      - group_model
      - psk_model
      - plugin_model
paths:
  /otp_register:
    put:
      tags:
        - otp
      summary: Configure OTP User
      description: >-
        Updates an OTP user with the given details. If already registered, a
        valid code is required
      operationId: updateOtpUser
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/OTPUserRequest'
      responses:
        '200':
          description: User updated successfully
      security:
        - basicAuth: []
        - bearerAuth: []
      x-codeSamples:
        - lang: cURL
          label: CLI
          source: >
            curl -X PUT -H "Authorization: Bearer [token]" -H "X-JWT-Token:
            [jwt-token]" \
              -d '{"Name": "name", "Code": "1234567", "UpdateAlwaysOn": false, "AlwaysOn": false}' \
              "http://192.168.2.1/otp_register"
    delete:
      tags:
        - otp
      summary: Delete OTP User
      description: Deletes an OTP user. Valid code required
      operationId: deleteOtpUser
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/OTPUserRequest'
      responses:
        '200':
          description: User deleted successfully
      security:
        - bearerAuth: []
        - basicAuth: []
      x-codeSamples:
        - lang: cURL
          label: CLI
          source: >
            curl -X DELETE -H "Authorization: Bearer [token]" -H "X-JWT-Token:
            [jwt-token]" \
              -d '{"Name": "name", "Code": "1234567"}' \
              "http://192.168.2.1/otp_register"
  /otp_validate:
    put:
      tags:
        - otp
      summary: Generate an OTP JWT
      description: >-
        Validates the provided OTP user details and generates the X-JWT-OTP
        token
      operationId: validateOtpUser
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/OTPUserRequest'
      responses:
        '200':
          description: User validation successful
          content:
            application/json:
              schema:
                type: string
      security:
        - bearerAuth: []
        - basicAuth: []
      x-codeSamples:
        - lang: cURL
          label: CLI
          source: >
            curl -X PUT -H "Authorization: Bearer [token]" -H "X-JWT-Token:
            [jwt-token]" \
              -d '{"Name": "name", "Code": "code"}' \
              "http://192.168.2.1/otp_validate"
  /otp_status:
    get:
      tags:
        - otp
      summary: Get OTP Status
      description: Retrieves the status of the OTP service.
      operationId: getOtpStatus
      responses:
        '200':
          description: OTP status retrieved successfully
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/OTPStatus'
      security:
        - basicAuth: []
        - bearerAuth: []
      x-codeSamples:
        - lang: cURL
          label: CLI
          source: >
            curl -H "Authorization: Bearer [token]" -H "X-JWT-Token:
            [jwt-token]" \
              "http://192.168.2.1/otp_status"
  /otp_jwt_test:
    put:
      tags:
        - otp
      summary: JWT OTP Test
      description: Endpoint to test OTP JWT validity.
      operationId: testJwt
      responses:
        '200':
          description: JWT OTP test successful
      security:
        - bearerAuth: []
          OTPAuth: []
        - basicAuth: []
          OTPAuth: []
      x-codeSamples:
        - lang: cURL
          label: CLI
          source: >
            curl -X PUT -H "Authorization: Bearer [token]" -H "X-JWT-Token:
            [jwt-token]" \
              "http://192.168.2.1/otp_jwt_test"
  /devices:
    get:
      tags:
        - device
      summary: Get Devices
      description: Returns a map of registered devices, indexed by MAC address
      operationId: getDevices
      responses:
        '200':
          description: successful operation
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/DeviceEntryMap'
      security:
        - basicAuth: []
        - bearerAuth: []
      x-codeSamples:
        - lang: cURL
          label: CLI
          source: |
            curl -u "admin:pass" \
              "http://192.168.2.1/devices"
    put:
      tags:
        - device
      summary: Sync Devices
      description: ''
      operationId: syncDevicesList
      responses:
        '200':
          description: Sync requested successfully
        '400':
          description: Invalid input
      requestBody:
        $ref: '#/components/requestBodies/DeviceSyncMap'
      security:
        - basicAuth: []
        - bearerAuth: []
      x-codeSamples:
        - lang: cURL
          label: CLI
          source: |
            curl -u "admin:pass" -X PUT \
              "http://192.168.2.1/devices" < devices.json
    delete:
      tags:
        - device
      summary: Delete Devices
      description: ''
      operationId: deleteDevices
      responses:
        '200':
          description: successful operation
          content:
            application/json:
              schema:
                type: object
                properties:
                  deleted:
                    type: array
                    description: Identities of devices that were deleted
                    items:
                      type: string
                    example:
                      - '11:22:33:44:55:66'
                  count:
                    type: integer
                    description: Number of devices deleted
                    example: 1
        '400':
          description: Invalid input
      requestBody:
        $ref: '#/components/requestBodies/DeviceIdentityList'
      security:
        - basicAuth: []
        - bearerAuth: []
      x-codeSamples:
        - lang: cURL
          label: CLI
          source: |
            curl -u "admin:pass" -X DELETE \
              "http://192.168.2.1/devices" < identities.json
  /device?identity={identity}:
    get:
      tags:
        - device
      summary: Get Device including PSK
      description: >-
        Get a Device specified by the MAC address in the identity parameter.
        Requires OTP Code
      operationId: getDevice
      parameters:
        - name: identity
          in: path
          description: MAC address
          required: true
          schema:
            type: string
            example: '11:22:33:44:55:61'
      responses:
        '200':
          description: successful operation
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/DeviceEntry'
        '404':
          description: Device not found
      security:
        - basicAuth: []
          OTPAuth: []
        - bearerAuth: []
          OTPAuth: []
      x-codeSamples:
        - lang: cURL
          label: CLI
          source: |
            curl -u "admin:pass" -X DELETE -H "X-JWT-OTP:..." \
              "http://192.168.2.1/device?identity=11:22:33:44:55:66"
    put:
      tags:
        - device
      summary: Update Device
      description: >-
        Update information specified by the MAC address in the identity
        parameter. All fields are optional. If a PSKEntry.PskType is set and a
        PSKEntry.Psk is not set, one will be generated and returned. To create a
        wildcard PSK for adding a new device, use the string "pending" for the
        identity.
      operationId: handleUpdateDevice
      parameters:
        - name: identity
          in: path
          description: MAC address
          required: true
          schema:
            type: string
            example: '11:22:33:44:55:61'
      requestBody:
        $ref: '#/components/requestBodies/DeviceEntry'
      responses:
        '200':
          description: successful operation
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/DeviceEntry'
        '404':
          description: Device not found
      security:
        - basicAuth: []
        - bearerAuth: []
      x-codeSamples:
        - lang: cURL
          label: CLI
          source: |
            curl -u "admin:pass" -X PUT \
              "http://192.168.2.1/device?identity=11:22:33:44:55:66" < device.json
    delete:
      tags:
        - device
      summary: Delete Device
      description: Delete a Device specified by the MAC address in the identity parameter
      operationId: deleteDevice
      parameters:
        - name: identity
          in: path
          description: MAC address
          required: true
          schema:
            type: string
            example: '11:22:33:44:55:61'
      responses:
        '200':
          description: successful operation
        '404':
          description: Device not found
      security:
        - basicAuth: []
        - bearerAuth: []
      x-codeSamples:
        - lang: cURL
          label: CLI
          source: |
            curl -u "admin:pass" -X DELETE \
              "http://192.168.2.1/device?identity=11:22:33:44:55:66"
  /groups:
    get:
      tags:
        - group
      summary: Get all Groups
      description: Return all available groups
      operationId: getGroups
      responses:
        '200':
          description: successful operation
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/GroupEntryArray'
      security:
        - basicAuth: []
        - bearerAuth: []
      x-codeSamples:
        - lang: cURL
          label: CLI
          source: |
            curl -u "admin:pass" \
              "http://192.168.2.1/groups"
    put:
      tags:
        - group
      summary: Add Group
      description: |
        If the group does not exist, it will be created.
        If it exists it will be updated. Fields are optional.
      operationId: updateGroups
      requestBody:
        $ref: '#/components/requestBodies/GroupEntry'
      responses:
        '200':
          description: successful operation
        '400':
          description: Invalid input
      security:
        - basicAuth: []
        - bearerAuth: []
      x-codeSamples:
        - lang: cURL
          label: CLI
          source: |
            curl -u "admin:pass" -X PUT  \
              "http://192.168.2.1/group" \
                 --data '{"Name": "vpn", "Disabled": false, "GroupTags": ["private"]}'
    delete:
      tags:
        - group
      summary: Delete Group
      description: ''
      operationId: deleteGroup
      responses:
        '200':
          description: successful operation
        '404':
          description: Invalid Group supplied
      requestBody:
        $ref: '#/components/requestBodies/GroupEntry'
      security:
        - basicAuth: []
        - bearerAuth: []
      x-codeSamples:
        - lang: cURL
          label: CLI
          source: |
            curl -u "admin:pass" -X DELETE  \
              "http://192.168.2.1/groups" \
                --data '{"Name": "vpn"}'
  /uplink/wifi:
    get:
      tags:
        - uplink
      summary: Get WPA Supplicant Configuration
      description: Retrieves the current WPA supplicant configuration.
      operationId: getWpaSupplicantConfig
      responses:
        '200':
          description: successful operation
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/WPASupplicantConfig'
        '404':
          description: not found
      security:
        - basicAuth: []
        - bearerAuth: []
    put:
      tags:
        - uplink
      summary: Update or Add WPA Supplicant Interface Configuration
      description: Updates an existing WPA interface configuration or adds a new one.
      operationId: updateWpaSupplicantConfig
      responses:
        '200':
          description: successful operation
        '400':
          description: malformed data
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/WPAIface'
      security:
        - basicAuth: []
        - bearerAuth: []
      x-codeSamples:
        - lang: cURL
          label: CLI
          source: |
            curl -u "admin:pass" -X PUT \
              "http://192.168.2.1/uplink/wifi" \
              --data '{
                        "Iface": "wlan0",
                        "Enabled": true,
                        "Networks": [
                          {
                            "Disabled": false,
                            "Password": "password123",
                            "SSID": "MySSID",
                            "KeyMgmt": "WPA-PSK",
                            "Priority": "1",
                            "BSSID": "00:11:22:33:44:55"
                          }
                        ]
                      }'
  /uplink/ppp:
    get:
      tags:
        - uplink
      summary: Get PPP Configuration
      description: Retrieves the current PPP configuration.
      operationId: getPPPConfig
      responses:
        '200':
          description: successful operation
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/PPPConfig'
        '404':
          description: not found
      security:
        - basicAuth: []
        - bearerAuth: []
    put:
      tags:
        - uplink
      summary: Update or Add PPP Interface Configuration
      description: Updates an existing PPP interface configuration or adds a new one.
      operationId: updatePPPConfig
      responses:
        '200':
          description: successful operation
        '400':
          description: malformed data
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/PPPIface'
      security:
        - basicAuth: []
        - bearerAuth: []
      x-codeSamples:
        - lang: cURL
          label: CLI
          source: |
            curl -u "admin:pass" -X PUT \
              "http://192.168.2.1/uplink/ppp" \
              --data '{
                        "Iface": "eth0",
                        "PPPIface": "ppp0",
                        "Enabled": true,
                        "Username": "user",
                        "Secret": "password",
                        "VLAN": "10",
                        "MTU": "1500"
                      }'
  /uplink/ip:
    put:
      tags:
        - uplink
      summary: Update Interface IP Configuration for an existing interface
      description: Updates the IP configuration of a network interface.
      operationId: updateLinkIpConfig
      responses:
        '200':
          description: successful operation
        '400':
          description: malformed data
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/InterfaceConfig'
      security:
        - basicAuth: []
        - bearerAuth: []
      x-codeSamples:
        - lang: cURL
          label: CLI
          source: |
            curl -u "admin:pass" -X PUT \
              "http://192.168.2.1/uplink/ip" \
              --data '{
                        "Name": "eth0",
                        "Type": "Downlink",
                        "Subtype": "VLAN-Trunk",
                        "Enabled": true,
                        "DisableDHCP": false,
                        "IP": "192.168.1.2",
                        "Router": "192.168.1.1",
                        "VLAN": "10"
                      }'
  /link/config:
    put:
      tags:
        - link
      summary: Update Link Configuration
      description: Updates the configuration of a LAN network interface.
      operationId: updateLinkConfig
      responses:
        '200':
          description: successful operation
        '400':
          description: malformed data
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/BasicInterfaceConfig'
      security:
        - basicAuth: []
        - bearerAuth: []
      x-codeSamples:
        - lang: cURL
          label: CLI
          source: |
            curl -u "admin:pass" -X PUT \
              "http://192.168.2.1/link/config" \
              --data '{
                        "Name": "eth0",
                        "Type": "static",
                        "Subtype": "default",
                        "Enabled": true
                      }'
  /link/vlan/{interface}/{state}:
    put:
      tags:
        - link
      summary: Update VLAN Trunk State on Interface
      description: Set an interface as a VLAN trunk, enabling or disabling it.
      operationId: updateLinkVlanTrunk
      parameters:
        - name: interface
          in: path
          required: true
          description: Name of the network interface.
          schema:
            type: string
        - name: state
          in: path
          required: true
          description: State of the VLAN trunk on the interface (enable or disable).
          schema:
            type: string
            enum:
              - enable
              - disable
      responses:
        '200':
          description: successful operation
        '400':
          description: malformed data
      security:
        - basicAuth: []
        - bearerAuth: []
      x-codeSamples:
        - lang: cURL
          label: CLI
          source: |
            # Example to enable VLAN trunk on eth0
            curl -u "admin:pass" -X PUT \
              "http://192.168.2.1/link/vlan/eth0/enable"
            # Example to disable VLAN trunk on eth0
            curl -u "admin:pass" -X PUT \
              "http://192.168.2.1/link/vlan/eth0/disable"
  /reloadPSKFiles:
    put:
      tags:
        - psk
      summary: Reload PSK files
      description: >-
        Tells Hostapd to reload PSK files. This will not boot off connected
        devices. This does not need to be called after adding or removing PSK
        entries.
      operationId: reloadPSKFiles
      responses:
        '200':
          description: successful operation
      security:
        - basicAuth: []
        - bearerAuth: []
      x-codeSamples:
        - lang: cURL
          label: CLI
          source: |
            curl -u "admin:pass" -X PUT  \
              "http://192.168.2.1/reloadPSKFiles"
  /pendingPSK:
    get:
      tags:
        - psk
      summary: Pending PSKs
      description: Checks if there is a pending PSK that has not been assigned to a MAC yet
      operationId: pendingPSK
      responses:
        '200':
          description: successful operation
          content:
            application/json:
              schema:
                type: boolean
      security:
        - basicAuth: []
        - bearerAuth: []
      x-codeSamples:
        - lang: cURL
          label: CLI
          source: |
            curl -u "admin:pass" \
              "http://192.168.2.1/pendingPSK"
  /ip/addr:
    get:
      tags:
        - network
      summary: IP Address Information
      description: Returns the output of `ip -j addr`
      operationId: ipAddr
      responses:
        '200':
          description: successful operation
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: '#/components/schemas/Interface'
      security:
        - basicAuth: []
        - bearerAuth: []
      x-codeSamples:
        - lang: cURL
          label: CLI
          source: |
            curl -u "admin:pass" \
              "http://192.168.2.1/ip/addr"
  /ip/link/{interface}/{state}:
    get:
      tags:
        - network
      summary: Set Link State
      description: Set ip link status `up` or `down`
      operationId: ipLink
      parameters:
        - name: interface
          in: path
          description: Interface name
          required: true
          schema:
            type: string
        - name: state
          in: path
          description: Set interface to up or down
          required: true
          schema:
            type: string
            pattern: /^(up|down)$/
      responses:
        '200':
          description: successful operation
      security:
        - basicAuth: []
        - bearerAuth: []
      x-codeSamples:
        - lang: cURL
          label: CLI
          source: |
            curl -u "admin:pass" \
              "http://192.168.2.1/ip/link/wlan0/up"
  /nfmap/{name}:
    get:
      tags:
        - network
      summary: NFTable Verdict Map
      description: >-
        Returns the output of `nft -j` for the verdict map specificed by the
        name parameter
      operationId: showNFMap
      parameters:
        - name: name
          in: path
          description: Name of the nfmap to fetch
          required: true
          schema:
            type: string
      responses:
        '200':
          description: successful operation
          content:
            application/json:
              schema:
                type: object
        '400':
          description: Invalid Map name supplied
      security:
        - basicAuth: []
        - bearerAuth: []
      x-codeSamples:
        - lang: cURL
          label: CLI
          source: |
            curl -u "admin:pass" \
              "http://192.168.2.1/nfmap/dns_access"
  /arp:
    get:
      tags:
        - network
      summary: ARP Table
      description: Returns the ARP table
      operationId: showARP
      responses:
        '200':
          description: successful operation
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: '#/components/schemas/ArpEntry'
      security:
        - basicAuth: []
        - bearerAuth: []
      x-codeSamples:
        - lang: cURL
          label: CLI
          source: |
            curl -u "admin:pass" \
              "http://192.168.2.1/arp"
  /iw/list:
    get:
      tags:
        - network
      summary: Wifi Interfaces
      description: Returns the output of `iw list` in json format
      operationId: iwList
      responses:
        '200':
          description: successful operation
          content:
            application/json:
              schema:
                type: array
                items:
                  type: object
      security:
        - basicAuth: []
        - bearerAuth: []
      x-codeSamples:
        - lang: cURL
          label: CLI
          source: |
            curl -u "admin:pass" \
              "http://192.168.2.1/iw/list"
  /iw/dev:
    get:
      tags:
        - network
      summary: Wifi Devices
      description: Returns the output of `iw dev` in json format
      operationId: iwDev
      responses:
        '200':
          description: successful operation
          content:
            application/json:
              schema:
                type: object
      security:
        - basicAuth: []
        - bearerAuth: []
      x-codeSamples:
        - lang: cURL
          label: CLI
          source: |
            curl -u "admin:pass" \
              "http://192.168.2.1/iw/dev"
  /iw/dev/{iface}/scan:
    get:
      tags:
        - network
      summary: Get Nearby Wifi Networks
      description: |
        Returns the output of `iw dev iface scan` in json format.

        *Note:* the specified interface needs to be in managed mode.
      operationId: iwScan
      parameters:
        - name: iface
          in: path
          description: interface
          required: true
          schema:
            type: string
            example: wlan0
      responses:
        '200':
          description: successful operation
          content:
            application/json:
              schema:
                type: array
                items:
                  type: object
                example:
                  - bssid: '11:11:11:11:11:11'
                    interface: wlan0
                    freq: 2412
                    ssid: sample_ssid1
                    authentication_suites: PSK
                    signal_dbm: -64
      security:
        - basicAuth: []
        - bearerAuth: []
      x-codeSamples:
        - lang: cURL
          label: CLI
          source: |
            curl -u "admin:pass" \
              "http://192.168.2.1/iw/dev/wlan0/scan"
  /firewall/config:
    get:
      tags:
        - firewall
      summary: Retrieve firewall config
      description: Returns the firewall API configuration
      operationId: firewallConfiguration
      responses:
        '200':
          description: successful operation
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/FirewallConfig'
      security:
        - basicAuth: []
        - bearerAuth: []
      x-codeSamples:
        - lang: cURL
          label: CLI
          source: |
            curl -u "admin:pass" \
              "http://192.168.2.1/firewall/config"
  /firewall/forward:
    put:
      tags:
        - firewall
      summary: Add a Forwarding Rule
      description: ''
      operationId: addFirewallForward
      responses:
        '200':
          description: successful operation
        '400':
          description: malformed data
      requestBody:
        $ref: '#/components/requestBodies/FirewallForward'
      security:
        - basicAuth: []
        - bearerAuth: []
      x-codeSamples:
        - lang: cURL
          label: CLI
          source: |
            curl -u "admin:pass" -X PUT  \
              "http://192.168.2.1/firewall/forward" \
              --data '{
                        "DstIP": "1.2.3.4",
                        "SrcIP": "0.0.0.0/24",
                        "SrcPort": "0-10",
                        "DstPort": "any",
                        "Protocol": "tcp"
                      }'
    delete:
      tags:
        - firewall
      summary: Delete a Forwarding Rule
      description: Delete forwarding rule with matching contents
      operationId: deleteFirewallForward
      responses:
        '200':
          description: successful operation
        '404':
          description: not found
      requestBody:
        $ref: '#/components/requestBodies/FirewallForward'
      security:
        - basicAuth: []
        - bearerAuth: []
      x-codeSamples:
        - lang: cURL
          label: CLI
          source: |
            curl -u "admin:pass" -X DELETE  \
              "http://192.168.2.1/firewall/forward" \
              --data '{
                        "DstIP": "1.2.3.4",
                        "SrcIP": "0.0.0.0/24",
                        "SrcPort": "0-10",
                        "DstPort": "any",
                        "Protocol": "tcp"
                      }'
  /firewall/block:
    put:
      tags:
        - firewall
      summary: Add IP Block
      description: Add IP Block Rule
      operationId: addFirewallBlock
      responses:
        '200':
          description: successful operation
        '400':
          description: malformed data
      requestBody:
        $ref: '#/components/requestBodies/FirewallBlock'
      security:
        - basicAuth: []
        - bearerAuth: []
      x-codeSamples:
        - lang: cURL
          label: CLI
          source: |
            curl -u "admin:pass" -X PUT  \
              "http://192.168.2.1/firewall/block" \
              --data '{
                        "DstIP": "1.2.3.4",
                        "SrcIP": "0.0.0.0/24",
                        "Protocol": "tcp"
                      }'
    delete:
      tags:
        - firewall
      summary: Delete IP Block
      description: Delete blocking rule with matching contents
      operationId: deleteFirewallBlock
      responses:
        '200':
          description: successful operation
        '404':
          description: not found
      requestBody:
        $ref: '#/components/requestBodies/FirewallBlock'
      security:
        - basicAuth: []
        - bearerAuth: []
      x-codeSamples:
        - lang: cURL
          label: CLI
          source: |
            curl -u "admin:pass" -X DELETE  \
              "http://192.168.2.1/firewall/block" \
              --data '{
                        "DstIP": "1.2.3.4",
                        "SrcIP": "0.0.0.0/24",
                        "Protocol": "tcp"
                      }'
  /firewall/block_forward:
    put:
      tags:
        - firewall
      summary: Add Forward Block
      description: Add Forward Block Rule, to block outbound traffic
      operationId: addFirewallBlockForward
      responses:
        '200':
          description: successful operation
        '400':
          description: malformed data
      requestBody:
        $ref: '#/components/requestBodies/FirewallBlockForward'
      security:
        - basicAuth: []
        - bearerAuth: []
      x-codeSamples:
        - lang: cURL
          label: CLI
          source: |
            curl -u "admin:pass" -X PUT  \
              "http://192.168.2.1/firewall/block_forward" \
              --data '{
                        "DstIP": "1.2.3.4",
                        "SrcIP": "0.0.0.0/24",
                        "Protocol": "tcp"
                        "DstPort: "0-65535"
                      }'
    delete:
      tags:
        - firewall
      summary: Delete Forward Block
      description: Delete blocking rule with matching contents
      operationId: deleteFirewallBlockForward
      responses:
        '200':
          description: successful operation
        '404':
          description: not found
      requestBody:
        $ref: '#/components/requestBodies/FirewallBlockForward'
      security:
        - basicAuth: []
        - bearerAuth: []
      x-codeSamples:
        - lang: cURL
          label: CLI
          source: |
            curl -u "admin:pass" -X DELETE  \
              "http://192.168.2.1/firewall/block_forward" \
              --data '{
                        "DstIP": "1.2.3.4",
                        "SrcIP": "0.0.0.0/24",
                        "Protocol": "tcp"
                        "DstPort: "0-65535"
                      }'
  /firewall/service_port:
    put:
      tags:
        - firewall
      summary: Allow Service Port Access
      description: >-
        Service Ports are ports that run on the SPR router itself. They can be
        for LAN clients only or for upstream also
      operationId: addFirewallServicePort
      responses:
        '200':
          description: successful operation
        '400':
          description: malformed data
      requestBody:
        $ref: '#/components/requestBodies/ServicePort'
      security:
        - basicAuth: []
        - bearerAuth: []
      x-codeSamples:
        - lang: cURL
          label: CLI
          source: |
            curl -u "admin:pass" -X PUT  \
              "http://192.168.2.1/firewall/service_port" \
              --data '{
                        "UpstreamEnabled": false,
                        "Protocol": "tcp"
                        "Port: "22"
                      }'
    delete:
      tags:
        - firewall
      summary: Delete Service Port Access
      description: Delete service port from allow list
      operationId: deleteFirewallServicePort
      responses:
        '200':
          description: successful operation
        '404':
          description: not found
      requestBody:
        $ref: '#/components/requestBodies/ServicePort'
      security:
        - basicAuth: []
        - bearerAuth: []
      x-codeSamples:
        - lang: cURL
          label: CLI
          source: |
            curl -u "admin:pass" -X DELETE  \
              "http://192.168.2.1/firewall/service_port" \
              --data '{
                        "UpstreamEnabled": false,
                        "Protocol": "tcp"
                        "Port: "22"
                      }'
  /firewall/endpoint:
    put:
      tags:
        - firewall
      summary: Add Firewall Endpoint
      description: Endpoints store common destinations for the UI to populate fields with
      operationId: addFirewallEndpoint
      responses:
        '200':
          description: successful operation
        '400':
          description: malformed data
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/Endpoint'
      security:
        - basicAuth: []
        - bearerAuth: []
      x-codeSamples:
        - lang: cURL
          label: CLI
          source: |
            curl -u "admin:pass" -X PUT \
              "http://192.168.2.1/firewall/endpoint" \
              --data '{
                        "RuleName": "exampleRule",
                        "Disabled": false,
                        "Protocol": "tcp",
                        "IP": "192.168.2.100",
                        "Domain": "example.com",
                        "Port": "8080",
                        "Tags": ["tag1", "tag2"]
                      }'
    delete:
      tags:
        - firewall
      summary: Delete Firewall Endpoint
      description: Delete an existing endpoint from the firewall configuration.
      operationId: deleteFirewallEndpoint
      responses:
        '200':
          description: successful operation
        '404':
          description: not found
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/Endpoint'
      security:
        - basicAuth: []
        - bearerAuth: []
      x-codeSamples:
        - lang: cURL
          label: CLI
          source: |
            curl -u "admin:pass" -X DELETE \
              "http://192.168.2.1/firewall/endpoint" \
              --data '{
                        "RuleName": "exampleRule",
                        "Disabled": false,
                        "Protocol": "tcp",
                        "IP": "192.168.2.100",
                        "Domain": "example.com",
                        "Port": "8080",
                        "Tags": ["tag1", "tag2"]
                      }'
  /firewall/multicast:
    put:
      tags:
        - firewall
      summary: Enable Multicast Port (UDP over a multicast IP/ethernet address)
      description: Configures a multicast port in the firewall.
      operationId: enableFirewallMulticastPort
      responses:
        '200':
          description: successful operation
        '400':
          description: malformed data
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/MulticastPort'
      security:
        - basicAuth: []
        - bearerAuth: []
      x-codeSamples:
        - lang: cURL
          label: CLI
          source: |
            curl -u "admin:pass" -X PUT \
              "http://192.168.2.1/firewall/multicast" \
              --data '{
                        "Port": "1234",
                        "Upstream": true
                      }'
    delete:
      tags:
        - firewall
      summary: Disable Multicast Port
      description: Removes a multicast port configuration from the firewall.
      operationId: disableFirewallMulticastPort
      responses:
        '200':
          description: successful operation
        '404':
          description: not found
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/MulticastPort'
      security:
        - basicAuth: []
        - bearerAuth: []
      x-codeSamples:
        - lang: cURL
          label: CLI
          source: |
            curl -u "admin:pass" -X DELETE \
              "http://192.168.2.1/firewall/multicast" \
              --data '{
                        "Port": "1234",
                        "Upstream": true
                      }'
  /firewall/custom_interface:
    put:
      tags:
        - firewall
      summary: Add Custom Interface Rule to join an interface to the network
      description: Adds a custom interface rule to the firewall.
      operationId: addFirewallCustomInterfaceRule
      responses:
        '200':
          description: successful operation
        '400':
          description: malformed data
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/CustomInterfaceRule'
      security:
        - basicAuth: []
        - bearerAuth: []
      x-codeSamples:
        - lang: cURL
          label: CLI
          source: |
            curl -u "admin:pass" -X PUT \
              "http://192.168.2.1/firewall/custom_interface" \
              --data '{
                        "Interface": "eth0",
                        "SrcIP": "192.168.1.100",
                        "RouteDst": "172.12.0.2",
                        "Policies": ["api"],
                        "Groups": ["group1", "group2"],
                        "Tags": ["tag1", "tag2"]
                      }'
    delete:
      tags:
        - firewall
      summary: Remove Custom Interface Rule
      description: Removes a custom interface rule from the firewall.
      operationId: removeFirewallCustomInterfaceRule
      responses:
        '200':
          description: successful operation
        '404':
          description: not found
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/CustomInterfaceRule'
      security:
        - basicAuth: []
        - bearerAuth: []
      x-codeSamples:
        - lang: cURL
          label: CLI
          source: |
            curl -u "admin:pass" -X DELETE \
              "http://192.168.2.1/firewall/custom_interface" \
              --data '{
                        "Interface": "eth0",
                        "SrcIP": "192.168.1.100",
                        "RouteDst": "172.12.0.2",
                        "Policies": ["api"],
                        "Groups": ["group1", "group2"],
                        "Tags": ["tag1", "tag2"]
                      }'
  /firewall/icmp:
    put:
      tags:
        - firewall
      summary: Configure ICMP Options
      description: Configures ICMP options in the firewall.
      operationId: configureFirewallIcmpOptions
      responses:
        '200':
          description: successful operation
        '400':
          description: malformed data
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/ICMPOptions'
      security:
        - basicAuth: []
        - bearerAuth: []
      x-codeSamples:
        - lang: cURL
          label: CLI
          source: |
            curl -u "admin:pass" -X PUT \
              "http://192.168.2.1/firewall/icmp" \
              --data '{
                        "PingLan": true,
                        "PingWan": false
                      }'
  /subnetConfig:
    get:
      tags:
        - network
      summary: Get Subnet Configuration
      description: Retrieves the current subnet configuration.
      operationId: getSubnetConfiguration
      responses:
        '200':
          description: successful operation
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/DHCPConfig'
        '404':
          description: not found
      security:
        - basicAuth: []
        - bearerAuth: []
    put:
      tags:
        - network
      summary: Set Subnet Configuration
      description: >-
        Sets or updates the subnet configuration. This will overwrite the
        existing configuration.
      operationId: setSubnetConfiguration
      responses:
        '200':
          description: successful operation
        '400':
          description: malformed data
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/DHCPConfig'
      security:
        - basicAuth: []
        - bearerAuth: []
      x-codeSamples:
        - lang: cURL
          label: CLI
          source: |
            curl -u "admin:pass" -X PUT \
              "http://192.168.2.1/subnetConfig" \
              --data '{
                        "TinyNets": ["192.168.1.0/24", "192.168.2.0/24"],
                        "LeaseTime": "12h"
                      }'
  /dnsSettings:
    get:
      tags:
        - network
      summary: Get DNS Settings
      description: Retrieves the current DNS settings.
      operationId: getDnsSettings
      responses:
        '200':
          description: successful operation
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/DNSSettings'
        '404':
          description: not found
      security:
        - basicAuth: []
        - bearerAuth: []
    put:
      tags:
        - network
      summary: Update DNS Settings
      description: >-
        Updates the DNS settings. This operation overwrites the existing
        settings.
      operationId: updateDnsSettings
      responses:
        '200':
          description: successful operation
        '400':
          description: malformed data
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/DNSSettings'
      security:
        - basicAuth: []
        - bearerAuth: []
      x-codeSamples:
        - lang: cURL
          label: CLI
          source: |
            curl -u "admin:pass" -X PUT \
              "http://192.168.2.1/dnsSettings" \
              --data '{
                        "UpstreamTLSHost": "dns.example.com",
                        "UpstreamIPAddress": "8.8.8.8",
                        "TlsDisable": false
                      }'
  /iptraffic:
    get:
      tags:
        - traffic
      summary: Retrieve IP traffic
      description: Returns IP traffic information
      operationId: getIPTraffic
      responses:
        '200':
          description: successful operation
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: '#/components/schemas/IPTrafficElement'
      security:
        - basicAuth: []
        - bearerAuth: []
      x-codeSamples:
        - lang: cURL
          label: CLI
          source: |
            curl -u "admin:pass" \
              "http://192.168.2.1/iptraffic"
  /traffic/{countermap}:
    get:
      tags:
        - traffic
      summary: Retrieve traffic for LAN/WAN
      description: >-
        Returns traffic information from the counter specified by the name
        parameter. Countermap can be one of `incoming_traffic_lan` |
        `outgoing_traffic_lan` | `outgoing_traffic_wan` |
        `incoming_traffic_wan`. See the
        [accounting.sh](https://github.com/spr-networks/super/blob/main/base/scripts/accounting.sh)
        NFT rules for additional information
      operationId: getDeviceTraffic
      parameters:
        - name: countermap
          in: path
          description: Name of counter
          required: true
          schema:
            type: string
            example: incoming_traffic_lan
      responses:
        '200':
          description: successful operation
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: '#/components/schemas/TrafficElement'
        '400':
          description: Failed to collect traffic statistics for device
      security:
        - basicAuth: []
        - bearerAuth: []
      x-codeSamples:
        - lang: cURL
          label: CLI
          source: |
            curl -u "admin:pass" \
              "http://192.168.2.1/traffic/outgoing_traffic_lan"
  /traffic_history:
    get:
      tags:
        - traffic
      summary: Retrieve historical traffic data for devices
      description: Returns traffic information for all devices
      operationId: getTrafficHistory
      responses:
        '200':
          description: successful operation
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/TrafficHistory'
      security:
        - basicAuth: []
        - bearerAuth: []
      x-codeSamples:
        - lang: cURL
          label: CLI
          source: |
            curl -u "admin:pass" \
              "http://192.168.2.1/traffic_history"
  /hostapd/{interface}/status:
    get:
      tags:
        - hostapd
      summary: Retrieve hostapd status
      description: Returns current status for hostapd
      operationId: hostapdStatus
      parameters:
        - name: interface
          in: path
          description: Name of wireless interface
          required: true
          schema:
            type: string
      responses:
        '200':
          description: successful operation
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/HostapdStatus'
      security:
        - basicAuth: []
        - bearerAuth: []
      x-codeSamples:
        - lang: cURL
          label: CLI
          source: |
            curl -u "admin:pass" \
              "http://192.168.2.1/hostapd/status"
  /hostapd/{interface}/all_stations:
    get:
      tags:
        - hostapd
      summary: Retrieve all_stations output
      description: Returns current status for all stations
      operationId: hostapdAllStations
      parameters:
        - name: interface
          in: path
          description: Name of wireless interface
          required: true
          schema:
            type: string
      responses:
        '200':
          description: successful operation
          content:
            application/json:
              schema:
                type: object
                additionalProperties:
                  x-additionalPropertiesName: '11:22:33:44:55:6'
                  $ref: '#/components/schemas/StationInfo'
      security:
        - basicAuth: []
        - bearerAuth: []
      x-codeSamples:
        - lang: cURL
          label: CLI
          source: |
            curl -u "admin:pass" \
              "http://192.168.2.1/hostapd/all_stations"
  /hostapd/{interface}/config:
    get:
      tags:
        - hostapd
      summary: Retrieve hostapd config
      description: Returns hostapd configuration
      operationId: hostapdGetConfiguration
      parameters:
        - name: interface
          in: path
          description: Name of wireless interface
          required: true
          schema:
            type: string
      responses:
        '200':
          description: successful operation
          content:
            text/plain:
              schema:
                type: string
      security:
        - basicAuth: []
        - bearerAuth: []
      x-codeSamples:
        - lang: cURL
          label: CLI
          source: |
            curl -u "admin:pass" \
              "http://192.168.2.1/hostapd/config"
    put:
      tags:
        - hostapd
      summary: Set hostapd config
      description: Set hostapd configuration
      operationId: hostapdUpdateConfiguration
      parameters:
        - name: interface
          in: path
          description: Name of wireless interface
          required: true
          schema:
            type: string
      requestBody:
        $ref: '#/components/requestBodies/HostapdConfig'
      responses:
        '200':
          description: successful operation
          content:
            text/plain:
              schema:
                type: string
      security:
        - basicAuth: []
        - bearerAuth: []
  /hostapd/{interface}/setChannel:
    put:
      tags:
        - hostapd
      summary: Set WiFi Channel
      description: Sets channel configuration
      operationId: hostapdSetChannel
      parameters:
        - name: interface
          in: path
          description: Name of wireless interface
          required: true
          schema:
            type: string
      requestBody:
        $ref: '#/components/requestBodies/ChannelParameters'
      responses:
        '200':
          description: successful operation
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/CalculatedChannelParameters'
      security:
        - basicAuth: []
        - bearerAuth: []
      x-codeSamples:
        - lang: cURL
          label: CLI
          source: |
            curl -u "admin:pass" \
              "http://192.168.2.1/hostapd/config"
  /hostapd/{interface}/enable:
    put:
      tags:
        - hostapd
      summary: Enable Wireless Interface
      description: >-
        Enables a wireless interface, creating an configuration if needed, and
        starting hostapd
      operationId: hostapdEnableInterface
      parameters:
        - name: interface
          in: path
          description: Name of wireless interface
          required: true
          schema:
            type: string
      responses:
        '200':
          description: successful operation
      security:
        - basicAuth: []
        - bearerAuth: []
  /hostapd/{interface}/disable:
    put:
      tags:
        - hostapd
      summary: Disable Wireless Interface
      description: Disables a wireless interface, and restarts hostapd
      operationId: hostapdDisableInterface
      parameters:
        - name: interface
          in: path
          description: Name of wireless interface
          required: true
          schema:
            type: string
      responses:
        '200':
          description: successful operation
      security:
        - basicAuth: []
        - bearerAuth: []
  /hostapd/{interface}/resetConfiguration:
    put:
      tags:
        - hostapd
      summary: Reset Wireless Interface Configuration
      description: Resets HostAP Configuration to the Default Template
      operationId: hostapdResetInterface
      parameters:
        - name: interface
          in: path
          description: Name of wireless interface
          required: true
          schema:
            type: string
      responses:
        '200':
          description: successful operation
      security:
        - basicAuth: []
        - bearerAuth: []
  /hostapd/restart:
    put:
      tags:
        - hostapd
      summary: Restart WiFI Service
      description: Restarts all hostapd instances
      operationId: hostapdRestart
      responses:
        '200':
          description: successful operation
      security:
        - basicAuth: []
        - bearerAuth: []
      x-codeSamples:
        - lang: cURL
          label: CLI
          source: |
            curl -u "admin:pass" \
              "http://192.168.2.1/hostapd/config"
  /hostapd/{interface}/enableExtraBSS:
    put:
      tags:
        - hostapd
      summary: Enable Additional BSS on Interface
      description: >-
        Enables an additional BSS (Basic Service Set) on the specified
        interface. This supports WPA1, and disabled isolation. Requires card
        support
      operationId: hostapdEnableExtraBSS
      parameters:
        - name: interface
          in: path
          required: true
          description: Name of the network interface.
          schema:
            type: string
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/ExtraBSS'
      responses:
        '200':
          description: successful operation
        '400':
          description: malformed data
      security:
        - basicAuth: []
        - bearerAuth: []
      x-codeSamples:
        - lang: cURL
          label: CLI
          source: |
            curl -u "admin:pass" -X PUT \
              "http://192.168.2.1/hostapd/eth0/enableExtraBSS" \
              --data '{
                        "Ssid": "ExtraSSID",
                        "Bssid": "00:11:22:33:44:55",
                        "Wpa": "2",
                        "WpaKeyMgmt": "WPA-PSK",
                        "DisableIsolation": false
                      }'
    delete:
      tags:
        - hostapd
      summary: Disable Extra BSS on Interface
      description: Disables an additional BSS on the specified interface.
      operationId: hostapdDisableExtraBSS
      parameters:
        - name: interface
          in: path
          required: true
          description: Name of the network interface.
          schema:
            type: string
      responses:
        '200':
          description: successful operation
        '404':
          description: not found
      security:
        - basicAuth: []
        - bearerAuth: []
      x-codeSamples:
        - lang: cURL
          label: CLI
          source: |
            curl -u "admin:pass" -X DELETE \
              "http://192.168.2.1/hostapd/eth0/enableExtraBSS"
  /interfacesConfiguration:
    get:
      tags:
        - hostapd
      summary: Retrieve interface configuration
      description: SPR Tracks the state of interfaces to decide launching hostap
      operationId: interfaceConfiguration
      responses:
        '200':
          description: successful operation
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: '#/components/schemas/InterfaceEntry'
      security:
        - basicAuth: []
        - bearerAuth: []
      x-codeSamples:
        - lang: cURL
          label: CLI
          source: |
            curl -u "admin:pass" \
              "http://192.168.2.1/interfacesConfiguration"
  /reportPSKAuthFailure:
    put:
      tags:
        - unix_wifid
      summary: Report PSK auth failure
      description: ''
      operationId: reportPSKAuthFailure
      responses:
        '200':
          description: successful operation
        '400':
          description: malformed data
      requestBody:
        $ref: '#/components/requestBodies/PSKAuthFailure'
  /reportPSKAuthSuccess:
    put:
      tags:
        - unix_wifid
      summary: Report PSK auth success
      description: ''
      operationId: reportPSKAuthSuccess
      responses:
        '200':
          description: successful operation
        '400':
          description: malformed data
      requestBody:
        $ref: '#/components/requestBodies/PSKAuthSuccess'
  /interfaces:
    get:
      tags:
        - unix_wifid
      summary: Get a space separated text listing of Wireless Interfaces
      description: ''
      operationId: getInterfaces
      responses:
        '200':
          description: successful operation
          content:
            application/text:
              example:
                - wlan1 wlan2
        '400':
          description: malformed data
  /dhcpUpdate:
    put:
      tags:
        - unix_dhcpd
      summary: Update DHCP information
      description: Handle networking tasks upon a DHCP
      operationId: dhcpUpdate
      responses:
        '200':
          description: successful operation
      requestBody:
        $ref: '#/components/requestBodies/DHCPUpdate'
  /start?service={service}&compose_file={compose_file}:
    get:
      tags:
        - unix_superd
      summary: Run docker compose up -d on a service
      parameters:
        - name: service
          in: path
          description: Name of service
          required: true
          schema:
            type: string
        - name: compose_file
          in: path
          description: Compose file to run
          required: true
          schema:
            type: string
      description: ''
      operationId: superdStartService
      responses:
        '200':
          description: successful operation
        '400':
          description: malformed data
  /restart?service={service}&compose_file={compose_file}:
    put:
      tags:
        - unix_superd
      summary: Run docker compose restart on a service
      description: ''
      operationId: superdRestartService
      parameters:
        - name: service
          in: path
          description: Name of service
          required: true
          schema:
            type: string
        - name: compose_file
          in: path
          description: Compose file to run
          required: true
          schema:
            type: string
      responses:
        '200':
          description: successful operation
        '400':
          description: malformed data
  /update?service={service}&compose_file={compose_file}:
    get:
      tags:
        - unix_superd
      summary: Run docker compose pull on a service
      description: ''
      operationId: superdUpdateService
      parameters:
        - name: service
          in: path
          description: Name of service
          required: true
          schema:
            type: string
        - name: compose_file
          in: path
          description: Compose file to run
          required: true
          schema:
            type: string
      responses:
        '200':
          description: successful operation
        '400':
          description: malformed data
  /stop?service={service}&compose_file={compose_file}:
    get:
      tags:
        - unix_superd
      summary: Run docker compose stop on a service
      description: ''
      operationId: superdStopService
      parameters:
        - name: service
          in: path
          description: Name of service
          required: true
          schema:
            type: string
        - name: compose_file
          in: path
          description: Compose file to run
          required: true
          schema:
            type: string
      responses:
        '200':
          description: successful operation
        '400':
          description: malformed data
  /ghcr_auth:
    get:
      tags:
        - unix_superd
      summary: Authenticate to GHCR
      description: ''
      operationId: superdAuthenticateGHCR
      parameters:
        - name: username
          in: query
          description: username
          required: false
          schema:
            type: string
        - name: secret
          in: query
          description: Secret
          required: false
          schema:
            type: string
      responses:
        '200':
          description: successful operation
        '400':
          description: malformed data
  /update_git:
    get:
      tags:
        - unix_superd
      summary: Update PLUS extension git repostiory
      description: ''
      operationId: superdUpdateGit
      parameters:
        - name: git_url
          in: query
          description: git url to update clone into plus extensions and update
          required: false
          schema:
            type: string
      responses:
        '200':
          description: successful operation
        '400':
          description: malformed data
  /git_version:
    get:
      tags:
        - unix_superd
      summary: Get Version from git
      description: Get latest tag from git repository specified by the plugin parameter
      operationId: superGetGitVersion
      parameters:
        - name: plugin
          in: query
          description: plugin to get version for
          required: false
          schema:
            type: string
      responses:
        '200':
          description: successful operation
          content:
            application/json:
              schema:
                type: string
                example: v0.1.23
        '400':
          description: malformed data
      x-codeSamples:
        - lang: cURL
          label: CLI
          source: |
            curl --unix-socket \
              state/plugins/superd/socket \
              http://localhost/git_version
  /container_version:
    get:
      tags:
        - unix_superd
      summary: Get Version for docker container
      description: Get latest tag from docker specified by the container parameter
      operationId: superGetContainerVersion
      parameters:
        - name: container
          in: query
          description: container to get version for
          required: false
          schema:
            type: string
      responses:
        '200':
          description: successful operation
          content:
            application/json:
              schema:
                type: string
                example: 0.1.23
        '400':
          description: malformed data
      x-codeSamples:
        - lang: cURL
          label: CLI
          source: |
            curl --unix-socket \
              state/plugins/superd/socket \
              http://localhost/container_version
  /DHCPRequest:
    put:
      tags:
        - tinysubnets
      summary: DHCPRequest - Reserves an IP
      description: Reserves an IP address for plugins like wireguard to assign to clients
      operationId: DHCPRequest
      responses:
        '200':
          description: successful operation
      requestBody:
        $ref: '#/components/requestBodies/AbstractDHCPRequest'
  /plugins:
    get:
      tags:
        - plugins
      summary: Get Plugins
      description: Get a list of all the plugins
      operationId: showPlugins
      responses:
        '200':
          description: successful operation
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: '#/components/schemas/PluginEntry'
      security:
        - basicAuth: []
        - bearerAuth: []
      x-codeSamples:
        - lang: cURL
          label: CLI
          source: |
            curl -u "admin:pass" \
              "http://192.168.2.1/plugins"
  /plugins/{name}:
    put:
      tags:
        - plugins
      summary: Add or Update Plugin
      description: Add or update a plugin specified by the name parameter
      operationId: updatePlugin
      parameters:
        - name: name
          in: path
          description: plugin name
          required: true
          schema:
            type: string
            example: dns-block
      requestBody:
        $ref: '#/components/requestBodies/PluginEntry'
      responses:
        '200':
          description: successful operation
      security:
        - basicAuth: []
        - bearerAuth: []
      x-codeSamples:
        - lang: cURL
          label: CLI
          source: |
            curl -u "admin:pass" -X PUT  \
              "http://192.168.2.1/plugins/dns-block" \
              --data '{"Enabled": false}'
    delete:
      tags:
        - plugins
      summary: Delete Plugin
      description: Delete plugin specified by the name parameter
      operationId: deletePlugin
      parameters:
        - name: name
          in: path
          description: plugin name
          required: true
          schema:
            type: string
            example: dns-block
      responses:
        '200':
          description: successful operation
      security:
        - basicAuth: []
        - bearerAuth: []
      x-codeSamples:
        - lang: cURL
          label: CLI
          source: |
            curl -u "admin:pass" -X DELETE  \
              "http://192.168.2.1/plugins/plugin-test" \
              --data '{}'
  /plugin/custom_compose_paths:
    get:
      tags:
        - plugins
      summary: Get Custom Compose Paths
      description: Retrieves the current set of custom compose paths.
      operationId: getCustomComposePaths
      responses:
        '200':
          description: List of custom compose paths
          content:
            application/json:
              schema:
                type: array
                items:
                  type: string
      security:
        - basicAuth: []
          OTPAuth: []
        - bearerAuth: []
          OTPAuth: []
    put:
      tags:
        - plugins
      summary: Update Custom Docker Compose Paths for plugins
      description: >-
        Updates the permit list of docker compose files that can be launched
        from disk
      operationId: updateCustomComposePaths
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: array
              items:
                type: string
      responses:
        '200':
          description: Custom compose paths updated successfully
      security:
        - basicAuth: []
          OTPAuth: []
        - bearerAuth: []
          OTPAuth: []
  /plugin/install_user_url:
    put:
      tags:
        - plugins
      summary: Install from Git URL
      description: Installs a plugin from the provided user URL on github.
      operationId: installPluginFromUrl
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: string
              example: https://github.com/spr-networks/spr-sample-plugin.git
      responses:
        '200':
          description: Plugin installation initiated successfully
      security:
        - basicAuth: []
          OTPAuth: []
        - bearerAuth: []
          OTPAuth: []
      x-codeSamples:
        - lang: cURL
          label: CLI
          source: |
            curl -u "admin:pass" -H "X-JWT-OTP: ..." -X PUT \
              "http://192.168.2.1/plugin/install_user_url" --data "https://github.com/spr-networks/spr-sample-plugin.git"
  /tokens:
    get:
      tags:
        - tokens
      summary: Get API Tokens
      description: Get an array of all tokens
      operationId: getTokens
      responses:
        '200':
          description: successful operation
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: '#/components/schemas/Token'
      security:
        - basicAuth: []
          OTPAuth: []
        - bearerAuth: []
          OTPAuth: []
      x-codeSamples:
        - lang: cURL
          label: CLI
          source: |
            curl -u "admin:pass" -H "X-JWT-OTP:..." \
              "http://192.168.2.1/tokens"
    put:
      tags:
        - tokens
      summary: Add API Token
      description: >-
        Create a new token. If Expire is 0 or undefined the Token will never
        expire
      operationId: addToken
      responses:
        '200':
          description: successful operation
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Token'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                Expire:
                  type: integer
                ScopedPaths:
                  type: array
                  items:
                    type: string
                  example:
                    - /status
                    - /docker/info
            example:
              Expire: 1656440879
              ScopedPaths:
                - /status
                - /docker/info
      security:
        - basicAuth: []
          OTPAuth: []
        - bearerAuth: []
          OTPAuth: []
      x-codeSamples:
        - lang: cURL
          label: CLI
          source: |
            curl -u "admin:pass" -H "X-JWT-OTP:..." -X PUT \
              "http://192.168.2.1/tokens" --data {"ScopedPaths": ["/status", "/docker/info"]}
    delete:
      tags:
        - tokens
      summary: Delete API Token
      description: Delete token specified by the Token parameter
      operationId: deleteToken
      responses:
        '200':
          description: successful operation
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                Token:
                  type: string
            example:
              Token: dG9rbnRva250b2tudG9rbnRva250b2tudG9rbnRva24K
      security:
        - basicAuth: []
        - bearerAuth: []
      x-codeSamples:
        - lang: cURL
          label: CLI
          source: |
            curl -u "admin:pass" -X DELETE \
              "http://192.168.2.1/tokens" --data '{"Token": "b64Token"}'
  /status:
    get:
      tags:
        - general
      summary: Get Status
      description: Returns "Online". Can be used to test authentication
      operationId: getStatus
      responses:
        '200':
          description: successful operation
          content:
            application/json:
              schema:
                type: string
                example: Online
      security:
        - basicAuth: []
        - bearerAuth: []
      x-codeSamples:
        - lang: cURL
          label: CLI
          source: |
            curl -u "admin:pass" \
              "http://192.168.2.1/status"
  /features:
    get:
      tags:
        - general
      summary: Get Features
      description: Returns an array of features
      operationId: getFeatures
      responses:
        '200':
          description: successful operation
          content:
            application/json:
              schema:
                type: array
                items:
                  type: string
                example:
                  - wifi
      security:
        - basicAuth: []
        - bearerAuth: []
      x-codeSamples:
        - lang: cURL
          label: CLI
          source: |
            curl -u "admin:pass" \
              "http://192.168.2.1/status"
  /version:
    get:
      tags:
        - general
      summary: Get Version
      description: >-
        Get latest tag from docker specified by the container parameter. If no
        container is specified version is fetched for superd
      operationId: getVersion
      parameters:
        - name: container
          in: query
          description: container to get version for
          required: false
          schema:
            type: string
      responses:
        '200':
          description: successful operation
          content:
            application/json:
              schema:
                type: string
                example: 0.1.23
        '400':
          description: malformed data
      security:
        - basicAuth: []
        - bearerAuth: []
      x-codeSamples:
        - lang: cURL
          label: CLI
          source: |
            curl -u "admin:pass" \
              "http://192.168.2.1/version"
  /release:
    get:
      tags:
        - releases
      summary: Get release settings
      description: >-
        Returns an object with the current SPR version and Channel, Version
        settings
      operationId: getRelease
      responses:
        '200':
          description: successful operation
          content:
            application/json:
              schema:
                type: object
                properties:
                  CustomChannel:
                    type: string
                  CustomVersion:
                    type: string
                  Current:
                    type: string
                example:
                  CustomChannel: '-dev'
                  CustomVersion: 0.1.2
                  Current: 0.1.2-dev
        '400':
          description: malformed data
      security:
        - basicAuth: []
        - bearerAuth: []
      x-codeSamples:
        - lang: cURL
          label: CLI
          source: |
            curl -u "admin:pass" \
              "http://192.168.2.1/release"
    put:
      tags:
        - releases
      summary: Set release settings
      description: Set a custom Channel, Version to update into
      operationId: putRelease
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                CustomChannel:
                  type: string
                CustomVersion:
                  type: string
                Current:
                  type: string
              example:
                CustomChannel: '-dev'
                CustomVersion: 0.1.3
      responses:
        '200':
          description: successful operation
      security:
        - basicAuth: []
        - bearerAuth: []
      x-codeSamples:
        - lang: cURL
          label: CLI
          source: |
            curl -X PUT -u "admin:pass" \
              "http://192.168.2.1/release" \
              --data '{"CustomChannel":"-dev","CustomVersion":"0.1.29"}'
    delete:
      tags:
        - releases
      summary: Reset release settings
      description: Clear out custom release and channel
      operationId: deleteReleaseSettings
      responses:
        '200':
          description: successful operation
      security:
        - basicAuth: []
        - bearerAuth: []
      x-codeSamples:
        - lang: cURL
          label: CLI
          source: |
            curl -u "admin:pass" -X DELETE \
              "http://192.168.2.1/release"
  /releaseChannels:
    get:
      tags:
        - releases
      summary: Get Release Channels
      description: Get configured release channels
      operationId: getReleaseChannels
      responses:
        '200':
          description: successful operation
          content:
            application/json:
              schema:
                type: array
                items:
                  type: string
                example:
                  - main
                  - '-dev'
        '400':
          description: malformed data
      security:
        - basicAuth: []
        - bearerAuth: []
      x-codeSamples:
        - lang: cURL
          label: CLI
          source: |
            curl -u "admin:pass" \
              "http://192.168.2.1/releaseChannels"
  /releasesAvailable:
    get:
      tags:
        - releases
      summary: Get releases available
      description: Returns a list of tags available to update into
      operationId: getReleasesAvailable
      parameters:
        - name: container
          in: query
          description: Container name
          required: true
          schema:
            type: string
          example: super_superd
      responses:
        '200':
          description: successful operation
          content:
            application/json:
              schema:
                type: array
                items:
                  type: string
                example:
                  - latest
                  - 0.1.23
                  - 0.1.23-dev
        '400':
          description: malformed data
      security:
        - basicAuth: []
        - bearerAuth: []
      x-codeSamples:
        - lang: cURL
          label: CLI
          source: |
            curl -u "admin:pass" \
              "http://192.168.2.1/releaseChannels"
  /update:
    put:
      tags:
        - releases
      summary: Trigger update
      description: >-
        SPR will run a self update, to the configured release Channel and
        Version (latest by default)
      operationId: putUpdate
      responses:
        '200':
          description: successful operation
      security:
        - basicAuth: []
        - bearerAuth: []
      x-codeSamples:
        - lang: cURL
          label: CLI
          source: |
            curl -X PUT -u "admin:pass" \
              "http://192.168.2.1/update"
  /speedtest:
    get:
      tags:
        - general
      summary: Test download speed to Web API
      operationId: speedTestDownload
      security:
        - basicAuth: []
        - bearerAuth: []
      responses:
        '200':
          description: successful operationId
          content:
            text/plain:
              schema:
                type: string
    put:
      tags:
        - general
      summary: Test upload speed to Web API
      operationId: speedTestUpload
      security:
        - basicAuth: []
        - bearerAuth: []
      requestBody:
        content:
          text/plain:
            schema:
              type: string
      responses:
        '200':
          description: successful operationId
          content:
            text/plain:
              schema:
                type: string
  /logs:
    get:
      tags:
        - general
      summary: Retreive System Logs
      description: |
        Returns the output of journalctl in json format
      operationId: getLogs
      responses:
        '200':
          description: successful operation
          content:
            application/json:
              schema:
                type: array
                items:
                  type: object
                  example:
                    CONTAINER_NAME: superapi
                    MESSAGE: 192.168.2.101:1234 GET /logs
                    __REALTIME_TIMESTAMP: 1651066188615770
      security:
        - basicAuth: []
        - bearerAuth: []
      x-codeSamples:
        - lang: cURL
          label: CLI
          source: |
            curl -u "admin:pass" \
              "http://192.168.2.1/logs"
  /alerts:
    get:
      tags:
        - alerts
      summary: Retrieve all alerts
      description: Returns a list of all alert settings.
      operationId: getAlerts
      responses:
        '200':
          description: A list of alert settings
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: '#/components/schemas/AlertSetting'
      x-codeSamples:
        - lang: cURL
          label: CLI
          source: |
            curl -X GET "http://192.168.2.1/alerts"
    put:
      tags:
        - alerts
      summary: Add or Update Alerts
      description: >
        If an alert setting does not exist, it will be created, otherwise
        updated
      operationId: updateAlerts
      requestBody:
        $ref: '#/components/requestBodies/AlertSetting'
      responses:
        '200':
          description: Successful operation
        '400':
          description: Invalid input
      security:
        - basicAuth: []
        - bearerAuth: []
      x-codeSamples:
        - lang: cURL
          label: CLI
          source: |
            curl -u "admin:pass" -X PUT  \
              "http://192.168.2.1/alerts" \
              --data '{"TopicPrefix": "security", "MatchAnyOne": false, "InvertRule": false, "Conditions": [{"JPath": "$.status"}], "Actions": [{"SendNotification": true}], "Name": "SecurityAlert", "Disabled": false, "RuleId": "rule123"}'
  /alerts/{index}:
    delete:
      tags:
        - alerts
      summary: Delete an alert by index
      description: Deletes a specific alert setting by its index.
      operationId: deleteAlertByIndex
      parameters:
        - name: index
          in: path
          required: true
          schema:
            type: integer
            example: 1
      responses:
        '200':
          description: Alert deleted
      x-codeSamples:
        - lang: cURL
          label: CLI
          source: |
            curl -X DELETE "http://192.168.2.1/alerts/{index}"
    put:
      tags:
        - alerts
      summary: Update Alert by Index
      description: >
        Update an alert setting at a specific index. If the alert setting does
        not exist at this index, it will be created. Fields are optional.
      operationId: updateAlertByIndex
      parameters:
        - name: index
          in: path
          required: true
          schema:
            type: integer
            example: 1
      requestBody:
        $ref: '#/components/requestBodies/AlertSetting'
      responses:
        '200':
          description: Successful operation
        '400':
          description: Invalid input
      security:
        - basicAuth: []
        - bearerAuth: []
      x-codeSamples:
        - lang: cURL
          label: CLI
          source: |
            curl -u "admin:pass" -X PUT  \
              "http://192.168.2.1/alerts/1" \
              --data '{"TopicPrefix": "system", "MatchAnyOne": true, "InvertRule": true, "Conditions": [{"JPath": "$.error"}], "Actions": [{"StoreAlert": true}], "Name": "SystemFailureAlert", "Disabled": true, "RuleId": "rule456"}'
  /startPlusExtension:
    get:
      tags:
        - plus
      summary: Start PLUS extension
      description: Start a PLUS extension. Currently this is the pfw plugin
      operationId: plusStart
      responses:
        '200':
          description: successful operation
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: '#/components/schemas/Notification'
      security:
        - basicAuth: []
        - bearerAuth: []
      parameters:
        - name: name
          in: query
          description: Name of plus extension
          required: false
          schema:
            type: string
            example: pfw
  /stopPlusExtension:
    get:
      tags:
        - plus
      summary: Stop PLUS extension
      description: Stop a PLUS extension. Currently this is the pfw plugin
      operationId: plusStop
      responses:
        '200':
          description: successful operation
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: '#/components/schemas/Notification'
      security:
        - basicAuth: []
        - bearerAuth: []
      parameters:
        - name: name
          in: query
          description: Name of plus extension
          required: false
          schema:
            type: string
            example: pfw
  /plusToken:
    get:
      tags:
        - plus
      summary: Get PLUS token
      description: Get the configured PLUS token
      operationId: plusGetToken
      responses:
        '200':
          description: successful operation
          content:
            application/json:
              schema:
                type: string
      security:
        - basicAuth: []
        - bearerAuth: []
      x-codeSamples:
        - lang: cURL
          label: CLI
          source: |
            curl -u "admin:pass" \
              "http://192.168.2.1/tokens"
    put:
      tags:
        - plus
      summary: Set PLUS token
      description: Configure a PLUS token and trigger PLUS installation
      operationId: plusSetToken
      responses:
        '200':
          description: successful operation
      requestBody:
        content:
          application/json:
            schema:
              type: string
            example: plus_token
      security:
        - basicAuth: []
        - bearerAuth: []
      x-codeSamples:
        - lang: cURL
          label: CLI
          source: |
            curl -u "admin:pass" -X PUT \
              "http://192.168.2.1/tokens" --data {}
  /ping/{interface}/{address}:
    put:
      tags:
        - network
      summary: Perform an ICMP ping test
      description: Performs an ICMP ping test from a specified interface to a given address
      operationId: performICMPPingTest
      parameters:
        - name: interface
          in: path
          description: Network interface to use for the ping test
          required: true
          schema:
            type: string
        - name: address
          in: path
          description: IP address to ping
          required: true
          schema:
            type: string
      responses:
        '200':
          description: Successful operation
          content:
            application/json:
              schema:
                type: array
                items:
                  type: string
                example:
                  - 10.523ms
                  - 9.872ms
                  - 11.245ms
                  - 10.101ms
        '400':
          description: Bad request (invalid interface, address, or socket error)
      x-codeSamples:
        - lang: cURL
          label: CLI
          source: |
            curl -X PUT http://localhost/ping/eth0/8.8.8.8
  /ping/{interface}/{address}/udp:
    put:
      tags:
        - network
      summary: Perform a UDP ping test
      description: Performs a UDP ping test from a specified interface to a given address
      operationId: performUDPPingTest
      parameters:
        - name: interface
          in: path
          description: Network interface to use for the UDP ping test
          required: true
          schema:
            type: string
        - name: address
          in: path
          description: IP address and port to ping
          required: true
          schema:
            type: string
      responses:
        '200':
          description: Successful operation
          content:
            application/json:
              schema:
                type: array
                items:
                  type: string
                example:
                  - 15.789ms
                  - 14.234ms
                  - 16.012ms
                  - 15.456ms
        '400':
          description: Bad request (invalid interface, address, or socket error)
      x-codeSamples:
        - lang: cURL
          label: CLI
          source: |
            curl -X PUT http://localhost/ping/eth0/8.8.8.8:53/udp
  /multicastSettings:
    get:
      tags:
        - firewall
      summary: Get multicast settings
      description: Retrieves the current multicast settings
      operationId: getMulticastSettings
      responses:
        '200':
          description: Successful operation
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/MulticastSettings'
      x-codeSamples:
        - lang: cURL
          label: CLI
          source: |
            curl http://localhost/multicastSettings
    put:
      tags:
        - firewall
      summary: Update multicast settings
      description: Updates the multicast settings
      operationId: updateMulticastSettings
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/MulticastSettings'
      responses:
        '200':
          description: Successful operation
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/MulticastSettings'
        '400':
          description: Bad request (invalid multicast address)
      x-codeSamples:
        - lang: cURL
          label: CLI
          source: |
            curl -X PUT -H "Content-Type: application/json" \
              -d '{"Disabled":false,"Addresses":[{"Address":"224.0.0.251:5353"}],"DisableMDNSAdvertise":false,"MDNSName":"MyDevice"}' \
              http://localhost/multicastSettings
  /ip/interfaces:
    get:
      tags:
        - general
      summary: Get IP to interface mappings
      description: Retrieves the current IP to interface mappings
      operationId: getIPInterfaceMappings
      responses:
        '200':
          description: Successful operation
          content:
            application/json:
              schema:
                type: object
                additionalProperties:
                  type: string
                example:
                  192.168.1.1: eth0
                  10.0.0.1: wlan0
      x-codeSamples:
        - lang: cURL
          label: CLI
          source: |
            curl http://localhost/ip/interfaces
  /firewall/geo_block/config:
    get:
      tags:
        - firewall
      summary: Get Geo/ASN Block Config
      description: ''
      operationId: getGeoBlockConfig
      responses:
        '200':
          description: successful operation
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/GeoBlockConfig'
        '400':
          description: malformed data
      security:
        - basicAuth: []
        - bearerAuth: []
      x-codeSamples:
        - lang: cURL
          label: CLI
          source: |
            curl -u "admin:pass" -X GET \
              "http://192.168.2.1/firewall/geo_block/config"
    put:
      tags:
        - firewall
      summary: Update Geo/ASN Block Config
      description: ''
      operationId: updateGeoBlockConfig
      responses:
        '200':
          description: successful operation
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/GeoBlockConfig'
        '400':
          description: malformed data
      requestBody:
        $ref: '#/components/requestBodies/GeoBlockConfig'
      security:
        - basicAuth: []
        - bearerAuth: []
      x-codeSamples:
        - lang: cURL
          label: CLI
          source: |
            curl -u "admin:pass" -X PUT \
              "http://192.168.2.1/firewall/geo_block/config" \
              --data '{
                        "Enabled": true,
                        "DenyCountries": ["CN", "RU"],
                        "DenyASNs": [{"ASN": 13335, "Name": "CLOUDFLARENET"}],
                        "Lists": [{"URI": "https://www.spamhaus.org/drop/asndrop.json", "Enabled": false, "Note": "Spamhaus ASN-DROP"}],
                        "RefreshSeconds": 86400
                      }'
  /firewall/geo_block/status:
    get:
      tags:
        - firewall
      summary: Get Geo/ASN Block Status
      description: ''
      operationId: getGeoBlockStatus
      responses:
        '200':
          description: successful operation
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/GeoBlockStatus'
        '400':
          description: malformed data
      security:
        - basicAuth: []
        - bearerAuth: []
      x-codeSamples:
        - lang: cURL
          label: CLI
          source: |
            curl -u "admin:pass" -X GET \
              "http://192.168.2.1/firewall/geo_block/status"
  /firewall/geo_block/refresh:
    put:
      tags:
        - firewall
      summary: Refresh Geo/ASN Block Ranges
      description: ''
      operationId: refreshGeoBlock
      responses:
        '200':
          description: successful operation
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/GeoBlockStatus'
        '400':
          description: malformed data
      security:
        - basicAuth: []
        - bearerAuth: []
      x-codeSamples:
        - lang: cURL
          label: CLI
          source: |
            curl -u "admin:pass" -X PUT \
              "http://192.168.2.1/firewall/geo_block/refresh"
  /firewall/geo_block/asn/{asn}:
    put:
      tags:
        - firewall
      summary: Add Blocked ASN
      description: ''
      operationId: addGeoBlockASN
      parameters:
        - name: asn
          in: path
          required: true
          description: Autonomous System Number to block
          schema:
            type: integer
            example: 13335
      responses:
        '200':
          description: successful operation
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/GeoBlockConfig'
        '400':
          description: invalid ASN
      security:
        - basicAuth: []
        - bearerAuth: []
      x-codeSamples:
        - lang: cURL
          label: CLI
          source: |
            curl -u "admin:pass" -X PUT \
              "http://192.168.2.1/firewall/geo_block/asn/13335"
    delete:
      tags:
        - firewall
      summary: Delete Blocked ASN
      description: ''
      operationId: deleteGeoBlockASN
      parameters:
        - name: asn
          in: path
          required: true
          description: Autonomous System Number to unblock
          schema:
            type: integer
            example: 13335
      responses:
        '200':
          description: successful operation
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/GeoBlockConfig'
        '400':
          description: invalid ASN
      security:
        - basicAuth: []
        - bearerAuth: []
      x-codeSamples:
        - lang: cURL
          label: CLI
          source: |
            curl -u "admin:pass" -X DELETE \
              "http://192.168.2.1/firewall/geo_block/asn/13335"
  /firewall/geo_block/country/{cc}:
    put:
      tags:
        - firewall
      summary: Add Blocked Country
      description: ''
      operationId: addGeoBlockCountry
      parameters:
        - name: cc
          in: path
          required: true
          description: Two-letter ISO 3166-1 alpha-2 country code
          schema:
            type: string
            example: CN
      responses:
        '200':
          description: successful operation
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/GeoBlockConfig'
        '400':
          description: invalid country code
      security:
        - basicAuth: []
        - bearerAuth: []
      x-codeSamples:
        - lang: cURL
          label: CLI
          source: |
            curl -u "admin:pass" -X PUT \
              "http://192.168.2.1/firewall/geo_block/country/CN"
    delete:
      tags:
        - firewall
      summary: Delete Blocked Country
      description: ''
      operationId: deleteGeoBlockCountry
      parameters:
        - name: cc
          in: path
          required: true
          description: Two-letter ISO 3166-1 alpha-2 country code
          schema:
            type: string
            example: CN
      responses:
        '200':
          description: successful operation
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/GeoBlockConfig'
        '400':
          description: invalid country code
      security:
        - basicAuth: []
        - bearerAuth: []
      x-codeSamples:
        - lang: cURL
          label: CLI
          source: |
            curl -u "admin:pass" -X DELETE \
              "http://192.168.2.1/firewall/geo_block/country/CN"
  /firewall/block_output:
    put:
      tags:
        - firewall
      summary: Add Output Block
      description: ''
      operationId: addFirewallBlockOutput
      responses:
        '200':
          description: successful operation
        '400':
          description: malformed data
      requestBody:
        $ref: '#/components/requestBodies/FirewallBlockOutput'
      security:
        - basicAuth: []
        - bearerAuth: []
      x-codeSamples:
        - lang: cURL
          label: CLI
          source: |
            curl -u "admin:pass" -X PUT \
              "http://192.168.2.1/firewall/block_output" \
              --data '{
                        "DstIP": "1.2.3.4",
                        "SrcIP": "0.0.0.0/24",
                        "DstPort": "0-65535",
                        "Protocol": "tcp"
                      }'
    delete:
      tags:
        - firewall
      summary: Delete Output Block
      description: ''
      operationId: deleteFirewallBlockOutput
      responses:
        '200':
          description: successful operation
        '400':
          description: malformed data
      requestBody:
        $ref: '#/components/requestBodies/FirewallBlockOutput'
      security:
        - basicAuth: []
        - bearerAuth: []
      x-codeSamples:
        - lang: cURL
          label: CLI
          source: |
            curl -u "admin:pass" -X DELETE \
              "http://192.168.2.1/firewall/block_output" \
              --data '{
                        "DstIP": "1.2.3.4",
                        "SrcIP": "0.0.0.0/24",
                        "DstPort": "0-65535",
                        "Protocol": "tcp"
                      }'
  /firewall/enableTLS:
    get:
      tags:
        - firewall
      summary: Get TLS Status
      description: ''
      operationId: getFirewallTLS
      responses:
        '200':
          description: successful operation
          content:
            application/json:
              schema:
                type: boolean
                example: true
        '400':
          description: malformed data
      security:
        - basicAuth: []
        - bearerAuth: []
      x-codeSamples:
        - lang: cURL
          label: CLI
          source: |
            curl -u "admin:pass" -X GET \
              "http://192.168.2.1/firewall/enableTLS"
    put:
      tags:
        - firewall
      summary: Enable TLS
      description: ''
      operationId: enableFirewallTLS
      responses:
        '200':
          description: successful operation
          content:
            application/json:
              schema:
                type: string
                example: Done
        '400':
          description: already configured or certificate generation failed
      security:
        - basicAuth: []
        - bearerAuth: []
      x-codeSamples:
        - lang: cURL
          label: CLI
          source: |
            curl -u "admin:pass" -X PUT \
              "http://192.168.2.1/firewall/enableTLS"
    delete:
      tags:
        - firewall
      summary: Disable TLS
      description: ''
      operationId: disableFirewallTLS
      responses:
        '200':
          description: successful operation
          content:
            application/json:
              schema:
                type: string
                example: Done
        '400':
          description: not configured
      security:
        - basicAuth: []
        - bearerAuth: []
      x-codeSamples:
        - lang: cURL
          label: CLI
          source: |
            curl -u "admin:pass" -X DELETE \
              "http://192.168.2.1/firewall/enableTLS"
  /firewall/systemDnsOverride:
    put:
      tags:
        - firewall
      summary: Set System DNS Override
      description: ''
      operationId: setSystemDnsOverride
      responses:
        '200':
          description: successful operation
        '400':
          description: invalid IP
      requestBody:
        $ref: '#/components/requestBodies/SystemDnsOverride'
      security:
        - basicAuth: []
        - bearerAuth: []
      x-codeSamples:
        - lang: cURL
          label: CLI
          source: |
            curl -u "admin:pass" -X PUT \
              "http://192.168.2.1/firewall/systemDnsOverride" \
              --data '"8.8.8.8"'
  /hostapd/roaming/config:
    get:
      tags:
        - hostapd
      summary: Get Fast-Roaming Configuration
      description: >-
        Returns the current 802.11v fast-roaming configuration proxied from
        wifid
      operationId: getRoamingConfig
      responses:
        '200':
          description: successful operation
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/RoamingConfig'
        '400':
          description: bad request
      security:
        - basicAuth: []
        - bearerAuth: []
      x-codeSamples:
        - lang: cURL
          label: CLI
          source: |
            curl -u "admin:pass" \
              "http://192.168.2.1/hostapd/roaming/config"
    put:
      tags:
        - hostapd
      summary: Update Fast-Roaming Configuration
      description: Validates and stores the 802.11v fast-roaming configuration
      operationId: updateRoamingConfig
      responses:
        '200':
          description: successful operation
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/RoamingConfig'
        '400':
          description: invalid configuration
      requestBody:
        $ref: '#/components/requestBodies/RoamingConfig'
      security:
        - basicAuth: []
        - bearerAuth: []
      x-codeSamples:
        - lang: cURL
          label: CLI
          source: |
            curl -u "admin:pass" -X PUT \
              -H "Content-Type: application/json" \
              -d '{"DryRun":true,"PollIntervalSeconds":15,"ObservationDelaySeconds":20,"RSSIThresholdDBM":-70,"MinimumImprovementDBM":5,"CooldownSeconds":900,"MaxTransitionsPerHour":4,"ExplorationRate":0,"AllowedInterfaces":[]}' \
              "http://192.168.2.1/hostapd/roaming/config"
  /hostapd/roaming/status:
    get:
      tags:
        - hostapd
      summary: Get Fast-Roaming Status
      description: Returns runtime status counters for the fast-roaming manager
      operationId: getRoamingStatus
      responses:
        '200':
          description: successful operation
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/RoamingStatus'
        '400':
          description: bad request
      security:
        - basicAuth: []
        - bearerAuth: []
      x-codeSamples:
        - lang: cURL
          label: CLI
          source: |
            curl -u "admin:pass" \
              "http://192.168.2.1/hostapd/roaming/status"
  /hostapd/roaming/history:
    get:
      tags:
        - hostapd
      summary: Get Fast-Roaming History
      description: Returns recorded BSS transition attempts, newest first
      operationId: getRoamingHistory
      responses:
        '200':
          description: successful operation
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: '#/components/schemas/RoamingRecord'
        '400':
          description: bad request
      security:
        - basicAuth: []
        - bearerAuth: []
      x-codeSamples:
        - lang: cURL
          label: CLI
          source: |
            curl -u "admin:pass" \
              "http://192.168.2.1/hostapd/roaming/history"
  /hostapd/roaming/model:
    get:
      tags:
        - hostapd
      summary: Get Fast-Roaming Model
      description: Returns the learned bandit model, keyed by device/interface/RSSI bucket
      operationId: getRoamingModel
      responses:
        '200':
          description: successful operation
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/RoamingModel'
        '400':
          description: bad request
      security:
        - basicAuth: []
        - bearerAuth: []
      x-codeSamples:
        - lang: cURL
          label: CLI
          source: |
            curl -u "admin:pass" \
              "http://192.168.2.1/hostapd/roaming/model"
  /hostapd/calcChannel:
    put:
      tags:
        - hostapd
      summary: Calculate Channel Parameters
      description: Computes center frequencies and channel widths without applying them
      operationId: hostapdCalcChannel
      responses:
        '200':
          description: successful operation
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/CalculatedChannelParameters'
        '400':
          description: bad request
      requestBody:
        $ref: '#/components/requestBodies/ChannelParameters'
      security:
        - basicAuth: []
        - bearerAuth: []
      x-codeSamples:
        - lang: cURL
          label: CLI
          source: |
            curl -u "admin:pass" -X PUT \
              -H "Content-Type: application/json" \
              -d '{"Mode":"a","Channel":36,"Bandwidth":80,"HT_Enable":true,"VHT_Enable":true,"HE_Enable":true}' \
              "http://192.168.2.1/hostapd/calcChannel"
  /hostapd/syncMesh:
    put:
      tags:
        - hostapd
      summary: Sync Mesh Devices
      description: Triggers the mesh plugin to synchronize device PSK state
      operationId: hostapdSyncMesh
      responses:
        '200':
          description: successful operation
        '400':
          description: bad request
      security:
        - basicAuth: []
        - bearerAuth: []
      x-codeSamples:
        - lang: cURL
          label: CLI
          source: |
            curl -u "admin:pass" -X PUT \
              "http://192.168.2.1/hostapd/syncMesh"
  /hostapd/restart_setup:
    put:
      tags:
        - hostapd
      summary: Restart Setup WiFi Service
      description: Restarts the wifid-setup service used during initial provisioning
      operationId: hostapdRestartSetup
      responses:
        '200':
          description: successful operation
        '400':
          description: bad request
      security:
        - basicAuth: []
        - bearerAuth: []
      x-codeSamples:
        - lang: cURL
          label: CLI
          source: |
            curl -u "admin:pass" -X PUT \
              "http://192.168.2.1/hostapd/restart_setup"
  /hostapd/{interface}/bssTransition:
    put:
      tags:
        - hostapd
      summary: Request BSS Transition
      description: >-
        Sends an advisory 802.11v BSS transition for a station toward a target
        interface
      operationId: hostapdBSSTransition
      parameters:
        - name: interface
          in: path
          description: Name of the source wireless interface
          required: true
          schema:
            type: string
      responses:
        '200':
          description: successful operation
        '400':
          description: invalid MAC or target interface
      requestBody:
        $ref: '#/components/requestBodies/BSSTransitionRequest'
      security:
        - basicAuth: []
        - bearerAuth: []
      x-codeSamples:
        - lang: cURL
          label: CLI
          source: |
            curl -u "admin:pass" -X PUT \
              -H "Content-Type: application/json" \
              -d '{"MAC":"11:22:33:44:55:66","TargetInterface":"wlan1"}' \
              "http://192.168.2.1/hostapd/wlan0/bssTransition"
  /hostapd/{interface}/deauth:
    put:
      tags:
        - hostapd
      summary: Deauthenticate Station
      description: Disassociates and deauthenticates a station from the interface
      operationId: hostapdDeauth
      parameters:
        - name: interface
          in: path
          description: Name of wireless interface
          required: true
          schema:
            type: string
      responses:
        '200':
          description: successful operation
        '400':
          description: invalid MAC
      requestBody:
        $ref: '#/components/requestBodies/HostapdDeauthMAC'
      security:
        - basicAuth: []
        - bearerAuth: []
      x-codeSamples:
        - lang: cURL
          label: CLI
          source: |
            curl -u "admin:pass" -X PUT \
              -H "Content-Type: application/json" \
              -d '"11:22:33:44:55:66"' \
              "http://192.168.2.1/hostapd/wlan0/deauth"
  /hostapd/{interface}/failsafe:
    get:
      tags:
        - hostapd
      summary: Get Failsafe Status
      description: Reports whether the interface is running in failsafe mode
      operationId: hostapdFailsafeStatus
      parameters:
        - name: interface
          in: path
          description: Name of wireless interface
          required: true
          schema:
            type: string
      responses:
        '200':
          description: successful operation
          content:
            application/json:
              schema:
                type: string
                description: ok when running normally, or "failsafe running"
                example: ok
        '400':
          description: bad request
      security:
        - basicAuth: []
        - bearerAuth: []
      x-codeSamples:
        - lang: cURL
          label: CLI
          source: |
            curl -u "admin:pass" \
              "http://192.168.2.1/hostapd/wlan0/failsafe"
  /devices/bulk:
    put:
      tags:
        - device
      summary: Bulk Update Devices
      description: ''
      operationId: bulkUpdateDevices
      responses:
        '200':
          description: successful operation
          content:
            application/json:
              schema:
                type: object
                properties:
                  updated:
                    type: array
                    description: Identities of devices that were changed
                    items:
                      type: string
                    example:
                      - '11:22:33:44:55:66'
                  count:
                    type: integer
                    description: Number of devices updated
                    example: 1
        '400':
          description: Invalid input
      requestBody:
        $ref: '#/components/requestBodies/BulkDeviceUpdate'
      security:
        - basicAuth: []
        - bearerAuth: []
      x-codeSamples:
        - lang: cURL
          label: CLI
          source: |
            curl -u "admin:pass" -X PUT \
              "http://192.168.2.1/devices/bulk" < bulk.json
  /topology:
    get:
      tags:
        - network
      summary: Get Topology
      description: ''
      operationId: getTopology
      responses:
        '200':
          description: successful operation
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Topology'
        '400':
          description: Invalid input
      security:
        - basicAuth: []
        - bearerAuth: []
      x-codeSamples:
        - lang: cURL
          label: CLI
          source: |
            curl -u "admin:pass" \
              "http://192.168.2.1/topology"
  /link/ip:
    put:
      tags:
        - link
      summary: Update LAN Link IP
      description: ''
      operationId: updateLanLinkIp
      responses:
        '200':
          description: successful operation
        '400':
          description: Invalid input
      requestBody:
        $ref: '#/components/requestBodies/LanLinkIPConfig'
      security:
        - basicAuth: []
        - bearerAuth: []
      x-codeSamples:
        - lang: cURL
          label: CLI
          source: |
            curl -u "admin:pass" -X PUT \
              "http://192.168.2.1/link/ip" < link.json
  /alerts_mobile_proxy:
    get:
      tags:
        - alerts
      summary: Get Mobile Alert Proxy Settings
      description: ''
      operationId: getAlertsMobileProxy
      responses:
        '200':
          description: successful operation
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/MobileAlertProxySettings'
        '400':
          description: Invalid input
      security:
        - basicAuth: []
        - bearerAuth: []
      x-codeSamples:
        - lang: cURL
          label: CLI
          source: |
            curl -u "admin:pass" \
              "http://192.168.2.1/alerts_mobile_proxy"
    put:
      tags:
        - alerts
      summary: Set Mobile Alert Proxy Settings
      description: ''
      operationId: setAlertsMobileProxy
      responses:
        '200':
          description: successful operation
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/MobileAlertProxySettings'
        '400':
          description: Invalid input
      requestBody:
        $ref: '#/components/requestBodies/MobileAlertProxySettings'
      security:
        - basicAuth: []
        - bearerAuth: []
      x-codeSamples:
        - lang: cURL
          label: CLI
          source: |
            curl -u "admin:pass" -X PUT \
              "http://192.168.2.1/alerts_mobile_proxy" < proxy.json
  /alerts_register_ios:
    get:
      tags:
        - alerts
      summary: Get Registered Alert Devices
      description: ''
      operationId: getAlertDevices
      responses:
        '200':
          description: successful operation
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: '#/components/schemas/AlertDevice'
        '400':
          description: Invalid input
      security:
        - basicAuth: []
        - bearerAuth: []
      x-codeSamples:
        - lang: cURL
          label: CLI
          source: |
            curl -u "admin:pass" \
              "http://192.168.2.1/alerts_register_ios"
    put:
      tags:
        - alerts
      summary: Register Alert Device
      description: ''
      operationId: registerAlertDevice
      responses:
        '200':
          description: successful operation
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: '#/components/schemas/AlertDevice'
        '400':
          description: Invalid input
      requestBody:
        $ref: '#/components/requestBodies/AlertDevice'
      security:
        - basicAuth: []
        - bearerAuth: []
      x-codeSamples:
        - lang: cURL
          label: CLI
          source: |
            curl -u "admin:pass" -X PUT \
              "http://192.168.2.1/alerts_register_ios" < alertdevice.json
    delete:
      tags:
        - alerts
      summary: Delete Alert Device
      description: ''
      operationId: deleteAlertDevice
      responses:
        '200':
          description: successful operation
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: '#/components/schemas/AlertDevice'
        '400':
          description: Invalid input
      requestBody:
        $ref: '#/components/requestBodies/AlertDevice'
      security:
        - basicAuth: []
        - bearerAuth: []
      x-codeSamples:
        - lang: cURL
          label: CLI
          source: |
            curl -u "admin:pass" -X DELETE \
              "http://192.168.2.1/alerts_register_ios" < alertdevice.json
  /alerts_test/{deviceToken}:
    put:
      tags:
        - alerts
      summary: Send Test Alert to Device
      description: ''
      operationId: testAlertDevice
      parameters:
        - name: deviceToken
          in: path
          description: APNS device token (64 hex characters)
          required: true
          schema:
            type: string
            example: aabbccddeeff00112233445566778899aabbccddeeff00112233445566778899
      responses:
        '200':
          description: successful operation
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/APNSAlert'
        '400':
          description: Invalid input
      requestBody:
        $ref: '#/components/requestBodies/APNSAlert'
      security:
        - basicAuth: []
        - bearerAuth: []
      x-codeSamples:
        - lang: cURL
          label: CLI
          source: |
            curl -u "admin:pass" -X PUT \
              "http://192.168.2.1/alerts_test/aabbccddeeff..." < alert.json
  /plugins/{name}/restart:
    put:
      tags:
        - plugins
      summary: Restart Plugin
      description: ''
      operationId: restartPlugin
      parameters:
        - name: name
          in: path
          description: Plugin name
          required: true
          schema:
            type: string
            example: dns-block
      responses:
        '200':
          description: successful operation
        '400':
          description: Invalid input
      security:
        - basicAuth: []
        - bearerAuth: []
      x-codeSamples:
        - lang: cURL
          label: CLI
          source: |
            curl -u "admin:pass" -X PUT \
              "http://192.168.2.1/plugins/dns-block/restart"
  /plugins/{name}/update_container:
    put:
      tags:
        - plugins
      summary: Update Plugin Container
      description: ''
      operationId: updatePluginContainer
      parameters:
        - name: name
          in: path
          description: Plugin name
          required: true
          schema:
            type: string
            example: dns-block
      responses:
        '200':
          description: successful operation
        '400':
          description: Invalid input
      security:
        - basicAuth: []
        - bearerAuth: []
      x-codeSamples:
        - lang: cURL
          label: CLI
          source: |
            curl -u "admin:pass" -X PUT \
              "http://192.168.2.1/plugins/dns-block/update_container"
  /plugin/complete_install:
    put:
      tags:
        - plugins
      summary: Complete User Plugin Install
      description: ''
      operationId: completePluginInstall
      responses:
        '200':
          description: successful operation
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: '#/components/schemas/PluginEntry'
        '400':
          description: Invalid input
      requestBody:
        $ref: '#/components/requestBodies/PluginEntry'
      security:
        - basicAuth: []
          OTPAuth: []
        - bearerAuth: []
          OTPAuth: []
      x-codeSamples:
        - lang: cURL
          label: CLI
          source: |
            curl -u "admin:pass" -X PUT -H "X-JWT-OTP:..." \
              "http://192.168.2.1/plugin/complete_install" < plugin.json
  /plugin/download_info:
    put:
      tags:
        - plugins
      summary: Download User Plugin Info
      description: ''
      operationId: downloadPluginInfo
      responses:
        '200':
          description: successful operation
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/PluginEntry'
        '400':
          description: Invalid input
      requestBody:
        $ref: '#/components/requestBodies/PluginGitURL'
      security:
        - basicAuth: []
          OTPAuth: []
        - bearerAuth: []
          OTPAuth: []
      x-codeSamples:
        - lang: cURL
          label: CLI
          source: |
            curl -u "admin:pass" -X PUT -H "X-JWT-OTP:..." \
              "http://192.168.2.1/plugin/download_info" < giturl.json
  /plusTokenValid:
    get:
      tags:
        - plus
      summary: Check Plus Token Validity
      description: ''
      operationId: getPlusTokenValid
      responses:
        '200':
          description: Plus token is valid
        '400':
          description: Plus token is empty or invalid
      security:
        - basicAuth: []
        - bearerAuth: []
      x-codeSamples:
        - lang: cURL
          label: CLI
          source: |
            curl -u "admin:pass" \
              "http://192.168.2.1/plusTokenValid"
  /cert/authorized:
    get:
      tags:
        - general
      summary: Get Authorized CA Certificate
      description: ''
      operationId: getAuthorizedCert
      responses:
        '200':
          description: successful operation
          content:
            application/x-x509-ca-cert:
              schema:
                type: string
                format: binary
        '400':
          description: Invalid input
      security:
        - basicAuth: []
        - bearerAuth: []
      x-codeSamples:
        - lang: cURL
          label: CLI
          source: |
            curl -u "admin:pass" \
              "http://192.168.2.1/cert/authorized"
  /parentalControls/personas:
    get:
      tags:
        - parentalcontrols
      summary: Get parental personas
      description: ''
      operationId: getParentalPersonas
      responses:
        '200':
          description: successful operation
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: '#/components/schemas/Persona'
        '400':
          description: Invalid request
      security:
        - basicAuth: []
        - bearerAuth: []
      x-codeSamples:
        - lang: cURL
          label: CLI
          source: |
            curl -u "admin:pass" \
              "http://192.168.2.1/parentalControls/personas"
    put:
      tags:
        - parentalcontrols
      summary: Create or update a parental persona
      description: ''
      operationId: modifyParentalPersonas
      responses:
        '200':
          description: successful operation
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: '#/components/schemas/Persona'
        '400':
          description: Invalid request
      requestBody:
        $ref: '#/components/requestBodies/Persona'
      security:
        - basicAuth: []
        - bearerAuth: []
      x-codeSamples:
        - lang: cURL
          label: CLI
          source: |
            curl -u "admin:pass" -X PUT \
              "http://192.168.2.1/parentalControls/personas" < persona.json
    delete:
      tags:
        - parentalcontrols
      summary: Delete a parental persona
      description: ''
      operationId: deleteParentalPersona
      responses:
        '200':
          description: successful operation
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: '#/components/schemas/Persona'
        '400':
          description: Invalid request
      requestBody:
        $ref: '#/components/requestBodies/Persona'
      security:
        - basicAuth: []
        - bearerAuth: []
      x-codeSamples:
        - lang: cURL
          label: CLI
          source: |
            curl -u "admin:pass" -X DELETE \
              "http://192.168.2.1/parentalControls/personas" < persona.json
  /parentalControls/usage:
    get:
      tags:
        - parentalcontrols
      summary: Get per-persona usage
      description: ''
      operationId: getParentalUsage
      responses:
        '200':
          description: successful operation
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/PersonasUsage'
        '400':
          description: Invalid request
      security:
        - basicAuth: []
        - bearerAuth: []
      x-codeSamples:
        - lang: cURL
          label: CLI
          source: |
            curl -u "admin:pass" \
              "http://192.168.2.1/parentalControls/usage"
  /parentalControls/pause:
    put:
      tags:
        - parentalcontrols
      summary: Pause a persona
      description: ''
      operationId: setParentalPause
      responses:
        '200':
          description: successful operation
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/PersonasState'
        '400':
          description: Invalid request
      requestBody:
        $ref: '#/components/requestBodies/ParentalControlRequest'
      security:
        - basicAuth: []
        - bearerAuth: []
      x-codeSamples:
        - lang: cURL
          label: CLI
          source: |
            curl -u "admin:pass" -X PUT \
              "http://192.168.2.1/parentalControls/pause" \
              -d '{"Tag": "persona:kids", "Minutes": 30}'
  /parentalControls/extend:
    put:
      tags:
        - parentalcontrols
      summary: Extend (grant) time for a persona
      description: ''
      operationId: setParentalExtend
      responses:
        '200':
          description: successful operation
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/PersonasState'
        '400':
          description: Invalid request
      requestBody:
        $ref: '#/components/requestBodies/ParentalControlRequest'
      security:
        - basicAuth: []
        - bearerAuth: []
      x-codeSamples:
        - lang: cURL
          label: CLI
          source: |
            curl -u "admin:pass" -X PUT \
              "http://192.168.2.1/parentalControls/extend" \
              -d '{"Tag": "persona:kids", "Minutes": 30}'
  /parentalControls/reset:
    put:
      tags:
        - parentalcontrols
      summary: Reset usage and overrides for a persona
      description: ''
      operationId: setParentalReset
      responses:
        '200':
          description: successful operation
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/PersonasState'
        '400':
          description: Invalid request
      requestBody:
        $ref: '#/components/requestBodies/ParentalResetRequest'
      security:
        - basicAuth: []
        - bearerAuth: []
      x-codeSamples:
        - lang: cURL
          label: CLI
          source: |
            curl -u "admin:pass" -X PUT \
              "http://192.168.2.1/parentalControls/reset" \
              -d '{"Tag": "persona:kids"}'
  /attestStatus:
    get:
      tags:
        - releases
      summary: Get attestation status
      description: ''
      operationId: getAttestStatus
      responses:
        '200':
          description: Attestation status passed through from superd
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/AttestStatus'
        '400':
          description: Failed to retrieve attestation status
      security:
        - basicAuth: []
        - bearerAuth: []
      x-codeSamples:
        - lang: cURL
          source: |
            curl -u "admin:pass" http://192.168.2.1/attestStatus
    put:
      tags:
        - releases
      summary: Refresh attestation status
      description: ''
      operationId: setAttestStatus
      responses:
        '200':
          description: Attestation status refreshed
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/AttestStatus'
        '400':
          description: Failed to refresh attestation status
      security:
        - basicAuth: []
        - bearerAuth: []
      x-codeSamples:
        - lang: cURL
          source: |
            curl -u "admin:pass" -X PUT http://192.168.2.1/attestStatus
  /autoupdate:
    get:
      tags:
        - releases
      summary: Get auto update setting
      description: ''
      operationId: getAutoUpdate
      responses:
        '200':
          description: Whether automatic updates are enabled
          content:
            application/json:
              schema:
                type: boolean
                example: false
        '400':
          description: Bad request
      security:
        - basicAuth: []
        - bearerAuth: []
      x-codeSamples:
        - lang: cURL
          source: |
            curl -u "admin:pass" http://192.168.2.1/autoupdate
    put:
      tags:
        - releases
      summary: Enable auto updates
      description: ''
      operationId: setAutoUpdate
      responses:
        '200':
          description: Automatic updates enabled
        '400':
          description: Bad request
      security:
        - basicAuth: []
        - bearerAuth: []
      x-codeSamples:
        - lang: cURL
          source: |
            curl -u "admin:pass" -X PUT http://192.168.2.1/autoupdate
    delete:
      tags:
        - releases
      summary: Disable auto updates
      description: ''
      operationId: deleteAutoUpdate
      responses:
        '200':
          description: Automatic updates disabled
        '400':
          description: Bad request
      security:
        - basicAuth: []
        - bearerAuth: []
      x-codeSamples:
        - lang: cURL
          source: |
            curl -u "admin:pass" -X DELETE http://192.168.2.1/autoupdate
  /checkupdates:
    get:
      tags:
        - releases
      summary: Get check-updates setting
      description: ''
      operationId: getCheckUpdates
      responses:
        '200':
          description: Whether update checking is enabled
          content:
            application/json:
              schema:
                type: boolean
                example: true
        '400':
          description: Bad request
      security:
        - basicAuth: []
        - bearerAuth: []
      x-codeSamples:
        - lang: cURL
          source: |
            curl -u "admin:pass" http://192.168.2.1/checkupdates
    put:
      tags:
        - releases
      summary: Enable update checks
      description: ''
      operationId: setCheckUpdates
      responses:
        '200':
          description: Update checking enabled
        '400':
          description: Bad request
      security:
        - basicAuth: []
        - bearerAuth: []
      x-codeSamples:
        - lang: cURL
          source: |
            curl -u "admin:pass" -X PUT http://192.168.2.1/checkupdates
    delete:
      tags:
        - releases
      summary: Disable update checks
      description: ''
      operationId: deleteCheckUpdates
      responses:
        '200':
          description: Update checking disabled
        '400':
          description: Bad request
      security:
        - basicAuth: []
        - bearerAuth: []
      x-codeSamples:
        - lang: cURL
          source: |
            curl -u "admin:pass" -X DELETE http://192.168.2.1/checkupdates
  /releaseSet:
    put:
      tags:
        - releases
      summary: Set release channel settings
      description: ''
      operationId: setReleaseSettings
      responses:
        '200':
          description: Release settings applied
        '400':
          description: Failed to decode or apply release settings
      requestBody:
        $ref: '#/components/requestBodies/setReleaseSettings'
      security:
        - basicAuth: []
          OTPAuth: []
        - bearerAuth: []
          OTPAuth: []
      x-codeSamples:
        - lang: cURL
          source: |
            curl -u "admin:pass" -X PUT http://192.168.2.1/releaseSet \
              -H "Content-Type: application/json" \
              -d '{"CustomChannel":"main","CustomVersion":"0.3.6","Current":"0.3.5"}'
    delete:
      tags:
        - releases
      summary: Clear release channel settings
      description: ''
      operationId: deleteReleaseSet
      responses:
        '200':
          description: Release settings cleared
        '400':
          description: Failed to clear release settings
      security:
        - basicAuth: []
          OTPAuth: []
        - bearerAuth: []
          OTPAuth: []
      x-codeSamples:
        - lang: cURL
          source: |
            curl -u "admin:pass" -X DELETE http://192.168.2.1/releaseSet
  /pluginAttest:
    get:
      tags:
        - plugins
      summary: Get plugin attestation
      description: ''
      operationId: getPluginAttest
      parameters:
        - name: compose_file
          in: query
          required: false
          description: >-
            Path to the plugin compose file to attest (compose_file or service
            required)
          schema:
            type: string
            example: /configs/plugins/mesh/docker-compose.yml
        - name: service
          in: query
          required: false
          description: Service name to attest (compose_file or service required)
          schema:
            type: string
            example: mesh
        - name: force
          in: query
          required: false
          description: Force re-attestation when set to a non-empty value
          schema:
            type: string
            example: '1'
      responses:
        '200':
          description: Plugin attestation result passed through from superd
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/PluginAttestStatus'
        '400':
          description: Missing parameters or failed to get plugin attestation
      security:
        - basicAuth: []
        - bearerAuth: []
      x-codeSamples:
        - lang: cURL
          source: |
            curl -u "admin:pass" "http://192.168.2.1/pluginAttest?service=mesh"
  /backup:
    get:
      tags:
        - general
      summary: List configuration backups
      description: ''
      operationId: getConfigsBackupList
      responses:
        '200':
          description: List of available configuration backup archives
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: '#/components/schemas/ConfigBackupEntry'
        '400':
          description: Failed to list backups
      security:
        - basicAuth: []
        - bearerAuth: []
      x-codeSamples:
        - lang: cURL
          source: |
            curl -u "admin:pass" http://192.168.2.1/backup
    put:
      tags:
        - general
      summary: Create a configuration backup
      description: ''
      operationId: createConfigsBackup
      responses:
        '200':
          description: Name of the created backup archive
          content:
            application/json:
              schema:
                type: string
                example: spr-configs-v0.3.5.tgz
        '400':
          description: Failed to create backup
      security:
        - basicAuth: []
        - bearerAuth: []
      x-codeSamples:
        - lang: cURL
          source: |
            curl -u "admin:pass" -X PUT http://192.168.2.1/backup
  /backup/{name}:
    get:
      tags:
        - general
      summary: Download a configuration backup
      description: ''
      operationId: downloadConfigsBackup
      parameters:
        - name: name
          in: path
          required: true
          description: Backup archive filename
          schema:
            type: string
            example: spr-configs-v0.3.5.tgz
      responses:
        '200':
          description: Backup archive file
          content:
            application/gzip:
              schema:
                type: string
                format: binary
        '400':
          description: Invalid config name
      security:
        - basicAuth: []
          OTPAuth: []
        - bearerAuth: []
          OTPAuth: []
      x-codeSamples:
        - lang: cURL
          source: >
            curl -u "admin:pass" -OJ
            http://192.168.2.1/backup/spr-configs-v0.3.5.tgz
    delete:
      tags:
        - general
      summary: Delete a configuration backup
      description: ''
      operationId: deleteConfigsBackup
      parameters:
        - name: name
          in: path
          required: true
          description: Backup archive filename
          schema:
            type: string
            example: spr-configs-v0.3.5.tgz
      responses:
        '200':
          description: Backup deleted
        '400':
          description: Invalid config name
      security:
        - basicAuth: []
          OTPAuth: []
        - bearerAuth: []
          OTPAuth: []
      x-codeSamples:
        - lang: cURL
          source: >
            curl -u "admin:pass" -X DELETE
            http://192.168.2.1/backup/spr-configs-v0.3.5.tgz
  /authorizedKeys:
    get:
      tags:
        - general
      summary: Get SSH authorized keys
      description: ''
      operationId: getAuthorizedKeys
      responses:
        '200':
          description: List of configured SSH authorized keys
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/AuthorizedKeys'
        '400':
          description: Bad request
      security:
        - basicAuth: []
        - bearerAuth: []
      x-codeSamples:
        - lang: cURL
          source: |
            curl -u "admin:pass" http://192.168.2.1/authorizedKeys
    put:
      tags:
        - general
      summary: Set SSH authorized keys
      description: ''
      operationId: setAuthorizedKeys
      responses:
        '200':
          description: Authorized keys stored
        '400':
          description: Bad request
      requestBody:
        $ref: '#/components/requestBodies/setAuthorizedKeys'
      security:
        - basicAuth: []
        - bearerAuth: []
      x-codeSamples:
        - lang: cURL
          source: |
            curl -u "admin:pass" -X PUT http://192.168.2.1/authorizedKeys \
              -H "Content-Type: application/json" \
              -d '["ssh-ed25519 AAAAC3Nza... user@host"]'
  /time:
    get:
      tags:
        - general
      summary: Get current server time
      description: ''
      operationId: getTime
      responses:
        '200':
          description: Current server time
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/TimeInfo'
        '400':
          description: Bad request
      security:
        - basicAuth: []
        - bearerAuth: []
      x-codeSamples:
        - lang: cURL
          source: |
            curl -u "admin:pass" http://192.168.2.1/time
  /time/sync:
    put:
      tags:
        - general
      summary: Sync system time
      description: ''
      operationId: syncTime
      responses:
        '200':
          description: Time sync triggered via superd
        '400':
          description: Failed to sync time
      security:
        - basicAuth: []
        - bearerAuth: []
      x-codeSamples:
        - lang: cURL
          source: |
            curl -u "admin:pass" -X PUT http://192.168.2.1/time/sync
  /info/{name}:
    get:
      tags:
        - general
      summary: Get system information
      description: ''
      operationId: getSystemInfo
      parameters:
        - name: name
          in: path
          required: true
          description: >-
            Info field to retrieve (uptime, dockernetworks, docker, hostname,
            ss)
          schema:
            type: string
            example: uptime
      responses:
        '200':
          description: Requested system information passed through as JSON
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/SystemInfo'
        '400':
          description: Invalid info name or failed to gather info
      security:
        - basicAuth: []
        - bearerAuth: []
      x-codeSamples:
        - lang: cURL
          source: |
            curl -u "admin:pass" http://192.168.2.1/info/uptime
    put:
      tags:
        - general
      summary: Set system information
      description: ''
      operationId: putSystemInfo
      parameters:
        - name: name
          in: path
          required: true
          description: Info field to set (currently only hostname is supported)
          schema:
            type: string
            example: hostname
      responses:
        '200':
          description: System information updated
        '400':
          description: Unsupported hostname or bad request
      requestBody:
        $ref: '#/components/requestBodies/putSystemInfo'
      security:
        - basicAuth: []
        - bearerAuth: []
      x-codeSamples:
        - lang: cURL
          source: |
            curl -u "admin:pass" -X PUT http://192.168.2.1/info/hostname \
              -H "Content-Type: application/json" \
              -d '"my-router"'
  /dockerPS:
    get:
      tags:
        - general
      summary: Get docker container status
      description: ''
      operationId: getDockerPS
      parameters:
        - name: service
          in: query
          required: false
          description: Service name to inspect
          schema:
            type: string
            example: mesh
        - name: compose_file
          in: query
          required: false
          description: Compose file path to inspect
          schema:
            type: string
            example: /configs/plugins/mesh/docker-compose.yml
      responses:
        '200':
          description: Raw docker ps output
          content:
            application/json:
              schema:
                type: string
                example: CONTAINER ID   IMAGE   STATUS
        '400':
          description: Bad request
        '404':
          description: Not found
      security:
        - basicAuth: []
        - bearerAuth: []
      x-codeSamples:
        - lang: cURL
          source: |
            curl -u "admin:pass" "http://192.168.2.1/dockerPS?service=mesh"
  /restart:
    put:
      tags:
        - general
      summary: Restart all containers
      description: ''
      operationId: restartService
      responses:
        '200':
          description: Restart of all containers triggered
        '400':
          description: Bad request
      security:
        - basicAuth: []
        - bearerAuth: []
      x-codeSamples:
        - lang: cURL
          source: |
            curl -u "admin:pass" -X PUT http://192.168.2.1/restart
  /nftables:
    get:
      tags:
        - network
      summary: List nftables tables
      description: ''
      operationId: listNFTables
      responses:
        '200':
          description: nftables tables in nft JSON format
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/NFTablesList'
        '400':
          description: nft failed to list tables
      security:
        - basicAuth: []
        - bearerAuth: []
      x-codeSamples:
        - lang: cURL
          source: |
            curl -u "admin:pass" http://192.168.2.1/nftables
  /nftable/{family}/{name}:
    get:
      tags:
        - network
      summary: Show an nftables table
      description: ''
      operationId: showNFTable
      parameters:
        - name: family
          in: path
          required: true
          description: nftables address family (e.g. ip, ip6, inet)
          schema:
            type: string
            example: inet
        - name: name
          in: path
          required: true
          description: nftables table name
          schema:
            type: string
            example: filter
      responses:
        '200':
          description: Table listing in nft text format
          content:
            text/plain:
              schema:
                type: string
                example: "table inet filter {\n\t# rules managed by nftables library\n}\n"
        '400':
          description: Bad request
        '404':
          description: Not found
      security:
        - basicAuth: []
        - bearerAuth: []
      x-codeSamples:
        - lang: cURL
          source: |
            curl -u "admin:pass" http://192.168.2.1/nftable/inet/filter
  /traffic_insights/config:
    get:
      tags:
        - traffic
      summary: Get Traffic Insights Configuration
      description: ''
      operationId: getTrafficInsightsConfig
      responses:
        '200':
          description: Current traffic insights configuration
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/TrafficInsightsConfig'
        '400':
          description: Bad request
      security:
        - basicAuth: []
        - bearerAuth: []
      x-codeSamples:
        - lang: cURL
          label: CLI
          source: |
            curl -u "admin:pass" \
              "http://192.168.2.1/traffic_insights/config"
    put:
      tags:
        - traffic
      summary: Update Traffic Insights Configuration
      description: ''
      operationId: updateTrafficInsightsConfig
      responses:
        '200':
          description: Updated traffic insights configuration
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/TrafficInsightsConfig'
        '400':
          description: Invalid configuration (RetentionDays must be 1-90)
      requestBody:
        $ref: '#/components/requestBodies/TrafficInsightsConfig'
      security:
        - basicAuth: []
        - bearerAuth: []
      x-codeSamples:
        - lang: cURL
          label: CLI
          source: |
            curl -u "admin:pass" -X PUT \
              -d '{"Enabled": true, "RetentionDays": 7}' \
              "http://192.168.2.1/traffic_insights/config"
  /traffic_insights/overview:
    get:
      tags:
        - traffic
      summary: Get Traffic Insights Overview
      description: ''
      operationId: getTrafficInsightsOverview
      parameters:
        - name: minutes
          in: query
          description: Length of the lookback window in minutes (defaults to 1440)
          required: false
          schema:
            type: integer
            example: 1440
      responses:
        '200':
          description: Aggregated traffic overview grouped by country and ASN
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/InsightOverview'
        '400':
          description: Bad request
      security:
        - basicAuth: []
        - bearerAuth: []
      x-codeSamples:
        - lang: cURL
          label: CLI
          source: |
            curl -u "admin:pass" \
              "http://192.168.2.1/traffic_insights/overview?minutes=1440"
  /traffic_insights/device/{ip}:
    get:
      tags:
        - traffic
      summary: Get Traffic Insights for a Device
      description: ''
      operationId: getTrafficInsightsDevice
      parameters:
        - name: ip
          in: path
          description: IP address of the local device to report on
          required: true
          schema:
            type: string
            example: 192.168.2.20
        - name: minutes
          in: query
          description: Length of the lookback window in minutes (defaults to 1440)
          required: false
          schema:
            type: integer
            example: 1440
      responses:
        '200':
          description: Per-device destination breakdown
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/InsightDevice'
        '400':
          description: Invalid ip
      security:
        - basicAuth: []
        - bearerAuth: []
      x-codeSamples:
        - lang: cURL
          label: CLI
          source: |
            curl -u "admin:pass" \
              "http://192.168.2.1/traffic_insights/device/192.168.2.20?minutes=1440"
  /customThemes:
    get:
      tags:
        - themes
      summary: Get Custom Themes
      description: ''
      operationId: getCustomThemes
      responses:
        '200':
          description: Array of stored custom themes
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/CustomThemeList'
        '400':
          description: Bad request
      security:
        - basicAuth: []
        - bearerAuth: []
      x-codeSamples:
        - lang: cURL
          label: CLI
          source: |
            curl -u "admin:pass" \
              "http://192.168.2.1/customThemes"
    put:
      tags:
        - themes
      summary: Update Custom Themes
      description: ''
      operationId: updateCustomThemes
      responses:
        '200':
          description: The stored array of custom themes
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/CustomThemeList'
        '400':
          description: >-
            Invalid themes (bad id, name, colorMode, hex colors, or too many
            themes)
      requestBody:
        $ref: '#/components/requestBodies/CustomThemeList'
      security:
        - basicAuth: []
        - bearerAuth: []
      x-codeSamples:
        - lang: cURL
          label: CLI
          source: |
            curl -u "admin:pass" -X PUT \
              -d '[{"id": "custom-ocean", "name": "Ocean", "spec": {"colorMode": "dark", "accent": "#3b82f6", "background": "#0b1220", "card": "#111827", "text": "#e5e7eb"}}]' \
              "http://192.168.2.1/customThemes"
  /wan/status:
    get:
      tags:
        - wan
      summary: Get WAN Status
      description: ''
      operationId: getWanStatus
      responses:
        '200':
          description: successful operation
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: '#/components/schemas/WanUplinkStatus'
        '400':
          description: Invalid request
      security:
        - basicAuth: []
        - bearerAuth: []
      x-codeSamples:
        - lang: cURL
          label: CLI
          source: |
            curl -u "admin:pass" \
              "http://192.168.2.1/wan/status"
  /wan/config:
    get:
      tags:
        - wan
      summary: Get WAN Health Config
      description: ''
      operationId: getWanHealthConfig
      responses:
        '200':
          description: successful operation
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/WanHealthConfig'
        '400':
          description: Invalid request
      security:
        - basicAuth: []
        - bearerAuth: []
      x-codeSamples:
        - lang: cURL
          label: CLI
          source: |
            curl -u "admin:pass" \
              "http://192.168.2.1/wan/config"
    put:
      tags:
        - wan
      summary: Update WAN Health Config
      description: ''
      operationId: updateWanHealthConfig
      responses:
        '200':
          description: successful operation
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/WanHealthConfig'
        '400':
          description: Invalid request
      requestBody:
        $ref: '#/components/requestBodies/WanHealthConfig'
      security:
        - basicAuth: []
        - bearerAuth: []
      x-codeSamples:
        - lang: cURL
          label: CLI
          source: |
            curl -u "admin:pass" -X PUT \
              "http://192.168.2.1/wan/config" < wan_config.json
  /wan/history/{interface}:
    get:
      tags:
        - wan
      summary: Get WAN History
      description: ''
      operationId: getWanHistory
      parameters:
        - name: interface
          in: path
          description: Uplink interface name
          required: true
          schema:
            type: string
            example: eth0
        - name: scale
          in: query
          description: Sample resolution, either minutes or hours
          required: false
          schema:
            type: string
            example: minutes
        - name: count
          in: query
          description: Maximum number of samples to return
          required: false
          schema:
            type: integer
            example: 60
      responses:
        '200':
          description: successful operation
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: '#/components/schemas/WanSample'
        '400':
          description: Invalid interface name, scale, or count
      security:
        - basicAuth: []
        - bearerAuth: []
      x-codeSamples:
        - lang: cURL
          label: CLI
          source: |
            curl -u "admin:pass" \
              "http://192.168.2.1/wan/history/eth0?scale=minutes&count=60"
  /wan/outages:
    get:
      tags:
        - wan
      summary: Get WAN Outages
      description: ''
      operationId: getWanOutages
      responses:
        '200':
          description: successful operation
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: '#/components/schemas/WanOutage'
        '400':
          description: Invalid request
      security:
        - basicAuth: []
        - bearerAuth: []
      x-codeSamples:
        - lang: cURL
          label: CLI
          source: |
            curl -u "admin:pass" \
              "http://192.168.2.1/wan/outages"
  /wan/speedtest:
    get:
      tags:
        - wan
      summary: Get WAN Speed Results
      description: ''
      operationId: getWanSpeedResults
      responses:
        '200':
          description: successful operation
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: '#/components/schemas/WanSpeedResult'
        '400':
          description: Invalid request
      security:
        - basicAuth: []
        - bearerAuth: []
      x-codeSamples:
        - lang: cURL
          label: CLI
          source: |
            curl -u "admin:pass" \
              "http://192.168.2.1/wan/speedtest"
  /wan/speedtest/{interface}:
    put:
      tags:
        - wan
      summary: Run WAN Speed Test
      description: ''
      operationId: runWanSpeedTest
      parameters:
        - name: interface
          in: path
          description: Uplink interface name to test
          required: true
          schema:
            type: string
            example: eth0
      responses:
        '200':
          description: successful operation
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/WanSpeedResult'
        '400':
          description: Invalid interface, not an enabled uplink, or monitoring disabled
      security:
        - basicAuth: []
        - bearerAuth: []
      x-codeSamples:
        - lang: cURL
          label: CLI
          source: |
            curl -u "admin:pass" -X PUT \
              "http://192.168.2.1/wan/speedtest/eth0"
  /plugins/mesh/config:
    get:
      summary: Get mesh configuration
      description: Retrieves the current mesh network configuration
      operationId: getMeshConfig
      tags:
        - mesh-common
      responses:
        '200':
          description: Successful response
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/MeshConfig'
      security:
        - basicAuth: []
        - bearerAuth: []
      x-codeSamples:
        - lang: cURL
          label: CLI
          source: |
            curl -u "admin:pass" \
              "http://192.168.2.1/plugins/mesh/config"
  /plugins/mesh/leafMode/{enable}:
    put:
      summary: Set leaf mode
      description: Enable or disable leaf mode for the mesh node
      operationId: setLeafMode
      tags:
        - mesh-node
      parameters:
        - name: enable
          in: path
          required: true
          schema:
            type: string
            enum:
              - enable
              - disable
      responses:
        '200':
          description: Successful response
        '400':
          description: Invalid enable parameter
      security:
        - basicAuth: []
        - bearerAuth: []
      x-codeSamples:
        - lang: cURL
          label: CLI
          source: |
            curl -u "admin:pass" -X PUT \
              "http://192.168.2.1/plugins/mesh/leafMode/enable"
  /plugins/mesh/leafMode:
    get:
      summary: Get leaf mode status
      description: Retrieves the current status of leaf mode
      operationId: getLeafModeStatus
      tags:
        - mesh-common
      responses:
        '200':
          description: Successful response
          content:
            application/json:
              schema:
                type: boolean
      security:
        - basicAuth: []
        - bearerAuth: []
      x-codeSamples:
        - lang: cURL
          label: CLI
          source: |
            curl -u "admin:pass" \
              "http://192.168.2.1/plugins/mesh/leafMode"
  /plugins/mesh/leafRouters:
    get:
      summary: Get list of leaf routers
      description: Retrieves a list of all leaf routers the main router has configured
      operationId: getLeafRouters
      tags:
        - mesh-parent
      responses:
        '200':
          description: Successful response
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: '#/components/schemas/LeafRouter'
      security:
        - basicAuth: []
        - bearerAuth: []
      x-codeSamples:
        - lang: cURL
          label: CLI
          source: |
            curl -u "admin:pass" \
              "http://192.168.2.1/plugins/mesh/leafRouters"
  /plugins/mesh/leafRouter:
    put:
      summary: Add or update a leaf router
      description: Adds a new leaf router or updates an existing one
      operationId: updateLeafRouter
      tags:
        - mesh-parent
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/LeafRouter'
      responses:
        '200':
          description: Successful response
        '400':
          description: Invalid request
      security:
        - basicAuth: []
        - bearerAuth: []
      x-codeSamples:
        - lang: cURL
          label: CLI
          source: |
            curl -u "admin:pass" -X PUT \
              "http://192.168.2.1/plugins/mesh/leafRouter" \
              -H "Content-Type: application/json" \
              -d '{"APIToken": "token123", "IP": "192.168.1.2"}'
    delete:
      summary: Remove a leaf router
      description: Removes a leaf router from the main router's mesh network
      operationId: deleteLeafRouter
      tags:
        - mesh-parent
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/LeafRouter'
      responses:
        '200':
          description: Successful response
        '400':
          description: Invalid request
      security:
        - basicAuth: []
        - bearerAuth: []
      x-codeSamples:
        - lang: cURL
          label: CLI
          source: |
            curl -u "admin:pass" -X DELETE \
              "http://192.168.2.1/plugins/mesh/leafRouter" \
              -H "Content-Type: application/json" \
              -d '{"IP": "192.168.1.2"}'
  /plugins/mesh/stationConnect:
    put:
      summary: Mesh node reports station connection
      description: >-
        Endpoint for mesh nodes to notify the main router/AP about a new station
        connection to the mesh network
      operationId: reportStationConnect
      tags:
        - mesh-parent
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/WifiConnectEvent'
      responses:
        '200':
          description: Successful response
        '400':
          description: Invalid request
      security:
        - basicAuth: []
        - bearerAuth: []
      x-codeSamples:
        - lang: cURL
          label: CLI
          source: |
            curl -u "admin:pass" -X PUT \
              "http://192.168.2.1/plugins/mesh/stationConnect" \
              -H "Content-Type: application/json" \
              -d '{"Event": "connect", "Iface": "wlan0", "Mac": "00:11:22:33:44:55", "Router": "192.168.1.1"}'
  /plugins/mesh/stationConnectFailure:
    put:
      summary: Mesh node reports station connection failure
      description: >-
        Endpoint for mesh nodes to notify the main router/AP about a failed
        station connection attempt
      operationId: reportStationConnectFailure
      tags:
        - mesh-parent
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/WifiConnectFailureEvent'
      responses:
        '200':
          description: Successful response
        '400':
          description: Invalid request
      security:
        - basicAuth: []
        - bearerAuth: []
      x-codeSamples:
        - lang: cURL
          label: CLI
          source: |
            curl -u "admin:pass" -X PUT \
              "http://192.168.2.1/plugins/mesh/stationConnectFailure" \
              -H "Content-Type: application/json" \
              -d '{"Type": "connection_failure", "MAC": "00:11:22:33:44:55", "Reason": "auth_timeout", "Status": "failure", "Router": "192.168.1.1"}'
  /plugins/mesh/stationDisconnect:
    put:
      summary: Mesh node reports station disconnection
      description: >-
        Endpoint for mesh nodes to notify the main router/AP about a station
        disconnection from the mesh network
      operationId: reportStationDisconnect
      tags:
        - mesh-parent
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/WifiConnectEvent'
      responses:
        '200':
          description: Successful response
        '400':
          description: Invalid request
      security:
        - basicAuth: []
        - bearerAuth: []
      x-codeSamples:
        - lang: cURL
          label: CLI
          source: |
            curl -u "admin:pass" -X PUT \
              "http://192.168.2.1/plugins/mesh/stationDisconnect" \
              -H "Content-Type: application/json" \
              -d '{"Event": "disconnect", "Iface": "wlan0", "Mac": "00:11:22:33:44:55", "Router": "192.168.1.1"}'
  /plugins/mesh/syncDevices:
    put:
      summary: Synchronize devices
      description: >-
        Mesh nodes handle this request when the main AP/Router sends down the
        devices listing
      operationId: syncDevices
      tags:
        - mesh-node
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              additionalProperties:
                $ref: '#/components/schemas/DeviceEntry'
      responses:
        '200':
          description: Successful response
        '400':
          description: Invalid request
      security:
        - basicAuth: []
        - bearerAuth: []
      x-codeSamples:
        - lang: cURL
          label: CLI
          source: |
            curl -u "admin:pass" -X PUT \
              "http://192.168.2.1/plugins/mesh/syncDevices" \
              -H "Content-Type: application/json" \
              -d '{"device1": {"Name": "Device1", "MAC": "00:11:22:33:44:55", "WGPubKey": "pubkey123", "VLANTag": "100", "RecentIP": "192.168.1.10", "PSKEntry": {"Type": "wpa2", "Psk": "password123"}, "Groups": ["group1"], "DeviceTags": ["tag1"]}}'
  /plugins/mesh/setSSID:
    put:
      summary: Set SSID
      description: The main router uses this call to set the SSID on mesh nodes
      operationId: setSSID
      tags:
        - mesh-node
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: string
      responses:
        '200':
          description: Successful response
        '400':
          description: Invalid request
      security:
        - basicAuth: []
        - bearerAuth: []
      x-codeSamples:
        - lang: cURL
          label: CLI
          source: |
            curl -u "admin:pass" -X PUT \
              "http://192.168.2.1/plugins/mesh/setSSID" \
              -H "Content-Type: application/json" \
              -d '"MyMeshNetwork"'
  /plugins/mesh/setOTP:
    put:
      summary: Set OTP settings
      description: >-
        The main router uses this call to sync the OTP login code on the mesh
        nodes
      operationId: setOTPSettings
      tags:
        - mesh-node
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/OTPSettingsRequest'
      responses:
        '200':
          description: Successful response
        '400':
          description: Invalid request
      security:
        - basicAuth: []
        - bearerAuth: []
      x-codeSamples:
        - lang: cURL
          label: CLI
          source: |
            curl -u "admin:pass" -X PUT \
              "http://192.168.2.1/plugins/mesh/setOTP" \
              -H "Content-Type: application/json" \
              -d '{"Token": "token123", "Settings": {"OTPUsers": [{"Name": "user1", "Secret": "secret123", "Confirmed": true, "AlwaysOn": false}], "JWTDurationSeconds": 3600}}'
  /plugins/mesh/syncOTP:
    put:
      summary: Synchronize OTP settings
      description: Tells the main router to sync the OTP code on the mesh nodes
      operationId: syncOTPSettings
      tags:
        - mesh-parent
      responses:
        '200':
          description: Successful response
      security:
        - basicAuth: []
        - bearerAuth: []
      x-codeSamples:
        - lang: cURL
          label: CLI
          source: |
            curl -u "admin:pass" -X PUT \
              "http://192.168.2.1/plugins/mesh/syncOTP"
  /plugins/mesh/setParentCredentials:
    put:
      summary: Set parent credentials
      description: >-
        Sets the credentials for the parent node in the mesh network, used for
        informing the parent about connection events
      operationId: setParentCredentials
      tags:
        - mesh-node
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/ParentCredentials'
      responses:
        '200':
          description: Successful response
        '400':
          description: Invalid request
      security:
        - basicAuth: []
        - bearerAuth: []
      x-codeSamples:
        - lang: cURL
          label: CLI
          source: |
            curl -u "admin:pass" -X PUT \
              "http://192.168.2.1/plugins/mesh/setParentCredentials" \
              -H "Content-Type: application/json" \
              -d '{"ParentIP": "192.168.1.1", "ParentAPIToken": "token123", "ParentCA": "-----BEGIN CERTIFICATE-----..."}'
    delete:
      summary: Remove parent credentials
      description: Removes the credentials for the parent node from the mesh node
      operationId: removeParentCredentials
      tags:
        - mesh-node
      responses:
        '200':
          description: Successful response
      security:
        - basicAuth: []
        - bearerAuth: []
      x-codeSamples:
        - lang: cURL
          label: CLI
          source: |
            curl -u "admin:pass" -X DELETE \
              "http://192.168.2.1/plugins/mesh/setParentCredentials"
  /plugins/mesh/cert:
    get:
      summary: Get mesh TLS certificate
      description: >
        Retrieves the TLS certificate for the mesh network.

        This endpoint implements HMAC Authentication using the mesh node's API
        key.
      operationId: getMeshCertificate
      tags:
        - mesh-node
      parameters:
        - in: header
          name: X-SPR-Mesh-TLS-Hash
          schema:
            type: string
          required: false
          description: >
            HMAC signature of the certificate file contents, using the Mesh's
            API Key.

            This header is used to verify the integrity and authenticity of the
            certificate.

            The client should validate this HMAC to ensure the certificate
            hasn't been tampered with.
      responses:
        '200':
          description: Successful response
          content:
            application/x-x509-ca-cert:
              schema:
                type: string
                format: binary
      security:
        - basicAuth: []
        - bearerAuth: []
      x-codeSamples:
        - lang: cURL
          label: CLI
          source: |
            curl -u "admin:pass" \
              "http://192.168.2.1/plugins/mesh/cert
  /plugins/dns/block/config:
    get:
      tags:
        - dnsblock
      summary: Retrieve coredns-block config
      description: Returns coredns-block config
      operationId: showConfig
      responses:
        '200':
          description: successful operation
          content:
            application/json:
              schema:
                type: string
                example: config
      security:
        - basicAuth: []
        - bearerAuth: []
      x-codeSamples:
        - lang: cURL
          label: CLI
          source: |
            curl -u "admin:pass" \
              "http://192.168.2.1/plugins/dns/block/config"
  /plugins/dns/block/override:
    put:
      tags:
        - dnsblock
      summary: Add override domain
      description: Add domain to be blocked/permitted by DNS
      operationId: addBlockDomains
      requestBody:
        $ref: '#/components/requestBodies/DNSDomainOverride'
      responses:
        '200':
          description: successful operation
      security:
        - basicAuth: []
        - bearerAuth: []
      x-codeSamples:
        - lang: cURL
          label: CLI
          source: |
            curl -u "admin:pass" -X PUT  \
              "http://192.168.2.1/plugins/dns/block/override" \
              --data '{"Type": "Permit", "Domain": "example.com.", "ResultIP": "1.1.1.1", "ClientIP": "*", "Expiration": 0}'
    delete:
      tags:
        - dnsblock
      summary: Delete override domain
      description: Delete domain to be blocked/permitted by DNS
      operationId: deleteBlockDomains
      requestBody:
        $ref: '#/components/requestBodies/DNSDomainOverride'
      responses:
        '200':
          description: successful operation
      security:
        - basicAuth: []
        - bearerAuth: []
      x-codeSamples:
        - lang: cURL
          label: CLI
          source: |
            curl -u "admin:pass" -X DELETE  \
              "http://192.168.2.1/plugins/dns/block/override" \
              --data '{"Domain": "example.com.", "Type": "Permit"}'
  /plugins/dns/block/blocklist:
    get:
      tags:
        - dnsblock
      summary: Retrieve blocklists
      description: Returns blocklist URIs
      operationId: showDNSBlocklist
      responses:
        '200':
          description: successful operation
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: '#/components/schemas/DNSListEntry'
      security:
        - basicAuth: []
        - bearerAuth: []
      x-codeSamples:
        - lang: cURL
          label: CLI
          source: |
            curl -u "admin:pass" \
              "http://192.168.2.1/plugins/dns/block/blocklist"
    put:
      tags:
        - dnsblock
      summary: Add blocklist
      description: Add blocklist entry
      operationId: addDNSBlocklist
      requestBody:
        $ref: '#/components/requestBodies/DNSListEntry'
      responses:
        '200':
          description: successful operation
      security:
        - basicAuth: []
        - bearerAuth: []
      x-codeSamples:
        - lang: cURL
          label: CLI
          source: |
            curl -u "admin:pass" -X PUT  \
              "http://192.168.2.1/plugins/dns/block/blocklist" \
              --data '{"URI": "http://asdf.com", "Enabled": true}'
    delete:
      tags:
        - dnsblock
      summary: Delete blocklist entry
      description: Delete a blocklist entry
      operationId: deleteDNSBlocklist
      requestBody:
        $ref: '#/components/requestBodies/DNSListEntry'
      responses:
        '200':
          description: successful operation
      security:
        - basicAuth: []
        - bearerAuth: []
      x-codeSamples:
        - lang: cURL
          label: CLI
          source: |
            curl -u "admin:pass" -X DELETE  \
              "http://192.168.2.1/plugins/dns/block/blocklist" \
              --data '{"URI": "http://asdf.com"}'
  /plugins/dns/block/exclusions:
    get:
      tags:
        - dnsblock
      summary: Retrieve IPs excluded from blocking
      description: Returns IPs excluded from DNS block
      operationId: showDNSExclusions
      responses:
        '200':
          description: successful operation
          content:
            application/json:
              schema:
                type: array
                items:
                  type: string
                example:
                  - 192.168.2.102
                  - 192.168.2.112
      security:
        - basicAuth: []
        - bearerAuth: []
      x-codeSamples:
        - lang: cURL
          label: CLI
          source: |
            curl -u "admin:pass" \
              "http://192.168.2.1/plugins/dns/block/exclusions"
    put:
      tags:
        - dnsblock
      summary: Add IP to exclude
      description: Add IP address to exclusion list
      operationId: addDNSExclusion
      requestBody:
        content:
          application/json:
            schema:
              type: string
              description: ip to exclude
              example: 192.168.2.102
      responses:
        '200':
          description: successful operation
      security:
        - basicAuth: []
        - bearerAuth: []
      x-codeSamples:
        - lang: cURL
          label: CLI
          source: |
            curl -u "admin:pass" -X PUT  \
              "http://192.168.2.1/plugins/dns/block/exclusions" \
              --data '"192.168.2.102"'
    delete:
      tags:
        - dnsblock
      summary: Delete IP from exclusion list
      description: Delete IP address from exclusion list
      operationId: deleteDNSExclusion
      requestBody:
        content:
          application/json:
            schema:
              type: string
              description: ip to delete exclude for
              example: 192.168.2.102
      responses:
        '200':
          description: successful operation
      security:
        - basicAuth: []
        - bearerAuth: []
      x-codeSamples:
        - lang: cURL
          label: CLI
          source: |
            curl -u "admin:pass" -X DELETE  \
              "http://192.168.2.1/plugins/dns/block/exclusions" \
              --data '"192.168.2.102"'
  /plugins/dns/block/dump_domains:
    get:
      tags:
        - dnsblock
      summary: Dump all domains loaded from block lists
      description: Returns aggregate list of all block domains
      operationId: dumpDNSEntries
      responses:
        '200':
          description: successful operation
          content:
            application/json:
              schema:
                type: array
                items:
                  type: string
                example:
                  - asdf.com
                  - example.com
      security:
        - basicAuth: []
        - bearerAuth: []
      x-codeSamples:
        - lang: cURL
          label: CLI
          source: >
            curl -u "admin:pass"
            "http://192.168.2.1/plugins/dns/block/dump_domains"
  /plugins/dns/block/metrics:
    get:
      tags:
        - dnsblock
      summary: Get metrics
      description: Returns metrics for DNS block
      operationId: getDNSMetrics
      responses:
        '200':
          description: successful operation
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/DNSBlockMetrics'
      security:
        - basicAuth: []
        - bearerAuth: []
      x-codeSamples:
        - lang: cURL
          label: CLI
          source: |
            curl -u "admin:pass" \
              "http://192.168.2.1/plugins/dns/block/metrics"
  /plugins/dns/log/config:
    get:
      tags:
        - dnslog
      summary: Retrieve coredns-jsonlog configuration
      operationId: showDnsLogConfig
      responses:
        '200':
          description: successful operation
          content:
            application/json:
              schema:
                example:
                  - HostPrivacyIPList:
                      - 192.168.1.10
                  - DomainIgnoreList:
                      - asdf.com
                      - asdf2.com
                      - test.com.
      security:
        - basicAuth: []
        - bearerAuth: []
      x-codeSamples:
        - lang: cURL
          label: CLI
          source: |
            curl -u "admin:pass" \
              "http://192.168.2.1/plugins/dns/log/config"
  /plugins/dns/log/host_privacy_list:
    get:
      tags:
        - dnslog
      summary: Retrieve list of privacy hosts
      description: List of hosts to exclude from DNS Log
      operationId: showHostPrivacyList
      responses:
        '200':
          description: successful operation
          content:
            application/json:
              schema:
                type: string
                example:
                  - 192.168.1.10
      security:
        - basicAuth: []
        - bearerAuth: []
      x-codeSamples:
        - lang: cURL
          label: CLI
          source: |
            curl -u "admin:pass" \
              "http://192.168.2.1/plugins/dns/log/host_privacy_list"
    put:
      tags:
        - dnslog
      summary: Set the list of privacy hosts
      operationId: setHostPrivacyList
      requestBody:
        content:
          application/json:
            schema:
              type: array
              items:
                type: string
      responses:
        '200':
          description: successful operation
      security:
        - basicAuth: []
        - bearerAuth: []
      x-codeSamples:
        - lang: cURL
          label: CLI
          source: |
            curl -u "admin:pass" -X PUT  \
              "http://192.168.2.1/plugins/dns/log/host_privacy_list" \
              --data '["192.168.1.10", "192.168.1.14"]'
  /plugins/dns/log/domain_ignores:
    get:
      tags:
        - dnslog
      summary: Retrieve list of domains to exclude from logging
      operationId: getDomainIgnores
      responses:
        '200':
          description: successful operation
          content:
            application/json:
              schema:
                type: string
                example:
                  - localhost
      security:
        - basicAuth: []
        - bearerAuth: []
      x-codeSamples:
        - lang: cURL
          label: CLI
          source: |
            curl -u "admin:pass" \
              "http://192.168.2.1/plugins/dns/log/domain_ignores"
  /plugins/dns/log/domain_ignore/{domain}:
    put:
      tags:
        - dnslog
      summary: Add domain to exclude from logs
      operationId: addDomainIgnore
      responses:
        '200':
          description: successful operation
          content:
            application/json:
              schema:
                type: array
                items:
                  type: object
      security:
        - basicAuth: []
        - bearerAuth: []
      parameters:
        - name: domain
          in: path
          description: domain name
          required: true
          schema:
            type: string
      x-codeSamples:
        - lang: cURL
          label: CLI
          source: |
            curl -u "admin:pass" -X PUT \
              "http://192.168.2.1/plugins/dns/log/domain_ignore/example.com"
    delete:
      tags:
        - dnslog
      summary: Remove domain from exclude list
      operationId: deleteDomainIgnore
      responses:
        '200':
          description: successful operation
          content:
            application/json:
              schema:
                type: array
                items:
                  type: string
      security:
        - basicAuth: []
        - bearerAuth: []
      parameters:
        - name: domain
          in: path
          description: domain name
          required: true
          schema:
            type: string
      x-codeSamples:
        - lang: cURL
          label: CLI
          source: |
            curl -u "admin:pass" -X DELETE \
              "http://192.168.2.1/plugins/dns/log/domain_ignore/example.com"
  /plugins/dns/log/history/{ip}:
    get:
      tags:
        - dnslog
      summary: Retrieve recent DNS history for a given IP
      operationId: getDNSHistory
      parameters:
        - name: ip
          in: path
          description: ip address
          required: true
          schema:
            type: string
            example: 1.1.1.1
      responses:
        '200':
          description: successful operation
          content:
            application/json:
              schema:
                type: array
                items:
                  type: object
                example:
                  - Q:
                      - Name: supernetworks.org.
                        Qtype: 1
                        Qclass: 1
                    A:
                      - Hdr:
                          Name: supernetworks.org.
                          Rrtype: 1
                          Class: 1
                          Ttl: 30
                          Rdlength: 4
                        A: 172.67.71.52
                      - Hdr:
                          Name: supernetworks.org.
                          Rrtype: 1
                          Class: 1
                          Ttl: 30
                          Rdlength: 4
                        A: 104.26.7.38
                      - Hdr:
                          Name: supernetworks.org.
                          Rrtype: 1
                          Class: 1
                          Ttl: 30
                          Rdlength: 4
                        A: 104.26.6.38
                    Type: NOERROR
                    FirstName: supernetworks.org.
                    FirstAnswer: 172.67.71.52
                    Local: '[::]:53'
                    Remote: 127.0.0.1:60237
                    Timestamp: '2022-03-28T21:47:49.563958-07:00'
      security:
        - basicAuth: []
        - bearerAuth: []
      x-codeSamples:
        - lang: cURL
          label: CLI
          source: |
            curl -u "admin:pass" \
              "http://192.168.2.1/plugins/dns/log/history/192.168.1.10"
    delete:
      tags:
        - dnslog
      summary: Delete Device History by IP
      description: Delete device history in the IP parameter
      operationId: deleteDNSHistory
      parameters:
        - name: ip
          in: path
          description: ip address
          required: true
          schema:
            type: string
            example: 1.1.1.1
      responses:
        '200':
          description: successful operation
      security:
        - basicAuth: []
        - bearerAuth: []
      x-codeSamples:
        - lang: cURL
          label: CLI
          source: |
            curl -u "admin:pass" -X DELETE \
              "http://192.168.2.1/plugins/dns/log/history/192.168.1.10"
  /plugins/lookup/asn/{ips}:
    get:
      tags:
        - lookup
      summary: IP ASN
      description: Get ASN information for IP address
      operationId: lookupASNIPs
      parameters:
        - name: ips
          in: path
          description: ip address list, separated by ,
          required: true
          schema:
            type: string
            example: 1.1.1.1,2.2.2.2
      responses:
        '200':
          description: successful operation
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/LookupASN'
      security:
        - basicAuth: []
        - bearerAuth: []
      x-codeSamples:
        - lang: cURL
          label: CLI
          source: |
            curl -u "admin:pass" \
              "http://192.168.2.1/plugins/lookup/asn/1.1.1.1"
  /plugins/lookup/asns/{ips}:
    get:
      tags:
        - lookup
      summary: IPs ASN
      description: Get ASN information for IPs separated by ,
      operationId: lookupASNsIPs
      parameters:
        - name: ips
          in: path
          description: ip address list, separated by ,
          required: true
          schema:
            type: string
            example: 1.1.1.1,2.2.2.2
      responses:
        '200':
          description: successful operation
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: '#/components/schemas/LookupASN'
      security:
        - basicAuth: []
        - bearerAuth: []
      x-codeSamples:
        - lang: cURL
          label: CLI
          source: |
            curl -u "admin:pass" \
              "http://192.168.2.1/plugins/lookup/asns/1.1.1.1,8.8.8.8"
  /plugins/lookup/oui/{mac}:
    get:
      tags:
        - lookup
      summary: MAC OUI
      description: Get OUI vendor information for MAC address
      operationId: lookupOUI
      parameters:
        - name: mac
          in: path
          description: MAC address
          required: true
          schema:
            type: string
            example: '11:22:33:44:55:66'
      responses:
        '200':
          description: successful operation
          content:
            application/json:
              schema:
                type: object
                example:
                  MAC: '00:11:22:33:44:66'
                  Vendor: CIMSYS
      security:
        - basicAuth: []
        - bearerAuth: []
      x-codeSamples:
        - lang: cURL
          label: CLI
          source: |
            curl -u "admin:pass" \
              "http://192.168.2.1/plugins/lookup/oui/00:11:22:33:44:55"
  /plugins/lookup/ouis/{macs}:
    get:
      tags:
        - lookup
      summary: MACs OUI
      description: Get OUI vendor information for MACs separated by ,
      operationId: lookupOUIs
      parameters:
        - name: macs
          in: path
          description: MAC address list separated by ,
          required: true
          schema:
            type: string
            example: '00:11:22:33:44:66'
      responses:
        '200':
          description: successful operation
          content:
            application/json:
              schema:
                type: array
                items:
                  type: object
                example:
                  - MAC: '00:11:22:33:44:66'
                    Vendor: CIMSYS
      security:
        - basicAuth: []
        - bearerAuth: []
      x-codeSamples:
        - lang: cURL
          label: CLI
          source: |
            curl -u "admin:pass" \
              "http://192.168.2.1/plugins/lookup/ouis/00:11:22:33:44:66"
  /plugins/dyndns/config:
    get:
      tags:
        - dyndns
      summary: Retrieve dyndns configuration
      description: Returns the dyndns configuration
      operationId: showDyndnsConfig
      responses:
        '200':
          description: successful operation
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/GodyndnsConfig'
      security:
        - basicAuth: []
        - bearerAuth: []
      x-codeSamples:
        - lang: cURL
          label: CLI
          source: |
            curl -u "admin:pass" \
              "http://192.168.2.1/plugins/dyndns/config"
    put:
      tags:
        - dyndns
      summary: Updates the dyndns config
      operationId: updateDyndnsConfig
      requestBody:
        $ref: '#/components/requestBodies/GodyndnsConfig'
      responses:
        '200':
          description: successful operation
      security:
        - basicAuth: []
        - bearerAuth: []
      x-codeSamples:
        - lang: cURL
          label: CLI
          source: |
            curl -u "admin:pass" \
              "http://192.168.2.1/plugins/dyndns/config"
  /plugins/dyndns/refresh:
    get:
      tags:
        - dyndns
      summary: Refresh the dyndns client
      description: Runs a dyndns update
      operationId: refreshDyndns
      responses:
        '200':
          description: successful operation
      security:
        - basicAuth: []
        - bearerAuth: []
      x-codeSamples:
        - lang: cURL
          label: CLI
          source: |
            curl -u "admin:pass" \
              "http://192.168.2.1/plugins/dyndns/refresh"
  /wireguardUpdate:
    put:
      tags:
        - unix_wireguard
      summary: Update Wireguard Peer
      description: Handle networking tasks for a new wireguard peer
      operationId: newWireguardUpdate
      responses:
        '200':
          description: successful operation
      requestBody:
        $ref: '#/components/requestBodies/WireguardUpdate'
    delete:
      tags:
        - unix_wireguard
      summary: Delete wireguard peer
      description: Handle networking tasks for removing a wireguard peer
      operationId: delWireguardUpdate
      responses:
        '200':
          description: successful operation
      requestBody:
        $ref: '#/components/requestBodies/WireguardUpdate'
  /plugins/wireguard/peers:
    get:
      tags:
        - wireguard
      summary: Peers
      description: Returns a list of peers connected to Wireguard
      operationId: getWireguardPeers
      responses:
        '200':
          description: successful operation
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: '#/components/schemas/WireguardPeer'
      security:
        - basicAuth: []
        - bearerAuth: []
      x-codeSamples:
        - lang: cURL
          label: CLI
          source: |
            curl -u "admin:pass" \
              "http://192.168.2.1/plugins/wireguard/peers"
  /plugins/wireguard/peer:
    put:
      tags:
        - wireguard
      summary: Peer
      description: Creates a new peer
      operationId: addWireguardPeer
      requestBody:
        $ref: '#/components/requestBodies/WireguardPeer'
      responses:
        '200':
          description: successful operation
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/WireguardConfig'
      security:
        - basicAuth: []
        - bearerAuth: []
      x-codeSamples:
        - lang: cURL
          label: CLI
          source: |
            curl -u "admin:pass" -X PUT \
              "http://192.168.2.1/plugins/wireguard/peer" --data '{}'
  /plugins/wireguard/config:
    get:
      tags:
        - wireguard
      summary: Config
      description: Return Wireguard server config
      operationId: getWireguardConfig
      responses:
        '200':
          description: successful operation
          content:
            application/json:
              schema:
                type: string
                example: |
                  [Interface]
                  Address = 192.168.3.1/24
                  ListenPort = 51280
                  PrivateKey = 6KVVbcmXanU/6mByHy17eNO9DXe9BQJWOyaA204JYH4=

                  [Peer]
                  PublicKey = 7SdFRh8o76RjUn/y4c7cQgCcCXA85s47/gVAdem3bBI=
                  PresharedKey = w9bfMAfqRnLjnlHofX+JSzaRDADrW1tvyW1UWzXJjrg=
                  AllowedIPs = 192.168.3.2/32
      security:
        - basicAuth: []
        - bearerAuth: []
      x-codeSamples:
        - lang: cURL
          label: CLI
          source: |
            curl -u "admin:pass" \
              "http://192.168.2.1/plugins/wireguard/config"
  /plugins/wireguard/status:
    get:
      tags:
        - wireguard
      summary: Status
      description: Return Wireguard server and peer status
      operationId: getWireguardStatus
      responses:
        '200':
          description: successful operation
          content:
            application/json:
              schema:
                type: object
                example:
                  wg0:
                    privateKey: 6KVVbcmXanU/6mByHy17eNO9DXe9BQJWOyaA204JYH4=
                    publicKey: 7SdFRh8o76RjUn/y4c7cQgCcCXA85s47/gVAdem3bBI=
                    listenPort: 51280,
                    peers:
                      HvtqvLJ1F33eHmR5Yk9PLZfTHg7w6sazPZtZi9u8pBQ=:
                        presharedKey: w9bfMAfqRnLjnlHofX+JSzaRDADrW1tvyW1UWzXJjrg=
                        allowedIps:
                          - 192.168.3.2/32
      security:
        - basicAuth: []
        - bearerAuth: []
      x-codeSamples:
        - lang: cURL
          label: CLI
          source: |
            curl -u "admin:pass" \
              "http://192.168.2.1/plugins/wireguard/status"
  /plugins/wireguard/up:
    put:
      tags:
        - wireguard
      summary: Up
      description: Start Wireguard if not running
      operationId: wireguardUp
      responses:
        '200':
          description: successful operation
          content:
            application/json:
              schema:
                type: boolean
                example: true
      security:
        - basicAuth: []
        - bearerAuth: []
      x-codeSamples:
        - lang: cURL
          label: CLI
          source: |
            curl -u "admin:pass" -X PUT \
              "http://192.168.2.1/plugins/wireguard/up"
  /plugins/wireguard/down:
    put:
      tags:
        - wireguard
      summary: Down
      description: Stop Wireguard if running
      operationId: wireguardDown
      responses:
        '200':
          description: successful operation
          content:
            application/json:
              schema:
                type: boolean
                example: true
      security:
        - basicAuth: []
        - bearerAuth: []
      x-codeSamples:
        - lang: cURL
          label: CLI
          source: |
            curl -u "admin:pass" -X PUT \
              "http://192.168.2.1/plugins/wireguard/down"
components:
  schemas:
    MulticastSettings:
      type: object
      properties:
        Disabled:
          type: boolean
          description: Whether multicast is disabled
        Addresses:
          type: array
          items:
            $ref: '#/components/schemas/MulticastAddress'
          description: List of multicast addresses
        DisableMDNSAdvertise:
          type: boolean
          description: Whether MDNS advertisement is disabled
        MDNSName:
          type: string
          description: MDNS name
      example:
        Disabled: false
        Addresses:
          - Address: 224.0.0.251:5353
        DisableMDNSAdvertise: false
        MDNSName: MyDevice
    MulticastAddress:
      type: object
      properties:
        Address:
          type: string
          description: Multicast address in the format IP:PORT
          example: 224.0.0.251:5353
    OTPUserRequest:
      type: object
      properties:
        Name:
          type: string
        Code:
          type: string
        UpdateAlwaysOn:
          type: boolean
        AlwaysOn:
          type: boolean
    OTPStatus:
      type: object
      properties:
        State:
          type: string
        AlwaysOn:
          type: boolean
    AlertSetting:
      type: object
      required:
        - TopicPrefix
      properties:
        TopicPrefix:
          type: string
        MatchAnyOne:
          type: boolean
        InvertRule:
          type: boolean
        Conditions:
          type: array
          items:
            $ref: '#/components/schemas/ConditionEntry'
        Actions:
          type: array
          items:
            $ref: '#/components/schemas/ActionConfig'
        Name:
          type: string
        Disabled:
          type: boolean
        RuleId:
          type: string
    ConditionEntry:
      type: object
      properties:
        JPath:
          type: string
    ActionConfig:
      type: object
      properties:
        SendNotification:
          type: boolean
        StoreAlert:
          type: boolean
        StoreTopicSuffix:
          type: string
        MessageTitle:
          type: string
        MessageBody:
          type: string
        NotificationType:
          type: string
        ActionType:
          type: string
        GrabEvent:
          type: boolean
        GrabValues:
          type: boolean
        GrabFields:
          type: array
          items:
            type: string
    GroupEntry:
      type: object
      properties:
        Name:
          description: Unique Group Name
          type: string
          example: vpn
        Disabled:
          description: If Group is disabled
          type: boolean
          example: false
        GroupTags:
          description: Tags for Group
          type: array
          items:
            type: string
            example:
              - private
      xml:
        name: Group
    GroupEntryArray:
      type: array
      items:
        $ref: '#/components/schemas/GroupEntry'
    DeviceEntry:
      type: object
      properties:
        Name:
          description: Client Name
          type: string
          example: rpi4
        MAC:
          description: HW address
          type: string
          example: '11:22:33:44:55:61'
        WGPubKey:
          description: PubKey
          type: string
          example: pubkey
        VLANTag:
          description: VLANTag
          type: string
          example: vlantag
        RecentIP:
          description: RecentIP
          type: string
          example: 192.168.2.102
        PSKEntry:
          description: PSK Entry
          $ref: '#/components/schemas/PSKEntry'
        Policies:
          description: Policies for Device
          type: array
          items:
            type: string
          example:
            - wan
            - dns
            - lan_upstream
        Groups:
          description: Interconnected Groups of Devices
          type: array
          items:
            type: string
          example:
            - cameras
            - tvs
        DeviceTags:
          description: Tags for Device
          type: array
          items:
            type: string
          example:
            - private
      xml:
        name: Device
    DeviceEntryMap:
      type: object
      additionalProperties:
        x-additionalPropertiesName: '11:22:33:44:55:6'
        $ref: '#/components/schemas/DeviceEntry'
    Interface:
      type: object
      properties:
        ifindex:
          type: integer
          example: 1
        ifname:
          type: string
          example: eth0
        flags:
          type: array
          items:
            type: string
            example: BROADCAST
        mtu:
          type: integer
          example: 1550
        qdisc:
          type: string
          example: mq
        operstate:
          type: string
          example: UP
        group:
          type: string
          example: default
        txqlen:
          type: integer
          example: 1000
        link_type:
          type: string
          example: ether
        address:
          description: HW address
          type: string
          example: '11:22:33:44:55:66'
        broadcast:
          description: HW address
          type: string
          example: ff:ff:ff:ff:ff:ff
        addr_info:
          type: array
          items:
            type: object
            properties:
              family:
                type: string
                example: inet6
              local:
                type: string
                example: '::1'
              prefixlen:
                type: integer
                example: 64
              scope:
                type: string
                example: link
              valid_life_time:
                type: integer
                example: 4294967295
              preferred_life_time:
                type: integer
                example: preferred_life_time
    ArpEntry:
      type: object
      properties:
        IP:
          type: string
          example: 192.168.2.142
        HWType:
          type: string
          example: '0x1'
        Flags:
          type: string
          example: '0x6'
        MAC:
          type: string
          example: '11:22:33:44:55:66'
        Mask:
          type: string
          example: '*'
        Device:
          type: string
          example: wlan1.4097
    PSKEntry:
      type: object
      properties:
        Type:
          description: sae for WPA3 or wpa for WPA2
          type: string
          enum:
            - sae
            - wpa
        Psk:
          description: Password
          type: string
          example: password
      xml:
        name: PSKEntry
    PSKAuthFailure:
      type: object
      properties:
        Type:
          type: string
          example: sae
        MAC:
          type: string
          pattern: /^([0-9A-Fa-f]{2}[:-]){5}([0-9A-Fa-f]{2})$/
          example: '11:22:33:44:55:66'
        Reason:
          type: string
          example: mismatch
        Status:
          type: string
          example: Okay
    PSKAuthSuccess:
      type: object
      properties:
        Iface:
          type: string
          example: wlan1
        Event:
          type: string
          example: AP-STA-CONNECTED
        MAC:
          type: string
          pattern: /^([0-9A-Fa-f]{2}[:-]){5}([0-9A-Fa-f]{2})$/
          example: '11:22:33:44:55:66'
        Status:
          type: string
          example: Okay
    TrafficElement:
      type: object
      properties:
        IP:
          type: string
          example: 192.168.2.1
        Packets:
          type: integer
          example: 7544
        Bytes:
          type: integer
          example: 824606
    IPTrafficElement:
      type: object
      properties:
        Interface:
          type: string
          example: wlan1
        Src:
          type: string
          pattern: /^(?:[0-9]{1,3}\.){3}[0-9]{1,3}$/
          example: 192.168.2.100
        Dst:
          type: string
          pattern: /^(?:[0-9]{1,3}\.){3}[0-9]{1,3}$/
          example: 192.168.2.102
        Packets:
          type: integer
          example: 1024
        Bytes:
          type: integer
          example: 4096
    NetCount:
      type: object
      properties:
        LanIn:
          type: integer
          example: 11125256532
        LanOut:
          type: integer
          example: 292437928
        WanIn:
          type: integer
          example: 52664
        WanOut:
          type: integer
          example: 52664
    TrafficHistory:
      type: object
      additionalProperties:
        x-additionalPropertiesName: 192.168.2.1
        $ref: '#/components/schemas/NetCount'
    DHCPUpdate:
      type: object
      properties:
        IP:
          type: string
          pattern: /^(?:[0-9]{1,3}\.){3}[0-9]{1,3}$/
          example: 192.168.2.102
        MAC:
          type: string
          pattern: /^([0-9A-Fa-f]{2}[:-]){5}([0-9A-Fa-f]{2})$/
          example: '11:22:33:44:55:66'
        Name:
          type: string
          example: rpi4
        Iface:
          type: string
          example: wlan1
        Router:
          type: string
          pattern: /^(?:[0-9]{1,3}\.){3}[0-9]{1,3}$/
          example: 192.168.2.1
    AbstractDHCPRequest:
      type: object
      properties:
        Identifier:
          type: string
          example: 7SdFRh8o76RjUn/y4c7cQgCcCXA85s47/gVAdem3bBI=
    FirewallForward:
      type: object
      properties:
        DstIP:
          type: string
          example: 1.2.3.4
        SrcIP:
          type: string
          example: 0.0.0.0/24
        SrcPort:
          type: string
          pattern: /any|[0-9]+/
          example: 0-10
        DstPort:
          type: string
          pattern: /any|[0-9]+/
          example: any
        Protocol:
          type: string
          pattern: /udp|tcp/
          example: tcp
    FirewallBlock:
      type: object
      properties:
        DstIP:
          type: string
          example: 1.2.3.4
        SrcIP:
          type: string
          example: 0.0.0.0/24
        Protocol:
          type: string
          pattern: /udp|tcp/
          example: tcp
    FirewallBlockForward:
      type: object
      properties:
        DstIP:
          type: string
          example: 1.2.3.4
        SrcIP:
          type: string
          example: 0.0.0.0/24
        DstPort:
          type: string
          example: 0-65535
        Protocol:
          type: string
          pattern: /udp|tcp/
          example: tcp
    ServicePort:
      type: object
      properties:
        UpstreamEnabled:
          type: boolean
          description: Reachable from WAN/Upstream Interface
          example: false
        Port:
          type: string
          example: '22'
        Protocol:
          type: string
          pattern: /tcp/
          example: tcp
          description: Only TCP services are currently supported
    Endpoint:
      type: object
      properties:
        RuleName:
          type: string
        Disabled:
          type: boolean
        Protocol:
          type: string
        IP:
          type: string
          example: 1.2.3.4
        Domain:
          type: string
          example: www.domain.com
        Port:
          type: string
          example: '22'
        Tags:
          description: Tags for Device
          type: array
          items:
            type: string
          example:
            - private
    MulticastPort:
      type: object
      properties:
        Upstream:
          description: Reachable from Uplinks
          type: boolean
        Port:
          type: string
          example: '22'
    CustomInterfaceRule:
      type: object
      properties:
        Interface:
          type: string
          description: interface name
          example: wlan1
        SrcIP:
          type: string
          description: IP or CIDR assigned to interface
          example: 172.16.0.0/16
        RouteDst:
          type: string
          description: IP destination to route to, for example container host IP
          example: 172.12.0.2
        Policies:
          description: Policies for Interface
          type: array
          items:
            type: string
          example:
            - api
            - wan
            - dns
            - lan_upstream
        Groups:
          description: Groups to join Interfaces to Devices
          type: array
          items:
            type: string
          example:
            - cameras
        Tags:
          description: Tags to apply. NOTE, no impact for now
          type: array
          items:
            type: string
          example:
            - private
    ICMPOptions:
      type: object
      properties:
        PingLan:
          description: Allow ping from LAN
          type: boolean
          example: true
        PingWan:
          description: Allow ping from WAN/upstream
          type: boolean
          example: false
      required:
        - PingLan
        - PingWan
    DHCPConfig:
      type: object
      properties:
        TinyNets:
          type: array
          items:
            type: string
          description: List of subnet pools.
        LeaseTime:
          type: string
          description: Duration of the DHCP lease time.
      required:
        - TinyNets
        - LeaseTime
    DNSSettings:
      type: object
      properties:
        UpstreamTLSHost:
          type: string
          description: DNS name of the upstream TLS host.
        UpstreamIPAddress:
          type: string
          description: IP address of the upstream DNS server.
        TlsDisable:
          type: boolean
          description: Flag to disable TLS.
      required:
        - UpstreamTLSHost
        - UpstreamIPAddress
        - TlsDisable
    InterfaceEntry:
      type: object
      properties:
        Name:
          type: string
          description: interface name
          example: wlan1
        Type:
          type: string
          description: interface type. Currently "Uplink" and "AP" are supported
          example: AP
        Enabled:
          type: boolean
          description: >-
            If the interface is enabled or not. Only has an effect for "AP" type
            for now
          example: true
    WPASupplicantConfig:
      type: object
      properties:
        WPAs:
          type: array
          items:
            $ref: '#/components/schemas/WPAIface'
    WPAIface:
      type: object
      properties:
        Iface:
          type: string
        Enabled:
          type: boolean
        Networks:
          type: array
          items:
            $ref: '#/components/schemas/WPANetwork'
    WPANetwork:
      type: object
      properties:
        Disabled:
          type: boolean
        Password:
          type: string
        SSID:
          type: string
        KeyMgmt:
          type: string
        Priority:
          type: string
          nullable: true
        BSSID:
          type: string
          nullable: true
    PPPConfig:
      type: object
      properties:
        PPPs:
          type: array
          items:
            $ref: '#/components/schemas/PPPIface'
    PPPIface:
      type: object
      properties:
        Iface:
          type: string
        PPPIface:
          type: string
        Enabled:
          type: boolean
        Username:
          type: string
        Secret:
          type: string
        VLAN:
          type: string
          nullable: true
        MTU:
          type: string
          nullable: true
    ExtraBSS:
      type: object
      properties:
        Ssid:
          type: string
        Bssid:
          type: string
        Wpa:
          type: string
        WpaKeyMgmt:
          type: string
        DisableIsolation:
          type: boolean
    InterfaceConfig:
      type: object
      properties:
        Name:
          type: string
        Enabled:
          type: boolean
        DisableDHCP:
          type: boolean
          nullable: true
        IP:
          type: string
          nullable: true
        Router:
          type: string
          nullable: true
        VLAN:
          type: string
          nullable: true
    BasicInterfaceConfig:
      type: object
      properties:
        Name:
          type: string
          description: Interface name on system
        Type:
          type: string
          enum:
            - AP
            - Uplink
            - Downlink
            - Other
        Subtype:
          type: string
        Enabled:
          type: boolean
    PluginEntry:
      type: object
      properties:
        Name:
          type: string
          description: Plugin name
          example: dns-block
        URI:
          type: string
          description: Plugin URI
          example: dns/block
        UnixPath:
          type: string
          description: Plugin path for unix socket
          example: /state/dns/dns_block_plugin
        Enabled:
          type: boolean
          description: Plugin state
          example: true
        Plus:
          type: boolean
          description: Indicates if this is a PLUS plugin
          example: false
        GitURL:
          type: string
          description: Git repository URL for the plugin
          example: https://github.com/example/dns-block-plugin.git
        ComposeFilePath:
          type: string
          description: Relative path to docker compose file
          example: plugins/plugin/docker-compose.yml
        HasUI:
          type: boolean
          description: Indicates if the plugin has a user interface
          example: true
        SandboxedUI:
          type: boolean
          description: Indicates if the plugin UI is sandboxed
          example: true
        InstallTokenPath:
          type: string
          description: Path to the installation token
          example: /config/plugins/dns-block/install-token
        ScopedPaths:
          type: array
          items:
            type: string
          description: List of scoped paths for the plugin
          example:
            - /config/plugins/dns-block
            - /state/plugins/dns-block
    HostapdStatus:
      type: object
      properties:
        beacon_int:
          type: string
          example: '100'
        bss[0]:
          type: string
          example: wlan1
        bssid[0]:
          type: string
          example: 00:c0:ca:33:11:22
        cac_time_left_seconds:
          type: string
          example: N/A
        cac_time_seconds:
          type: string
          example: '0'
        channel:
          type: string
          example: '36'
        dtim_period:
          type: string
          example: '2'
        edmg_channel:
          type: string
          example: '0'
        edmg_enable:
          type: string
          example: '0'
        freq:
          type: string
          example: '5180'
        ht_caps_info:
          type: string
          example: 01ff
        ht_mcs_bitmask:
          type: string
          example: ffff0000000000000000
        ht_op_mode:
          type: string
          example: '0x6'
        ieee80211ac:
          type: string
          example: '1'
        ieee80211ax:
          type: string
          example: '0'
        ieee80211n:
          type: string
          example: '1'
        max_txpower:
          type: string
          example: '23'
        num_sta[0]:
          type: string
          example: '6'
        num_sta_ht40_intolerant:
          type: string
          example: '0'
        num_sta_ht_20_mhz:
          type: string
          example: '2'
        num_sta_ht_no_gf:
          type: string
          example: '6'
        num_sta_no_ht:
          type: string
          example: '0'
        num_sta_no_short_preamble:
          type: string
          example: '6'
        num_sta_no_short_slot_time:
          type: string
          example: '6'
        num_sta_non_erp:
          type: string
          example: '0'
        olbc:
          type: string
          example: '0'
        olbc_ht:
          type: string
          example: '0'
        phy:
          type: string
          example: phy1
        rx_vht_mcs_map:
          type: string
          example: fffa
        secondary_channel:
          type: string
          example: '1'
        ssid[0]:
          type: string
          example: test_ap
        state:
          type: string
          example: ENABLED
        supported_rates:
          type: string
          example: 0c 12 18 24 30 48 60 6c
        tx_vht_mcs_map:
          type: string
          example: fffa
        vht_caps_info:
          type: string
          example: 318001b0
        vht_oper_centr_freq_seg0_idx:
          type: string
          example: '42'
        vht_oper_centr_freq_seg1_idx:
          type: string
          example: '0'
        vht_oper_chwidth:
          type: string
          example: '1'
    StationInfo:
      type: object
      properties:
        AKMSuiteSelector:
          type: string
          example: 00-0f-ac-2
        aid:
          type: string
          example: '3'
        capability:
          type: string
          example: '0x11'
        connected_time:
          type: string
          example: '4946'
        dot11RSNAStatsSTAAddress:
          type: string
          example: '11:22:33:44:55:61'
        dot11RSNAStatsSelectedPairwiseCipher:
          type: string
          example: 00-0f-ac-4
        dot11RSNAStatsTKIPLocalMICFailures:
          type: string
          example: '0'
        dot11RSNAStatsTKIPRemoteMICFailures:
          type: string
          example: '0'
        dot11RSNAStatsVersion:
          type: string
          example: '1'
        flags:
          type: string
          example: '[AUTH][ASSOC][AUTHORIZED][WMM][HT]'
        hostapdWPAPTKGroupState:
          type: string
          example: '0'
        hostapdWPAPTKState:
          type: string
          example: '11'
        ht_caps_info:
          type: string
          example: '0x016e'
        ht_mcs_bitmask:
          type: string
          example: ff000000000000000000
        inactive_msec:
          type: string
          example: '1584'
        listen_interval:
          type: string
          example: '1'
        rx_bytes:
          type: string
          example: '126055'
        rx_packets:
          type: string
          example: '2394'
        rx_rate_info:
          type: string
          example: '60'
        signal:
          type: string
          example: '-85'
        supported_rates:
          type: string
          example: 8c 12 98 24 b0 48 60 6c
        timeout_next:
          type: string
          example: NULLFUNC POLL
        tx_bytes:
          type: string
          example: '485584'
        tx_packets:
          type: string
          example: '1957'
        tx_rate_info:
          type: string
          example: 1200 mcs 5 shortGI
        vlan_id:
          type: string
          example: '4247'
        wpa:
          type: string
          example: '2'
    ChannelParameters:
      type: object
      properties:
        Mode:
          type: string
          description: g for 2.4Ghz, a for 5Ghz
          pattern: /^(a|b|g)$/
          example: a
        Channel:
          type: integer
          example: 36
          description: >-
            See the [list of WLAN
            channels](https://en.wikipedia.org/wiki/List_of_WLAN_channels)
        Bandwidth:
          type: integer
          description: Channel width in Mhz. One of 20, 40, 80, 160, or 8080 for 80+80
          example: 80
        HT_Enable:
          type: boolean
          description: 802.11n support - High Throughput
          example: true
        VHT_Enable:
          type: boolean
          description: 802.11ac support - Very High Throughput (WiFi 5)
          example: true
        HE_Enable:
          type: boolean
          description: 802.11ax support - High Effiency (WiFi 6)
          example: true
    CalculatedChannelParameters:
      type: object
      description: Calculated center frequencies and channel widths
      properties:
        Vht_oper_centr_freq_seg0_idx:
          type: integer
          example: 42
        He_oper_centr_freq_seg0_idx:
          type: integer
          example: 42
        Vht_oper_chwidth:
          type: integer
          example: 1
        He_oper_chwidth:
          type: integer
          example: 1
    HostapdConfig:
      type: object
      properties:
        Country_code:
          type: string
          description: 2-letter country code
          example: US
        Vht_capab:
          description: >-
            Very High Throughput capabilities for 5ghz (802.11ac). Should be
            removed for 2.4ghz
          type: string
          example: >-
            [RXLDPC][SHORT-GI-80][TX-STBC-2BY1][RX-STBC-1][MAX-A-MPDU-LEN-EXP3][RX-ANTENNA-PATTERN][TX-ANTENNA-PATTERN]
        Ht_capab:
          type: string
          description: High Throughput capabilities (802.11n)
          example: >-
            [LDPC][HT40+][HT40-][GF][SHORT-GI-20][SHORT-GI-40][TX-STBC][RX-STBC1]
        Hw_mode:
          type: string
          description: a for 5ghz, b/g for 2.4ghz
          pattern: /^(a/b/g)$/
          example: a
        Ieee80211ax:
          type: integer
          description: WiFi 6 support
          example: 1
        He_su_beamformer:
          type: integer
          description: High Efficiency (WiFi 6) Single User Beamformer enable
          example: 1
        He_su_beamformee:
          type: integer
          description: High Efficiency (WiFi 6) Single User Beamformee enable
          example: 1
        He_mu_beamformer:
          type: integer
          description: High Efficiency (WiFi 6) Multiple User Beamformer enable
          example: 1
        Ssid:
          type: string
          description: WiFi SSID Name
          example: 8hzWANip
        Channel:
          type: integer
          description: >-
            See the [list of WLAN
            channels](https://en.wikipedia.org/wiki/List_of_WLAN_channels)
          example: 36
        Vht_oper_centr_freq_seg0_idx:
          type: integer
          example: 42
        He_oper_centr_freq_seg0_idx:
          type: integer
          example: 42
        Vht_oper_chwidth:
          type: integer
          example: 1
        He_oper_chwidth:
          type: integer
          example: 1
    FirewallConfig:
      type: object
      properties:
        ForwardingRules:
          description: Forwarding Rules
          type: array
          items:
            $ref: '#/components/schemas/FirewallForward'
        BlockRules:
          description: Block Rules
          type: array
          items:
            $ref: '#/components/schemas/FirewallBlock'
        ForwardingBlockRules:
          description: Forwarding Block Rules
          type: array
          items:
            $ref: '#/components/schemas/FirewallBlockForward'
        ServicePorts:
          description: Service Ports
          type: array
          items:
            $ref: '#/components/schemas/ServicePort'
    Token:
      type: object
      properties:
        Name:
          type: string
          example: TestToken
        Token:
          type: string
          example: dG9rbnRva250b2tudG9rbnRva250b2tudG9rbnRva24K
        ScopedPaths:
          type: array
          items:
            type: string
          example:
            - wifi
        Expire:
          type: integer
          example: 1656440879
    Notification:
      type: object
      properties:
        Conditions:
          type: object
          properties:
            Prefix:
              type: string
              example: drop:input
            Protocol:
              type: string
              example: tcp
            DstIP:
              type: string
              example: 1.1.1.1
            DstPort:
              type: integer
              example: 80
            SrcIP:
              type: string
              example: 192.168.2.10
            SrcPort:
              type: integer
              example: 1234
        Notification:
          type: boolean
          example: true
    GeoASN:
      type: object
      properties:
        ASN:
          description: Autonomous System Number
          type: integer
          example: 13335
        Name:
          description: ASN name, resolved on add when available
          type: string
          example: CLOUDFLARENET
    GeoBlockList:
      type: object
      properties:
        URI:
          description: HTTP(S) URI of an ASN/CIDR block list to fetch
          type: string
          example: https://www.spamhaus.org/drop/asndrop.json
        Enabled:
          description: Whether this list is fetched and applied
          type: boolean
          example: false
        Note:
          description: Human readable note for the list
          type: string
          example: Spamhaus ASN-DROP
    GeoBlockConfig:
      type: object
      properties:
        Enabled:
          description: Master enable for geo/ASN blocking
          type: boolean
          example: true
        DenyCountries:
          description: Two-letter ISO country codes to block
          type: array
          items:
            type: string
            example: CN
        DenyASNs:
          description: Autonomous Systems to block
          type: array
          items:
            $ref: '#/components/schemas/GeoASN'
        Lists:
          description: External block lists to fetch
          type: array
          items:
            $ref: '#/components/schemas/GeoBlockList'
        RefreshSeconds:
          description: Refresh interval in seconds (minimum 3600, defaults to 86400)
          type: integer
          example: 86400
    GeoBlockSource:
      type: object
      properties:
        Type:
          description: Source type (country, asn, list, nft)
          type: string
          example: asn
        Key:
          description: Source identifier (country code, ASxxxx, or list URI)
          type: string
          example: AS13335
        Ranges:
          description: Number of IP ranges contributed by this source
          type: integer
          example: 42
        ASNs:
          description: Number of ASNs discovered (list sources only)
          type: integer
          example: 3
        LastFetch:
          description: RFC3339 timestamp of the last fetch
          type: string
          example: '2026-07-09T12:00:00Z'
        Error:
          description: Error string if this source failed
          type: string
          example: ''
    GeoBlockStatus:
      type: object
      properties:
        Enabled:
          description: Whether geo/ASN blocking is currently active
          type: boolean
          example: true
        LastRefresh:
          description: RFC3339 timestamp of the last refresh
          type: string
          example: '2026-07-09T12:00:00Z'
        RangesProgrammed:
          description: Number of merged IP ranges programmed into the nftables set
          type: integer
          example: 1024
        Sources:
          description: Per-source breakdown of the last refresh
          type: array
          items:
            $ref: '#/components/schemas/GeoBlockSource'
    FirewallBlockOutput:
      type: object
      properties:
        DstIP:
          type: string
          example: 1.2.3.4
        SrcIP:
          type: string
          example: 0.0.0.0/24
        DstPort:
          type: string
          example: 0-65535
        Protocol:
          type: string
          pattern: /udp|tcp/
          example: tcp
    RoamingConfig:
      type: object
      description: 802.11v fast-roaming manager configuration
      properties:
        DryRun:
          type: boolean
          description: When true, recommend transitions without sending them
          example: true
        PollIntervalSeconds:
          type: integer
          description: Seconds between topology polls (5-300)
          example: 15
        ObservationDelaySeconds:
          type: integer
          description: Seconds to wait before observing a transition outcome (5-180)
          example: 20
        RSSIThresholdDBM:
          type: integer
          description: Only roam stations weaker than this RSSI in dBm (-100 to -30)
          example: -70
        MinimumImprovementDBM:
          type: integer
          description: Minimum expected RSSI improvement in dBm to act (0-40)
          example: 5
        CooldownSeconds:
          type: integer
          description: Per-station cooldown between transitions in seconds (30-86400)
          example: 900
        MaxTransitionsPerHour:
          type: integer
          description: Maximum live transitions per hour across the router (1-100)
          example: 4
        ExplorationRate:
          type: number
          format: float
          description: Probability of exploring a random candidate (0-1)
          example: 0
        AllowedInterfaces:
          type: array
          description: Interfaces eligible as transition targets; empty means all
          items:
            type: string
          example: []
    RoamingStatus:
      type: object
      description: Runtime status of the fast-roaming manager
      properties:
        RoamingEnabled:
          type: boolean
          description: Whether the roaming feature is currently enabled
          example: true
        Config:
          $ref: '#/components/schemas/RoamingConfig'
        HistoryCount:
          type: integer
          description: Number of records retained in history
          example: 12
        ModelArms:
          type: integer
          description: Number of learned model arms
          example: 8
        TransitionsActive:
          type: integer
          description: Number of transitions currently in flight
          example: 0
    RoamingRecord:
      type: object
      description: A single BSS transition attempt and its observed outcome
      properties:
        ID:
          type: string
          description: Unique record identifier
          example: 1718000000000000000-1
        RequestedAt:
          type: string
          format: date-time
          description: When the transition was requested
          example: '2026-07-09T12:00:00Z'
        ObservedAt:
          type: string
          format: date-time
          description: When the outcome was observed
          example: '2026-07-09T12:00:20Z'
        Origin:
          type: string
          description: Trigger source (auto, auto_explore, or manual)
          example: auto
        MAC:
          type: string
          description: Station MAC address
          example: '11:22:33:44:55:66'
        SourceInterface:
          type: string
          description: Interface the station roamed from
          example: wlan0
        TargetInterface:
          type: string
          description: Interface the station was steered toward
          example: wlan1
        SourceRSSI:
          type: integer
          description: Station RSSI in dBm at request time
          example: -75
        PostRSSI:
          type: integer
          description: Station RSSI in dBm after observation
          example: -55
        PostInterface:
          type: string
          description: Interface the station was on after observation
          example: wlan1
        DryRun:
          type: boolean
          description: Whether this was a recommendation only
          example: false
        State:
          type: string
          description: >-
            Outcome state (sent, succeeded, ignored, offline, moved_elsewhere,
            recommended, disabled, observation_failed)
          example: succeeded
        Reward:
          type: number
          format: float
          description: Reward assigned to the learning model
          example: 45
        HostapdResponse:
          type: string
          description: Raw response from hostapd
          example: OK
        Error:
          type: string
          description: Error detail when the attempt failed
          example: ''
    ArmStat:
      type: object
      description: Learned statistics for a single model arm
      properties:
        Count:
          type: integer
          description: Number of observations for this arm
          example: 3
        Value:
          type: number
          format: float
          description: Running mean reward estimate
          example: 42.5
        LastReward:
          type: number
          format: float
          description: Reward from the most recent observation
          example: 45
        UpdatedAt:
          type: string
          format: date-time
          description: When this arm was last updated
          example: '2026-07-09T12:00:20Z'
    RoamingModel:
      type: object
      description: Learned bandit model keyed by MAC|source|target|rssiBucket
      additionalProperties:
        $ref: '#/components/schemas/ArmStat'
    BSSTransitionRequest:
      type: object
      description: Advisory 802.11v BSS transition request
      properties:
        MAC:
          type: string
          description: Station MAC address to steer
          example: '11:22:33:44:55:66'
        TargetInterface:
          type: string
          description: Interface to steer the station toward
          example: wlan1
    DeviceIdentityList:
      type: array
      description: List of device identities (MAC address or WireGuard public key)
      items:
        type: string
        example: '11:22:33:44:55:66'
    BulkDeviceUpdate:
      type: object
      properties:
        Identities:
          type: array
          description: Device identities to update (MAC address or WireGuard public key)
          items:
            type: string
          example:
            - '11:22:33:44:55:66'
        Groups:
          type: array
          description: Groups to add to each device
          items:
            type: string
          example:
            - dns
            - wan
        Tags:
          type: array
          description: Tags to add to each device
          items:
            type: string
          example:
            - lab
        Policies:
          type: array
          description: Policies to add to each device (must be bulk-settable)
          items:
            type: string
          example:
            - lan
    AlertDevice:
      type: object
      properties:
        DeviceId:
          type: string
          description: Mobile device identifier (36 char UUID for iOS)
          example: FCDBD8EF-62FC-4ECB-B2F5-92C9E79AC7F9
        DeviceToken:
          type: string
          description: APNS device token (64 hex characters)
          example: aabbccddeeff00112233445566778899aabbccddeeff00112233445566778899
        PublicKey:
          type: string
          description: Device public key used to encrypt alert payloads
          example: MFkwEwYHKoZIzj0CAQYIK...
        LastActive:
          type: string
          format: date-time
          description: Timestamp the device was last active
          example: '2024-03-13T23:43:39Z'
    MobileAlertProxySettings:
      type: object
      properties:
        Disabled:
          type: boolean
          description: When true, the mobile alert proxy is disabled
          example: false
        APNSDomain:
          type: string
          description: Domain of the APNS proxy that relays notifications
          example: apns.supernetworks.org
    APNSAlert:
      type: object
      properties:
        title:
          type: string
          description: Alert title
          example: SPR Alert
        body:
          type: string
          description: Alert body text
          example: A new device joined the network
    PluginGitURL:
      type: string
      description: Git URL of the user plugin to download
      example: https://github.com/spr-networks/spr-sample-plugin
    AdditionalIP:
      type: object
      properties:
        IP:
          type: string
          description: Additional IP or CIDR bound to the interface
          example: 192.168.5.1/24
        Router:
          type: string
          description: Optional gateway for this additional IP
          example: 192.168.5.1
    LanLinkIPConfig:
      type: object
      properties:
        Name:
          type: string
          description: Interface name on system
          example: eth1
        Type:
          type: string
          description: Interface type
          example: Downlink
        Enabled:
          type: boolean
          description: Whether the interface is enabled
          example: true
        IP:
          type: string
          description: Primary IP or CIDR for the interface
          example: 192.168.2.1/24
        Router:
          type: string
          description: Gateway IP for the interface
          example: 192.168.2.1
        VLAN:
          type: string
          description: VLAN tag for the interface
          example: '10'
        AdditionalIPs:
          type: array
          description: Additional IPs bound to the interface
          items:
            $ref: '#/components/schemas/AdditionalIP'
    RadioInfo:
      type: object
      properties:
        Channel:
          type: integer
          description: Operating channel
          example: 36
        Freq:
          type: integer
          description: Operating frequency in MHz
          example: 5180
        Modes:
          type: array
          description: Supported 802.11 modes (n, ac, ax, be)
          items:
            type: string
          example:
            - ac
            - ax
        Stations:
          type: integer
          description: Number of associated stations
          example: 3
    StationSignal:
      type: object
      properties:
        RSSI:
          type: integer
          description: Signal strength in dBm
          example: -55
        TxRate:
          type: integer
          description: Transmit rate
          example: 866
        RxRate:
          type: integer
          description: Receive rate
          example: 866
        Caps:
          type: array
          description: Station capabilities (HT, VHT, HE, EHT)
          items:
            type: string
          example:
            - VHT
            - HE
    TopoNode:
      type: object
      properties:
        ID:
          type: string
          description: Unique node identifier
          example: dev:11:22:33:44:55:66
        Kind:
          type: string
          description: >-
            Node kind (router, uplink, ap_radio, port, vpn, device, leaf_router,
            endpoint, extension, sink)
          example: device
        Name:
          type: string
          description: Display name
          example: laptop
        MAC:
          type: string
          description: MAC address
          example: '11:22:33:44:55:66'
        IP:
          type: string
          description: Recent IP address
          example: 192.168.2.20
        TinyNet:
          type: string
          description: Device tiny subnet (/30)
          example: 192.168.2.20/30
        VLANTag:
          type: string
          description: VLAN tag
          example: '10'
        ConnType:
          type: string
          description: Connection type (wifi, wired, wireguard, offline)
          example: wifi
        Iface:
          type: string
          description: Interface the node is attached to
          example: wlan0
        SSID:
          type: string
          description: SSID for AP radio nodes
          example: SPR
        Radio:
          $ref: '#/components/schemas/RadioInfo'
        Groups:
          type: array
          description: Device groups
          items:
            type: string
          example:
            - dns
            - wan
        Policies:
          type: array
          description: Device policies
          items:
            type: string
          example:
            - lan
        Tags:
          type: array
          description: Device tags
          items:
            type: string
          example:
            - lab
        Signal:
          $ref: '#/components/schemas/StationSignal'
        Online:
          type: boolean
          description: Whether the node is online
          example: true
        Isolated:
          type: boolean
          description: Whether the device is isolated (quarantined/disabled)
          example: false
        Style:
          type: object
          description: Device display style
        DHCPFirstTime:
          type: string
          description: First DHCP lease time
          example: '2024-03-13T23:43:39Z'
        DHCPLastTime:
          type: string
          description: Most recent DHCP lease time
          example: '2024-03-14T10:12:00Z'
    TopoEdge:
      type: object
      properties:
        From:
          type: string
          description: Source node ID
          example: dev:11:22:33:44:55:66
        To:
          type: string
          description: Destination node ID
          example: iface:wlan0
        Layer:
          type: string
          description: Edge layer (l1, policy)
          example: l1
        Kind:
          type: string
          description: >-
            Edge kind (wifi, wired, wg, uplink, group:<name>, policy:<name>,
            endpoint:<name>, route, route:split, route:dns)
          example: wifi
        Metric:
          type: number
          description: Edge metric (e.g. RSSI for wifi edges)
          example: -55
        Bidir:
          type: boolean
          description: Whether the policy edge applies both ways
          example: true
    TopoSink:
      type: object
      properties:
        ID:
          type: string
          description: Unique sink identifier
          example: plugin:mesh:sink:tailscale
        Name:
          type: string
          description: Sink display name
          example: tailscale
        Iface:
          type: string
          description: Egress interface for the sink
          example: tailscale0
        IP:
          type: string
          description: Optional IP of the sink egress
          example: 100.64.0.1
        Online:
          type: boolean
          description: Whether the sink is online
          example: true
    Topology:
      type: object
      properties:
        GeneratedAt:
          type: string
          format: date-time
          description: Time the topology was generated
          example: '2024-03-14T10:12:00Z'
        Nodes:
          type: array
          description: Topology nodes
          items:
            $ref: '#/components/schemas/TopoNode'
        Edges:
          type: array
          description: Topology edges
          items:
            $ref: '#/components/schemas/TopoEdge'
        Sinks:
          type: array
          description: Advertised routeable egress sinks
          items:
            $ref: '#/components/schemas/TopoSink'
    TimeWindow:
      type: object
      properties:
        Days:
          description: >-
            Seven day-of-week flags (Sunday first); 1 means the window applies
            that day
          type: array
          items:
            type: integer
          example:
            - 0
            - 1
            - 1
            - 1
            - 1
            - 1
            - 0
        Start:
          description: Window start time in HH:MM 24-hour format
          type: string
          example: '21:00'
        End:
          description: Window end time in HH:MM 24-hour format
          type: string
          example: '07:00'
    Persona:
      type: object
      properties:
        Name:
          description: Unique persona name
          type: string
          example: kids
        Tag:
          description: >-
            Device tag bound to the persona; must start with "persona:"
            (defaults to persona:Name)
          type: string
          example: persona:kids
        Description:
          description: Human-readable description of the persona
          type: string
          example: Children devices
        DailyLimitMinutes:
          description: Daily internet time budget in minutes; 0 disables the limit
          type: integer
          example: 120
        Schedules:
          description: Recurring time windows during which internet access is blocked
          type: array
          items:
            $ref: '#/components/schemas/TimeWindow'
        DNSFamily:
          description: Whether to apply family-safe DNS filtering to the persona
          type: boolean
          example: true
        Disabled:
          description: Whether enforcement for this persona is disabled
          type: boolean
          example: false
    PersonaUsageInfo:
      type: object
      properties:
        Used:
          description: Minutes of active internet usage counted today
          type: integer
          example: 45
        Limit:
          description: Daily limit in minutes copied from the persona (0 means unlimited)
          type: integer
          example: 120
        Blocked:
          description: Whether the persona is currently blocked
          type: boolean
          example: false
        PauseUntil:
          description: >-
            Unix timestamp (seconds) until which the persona is paused; 0 if not
            paused
          type: integer
          format: int64
          example: 0
        GrantUntil:
          description: >-
            Unix timestamp (seconds) until which extra time is granted; 0 if
            none
          type: integer
          format: int64
          example: 0
    PersonasUsage:
      type: object
      description: Usage keyed by persona tag
      additionalProperties:
        $ref: '#/components/schemas/PersonaUsageInfo'
      example:
        persona:kids:
          Used: 45
          Limit: 120
          Blocked: false
          PauseUntil: 0
          GrantUntil: 0
    PersonasState:
      type: object
      properties:
        Date:
          description: Usage accounting day (YYYY-MM-DD) for the current counters
          type: string
          example: '2026-07-09'
        UsedMinutes:
          description: Minutes used today keyed by persona tag
          type: object
          additionalProperties:
            type: integer
          example:
            persona:kids: 45
        PauseUntil:
          description: Pause expiry Unix timestamps (seconds) keyed by persona tag
          type: object
          additionalProperties:
            type: integer
            format: int64
          example:
            persona:kids: 1752096000
        GrantUntil:
          description: Grant (extend) expiry Unix timestamps (seconds) keyed by persona tag
          type: object
          additionalProperties:
            type: integer
            format: int64
          example:
            persona:kids: 1752096000
    ParentalControlRequest:
      type: object
      properties:
        Tag:
          description: Persona tag or persona name to target
          type: string
          example: persona:kids
        Minutes:
          description: Duration in minutes; 0 or less clears the override
          type: integer
          example: 30
    ParentalResetRequest:
      type: object
      properties:
        Tag:
          description: Persona tag or persona name to reset
          type: string
          example: persona:kids
    ReleaseInfo:
      type: object
      properties:
        CustomChannel:
          description: Custom release channel to track
          type: string
          example: main
        CustomVersion:
          description: Pinned custom version to install
          type: string
          example: 0.3.6
        Current:
          description: Currently running release version
          type: string
          example: 0.3.5
    ConfigBackupEntry:
      type: object
      properties:
        Name:
          description: Backup archive filename
          type: string
          example: spr-configs-v0.3.5.tgz
        Timestamp:
          description: Backup file modification time
          type: string
          format: date-time
          example: '2026-07-09T12:00:00Z'
    TimeInfo:
      type: object
      properties:
        unix:
          description: Current server time as a Unix timestamp in seconds
          type: integer
          format: int64
          example: 1752048000
    AuthorizedKeys:
      type: array
      description: List of SSH authorized public keys
      items:
        type: string
        example: ssh-ed25519 AAAAC3Nza... user@host
    AttestStatus:
      type: object
      description: >-
        Attestation status reported by superd; structure is passed through
        unchanged
      additionalProperties: true
    PluginAttestStatus:
      type: object
      description: >-
        Plugin attestation result reported by superd; structure is passed
        through unchanged
      additionalProperties: true
    SystemInfo:
      type: object
      description: >-
        System information payload; shape varies by requested field (uptime,
        dockernetworks, docker, hostname, ss)
      additionalProperties: true
    NFTablesList:
      type: object
      description: nftables ruleset listing in nft JSON format
      additionalProperties: true
    TrafficInsightsConfig:
      type: object
      properties:
        Enabled:
          description: Whether traffic insights collection is enabled
          type: boolean
          example: true
        RetentionDays:
          description: Number of days of hourly buckets to retain (1-90)
          type: integer
          example: 7
    InsightDevBytes:
      type: object
      properties:
        IP:
          description: Local device IP address
          type: string
          example: 192.168.2.20
        BytesIn:
          description: Bytes received by the device over the window
          type: integer
          format: int64
          example: 1048576
        BytesOut:
          description: Bytes sent by the device over the window
          type: integer
          format: int64
          example: 524288
    InsightASNBytes:
      type: object
      properties:
        ASN:
          description: Autonomous System Number of the remote endpoint
          type: integer
          example: 15169
        Name:
          description: Autonomous System name
          type: string
          example: GOOGLE
        Country:
          description: ISO country code associated with the ASN
          type: string
          example: US
        BytesIn:
          description: Bytes received from this ASN over the window
          type: integer
          format: int64
          example: 2097152
        BytesOut:
          description: Bytes sent to this ASN over the window
          type: integer
          format: int64
          example: 1048576
        Devices:
          description: Per-device byte breakdown for this ASN
          type: array
          items:
            $ref: '#/components/schemas/InsightDevBytes'
    InsightCountry:
      type: object
      properties:
        Country:
          description: ISO country code
          type: string
          example: US
        BytesIn:
          description: Bytes received from this country over the window
          type: integer
          format: int64
          example: 4194304
        BytesOut:
          description: Bytes sent to this country over the window
          type: integer
          format: int64
          example: 2097152
        Devices:
          description: Per-device byte breakdown for this country
          type: array
          items:
            $ref: '#/components/schemas/InsightDevBytes'
        ASNs:
          description: Top ASNs seen for this country
          type: array
          items:
            $ref: '#/components/schemas/InsightASNBytes'
    InsightOverview:
      type: object
      properties:
        Start:
          description: Start of the reporting window (RFC3339)
          type: string
          format: date-time
          example: '2026-07-08T00:00:00Z'
        End:
          description: End of the reporting window (RFC3339)
          type: string
          format: date-time
          example: '2026-07-09T00:00:00Z'
        TotalIn:
          description: Total bytes received across all devices over the window
          type: integer
          format: int64
          example: 8388608
        TotalOut:
          description: Total bytes sent across all devices over the window
          type: integer
          format: int64
          example: 4194304
        Countries:
          description: Byte breakdown grouped by country, sorted by total bytes
          type: array
          items:
            $ref: '#/components/schemas/InsightCountry'
        ASNs:
          description: Byte breakdown grouped by ASN, sorted by total bytes (top 50)
          type: array
          items:
            $ref: '#/components/schemas/InsightASNBytes'
        ContainerNets:
          description: Docker container CIDRs treated as local networks
          type: array
          items:
            type: string
            example: 172.17.0.0/16
    InsightDestination:
      type: object
      properties:
        IP:
          description: Remote destination IP address
          type: string
          example: 142.250.72.14
        Domain:
          description: Resolved domain name for the destination, if known
          type: string
          example: www.google.com
        ASN:
          description: Autonomous System Number of the destination
          type: integer
          example: 15169
        ASNName:
          description: Autonomous System name of the destination
          type: string
          example: GOOGLE
        Country:
          description: ISO country code of the destination
          type: string
          example: US
        BytesIn:
          description: Bytes received from this destination over the window
          type: integer
          format: int64
          example: 65536
        BytesOut:
          description: Bytes sent to this destination over the window
          type: integer
          format: int64
          example: 32768
        LastSeen:
          description: Last time traffic to this destination was observed (RFC3339)
          type: string
          format: date-time
          example: '2026-07-09T11:30:00Z'
    InsightDevice:
      type: object
      properties:
        IP:
          description: Local device IP address
          type: string
          example: 192.168.2.20
        BytesIn:
          description: Total bytes received by the device over the window
          type: integer
          format: int64
          example: 1048576
        BytesOut:
          description: Total bytes sent by the device over the window
          type: integer
          format: int64
          example: 524288
        Destinations:
          description: Remote destinations for the device, sorted by total bytes (top 500)
          type: array
          items:
            $ref: '#/components/schemas/InsightDestination'
    CustomThemeSpec:
      type: object
      properties:
        colorMode:
          description: Base color mode for the theme
          type: string
          example: dark
        accent:
          description: Accent color as a 6-digit hex value
          type: string
          example: '#3b82f6'
        background:
          description: Background color as a 6-digit hex value
          type: string
          example: '#0b1220'
        card:
          description: Card surface color as a 6-digit hex value
          type: string
          example: '#111827'
        text:
          description: Text color as a 6-digit hex value
          type: string
          example: '#e5e7eb'
    CustomTheme:
      type: object
      properties:
        id:
          description: Unique theme identifier matching ^custom-[a-z0-9-]{1,64}$
          type: string
          example: custom-ocean
        name:
          description: Human-readable theme name (1-64 characters)
          type: string
          example: Ocean
        spec:
          description: Color specification for the theme
          $ref: '#/components/schemas/CustomThemeSpec'
    CustomThemeList:
      type: array
      description: Array of custom themes (maximum 32)
      items:
        $ref: '#/components/schemas/CustomTheme'
    WanHealthConfig:
      type: object
      properties:
        Enabled:
          description: Whether WAN health monitoring is enabled
          type: boolean
          example: true
        IntervalSeconds:
          description: Probe interval in seconds (2-60)
          type: integer
          example: 5
        ProbeTargets:
          description: List of IPv4 addresses to probe via ICMP
          type: array
          items:
            type: string
            example: 1.1.1.1
        FailThreshold:
          description: Consecutive probe failures before marking an uplink down (1-60)
          type: integer
          example: 4
        RecoverThreshold:
          description: Consecutive probe successes before marking an uplink up (1-60)
          type: integer
          example: 3
        FailoverEnabled:
          description: Whether to remove a failed uplink from load balancing
          type: boolean
          example: true
        SpeedTestURL:
          description: HTTP(S) URL used for downlink speed tests
          type: string
          example: https://speed.cloudflare.com/__down?bytes=33554432
    WanUplinkStatus:
      type: object
      properties:
        Iface:
          description: Uplink interface name
          type: string
          example: eth0
        Up:
          description: Whether the uplink is currently considered up by health probing
          type: boolean
          example: true
        Active:
          description: Whether the uplink is active in load balancing (not failed over)
          type: boolean
          example: true
        Gateway:
          description: Default gateway address for the uplink
          type: string
          example: 192.168.1.1
        LatencyMs:
          description: Recent average round-trip latency in milliseconds
          type: number
          example: 12.4
        JitterMs:
          description: Recent average jitter in milliseconds
          type: number
          example: 1.8
        LossPct:
          description: Recent packet loss percentage
          type: number
          example: 0
        LastChange:
          description: Unix timestamp of the last up/down transition
          type: integer
          example: 1720000000
        TotalOutages:
          description: Total number of recorded outages for this uplink
          type: integer
          example: 2
        Downtime24h:
          description: Total downtime over the last 24 hours in seconds
          type: integer
          example: 45
    WanSample:
      type: object
      properties:
        Time:
          description: Unix timestamp of the sample
          type: integer
          example: 1720000000
        LatencyMs:
          description: Average round-trip latency in milliseconds
          type: number
          example: 12.4
        JitterMs:
          description: Average jitter in milliseconds
          type: number
          example: 1.8
        LossPct:
          description: Packet loss percentage
          type: number
          example: 0
        Up:
          description: Whether the uplink was up during the sample period
          type: boolean
          example: true
    WanOutage:
      type: object
      properties:
        Iface:
          description: Uplink interface name
          type: string
          example: eth0
        Start:
          description: Unix timestamp when the outage began
          type: integer
          example: 1720000000
        End:
          description: Unix timestamp when the outage ended, or 0 if ongoing
          type: integer
          example: 1720000300
        Reason:
          description: Reason the outage was recorded
          type: string
          example: probe timeouts
    WanSpeedResult:
      type: object
      properties:
        Iface:
          description: Uplink interface name tested
          type: string
          example: eth0
        Time:
          description: Unix timestamp when the test ran
          type: integer
          example: 1720000000
        DownMbps:
          description: Measured download throughput in megabits per second
          type: number
          example: 235.6
        Seconds:
          description: Duration of the download in seconds
          type: number
          example: 1.14
        Bytes:
          description: Number of bytes downloaded during the test
          type: integer
          example: 33554432
        URL:
          description: URL used for the speed test
          type: string
          example: https://speed.cloudflare.com/__down?bytes=33554432
        Error:
          description: Error message if the test failed, omitted on success
          type: string
          example: no data transferred
    ParentCredentials:
      type: object
      properties:
        ParentIP:
          type: string
        ParentAPIToken:
          type: string
        ParentCA:
          type: string
    LeafRouter:
      type: object
      properties:
        APIToken:
          type: string
        IP:
          type: string
        TLSCA:
          type: string
          description: >-
            This field should be left empty when adding or updating a leaf
            router.
    MeshConfig:
      type: object
      properties:
        ParentCredentials:
          $ref: '#/components/schemas/ParentCredentials'
        LeafRouters:
          type: array
          items:
            $ref: '#/components/schemas/LeafRouter'
    WifiConnectEvent:
      type: object
      description: >-
        Event data sent by a mesh node to the main router/AP for station
        connections and disconnections
      properties:
        Event:
          type: string
          description: Type of event (e.g., "connect" or "disconnect")
        Iface:
          type: string
          description: Network interface on the mesh node where the event occurred
        Mac:
          type: string
          description: MAC address of the station
        Router:
          type: string
          description: IP address of the mesh node reporting the event
    WifiConnectFailureEvent:
      type: object
      description: >-
        Event data sent by a mesh node to the main router/AP for failed station
        connection attempts
      properties:
        Type:
          type: string
          description: Type of failure event (e.g., "connection_failure")
        MAC:
          type: string
          description: MAC address of the station that failed to connect
        Reason:
          type: string
          description: Reason for the connection failure
        Status:
          type: string
          description: Status of the connection attempt (e.g., "failure")
        Router:
          type: string
          description: IP address of the mesh node reporting the failure
    OTPUser:
      type: object
      properties:
        Name:
          type: string
          description: Name of the OTP user
        Secret:
          type: string
          description: Secret key for the OTP
        Confirmed:
          type: boolean
          description: Whether the OTP has been confirmed
        AlwaysOn:
          type: boolean
          description: Whether OTP is always required for this user
    OTPSettings:
      type: object
      properties:
        OTPUsers:
          type: array
          items:
            $ref: '#/components/schemas/OTPUser'
        JWTDurationSeconds:
          type: integer
          description: Duration of the JWT token in seconds
    OTPSettingsRequest:
      type: object
      properties:
        Token:
          type: string
          description: Authentication token for the request
        Settings:
          $ref: '#/components/schemas/OTPSettings'
    DNSDomainOverride:
      type: object
      properties:
        Type:
          type: string
          description: type of override (permit or block)
          example: permit
        Domain:
          type: string
          description: domain name to override
          example: example.com
        ResultIP:
          type: string
          description: ip to return
          example: 1.2.3.4
          pattern: /^(?:[0-9]{1,3}\.){3}[0-9]{1,3}$/
        ClientIP:
          type: string
          description: target to apply to, '*' for all
          example: 192.168.2.102
          pattern: /^(?:[0-9]{1,3}\.){3}[0-9]{1,3}$/
        Expiration:
          type: integer
          description: if non zero has unix time for when the entry should disappear
          example: 0
    DNSListEntry:
      type: object
      properties:
        URI:
          type: string
          example: http://asdf.com/
        Enabled:
          type: boolean
          example: true
    DNSBlockMetrics:
      type: object
      properties:
        TotalQueries:
          type: integer
          example: 1024
        BlockedQueries:
          type: integer
          example: 512
        BlockedDomains:
          type: integer
          example: 1000
    LookupASN:
      type: object
      properties:
        IP:
          description: IP address
          type: string
          example: 1.1.1.1
        ASN:
          description: ASN identifier
          type: string
          example: 13335
        Name:
          description: ASN Name
          type: string
          example: CLOUDFLARENET
        Country:
          description: ASN Country
          type: string
          example: US
    GodyndnsDomain:
      type: object
      properties:
        DomainName:
          type: string
          example: supernetworks.org
        SubDomains:
          type: array
          items:
            type: string
          example:
            - dyndns
    GodyndnsConfig:
      type: object
      properties:
        Provider:
          type: string
          example: Cloudflare
        Email:
          type: string
          example: root@localhost.domain
        Password:
          type: string
          example: stringypassword
        LoginToken:
          type: string
          example: logintoken++
        IpUrl:
          type: string
          example: https://ip4.seeip.org
        Ipv6Url:
          type: string
          example: https://ip6.seeip.org
        IpType:
          type: string
          example: IPv4
        Interval:
          type: integer
          description: How many seconds to wait before checking for an update
          example: 300
        Socks5Proxy:
          type: string
          description: socks5 proxy to use
        Resolver:
          type: string
          description: DNS Resolver to use
          example: 8.8.8.8
        RunOnce:
          type: boolean
          description: Run once and exit (note always set to true)
          example: true
        Domains:
          type: array
          items:
            $ref: '#/components/schemas/GodyndnsDomain'
    WireguardUpdate:
      type: object
      properties:
        IP:
          type: string
          pattern: /^(?:[0-9]{1,3}\.){3}[0-9]{1,3}$/
          example: 192.168.2.102
        PublicKey:
          description: Base64 public key
          type: string
          example: 7SdFRh8o76RjUn/y4c7cQgCcCXA85s47/gVAdem3bBI=
        Iface:
          type: string
          example: wg0
        Name:
          type: string
          example: wfh-laptop
    WireguardPeer:
      type: object
      properties:
        PublicKey:
          description: Base64 public key
          type: string
          example: 7SdFRh8o76RjUn/y4c7cQgCcCXA85s47/gVAdem3bBI=
        AllowedIPs:
          description: Allowed IP address
          type: string
          example: 192.168.3.3/32
        Endpoint:
          description: Endpoint to connect to
          type: string
          example: 192.168.2.1:51280
        PresharedKey:
          description: Preshared key
          example: w9bfMAfqRnLjnlHofX+JSzaRDADrW1tvyW1UWzXJjrg=
        PersistentKeepalive:
          description: Keepalive timeout
          type: integer
          example: 25
      xml:
        name: WireguardPeer
    WireguardInterface:
      type: object
      properties:
        PrivateKey:
          description: Base64 private key
          type: string
          example: 6KVVbcmXanU/6mByHy17eNO9DXe9BQJWOyaA204JYH4=
        Address:
          description: IP address for interface
          type: string
          example: 192.168.3.3/24
        DNS:
          description: DNS IP address to use
          type: string
          example: 1.1.1.1
    WireguardConfig:
      type: object
      properties:
        Interface:
          description: Client interface
          $ref: '#/components/schemas/WireguardInterface'
        Peer:
          description: Client peer
          $ref: '#/components/schemas/WireguardPeer'
  requestBodies:
    AlertSetting:
      content:
        application/json:
          schema:
            allOf:
              - description: My AlertSetting
                title: AlertSetting
              - $ref: '#/components/schemas/AlertSetting'
      description: AlertSetting object that needs to be added
      required: true
    DeviceEntry:
      content:
        application/json:
          schema:
            allOf:
              - description: My Device
              - $ref: '#/components/schemas/DeviceEntry'
      description: Device object
      required: true
    GroupEntry:
      content:
        application/json:
          schema:
            allOf:
              - description: My Group
                title: VPN
              - $ref: '#/components/schemas/GroupEntry'
      description: Group object
      required: true
    PSKEntry:
      content:
        application/json:
          schema:
            allOf:
              - description: My PSK
                title: PSK
              - $ref: '#/components/schemas/PSKEntry'
      description: PSKEntry object
      required: true
    PSKAuthFailure:
      content:
        application/json:
          schema:
            allOf:
              - description: My PSKAuthFailure
                title: PSK Auth Failure
              - $ref: '#/components/schemas/PSKAuthFailure'
      description: PSKAuthFailure object that needs to be added
      required: true
    PSKAuthSuccess:
      content:
        application/json:
          schema:
            allOf:
              - description: My PSKAuthSuccess
                title: PSK Auth Success
              - $ref: '#/components/schemas/PSKAuthSuccess'
      description: PSKAuthSuccess object that needs to be added
      required: true
    DHCPUpdate:
      content:
        application/json:
          schema:
            allOf:
              - description: My DHCPUpdate
                title: DHCPUpdate
              - $ref: '#/components/schemas/DHCPUpdate'
      description: DHCPUpdate object that needs to be added
      required: true
    PluginEntry:
      content:
        application/json:
          schema:
            allOf:
              - description: My PluginEntry
                title: PluginEntry
              - $ref: '#/components/schemas/PluginEntry'
      description: PluginEntry to be added or updated
      required: true
    InterfaceEntry:
      content:
        application/json:
          schema:
            allOf:
              - description: InterfaceEntry
                title: InterfaceEntry
              - $ref: '#/components/schemas/InterfaceEntry'
      description: InterfaceEntry to be added or updated
      required: true
    ChannelParameters:
      content:
        application/json:
          schema:
            allOf:
              - description: ChannelParameters
              - $ref: '#/components/schemas/ChannelParameters'
      description: Channel Parameters for WiFi
      required: true
    HostapdConfig:
      content:
        application/json:
          schema:
            allOf:
              - description: HostapdConfig
              - $ref: '#/components/schemas/HostapdConfig'
      description: Channel Parameters for WiFi
      required: true
    AbstractDHCPRequest:
      content:
        application/json:
          schema:
            allOf:
              - description: DHCP Request
                title: AbstractDHCPRequest
              - $ref: '#/components/schemas/AbstractDHCPRequest'
      description: AbstractDHCPRequest for requesting an IP by an Identifier
      required: true
    FirewallBlock:
      content:
        application/json:
          schema:
            allOf:
              - description: Block Source and Destination IP combination
                title: FirewallBlock
              - $ref: '#/components/schemas/FirewallBlock'
      description: FirewallBlock
      required: true
    FirewallForward:
      content:
        application/json:
          schema:
            allOf:
              - description: Forward Source and Destination IP/Port Combination
                title: FirewallBlock
              - $ref: '#/components/schemas/FirewallForward'
      description: >-
        Use 'any' for the port to forward all ports. Specify a port or a port
        range otherwise
      required: true
    FirewallBlockForward:
      content:
        application/json:
          schema:
            allOf:
              - description: Block Forwarding of Traffic
                title: FirewallBlockForward
              - $ref: '#/components/schemas/FirewallBlockForward'
      description: FirewallBlockForward
      required: true
    ServicePort:
      content:
        application/json:
          schema:
            allOf:
              - description: Service Ports to SPR allowed by Firewall
                title: FirewallBlock
              - $ref: '#/components/schemas/ServicePort'
      description: ServicePort
      required: true
    Token:
      content:
        application/json:
          schema:
            allOf:
              - description: My Token
              - $ref: '#/components/schemas/Token'
      description: Token object
      required: true
    Notification:
      content:
        application/json:
          schema:
            allOf:
              - description: Notification
              - $ref: '#/components/schemas/Notification'
      description: Notification object
      required: true
    GeoBlockConfig:
      content:
        application/json:
          schema:
            allOf:
              - description: Geo/ASN blocking configuration
                title: GeoBlockConfig
              - $ref: '#/components/schemas/GeoBlockConfig'
      description: GeoBlockConfig
      required: true
    FirewallBlockOutput:
      content:
        application/json:
          schema:
            allOf:
              - description: Block Output (locally originated) Traffic
                title: FirewallBlockOutput
              - $ref: '#/components/schemas/FirewallBlockOutput'
      description: FirewallBlockOutput
      required: true
    SystemDnsOverride:
      content:
        application/json:
          schema:
            allOf:
              - description: System DNS override upstream IP, empty string to clear
                title: SystemDnsOverride
              - type: string
                example: 8.8.8.8
      description: SystemDnsOverride
      required: true
    RoamingConfig:
      description: Fast-roaming configuration to store
      required: true
      content:
        application/json:
          schema:
            allOf:
              - title: RoamingConfig
                description: Fast-roaming configuration
              - $ref: '#/components/schemas/RoamingConfig'
    BSSTransitionRequest:
      description: BSS transition target for a station
      required: true
      content:
        application/json:
          schema:
            allOf:
              - title: BSSTransitionRequest
                description: BSS transition request
              - $ref: '#/components/schemas/BSSTransitionRequest'
    HostapdDeauthMAC:
      description: JSON string containing the station MAC to deauthenticate
      required: true
      content:
        application/json:
          schema:
            type: string
            description: Station MAC address
            example: '11:22:33:44:55:66'
    DeviceSyncMap:
      content:
        application/json:
          schema:
            allOf:
              - description: Full device map to sync, indexed by identity
                title: DeviceSyncMap
              - $ref: '#/components/schemas/DeviceEntryMap'
      description: Map of devices to sync, indexed by MAC address
      required: true
    DeviceIdentityList:
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/DeviceIdentityList'
      description: Array of device identities to delete
      required: true
    BulkDeviceUpdate:
      content:
        application/json:
          schema:
            allOf:
              - description: Bulk device update request
                title: BulkDeviceUpdate
              - $ref: '#/components/schemas/BulkDeviceUpdate'
      description: Identities plus groups/tags/policies to add
      required: true
    LanLinkIPConfig:
      content:
        application/json:
          schema:
            allOf:
              - description: LAN link IP configuration
                title: LanLinkIPConfig
              - $ref: '#/components/schemas/LanLinkIPConfig'
      description: Interface IP configuration to apply
      required: true
    MobileAlertProxySettings:
      content:
        application/json:
          schema:
            allOf:
              - description: Mobile alert proxy settings
                title: MobileAlertProxySettings
              - $ref: '#/components/schemas/MobileAlertProxySettings'
      description: Mobile alert proxy settings object
      required: true
    AlertDevice:
      content:
        application/json:
          schema:
            allOf:
              - description: Alert device registration
                title: AlertDevice
              - $ref: '#/components/schemas/AlertDevice'
      description: Alert device object
      required: true
    APNSAlert:
      content:
        application/json:
          schema:
            allOf:
              - description: APNS alert payload
                title: APNSAlert
              - $ref: '#/components/schemas/APNSAlert'
      description: APNS alert to send
      required: true
    PluginGitURL:
      content:
        application/json:
          schema:
            allOf:
              - description: Git URL of the plugin to download
                title: PluginGitURL
              - $ref: '#/components/schemas/PluginGitURL'
      description: Git URL string of the user plugin
      required: true
    Persona:
      content:
        application/json:
          schema:
            allOf:
              - description: My Persona
                title: Persona
              - $ref: '#/components/schemas/Persona'
      description: Persona object
      required: true
    ParentalControlRequest:
      content:
        application/json:
          schema:
            allOf:
              - description: Persona pause/extend request
                title: ParentalControlRequest
              - $ref: '#/components/schemas/ParentalControlRequest'
      description: Persona tag and duration in minutes
      required: true
    ParentalResetRequest:
      content:
        application/json:
          schema:
            allOf:
              - description: Persona reset request
                title: ParentalResetRequest
              - $ref: '#/components/schemas/ParentalResetRequest'
      description: Persona tag to reset
      required: true
    setReleaseSettings:
      description: Release channel and version settings to apply
      content:
        application/json:
          schema:
            allOf:
              - title: SetReleaseSettings
                description: Release settings payload
              - $ref: '#/components/schemas/ReleaseInfo'
    setAuthorizedKeys:
      description: Full list of SSH authorized keys to store
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/AuthorizedKeys'
    putSystemInfo:
      description: New value for the named system info field (currently hostname)
      content:
        application/json:
          schema:
            type: string
            example: my-router
    TrafficInsightsConfig:
      content:
        application/json:
          schema:
            allOf:
              - description: Traffic insights configuration
                title: TrafficInsightsConfig
              - $ref: '#/components/schemas/TrafficInsightsConfig'
      description: Traffic insights configuration object
      required: true
    CustomThemeList:
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/CustomThemeList'
      description: Array of custom theme objects to store
      required: true
    WanHealthConfig:
      content:
        application/json:
          schema:
            allOf:
              - description: My WanHealthConfig
                title: WanHealthConfig
              - $ref: '#/components/schemas/WanHealthConfig'
      description: WanHealthConfig object that needs to be updated
      required: true
    DNSDomainOverride:
      content:
        application/json:
          schema:
            allOf:
              - description: My DNSDomainOverride
                title: DNSDomainOverride
              - $ref: '#/components/schemas/DNSDomainOverride'
      description: DNSDomainOverride object that needs to be added
      required: true
    DNSListEntry:
      content:
        application/json:
          schema:
            allOf:
              - description: My DNSListEntry
                title: DNSListEntry
              - $ref: '#/components/schemas/DNSListEntry'
      description: DNSListEntry object that needs to be added
      required: true
    GodyndnsConfig:
      content:
        application/json:
          schema:
            allOf:
              - description: GodyndnsConfig
              - $ref: '#/components/schemas/GodyndnsConfig'
      description: >-
        Dyndns Configuration. See
        [godns](https://github.com/TimothyYe/godns#configuration-file-format)
        for details
      required: true
    WireguardUpdate:
      content:
        application/json:
          schema:
            allOf:
              - description: WireguardUpdate
                title: WireguardUpdate
              - $ref: '#/components/schemas/WireguardUpdate'
      description: WireguardUpdate object that needs to be added
      required: true
    WireguardPeer:
      content:
        application/json:
          schema:
            allOf:
              - description: Peer
              - $ref: '#/components/schemas/WireguardPeer'
      description: Device object
      required: false
  securitySchemes:
    basicAuth:
      description: >
        The API supports Basic Authentication based on the auth_users file,
        using the Basic Schema.


        To implement this, a client should include an "Authorization: Basic"
        header with the credentials formatted as `base64(username:password)`.
        For a javascript example, see the frontend's
        [Api.js](https://github.com/spr-networks/super/blob/main/frontend/src/components/Helpers/Api.js#L38).
      type: http
      scheme: basic
    bearerAuth:
      description: >
        The API also supports Bearer Tokens, based on the `auth_tokens` file.


        To implement this, a client should include an "Authorization: Bearer"
        token.

        See [Swagger's
        page](https://swagger.io/docs/specification/authentication/bearer-authentication/)
        for more examples.
      type: http
      scheme: bearer
    OTPAuth:
      type: apiKey
      in: header
      name: X-JWT-OTP
      description: >-
        A valid JWT proving the OTP was validated recently via the
        `/otp_validate` endpoint
  examples:
    DeviceEntry:
      value:
        Name: mbp
        MAC: '11:22:33:44:55:66'
        WGPubKey: ''
        VLANTag: ''
        RecentIP: 192.168.2.102
        PskEntry:
          Type: sae
          Psk: '**'
        Policies:
          - wan
          - lan
          - dns
          - lan_upstream
        Groups:
          - cameras
          - lightbulbs
        DeviceTags:
          - private
    GroupEntry:
      value:
        Name: vpn
        Disabled: false
        GroupTags:
          - private
    PSKEntry:
      value:
        Type: sae
        Psk: password
    PluginEntry:
      value:
        Name: dns-block
        URI: dns/block
        UnixPath: /state/dns/dns_block_plugin
        Enabled: true
