{
  "openapi": "3.1.0",
  "info": {
    "version": "1.0.0",
    "title": "ZeroTier Central V2 API",
    "description": "API for managing ZeroTier organizations, network groups, networks, and network members.\n\n## Authentication\n\nAll endpoints require an API key passed as a Bearer token:\n```\nAuthorization: Bearer <api-key>\n```\n\nAPI keys are created for service accounts via the `/api/v2/org/{id}/service-account` and\n`/api/v2/service-account/{id}/api-key` endpoints. They can be revoked at any time.\n\n## IAM\n\nAccess to resources is controlled via role-based access control (RBAC). Roles are assigned per resource\nand inherited through the resource hierarchy: `org → network group → network`.\n"
  },
  "servers": [
    {
      "url": "https://central.zerotier.com",
      "description": "Production server"
    }
  ],
  "security": [
    {
      "BearerAuth": []
    }
  ],
  "tags": [
    {
      "name": "org",
      "x-displayName": "Organizations",
      "description": "Manage ZeroTier organizations. An organization is the top-level container for all resources."
    },
    {
      "name": "network-group",
      "x-displayName": "Network Groups",
      "description": "Manage network groups. A network group is a collection of networks within an organization."
    },
    {
      "name": "network",
      "x-displayName": "Networks",
      "description": "Manage ZeroTier networks. Networks define the virtual Layer 2 segment devices connect to."
    },
    {
      "name": "member",
      "x-displayName": "Network Members",
      "description": "Manage devices (members) on a network. Members must be authorized before they can communicate."
    },
    {
      "name": "service-account",
      "x-displayName": "Service Accounts",
      "description": "Manage service accounts and their API keys for programmatic access."
    },
    {
      "name": "user",
      "x-displayName": "Users",
      "description": "Manage the authenticated user and invite new users to organizations."
    },
    {
      "name": "webhook",
      "x-displayName": "Webhooks",
      "description": "Manage webhooks that deliver organization events to external HTTPS endpoints."
    }
  ],
  "paths": {
    "/api/v2/org": {
      "get": {
        "operationId": "listOrgs",
        "summary": "List organizations",
        "description": "Returns all organizations the authenticated user has access to.",
        "tags": [
          "org"
        ],
        "security": [
          {
            "BearerAuth": []
          }
        ],
        "parameters": [
          {
            "in": "query",
            "name": "permission-check",
            "required": false,
            "explode": true,
            "description": "List of permissions to check on each organization. Results include a `permissions` map keyed by permission name.",
            "schema": {
              "type": "array",
              "items": {
                "type": "string"
              }
            }
          },
          {
            "in": "query",
            "name": "latest",
            "required": false,
            "description": "Limits the list to 3 organizations with recent activity, plus any organizations whose IDs are included in this parameter.",
            "schema": {
              "type": "array",
              "items": {
                "type": "string"
              }
            }
          },
          {
            "in": "query",
            "name": "stats",
            "required": false,
            "description": "When true, includes aggregate statistics in the response.",
            "schema": {
              "type": "boolean"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "List of organizations",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Orgs"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/401"
          },
          "403": {
            "$ref": "#/components/responses/403"
          },
          "500": {
            "$ref": "#/components/responses/500"
          }
        }
      },
      "post": {
        "operationId": "createOrg",
        "summary": "Create organization",
        "description": "Creates a new organization. The authenticated user becomes the owner.",
        "tags": [
          "org"
        ],
        "security": [
          {
            "BearerAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateOrgRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Created organization",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/OrgResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/400"
          },
          "401": {
            "$ref": "#/components/responses/401"
          },
          "403": {
            "$ref": "#/components/responses/403"
          },
          "413": {
            "$ref": "#/components/responses/413"
          },
          "500": {
            "$ref": "#/components/responses/500"
          }
        }
      }
    },
    "/api/v2/org/{id}": {
      "get": {
        "operationId": "getOrg",
        "summary": "Get organization",
        "description": "Returns details of a specific organization.",
        "tags": [
          "org"
        ],
        "security": [
          {
            "BearerAuth": []
          }
        ],
        "parameters": [
          {
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "The organization ID"
          }
        ],
        "responses": {
          "200": {
            "description": "Organization details",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/OrgResponse"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/401"
          },
          "403": {
            "$ref": "#/components/responses/403"
          },
          "500": {
            "$ref": "#/components/responses/500"
          }
        }
      },
      "post": {
        "operationId": "updateOrg",
        "summary": "Update organization",
        "description": "Updates properties of an existing organization. Only provided fields are updated.",
        "tags": [
          "org"
        ],
        "security": [
          {
            "BearerAuth": []
          }
        ],
        "parameters": [
          {
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "The organization ID"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/UpdateOrgRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Updated organization details",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/OrgResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/400"
          },
          "401": {
            "$ref": "#/components/responses/401"
          },
          "403": {
            "$ref": "#/components/responses/403"
          },
          "413": {
            "$ref": "#/components/responses/413"
          },
          "500": {
            "$ref": "#/components/responses/500"
          }
        }
      },
      "delete": {
        "operationId": "deleteOrg",
        "summary": "Delete organization",
        "description": "Permanently deletes an organization and all its resources.",
        "tags": [
          "org"
        ],
        "security": [
          {
            "BearerAuth": []
          }
        ],
        "parameters": [
          {
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "The organization ID"
          }
        ],
        "responses": {
          "200": {
            "description": "Organization deleted",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SuccessMessageResponse"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/401"
          },
          "403": {
            "$ref": "#/components/responses/403"
          },
          "500": {
            "$ref": "#/components/responses/500"
          }
        }
      }
    },
    "/api/v2/org/{id}/iam": {
      "get": {
        "operationId": "getOrgIam",
        "summary": "Get organization IAM",
        "description": "Returns the current IAM role assignments for an organization.",
        "tags": [
          "org"
        ],
        "security": [
          {
            "BearerAuth": []
          }
        ],
        "parameters": [
          {
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "The organization ID"
          }
        ],
        "responses": {
          "200": {
            "description": "IAM role assignments for the organization",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Iam"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/401"
          },
          "403": {
            "$ref": "#/components/responses/403"
          },
          "500": {
            "$ref": "#/components/responses/500"
          }
        }
      },
      "post": {
        "operationId": "addOrgIam",
        "summary": "Add organization IAM roles",
        "description": "Grants additional roles to principals on this organization. Existing roles are preserved.",
        "tags": [
          "org"
        ],
        "security": [
          {
            "BearerAuth": []
          }
        ],
        "parameters": [
          {
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "The organization ID"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/IamRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "IAM roles added",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SuccessMessageResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/400"
          },
          "401": {
            "$ref": "#/components/responses/401"
          },
          "403": {
            "$ref": "#/components/responses/403"
          },
          "413": {
            "$ref": "#/components/responses/413"
          },
          "500": {
            "$ref": "#/components/responses/500"
          }
        }
      },
      "put": {
        "operationId": "replaceOrgIam",
        "summary": "Replace organization IAM roles",
        "description": "Replaces the entire IAM policy for this organization. All existing role assignments are overwritten.",
        "tags": [
          "org"
        ],
        "security": [
          {
            "BearerAuth": []
          }
        ],
        "parameters": [
          {
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "The organization ID"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/IamRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "IAM roles replaced",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SuccessMessageResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/400"
          },
          "401": {
            "$ref": "#/components/responses/401"
          },
          "403": {
            "$ref": "#/components/responses/403"
          },
          "413": {
            "$ref": "#/components/responses/413"
          },
          "500": {
            "$ref": "#/components/responses/500"
          }
        }
      },
      "delete": {
        "operationId": "removeOrgIam",
        "summary": "Remove organization IAM roles",
        "description": "Removes specific role assignments from this organization.",
        "tags": [
          "org"
        ],
        "security": [
          {
            "BearerAuth": []
          }
        ],
        "parameters": [
          {
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "The organization ID"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/IamRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "IAM roles removed",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SuccessMessageResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/400"
          },
          "401": {
            "$ref": "#/components/responses/401"
          },
          "403": {
            "$ref": "#/components/responses/403"
          },
          "413": {
            "$ref": "#/components/responses/413"
          },
          "500": {
            "$ref": "#/components/responses/500"
          }
        }
      }
    },
    "/api/v2/org/{id}/iam-tree": {
      "get": {
        "operationId": "getOrgIamTree",
        "summary": "Get organization IAM tree",
        "description": "Returns the full hierarchical IAM structure for the organization, showing role assignments across all nested resources.",
        "tags": [
          "org"
        ],
        "security": [
          {
            "BearerAuth": []
          }
        ],
        "parameters": [
          {
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "The organization ID"
          }
        ],
        "responses": {
          "200": {
            "description": "Hierarchical IAM tree for the organization",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/IamLeaf"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/401"
          },
          "403": {
            "$ref": "#/components/responses/403"
          },
          "500": {
            "$ref": "#/components/responses/500"
          }
        }
      }
    },
    "/api/v2/org/{id}/principal": {
      "get": {
        "operationId": "searchPrincipals",
        "summary": "Search principals",
        "description": "Searches for users within an organization by email. Used for IAM assignment UIs.",
        "tags": [
          "org"
        ],
        "security": [
          {
            "BearerAuth": []
          }
        ],
        "parameters": [
          {
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "The organization ID"
          },
          {
            "in": "query",
            "name": "search",
            "required": true,
            "description": "Search term to match against user email addresses.",
            "schema": {
              "type": "string"
            }
          },
          {
            "in": "query",
            "name": "principal-type",
            "required": false,
            "description": "Filter results to specific principal types. Returns all types if omitted.",
            "schema": {
              "type": "array",
              "items": {
                "type": "string",
                "enum": [
                  "user"
                ]
              }
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Principals matching the search query",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Principals"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/401"
          },
          "403": {
            "$ref": "#/components/responses/403"
          },
          "500": {
            "$ref": "#/components/responses/500"
          }
        }
      }
    },
    "/api/v2/org/{id}/invite-users": {
      "post": {
        "operationId": "inviteUsers",
        "summary": "Invite users to organization",
        "description": "Sends email invitations to one or more users to join an organization.",
        "tags": [
          "user"
        ],
        "security": [
          {
            "BearerAuth": []
          }
        ],
        "parameters": [
          {
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "The organization ID"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/Invite"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Invitations sent",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SuccessMessageResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/400"
          },
          "401": {
            "$ref": "#/components/responses/401"
          },
          "403": {
            "$ref": "#/components/responses/403"
          },
          "413": {
            "$ref": "#/components/responses/413"
          },
          "500": {
            "$ref": "#/components/responses/500"
          }
        }
      }
    },
    "/api/v2/org/{id}/subscription": {
      "get": {
        "operationId": "getOrgSubscription",
        "summary": "Get organization subscription",
        "description": "Returns the current subscription plan and feature entitlements for an organization.",
        "tags": [
          "org"
        ],
        "security": [
          {
            "BearerAuth": []
          }
        ],
        "parameters": [
          {
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "The organization ID"
          }
        ],
        "responses": {
          "200": {
            "description": "Subscription details for the organization",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Subscription"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/401"
          },
          "403": {
            "$ref": "#/components/responses/403"
          },
          "500": {
            "$ref": "#/components/responses/500"
          }
        }
      }
    },
    "/api/v2/org/{id}/network-group": {
      "get": {
        "operationId": "listOrgNetworkGroups",
        "summary": "List organization network groups",
        "description": "Returns all network groups within an organization the authenticated user has access to.",
        "tags": [
          "org"
        ],
        "security": [
          {
            "BearerAuth": []
          }
        ],
        "parameters": [
          {
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "The organization ID"
          },
          {
            "in": "query",
            "name": "stats",
            "required": false,
            "description": "When true, includes aggregate device and network statistics per group.",
            "schema": {
              "type": "boolean"
            }
          },
          {
            "in": "query",
            "name": "permission-check",
            "required": false,
            "explode": true,
            "description": "List of permissions to check on each network group.",
            "schema": {
              "type": "array",
              "items": {
                "type": "string"
              }
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Network groups in the organization",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/NetworkGroups"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/401"
          },
          "403": {
            "$ref": "#/components/responses/403"
          },
          "500": {
            "$ref": "#/components/responses/500"
          }
        }
      },
      "post": {
        "operationId": "createNetworkGroup",
        "summary": "Create network group",
        "description": "Creates a new network group within an organization.",
        "tags": [
          "org"
        ],
        "security": [
          {
            "BearerAuth": []
          }
        ],
        "parameters": [
          {
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "The organization ID"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateNetworkGroupRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Created network group",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/NetworkGroup"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/400"
          },
          "401": {
            "$ref": "#/components/responses/401"
          },
          "403": {
            "$ref": "#/components/responses/403"
          },
          "413": {
            "$ref": "#/components/responses/413"
          },
          "500": {
            "$ref": "#/components/responses/500"
          }
        }
      }
    },
    "/api/v2/network-group": {
      "get": {
        "operationId": "listNetworkGroups",
        "summary": "List network groups",
        "description": "List all network groups the authenticated user has access to. Optionally filter by organization, include statistics, and check specific permissions.",
        "tags": [
          "network-group"
        ],
        "security": [
          {
            "BearerAuth": []
          }
        ],
        "parameters": [
          {
            "in": "query",
            "name": "org-id",
            "required": false,
            "schema": {
              "type": "string"
            },
            "description": "Filter network groups by organization ID"
          },
          {
            "in": "query",
            "name": "stats",
            "required": false,
            "schema": {
              "type": "boolean"
            },
            "description": "Include device and network statistics for each network group"
          },
          {
            "in": "query",
            "name": "permission-check",
            "required": false,
            "explode": true,
            "schema": {
              "type": "array",
              "items": {
                "type": "string"
              }
            },
            "description": "List of permissions to check for each network group (returned in the `permissions` field)"
          }
        ],
        "responses": {
          "200": {
            "description": "Network groups the user has access to",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/NetworkGroups"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/401"
          },
          "403": {
            "$ref": "#/components/responses/403"
          },
          "500": {
            "$ref": "#/components/responses/500"
          }
        }
      }
    },
    "/api/v2/network-group/{id}": {
      "get": {
        "operationId": "getNetworkGroup",
        "summary": "Get network group",
        "description": "Retrieve details for a specific network group by ID.",
        "tags": [
          "network-group"
        ],
        "security": [
          {
            "BearerAuth": []
          }
        ],
        "parameters": [
          {
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "The network group ID"
          }
        ],
        "responses": {
          "200": {
            "description": "Network group details",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/NetworkGroup"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/401"
          },
          "403": {
            "$ref": "#/components/responses/403"
          },
          "500": {
            "$ref": "#/components/responses/500"
          }
        }
      },
      "post": {
        "operationId": "updateNetworkGroup",
        "summary": "Update network group",
        "description": "Update the name or description of a network group.",
        "tags": [
          "network-group"
        ],
        "security": [
          {
            "BearerAuth": []
          }
        ],
        "parameters": [
          {
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "The network group ID"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/UpdateNetworkGroupRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Updated network group",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/NetworkGroup"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/400"
          },
          "401": {
            "$ref": "#/components/responses/401"
          },
          "403": {
            "$ref": "#/components/responses/403"
          },
          "413": {
            "$ref": "#/components/responses/413"
          },
          "500": {
            "$ref": "#/components/responses/500"
          }
        }
      },
      "delete": {
        "operationId": "deleteNetworkGroup",
        "summary": "Delete network group",
        "description": "Permanently delete a network group. The networks of the group are also deleted.",
        "tags": [
          "network-group"
        ],
        "security": [
          {
            "BearerAuth": []
          }
        ],
        "parameters": [
          {
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "The network group ID"
          }
        ],
        "responses": {
          "200": {
            "description": "Network group deleted",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SuccessMessageResponse"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/401"
          },
          "403": {
            "$ref": "#/components/responses/403"
          },
          "500": {
            "$ref": "#/components/responses/500"
          }
        }
      }
    },
    "/api/v2/network-group/{id}/iam": {
      "post": {
        "operationId": "addNetworkGroupIam",
        "summary": "Add network group IAM roles",
        "description": "Grant additional IAM roles to users on this network group without replacing existing roles.",
        "tags": [
          "network-group"
        ],
        "security": [
          {
            "BearerAuth": []
          }
        ],
        "parameters": [
          {
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "The network group ID"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/IamRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Network group IAM roles updated",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SuccessMessageResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/400"
          },
          "401": {
            "$ref": "#/components/responses/401"
          },
          "403": {
            "$ref": "#/components/responses/403"
          },
          "413": {
            "$ref": "#/components/responses/413"
          },
          "500": {
            "$ref": "#/components/responses/500"
          }
        }
      },
      "delete": {
        "operationId": "removeNetworkGroupIam",
        "summary": "Remove network group IAM roles",
        "description": "Revoke IAM roles from users on this network group.",
        "tags": [
          "network-group"
        ],
        "security": [
          {
            "BearerAuth": []
          }
        ],
        "parameters": [
          {
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "The network group ID"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/IamRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Network group IAM roles removed",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SuccessMessageResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/400"
          },
          "401": {
            "$ref": "#/components/responses/401"
          },
          "403": {
            "$ref": "#/components/responses/403"
          },
          "413": {
            "$ref": "#/components/responses/413"
          },
          "500": {
            "$ref": "#/components/responses/500"
          }
        }
      },
      "get": {
        "operationId": "getNetworkGroupIam",
        "summary": "Get network group IAM",
        "description": "Retrieve all IAM role assignments for this network group.",
        "tags": [
          "network-group"
        ],
        "security": [
          {
            "BearerAuth": []
          }
        ],
        "parameters": [
          {
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "The network group ID"
          }
        ],
        "responses": {
          "200": {
            "description": "IAM role assignments for the network group",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Iam"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/401"
          },
          "403": {
            "$ref": "#/components/responses/403"
          },
          "500": {
            "$ref": "#/components/responses/500"
          }
        }
      },
      "put": {
        "operationId": "replaceNetworkGroupIam",
        "summary": "Replace network group IAM roles",
        "description": "Replace all IAM role assignments on this network group. Existing roles not included in the request are removed.",
        "tags": [
          "network-group"
        ],
        "security": [
          {
            "BearerAuth": []
          }
        ],
        "parameters": [
          {
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "The network group ID"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/IamRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Network group IAM roles replaced",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SuccessMessageResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/400"
          },
          "401": {
            "$ref": "#/components/responses/401"
          },
          "403": {
            "$ref": "#/components/responses/403"
          },
          "413": {
            "$ref": "#/components/responses/413"
          },
          "500": {
            "$ref": "#/components/responses/500"
          }
        }
      }
    },
    "/api/v2/network-group/{id}/network": {
      "get": {
        "operationId": "listNetworkGroupNetworks",
        "summary": "List networks in network group",
        "description": "List all networks within a network group. Optionally include device statistics and check specific permissions.",
        "tags": [
          "network-group"
        ],
        "security": [
          {
            "BearerAuth": []
          }
        ],
        "parameters": [
          {
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "The network group ID"
          },
          {
            "in": "query",
            "name": "stats",
            "required": false,
            "schema": {
              "type": "boolean"
            },
            "description": "Include device statistics for each network"
          },
          {
            "in": "query",
            "name": "permission-check",
            "required": false,
            "explode": true,
            "schema": {
              "type": "array",
              "items": {
                "type": "string"
              }
            },
            "description": "List of permissions to check for each network (returned in the `permissions` field)"
          }
        ],
        "responses": {
          "200": {
            "description": "Networks in the network group",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Networks"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/401"
          },
          "403": {
            "$ref": "#/components/responses/403"
          },
          "500": {
            "$ref": "#/components/responses/500"
          }
        }
      },
      "post": {
        "operationId": "createNetwork",
        "summary": "Create network",
        "description": "Create a new network within a network group.",
        "tags": [
          "network-group"
        ],
        "security": [
          {
            "BearerAuth": []
          }
        ],
        "parameters": [
          {
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "The network group ID"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateNetworkRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Created network",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/NetworkResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/400"
          },
          "401": {
            "$ref": "#/components/responses/401"
          },
          "403": {
            "$ref": "#/components/responses/403"
          },
          "413": {
            "$ref": "#/components/responses/413"
          },
          "500": {
            "$ref": "#/components/responses/500"
          }
        }
      }
    },
    "/api/v2/network": {
      "get": {
        "operationId": "listNetworks",
        "summary": "List networks",
        "description": "List all networks the authenticated user has access to. Optionally filter by organization, include device statistics, and check specific permissions.",
        "tags": [
          "network"
        ],
        "security": [
          {
            "BearerAuth": []
          }
        ],
        "parameters": [
          {
            "in": "query",
            "name": "org-id",
            "required": false,
            "schema": {
              "type": "string"
            },
            "description": "Filter networks by organization ID"
          },
          {
            "in": "query",
            "name": "stats",
            "required": false,
            "schema": {
              "type": "boolean"
            },
            "description": "Include device statistics for each network"
          },
          {
            "in": "query",
            "name": "permission-check",
            "required": false,
            "explode": true,
            "schema": {
              "type": "array",
              "items": {
                "type": "string"
              }
            },
            "description": "List of permissions to check for each network (returned in the `permissions` field)"
          }
        ],
        "responses": {
          "200": {
            "description": "Networks the user has access to",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Networks"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/401"
          },
          "403": {
            "$ref": "#/components/responses/403"
          },
          "500": {
            "$ref": "#/components/responses/500"
          }
        }
      }
    },
    "/api/v2/network/{id}": {
      "get": {
        "operationId": "getNetwork",
        "summary": "Get network",
        "description": "Retrieve details for a specific network by ID.",
        "tags": [
          "network"
        ],
        "security": [
          {
            "BearerAuth": []
          }
        ],
        "parameters": [
          {
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "The network ID"
          }
        ],
        "responses": {
          "200": {
            "description": "Network details",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/NetworkResponse"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/401"
          },
          "403": {
            "$ref": "#/components/responses/403"
          },
          "404": {
            "description": "Network not found"
          },
          "500": {
            "$ref": "#/components/responses/500"
          }
        }
      },
      "post": {
        "operationId": "updateNetwork",
        "summary": "Update network",
        "description": "Update the name, description, or configuration of a network. Only provided fields are updated.",
        "tags": [
          "network"
        ],
        "security": [
          {
            "BearerAuth": []
          }
        ],
        "parameters": [
          {
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "The network ID"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/UpdateNetworkRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Updated network details",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/NetworkResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/400"
          },
          "401": {
            "$ref": "#/components/responses/401"
          },
          "403": {
            "$ref": "#/components/responses/403"
          },
          "404": {
            "description": "Network not found"
          },
          "413": {
            "$ref": "#/components/responses/413"
          },
          "500": {
            "$ref": "#/components/responses/500"
          }
        }
      },
      "delete": {
        "operationId": "deleteNetwork",
        "summary": "Delete network",
        "description": "Permanently delete a network and all its members.",
        "tags": [
          "network"
        ],
        "security": [
          {
            "BearerAuth": []
          }
        ],
        "parameters": [
          {
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "The network ID"
          }
        ],
        "responses": {
          "200": {
            "description": "Network deleted",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SuccessMessageResponse"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/401"
          },
          "403": {
            "$ref": "#/components/responses/403"
          },
          "404": {
            "description": "Network not found"
          },
          "500": {
            "$ref": "#/components/responses/500"
          }
        }
      }
    },
    "/api/v2/network/{id}/iam": {
      "post": {
        "operationId": "addNetworkIam",
        "summary": "Add network IAM roles",
        "description": "Grant additional IAM roles to users on this network without replacing existing roles.",
        "tags": [
          "network"
        ],
        "security": [
          {
            "BearerAuth": []
          }
        ],
        "parameters": [
          {
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "The network ID"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/IamRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Network IAM roles updated",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SuccessMessageResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/400"
          },
          "401": {
            "$ref": "#/components/responses/401"
          },
          "403": {
            "$ref": "#/components/responses/403"
          },
          "413": {
            "$ref": "#/components/responses/413"
          },
          "500": {
            "$ref": "#/components/responses/500"
          }
        }
      },
      "delete": {
        "operationId": "removeNetworkIam",
        "summary": "Remove network IAM roles",
        "description": "Revoke IAM roles from users on this network.",
        "tags": [
          "network"
        ],
        "security": [
          {
            "BearerAuth": []
          }
        ],
        "parameters": [
          {
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "The network ID"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/IamRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Network IAM roles removed",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SuccessMessageResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/400"
          },
          "401": {
            "$ref": "#/components/responses/401"
          },
          "403": {
            "$ref": "#/components/responses/403"
          },
          "413": {
            "$ref": "#/components/responses/413"
          },
          "500": {
            "$ref": "#/components/responses/500"
          }
        }
      },
      "get": {
        "operationId": "getNetworkIam",
        "summary": "Get network IAM",
        "description": "Retrieve all IAM role assignments for this network.",
        "tags": [
          "network"
        ],
        "security": [
          {
            "BearerAuth": []
          }
        ],
        "parameters": [
          {
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "The network ID"
          }
        ],
        "responses": {
          "200": {
            "description": "IAM role assignments for the network",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Iam"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/401"
          },
          "403": {
            "$ref": "#/components/responses/403"
          },
          "500": {
            "$ref": "#/components/responses/500"
          }
        }
      },
      "put": {
        "operationId": "replaceNetworkIam",
        "summary": "Replace network IAM roles",
        "description": "Replace all IAM role assignments on this network. Existing roles not included in the request are removed.",
        "tags": [
          "network"
        ],
        "security": [
          {
            "BearerAuth": []
          }
        ],
        "parameters": [
          {
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "The network ID"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/IamRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Network IAM roles replaced",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SuccessMessageResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/400"
          },
          "401": {
            "$ref": "#/components/responses/401"
          },
          "403": {
            "$ref": "#/components/responses/403"
          },
          "413": {
            "$ref": "#/components/responses/413"
          },
          "500": {
            "$ref": "#/components/responses/500"
          }
        }
      }
    },
    "/api/v2/network/{id}/member": {
      "post": {
        "operationId": "addNetworkMembers",
        "summary": "Add network members",
        "description": "Add one or more devices to the network. Devices are not authorized until explicitly authorized.",
        "tags": [
          "member"
        ],
        "security": [
          {
            "BearerAuth": []
          }
        ],
        "parameters": [
          {
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "The network ID"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "array",
                "items": {
                  "$ref": "#/components/schemas/PostMembersRequest"
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Updated network member device list",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/NetworkMembers"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/400"
          },
          "401": {
            "$ref": "#/components/responses/401"
          },
          "403": {
            "$ref": "#/components/responses/403"
          },
          "413": {
            "$ref": "#/components/responses/413"
          },
          "500": {
            "$ref": "#/components/responses/500"
          }
        }
      },
      "delete": {
        "operationId": "removeNetworkMembers",
        "summary": "Remove network members",
        "description": "Remove one or more devices from the network by device ID.",
        "tags": [
          "member"
        ],
        "security": [
          {
            "BearerAuth": []
          }
        ],
        "parameters": [
          {
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "The network ID"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "array",
                "items": {
                  "$ref": "#/components/schemas/DeleteMembersRequest"
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Members removed from the network",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SuccessMessageResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/400"
          },
          "401": {
            "$ref": "#/components/responses/401"
          },
          "403": {
            "$ref": "#/components/responses/403"
          },
          "413": {
            "$ref": "#/components/responses/413"
          },
          "500": {
            "$ref": "#/components/responses/500"
          }
        }
      },
      "get": {
        "operationId": "listNetworkMembers",
        "summary": "List network members",
        "description": "Retrieve all device members on the network.",
        "tags": [
          "member"
        ],
        "security": [
          {
            "BearerAuth": []
          }
        ],
        "parameters": [
          {
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "The network ID"
          }
        ],
        "responses": {
          "200": {
            "description": "Device members on the network",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/NetworkMembers"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/401"
          },
          "403": {
            "$ref": "#/components/responses/403"
          },
          "500": {
            "$ref": "#/components/responses/500"
          }
        }
      }
    },
    "/api/v2/network/{id}/member/authorize": {
      "post": {
        "operationId": "authorizeNetworkMembers",
        "summary": "Authorize network members (bulk)",
        "description": "Authorize multiple devices on the network by device ID. Authorized devices can communicate on the network.",
        "tags": [
          "member"
        ],
        "security": [
          {
            "BearerAuth": []
          }
        ],
        "parameters": [
          {
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "The network ID"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "array",
                "items": {
                  "type": "string",
                  "description": "Device ID (10-character hex string)",
                  "minLength": 10,
                  "maxLength": 10,
                  "pattern": "^[0-9a-fA-F]{10}$"
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Devices authorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SuccessMessageResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/400"
          },
          "401": {
            "$ref": "#/components/responses/401"
          },
          "403": {
            "$ref": "#/components/responses/403"
          },
          "413": {
            "$ref": "#/components/responses/413"
          },
          "500": {
            "$ref": "#/components/responses/500"
          }
        }
      }
    },
    "/api/v2/network/{id}/member/de-authorize": {
      "post": {
        "operationId": "deauthorizeNetworkMembers",
        "summary": "Deauthorize network members (bulk)",
        "description": "Deauthorize multiple devices on the network by device ID. Deauthorized devices can no longer communicate on the network.",
        "tags": [
          "member"
        ],
        "security": [
          {
            "BearerAuth": []
          }
        ],
        "parameters": [
          {
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "The network ID"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "array",
                "items": {
                  "type": "string",
                  "description": "Device ID (10-character hex string)",
                  "minLength": 10,
                  "maxLength": 10,
                  "pattern": "^[0-9a-fA-F]{10}$"
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Devices deauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SuccessMessageResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/400"
          },
          "401": {
            "$ref": "#/components/responses/401"
          },
          "403": {
            "$ref": "#/components/responses/403"
          },
          "413": {
            "$ref": "#/components/responses/413"
          },
          "500": {
            "$ref": "#/components/responses/500"
          }
        }
      }
    },
    "/api/v2/network/{id}/member/reject": {
      "post": {
        "operationId": "rejectNetworkMembers",
        "summary": "Reject network members (bulk)",
        "description": "Reject multiple devices on the network by device ID. Rejected devices are blocked from joining the network.",
        "tags": [
          "member"
        ],
        "security": [
          {
            "BearerAuth": []
          }
        ],
        "parameters": [
          {
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "The network ID"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "array",
                "items": {
                  "type": "string",
                  "description": "Device ID (10-character hex string)",
                  "minLength": 10,
                  "maxLength": 10,
                  "pattern": "^[0-9a-fA-F]{10}$"
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Devices rejected",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SuccessMessageResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/400"
          },
          "401": {
            "$ref": "#/components/responses/401"
          },
          "403": {
            "$ref": "#/components/responses/403"
          },
          "413": {
            "$ref": "#/components/responses/413"
          },
          "500": {
            "$ref": "#/components/responses/500"
          }
        }
      }
    },
    "/api/v2/network/{id}/member/{device-id}": {
      "get": {
        "operationId": "getNetworkMember",
        "summary": "Get network member",
        "description": "Retrieve details for a specific device member on a network.",
        "tags": [
          "member"
        ],
        "security": [
          {
            "BearerAuth": []
          }
        ],
        "parameters": [
          {
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "The network ID"
          },
          {
            "in": "path",
            "name": "device-id",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "The device ID"
          }
        ],
        "responses": {
          "200": {
            "description": "Device member details",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/NetworkMember"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/401"
          },
          "403": {
            "$ref": "#/components/responses/403"
          },
          "404": {
            "description": "Member not found"
          },
          "500": {
            "$ref": "#/components/responses/500"
          }
        }
      },
      "post": {
        "operationId": "updateNetworkMember",
        "summary": "Update network member",
        "description": "Update the configuration of a specific device member on a network.",
        "tags": [
          "member"
        ],
        "security": [
          {
            "BearerAuth": []
          }
        ],
        "parameters": [
          {
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "The network ID"
          },
          {
            "in": "path",
            "name": "device-id",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "The device ID"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/UpdateMemberRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Updated device member",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/NetworkMember"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/400"
          },
          "401": {
            "$ref": "#/components/responses/401"
          },
          "403": {
            "$ref": "#/components/responses/403"
          },
          "404": {
            "description": "Member not found"
          },
          "413": {
            "$ref": "#/components/responses/413"
          },
          "500": {
            "$ref": "#/components/responses/500"
          }
        }
      }
    },
    "/api/v2/network/{id}/member/{device-id}/authorize": {
      "post": {
        "operationId": "authorizeNetworkMember",
        "summary": "Authorize network member",
        "description": "Authorize a specific device to communicate on the network.",
        "tags": [
          "member"
        ],
        "security": [
          {
            "BearerAuth": []
          }
        ],
        "parameters": [
          {
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "The network ID"
          },
          {
            "in": "path",
            "name": "device-id",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "The device ID"
          }
        ],
        "responses": {
          "200": {
            "description": "Authorized device member",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/NetworkMember"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/401"
          },
          "403": {
            "$ref": "#/components/responses/403"
          },
          "404": {
            "description": "Member not found"
          },
          "500": {
            "$ref": "#/components/responses/500"
          }
        }
      }
    },
    "/api/v2/network/{id}/member/{device-id}/de-authorize": {
      "post": {
        "operationId": "deauthorizeNetworkMember",
        "summary": "Deauthorize network member",
        "description": "Deauthorize a specific device, preventing it from communicating on the network.",
        "tags": [
          "member"
        ],
        "security": [
          {
            "BearerAuth": []
          }
        ],
        "parameters": [
          {
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "The network ID"
          },
          {
            "in": "path",
            "name": "device-id",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "The device ID"
          }
        ],
        "responses": {
          "200": {
            "description": "Deauthorized device member",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/NetworkMember"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/401"
          },
          "403": {
            "$ref": "#/components/responses/403"
          },
          "404": {
            "description": "Member not found"
          },
          "500": {
            "$ref": "#/components/responses/500"
          }
        }
      }
    },
    "/api/v2/network/{id}/member/{device-id}/reject": {
      "post": {
        "operationId": "rejectNetworkMember",
        "summary": "Reject network member",
        "description": "Reject a specific device, blocking it from joining the network.",
        "tags": [
          "member"
        ],
        "security": [
          {
            "BearerAuth": []
          }
        ],
        "parameters": [
          {
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "The network ID"
          },
          {
            "in": "path",
            "name": "device-id",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "The device ID"
          }
        ],
        "responses": {
          "200": {
            "description": "Rejected device member",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/NetworkMember"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/401"
          },
          "403": {
            "$ref": "#/components/responses/403"
          },
          "404": {
            "description": "Member not found"
          },
          "500": {
            "$ref": "#/components/responses/500"
          }
        }
      }
    },
    "/api/v2beta/network/{id}/flow-rule": {
      "get": {
        "operationId": "getNetworkFlowRules",
        "summary": "Get flow rules",
        "description": "Retrieve the current flow rules for a network. Flow rules control how traffic is routed between devices. **This endpoint is in beta and may change.**",
        "tags": [
          "network"
        ],
        "security": [
          {
            "BearerAuth": []
          }
        ],
        "parameters": [
          {
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "The network ID"
          }
        ],
        "responses": {
          "200": {
            "description": "Flow rules for the network",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/FlowRules"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/401"
          },
          "403": {
            "$ref": "#/components/responses/403"
          },
          "404": {
            "description": "Network not found"
          },
          "500": {
            "$ref": "#/components/responses/500"
          }
        }
      },
      "post": {
        "operationId": "updateNetworkFlowRules",
        "summary": "Update flow rules",
        "description": "Update the flow rules for a network. Supports two modes: `custom` for raw flow rule source, and `isolation` for managed network isolation with service filters. **This endpoint is in beta and may change.**",
        "tags": [
          "network"
        ],
        "security": [
          {
            "BearerAuth": []
          }
        ],
        "parameters": [
          {
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "The network ID"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/UpdateFlowRulesRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Updated flow rules",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/FlowRules"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/400"
          },
          "401": {
            "$ref": "#/components/responses/401"
          },
          "403": {
            "$ref": "#/components/responses/403"
          },
          "404": {
            "description": "Network not found"
          },
          "413": {
            "$ref": "#/components/responses/413"
          },
          "500": {
            "$ref": "#/components/responses/500"
          }
        }
      }
    },
    "/api/v2/org/{id}/service-account": {
      "get": {
        "operationId": "listServiceAccounts",
        "summary": "List service accounts",
        "description": "List all service accounts in an organization.",
        "tags": [
          "service-account"
        ],
        "security": [
          {
            "BearerAuth": []
          }
        ],
        "parameters": [
          {
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "The organization ID"
          }
        ],
        "responses": {
          "200": {
            "description": "Service accounts for the organization",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ServiceAccounts"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/401"
          },
          "403": {
            "$ref": "#/components/responses/403"
          },
          "500": {
            "$ref": "#/components/responses/500"
          }
        }
      },
      "post": {
        "operationId": "createServiceAccount",
        "summary": "Create service account",
        "description": "Create a new service account in an organization. Service accounts are used for programmatic API access.",
        "tags": [
          "service-account"
        ],
        "security": [
          {
            "BearerAuth": []
          }
        ],
        "parameters": [
          {
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "The organization ID"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateServiceAccountRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Created service account",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ServiceAccountResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/400"
          },
          "401": {
            "$ref": "#/components/responses/401"
          },
          "403": {
            "$ref": "#/components/responses/403"
          },
          "413": {
            "$ref": "#/components/responses/413"
          },
          "500": {
            "$ref": "#/components/responses/500"
          }
        }
      }
    },
    "/api/v2/service-account/{id}": {
      "get": {
        "operationId": "getServiceAccount",
        "summary": "Get service account",
        "description": "Retrieve details for a specific service account.",
        "tags": [
          "service-account"
        ],
        "security": [
          {
            "BearerAuth": []
          }
        ],
        "parameters": [
          {
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "The service account ID"
          }
        ],
        "responses": {
          "200": {
            "description": "Service account details",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ServiceAccountResponse"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/401"
          },
          "403": {
            "$ref": "#/components/responses/403"
          },
          "500": {
            "$ref": "#/components/responses/500"
          }
        }
      },
      "post": {
        "operationId": "updateServiceAccount",
        "summary": "Update service account",
        "description": "Update the name or description of a service account.",
        "tags": [
          "service-account"
        ],
        "security": [
          {
            "BearerAuth": []
          }
        ],
        "parameters": [
          {
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "The service account ID"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/UpdateServiceAccountRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Updated service account",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ServiceAccountResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/400"
          },
          "401": {
            "$ref": "#/components/responses/401"
          },
          "403": {
            "$ref": "#/components/responses/403"
          },
          "413": {
            "$ref": "#/components/responses/413"
          },
          "500": {
            "$ref": "#/components/responses/500"
          }
        }
      },
      "delete": {
        "operationId": "deleteServiceAccount",
        "summary": "Delete service account",
        "description": "Permanently delete a service account and all its API keys.",
        "tags": [
          "service-account"
        ],
        "security": [
          {
            "BearerAuth": []
          }
        ],
        "parameters": [
          {
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "The service account ID"
          }
        ],
        "responses": {
          "200": {
            "description": "Service account deleted",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SuccessMessageResponse"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/401"
          },
          "403": {
            "$ref": "#/components/responses/403"
          },
          "500": {
            "$ref": "#/components/responses/500"
          }
        }
      }
    },
    "/api/v2/service-account/{id}/api-key": {
      "post": {
        "operationId": "createApiKey",
        "summary": "Create API key",
        "description": "Create a new API key for a service account. The secret key value is returned **only once** in this response — store it securely, as it cannot be retrieved again.",
        "tags": [
          "service-account"
        ],
        "security": [
          {
            "BearerAuth": []
          }
        ],
        "parameters": [
          {
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "The service account ID"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateApiKeyRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Created API key (secret is only returned in this response)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/NewApiKeyResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/400"
          },
          "401": {
            "$ref": "#/components/responses/401"
          },
          "403": {
            "$ref": "#/components/responses/403"
          },
          "413": {
            "$ref": "#/components/responses/413"
          },
          "500": {
            "$ref": "#/components/responses/500"
          }
        }
      }
    },
    "/api/v2/api-key/{id}": {
      "get": {
        "operationId": "getApiKey",
        "summary": "Get API key",
        "description": "Retrieve metadata for a specific API key. The secret key value is never returned after creation.",
        "tags": [
          "service-account"
        ],
        "security": [
          {
            "BearerAuth": []
          }
        ],
        "parameters": [
          {
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "The API key ID"
          }
        ],
        "responses": {
          "200": {
            "description": "API key metadata",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiKeyResponse"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/401"
          },
          "403": {
            "$ref": "#/components/responses/403"
          },
          "500": {
            "$ref": "#/components/responses/500"
          }
        }
      },
      "post": {
        "operationId": "updateApiKey",
        "summary": "Update API key",
        "description": "Update the name or description of an API key.",
        "tags": [
          "service-account"
        ],
        "security": [
          {
            "BearerAuth": []
          }
        ],
        "parameters": [
          {
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "The API key ID"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/UpdateApiKeyRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Updated API key metadata",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiKeyResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/400"
          },
          "401": {
            "$ref": "#/components/responses/401"
          },
          "403": {
            "$ref": "#/components/responses/403"
          },
          "413": {
            "$ref": "#/components/responses/413"
          },
          "500": {
            "$ref": "#/components/responses/500"
          }
        }
      },
      "delete": {
        "operationId": "deleteApiKey",
        "summary": "Delete API key",
        "description": "Permanently revoke and delete an API key. Requests using this key will immediately fail.",
        "tags": [
          "service-account"
        ],
        "security": [
          {
            "BearerAuth": []
          }
        ],
        "parameters": [
          {
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "The API key ID"
          }
        ],
        "responses": {
          "200": {
            "description": "API key deleted",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SuccessMessageResponse"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/401"
          },
          "403": {
            "$ref": "#/components/responses/403"
          },
          "500": {
            "$ref": "#/components/responses/500"
          }
        }
      }
    },
    "/api/v2/user/check-permissions": {
      "post": {
        "operationId": "checkPermissions",
        "summary": "Check permissions",
        "description": "Batch-checks whether the authenticated user has specific permissions on one or more resources.",
        "tags": [
          "user"
        ],
        "security": [
          {
            "BearerAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "array",
                "items": {
                  "$ref": "#/components/schemas/CheckPermissionRequest"
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Permission check results, one entry per request item",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/CheckPermissionResponse"
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/400"
          },
          "401": {
            "$ref": "#/components/responses/401"
          },
          "403": {
            "$ref": "#/components/responses/403"
          },
          "413": {
            "$ref": "#/components/responses/413"
          },
          "500": {
            "$ref": "#/components/responses/500"
          }
        }
      }
    },
    "/api/v2/user": {
      "post": {
        "operationId": "updateUser",
        "summary": "Update current user",
        "description": "Updates profile information for the authenticated user.",
        "tags": [
          "user"
        ],
        "security": [
          {
            "BearerAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/UpdateUserRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Updated user profile",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/User"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/400"
          },
          "401": {
            "$ref": "#/components/responses/401"
          },
          "403": {
            "$ref": "#/components/responses/403"
          },
          "413": {
            "$ref": "#/components/responses/413"
          },
          "500": {
            "$ref": "#/components/responses/500"
          }
        }
      },
      "delete": {
        "operationId": "deleteUser",
        "summary": "Delete current user",
        "description": "Permanently deletes the authenticated user account.",
        "tags": [
          "user"
        ],
        "security": [
          {
            "BearerAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "User deleted",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SuccessMessageResponse"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/401"
          },
          "403": {
            "$ref": "#/components/responses/403"
          },
          "500": {
            "$ref": "#/components/responses/500"
          }
        }
      }
    },
    "/api/v2/org/{id}/webhook": {
      "get": {
        "operationId": "listWebhooks",
        "tags": [
          "webhook"
        ],
        "summary": "List webhooks for an organization",
        "security": [
          {
            "BearerAuth": []
          }
        ],
        "parameters": [
          {
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "The organization ID"
          }
        ],
        "responses": {
          "200": {
            "description": "Webhooks for the organization",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebhooksList"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/401"
          },
          "403": {
            "$ref": "#/components/responses/403"
          },
          "500": {
            "$ref": "#/components/responses/500"
          }
        }
      },
      "post": {
        "operationId": "createWebhook",
        "tags": [
          "webhook"
        ],
        "summary": "Create a webhook",
        "security": [
          {
            "BearerAuth": []
          }
        ],
        "parameters": [
          {
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "The organization ID"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateWebhookRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Created webhook",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebhookResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/400"
          },
          "401": {
            "$ref": "#/components/responses/401"
          },
          "403": {
            "$ref": "#/components/responses/403"
          },
          "413": {
            "$ref": "#/components/responses/413"
          },
          "500": {
            "$ref": "#/components/responses/500"
          }
        }
      }
    },
    "/api/v2/webhook/{id}": {
      "get": {
        "operationId": "getWebhook",
        "tags": [
          "webhook"
        ],
        "summary": "Get a webhook by ID",
        "security": [
          {
            "BearerAuth": []
          }
        ],
        "parameters": [
          {
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "The webhook ID"
          }
        ],
        "responses": {
          "200": {
            "description": "Webhook details",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebhookResponse"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/401"
          },
          "403": {
            "$ref": "#/components/responses/403"
          },
          "500": {
            "$ref": "#/components/responses/500"
          }
        }
      },
      "post": {
        "operationId": "updateWebhook",
        "tags": [
          "webhook"
        ],
        "summary": "Update a webhook",
        "security": [
          {
            "BearerAuth": []
          }
        ],
        "parameters": [
          {
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "The webhook ID"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/UpdateWebhookRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Updated webhook",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebhookResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/400"
          },
          "401": {
            "$ref": "#/components/responses/401"
          },
          "403": {
            "$ref": "#/components/responses/403"
          },
          "413": {
            "$ref": "#/components/responses/413"
          },
          "500": {
            "$ref": "#/components/responses/500"
          }
        }
      },
      "delete": {
        "operationId": "deleteWebhook",
        "tags": [
          "webhook"
        ],
        "summary": "Delete a webhook",
        "security": [
          {
            "BearerAuth": []
          }
        ],
        "parameters": [
          {
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "The webhook ID"
          }
        ],
        "responses": {
          "200": {
            "description": "Webhook deleted",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SuccessMessageResponse"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/401"
          },
          "403": {
            "$ref": "#/components/responses/403"
          },
          "500": {
            "$ref": "#/components/responses/500"
          }
        }
      }
    },
    "/api/v2/webhook/{id}/rotate-secret": {
      "post": {
        "operationId": "rotateWebhookSecret",
        "tags": [
          "webhook"
        ],
        "summary": "Rotate the webhook signing secret",
        "description": "Generates a new signing secret and places the previous secret into a grace/overlap window. The response contains exactly two active secrets: the new primary (expiryAt null) and the previous primary (expiryAt set to now + overlapHours).\nIf an overlap secret is already active (a previous rotation is still within its grace window), rotation is blocked and a 409 Conflict is returned. The caller must first explicitly revoke the overlap secret via DELETE /webhook-secret/{id}, or wait for the grace window to expire, before rotating again. This ensures the active secret count never exceeds two and makes the invariant explicit rather than silently evicting secrets.\n",
        "security": [
          {
            "BearerAuth": []
          }
        ],
        "parameters": [
          {
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "The webhook ID"
          }
        ],
        "requestBody": {
          "required": false,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/RotateWebhookSecretRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Webhook with the new and previous secrets",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebhookResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/400"
          },
          "401": {
            "$ref": "#/components/responses/401"
          },
          "403": {
            "$ref": "#/components/responses/403"
          },
          "409": {
            "description": "An overlap secret is already active. Revoke it first via DELETE /webhook-secret/{id} or wait for its grace window to expire.\n"
          },
          "413": {
            "$ref": "#/components/responses/413"
          },
          "500": {
            "$ref": "#/components/responses/500"
          }
        }
      }
    },
    "/api/v2/webhook-secret/{id}": {
      "delete": {
        "operationId": "deleteWebhookSecret",
        "tags": [
          "webhook"
        ],
        "summary": "Revoke an overlap secret early",
        "description": "Immediately revokes an overlap secret before its grace window expires. The active primary secret (expiryAt null) cannot be deleted — rotate first. Attempting to delete the primary returns 400.\n",
        "security": [
          {
            "BearerAuth": []
          }
        ],
        "parameters": [
          {
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "The webhook secret ID to revoke"
          }
        ],
        "responses": {
          "200": {
            "description": "Secret revoked",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SuccessMessageResponse"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/401"
          },
          "403": {
            "$ref": "#/components/responses/403"
          },
          "500": {
            "$ref": "#/components/responses/500"
          }
        }
      }
    }
  },
  "components": {
    "schemas": {
      "BadRequestResponse": {
        "type": "object",
        "required": [
          "code",
          "message"
        ],
        "properties": {
          "code": {
            "type": "integer",
            "description": "HTTP status code",
            "example": 400
          },
          "message": {
            "type": "string",
            "description": "Human-readable error summary",
            "example": "validation failed"
          },
          "details": {
            "type": "array",
            "description": "Per-field validation errors, present when the request body fails validation",
            "items": {
              "type": "object",
              "required": [
                "field",
                "message"
              ],
              "properties": {
                "field": {
                  "type": "string",
                  "description": "JSON field path that failed validation",
                  "example": "name"
                },
                "message": {
                  "type": "string",
                  "description": "Reason the field failed validation",
                  "example": "name is required"
                }
              }
            }
          }
        }
      },
      "SuccessMessageResponse": {
        "type": "object",
        "required": [
          "message"
        ],
        "properties": {
          "message": {
            "type": "string",
            "description": "Human-readable confirmation message",
            "example": "success"
          }
        }
      },
      "Orgs": {
        "type": "object",
        "required": [
          "items"
        ],
        "properties": {
          "items": {
            "type": "array",
            "items": {
              "type": "object",
              "required": [
                "id",
                "name"
              ],
              "properties": {
                "id": {
                  "type": "string"
                },
                "name": {
                  "type": "string"
                },
                "permissions": {
                  "$ref": "#/components/schemas/PermissionCheckDetails"
                }
              }
            }
          },
          "stats": {
            "type": "object",
            "required": [
              "totalOrgs"
            ],
            "properties": {
              "totalOrgs": {
                "type": "integer",
                "description": "The total number of organizations the user has access to, or -1 if the total could not be determined due to performance limits."
              }
            }
          }
        }
      },
      "OrgResponse": {
        "type": "object",
        "required": [
          "id",
          "name"
        ],
        "properties": {
          "id": {
            "type": "string"
          },
          "name": {
            "type": "string"
          }
        }
      },
      "CreateOrgRequest": {
        "type": "object",
        "required": [
          "name"
        ],
        "properties": {
          "name": {
            "type": "string"
          }
        },
        "example": {
          "name": "Acme Corp"
        }
      },
      "UpdateOrgRequest": {
        "type": "object",
        "properties": {
          "name": {
            "type": "string"
          }
        },
        "example": {
          "name": "Acme Corp (Renamed)"
        }
      },
      "Principals": {
        "type": "object",
        "required": [
          "items"
        ],
        "properties": {
          "items": {
            "type": "array",
            "items": {
              "type": "object",
              "required": [
                "id",
                "name",
                "principalType"
              ],
              "properties": {
                "id": {
                  "type": "string"
                },
                "name": {
                  "type": "string"
                },
                "principalType": {
                  "type": "string",
                  "enum": [
                    "user"
                  ]
                }
              }
            }
          }
        }
      },
      "IamLeaf": {
        "type": "object",
        "required": [
          "id",
          "name",
          "principalType",
          "principals",
          "children"
        ],
        "properties": {
          "id": {
            "type": "string"
          },
          "name": {
            "type": "string"
          },
          "principalType": {
            "type": "string",
            "enum": [
              "user",
              "team"
            ]
          },
          "principals": {
            "type": "array",
            "items": {
              "type": "object",
              "required": [
                "id",
                "name",
                "principalType",
                "roles"
              ],
              "properties": {
                "id": {
                  "type": "string"
                },
                "name": {
                  "type": "string"
                },
                "principalType": {
                  "type": "string",
                  "enum": [
                    "user"
                  ]
                },
                "roles": {
                  "type": "array",
                  "items": {
                    "type": "string"
                  }
                }
              }
            }
          },
          "children": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/IamLeaf"
            }
          }
        }
      },
      "Iam": {
        "type": "array",
        "description": "All IAM role assignments on a resource",
        "items": {
          "$ref": "#/components/schemas/IamTuple"
        }
      },
      "IamTuple": {
        "type": "object",
        "description": "An existing IAM role assignment on a resource.",
        "required": [
          "principal",
          "principalType",
          "roles"
        ],
        "properties": {
          "principal": {
            "type": "string",
            "description": "Identifier of the principal (email for users and service accounts)"
          },
          "principalType": {
            "type": "string",
            "enum": [
              "user",
              "service_account"
            ],
            "description": "The kind of principal that holds these roles"
          },
          "roles": {
            "type": "array",
            "description": "Roles currently assigned to the principal on this resource",
            "items": {
              "$ref": "#/components/schemas/IamRole"
            }
          }
        }
      },
      "IamRequest": {
        "type": "array",
        "description": "List of principal–roles assignments. Semantics depend on the HTTP method: `POST` adds the specified roles, `DELETE` removes them, `PUT` replaces all existing assignments.",
        "items": {
          "$ref": "#/components/schemas/IamTupleRequest"
        },
        "example": [
          {
            "principal": "alice@example.com",
            "roles": [
              "Admin"
            ]
          },
          {
            "principal": "bob@example.com",
            "roles": [
              "Viewer"
            ]
          }
        ]
      },
      "IamTupleRequest": {
        "type": "object",
        "description": "A principal–roles assignment to apply to a resource.",
        "required": [
          "principal",
          "roles"
        ],
        "properties": {
          "principal": {
            "type": "string",
            "format": "email",
            "description": "Email address of the user or service account to assign roles to",
            "example": "alice@example.com"
          },
          "roles": {
            "type": "array",
            "minItems": 1,
            "uniqueItems": true,
            "items": {
              "$ref": "#/components/schemas/IamRole"
            },
            "description": "One or more roles to assign to the principal"
          }
        },
        "example": {
          "principal": "alice@example.com",
          "roles": [
            "Admin"
          ]
        }
      },
      "IamRole": {
        "type": "string",
        "enum": [
          "Owner",
          "Admin",
          "Editor",
          "Viewer",
          "NetworkGroupAdmin",
          "NetworkGroupEditor",
          "NetworkGroupViewer",
          "NetworkAdmin",
          "NetworkEditor",
          "NetworkViewer"
        ],
        "description": "Role of a principal on a resource. Roles are hierarchical and inherited through the resource tree (`org → network group → network`). Org-level roles (`Owner`, `Admin`, `Editor`, `Viewer`) apply to all child resources. Resource-scoped roles (`NetworkGroupAdmin`, `NetworkAdmin`, etc.) apply only at the specified level and below."
      },
      "Invite": {
        "type": "object",
        "required": [
          "emails"
        ],
        "properties": {
          "emails": {
            "type": "array",
            "description": "List of email addresses to invite",
            "items": {
              "type": "string",
              "format": "email"
            }
          }
        },
        "example": {
          "emails": [
            "alice@example.com",
            "bob@example.com"
          ]
        }
      },
      "NetworkGroup": {
        "type": "object",
        "required": [
          "id",
          "name",
          "description",
          "orgId"
        ],
        "properties": {
          "id": {
            "type": "string"
          },
          "name": {
            "type": "string"
          },
          "description": {
            "type": "string"
          },
          "orgId": {
            "type": "string"
          }
        }
      },
      "NetworkGroups": {
        "type": "object",
        "required": [
          "items"
        ],
        "properties": {
          "items": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/NetworkGroupSummary"
            }
          },
          "stats": {
            "$ref": "#/components/schemas/NetworkGroupsListStats"
          }
        }
      },
      "NetworkGroupSummary": {
        "type": "object",
        "required": [
          "id",
          "name",
          "description",
          "orgId"
        ],
        "properties": {
          "id": {
            "type": "string"
          },
          "name": {
            "type": "string"
          },
          "description": {
            "type": "string"
          },
          "orgId": {
            "type": "string"
          },
          "stats": {
            "$ref": "#/components/schemas/NetworkGroupSummaryStats"
          },
          "permissions": {
            "$ref": "#/components/schemas/PermissionCheckDetails"
          }
        }
      },
      "NetworkGroupSummaryStats": {
        "type": "object",
        "required": [
          "activeDevices",
          "authorizedDevices",
          "unauthorizedMemberships",
          "totalNetworks"
        ],
        "properties": {
          "activeDevices": {
            "type": "integer"
          },
          "authorizedDevices": {
            "type": "integer"
          },
          "unauthorizedMemberships": {
            "type": "integer"
          },
          "totalNetworks": {
            "type": "integer"
          }
        }
      },
      "NetworkGroupsListStats": {
        "type": "object",
        "required": [
          "unauthorizedMemberships",
          "authorizedDevices",
          "totalNetworks"
        ],
        "properties": {
          "unauthorizedMemberships": {
            "type": "integer"
          },
          "authorizedDevices": {
            "type": "integer"
          },
          "totalNetworks": {
            "type": "integer"
          }
        }
      },
      "CreateNetworkGroupRequest": {
        "type": "object",
        "required": [
          "name"
        ],
        "properties": {
          "name": {
            "type": "string"
          },
          "description": {
            "type": "string"
          }
        },
        "example": {
          "name": "Production",
          "description": "Production network group"
        }
      },
      "UpdateNetworkGroupRequest": {
        "type": "object",
        "properties": {
          "name": {
            "type": "string"
          },
          "description": {
            "type": "string"
          }
        },
        "example": {
          "name": "Production (Updated)",
          "description": "Updated production network group"
        }
      },
      "Networks": {
        "type": "object",
        "required": [
          "items"
        ],
        "properties": {
          "items": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/NetworkSummary"
            }
          },
          "stats": {
            "$ref": "#/components/schemas/NetworksListStats"
          }
        }
      },
      "NetworkSummary": {
        "type": "object",
        "required": [
          "id",
          "name",
          "networkGroupId",
          "networkGroupName",
          "kind"
        ],
        "properties": {
          "id": {
            "type": "string",
            "description": "Unique network identifier"
          },
          "name": {
            "type": "string",
            "description": "Display name of the network"
          },
          "networkGroupId": {
            "type": "string",
            "description": "ID of the network group this network belongs to"
          },
          "networkGroupName": {
            "type": "string",
            "description": "Display name of the network group"
          },
          "description": {
            "type": "string",
            "description": "Description of the network (may be an empty string)"
          },
          "kind": {
            "type": "string",
            "description": "The kind of ZeroTier network (e.g. `v1`)"
          },
          "stats": {
            "$ref": "#/components/schemas/NetworkStats"
          },
          "permissions": {
            "$ref": "#/components/schemas/PermissionCheckDetails"
          }
        }
      },
      "NetworkMember": {
        "type": "object",
        "required": [
          "deviceId",
          "networkId",
          "name",
          "description",
          "status",
          "activeBridge",
          "ipv4Assignments",
          "ipv6Assignments",
          "ipAssignment6plane",
          "ipAssignmentRfc4193",
          "noAutoAssignIps",
          "capabilities",
          "tags",
          "creationTime",
          "lastModified",
          "identity",
          "revision",
          "agentVersion",
          "macAddress",
          "lastSeen",
          "lastSeenIp",
          "os",
          "arch"
        ],
        "properties": {
          "deviceId": {
            "type": "string",
            "description": "Unique device identifier"
          },
          "networkId": {
            "type": "string",
            "description": "ID of the network this member belongs to"
          },
          "name": {
            "type": "string",
            "description": "Display name of the device"
          },
          "description": {
            "type": "string",
            "description": "Description of the device"
          },
          "status": {
            "type": "string",
            "enum": [
              "authorized",
              "not_authorized",
              "rejected"
            ],
            "description": "Authorization status of the device on this network"
          },
          "activeBridge": {
            "type": "boolean",
            "description": "Whether this device acts as an active bridge"
          },
          "ipv4Assignments": {
            "type": "array",
            "description": "IPv4 addresses assigned to this device on the network",
            "items": {
              "type": "string",
              "format": "ipv4"
            }
          },
          "ipv6Assignments": {
            "type": "array",
            "description": "IPv6 addresses assigned to this device on the network",
            "items": {
              "type": "string",
              "format": "ipv6"
            }
          },
          "ipAssignment6plane": {
            "type": "string",
            "format": "ipv6",
            "description": "IPv6 address assigned via 6PLANE addressing"
          },
          "ipAssignmentRfc4193": {
            "type": "string",
            "format": "ipv6",
            "description": "IPv6 address assigned via RFC 4193 addressing"
          },
          "noAutoAssignIps": {
            "type": "boolean",
            "description": "Whether automatic IP address assignment is disabled for this device"
          },
          "capabilities": {
            "type": "array",
            "description": "ZeroTier capability IDs granted to this device",
            "items": {
              "type": "string"
            }
          },
          "creationTime": {
            "type": "string",
            "format": "date-time",
            "description": "Time the device was first seen on the network"
          },
          "lastModified": {
            "type": "string",
            "format": "date-time",
            "description": "Time the member record was last modified"
          },
          "identity": {
            "type": "string",
            "description": "ZeroTier public identity of the device"
          },
          "lastAuthorizedCredential": {
            "type": "string",
            "description": "Credential used for the last authorization"
          },
          "lastAuthorizedTime": {
            "type": "string",
            "format": "date-time",
            "description": "Time the device was last authorized"
          },
          "lastDeauthorizedTime": {
            "type": "string",
            "format": "date-time",
            "description": "Time the device was last deauthorized"
          },
          "revision": {
            "type": "integer",
            "description": "Revision counter for the member record"
          },
          "tags": {
            "type": "array",
            "description": "ZeroTier tag IDs applied to this device",
            "items": {
              "type": "string"
            }
          },
          "agentVersion": {
            "type": "string",
            "description": "ZeroTier client version running on the device"
          },
          "macAddress": {
            "type": "string",
            "description": "MAC address of the device's virtual network interface"
          },
          "lastSeen": {
            "type": "object",
            "description": "Map of IP/port to last-seen timestamp",
            "additionalProperties": {
              "type": "string"
            }
          },
          "lastSeenIp": {
            "type": "string",
            "description": "Last known public IP address of the device"
          },
          "lastSeenTime": {
            "type": "string",
            "format": "date-time",
            "description": "Time the device was last seen by a controller"
          },
          "os": {
            "type": "string",
            "description": "Operating system reported by the ZeroTier client"
          },
          "arch": {
            "type": "string",
            "description": "CPU architecture reported by the ZeroTier client"
          }
        }
      },
      "NetworkMembers": {
        "type": "array",
        "items": {
          "$ref": "#/components/schemas/NetworkMember"
        }
      },
      "UpdateMemberRequest": {
        "type": "object",
        "description": "All fields are optional. Only provided fields are updated.",
        "properties": {
          "name": {
            "type": "string",
            "description": "Display name for the device"
          },
          "description": {
            "type": "string",
            "description": "Description of the device (may be an empty string)"
          },
          "activeBridge": {
            "type": "boolean",
            "description": "Whether this device acts as an active bridge"
          },
          "noAutoAssignIps": {
            "type": "boolean",
            "description": "Disable automatic IP address assignment for this device"
          },
          "ipv4Assignments": {
            "type": "array",
            "description": "Static IPv4 addresses to assign to this device",
            "items": {
              "type": "string",
              "format": "ipv4"
            }
          },
          "ipv6Assignments": {
            "type": "array",
            "description": "Static IPv6 addresses to assign to this device",
            "items": {
              "type": "string",
              "format": "ipv6"
            }
          }
        },
        "example": {
          "name": "Alice's Laptop (updated)",
          "ipv4Assignments": [
            "10.147.20.10"
          ]
        }
      },
      "PostMembersRequest": {
        "type": "object",
        "required": [
          "deviceId"
        ],
        "properties": {
          "deviceId": {
            "type": "string",
            "description": "Device ID to add to the network",
            "minLength": 10,
            "maxLength": 10,
            "pattern": "^[0-9a-fA-F]{10}$"
          },
          "name": {
            "type": "string",
            "description": "Display name for the device"
          },
          "description": {
            "type": "string",
            "description": "Description of the device (may be an empty string)"
          },
          "activeBridge": {
            "type": "boolean",
            "description": "Whether this device acts as an active bridge"
          },
          "noAutoAssignIps": {
            "type": "boolean",
            "description": "Disable automatic IP address assignment for this device"
          },
          "ipv4Assignments": {
            "type": "array",
            "description": "Static IPv4 addresses to assign to this device",
            "items": {
              "type": "string",
              "format": "ipv4"
            }
          },
          "ipv6Assignments": {
            "type": "array",
            "description": "Static IPv6 addresses to assign to this device",
            "items": {
              "type": "string",
              "format": "ipv6"
            }
          }
        },
        "example": {
          "deviceId": "cafe001234",
          "name": "Alice's Laptop",
          "description": "MacBook Pro",
          "ipv4Assignments": [
            "10.147.20.5"
          ]
        }
      },
      "DeleteMembersRequest": {
        "type": "object",
        "required": [
          "deviceId"
        ],
        "properties": {
          "deviceId": {
            "type": "string",
            "description": "Device ID to remove from the network (10-character hex string)",
            "minLength": 10,
            "maxLength": 10,
            "pattern": "^[0-9a-fA-F]{10}$"
          }
        },
        "example": {
          "deviceId": "cafe001234"
        }
      },
      "FlowRules": {
        "oneOf": [
          {
            "$ref": "#/components/schemas/FlowRulesCustom"
          },
          {
            "$ref": "#/components/schemas/FlowRulesIsolation"
          }
        ],
        "discriminator": {
          "propertyName": "kind",
          "mapping": {
            "custom": "#/components/schemas/FlowRulesCustom",
            "isolation": "#/components/schemas/FlowRulesIsolation"
          }
        }
      },
      "FlowRulesCustom": {
        "type": "object",
        "required": [
          "kind",
          "config"
        ],
        "properties": {
          "kind": {
            "type": "string",
            "enum": [
              "custom"
            ],
            "description": "The kind of flow rule"
          },
          "config": {
            "$ref": "#/components/schemas/FlowRulesCustomConfig"
          }
        }
      },
      "FlowRulesCustomConfig": {
        "type": "object",
        "required": [
          "source"
        ],
        "properties": {
          "source": {
            "type": "string",
            "description": "Raw ZeroTier flow rule source code"
          }
        }
      },
      "FlowRulesIsolation": {
        "type": "object",
        "required": [
          "kind",
          "config"
        ],
        "properties": {
          "kind": {
            "type": "string",
            "enum": [
              "isolation"
            ],
            "description": "The kind of flow rule"
          },
          "config": {
            "$ref": "#/components/schemas/FlowRulesIsolationConfig"
          }
        }
      },
      "FlowRulesIsolationConfig": {
        "type": "object",
        "required": [
          "blockNonIP",
          "enableServiceFilter",
          "allowedServices",
          "excludedDeviceIds"
        ],
        "properties": {
          "blockNonIP": {
            "type": "boolean",
            "description": "Whether to block non-IP traffic (e.g. ARP, IPv6 NDP)"
          },
          "enableServiceFilter": {
            "type": "boolean",
            "description": "Whether to restrict traffic to only the ports and protocols in `allowedServices`"
          },
          "allowedServices": {
            "type": "array",
            "description": "Ports and protocols to allow when service filtering is enabled",
            "items": {
              "$ref": "#/components/schemas/FlowRuleIsolationAllowedPorts"
            }
          },
          "excludedDeviceIds": {
            "type": "array",
            "description": "Device IDs exempt from isolation rules (can communicate freely)",
            "items": {
              "type": "string",
              "minLength": 10,
              "maxLength": 10,
              "pattern": "^[0-9a-fA-F]{10}$"
            }
          }
        }
      },
      "FlowRuleIsolationAllowedPorts": {
        "type": "object",
        "required": [
          "ports",
          "protocol"
        ],
        "properties": {
          "ports": {
            "type": "string",
            "description": "Port list in ZeroTier format: single port (`80`), range (`8000-9000`), or comma-separated"
          },
          "protocol": {
            "type": "integer",
            "minimum": 0,
            "maximum": 255,
            "description": "IP protocol number (e.g. 6 = TCP, 17 = UDP, 1 = ICMP)"
          }
        }
      },
      "UpdateFlowRulesRequest": {
        "oneOf": [
          {
            "$ref": "#/components/schemas/UpdateFlowRulesCustomRequest"
          },
          {
            "$ref": "#/components/schemas/UpdateFlowRulesIsolationRequest"
          }
        ],
        "discriminator": {
          "propertyName": "kind",
          "mapping": {
            "custom": "#/components/schemas/UpdateFlowRulesCustomRequest",
            "isolation": "#/components/schemas/UpdateFlowRulesIsolationRequest"
          }
        }
      },
      "UpdateFlowRulesCustomRequest": {
        "type": "object",
        "required": [
          "kind"
        ],
        "properties": {
          "kind": {
            "type": "string",
            "enum": [
              "custom"
            ],
            "description": "The kind of flow rule"
          },
          "config": {
            "$ref": "#/components/schemas/UpdateFlowRulesCustomConfig"
          }
        },
        "example": {
          "kind": "custom",
          "config": {
            "source": "drop ethertype ipv6\naccept"
          }
        }
      },
      "UpdateFlowRulesCustomConfig": {
        "type": "object",
        "properties": {
          "source": {
            "type": "string",
            "description": "Raw ZeroTier flow rule source code"
          }
        }
      },
      "UpdateFlowRulesIsolationRequest": {
        "type": "object",
        "required": [
          "kind"
        ],
        "properties": {
          "kind": {
            "type": "string",
            "enum": [
              "isolation"
            ],
            "description": "The kind of flow rule"
          },
          "config": {
            "$ref": "#/components/schemas/UpdateFlowRulesIsolationConfig"
          }
        },
        "example": {
          "kind": "isolation",
          "config": {
            "blockNonIP": true,
            "enableServiceFilter": true,
            "allowedServices": [
              {
                "ports": "443",
                "protocol": 6
              },
              {
                "ports": "53",
                "protocol": 17
              }
            ],
            "excludedDeviceIds": [
              "cafe001234"
            ]
          }
        }
      },
      "UpdateFlowRulesIsolationConfig": {
        "type": "object",
        "description": "All fields are optional. Only provided fields are updated.",
        "properties": {
          "blockNonIP": {
            "type": "boolean",
            "description": "Whether to block non-IP traffic (e.g. ARP, IPv6 NDP)"
          },
          "enableServiceFilter": {
            "type": "boolean",
            "description": "Whether to restrict traffic to only the ports and protocols in `allowedServices`"
          },
          "allowedServices": {
            "type": "array",
            "description": "Ports and protocols to allow when service filtering is enabled",
            "items": {
              "$ref": "#/components/schemas/FlowRuleIsolationAllowedPorts"
            }
          },
          "excludedDeviceIds": {
            "type": "array",
            "description": "Device IDs exempt from isolation rules (can communicate freely)",
            "items": {
              "type": "string",
              "minLength": 10,
              "maxLength": 10,
              "pattern": "^[0-9a-fA-F]{10}$"
            }
          }
        }
      },
      "ServiceAccounts": {
        "type": "object",
        "required": [
          "items"
        ],
        "properties": {
          "items": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ServiceAccountResponse"
            }
          }
        }
      },
      "ServiceAccountResponse": {
        "type": "object",
        "required": [
          "id",
          "name",
          "description",
          "orgId",
          "apiKeys",
          "creationTime",
          "lastModified"
        ],
        "properties": {
          "id": {
            "type": "string"
          },
          "name": {
            "type": "string"
          },
          "description": {
            "type": "string"
          },
          "orgId": {
            "type": "string"
          },
          "apiKeys": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ApiKeyResponse"
            }
          },
          "creationTime": {
            "type": "string",
            "format": "date-time",
            "description": "Time the service account was created",
            "readOnly": true
          },
          "lastModified": {
            "type": "string",
            "format": "date-time",
            "description": "Time the service account was last modified",
            "readOnly": true
          }
        }
      },
      "CreateServiceAccountRequest": {
        "type": "object",
        "required": [
          "id",
          "name"
        ],
        "properties": {
          "id": {
            "type": "string"
          },
          "name": {
            "type": "string"
          },
          "description": {
            "type": "string"
          }
        },
        "example": {
          "id": "ci-deploy",
          "name": "CI Deploy Bot",
          "description": "Used by the CI pipeline to manage networks"
        }
      },
      "UpdateServiceAccountRequest": {
        "type": "object",
        "properties": {
          "name": {
            "type": "string"
          },
          "description": {
            "type": "string"
          }
        },
        "example": {
          "name": "CI Deploy Bot v2",
          "description": "Updated deploy bot for v2 pipeline"
        }
      },
      "ApiKeyResponse": {
        "type": "object",
        "required": [
          "id",
          "serviceAccountId",
          "description",
          "creationTime",
          "lastModified"
        ],
        "properties": {
          "id": {
            "type": "string"
          },
          "serviceAccountId": {
            "type": "string"
          },
          "description": {
            "type": "string"
          },
          "expires": {
            "type": "string",
            "format": "date-time",
            "description": "Expiration time of the API key"
          },
          "creationTime": {
            "type": "string",
            "format": "date-time",
            "description": "Time the API key was created"
          },
          "lastModified": {
            "type": "string",
            "format": "date-time",
            "description": "Time the API key was last modified"
          },
          "lastUsed": {
            "type": "string",
            "format": "date-time",
            "description": "Time the API key was last used"
          }
        }
      },
      "NewApiKeyResponse": {
        "type": "object",
        "required": [
          "id",
          "serviceAccountId",
          "description",
          "expires",
          "key",
          "creationTime",
          "lastModified"
        ],
        "properties": {
          "id": {
            "type": "string"
          },
          "serviceAccountId": {
            "type": "string"
          },
          "description": {
            "type": "string"
          },
          "expires": {
            "type": "string",
            "format": "date-time",
            "description": "Expiration time of the API key"
          },
          "key": {
            "type": "string",
            "description": "The API key value"
          },
          "creationTime": {
            "type": "string",
            "format": "date-time",
            "description": "Time the API key was created"
          },
          "lastModified": {
            "type": "string",
            "format": "date-time",
            "description": "Time the API key was last modified"
          }
        }
      },
      "CreateApiKeyRequest": {
        "type": "object",
        "required": [
          "expires"
        ],
        "properties": {
          "description": {
            "type": "string"
          },
          "expires": {
            "type": "string",
            "format": "date-time"
          }
        },
        "example": {
          "description": "CI deploy key — expires annually",
          "expires": "2027-04-08T00:00:00Z"
        }
      },
      "UpdateApiKeyRequest": {
        "type": "object",
        "properties": {
          "description": {
            "type": "string"
          }
        },
        "example": {
          "description": "Updated key description"
        }
      },
      "SearchResult": {
        "type": "object",
        "properties": {
          "found": {
            "type": "boolean"
          }
        }
      },
      "User": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "description": "Unique identifier for the user",
            "readOnly": true
          },
          "email": {
            "type": "string",
            "format": "email",
            "description": "Email address of the user (unique within ZeroTier)",
            "readOnly": true
          },
          "firstName": {
            "type": "string"
          },
          "lastName": {
            "type": "string"
          }
        }
      },
      "UpdateUserRequest": {
        "type": "object",
        "properties": {
          "firstName": {
            "type": "string"
          },
          "lastName": {
            "type": "string"
          }
        },
        "example": {
          "firstName": "Alice",
          "lastName": "Smith"
        }
      },
      "CheckPermissionRequest": {
        "type": "object",
        "required": [
          "resourceId",
          "resourceType",
          "permission"
        ],
        "properties": {
          "resourceId": {
            "type": "string",
            "description": "The ID of the resource to check permissions for"
          },
          "resourceType": {
            "type": "string",
            "enum": [
              "org",
              "network_group",
              "network"
            ],
            "description": "The type of resource to check permissions for"
          },
          "permission": {
            "type": "string",
            "description": "The permission to check"
          }
        },
        "example": {
          "resourceId": "a1b2c3d4e5",
          "resourceType": "network",
          "permission": "updateNetwork"
        }
      },
      "CheckPermissionResponse": {
        "type": "object",
        "required": [
          "resourceId",
          "resourceType",
          "permission",
          "allowed"
        ],
        "properties": {
          "resourceId": {
            "type": "string",
            "description": "The ID of the resource that was checked"
          },
          "resourceType": {
            "type": "string",
            "enum": [
              "org",
              "network_group",
              "network"
            ],
            "description": "The type of resource that was checked"
          },
          "permission": {
            "type": "string",
            "description": "The permission that was checked"
          },
          "allowed": {
            "type": "boolean",
            "description": "Whether the permission is allowed"
          }
        }
      },
      "WebhookSecret": {
        "type": "object",
        "required": [
          "id",
          "webhookId",
          "value",
          "createdAt",
          "lastModified"
        ],
        "properties": {
          "id": {
            "type": "string"
          },
          "webhookId": {
            "type": "string"
          },
          "value": {
            "type": "string",
            "description": "The HMAC-SHA256 signing secret value"
          },
          "createdAt": {
            "type": "string",
            "format": "date-time"
          },
          "lastModified": {
            "type": "string",
            "format": "date-time"
          },
          "expiryAt": {
            "type": "string",
            "format": "date-time",
            "nullable": true,
            "description": "When set, the secret is in a grace/overlap window and will stop being valid after this time. Null means this is the active primary secret.\n"
          }
        }
      },
      "WebhookResponse": {
        "type": "object",
        "required": [
          "id",
          "orgId",
          "url",
          "eventList",
          "secrets",
          "createdAt",
          "lastModified"
        ],
        "properties": {
          "id": {
            "type": "string"
          },
          "orgId": {
            "type": "string"
          },
          "description": {
            "type": "string"
          },
          "url": {
            "type": "string",
            "format": "uri",
            "description": "The HTTPS endpoint URL that will receive webhook events. Must be a fully-qualified domain name (FQDN) — raw IP addresses are not allowed. The domain must not resolve to private or internal IP ranges (RFC1918, loopback, link-local, etc.)."
          },
          "eventList": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Event types that trigger this webhook"
          },
          "secrets": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/WebhookSecret"
            },
            "description": "Active secrets for this webhook. Normally contains one entry (the primary). During a rotation overlap window there will be two: the new primary (expiryAt null) and the previous primary (expiryAt set).\n"
          },
          "createdAt": {
            "type": "string",
            "format": "date-time"
          },
          "lastModified": {
            "type": "string",
            "format": "date-time"
          }
        }
      },
      "WebhooksList": {
        "type": "object",
        "required": [
          "items"
        ],
        "properties": {
          "items": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/WebhookResponse"
            }
          }
        }
      },
      "CreateWebhookRequest": {
        "type": "object",
        "required": [
          "url",
          "eventList"
        ],
        "properties": {
          "description": {
            "type": "string",
            "maxLength": 255
          },
          "url": {
            "type": "string",
            "format": "uri",
            "description": "The HTTPS endpoint URL that will receive webhook events. Must be a fully-qualified domain name (FQDN) — raw IP addresses are not allowed. The domain must not resolve to private or internal IP ranges (RFC1918, loopback, link-local, etc.).",
            "example": "https://hooks.example.com/zerotier/events"
          },
          "eventList": {
            "type": "array",
            "minItems": 1,
            "items": {
              "type": "string"
            }
          }
        }
      },
      "UpdateWebhookRequest": {
        "type": "object",
        "properties": {
          "description": {
            "type": "string",
            "maxLength": 255
          },
          "url": {
            "type": "string",
            "format": "uri",
            "description": "The HTTPS endpoint URL that will receive webhook events. Must be a fully-qualified domain name (FQDN) — raw IP addresses are not allowed. The domain must not resolve to private or internal IP ranges (RFC1918, loopback, link-local, etc.)."
          },
          "eventList": {
            "type": "array",
            "minItems": 1,
            "items": {
              "type": "string"
            }
          }
        }
      },
      "RotateWebhookSecretRequest": {
        "type": "object",
        "properties": {
          "overlapHours": {
            "type": "integer",
            "minimum": 0,
            "maximum": 720,
            "default": 24,
            "description": "How many hours the previous secret remains valid after rotation. Defaults to 24. Use 0 for an immediate hard cutover with no overlap.\n"
          }
        }
      },
      "MessageResponse": {
        "type": "object",
        "required": [
          "message"
        ],
        "properties": {
          "message": {
            "type": "string",
            "description": "Human-readable error message",
            "example": "an error occurred"
          }
        }
      },
      "PermissionCheckDetails": {
        "type": "object",
        "description": "Map of permission name to whether the authenticated principal has that permission on the resource",
        "additionalProperties": {
          "type": "boolean"
        }
      },
      "NumericEntitlement": {
        "type": "object",
        "required": [
          "value",
          "kind",
          "max",
          "hasUnlimitedUsage"
        ],
        "properties": {
          "value": {
            "type": "integer"
          },
          "max": {
            "type": "integer",
            "description": "Maximum allowed"
          },
          "kind": {
            "type": "string",
            "enum": [
              "numeric-hard-cap",
              "numeric-soft-cap"
            ]
          },
          "hasUnlimitedUsage": {
            "type": "boolean",
            "description": "True if unlimited usages allowed."
          },
          "resetPeriod": {
            "type": "string",
            "enum": [
              "hourly",
              "daily",
              "weekly",
              "monthly",
              "yearly"
            ]
          },
          "resetsWhen": {
            "type": "string",
            "format": "date-time"
          }
        }
      },
      "BooleanEntitlement": {
        "type": "object",
        "required": [
          "value",
          "kind"
        ],
        "properties": {
          "value": {
            "type": "boolean"
          },
          "kind": {
            "type": "string",
            "enum": [
              "boolean"
            ]
          }
        }
      },
      "SubscriptionEntitlements": {
        "type": "object",
        "required": [
          "admins",
          "devices",
          "networks",
          "networkGroups",
          "customRoutes",
          "customDns",
          "flowRulesCustom",
          "flowRulesTemplates",
          "publicNetworks",
          "fullRebac",
          "serviceAccounts",
          "api",
          "webhooks"
        ],
        "properties": {
          "admins": {
            "$ref": "#/components/schemas/NumericEntitlement"
          },
          "devices": {
            "$ref": "#/components/schemas/NumericEntitlement"
          },
          "networks": {
            "$ref": "#/components/schemas/NumericEntitlement"
          },
          "networkGroups": {
            "$ref": "#/components/schemas/NumericEntitlement"
          },
          "customRoutes": {
            "$ref": "#/components/schemas/BooleanEntitlement"
          },
          "customDns": {
            "$ref": "#/components/schemas/BooleanEntitlement"
          },
          "flowRulesCustom": {
            "$ref": "#/components/schemas/BooleanEntitlement"
          },
          "flowRulesTemplates": {
            "$ref": "#/components/schemas/BooleanEntitlement"
          },
          "publicNetworks": {
            "$ref": "#/components/schemas/BooleanEntitlement"
          },
          "fullRebac": {
            "$ref": "#/components/schemas/BooleanEntitlement"
          },
          "serviceAccounts": {
            "$ref": "#/components/schemas/NumericEntitlement"
          },
          "api": {
            "$ref": "#/components/schemas/NumericEntitlement"
          },
          "webhooks": {
            "$ref": "#/components/schemas/NumericEntitlement"
          }
        }
      },
      "Subscription": {
        "type": "object",
        "required": [
          "id",
          "plan",
          "planDisplayName",
          "status",
          "entitlements"
        ],
        "properties": {
          "id": {
            "type": "string"
          },
          "plan": {
            "type": "string",
            "enum": [
              "plan-zt1-basic",
              "plan-zt1-essential",
              "plan-zt1-scale",
              "plan-zt1-premium"
            ]
          },
          "planDisplayName": {
            "type": "string"
          },
          "status": {
            "type": "string",
            "enum": [
              "active",
              "in-trial",
              "past-due"
            ]
          },
          "entitlements": {
            "$ref": "#/components/schemas/SubscriptionEntitlements"
          }
        }
      },
      "NetworkStats": {
        "type": "object",
        "required": [
          "totalDevices",
          "authorizedDevices",
          "activeDevices",
          "rejectedDevices",
          "notAuthorizedDevices"
        ],
        "properties": {
          "totalDevices": {
            "type": "integer",
            "description": "Total number of devices (all statuses)"
          },
          "authorizedDevices": {
            "type": "integer",
            "description": "Number of authorized devices"
          },
          "activeDevices": {
            "type": "integer",
            "description": "Number of devices that have been seen recently"
          },
          "rejectedDevices": {
            "type": "integer",
            "description": "Number of rejected devices"
          },
          "notAuthorizedDevices": {
            "type": "integer",
            "description": "Number of devices pending authorization"
          }
        }
      },
      "NetworksListStats": {
        "type": "object",
        "required": [
          "authorizedDevices",
          "unauthorizedMemberships"
        ],
        "properties": {
          "authorizedDevices": {
            "type": "integer",
            "description": "Total number of authorized devices across all networks"
          },
          "unauthorizedMemberships": {
            "type": "integer",
            "description": "Total number of devices pending authorization across all networks"
          }
        }
      },
      "DNS": {
        "type": "object",
        "required": [
          "domain",
          "servers"
        ],
        "properties": {
          "domain": {
            "type": "string",
            "example": "some.domain",
            "description": "Search domain to use for DNS records",
            "maxLength": 253
          },
          "servers": {
            "type": "array",
            "maxItems": 10,
            "items": {
              "type": "string"
            },
            "example": [
              "10.0.0.3"
            ],
            "description": "IP addresses of unicast DNS servers (IPv4 or IPv6)"
          }
        }
      },
      "IPRange": {
        "type": "object",
        "required": [
          "ipRangeStart",
          "ipRangeEnd"
        ],
        "properties": {
          "ipRangeStart": {
            "type": "string",
            "description": "Start of the IP address range (inclusive)",
            "example": "10.0.0.1"
          },
          "ipRangeEnd": {
            "type": "string",
            "description": "End of the IP address range (inclusive)",
            "example": "10.0.0.255"
          }
        }
      },
      "Route": {
        "type": "object",
        "required": [
          "target",
          "via"
        ],
        "properties": {
          "target": {
            "type": "string",
            "description": "Destination CIDR for this route",
            "example": "10.0.0.0/24"
          },
          "via": {
            "type": "string",
            "description": "Next-hop IP address, or null to route directly on the ZeroTier network",
            "example": null
          }
        }
      },
      "IPV4AssignMode": {
        "type": "object",
        "required": [
          "zt"
        ],
        "properties": {
          "zt": {
            "type": "boolean",
            "example": true,
            "description": "Enable ZeroTier auto-assignment of IPv4 addresses from the assignment pool"
          }
        }
      },
      "IPV6AssignMode": {
        "type": "object",
        "required": [
          "zt",
          "rfc4193",
          "6plane"
        ],
        "properties": {
          "6plane": {
            "type": "boolean",
            "example": true,
            "description": "Enable 6PLANE addressing (a /80 per device from a /40 assigned to the network)"
          },
          "rfc4193": {
            "type": "boolean",
            "example": false,
            "description": "Enable RFC 4193 private addressing (a /128 per device from a /88 assigned to the network)"
          },
          "zt": {
            "type": "boolean",
            "example": false,
            "description": "Enable ZeroTier auto-assignment of IPv6 addresses from the assignment pool"
          }
        }
      },
      "NetworkConfigRequest": {
        "type": "object",
        "description": "Network configuration. All fields are optional when updating.",
        "properties": {
          "dns": {
            "$ref": "#/components/schemas/DNS"
          },
          "enableBroadcast": {
            "type": "boolean",
            "example": true,
            "description": "Enable broadcast packets on the network"
          },
          "v4Subnet": {
            "type": "string",
            "description": "CIDR subnet that defines the IPv4 network boundary",
            "example": "192.168.0.0/16"
          },
          "v6Subnet": {
            "type": "string",
            "description": "CIDR subnet that defines the IPv6 network boundary",
            "example": "2001:db8::/32"
          },
          "v4IpAssignmentPools": {
            "type": "array",
            "description": "IP address ranges for the IPv4 auto-assignment pool",
            "items": {
              "$ref": "#/components/schemas/IPRange"
            }
          },
          "v6IpAssignmentPools": {
            "type": "array",
            "description": "IP address ranges for the IPv6 auto-assignment pool",
            "items": {
              "$ref": "#/components/schemas/IPRange"
            }
          },
          "mtu": {
            "type": "integer",
            "example": 2800,
            "description": "MTU to set on the client virtual network adapter"
          },
          "multicastLimit": {
            "type": "integer",
            "example": 32,
            "description": "Maximum number of recipients per multicast or broadcast. Warning — setting this to 0 will disable IPv4 communication on your network!"
          },
          "private": {
            "type": "boolean",
            "example": true,
            "description": "Whether the network is private. If `false`, devices will **not** need to be authorized to join."
          },
          "routes": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Route"
            },
            "description": "Static routes to push to network members"
          },
          "v4AssignmentMode": {
            "$ref": "#/components/schemas/IPV4AssignMode"
          },
          "v6AssignmentMode": {
            "$ref": "#/components/schemas/IPV6AssignMode"
          }
        }
      },
      "CreateNetworkRequest": {
        "type": "object",
        "required": [
          "name"
        ],
        "properties": {
          "name": {
            "type": "string",
            "description": "Display name for the network",
            "minLength": 3,
            "maxLength": 127
          },
          "description": {
            "type": "string",
            "description": "Description of the network (may be an empty string)",
            "maxLength": 1024
          },
          "config": {
            "$ref": "#/components/schemas/NetworkConfigRequest"
          }
        },
        "example": {
          "name": "office-network",
          "description": "Main office network",
          "config": {
            "private": true,
            "v4Subnet": "10.147.20.0/24",
            "v4IpAssignmentPools": [
              {
                "ipRangeStart": "10.147.20.1",
                "ipRangeEnd": "10.147.20.254"
              }
            ],
            "v4AssignmentMode": {
              "zt": true
            },
            "v6AssignmentMode": {
              "zt": false,
              "rfc4193": false,
              "6plane": false
            },
            "dns": {
              "domain": "office.local",
              "servers": [
                "10.147.20.1"
              ]
            },
            "routes": [
              {
                "target": "10.147.20.0/24",
                "via": null
              }
            ],
            "enableBroadcast": true,
            "mtu": 2800,
            "multicastLimit": 32
          }
        }
      },
      "NetworkConfigResponse": {
        "type": "object",
        "required": [
          "dns",
          "enableBroadcast",
          "v4Subnet",
          "v6Subnet",
          "v4IpAssignmentPools",
          "v6IpAssignmentPools",
          "mtu",
          "multicastLimit",
          "private",
          "routes",
          "v4AssignmentMode",
          "v6AssignmentMode"
        ],
        "properties": {
          "dns": {
            "$ref": "#/components/schemas/DNS"
          },
          "enableBroadcast": {
            "type": "boolean",
            "example": true,
            "description": "Enable broadcast packets on the network"
          },
          "v4Subnet": {
            "type": "string",
            "description": "CIDR subnet that defines the IPv4 network boundary",
            "example": "192.168.0.0/16"
          },
          "v6Subnet": {
            "type": "string",
            "description": "CIDR subnet that defines the IPv6 network boundary",
            "example": "2001:db8::/32"
          },
          "v4IpAssignmentPools": {
            "type": "array",
            "description": "IP address ranges for the IPv4 auto-assignment pool",
            "items": {
              "$ref": "#/components/schemas/IPRange"
            }
          },
          "v6IpAssignmentPools": {
            "type": "array",
            "description": "IP address ranges for the IPv6 auto-assignment pool",
            "items": {
              "$ref": "#/components/schemas/IPRange"
            }
          },
          "mtu": {
            "type": "integer",
            "example": 2800,
            "description": "MTU to set on the client virtual network adapter"
          },
          "multicastLimit": {
            "type": "integer",
            "example": 32,
            "description": "Maximum number of recipients per multicast or broadcast. Warning — setting this to 0 will disable IPv4 communication on your network!"
          },
          "private": {
            "type": "boolean",
            "example": true,
            "description": "Whether the network is private. If `false`, devices will **not** need to be authorized to join."
          },
          "routes": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Route"
            },
            "description": "Static routes pushed to network members"
          },
          "v4AssignmentMode": {
            "$ref": "#/components/schemas/IPV4AssignMode"
          },
          "v6AssignmentMode": {
            "$ref": "#/components/schemas/IPV6AssignMode"
          }
        }
      },
      "NetworkResponse": {
        "type": "object",
        "required": [
          "id",
          "name",
          "networkGroupId",
          "config",
          "creationTime",
          "lastModified",
          "kind"
        ],
        "properties": {
          "id": {
            "type": "string",
            "description": "Unique network identifier"
          },
          "name": {
            "type": "string",
            "description": "Display name of the network"
          },
          "networkGroupId": {
            "type": "string",
            "description": "ID of the network group this network belongs to"
          },
          "description": {
            "type": "string",
            "description": "Description of the network (may be an empty string)"
          },
          "config": {
            "$ref": "#/components/schemas/NetworkConfigResponse"
          },
          "creationTime": {
            "type": "string",
            "format": "date-time",
            "description": "Time the network was created"
          },
          "lastModified": {
            "type": "string",
            "format": "date-time",
            "description": "Time the network was last modified"
          },
          "kind": {
            "type": "string",
            "description": "The kind of ZeroTier network (e.g. `v1`)"
          }
        }
      },
      "UpdateNetworkRequest": {
        "type": "object",
        "description": "All fields are optional. Only provided fields are updated.",
        "properties": {
          "name": {
            "type": "string",
            "description": "Display name for the network",
            "minLength": 3,
            "maxLength": 127
          },
          "description": {
            "type": "string",
            "description": "Description of the network (may be an empty string)",
            "maxLength": 1024
          },
          "config": {
            "$ref": "#/components/schemas/NetworkConfigRequest"
          }
        },
        "example": {
          "name": "office-network-v2",
          "config": {
            "mtu": 2800,
            "private": true
          }
        }
      }
    },
    "responses": {
      "400": {
        "description": "Invalid data provided",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/BadRequestResponse"
            }
          }
        }
      },
      "401": {
        "description": "Missing or invalid authentication token",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/MessageResponse"
            }
          }
        }
      },
      "403": {
        "description": "Insufficient permissions",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/MessageResponse"
            }
          }
        }
      },
      "413": {
        "description": "Request body exceeds the 1 MB size limit",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/MessageResponse"
            }
          }
        }
      },
      "500": {
        "description": "Internal server error",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/MessageResponse"
            }
          }
        }
      }
    },
    "securitySchemes": {
      "BearerAuth": {
        "type": "http",
        "scheme": "bearer",
        "bearerFormat": "JWT",
        "description": "API key issued to a service account. Create a service account under an organization and generate an API key via the service account endpoints. Keys can have an optional expiry and can be revoked at any time."
      }
    }
  },
  "x-tagGroups": [
    {
      "name": "Identity & Access",
      "tags": [
        "user",
        "org"
      ]
    },
    {
      "name": "Networking",
      "tags": [
        "network-group",
        "network",
        "member"
      ]
    },
    {
      "name": "Automation",
      "tags": [
        "service-account",
        "webhook"
      ]
    }
  ]
}
