openapi: 3.0.4
info:
  title: Public APIs
  description: WEDA Public APIs
  version: 1.1.1
servers:
  - url: https://tpe.cloud.advantech.com/demo/weda
    description: API Server
tags:
  - name: ___swagger_1-iam_swagger_json_Identity & Access
    x-displayName: Identity & Access
  - name: ___swagger_2-device-management_swagger_json_Devices
    x-displayName: Devices
  - name: ___swagger_2-device-management_swagger_json_WEDA Node Credentials
    x-displayName: WEDA Node Credentials
  - name: ___swagger_3-container-management_swagger_json_Container Commands
    x-displayName: Container Commands
  - name: ___swagger_3-container-management_swagger_json_Container Deployments
    x-displayName: Container Deployments
  - name: ___swagger_3-container-management_swagger_json_Container Registries
    x-displayName: Container Registries
  - name: ___swagger_3-container-management_swagger_json_Container Stacks
    x-displayName: Container Stacks
  - name: ___swagger_4-ai-model-management_swagger_json_Model Deployments
    x-displayName: Model Deployments
  - name: ___swagger_4-ai-model-management_swagger_json_Model Management
    x-displayName: Model Management
  - name: ___swagger_4-ai-model-management_swagger_json_Model Uploads
    x-displayName: Model Uploads
  - name: ___swagger_5-data-stream_swagger_json_DataStreams
    x-displayName: DataStreams
  - name: ___swagger_6-data-analyzer_swagger_json_Analyzers
    description: Manage device analyzers that transform input data streams using
      mathematical expressions.
    x-displayName: Analyzers
  - name: ___swagger_7-data-bridge_swagger_json_Data Bridges
    x-displayName: Data Bridges
  - name: ___swagger_7-data-bridge_swagger_json_Data Bridges Components
    x-displayName: Data Bridges Components
  - name: ___swagger_8-alert-policy_swagger_json_AlertEvents
    x-displayName: AlertEvents
  - name: ___swagger_8-alert-policy_swagger_json_AlertPolicies
    x-displayName: AlertPolicies
  - name: ___swagger_8-alert-policy_swagger_json_Notifications
    x-displayName: Notifications
  - name: ___swagger_9-reports_swagger_json_Reports
    x-displayName: Reports
  - name: ___swagger_10-tunnel-management_swagger_json_Tunnels
    x-displayName: Tunnels
paths:
  /api/v1/users:
    get:
      tags:
        - ___swagger_1-iam_swagger_json_Identity & Access
      summary: List all application users
      description: >-
        
        Retrieve a paginated and sorted list of application users.  


        **Usage**

        - Provide pagination parameters (`skipCount`, `maxResultCount`) to
        control result size.  

        - Provide sorting parameters (`sorting`) to order results.  


        **Parameters**

        - `skipCount` (int, optional): number of records to skip before starting
        to collect results.  

        - `maxResultCount` (int, optional): maximum number of records to return
        (1–1000).  

        - `sorting` (string, optional): field and direction to sort the results
        (e.g., "name asc", "email desc").  


        **Responses**

        - `200 OK`: successfully returns a paginated list of users.  

        - `401 Unauthorized`: caller does not have permission.  

        - `403 Forbidden`: caller does not have permission to list users.  


        **Security**

        - This API requires authentication.  

        - Available to users with appropriate roles.
      parameters:
        - name: skipCount
          in: query
          description: Number of records to skip for pagination. Must be 0 or greater.
          schema:
            type: integer
            description: Number of records to skip for pagination. Must be 0 or greater.
            format: int32
        - name: maxResultCount
          in: query
          description: Maximum number of records to return (1–1000).
          schema:
            maximum: 1000
            minimum: 0
            type: integer
            description: Maximum number of records to return (1–1000).
            format: int32
            nullable: true
        - name: sorting
          in: query
          description: "Sorting criteria in the format: 'PropertyName ASC|DESC'. Available
            properties: name, email."
          schema:
            type: string
            description: "Sorting criteria in the format: 'PropertyName ASC|DESC'. Available
              properties: name, email."
            nullable: true
        - name: filter
          in: query
          description: Fuzzy search keywords
          schema:
            type: string
            description: Fuzzy search keywords
      responses:
        "200":
          description: OK
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/AppUserDisplayDtoPagedResultDto"
        "400":
          description: Bad Request
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/RemoteServiceErrorResponse"
        "401":
          description: Unauthorized
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/RemoteServiceErrorResponse"
        "403":
          description: Forbidden
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/RemoteServiceErrorResponse"
        "404":
          description: Not Found
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/RemoteServiceErrorResponse"
        "500":
          description: Internal Server Error
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/RemoteServiceErrorResponse"
        "501":
          description: Not Implemented
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/RemoteServiceErrorResponse"
      security:
        - Bearer: []
  /api/v1/users/{userId}:
    get:
      tags:
        - ___swagger_1-iam_swagger_json_Identity & Access
      summary: Get a user by ID
      description: >-
        
        Retrieve details of a single application user by their unique ID.


        **Usage**

        - Provide the `userId` of the target user to fetch detailed information.


        **Parameters**

        - `userId` (Guid, required): the unique identifier of the user to
        retrieve.


        **Responses**

        - `200 OK`: successfully returns the user details.

        - `403 Forbidden`: caller does not have permission to view this user.

        - `404 Not Found`: the user with the specified ID does not exist.


        **Security**

        - This API requires authentication.

        - Accessible only to users with appropriate roles.
      parameters:
        - name: userId
          in: path
          description: |-
            The ID of the user.  
                        Example : 783707f1-0659-4892-a872-8f506d225d7b
          required: true
          schema:
            type: string
            description: |-
              The ID of the user.  
                          Example : 783707f1-0659-4892-a872-8f506d225d7b
      responses:
        "200":
          description: OK
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/AppUserDisplayDto"
        "400":
          description: Bad Request
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/RemoteServiceErrorResponse"
        "401":
          description: Unauthorized
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/RemoteServiceErrorResponse"
        "403":
          description: Forbidden
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/RemoteServiceErrorResponse"
        "404":
          description: Not Found
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/RemoteServiceErrorResponse"
        "500":
          description: Internal Server Error
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/RemoteServiceErrorResponse"
        "501":
          description: Not Implemented
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/RemoteServiceErrorResponse"
      security:
        - Bearer: []
  /api/v1/oauth2/client-credentials:
    post:
      tags:
        - ___swagger_1-iam_swagger_json_Identity & Access
      summary: Create a Client Credential.
      description: Create a new Client Credential with specified scopes and expiration.
      requestBody:
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/CreatePatDto"
            example:
              name: string
              expiredAt: 2026-09-01T00:00:00Z
              scopes:
                - dataobject.read
              deviceIds:
                - string
      responses:
        "201":
          description: Created
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/PatDetailDto"
      security:
        - Bearer: []
    get:
      tags:
        - ___swagger_1-iam_swagger_json_Identity & Access
      summary: Get all Client Credentials.
      description: Retrieve all Client Credentials.
      responses:
        "200":
          description: OK
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: "#/components/schemas/PatDto"
              example:
                - clientCredentialId: 3fa85f64-5717-4562-b3fc-2c963f66afa6
                  name: string
                  clientId: string
                  createdAt: 2026-09-01T00:00:00Z
                  expiredAt: 2026-09-01T00:00:00Z
                  scopes:
                    - dataobject.read
                  deviceIds:
                    - string
      security:
        - Bearer: []
  /api/v1/oauth2/client-credentials/{clientCredentialId}:
    delete:
      tags:
        - ___swagger_1-iam_swagger_json_Identity & Access
      summary: Delete a Client Credential by ID.
      description: Revoke and delete a Client Credential by its ID.
      parameters:
        - name: clientCredentialId
          in: path
          description: The ID of the Client Credential to be removed. Returned as
            'clientCredentialId' when the credential was created.
          required: true
          schema:
            type: string
            description: The ID of the Client Credential to be removed. Returned as
              'clientCredentialId' when the credential was created.
            format: uuid
      responses:
        "204":
          description: No Content
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Success"
      security:
        - Bearer: []
  /api/v1/orgs:
    get:
      tags:
        - ___swagger_1-iam_swagger_json_Identity & Access
      summary: Get organizations (root or sub-orgs)
      description: >-
        Retrieve organizations in multiple formats:

        * Paged results (`default`)

        * Flat list (`view=list`)

        * Hierarchical tree (`view=tree`)


        **Parameters**

        * `parentOrgId` (Guid, optional): retrieve sub-organizations under a
        specific parent.

        * `view` (enum, optional): "list", "tree", or "page" (default).

        * `skipCount`, `maxResultCount`, `sorting`: standard paging/sorting
        fields.

        * `sorting`: Sorting criteria in the format: 'PropertyName ASC|DESC'.
        Available properties: name, id.


        **Responses**

        * `200 OK`: returns paged data, list, or tree depending on `view`.

        **Security**


        * This API requires authentication.
      parameters:
        - name: parentOrgId
          in: query
          description: >-
            The parent organization ID. If specified, retrieves
            sub-organizations under this org. If omitted, retrieves root-level
            organizations.  
                    Example : 783707f1-0659-4892-a872-8f506d225d7b
          schema:
            type: string
            description: >-
              The parent organization ID. If specified, retrieves
              sub-organizations under this org. If omitted, retrieves root-level
              organizations.  
                      Example : 783707f1-0659-4892-a872-8f506d225d7b
            format: uuid
            nullable: true
        - name: view
          in: query
          description: >-
            View mode: 'list' for flat list, 'tree' for hierarchical tree view,
            'page' for paged results (default is 'page').  
                    Example : page, list, tree
          schema:
            $ref: "#/components/schemas/ViewType"
        - name: sorting
          in: query
          description: "Sorting criteria in the format: 'PropertyName ASC|DESC'. Available
            properties: name, id."
          schema:
            type: string
            description: "Sorting criteria in the format: 'PropertyName ASC|DESC'. Available
              properties: name, id."
            nullable: true
        - name: skipCount
          in: query
          description: Number of records to skip for pagination. Must be 0 or greater.
          schema:
            type: integer
            description: Number of records to skip for pagination. Must be 0 or greater.
            format: int32
        - name: maxResultCount
          in: query
          description: Maximum number of records to return (1–1000).
          schema:
            type: integer
            description: Maximum number of records to return (1–1000).
            format: int32
            nullable: true
      responses:
        "200":
          description: OK
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/OrgDtoPagedResultDto"
              example:
                totalCount: 2
                items:
                  - name: Advantech HQ
                    orgId: 70c00505-4678-4128-8eb5-88221ecccd75
                    parentOrgId: null
                  - name: R&D Department
                    orgId: 8c77338d-0f1f-4ac8-97eb-0ef3a1b68e23
                    parentOrgId: 70c00505-4678-4128-8eb5-88221ecccd75
        "400":
          description: Bad Request
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/RemoteServiceErrorResponse"
        "401":
          description: Unauthorized
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/RemoteServiceErrorResponse"
        "403":
          description: Forbidden
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/RemoteServiceErrorResponse"
        "404":
          description: Not Found
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/RemoteServiceErrorResponse"
        "500":
          description: Internal Server Error
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/RemoteServiceErrorResponse"
        "501":
          description: Not Implemented
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/RemoteServiceErrorResponse"
      security:
        - Bearer: []
    post:
      tags:
        - ___swagger_1-iam_swagger_json_Identity & Access
      summary: Create a new organization
      description: >-
        Add a new organization with the provided details.


        **Parameters**

        * Request body: The organization definition includes:

        - `name` (string, required, max length 100): the name of the
        organization.

        - `parentOrgId` (string, optional): the ID of the parent organization,
        if applicable.

        - `description` (string, optional, max length 200): description of the
        organization.

        - `admins` (list of userId, optional): list of admin users for this
        organization.


        **Responses**


        * `201 Created`: new organization created successfully.

        * `400 Bad Request`: invalid input data.

        * `403 Forbidden`: caller does not have permission to create orgs under
        the specified parent.

        * `404 Not Found`: specified parent organization not found.

        * `409 Conflict`: organization name already exists.


        **Security**


        * This API requires authentication.
      requestBody:
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/CreateOrgDto"
            example:
              parentOrgId: 70c00505-4678-4128-8eb5-88221ecccd75
              admins:
                - userId: 783707f1-0659-4892-a872-8f506d225d7b
                - userId: 783707f1-0659-4892-a872-8f506d225d7c
              name: OrgSample
              description: This is a sample organization.
      responses:
        "201":
          description: Created
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/CreateOrgResponseDto"
              example:
                name: OrgSample
                orgId: 70c00505-4678-4128-8eb5-88221ecccd75
                parentOrgId: 70c00505-4678-4128-8eb5-88221ecccd75
                description: Sample organization
                admins:
                  - userId: 783707f1-0659-4892-a872-8f506d225d7b
                    orgRole: admin
                    name: AdminUserSample
                dateCreated: 2026-07-31T08:13:53.0156136Z
                dateModified: 2026-07-31T08:13:53.0156463Z
        "400":
          description: Bad Request
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/RemoteServiceErrorResponse"
        "401":
          description: Unauthorized
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/RemoteServiceErrorResponse"
        "403":
          description: Forbidden
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/RemoteServiceErrorResponse"
        "404":
          description: Not Found
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/RemoteServiceErrorResponse"
        "500":
          description: Internal Server Error
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/RemoteServiceErrorResponse"
        "501":
          description: Not Implemented
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/RemoteServiceErrorResponse"
      security:
        - Bearer: []
  /api/v1/orgs/{orgId}:
    get:
      tags:
        - ___swagger_1-iam_swagger_json_Identity & Access
      summary: Get a specific organization by ID
      description: >-
        Retrieve detailed information of an organization by its unique
        identifier.


        **Parameters**


        * `orgId` (Guid, required): unique identifier of the organization.


        **Responses**


        * `200 OK`: returns the organization details.

        * `404 Not Found`: no organization found with the given ID.


        **Security**


        * This API requires authentication.
      parameters:
        - name: orgId
          in: path
          description: |-
            The ID of the organization.  
                Example : 783707f1-0659-4892-a872-8f506d225d7b
          required: true
          schema:
            type: string
            description: |-
              The ID of the organization.  
                  Example : 783707f1-0659-4892-a872-8f506d225d7b
            format: uuid
      responses:
        "200":
          description: OK
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/OrgDto"
              example:
                name: OrgSample
                orgId: 70c00505-4678-4128-8eb5-88221ecccd75
                parentOrgId: 70c00505-4678-4128-8eb5-88221ecccd75
        "400":
          description: Bad Request
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/RemoteServiceErrorResponse"
        "401":
          description: Unauthorized
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/RemoteServiceErrorResponse"
        "403":
          description: Forbidden
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/RemoteServiceErrorResponse"
        "404":
          description: Not Found
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/RemoteServiceErrorResponse"
        "500":
          description: Internal Server Error
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/RemoteServiceErrorResponse"
        "501":
          description: Not Implemented
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/RemoteServiceErrorResponse"
      security:
        - Bearer: []
    patch:
      tags:
        - ___swagger_1-iam_swagger_json_Identity & Access
      summary: Update an existing organization
      description: >-
        Update the name and description of an existing organization.


        **Parameters**


        * `orgId` (Guid, required): ID of the organization to update.

        * Request body: The updatable fields are:

        - `name` (string, required, max length 100): updated organization name.
        Must be globally unique (case-insensitive, whitespace-normalized).

        - `description` (string, optional, max length 200): updated organization
        description.


        **Responses**


        * `200 OK`: organization updated successfully.

        * `400 Bad Request`: invalid input (name conflict, parentOrgId mismatch,
        field length exceeded).

        * `403 Forbidden`: caller does not have admin role in this organization.

        * `404 Not Found`: organization not found.


        **Security**


        * This API requires authentication.
      parameters:
        - name: orgId
          in: path
          description: |-
            The ID of the organization.  
                    Example : 783707f1-0659-4892-a872-8f506d225d7b
          required: true
          schema:
            type: string
            description: |-
              The ID of the organization.  
                      Example : 783707f1-0659-4892-a872-8f506d225d7b
            format: uuid
      requestBody:
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/CreateUpdateOrgDto"
            example:
              name: OrgSample
              description: This is a sample organization.
      responses:
        "200":
          description: OK
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/UpdateOrgResponseDto"
              example:
                orgId: 8c77338d-0f1f-4ac8-97eb-0ef3a1b68e23
                name: OrgSampleUpdated
                description: Updated description
                dateModified: 2025-12-20T08:45:00Z
        "400":
          description: Bad Request
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/RemoteServiceErrorResponse"
        "401":
          description: Unauthorized
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/RemoteServiceErrorResponse"
        "403":
          description: Forbidden
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/RemoteServiceErrorResponse"
        "404":
          description: Not Found
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/RemoteServiceErrorResponse"
        "500":
          description: Internal Server Error
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/RemoteServiceErrorResponse"
        "501":
          description: Not Implemented
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/RemoteServiceErrorResponse"
      security:
        - Bearer: []
    delete:
      tags:
        - ___swagger_1-iam_swagger_json_Identity & Access
      summary: Delete an organization
      description: >-
        Remove an organization by its ID. Requires confirmation of the
        organization name.


        **Usage**

        `DELETE /orgs/{orgId}?orgName={orgName}`


        **Parameters**


        * `orgId` (Guid, required): ID of the organization.

        * `orgName` (string, required): The name of the organization, used for
        confirmation.


        **Responses**


        * `204 No Content`: organization deleted successfully.

        * `400 Bad Request`: orgName does not match the actual organization
        name.

        * `403 Forbidden`: caller is not admin, target is root org, org has
        sub-organizations, devices, or other users.

        * `404 Not Found`: organization not found.


        **Security**


        * This API requires authentication.

        * Only an `admin` of the target org may delete it.

        * Root organizations cannot be deleted.

        * Organizations with sub-orgs, devices, or other users cannot be
        deleted.
      parameters:
        - name: orgId
          in: path
          description: |-
            The ID of the organization.  
                    Example : 783707f1-0659-4892-a872-8f506d225d7b
          required: true
          schema:
            type: string
            description: |-
              The ID of the organization.  
                      Example : 783707f1-0659-4892-a872-8f506d225d7b
            format: uuid
        - name: orgName
          in: query
          description: |-
            The name of the organization for deletion confirmation.  
                    Example : MyOrg
          required: true
          schema:
            type: string
            description: |-
              The name of the organization for deletion confirmation.  
                      Example : MyOrg
      responses:
        "204":
          description: No Content
        "400":
          description: Bad Request
        "401":
          description: Unauthorized
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/RemoteServiceErrorResponse"
        "403":
          description: Forbidden
        "404":
          description: Not Found
        "500":
          description: Internal Server Error
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/RemoteServiceErrorResponse"
        "501":
          description: Not Implemented
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/RemoteServiceErrorResponse"
      security:
        - Bearer: []
  /api/v1/orgs/{orgId}/children:
    get:
      tags:
        - ___swagger_1-iam_swagger_json_Identity & Access
      summary: Get children organizations
      description: >-
        Retrieve child organizations under a given organization up to a
        specified depth.


        **Parameters**


        * `orgId` (Guid, required): ID of the parent organization.

        * `depth` (int, optional, default=1): Number of levels of children to
        retrieve.


        **Responses**


        * `200 OK`: returns children org tree.
      parameters:
        - name: orgId
          in: path
          description: |-
            The ID of the organization.  
                    Example : 783707f1-0659-4892-a872-8f506d225d7b
          required: true
          schema:
            type: string
            description: |-
              The ID of the organization.  
                      Example : 783707f1-0659-4892-a872-8f506d225d7b
            format: uuid
        - name: depth
          in: query
          description: |-
            Number of levels of children to retrieve.  
                    Example : 1, 2, 3
          schema:
            type: integer
            description: |-
              Number of levels of children to retrieve.  
                      Example : 1, 2, 3
            format: int32
            default: 1
            nullable: true
      responses:
        "200":
          description: OK
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/OrgTreeDto"
              example:
                orgId: 70c00505-4678-4128-8eb5-88221ecccd75
                name: Advantech HQ
                parentOrgId: null
                children:
                  - orgId: c6de8b2f-116a-4f89-b7c7-4aaf43c02c3e
                    name: R&D Division
                    parentOrgId: 70c00505-4678-4128-8eb5-88221ecccd75
                    children:
                      - orgId: d5b84af3-8b4b-4e71-8b32-c23d9dce7bb3
                        name: AI Department
                        parentOrgId: c6de8b2f-116a-4f89-b7c7-4aaf43c02c3e
                        children: []
                      - orgId: 77dcb763-3c46-49a8-92ab-451c7c6d47f2
                        name: IoT Department
                        parentOrgId: c6de8b2f-116a-4f89-b7c7-4aaf43c02c3e
                        children: []
                  - orgId: 8b3a0a7e-05a8-4a90-861a-5e015b0e9a47
                    name: Sales Division
                    parentOrgId: 70c00505-4678-4128-8eb5-88221ecccd75
                    children:
                      - orgId: 2e8708f4-9ad5-4bb9-b16c-53cb5f7c1f71
                        name: Asia Region
                        parentOrgId: 8b3a0a7e-05a8-4a90-861a-5e015b0e9a47
                        children: []
                      - orgId: 95b49b55-f021-4f70-92b3-256f4a7e20a6
                        name: Europe Region
                        parentOrgId: 8b3a0a7e-05a8-4a90-861a-5e015b0e9a47
                        children: []
        "400":
          description: Bad Request
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/RemoteServiceErrorResponse"
        "401":
          description: Unauthorized
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/RemoteServiceErrorResponse"
        "403":
          description: Forbidden
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/RemoteServiceErrorResponse"
        "404":
          description: Not Found
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/RemoteServiceErrorResponse"
        "500":
          description: Internal Server Error
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/RemoteServiceErrorResponse"
        "501":
          description: Not Implemented
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/RemoteServiceErrorResponse"
      security:
        - Bearer: []
  /api/v1/orgs/{orgId}/parents:
    get:
      tags:
        - ___swagger_1-iam_swagger_json_Identity & Access
      summary: Get parent organizations
      description: >-
        Retrieve parent organizations of a given organization up to a specified
        depth.


        **Parameters**


        * `orgId` (Guid, required): ID of the child organization.

        * `depth` (int, optional, default=1): Number of parent levels to
        retrieve.


        **Responses**


        * `200 OK`: returns parent org tree.
      parameters:
        - name: orgId
          in: path
          description: |-
            The ID of the organization.  
                    Example : 783707f1-0659-4892-a872-8f506d225d7b
          required: true
          schema:
            type: string
            description: |-
              The ID of the organization.  
                      Example : 783707f1-0659-4892-a872-8f506d225d7b
            format: uuid
        - name: depth
          in: query
          description: "Depth of parent levels to retrieve. Example: 1, 2, 3"
          schema:
            type: integer
            description: "Depth of parent levels to retrieve. Example: 1, 2, 3"
            format: int32
            default: 1
            nullable: true
      responses:
        "200":
          description: OK
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/OrgTreeDto"
              example:
                orgId: 70c00505-4678-4128-8eb5-88221ecccd75
                name: Advantech HQ
                parentOrgId: null
                children:
                  - orgId: c6de8b2f-116a-4f89-b7c7-4aaf43c02c3e
                    name: R&D Division
                    parentOrgId: 70c00505-4678-4128-8eb5-88221ecccd75
                    children:
                      - orgId: d5b84af3-8b4b-4e71-8b32-c23d9dce7bb3
                        name: AI Department
                        parentOrgId: c6de8b2f-116a-4f89-b7c7-4aaf43c02c3e
                        children: []
                      - orgId: 77dcb763-3c46-49a8-92ab-451c7c6d47f2
                        name: IoT Department
                        parentOrgId: c6de8b2f-116a-4f89-b7c7-4aaf43c02c3e
                        children: []
                  - orgId: 8b3a0a7e-05a8-4a90-861a-5e015b0e9a47
                    name: Sales Division
                    parentOrgId: 70c00505-4678-4128-8eb5-88221ecccd75
                    children:
                      - orgId: 2e8708f4-9ad5-4bb9-b16c-53cb5f7c1f71
                        name: Asia Region
                        parentOrgId: 8b3a0a7e-05a8-4a90-861a-5e015b0e9a47
                        children: []
                      - orgId: 95b49b55-f021-4f70-92b3-256f4a7e20a6
                        name: Europe Region
                        parentOrgId: 8b3a0a7e-05a8-4a90-861a-5e015b0e9a47
                        children: []
        "400":
          description: Bad Request
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/RemoteServiceErrorResponse"
        "401":
          description: Unauthorized
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/RemoteServiceErrorResponse"
        "403":
          description: Forbidden
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/RemoteServiceErrorResponse"
        "404":
          description: Not Found
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/RemoteServiceErrorResponse"
        "500":
          description: Internal Server Error
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/RemoteServiceErrorResponse"
        "501":
          description: Not Implemented
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/RemoteServiceErrorResponse"
      security:
        - Bearer: []
  /api/v1/users/{userId}/orgs:
    get:
      tags:
        - ___swagger_1-iam_swagger_json_Identity & Access
      summary: Retrieve all organization roles linked to the specified user
      description: |-
        Retrieve all organization roles linked to the specified user.
        **Usage**  
        `GET /users/{userId}/orgs?orgId={Guid}&orgName={string}`

        **Parameters**
        - `userId` (string, required): ID of the user.

        **Responses**
        - `200 OK`: list of organizations with associated roles for the user.
        - `403 Forbidden`: caller does not have permission to access the user.
        - `404 Not Found`: user not found.

        **Security**

        * This API requires authentication.
      parameters:
        - name: userId
          in: path
          description: "The ID of the user. Example : 783707f1-0659-4892-a872-8f506d225d7b"
          required: true
          schema:
            type: string
            description: "The ID of the user. Example :
              783707f1-0659-4892-a872-8f506d225d7b"
        - name: orgId
          in: query
          description: Filter results to a specific organization by its ID.
          schema:
            type: string
            description: Filter results to a specific organization by its ID.
            format: uuid
            nullable: true
        - name: orgName
          in: query
          description: Filter results by organization name (partial match).
          schema:
            type: string
            description: Filter results by organization name (partial match).
            nullable: true
        - name: sorting
          in: query
          description: Not applicable for this endpoint — results are returned as a tree
            structure.
          schema:
            type: string
            description: Not applicable for this endpoint — results are returned as a tree
              structure.
            nullable: true
        - name: skipCount
          in: query
          description: Number of records to skip for pagination. Must be 0 or greater.
          schema:
            type: integer
            description: Number of records to skip for pagination. Must be 0 or greater.
            format: int32
        - name: maxResultCount
          in: query
          description: Maximum number of records to return (1–1000).
          schema:
            maximum: 1000
            minimum: 0
            type: integer
            description: Maximum number of records to return (1–1000).
            format: int32
            nullable: true
        - name: filter
          in: query
          description: Fuzzy search keywords
          schema:
            type: string
            description: Fuzzy search keywords
      responses:
        "200":
          description: OK
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/OrgTreeDetailDtoPagedResultDto"
        "400":
          description: Bad Request
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/RemoteServiceErrorResponse"
        "401":
          description: Unauthorized
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/RemoteServiceErrorResponse"
        "403":
          description: Forbidden
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/RemoteServiceErrorResponse"
        "404":
          description: Not Found
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/RemoteServiceErrorResponse"
        "500":
          description: Internal Server Error
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/RemoteServiceErrorResponse"
        "501":
          description: Not Implemented
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/RemoteServiceErrorResponse"
      security:
        - Bearer: []
  /api/v1/orgs/{orgId}/users:
    get:
      tags:
        - ___swagger_1-iam_swagger_json_Identity & Access
      summary: Get users by organization ID
      description: >-
        Retrieve a paginated list of users belonging to a specific
        organization.  


        **Usage**  

        `GET /orgs/{orgId}/users?skipCount=0&maxResultCount=10&sorting=name
        asc`  


        **Parameters**  

        - `orgId` (Guid, required): the ID of the organization.  

        - `skipCount` (int, optional): number of records to skip.  

        - `maxResultCount` (int, optional, range 1–1000): maximum number of
        records to return.  

        - `sorting` (string, optional): sorting expression. Supported fields:
        `name`, `orgRole`, `userId`. Direction: `asc` (default) or `desc`.
        Example: `name desc`.  

        - `orgRole` (string, optional): filter by user's role within the
        organization. (`admin`, `operator`, `viewer`)

        - `name` (string, optional): filter by user's name (partial match).


        **Responses**  

        - `200 OK`: paginated list of users in the organization. 

        - `400 Bad Request`: invalid query parameters (e.g. invalid role value).

        - `404 Not Found`: organization not found.  


        **Security**  

        This API requires authentication.
      parameters:
        - name: orgId
          in: path
          description: "The ID of the organization. Example :
            783707f1-0659-4892-a872-8f506d225d7b"
          required: true
          schema:
            type: string
            description: "The ID of the organization. Example :
              783707f1-0659-4892-a872-8f506d225d7b"
            format: uuid
        - name: name
          in: query
          description: Filter users by name (partial match)
          schema:
            type: string
            description: Filter users by name (partial match)
        - name: orgRole
          in: query
          description: Filter users by role within the organization (e.g. admin, viewer)
          schema:
            type: string
            description: Filter users by role within the organization (e.g. admin, viewer)
        - name: skipCount
          in: query
          description: Number of records to skip for pagination. Must be 0 or greater.
          schema:
            type: integer
            description: Number of records to skip for pagination. Must be 0 or greater.
            format: int32
        - name: maxResultCount
          in: query
          description: Maximum number of records to return (1–1000).
          schema:
            type: integer
            description: Maximum number of records to return (1–1000).
            format: int32
            nullable: true
        - name: sorting
          in: query
          description: "Sorting criteria in the format: 'PropertyName ASC|DESC'."
          schema:
            type: string
            description: "Sorting criteria in the format: 'PropertyName ASC|DESC'."
            nullable: true
      responses:
        "200":
          description: OK
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/OrgUserDeskDtoCustomPagedResultDto"
              example:
                skipCount: 0
                maxResultCount: 10
                totalPages: 1
                totalCount: 2
                items:
                  - userId: user-12345
                    orgRole: admin
                    name: Ken Huang
                    email: ken.huang@advantech.com
                    role: admin
                    orgId: 70c00505-4678-4128-8eb5-88221ecccd75
                    createdAt: 0001-01-01T00:00:00Z
                    updatedAt: null
                  - userId: user-67890
                    orgRole: admin
                    name: An Nguyen
                    email: an.nguyen@advantech.vn
                    role: viewer
                    orgId: 70c00505-4678-4128-8eb5-88221ecccd75
                    createdAt: 0001-01-01T00:00:00Z
                    updatedAt: null
        "400":
          description: Invalid query parameters (e.g. invalid sorting field or pagination
            values).
        "401":
          description: Unauthorized
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/RemoteServiceErrorResponse"
        "403":
          description: Forbidden
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/RemoteServiceErrorResponse"
        "404":
          description: Organization not found.
        "500":
          description: Internal Server Error
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/RemoteServiceErrorResponse"
        "501":
          description: Not Implemented
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/RemoteServiceErrorResponse"
      security:
        - Bearer: []
    post:
      tags:
        - ___swagger_1-iam_swagger_json_Identity & Access
      summary: Add multiple existing users to an organization
      description: >-
        Associates multiple existing users with an existing organization,
        assigning the `admin` role to each. All items are validated before any
        insertion — if any item fails, the entire batch is rejected.  


        **Usage**  

        `POST /orgs/{orgId}/users`  


        **Parameters**  

        - `orgId` (Guid, required): the ID of the organization.  

        - Request body: An array of user entries to add, each containing:
            - `userId` (string, required): the system GUID of the user to be added to the organization.
            - `orgRole` (string, required): the role assigned to the user within the organization. Only `admin` is accepted.

        **Responses**  

        - `201 Created`: all users successfully added; returns the created
        org-user list in request order.  

        - `400 Bad Request`: array is empty, any `orgRole` is not `admin`, or
        any `userId` is not a valid GUID.  

        - `403 Forbidden`: caller is not admin in the target org; or any
        `userId` is not admin in the parent org (when org has a parent).  

        - `404 Not Found`: target org not found; parent org not found; or any
        `userId` does not exist in the system.  

        - `409 Conflict`: any `userId` is already a member of the target org.  


        **Security**  

        This API requires authentication.
      parameters:
        - name: orgId
          in: path
          description: "The ID of the organization. Example :
            783707f1-0659-4892-a872-8f506d225d7b"
          required: true
          schema:
            type: string
            description: "The ID of the organization. Example :
              783707f1-0659-4892-a872-8f506d225d7b"
            format: uuid
      requestBody:
        content:
          application/json:
            schema:
              type: array
              items:
                $ref: "#/components/schemas/CreateUpdateOrgUserDtoNoOrg"
            example:
              - userId: 70c00505-4678-4128-8eb5-88221ecccd75
                orgRole: admin
              - userId: 83a11614-5789-5239-9fc6-99332fddde86
                orgRole: admin
      responses:
        "201":
          description: Created
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: "#/components/schemas/OrgUserDto"
        "400":
          description: Array is empty, any orgRole is not admin, or any userId is not a
            valid GUID.
        "401":
          description: Unauthorized
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/RemoteServiceErrorResponse"
        "403":
          description: Caller is not admin in target org, or any userId is not admin in
            parent org.
        "404":
          description: Target org not found, parent org not found, or any userId does not
            exist in the system.
        "409":
          description: Any userId is already a member of the target org.
        "500":
          description: Internal Server Error
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/RemoteServiceErrorResponse"
        "501":
          description: Not Implemented
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/RemoteServiceErrorResponse"
      security:
        - Bearer: []
  /api/v1/orgs/{orgId}/users/{userId}:
    get:
      tags:
        - ___swagger_1-iam_swagger_json_Identity & Access
      summary: Get User in Organization
      description: >-
        Retrieve detailed information about an organization user by specifying
        both **orgId** and **userId**.  


        **Usage**  

        `GET /orgs/{orgId}/users/{userId}`  


        **Parameters**  

        - `orgId` (Guid, required): the ID of the organization.  

        - `userId` (string, required): the ID of the user within the
        organization.  


        **Responses**  

        - `200 OK`: detailed information of the organization user.  

        - `404 Not Found`: organization or user not found.  


        **Security**  

        This API requires authentication.
      parameters:
        - name: orgId
          in: path
          description: "The ID of the organization. Example :
            783707f1-0659-4892-a872-8f506d225d7b"
          required: true
          schema:
            type: string
            description: "The ID of the organization. Example :
              783707f1-0659-4892-a872-8f506d225d7b"
            format: uuid
        - name: userId
          in: path
          description: "The ID of the user within the organization. Example :
            783707f1-0659-4892-a872-8f506d225d7b"
          required: true
          schema:
            type: string
            description: "The ID of the user within the organization. Example :
              783707f1-0659-4892-a872-8f506d225d7b"
      responses:
        "200":
          description: OK
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/OrgUserDeskDto"
              example:
                userId: 70c00505-4678-4128-8eb5-88221ecccd75
                orgRole: admin
                name: Ken Huang
                email: ken.huang@advantech.com
                role: SystemAdmin
                orgId: 70c00505-4678-4128-8eb5-88221ecccd75
                createdAt: 0001-01-01T00:00:00Z
                updatedAt: null
        "400":
          description: Bad Request
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/RemoteServiceErrorResponse"
        "401":
          description: Unauthorized
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/RemoteServiceErrorResponse"
        "403":
          description: Forbidden
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/RemoteServiceErrorResponse"
        "404":
          description: Not Found
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/RemoteServiceErrorResponse"
        "500":
          description: Internal Server Error
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/RemoteServiceErrorResponse"
        "501":
          description: Not Implemented
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/RemoteServiceErrorResponse"
      security:
        - Bearer: []
    delete:
      tags:
        - ___swagger_1-iam_swagger_json_Identity & Access
      summary: Remove user from organization
      description: >-
        Remove a user from an organization by specifying both **orgId** and
        **userId**.


        **Usage**  

        `DELETE /orgs/{orgId}/users/{userId}`  


        **Parameters**

        - `orgId` (Guid, required): the ID of the organization.

        - `userId` (string, required): the user ID of the user to remove from
        the organization.


        > **Warning:** Removing a user from this organization will also remove
        the user from all sub-organizations.


        **Responses**

        - `204 No Content`: user successfully removed from organization.

        - `403 Forbidden`: caller is not an admin of the organization, or caller
        is attempting to remove themselves.

        - `404 Not Found`: organization or user not found.

        - `409 Conflict`: cannot delete the last admin in the organization.


        **Security**  

        This API requires authentication. Only admins of the target organization
        can remove members. An admin cannot remove their own membership.
      parameters:
        - name: orgId
          in: path
          description: "The ID of the organization. Example :
            783707f1-0659-4892-a872-8f506d225d7b"
          required: true
          schema:
            type: string
            description: "The ID of the organization. Example :
              783707f1-0659-4892-a872-8f506d225d7b"
            format: uuid
        - name: userId
          in: path
          description: "The ID of the user within the organization to be removed. Example
            : 783707f1-0659-4892-a872-8f506d225d7b"
          required: true
          schema:
            type: string
            description: "The ID of the user within the organization to be removed. Example
              : 783707f1-0659-4892-a872-8f506d225d7b"
      responses:
        "204":
          description: No Content
        "400":
          description: Bad Request
          content:
            text/plain:
              schema:
                $ref: "#/components/schemas/RemoteServiceErrorResponse"
            application/json:
              schema:
                $ref: "#/components/schemas/RemoteServiceErrorResponse"
            text/json:
              schema:
                $ref: "#/components/schemas/RemoteServiceErrorResponse"
        "401":
          description: Unauthorized
          content:
            text/plain:
              schema:
                $ref: "#/components/schemas/RemoteServiceErrorResponse"
            application/json:
              schema:
                $ref: "#/components/schemas/RemoteServiceErrorResponse"
            text/json:
              schema:
                $ref: "#/components/schemas/RemoteServiceErrorResponse"
        "403":
          description: "Forbidden: caller is not admin in the organization, or attempted
            self-removal."
        "404":
          description: "Not Found: organization or user not found."
        "409":
          description: "Conflict: Cannot delete the last admin in the organization."
        "500":
          description: Internal Server Error
          content:
            text/plain:
              schema:
                $ref: "#/components/schemas/RemoteServiceErrorResponse"
            application/json:
              schema:
                $ref: "#/components/schemas/RemoteServiceErrorResponse"
            text/json:
              schema:
                $ref: "#/components/schemas/RemoteServiceErrorResponse"
        "501":
          description: Not Implemented
          content:
            text/plain:
              schema:
                $ref: "#/components/schemas/RemoteServiceErrorResponse"
            application/json:
              schema:
                $ref: "#/components/schemas/RemoteServiceErrorResponse"
            text/json:
              schema:
                $ref: "#/components/schemas/RemoteServiceErrorResponse"
      security:
        - Bearer: []
  /api/v1/auth/tokens:
    post:
      tags:
        - ___swagger_1-iam_swagger_json_Identity & Access
      summary: Create JWT access token
      description: >-
        Exchanges an existing authentication credential (header, body, cookie or
        refresh token) for a JWT access token.


        **Authentication Methods**


        **1. Authorization Header (Recommended)**

        Use the Authorization Bearer header with a valid token to perform the
        token exchange.

        ```

        Authorization: Bearer eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9...

        ```


        **2. Cookie Authentication**

        Use the *'AdvOidc.Login'* cookie (automatically detected if present).


        **3. Refresh Token**

        Use grant_type=refresh_token with a valid refresh token to obtain a new
        JWT.

        ```json

        {
          "refreshToken": "d891ac59aef945a3b67dc2ef569b20aa"
        }

        ```


        **Parameters**

        * `grant_type`: Set to `refresh_token` when using a refresh token to
        obtain a new JWT

        * `refreshToken` (string, optional): Required when grant_type is
        refresh_token. Provide a valid Refresh Token to obtain a new JWT


        **Responses**

        * `201 Created`: Successfully returns a new access_token  

        * `403 Forbidden`: No valid credentials found


        **Security**

        * This API supports multiple authentication methods for flexibility

        * Priority order: Refresh token → Authorization header → Cookie

        * Applicable for both public and internal applications, but
        authentication is required
      parameters:
        - name: grant_type
          in: query
          description: "Grant type: use 'cc' for refresh token operation"
          schema:
            $ref: "#/components/schemas/RefreshGrantType"
      requestBody:
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/TokenBodyDto"
            example:
              token: null
              refreshToken: d891ac59aef945a3b67dc2ef569b20aa
      responses:
        "201":
          description: Created
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/TokenResultDto"
              example:
                accessToken: eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCc8.eyJleHAiOjE3NjExODQ0NTgsXmlzcyI6IkVkZ2VTeW5jLkF1dGhTZXJ2ZXIiLCJhdWQiOiJFZGdlU3luYy5BUEkiLCJpZCI6IjNhMWMxNjVlLTg2YmUtZDY3Yy03ZjVlLTY1ZjljMGZhZTAxNCIsInN1YiI6ImJhNmRjNzUyLTgxMDgtNGVjNS1hM2NhLWFmMDFhYjY0ODlkNiIsInJvbGUiOiJhZG1pbiIsInJlYWxtX2FjY2VzcyI6eyJyb2xlcyI6WyJhZG1pbiJdfSwicHJlZmVycmVkX3VzZXJuYW1lIjoiYWRtaW5AYWR2YW50ZWNoLmNvbSIsImVtYWlsIjoiYWRtaW5AYWR2YW50ZWNoLmNvbSIsInJlc291cmNlX2FjY2VzcyI6eyIzYTFiMDA0NS0xYmRmLTI1YWQtMzg3Ny01ZTdlY2M5ZTBmM2EiOnsib3JnTmFtZSI6IlNlY29uZE9yZ18yMSIsIm9yZ1JvbGUiOiJhZG1pbiIsInJvbGVzIjpbXX0sIjNhMWIwMDNjLWE0MmMtZWU0ZS01ZDViLTcyNDlmYTljYWUzNCI6eyJvcmdOYW1lIjoiRmlyc3RPcmcyIiwib3JnUm9sZSI6ImFkbWluIiwicm9sZXMiOltdfSwiM2ExYjAwM2ItM2VjMS0xNzkyLTQ0NzYtMTI5N2VmMGMyOGE1Ijp7Im9yZ05hbWUiOiJSb290T3JnIiwib3JnUm9sZSI6ImFkbWluIiwicm9sZXMiOltdfSwiM2ExZDAyNDQtMGQyMy1kNjQ0LWRjOWUtNzEwZjRkOWI4MjFlIjp7Im9yZ05hbWUiOiJSb290Q2hpbGQwMSIsIm9yZ1JvbGUiOiJhZG1pbiIsInJvbGVzIjpbXX0sIjNhMWQwMjQ1LTA2NTUtNzI0Ny1jN2M2LWYyZDIyMWVkM2YzYSI6eyJvcmdOYW1lIjoiUm9vdENoaWxkMDIiLCJvcmdSb2xlIjoiYWRtaW4iLCJyb2xlcyI6W119fSwidGVuYW50SWQiOiJ5eWRzIiwic3JwX25hbWUiOiJlZGdlc3luYyJ9.XqET_6BoV8D1UXhgqQQro8AOG7faeS2loTgJMRRycuFtbrAHMgGBJecFKqRlVsSrouBZZp62mfbpC9dfQAGVddadvwKza3P6u26WwSvVUmj67rL8rJfhFNiB0bAsqxK6yNK50MIxBYtCM_KpdEeDG-1X04TNgsDYZ5nXlxGcUzzNVPceVocfmTa2I6sVEYJCxCFsZRNdz-pUpVT11J97gTIAO_lqAanVI9H8aKtEOkLF844sm8NAKynogJhySGjhM79dbcdClPICYJZ9IVo1IL6VlNhyui3PkZKD0h2DA32xCScOdZI7klSg1x5o1r1_oMV-b03cxtyTxjERCCxTDA
                refreshToken: d891ac59aef945a3b67dc2ef569b20aa
                expiresIn: 7200
                tokenType: Bearer
        "400":
          description: Bad Request
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/RemoteServiceErrorResponse"
        "401":
          description: Unauthorized
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/RemoteServiceErrorResponse"
        "403":
          description: Forbidden
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/RemoteServiceErrorResponse"
        "404":
          description: Not Found
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/RemoteServiceErrorResponse"
        "500":
          description: Internal Server Error
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/RemoteServiceErrorResponse"
        "501":
          description: Not Implemented
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/RemoteServiceErrorResponse"
      security:
        - Bearer: []
  /api/v1/devices/{deviceId}/telemetry-configs:
    get:
      tags:
        - ___swagger_2-device-management_swagger_json_Devices
      summary: Get device telemetry configurations
      description: Get telemetry configurations for a specific device.
      parameters:
        - name: deviceId
          in: path
          description: Device ID
          required: true
          schema:
            type: string
            description: Device ID
          example: "251547379986071552"
        - name: deviceName
          in: query
          description: Device declared name
          schema:
            type: string
            description: Device declared name
          example: MyFirstDevice
      responses:
        "200":
          description: OK
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Success"
              example:
                - enabled: true
                  deviceName: EPC-R7300-cc827f50f409
                  sensors:
                    - name: AI_0
                      config:
                        enabled: true
                        interval: 1000
                      sensorInfo:
                        schema: double
                        displayName: Temperature Sensor
                        description: Analog input sensor for temperature measurement
                    - name: DI_0
                      config:
                        enabled: false
                        interval: 500
                      sensorInfo:
                        schema: boolean
                        displayName: Door Switch
                        description: Digital input for door open/close status
      security:
        - Bearer: []
    patch:
      tags:
        - ___swagger_2-device-management_swagger_json_Devices
      summary: Update device telemetry configurations
      description: >-
        Partially update telemetry configurations for a specific device.


        Use the GET endpoint to verify the actual applied configuration.


        The 202 Accepted response indicates the desired configuration was sent,
        but not that the device has already applied it.
      parameters:
        - name: deviceId
          in: path
          description: Device ID
          required: true
          schema:
            type: string
            description: Device ID
          example: "251547379986071552"
      requestBody:
        content:
          application/json:
            schema:
              type: array
              items:
                $ref: "#/components/schemas/SubNodeDeviceConfigForEndUserDto"
            example:
              - enabled: true
                deviceName: EPC-R7300-cc827f50f409
                sensors:
                  - name: AI_0
                    config:
                      enabled: true
                      interval: 1000
                    sensorInfo:
                      schema: double
                      displayName: Temperature Sensor
                      description: Analog input sensor for temperature measurement
                  - name: DI_0
                    config:
                      enabled: false
                      interval: 1500
                    sensorInfo:
                      schema: boolean
                      displayName: Door Switch
                      description: Digital input for door open/close status
              - enabled: true
                deviceName: EPC-R7300-d4e5f6a0b1c2
                sensors:
                  - name: AI_0
                    config:
                      enabled: true
                      interval: 2000
                    sensorInfo:
                      schema: integer
                      displayName: Pressure Sensor
                      description: Analog input for pressure measurement
                  - name: DO_0
                    config:
                      enabled: true
                      interval: 1000
                    sensorInfo:
                      schema: boolean
                      displayName: Relay Output
                      description: Digital output for relay control
          text/json:
            schema:
              type: array
              items:
                $ref: "#/components/schemas/SubNodeDeviceConfigForEndUserDto"
            example:
              - enabled: true
                deviceName: EPC-R7300-cc827f50f409
                sensors:
                  - name: AI_0
                    config:
                      enabled: true
                      interval: 1000
                    sensorInfo:
                      schema: double
                      displayName: Temperature Sensor
                      description: Analog input sensor for temperature measurement
                  - name: DI_0
                    config:
                      enabled: false
                      interval: 1500
                    sensorInfo:
                      schema: boolean
                      displayName: Door Switch
                      description: Digital input for door open/close status
              - enabled: true
                deviceName: EPC-R7300-d4e5f6a0b1c2
                sensors:
                  - name: AI_0
                    config:
                      enabled: true
                      interval: 2000
                    sensorInfo:
                      schema: integer
                      displayName: Pressure Sensor
                      description: Analog input for pressure measurement
                  - name: DO_0
                    config:
                      enabled: true
                      interval: 1000
                    sensorInfo:
                      schema: boolean
                      displayName: Relay Output
                      description: Digital output for relay control
          application/*+json:
            schema:
              type: array
              items:
                $ref: "#/components/schemas/SubNodeDeviceConfigForEndUserDto"
            example:
              - enabled: true
                deviceName: EPC-R7300-cc827f50f409
                sensors:
                  - name: AI_0
                    config:
                      enabled: true
                      interval: 1000
                    sensorInfo:
                      schema: double
                      displayName: Temperature Sensor
                      description: Analog input sensor for temperature measurement
                  - name: DI_0
                    config:
                      enabled: false
                      interval: 1500
                    sensorInfo:
                      schema: boolean
                      displayName: Door Switch
                      description: Digital input for door open/close status
              - enabled: true
                deviceName: EPC-R7300-d4e5f6a0b1c2
                sensors:
                  - name: AI_0
                    config:
                      enabled: true
                      interval: 2000
                    sensorInfo:
                      schema: integer
                      displayName: Pressure Sensor
                      description: Analog input for pressure measurement
                  - name: DO_0
                    config:
                      enabled: true
                      interval: 1000
                    sensorInfo:
                      schema: boolean
                      displayName: Relay Output
                      description: Digital output for relay control
      responses:
        "202":
          description: Request accepted and desired configuration sent to device
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Success"
              example:
                - enabled: true
                  deviceName: EPC-R7300-cc827f50f409
                  sensors:
                    - name: AI_0
                      config:
                        enabled: true
                        interval: 1000
                      sensorInfo:
                        schema: double
                        displayName: Temperature Sensor
                        description: Analog input sensor for temperature measurement
                    - name: DI_0
                      config:
                        enabled: false
                        interval: 1500
                      sensorInfo:
                        schema: boolean
                        displayName: Door Switch
                        description: Digital input for door open/close status
                - enabled: true
                  deviceName: EPC-R7300-d4e5f6a0b1c2
                  sensors:
                    - name: AI_0
                      config:
                        enabled: true
                        interval: 2000
                      sensorInfo:
                        schema: integer
                        displayName: Pressure Sensor
                        description: Analog input for pressure measurement
                    - name: DO_0
                      config:
                        enabled: true
                        interval: 1000
                      sensorInfo:
                        schema: boolean
                        displayName: Relay Output
                        description: Digital output for relay control
      security:
        - Bearer: []
  /api/v1/devices/{deviceId}:{status}:
    post:
      tags:
        - ___swagger_2-device-management_swagger_json_Devices
      summary: Update device status
      description: Deactivate or reactivate a device.
      parameters:
        - name: deviceId
          in: path
          description: Device id
          required: true
          schema:
            type: string
            description: Device id
          example: 74fe488d5d35
        - name: status
          in: path
          description: Device status
          required: true
          schema:
            $ref: "#/components/schemas/DeviceToggle"
          example: deactivate
      responses:
        "200":
          description: OK
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/EdgeSyncDeviceGetResponseDto"
              example:
                deviceId: 74fe488d5d54
                hwModel: EPC-R7300
                orgId: 5de4bd4f-bbb1-4653-95b8-239584600203
                status: Deactivated
                creationTime: 2024-01-15T10:20:30Z
                deviceName: First device
      security:
        - Bearer: []
  /api/v1/devices/{deviceId}:
    delete:
      tags:
        - ___swagger_2-device-management_swagger_json_Devices
      summary: Delete a device
      description: |-
        Permanently delete device by given deviceId.

        Before deletion, set the device status to Deactivated.
      parameters:
        - name: deviceId
          in: path
          description: Device ID
          required: true
          schema:
            type: string
            description: Device ID
          example: 74fe488d5d35
      responses:
        "204":
          description: No Content
        "403":
          description: Forbidden
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ProblemDetails"
              example:
                error:
                  code: Device.NotFound
                  message: The specified device does not exist.
                  details: "DeviceId: 74fe488d-5d35-4c00-a3b9-3c2b92e4b27a"
                  data:
                    timestamp: 2026-07-30T05:41:59.2583515Z
                    requestId: d497415c-a0cb-4395-b007-524ecd0600c8
                  validationErrors:
                    - message: DeviceId cannot be empty.
                      members:
                        - DeviceId
        "404":
          description: Not Found
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ProblemDetails"
              example:
                error:
                  code: Device.NotFound
                  message: The specified device does not exist.
                  details: "DeviceId: 74fe488d-5d35-4c00-a3b9-3c2b92e4b27a"
                  data:
                    timestamp: 2026-07-30T05:41:59.2711677Z
                    requestId: 9e79d6ea-456e-4f75-8919-d429841f4175
                  validationErrors:
                    - message: DeviceId cannot be empty.
                      members:
                        - DeviceId
      security:
        - Bearer: []
    patch:
      tags:
        - ___swagger_2-device-management_swagger_json_Devices
      summary: Update a device
      description: Update device by given deviceId.
      parameters:
        - name: deviceId
          in: path
          description: Device id
          required: true
          schema:
            type: string
            description: Device id
          example: 74fe488d5d35
      requestBody:
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/EdgeSyncDeviceUpdateRequestDto"
            example:
              orgId: 783707f1-0659-4892-a872-8f506d225d7b
              deviceName: First name
      responses:
        "200":
          description: OK
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/EdgeSyncDeviceUpdateResponseDto"
              example:
                deviceId: 74fe488d5d54
                orgId: 5de4bd4f-bbb1-4653-95b8-239584600203
                status: Activated
                hwModel: EPC_R7300
                deviceName: First name
      security:
        - Bearer: []
  /api/v1/devices/{deviceId}/capabilities:
    get:
      tags:
        - ___swagger_2-device-management_swagger_json_Devices
      summary: Get device hardware capabilities
      description: Retrieve the full hardware capability report of the specified
        device, including CPU, memory, disk, network interfaces, sensors,
        containers, and sub-nodes.
      parameters:
        - name: deviceId
          in: path
          description: Device MAC address or Device ID
          required: true
          schema:
            type: string
            description: Device MAC address or Device ID
          example: 74fe488d5d35
      responses:
        "200":
          description: OK
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/DeviceCapResponseDto"
              example:
                cmd: getDeviceCap
                seqId: 2
                reqSeqId: null
                rspSeqId: cf58e8bd-8304-469e-80a4-934cfddeddf6
                timestamp: 1774484514
                data:
                  deviceCapsDto:
                    - creationTime: 2026-03-26T05:32:44Z
                      groupId: eco1j
                      deviceId: 74fe488d5d52
                      data:
                        reported:
                          osName: ubuntu 24.04
                          manufacturer: NVIDIA
                          model: EPC-R7300
                          serialNumber: "1423623008565"
                          swVersion: 1.2.0
                          timestamp: "1774484514"
                          cpu:
                            numOfCores: 6
                            resourceName: deviceCPU
                            deviceResourceId: 07fe4715-d302-565d-9080-5a26ad3bda3b
                            processorArchitecture: ARM64
                            processorManufacturer: ARM
                          ram:
                            totalMemory: 7619.86
                            resourceName: deviceRAM
                            deviceResourceId: 0c88af70-048b-58c0-a8e9-012b7e92b365
                          disks:
                            - diskType: SSD
                              totalSize: 59.45
                              resourceName: /dev/nvme0n1p10
                              deviceResourceId: 39492b81-19cb-5fea-a508-cc4f68d9f38f
                          networkInterfaces:
                            - macAddress: 3a:33:de:72:29:69
                              resourceName: usb0
                              interfaceType: USB
                              deviceResourceId: 1c97412e-0e2f-5ff1-bd81-a41e306af252
                          sensors:
                            - dtmi: dtmi:advantech:EdgeSync:ContainerInfo:running;1
                              name: system-agent:running
                              resourceId: 7593453b-ee76-59c4-98b0-5eaf949ce47b
                              resourceShortId: ce47b
                              deviceResourceId: 470c611f560725a3c6d609c30cdc927a4b1f3404d71ca52d1a4ca75915d67323
                            - dtmi: dtmi:advantech:EdgeSync:CPUInfo:cpuUsage;1
                              name: deviceCPU:cpuUsage
                              resourceId: a1b2c3d4-0000-1111-2222-333344445555
                              resourceShortId: "45555"
                              deviceResourceId: 07fe4715-d302-565d-9080-5a26ad3bda3b
                          subNodes:
                            - deviceId: "315776044562907136"
                              updatedAt: 2026-03-25T06:49:25Z
                              deviceName: DeviceSubNode
                              deviceType: SubNode
                          containers:
                            - image: edgesync.azurecr.io/weda-edge/system-agent:v1.0
                              resourceName: system-agent
                              containerName: system-agent
                              deviceResourceId: 470c611f560725a3c6d609c30cdc927a4b1f3404d71ca52d1a4ca75915d67323
                          mainboardExtension:
                            deviceId: 74fe488d5d54
                            updatedAt: 2026-03-26T00:21:54Z
                            sensorCount: 42
                        desired: {}
      security:
        - Bearer: []
  /api/v1/devices/{deviceId}/custom-info:
    get:
      tags:
        - ___swagger_2-device-management_swagger_json_Devices
      summary: Get custom info of a device
      description: >-
        Retrieve all custom info entries of the specified device in JSON
        key/value format.  

        Each key represents a custom property of the device.  


        **Usage**  

        `GET /devices/{deviceId}/custom-info`  


        **Parameters**  

        - `deviceId` (string, required): the ID of the device.  


        **Responses**  

        - `200 OK`: returns a dictionary of key/value pairs.  

        - `404 Not Found`: device not found.  


        **Security**  

        This API requires authentication.
      parameters:
        - name: deviceId
          in: path
          description: The ID of the device
          required: true
          schema:
            type: string
            description: The ID of the device
          example: 74fe488d5d35
      responses:
        "200":
          description: OK
          content:
            application/json:
              schema:
                type: object
                additionalProperties: {}
              example:
                owner: a67a9314-997b-4a14-aad7-5f5f0c523591
                firmwareVersion: v1.2.3
                deviceName: Temperature Sensor A1
        "403":
          description: Forbidden
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/RemoteServiceErrorResponse"
              example:
                error:
                  code: Device.NotFound
                  message: The specified device does not exist.
                  details: "DeviceId: 74fe488d-5d35-4c00-a3b9-3c2b92e4b27a"
                  data:
                    timestamp: 2026-07-30T05:41:59.4575117Z
                    requestId: ffe1c693-cde7-4e26-be20-454eb01fea0d
                  validationErrors:
                    - message: DeviceId cannot be empty.
                      members:
                        - DeviceId
      security:
        - Bearer: []
    put:
      tags:
        - ___swagger_2-device-management_swagger_json_Devices
      summary: Update multiple custom info values
      description: >-
        Insert or update multiple custom info key/value pairs for the specified
        device.  

        New keys will be created, and existing keys will be updated with the new
        values.  


        **Usage**  

        `PUT /devices/{deviceId}/custom-info`  


        **Parameters**  

        - `deviceId` (string, required): the ID of the device.  

        - `input` (Dictionary<string, string?>, required): JSON object
        containing key/value pairs.  


        **Responses**  

        - `200 OK`: update successful.  

        - `404 Not Found`: device not found.  


        **Security**  

        This API requires authentication.
      parameters:
        - name: deviceId
          in: path
          description: The ID of the device
          required: true
          schema:
            type: string
            description: The ID of the device
          example: 74fe488d5d35
      requestBody:
        content:
          application/json:
            schema:
              type: object
              additionalProperties:
                type: string
            example:
              owner: a67a9314-997b-4a14-aad7-5f5f0c523591
              firmwareVersion: v1.2.3
              deviceName: Temperature Sensor A1
      responses:
        "200":
          description: OK
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: "#/components/schemas/DeviceCustomInfoDto"
              example:
                owner: a67a9314-997b-4a14-aad7-5f5f0c523591
                firmwareVersion: v1.2.3
                deviceName: Temperature Sensor A1
        "400":
          description: Bad Request
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/RemoteServiceErrorResponse"
              example:
                error:
                  code: Device.NotFound
                  message: The specified device does not exist.
                  details: "DeviceId: 74fe488d-5d35-4c00-a3b9-3c2b92e4b27a"
                  data:
                    timestamp: 2026-07-30T05:41:59.470742Z
                    requestId: f403b99b-8ac3-4bfe-a68b-cd9e8f0cce55
                  validationErrors:
                    - message: DeviceId cannot be empty.
                      members:
                        - DeviceId
        "401":
          description: Unauthorized
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/RemoteServiceErrorResponse"
              example:
                error:
                  code: Device.NotFound
                  message: The specified device does not exist.
                  details: "DeviceId: 74fe488d-5d35-4c00-a3b9-3c2b92e4b27a"
                  data:
                    timestamp: 2026-07-30T05:41:59.4704243Z
                    requestId: 89f4d9b3-1ac1-46c5-b113-2b9f6931b33b
                  validationErrors:
                    - message: DeviceId cannot be empty.
                      members:
                        - DeviceId
        "403":
          description: Forbidden
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/RemoteServiceErrorResponse"
              example:
                error:
                  code: Device.NotFound
                  message: The specified device does not exist.
                  details: "DeviceId: 74fe488d-5d35-4c00-a3b9-3c2b92e4b27a"
                  data:
                    timestamp: 2026-07-30T05:41:59.469911Z
                    requestId: 53b58b1e-8795-4825-9939-3f60b6a15350
                  validationErrors:
                    - message: DeviceId cannot be empty.
                      members:
                        - DeviceId
        "404":
          description: Not Found
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/RemoteServiceErrorResponse"
              example:
                error:
                  code: Device.NotFound
                  message: The specified device does not exist.
                  details: "DeviceId: 74fe488d-5d35-4c00-a3b9-3c2b92e4b27a"
                  data:
                    timestamp: 2026-07-30T05:41:59.4710836Z
                    requestId: 9e01b4ea-1f47-410f-b992-58827ecec785
                  validationErrors:
                    - message: DeviceId cannot be empty.
                      members:
                        - DeviceId
        "500":
          description: Internal Server Error
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/RemoteServiceErrorResponse"
              example:
                error:
                  code: Device.NotFound
                  message: The specified device does not exist.
                  details: "DeviceId: 74fe488d-5d35-4c00-a3b9-3c2b92e4b27a"
                  data:
                    timestamp: 2026-07-30T05:41:59.4715961Z
                    requestId: a2c0fb3c-cf27-4705-a9bb-edd90deb28d7
                  validationErrors:
                    - message: DeviceId cannot be empty.
                      members:
                        - DeviceId
        "501":
          description: Not Implemented
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/RemoteServiceErrorResponse"
              example:
                error:
                  code: Device.NotFound
                  message: The specified device does not exist.
                  details: "DeviceId: 74fe488d-5d35-4c00-a3b9-3c2b92e4b27a"
                  data:
                    timestamp: 2026-07-30T05:41:59.4713492Z
                    requestId: 85c9359e-80bd-4e64-85d3-6c6735431b5b
                  validationErrors:
                    - message: DeviceId cannot be empty.
                      members:
                        - DeviceId
      security:
        - Bearer: []
    delete:
      tags:
        - ___swagger_2-device-management_swagger_json_Devices
      summary: Delete all custom info of a device
      description: |-
        Remove all custom info entries associated with the specified device.  
        After deletion, the device will have no custom info data.  

        **Usage**  
        `DELETE /devices/{deviceId}/custom-info`  

        **Parameters**  
        - `deviceId` (string, required): the ID of the device.  

        **Responses**  
        - `204 No Content`: all custom info deleted.  
        - `404 Not Found`: device not found.  

        **Security**  
        This API requires authentication.
      parameters:
        - name: deviceId
          in: path
          description: The ID of the device
          required: true
          schema:
            type: string
            description: The ID of the device
          example: 74fe488d5d35
      responses:
        "204":
          description: NoContent
        "403":
          description: Forbidden
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/RemoteServiceErrorResponse"
              example:
                error:
                  code: Device.NotFound
                  message: The specified device does not exist.
                  details: "DeviceId: 74fe488d-5d35-4c00-a3b9-3c2b92e4b27a"
                  data:
                    timestamp: 2026-07-30T05:41:59.4782472Z
                    requestId: ef659df7-7164-454e-9868-fa7d10abe5c3
                  validationErrors:
                    - message: DeviceId cannot be empty.
                      members:
                        - DeviceId
      security:
        - Bearer: []
  /api/v1/devices/{deviceId}/custom-info/{key}:
    patch:
      tags:
        - ___swagger_2-device-management_swagger_json_Devices
      summary: Update Device Custom Info Value
      description: >-
        Updates the value of the specified custom info key for the given device.


        If the key does not exist, returns 404.


        Returns the complete list of all custom info entries for the device
        after the update.
      parameters:
        - name: deviceId
          in: path
          description: The ID of the device
          required: true
          schema:
            type: string
            description: The ID of the device
          example: 74fe488d5d35
        - name: key
          in: path
          description: The key of the custom info entry
          required: true
          schema:
            type: string
            description: The key of the custom info entry
          example: owner
      requestBody:
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/DeviceCustomInfoPatchDto"
            example:
              value: 26feee27-b0b3-4ab8-a1c5-9f520938fee6
      responses:
        "200":
          description: OK
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: "#/components/schemas/DeviceCustomInfoDto"
              example:
                - deviceId: 74fe488d5d35
                  key: owner
                  value: 26feee27-b0b3-4ab8-a1c5-9f520938fee6
                  datatype: uuid
        "403":
          description: Forbidden
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/RemoteServiceErrorResponse"
              example:
                error:
                  code: Device.NotFound
                  message: The specified device does not exist.
                  details: "DeviceId: 74fe488d-5d35-4c00-a3b9-3c2b92e4b27a"
                  data:
                    timestamp: 2026-07-30T05:41:59.4925837Z
                    requestId: 67165fe8-25dc-483f-9fae-9f5aeec17051
                  validationErrors:
                    - message: DeviceId cannot be empty.
                      members:
                        - DeviceId
      security:
        - Bearer: []
    delete:
      tags:
        - ___swagger_2-device-management_swagger_json_Devices
      summary: Delete a single custom info entry for device
      description: >-
        Remove a specific custom info entry identified by its key for the
        specified device.  

        If the key does not exist, a `404 Not Found` will be returned.  

        After deletion, returns the remaining custom info entries of the
        device.  


        **Usage**  

        `DELETE /devices/{deviceId}/custom-info/{key}`  


        **Parameters**  

        - `deviceId` (string, required): the ID of the device.  

        - `key` (string, required): the key of the custom info entry.  


        **Responses**  

        - `200 OK`: key deleted successfully, returns remaining custom info
        entries.  

        - `404 Not Found`: key not found.  


        **Security**  

        This API requires authentication.
      parameters:
        - name: deviceId
          in: path
          description: The ID of the device
          required: true
          schema:
            type: string
            description: The ID of the device
          example: 74fe488d5d35
        - name: key
          in: path
          description: The key of the custom info entry
          required: true
          schema:
            type: string
            description: The key of the custom info entry
          example: owner
      responses:
        "200":
          description: OK
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: "#/components/schemas/DeviceCustomInfoDto"
              example:
                - deviceId: 74fe488d5d35
                  key: owner
                  value: 26feee27-b0b3-4ab8-a1c5-9f520938fee6
                  datatype: uuid
        "403":
          description: Forbidden
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/RemoteServiceErrorResponse"
              example:
                error:
                  code: Device.NotFound
                  message: The specified device does not exist.
                  details: "DeviceId: 74fe488d-5d35-4c00-a3b9-3c2b92e4b27a"
                  data:
                    timestamp: 2026-07-30T05:41:59.5019663Z
                    requestId: 5b6ec5b2-31f0-4524-b331-d6330c74f224
                  validationErrors:
                    - message: DeviceId cannot be empty.
                      members:
                        - DeviceId
      security:
        - Bearer: []
  /api/v1/devices:
    get:
      tags:
        - ___swagger_2-device-management_swagger_json_Devices
      summary: Get devices with pagination
      description: Get kinds of devices. Including WEDA Node, subnodes, and Custom devices.
      parameters:
        - name: sorting
          in: query
          schema:
            type: string
        - name: skipCount
          in: query
          schema:
            maximum: 2147483647
            minimum: 0
            type: integer
            format: int32
        - name: maxResultCount
          in: query
          schema:
            maximum: 2147483647
            minimum: 1
            type: integer
            format: int32
      responses:
        "200":
          description: OK
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/BasicInfoDtoPagedResultDto"
              example:
                totalCount: 2
                items:
                  - subNodes:
                      - deviceId: aabbccddeeff
                        deviceName: SubNode Sensor 1
                        deviceType: sub-node
                    basicInfoId: 3fa85f64-5717-4562-b3fc-2c963f66afa6
                    deviceName: WedaNode 001
                    type: WedaNode
                    status: Activated
                    deviceId: 74fe488d5d54
                    creationTime: 2025-01-01T00:00:00Z
                  - wedaNode:
                      deviceId: 74fe488d5d54
                      deviceName: WedaNode 001
                      deviceType: weda-node
                    basicInfoId: 4fa85f64-5717-4562-b3fc-2c963f66afb7
                    deviceName: SubNode 001
                    type: SubNode
                    status: Activated
                    deviceId: aabbccddeeff
                    creationTime: 2025-01-01T00:00:00Z
      security:
        - Bearer: []
  /api/v1/orgs/{orgId}/devices:
    post:
      tags:
        - ___swagger_2-device-management_swagger_json_Devices
      summary: Register a device to an organization
      description: Link one existed weda node device to one organization. Or create a
        weda node device which is associated with the organization.
      parameters:
        - name: orgId
          in: path
          required: true
          schema:
            type: string
          example: 5bd0c9f4-3b8f-4f24-b4f5-923f5c9eda50
      requestBody:
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/EdgeSyncDeviceCreateDto"
            example:
              deviceId: 74fe488d5d54
              hwModel: EPC-R7300
              deviceName: First device
      responses:
        "200":
          description: OK
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/EdgeSyncDeviceDto"
              example:
                deviceId: 74fe488d5d54
                hwModel: EPC-R7300
                orgId: 5de4bd4f-bbb1-4653-95b8-239584600203
                status: Activated
                deviceName: First device
        "400":
          description: Bad Request
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/RemoteServiceErrorResponse"
              example:
                error:
                  code: Device.NotFound
                  message: The specified device does not exist.
                  details: "DeviceId: 74fe488d-5d35-4c00-a3b9-3c2b92e4b27a"
                  data:
                    timestamp: 2026-07-30T05:41:59.6655621Z
                    requestId: 4943efc1-4595-49ce-947e-b485f2034792
                  validationErrors:
                    - message: DeviceId cannot be empty.
                      members:
                        - DeviceId
        "401":
          description: Unauthorized
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/RemoteServiceErrorResponse"
              example:
                error:
                  code: Device.NotFound
                  message: The specified device does not exist.
                  details: "DeviceId: 74fe488d-5d35-4c00-a3b9-3c2b92e4b27a"
                  data:
                    timestamp: 2026-07-30T05:41:59.6653093Z
                    requestId: 287af199-3a71-48d8-b723-e17a76cab548
                  validationErrors:
                    - message: DeviceId cannot be empty.
                      members:
                        - DeviceId
        "403":
          description: Forbidden
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/RemoteServiceErrorResponse"
              example:
                error:
                  code: Device.NotFound
                  message: The specified device does not exist.
                  details: "DeviceId: 74fe488d-5d35-4c00-a3b9-3c2b92e4b27a"
                  data:
                    timestamp: 2026-07-30T05:41:59.6649964Z
                    requestId: c99dc9d4-efaf-4606-b1ab-953d8c7f3d5e
                  validationErrors:
                    - message: DeviceId cannot be empty.
                      members:
                        - DeviceId
        "404":
          description: Not Found
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/RemoteServiceErrorResponse"
              example:
                error:
                  code: Device.NotFound
                  message: The specified device does not exist.
                  details: "DeviceId: 74fe488d-5d35-4c00-a3b9-3c2b92e4b27a"
                  data:
                    timestamp: 2026-07-30T05:41:59.6657571Z
                    requestId: 5699853f-23c4-4860-8873-e123acfc9a91
                  validationErrors:
                    - message: DeviceId cannot be empty.
                      members:
                        - DeviceId
        "409":
          description: Conflict
        "500":
          description: Internal Server Error
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/RemoteServiceErrorResponse"
              example:
                error:
                  code: Device.NotFound
                  message: The specified device does not exist.
                  details: "DeviceId: 74fe488d-5d35-4c00-a3b9-3c2b92e4b27a"
                  data:
                    timestamp: 2026-07-30T05:41:59.6661475Z
                    requestId: ac6f33b2-7262-43e9-b7a3-f761fbad7265
                  validationErrors:
                    - message: DeviceId cannot be empty.
                      members:
                        - DeviceId
        "501":
          description: Not Implemented
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/RemoteServiceErrorResponse"
              example:
                error:
                  code: Device.NotFound
                  message: The specified device does not exist.
                  details: "DeviceId: 74fe488d-5d35-4c00-a3b9-3c2b92e4b27a"
                  data:
                    timestamp: 2026-07-30T05:41:59.6659548Z
                    requestId: 0b6926d3-7668-4e31-8f3b-673dc52c37b3
                  validationErrors:
                    - message: DeviceId cannot be empty.
                      members:
                        - DeviceId
      security:
        - Bearer: []
    get:
      tags:
        - ___swagger_2-device-management_swagger_json_Devices
      summary: List Weda Nodes by Organization
      description: This api will response paginated list of Weda Node devices
        belonging to a specific organization ID.
      parameters:
        - name: orgId
          in: path
          description: Organization ID
          required: true
          schema:
            type: string
            description: Organization ID
            format: uuid
          example: 77ffccee-4f7a-46cd-a000-8a2c254edb53
        - name: sorting
          in: query
          schema:
            type: string
          example: deviceId asc
        - name: skipCount
          in: query
          schema:
            type: integer
            format: int32
          example: 0
        - name: maxResultCount
          in: query
          schema:
            type: integer
            format: int32
          example: 100
      responses:
        "200":
          description: OK
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/EdgeSyncDeviceGetResponseDtoPagedResultDto"
              example:
                totalCount: 1
                items:
                  - deviceId: 74fe488d5d54
                    hwModel: EPC-R7300
                    orgId: 5de4bd4f-bbb1-4653-95b8-239584600203
                    status: Activated
                    creationTime: 2024-01-15T10:20:30Z
                    deviceName: First device
        "400":
          description: Bad Request
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/RemoteServiceErrorResponse"
              example:
                error:
                  code: Device.NotFound
                  message: The specified device does not exist.
                  details: "DeviceId: 74fe488d-5d35-4c00-a3b9-3c2b92e4b27a"
                  data:
                    timestamp: 2026-07-30T05:41:59.756329Z
                    requestId: ed8db631-7378-4d1a-a064-759d733b5828
                  validationErrors:
                    - message: DeviceId cannot be empty.
                      members:
                        - DeviceId
        "401":
          description: Unauthorized
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/RemoteServiceErrorResponse"
              example:
                error:
                  code: Device.NotFound
                  message: The specified device does not exist.
                  details: "DeviceId: 74fe488d-5d35-4c00-a3b9-3c2b92e4b27a"
                  data:
                    timestamp: 2026-07-30T05:41:59.7561335Z
                    requestId: d56e25dc-f53e-43e3-a998-7ed02c7e7d3f
                  validationErrors:
                    - message: DeviceId cannot be empty.
                      members:
                        - DeviceId
        "403":
          description: Forbidden
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/RemoteServiceErrorResponse"
              example:
                error:
                  code: Device.NotFound
                  message: The specified device does not exist.
                  details: "DeviceId: 74fe488d-5d35-4c00-a3b9-3c2b92e4b27a"
                  data:
                    timestamp: 2026-07-30T05:41:59.7557551Z
                    requestId: de55287b-ac04-4c75-b33a-74d665deb415
                  validationErrors:
                    - message: DeviceId cannot be empty.
                      members:
                        - DeviceId
        "404":
          description: Not Found
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/RemoteServiceErrorResponse"
              example:
                error:
                  code: Device.NotFound
                  message: The specified device does not exist.
                  details: "DeviceId: 74fe488d-5d35-4c00-a3b9-3c2b92e4b27a"
                  data:
                    timestamp: 2026-07-30T05:41:59.7565442Z
                    requestId: 9ae06a21-d0d3-491c-8e7b-bfbee1de348e
                  validationErrors:
                    - message: DeviceId cannot be empty.
                      members:
                        - DeviceId
        "500":
          description: Internal Server Error
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/RemoteServiceErrorResponse"
              example:
                error:
                  code: Device.NotFound
                  message: The specified device does not exist.
                  details: "DeviceId: 74fe488d-5d35-4c00-a3b9-3c2b92e4b27a"
                  data:
                    timestamp: 2026-07-30T05:41:59.7569575Z
                    requestId: 350fd9d8-4de3-496a-bd9e-7243c1169695
                  validationErrors:
                    - message: DeviceId cannot be empty.
                      members:
                        - DeviceId
        "501":
          description: Not Implemented
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/RemoteServiceErrorResponse"
              example:
                error:
                  code: Device.NotFound
                  message: The specified device does not exist.
                  details: "DeviceId: 74fe488d-5d35-4c00-a3b9-3c2b92e4b27a"
                  data:
                    timestamp: 2026-07-30T05:41:59.7567396Z
                    requestId: bf246cb0-1464-49ce-ab12-d6e3f7aed469
                  validationErrors:
                    - message: DeviceId cannot be empty.
                      members:
                        - DeviceId
      security:
        - Bearer: []
  /api/v1/devices/{deviceId}/auth:
    get:
      tags:
        - ___swagger_2-device-management_swagger_json_WEDA Node Credentials
      summary: Get device auth info
      description: Get auth info of a device with downloadable encrypted file
      parameters:
        - name: deviceId
          in: path
          description: Device mac
          required: true
          schema:
            type: string
            description: Device mac
          example: 74fe488d5d35
        - name: type
          in: query
          description: Auth info type
          schema:
            $ref: "#/components/schemas/ProvisionServiceType"
          example: 1
        - name: enc
          in: query
          description: Encrypt or not
          schema:
            type: boolean
            description: Encrypt or not
          example: true
      responses:
        "200":
          description: OK
          content:
            application/json:
              schema:
                type: string
                format: binary
        "403":
          description: Forbidden
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ProblemDetails"
        "404":
          description: Not Found
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ProblemDetails"
      security:
        - Bearer: []
  /api/v1/devices/{deviceId}/docker/stacks/commands:{action}:
    post:
      tags:
        - ___swagger_3-container-management_swagger_json_Container Commands
      summary: Manage Container State
      description: |-
        
        Overview: Requests a command to be executed on a device.

        • Valid actions: start, stop, resume, restart, and pause

        • Real-time execution: Sends command via NATS and waits for response

        • Command logging: Tracks command execution for audit purposes
      parameters:
        - name: deviceId
          in: path
          description: The unique identifier of the target device.
          required: true
          schema:
            type: string
        - name: action
          in: path
          description: "Container lifecycle action to execute. Valid values: start, stop,
            resume, restart, pause."
          required: true
          schema:
            $ref: "#/components/schemas/StackAction"
      requestBody:
        description: Represents a command request for container stack operations on edge
          devices.
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/CommandRequest"
            example:
              stackConfigId: 02933b82-83d6-4d90-a1f5-37c767158d75
        required: true
      responses:
        "200":
          description: OK
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/CreateContainerStackDto"
              example:
                deviceId: 74fe488d5d54
                seqId: 1
                reqSeqId: 653e9d37-858b-4c32-bbf9-371b72add1ea
                rspSeqId: 6b80de22-cf58-4612-bf40-c2cef7fbab33
                cmd: deviceCmd
                status: 0
                message: "Stack command: stack.pause sent successfully"
        "400":
          description: Bad Request
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ProblemDetails"
              example:
                type: https://learn.advantech.com/WEDA/api/errorcode#ValidationError
                title: Bad Request - Invalid request parameters
                status: 400
                detail: The field Action is invalid.
                instance: /api/v1/orgs/{orgId}/commands
        "500":
          description: Internal Server Error
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ProblemDetails"
              example:
                type: https://learn.advantech.com/WEDA/api/errorcode#InternalServerError
                title: Internal Server Error
                status: 500
                detail: An internal error occurred during your request!
      security:
        - Bearer: []
  /api/v1/devices/{deviceId}/docker/stacks/commands/results:
    get:
      tags:
        - ___swagger_3-container-management_swagger_json_Container Commands
      summary: List Container State Changing Results
      description: >-
        
        Overview: Retrieves paginated command execution results for a specific
        device and stack.


        • Latest mode: When range is set to "latest", only the most recent
        command result is returned


        • Pagination support: Supports skip and take for result pagination


        • Sorting support: Supports sorting by ExecutedAt field (ascending or
        descending)


        • Cache-based: Results are cached in memory for 1 hour
      parameters:
        - name: deviceId
          in: path
          description: The unique identifier of the device.
          required: true
          schema:
            type: string
        - name: stackConfigId
          in: query
          description: An unique ID for the stack configuration.
          required: true
          schema:
            type: string
            format: uuid
        - name: range
          in: query
          description: >-
            Specifies the log range to query. If set to "latest", only the most
            recent command result is returned.

            Valid values: "all" (default) or "latest"
          schema:
            type: string
            default: all
        - name: maxResultCount
          in: query
          description: Maximum number of results to return. Must be between 1 and 1000.
          schema:
            maximum: 1000
            minimum: 1
            type: integer
            format: int32
        - name: skipCount
          in: query
          description: Number of results to skip for pagination.
          schema:
            type: integer
            format: int32
        - name: sorting
          in: query
          description: |-
            Sorting expression for the results.
            The allowed values are "ExecutedAt desc" and "ExecutedAt asc".
          schema:
            type: string
            default: executedAt desc
      responses:
        "200":
          description: OK
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/PagedResultDto  of  CommandExecutionResultCacheDto"
              example:
                totalCount: 1
                items:
                  - deviceId: 74fe488d5d54
                    seqId: 1
                    reqSeqId: 2f96a5f1-47e7-4747-b61b-5196ddf842eb
                    rspSeqId: f9ad819e-dc73-423d-a542-c80929d7ffe7
                    cmd: deviceCmd
                    data:
                      deviceCmd: stack.start
                      status: 0
                      message: stack command received
                      resultData:
                        stackId: 022615e9-87ef-4c2e-b3cb-f2615654e7c4
                      executedAt: 2025-12-01T05:39:58.871141Z
                      completedAt: 2025-12-01T05:39:58.871141Z
      security:
        - Bearer: []
  /api/v1/orgs/{orgId}/stack-configs/{stackConfigId}/revisions/{stackRevisionId}:deploy:
    post:
      tags:
        - ___swagger_3-container-management_swagger_json_Container Deployments
      summary: Deploys container stack
      description: >-
        
        Overview: Deploys a container stack to multiple devices simultaneously
        with intelligent conflict resolution.


        Request body example:

        ```

        {
          "deviceIds": ["74fe488d5d54", "a1b2c3d4e5f6", "001122334455"]
        }
                    
        ```


        • Intelligent conflict resolution: Automatically determines action for
        each device:


        -- Skip: Device already has the exact same stack version deployed


        -- Update: Device has a different version of the same stack (old version
        is removed)


        -- Add: Device doesn't have this stack deployed


        • Batch processing: All devices are processed in parallel for optimal
        performance


        • Maximum count: Limited to 128 devices per batch deployment


        • Detailed reporting: Returns comprehensive statistics including total,
        skipped, and newly deployed device counts


        • Device action tracking: DeviceActions dictionary maps each device ID
        to its action (skip/update/add)


        • Order preservation: Results maintain the same order as input DeviceIds


        • Error handling: If any device deployment fails, the entire operation
        fails with detailed error message
      parameters:
        - name: stackConfigId
          in: path
          description: An unique ID for the stack configuration.
          required: true
          schema:
            type: string
            format: uuid
        - name: stackRevisionId
          in: path
          description: Revision ID for the specified version of stack configuration.
          required: true
          schema:
            type: string
            format: uuid
        - name: orgId
          in: path
          description: Identity for user's organization.
          required: true
          schema:
            type: string
            format: uuid
      requestBody:
        description: Batch deployment configuration containing list of device IDs to
          deploy to.
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/CreateUpdateStackDeploymentsDto"
            example:
              deviceIds:
                - 74fe488d5d54
                - a1b2c3d4e5f6
                - "001122334455"
        required: true
      responses:
        "200":
          description: OK
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/StackDeploymentsDto"
              example:
                stackDeployments:
                  - stackConfigId: 00000000-0000-0000-0000-000000000000
                    stackRevisionId: 9ad86e25-c585-4c64-964f-505595f29b07
                    deploymentId: 59e2e9ca-f833-44f9-8910-b3fd51651039
                    taskId: 739d7da8-9a0a-4442-9b9e-d9b6de8b3a49
                    stackName: test-name
                    deviceId: 74fe488d5d54
                    version: "1"
                    status: deploying
                    containers: []
                    error: null
                    operationAction: null
                    operationStatus: null
                    reason: null
                    active: true
                    creationTime: 0001-01-01T00:00:00Z
                totalDevices: 3
                skippedDevices: 0
                newlyDeployedDevices: 3
                deviceActions:
                  74fe488d5d54: add
                  a1b2c3d4e5f6: add
                  "001122334455": update
        "400":
          description: Bad Request
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ProblemDetails"
              example:
                type: https://learn.advantech.com/WEDA/api/errorcode#ValidationError
                title: Bad Request - Invalid request parameters
                status: 400
                detail: The field Action is invalid for DeviceIds.
                instance: /api/v1/orgs/{orgId}/stacks/{stackRevisionId}/deployments
        "404":
          description: Not Found
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ProblemDetails"
              example:
                type: https://learn.advantech.com/WEDA/api/errorcode#ResourceNotFound
                title: Resource Not Found
                status: 404
                detail: "Resource Not Found. input: 3fa85f64-5717-4562-b3fc-2c963f66afa6"
                instance: /api/v1/orgs/{orgId}/stacks/{stackRevisionId}/deployments
        "500":
          description: Internal Server Error
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ProblemDetails"
              example:
                type: https://learn.advantech.com/WEDA/api/errorcode#InternalServerError
                title: Internal Server Error
                status: 500
                detail: An internal error occurred during your request!
      security:
        - Bearer: []
  /api/v1/devices/{deviceId}/docker/stacks:
    get:
      tags:
        - ___swagger_3-container-management_swagger_json_Container Deployments
      summary: List stacks in device
      description: >-
        
        Overview: Retrieves all deployed container stacks on a specific device.


        • Filter by stackConfigId: When `stackConfigId` is provided, returns
        only the deployment matching that stack config


        • All stacks: When `stackConfigId` is omitted or empty, returns all
        deployed stacks on the device


        • Real-time status: Response includes container runtime status (e.g.,
        running, stopped) reported by the device, not just the deployment record


        • Sorting support: Supports sorting by CreationTime (default:
        descending)


        • MaxResultCount: Maximum 1000 records per page
      parameters:
        - name: deviceId
          in: path
          description: The unique identifier of the target device (e.g., "74fe488d5d54").
          required: true
          schema:
            type: string
        - name: stackConfigId
          in: query
          description: An unique ID for the stack configuration. If not provided, all
            stacks on the device will be return.
          schema:
            type: string
            format: uuid
        - name: maxResultCount
          in: query
          description: Maximum number of results to return. Must be between 1 and 1000.
          schema:
            maximum: 1000
            minimum: 1
            type: integer
            format: int32
        - name: skipCount
          in: query
          description: Number of results to skip for pagination.
          schema:
            type: integer
            format: int32
        - name: sorting
          in: query
          description: |-
            Sorting expression for the results.
            The allowed values are "CreationTime desc" and "CreationTime asc".
          schema:
            type: string
            default: creationTime desc
      responses:
        "200":
          description: OK
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/StackDeploymentDto"
              example:
                totalCount: 1
                items:
                  - stackConfigId: 00000000-0000-0000-0000-000000000000
                    stackRevisionId: d4dafc55-c2d8-4a5d-9f4c-a5d7fed152ad
                    deploymentId: bdd9db57-0ff9-451f-b070-fc2fad11779b
                    taskId: b2f11c76-eba1-4856-80fe-9cb7e8750c93
                    stackName: test-name
                    deviceId: 74fe488d5d54
                    version: "1"
                    status: running
                    containers: []
                    error: null
                    operationAction: null
                    operationStatus: null
                    reason: null
                    active: true
                    creationTime: 0001-01-01T00:00:00Z
        "404":
          description: Not Found
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ProblemDetails"
              example:
                type: https://learn.advantech.com/WEDA/api/errorcode#ResourceNotFound
                title: Forbidden
                status: 403
                detail: No active deployment found for device 74fe488d5d51 and stack
                  1f225b34-2760-4e35-b5d5-ea81f175d861
                instance: /api/v1/orgs/{orgId}/devices/{deviceId}/deployments
        "500":
          description: Internal Server Error
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ProblemDetails"
              example:
                type: https://learn.advantech.com/WEDA/api/errorcode#InternalServerError
                title: Internal Server Error
                status: 500
                detail: An internal error occurred during your request!
      security:
        - Bearer: []
    delete:
      tags:
        - ___swagger_3-container-management_swagger_json_Container Deployments
      summary: Remove stack from device
      description: >-
        
        Overview: Undeploy a specific stack deployment from a single device.


        • Single stack removal: Removes only the specified stack from the device


        • Preserve other stacks: All other stacks on the device remain unchanged


        • Active deployment only: Only removes currently active deployments


        • NATS notification: Sends updated configuration to the device


        • Database cleanup: Removes the deployment record from the database


        • Complete configuration: Device receives its complete remaining stack
        configuration
      parameters:
        - name: deviceId
          in: path
          description: ID of the device to undeploy from
          required: true
          schema:
            type: string
        - name: stackConfigId
          in: query
          description: An unique ID for the stack configuration. If not provided, all
            stacks on the device will be undeployed.
          schema:
            type: string
            format: uuid
      responses:
        "204":
          description: No Content
        "404":
          description: Not Found
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ProblemDetails"
              example:
                type: https://learn.advantech.com/WEDA/api/errorcode#Common.NotFoundWithKey
                title: Common.NotFoundWithKey
                status: 404
                detail: Resource 'deployment'(device cc827f50f406, stack
                  3fa85f64-5717-4562-b3fc-2c963f66afa6) not found
                instance: /api/v1/devices/{deviceId}/docker/stacks
        "500":
          description: Internal Server Error
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ProblemDetails"
              example:
                type: https://learn.advantech.com/WEDA/api/errorcode#InternalServerError
                title: Internal Server Error
                status: 500
                detail: An internal error occurred during your request!
      security:
        - Bearer: []
  /api/v1/orgs/{orgId}/stack-configs/deployments:
    get:
      tags:
        - ___swagger_3-container-management_swagger_json_Container Deployments
      summary: Get stack deployments
      description: >-
        
        Overview: Retrieves paginated list of all active stack deployments in
        the system.


        • System-wide view: Returns deployments across all devices and stacks


        • Active only: Excludes deleted or inactive deployments


        • Administrative use: Primarily for system administrators to monitor all
        deployments


        • MaxResultCount: Maximum 1000 records per page


        • Sorting support: Supports sorting by CreationTime, with descending
        order by CreationTime as the default.
      parameters:
        - name: orgId
          in: path
          description: Identity for user's organization.
          required: true
          schema:
            type: string
            format: uuid
        - name: stackRevisionId
          in: query
          description: Query the deployment results by specific revision ids of container
            stack.
          schema:
            type: array
            items:
              type: string
              format: uuid
        - name: stackNames
          in: query
          description: Query the deployment results by the specific stack names.
          schema:
            type: array
            items:
              type: string
        - name: deviceIds
          in: query
          description: Query the deployment results by the targeted device ids.
          schema:
            type: array
            items:
              type: string
        - name: maxResultCount
          in: query
          description: Maximum number of results to return. Must be between 1 and 1000.
          schema:
            maximum: 1000
            minimum: 1
            type: integer
            format: int32
        - name: skipCount
          in: query
          description: Number of results to skip for pagination.
          schema:
            type: integer
            format: int32
        - name: sorting
          in: query
          description: |-
            Sorting expression for the results
            Default is "CreationTime desc".
          schema:
            type: string
            default: creationTime desc
      responses:
        "200":
          description: OK
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/CreateContainerStackDto"
              example:
                totalCount: 1
                items:
                  - stackConfigId: 00000000-0000-0000-0000-000000000000
                    stackRevisionId: 068372dd-4cfe-4c2b-8c1a-71f6ebb8fddd
                    deploymentId: 0c3852d8-a555-4138-bec7-42ed0dfd36c5
                    taskId: 997d89de-2729-40d6-9ec1-82f0211bdd58
                    stackName: test-name
                    deviceId: 74fe488d5d54
                    version: "1"
                    status: running
                    containers: []
                    error: null
                    operationAction: null
                    operationStatus: null
                    reason: null
                    active: true
                    creationTime: 0001-01-01T00:00:00Z
        "400":
          description: Bad Request
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ProblemDetails"
              example:
                type: https://learn.advantech.com/WEDA/api/errorcode#ValidationError
                title: Bad Request - Invalid request parameters
                status: 400
                detail: The value 'a' is not valid for StackDeploymentIds.
                instance: /api/v1/orgs/{orgId}/stacks/{stackRevisionId}/deployments
        "403":
          description: Forbidden
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ProblemDetails"
              example:
                type: https://learn.advantech.com/WEDA/api/errorcode#InvalidSortDirectionError
                title: Forbidden
                status: 403
                detail: "Invalid sort direction: 'besc'. Use 'asc' or 'desc'"
                instance: /api/v1/orgs/{orgId}/stacks/{stackRevisionId}/deployments
        "500":
          description: Internal Server Error
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ProblemDetails"
              example:
                type: https://learn.advantech.com/WEDA/api/errorcode#InternalServerError
                title: Internal Server Error
                status: 500
                detail: An internal error occurred during your request!
      security:
        - Bearer: []
  /api/v1/devices/{deviceId}/stacks/deployments:
    delete:
      tags:
        - ___swagger_3-container-management_swagger_json_Container Deployments
      summary: Clear Device Containers
      description: >-
        
        Overview: This operation completely removes all deployed stacks from a
        device, effectively returning it to a clean, initial state with no
        deployed containers.


        • Complete Removal: All stacks are removed from the device in one
        operation.


        • Clean Slate: The device reverts to its initial state, having no
        deployed stacks.


        • Process: The system sends an **empty stacks configuration** array to
        the device via NATS, immediately notifying the device to stop all
        containers.


        • Database Cleanup: All corresponding deployment records for the device
        are removed from the database.


        • Irreversible: Due to the nature of the reset, all stacks must be
        **redeployed individually** after this operation is complete.
      parameters:
        - name: deviceId
          in: path
          description: ID of the device to reset.
          required: true
          schema:
            type: string
      responses:
        "204":
          description: No Content
        "404":
          description: Not Found
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ProblemDetails"
              example:
                type: https://learn.advantech.com/WEDA/api/errorcode#ResourceNotFound
                title: Resource Not Found
                status: 404
                detail: "Device Not Found.DeviceId: 123123123"
                instance: /api/v1/orgs/{orgId}/devices/{deviceId}/reset
        "500":
          description: Internal Server Error
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ProblemDetails"
              example:
                type: https://learn.advantech.com/WEDA/api/errorcode#InternalServerError
                title: Internal Server Error
                status: 500
                detail: An internal error occurred during your request!
      security:
        - Bearer: []
  /api/v1/orgs/{orgId}/containers/registries:
    post:
      tags:
        - ___swagger_3-container-management_swagger_json_Container Registries
      summary: Create Registry Config
      description: >-
        <b>Overview:</b> Creates a new registry configuration with automatic
        encryption for sensitive credentials.
                    

        <b>Registry Type Requirements:</b>


        <b>• DockerHub:</b> Requires <b>username</b> and <b>accessToken</b>
        (must be provided together).
                    

        <b>• AzureACR:</b> Requires <b>username</b> and <b>userPassword</b>
        (must be provided together).
                    

        <b>• AwsECR:</b><b>region</b> is required. <b>accessKey</b> and
        <b>accessSecretKey</b> are optional, but if provided, they must be used
        together. 
                    

        <b>• Custom (e.g., Harbor):</b> All credentials are optional. If
        authentication is used, <b>username</b> and <b>userPassword</b> must be
        provided together.
                    

        <b>Please refer to the Example Value section below to view the complete
        request examples for each Registry type.</b>
      parameters:
        - name: orgId
          in: path
          description: Identity for user's organization.
          required: true
          schema:
            type: string
            format: uuid
      requestBody:
        description: Registry creation data/configuration.
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/CreateRegistryDto"
            examples:
              1. DockerHub:
                value:
                  registryName: my-dockerhub
                  registryUrl: https://hub.docker.com
                  registryCredentials:
                    registryType: DockerHub
                    username: dockeruser123
                    accessToken: dckr_pat_example123456789
              2. AWS ECR:
                value:
                  registryName: my-aws-ecr
                  registryUrl: https://123456789012.dkr.ecr.ap-southeast-1.amazonaws.com
                  registryCredentials:
                    registryType: AwsECR
                    accessKey: AKIA2V7EXAMPLE123456
                    accessSecretKey: 8xJalrXUtnFEMI/K7MDENG/bPxRfiCYzEXAMPLE7
                    region: ap-southeast-1
              3. Azure ACR:
                value:
                  registryName: my-azure-acr
                  registryUrl: https://myregistry.azurecr.io
                  registryCredentials:
                    registryType: AzureACR
                    username: myregistry
                    userPassword: Azure_ACR_Password_Example123
              4. Custom:
                value:
                  registryName: my-harbor
                  registryUrl: https://harbor.company.com
                  registryCredentials:
                    registryType: Custom
                    username: harbor_admin
                    userPassword: Harbor_Password_123
      responses:
        "200":
          description: OK
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/RegistryDto"
              example:
                registryId: fb9822d7-441a-469d-84ed-0c93225fa3fc
                registryName: harbor-ecr-sync
                registryUrl: https://registry.dev.company.com
                creationTime: 2026-06-16T09:23:31.006469Z
                registryEncryptedCredentials:
                  registryType: AwsECR
                  encryptedAccessKey: AKIA2V7EXAMPLE123456
                  encryptedAccessSecretKey: 8xJalrXUtnFEMI/K7MDENG/bPxRfiCYzEXAMPLE7
                  region: ap-southeast-1
                orgId: dd37e178-750b-4d13-a122-63567988652a
        "400":
          description: Bad Request
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ProblemDetails"
              example:
                type: https://learn.advantech.com/WEDA/api/errorcode#ValidationError
                title: Bad Request - Invalid request parameters
                status: 400
                detail: The RegistryName field is required.
                instance: /api/v1/orgs/{orgId}/registries
        "500":
          description: Internal Server Error
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ProblemDetails"
              example:
                type: https://learn.advantech.com/WEDA/api/errorcode#InternalServerError
                title: Internal Server Error
                status: 500
                detail: An internal error occurred during your request!
      security:
        - Bearer: []
    get:
      tags:
        - ___swagger_3-container-management_swagger_json_Container Registries
      summary: List Registry Configs by Organization
      description: >-
        
        Overview: Retrieves a paginated list of all configured registries.


        • MaxResultCount: Maximum 1000 records per page


        • Sorting support: Supports sorting by CreationTime and RegistryName,
        with descending order by CreationTime as the default.
      parameters:
        - name: orgId
          in: path
          description: Identity for user's organization.
          required: true
          schema:
            type: string
            format: uuid
        - name: maxResultCount
          in: query
          description: Maximum number of results to return. Must be between 1 and 1000.
          schema:
            maximum: 1000
            minimum: 1
            type: integer
            format: int32
        - name: skipCount
          in: query
          description: Number of results to skip for pagination.
          schema:
            type: integer
            format: int32
        - name: sorting
          in: query
          description: >-
            Sorting expression for the results.

            The allowed values are "CreationTime desc", "CreationTime
            asc", "RegistryName desc", "RegistryName asc".
          schema:
            type: string
            default: creationTime desc
      responses:
        "200":
          description: OK
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/PagedResultDto  of  RegistryDto"
              example:
                totalCount: 2
                items:
                  - registryId: 1e627a9f-0374-4c87-a2a9-ba7cfd1a6db3
                    registryName: harbor-ecr-sync
                    registryUrl: https://registry.dev.company.com
                    creationTime: 2026-06-16T09:23:31.0190207Z
                    registryEncryptedCredentials:
                      registryType: AwsECR
                      encryptedAccessKey: AKIA2V7EXAMPLE123456
                      encryptedAccessSecretKey: 8xJalrXUtnFEMI/K7MDENG/bPxRfiCYzEXAMPLE7
                      region: ap-southeast-1
                    orgId: c46a1330-7a26-4e17-ba55-fdbadf9e66ea
                  - registryId: 32758f83-97b0-4022-b7dc-4a7a5f6c52ae
                    registryName: harbor-ecr-sync
                    registryUrl: https://registry.dev.company.com
                    creationTime: 2026-06-16T09:23:31.0190349Z
                    registryEncryptedCredentials:
                      registryType: AwsECR
                      encryptedAccessKey: AKIA2V7EXAMPLE123456
                      encryptedAccessSecretKey: 8xJalrXUtnFEMI/K7MDENG/bPxRfiCYzEXAMPLE7
                      region: ap-southeast-1
                    orgId: 9b181282-5b68-44c9-9595-9b0ddbff143e
        "403":
          description: Forbidden
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ProblemDetails"
              example:
                type: https://learn.advantech.com/WEDA/api/errorcode#InvalidSortDirectionError
                title: Forbidden
                status: 403
                detail: "Invalid sort direction: 'a'. Use 'asc' or 'desc'"
                instance: /api/v1/orgs/{orgId}/registries
        "500":
          description: Internal Server Error
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ProblemDetails"
              example:
                type: https://learn.advantech.com/WEDA/api/errorcode#InternalServerError
                title: Internal Server Error
                status: 500
                detail: An internal error occurred during your request!
      security:
        - Bearer: []
  /api/v1/orgs/{orgId}/containers/registries/{registryId}:
    put:
      tags:
        - ___swagger_3-container-management_swagger_json_Container Registries
      summary: Update registry config
      description: >-
        
        Overview: Updates an existing registry configuration, applying
        validation and re-encryption to sensitive data.


        • Uniqueness Check: Throws an exception if the updated registry name
        already exists in the current deployment (excluding the registry
        currently being modified).


        • Type Validation and Requirements: Validates the specified registry
        type and requires both an access key and secret key for authentication.


        • Supported Types: The registry type must be one of **Custom**,
        **DockerHub**, **AzureACR**, or **AwsECR**.


        • Encryption: Sensitive data (such as password, access key, and secret
        key) is automatically encrypted upon update.


        • Region: The configuration allows for specifying the geographical
        region for the registry.
      parameters:
        - name: orgId
          in: path
          description: Identity for user's organization.
          required: true
          schema:
            type: string
            format: uuid
        - name: registryId
          in: path
          description: The unique ID of the registry to update.
          required: true
          schema:
            type: string
            format: uuid
      requestBody:
        description: Registry update data/configuration.
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/UpdateRegistryDto"
            example:
              registryName: harbor-ecr-sync
              registryUrl: https://registry.dev.company.com
              registryCredentials:
                registryType: AwsECR
                accessKey: AKIA2V7EXAMPLE123456
                accessSecretKey: 8xJalrXUtnFEMI/K7MDENG/bPxRfiCYzEXAMPLE7
                region: ap-southeast-1
      responses:
        "200":
          description: OK
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/RegistryDto"
              example:
                registryId: 762d04fa-97e0-4035-8bb9-6d49d86bd4f3
                registryName: harbor-ecr-sync
                registryUrl: https://registry.dev.company.com
                creationTime: 2026-06-16T09:23:31.0410192Z
                registryEncryptedCredentials:
                  registryType: AwsECR
                  encryptedAccessKey: AKIA2V7EXAMPLE123456
                  encryptedAccessSecretKey: 8xJalrXUtnFEMI/K7MDENG/bPxRfiCYzEXAMPLE7
                  region: ap-southeast-1
                orgId: fd9af585-92f0-42bc-88e0-9033c3da2da4
        "400":
          description: Bad Request
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ProblemDetails"
              example:
                type: https://learn.advantech.com/WEDA/api/errorcode#ValidationError
                title: Bad Request - Invalid request parameters
                status: 400
                detail: The RegistryUserPassword field is required.
                instance: /api/v1/orgs/{orgId}/registries/{registryId}
        "403":
          description: Forbidden
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ProblemDetails"
              example:
                type: https://learn.advantech.com/WEDA/api/errorcode#ContainerMgmt:Registry:DuplicateName
                title: Forbidden
                status: 403
                detail: Registry with name 'harbor-ecr-sync' already exists in the deployment.
                  Cannot rename registry to 'harbor-ecr-sync' because another
                  registry with this name already exists. Please choose a
                  different name.
                instance: /api/v1/orgs/{orgId}/registries/{registryId}
        "500":
          description: Internal Server Error
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ProblemDetails"
              example:
                type: https://learn.advantech.com/WEDA/api/errorcode#InternalServerError
                title: Internal Server Error
                status: 500
                detail: An internal error occurred during your request!
      security:
        - Bearer: []
    delete:
      tags:
        - ___swagger_3-container-management_swagger_json_Container Registries
      summary: Delete docker registry config
      parameters:
        - name: orgId
          in: path
          description: Identity for user's organization.
          required: true
          schema:
            type: string
            format: uuid
        - name: registryId
          in: path
          description: The unique ID of the registry to delete.
          required: true
          schema:
            type: string
            format: uuid
      responses:
        "204":
          description: No Content
        "404":
          description: Not Found
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ProblemDetails"
              example:
                type: https://learn.advantech.com/WEDA/api/errorcode#ResourceNotFound
                title: Resource Not Found
                status: 404
                detail: "Resource Not Found. input: b34deae8-08a5-4357-b0b4-172303c3fe51"
                instance: /api/v1/orgs/{orgId}/registries/{registryId}
        "500":
          description: Internal Server Error
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ProblemDetails"
              example:
                type: https://learn.advantech.com/WEDA/api/errorcode#InternalServerError
                title: Internal Server Error
                status: 500
                detail: An internal error occurred during your request!
      security:
        - Bearer: []
    get:
      tags:
        - ___swagger_3-container-management_swagger_json_Container Registries
      summary: Get registry config
      description: >-
        
        Overview: Retrieves a specific registry configuration by its ID.


        • Exact match: Returns the registry with the exact ID


        • Sensitive data: Password and keys are encrypted and not included in
        the response
      parameters:
        - name: orgId
          in: path
          description: Identity for user's organization.
          required: true
          schema:
            type: string
            format: uuid
        - name: registryId
          in: path
          description: The unique ID of the registry to retrieve (may be referred to as
            registryId).
          required: true
          schema:
            type: string
            format: uuid
      responses:
        "200":
          description: OK
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/RegistryDto"
              example:
                registryId: dc45f625-69d0-460b-a1a3-a6590195e717
                registryName: harbor-ecr-sync
                registryUrl: https://registry.dev.company.com
                creationTime: 2026-06-16T09:23:31.1109524Z
                registryEncryptedCredentials:
                  registryType: AwsECR
                  encryptedAccessKey: AKIA2V7EXAMPLE123456
                  encryptedAccessSecretKey: 8xJalrXUtnFEMI/K7MDENG/bPxRfiCYzEXAMPLE7
                  region: ap-southeast-1
                orgId: 25eecce6-7817-47be-8504-fa72c2e46d13
        "404":
          description: Not Found
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ProblemDetails"
              example:
                type: https://learn.advantech.com/WEDA/api/errorcode#ResourceNotFound
                title: Resource Not Found
                status: 404
                detail: "Resource Not Found. input: b34deae8-08a5-4357-b0b4-172303c3fe51"
                instance: /api/v1/orgs/{orgId}/registries/{registryId}
        "500":
          description: Internal Server Error
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ProblemDetails"
              example:
                type: https://learn.advantech.com/WEDA/api/errorcode#InternalServerError
                title: Internal Server Error
                status: 500
                detail: An internal error occurred during your request!
      security:
        - Bearer: []
  /api/v1/orgs/{orgId}/stack-configs:
    post:
      tags:
        - ___swagger_3-container-management_swagger_json_Container Stacks
      summary: Create container stack
      description: >-
        
        Overview: Creates a new container stack configuration with automatic
        version assignment.


        • Stack name must be unique and cannot duplicate the name of any
        existing stack config.


        • ComposeFileContent: Must be valid Base64 encoded Docker Compose
        content


        • Environment: Optional key-value pairs that can be referenced in Docker
        Compose files using `${VARIABLE_NAME}` syntax. Pass `null` or omit to
        skip.


        • Stack Naming Rules: Must follow Docker container naming rules:


        1. Stack name may contain lowercase letters, digits and hyphen (-)


        2. Stack name may not start or end with a hyphen (-)


        3. Stack name cannot contain consecutive hyphens (-)


        4. Maximum length of 63 characters


        Request body example:

        ```

        {
          "stackName": "my-nginx",
          "type": "compose",
          "composeFileContent": "dmVyc2lvbjogIjMuOCIKc2VydmljZXM6...",
          "environment": {
            "NGINX_PORT": "8080",
            "APP_ENV": "production",
            "REPLICAS": "3"
          },
          "description": "Production nginx stack"
        }
                    
        ```
      parameters:
        - name: orgId
          in: path
          description: Identity for user's organization.
          required: true
          schema:
            type: string
            format: uuid
      requestBody:
        description: Container stack creation data
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/CreateContainerStackDto"
            example:
              stackName: no-duplicate-stack-name
              type: compose
              composeFileContent: dmVyc2lvbjogIjMuOCIKc2VydmljZXM6CiAgbmdpbng6CiAgICBpbWFnZTogbmdpbng6bGF0ZXN0CiAgICBwb3J0czoKICAgICAgLSAiODA6ODAiCiAgICB2b2x1bWVzOgogICAgICAtIC4vaHR0bWw6L3Vzci9zaGFyZS9uZ2lueC9odG1s
              environment: {}
              description: this is description
      responses:
        "201":
          description: Created
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ContainerStackDto"
              example:
                stackConfigId: fada0a4c-36e0-4d2c-adb1-94b844b74d0e
                stackRevisionId: d875d31e-889d-4fc0-a4da-ce9ad3249031
                stackName: no-duplicate-stack-name
                type: compose
                composeFileContent: dmVyc2lvbjogIjMuOCIKc2VydmljZXM6CiAgbmdpbng6CiAgICBpbWFnZTogbmdpbng6bGF0ZXN0CiAgICBwb3J0czoKICAgICAgLSAiODA6ODAiCiAgICB2b2x1bWVzOgogICAgICAtIC4vaHRtbDovdXNyL3NoYXJlL25naW54L2h0bWw
                environment: {}
                description: this is description
                creationTime: 2026-06-16T09:23:31.1246975Z
                orgId: 1fa415b7-b9dd-416d-9aad-3f0d7ce924f0
                version: 0
        "403":
          description: Forbidden
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ProblemDetails"
              example:
                type: https://learn.advantech.com/WEDA/api/errorcode#InvalidYamlContent
                title: Forbidden
                status: 403
                detail: composeFileContent must contain valid base64 encoded YAML content
                instance: /api/v1/orgs/{orgId}/stacks
        "500":
          description: Internal Server Error
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ProblemDetails"
              example:
                type: https://learn.advantech.com/WEDA/api/errorcode#InternalServerError
                title: Internal Server Error
                status: 500
                detail: An internal error occurred during your request!
      security:
        - Bearer: []
    get:
      tags:
        - ___swagger_3-container-management_swagger_json_Container Stacks
      summary: List Stack Configs by Organization
      description: >-
        
        Overview: Retrieves a paginated list of container stack configurations
        with optional filtering and sorting.


        • Flexible filtering: Supports filtering by stackName, version, and type


        • Stack name filtering: When stackName is provided, filters stacks by
        exact name match


        • Version filtering: When both stackName and version are provided,
        returns specific version


        • Type filtering: When type is provided, filters stacks by exact type
        match


        • Combined filtering: All filters can be combined for precise queries


        • Results ordering: Results are returned in descending order by creation
        time by default


        • MaxResultCount: Maximum 1000 records per page


        • Sorting support: Supports sorting by creationTime and stackName, with
        descending order by CreationTime as the default.
      parameters:
        - name: orgId
          in: path
          description: Identity for user's organization.
          required: true
          schema:
            type: string
            format: uuid
        - name: stackName
          in: query
          description: Optional stack name filter
          schema:
            type: string
        - name: type
          in: query
          description: |-
            Optional type filter
            value : compose
          schema:
            type: string
            format: Enumeration
            default: compose
        - name: maxResultCount
          in: query
          description: Maximum number of results to return. Must be between 1 and 1000.
          schema:
            maximum: 1000
            minimum: 1
            type: integer
            format: int32
        - name: skipCount
          in: query
          description: Number of results to skip for pagination.
          schema:
            type: integer
            format: int32
        - name: sorting
          in: query
          description: |-
            Sorting expression for the results
            Default is "CreationTime desc".
          schema:
            type: string
            default: creationTime desc
      responses:
        "200":
          description: OK
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/PagedResultDto  of  ContainerStackDto"
              example:
                totalCount: 1
                items:
                  - stackConfigId: 245ee2f2-8c48-42dd-b471-99e60510995e
                    stackRevisionId: c38e45fc-86c2-4aba-8d3b-53b68d578269
                    stackName: no-duplicate-stack-name
                    type: compose
                    composeFileContent: dmVyc2lvbjogIjMuOCIKc2VydmljZXM6CiAgbmdpbng6CiAgICBpbWFnZTogbmdpbng6bGF0ZXN0CiAgICBwb3J0czoKICAgICAgLSAiODA6ODAiCiAgICB2b2x1bWVzOgogICAgICAtIC4vaHRtbDovdXNyL3NoYXJlL25naW54L2h0bWw
                    environment: {}
                    description: this is description
                    creationTime: 2026-06-16T09:23:31.13435Z
                    orgId: 41c095a1-9c3b-4e1b-a998-64184acf1ec4
                    version: 0
        "500":
          description: Internal Server Error
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ProblemDetails"
              example:
                type: https://learn.advantech.com/WEDA/api/errorcode#InternalServerError
                title: Internal Server Error
                status: 500
                detail: An internal error occurred during your request!
      security:
        - Bearer: []
  /api/v1/orgs/{orgId}/stack-configs/{stackConfigId}/revisions/{stackRevisionId}:
    get:
      tags:
        - ___swagger_3-container-management_swagger_json_Container Stacks
      summary: Get stack revision configuration
      description: >-
        
        Overview: Retrieves a specific container stack configuration revision by
        its `stackRevisionId`.


        • Exact match: Filters by `orgId`, `stackConfigId`, and
        `stackRevisionId` to locate the exact revision


        • Returns 404 if no revision matches all three identifiers
      parameters:
        - name: orgId
          in: path
          description: Identity for user's organization.
          required: true
          schema:
            type: string
            format: uuid
        - name: stackConfigId
          in: path
          description: An unique ID for the stack configuration.
          required: true
          schema:
            type: string
            format: uuid
        - name: stackRevisionId
          in: path
          description: Revision ID for the specified version of stack configuration.
          required: true
          schema:
            type: string
            format: uuid
      responses:
        "200":
          description: OK
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ContainerStackDto"
              example:
                stackConfigId: 8c95394a-f80f-4058-96a1-9b22f2d31fff
                stackRevisionId: 282cc998-a15c-4bb7-ba17-26e5bcd679fd
                stackName: no-duplicate-stack-name
                type: compose
                composeFileContent: dmVyc2lvbjogIjMuOCIKc2VydmljZXM6CiAgbmdpbng6CiAgICBpbWFnZTogbmdpbng6bGF0ZXN0CiAgICBwb3J0czoKICAgICAgLSAiODA6ODAiCiAgICB2b2x1bWVzOgogICAgICAtIC4vaHRtbDovdXNyL3NoYXJlL25naW54L2h0bWw
                environment: {}
                description: this is description
                creationTime: 2026-06-16T09:23:31.1430589Z
                orgId: 81d5f4e1-6562-4172-a7eb-2d680a3bb072
                version: 0
        "500":
          description: Internal Server Error
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ProblemDetails"
              example:
                type: https://learn.advantech.com/WEDA/api/errorcode#InternalServerError
                title: Internal Server Error
                status: 500
                detail: An internal error occurred during your request!
      security:
        - Bearer: []
    delete:
      tags:
        - ___swagger_3-container-management_swagger_json_Container Stacks
      summary: Delete stack revision
      description: >-
        
        Overview: Deletes a specific container stack configuration revision if
        it has no active deployments.


        • Deployment check: Cannot delete stack configuration that have any
        associated deployments


        • Safety first: Must undeploy all revisions before deletion is allowed


        • Referential integrity: Prevents orphaned deployment records


        • Business exception: Throws BusinessException with stack revision ID if
        deployments exist
      parameters:
        - name: orgId
          in: path
          description: Identity of the organization that owns the stack revision to be
            deleted.
          required: true
          schema:
            type: string
            format: uuid
        - name: stackConfigId
          in: path
          description: Unique identifier of the stack configuration to be deleted.
          required: true
          schema:
            type: string
            format: uuid
        - name: stackRevisionId
          in: path
          description: Unique identifier of the stack revision to be deleted.
          required: true
          schema:
            type: string
            format: uuid
      responses:
        "204":
          description: No Content
        "403":
          description: Forbidden
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ProblemDetails"
              example:
                type: https://learn.advantech.com/WEDA/api/errorcode#DeleteFail
                title: Forbidden
                status: 403
                detail: Cannot delete stack with ID 3fa85f64-5717-4562-b3fc-2c963f66afa6 because
                  it has associated deployments.
                instance: /api/v1/orgs/{orgId}/stacks/{stackConfigId}/revisions/{stackRevisionId}
        "404":
          description: Not Found
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ProblemDetails"
              example:
                type: https://learn.advantech.com/WEDA/api/errorcode#ResourceNotFound
                title: Resource Not Found
                status: 404
                detail: "Resource Not Found. input: 3fa85f64-5717-4562-b3fc-2c963f66afa6"
                instance: /api/v1/orgs/{orgId}/stacks/{stackConfigId}/revisions/{stackRevisionId}
        "500":
          description: Internal Server Error
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ProblemDetails"
              example:
                type: https://learn.advantech.com/WEDA/api/errorcode#InternalServerError
                title: Internal Server Error
                status: 500
                detail: An internal error occurred during your request!
      security:
        - Bearer: []
  /api/v1/orgs/{orgId}/stack-configs/revisions/diff:
    get:
      tags:
        - ___swagger_3-container-management_swagger_json_Container Stacks
      summary: Compare Stack Revisions
      description: >-
        
        Overview: Compare two container stack configurations revisions and
        return their differences.


        • Git-like Diff: The output provides a detailed comparison similar to a
        standard git diff tool.


        • Field-level Analysis: Compares all stack properties, including
        metadata.


        • Environment Variables: Includes a detailed comparison of environment
        configurations.


        • Compose Content Deep Dive: Compares the decoded Docker Compose file
        content (Base64 decoded).
      parameters:
        - name: orgId
          in: path
          description: Identity of the organization that owns the stack revision to be
            compared.
          required: true
          schema:
            type: string
            format: uuid
        - name: sourceStackRevisionId
          in: query
          description: Unique identifier of the stack revision to compare from
          required: true
          schema:
            type: string
            format: uuid
        - name: targetStackRevisionId
          in: query
          description: Unique identifier of the stack revision to compare to
          required: true
          schema:
            type: string
            format: uuid
      responses:
        "200":
          description: OK
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ContainerStackDto"
              example:
                sourceStack:
                  stackConfigId: 684b3a8f-af2c-4b66-ad5f-8f96d87e489c
                  stackRevisionId: 5ba2dc3b-3464-44de-a6b0-43e1ab6cfcee
                  stackName: no-duplicate-stack-name
                  type: compose
                  composeFileContent: dmVyc2lvbjogIjMuOCIKc2VydmljZXM6CiAgbmdpbng6CiAgICBpbWFnZTogbmdpbng6bGF0ZXN0CiAgICBwb3J0czoKICAgICAgLSAiODA6ODAiCiAgICB2b2x1bWVzOgogICAgICAtIC4vaHRtbDovdXNyL3NoYXJlL25naW54L2h0bWw
                  environment: {}
                  description: this is description
                  creationTime: 2026-06-16T09:23:31.2188308Z
                  orgId: aef0ae5b-d63c-46dc-a403-e7c39a3992b0
                  version: 0
                targetStack:
                  stackConfigId: fc4bbf67-efbb-4767-bbec-db00ae1f4752
                  stackRevisionId: c07f028b-c760-42e5-b164-f085c35f9ed5
                  stackName: no-duplicate-stack-name
                  type: compose
                  composeFileContent: dmVyc2lvbjogIjMuOCIKc2VydmljZXM6CiAgbmdpbng6CiAgICBpbWFnZTogbmdpbng6bGF0ZXN0CiAgICBwb3J0czoKICAgICAgLSAiODA6ODAiCiAgICB2b2x1bWVzOgogICAgICAtIC4vaHRtbDovdXNyL3NoYXJlL25naW54L2h0bWw
                  environment: {}
                  description: this is description 2
                  creationTime: 2026-06-16T09:23:31.218844Z
                  orgId: d9c8371b-ad9a-4605-98a0-b8f427c34413
                  version: 0
                fieldDifferences:
                  - fieldName: Description
                    sourceValue: this is description
                    targetValue: this is description 2
                    changeType: modified
                environmentDiff:
                  addedVariables: {}
                  removedVariables: {}
                  changedVariables: {}
                yamlDiff:
                  addedFields: []
                  removedFields: []
                  modifiedFields: []
                  errors: []
                  hasChanges: false
                  summary: No changes in YAML content
                areIdentical: false
                summary: 2 field(s) modified
        "500":
          description: Internal Server Error
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ProblemDetails"
              example:
                type: https://learn.advantech.com/WEDA/api/errorcode#InternalServerError
                title: Internal Server Error
                status: 500
                detail: An internal error occurred during your request!
      security:
        - Bearer: []
  /api/v1/orgs/{orgId}/stack-configs/{stackConfigId}:
    get:
      tags:
        - ___swagger_3-container-management_swagger_json_Container Stacks
      summary: Get latest container stack configuration
      description: >-
        
        Overview: Retrieves the latest revision of a specific container stack
        configuration.


        • Exact match: Returns the stack configuration with the exact
        StackConfigId


        • Latest revision: Returns the latest revision of the stack
        configuration
      parameters:
        - name: orgId
          in: path
          description: Identity for user's organization.
          required: true
          schema:
            type: string
            format: uuid
        - name: stackConfigId
          in: path
          description: StackConfigId of the stack to retrieve
          required: true
          schema:
            type: string
            format: uuid
      responses:
        "200":
          description: OK
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ContainerStackDto"
              example:
                stackConfigId: eb944ef5-0da7-430c-899a-89e58fb9397c
                stackRevisionId: aec464b4-722b-4587-88ee-55a2f041b619
                stackName: no-duplicate-stack-name
                type: compose
                composeFileContent: dmVyc2lvbjogIjMuOCIKc2VydmljZXM6CiAgbmdpbng6CiAgICBpbWFnZTogbmdpbng6bGF0ZXN0CiAgICBwb3J0czoKICAgICAgLSAiODA6ODAiCiAgICB2b2x1bWVzOgogICAgICAtIC4vaHRtbDovdXNyL3NoYXJlL25naW54L2h0bWw
                environment: {}
                description: this is description
                creationTime: 2026-06-16T09:23:31.2261362Z
                orgId: f1c47239-1396-4875-829a-1b6d7db3c0b1
                version: 0
        "500":
          description: Internal Server Error
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ProblemDetails"
              example:
                type: https://learn.advantech.com/WEDA/api/errorcode#InternalServerError
                title: Internal Server Error
                status: 500
                detail: An internal error occurred during your request!
      security:
        - Bearer: []
    delete:
      tags:
        - ___swagger_3-container-management_swagger_json_Container Stacks
      summary: Delete stack
      description: >-
        
        Overview: Deletes a container stack configuration and all its revisions
        if they have no active deployments.


        • Deployment check: Cannot delete stack configuration that have any
        associated deployments
      parameters:
        - name: orgId
          in: path
          description: Identity for user's organization.
          required: true
          schema:
            type: string
            format: uuid
        - name: stackConfigId
          in: path
          description: An unique ID for the stack configuration.
          required: true
          schema:
            type: string
            format: uuid
      responses:
        "204":
          description: No Content
        "403":
          description: Forbidden
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ProblemDetails"
              example:
                type: https://learn.advantech.com/WEDA/api/errorcode#DeleteFail
                title: Forbidden
                status: 403
                detail: Cannot delete stack with ID 3fa85f64-5717-4562-b3fc-2c963f66afa6 because
                  it has associated deployments.
                instance: /api/v1/orgs/{orgId}/stacks/{stackConfigId}
        "404":
          description: Not Found
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ProblemDetails"
              example:
                type: https://learn.advantech.com/WEDA/api/errorcode#ResourceNotFound
                title: Resource Not Found
                status: 404
                detail: "Resource Not Found. input: 3fa85f64-5717-4562-b3fc-2c963f66afa6"
                instance: /api/v1/orgs/{orgId}/stacks/{stackConfigId}
        "500":
          description: Internal Server Error
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ProblemDetails"
              example:
                type: https://learn.advantech.com/WEDA/api/errorcode#InternalServerError
                title: Internal Server Error
                status: 500
                detail: An internal error occurred during your request!
      security:
        - Bearer: []
    patch:
      tags:
        - ___swagger_3-container-management_swagger_json_Container Stacks
      summary: Update Stack Revision
      description: >-
        
        Overview: Updates an existing container stack configuration by creating
        a new revision.


        • Active deployments: Existing deployments will NOT be affected by the
        update.


        • Partial update: Only fields with non-null values will be updated.
        Fields that are not included or explicitly set to null will be ignored.
      parameters:
        - name: orgId
          in: path
          description: Identity for user's organization.
          required: true
          schema:
            type: string
            format: uuid
        - name: stackConfigId
          in: path
          description: An unique ID for the stack configuration.
          required: true
          schema:
            type: string
            format: uuid
      requestBody:
        description: Updated container stack configuration data
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/UpdateStackDto"
            example:
              composeFileContent: dmVyc2lvbjogIjMuOCIKc2VydmljZXM6CiAgbmdpbng6CiAgICBpbWFnZTogbmdpbng6bGF0ZXN0CiAgICBwb3J0czoKICAgICAgLSAiODA6ODAiCiAgICB2b2x1bWVzOgogICAgICAtIC4vaHRtbDovdXNyL3NoYXJlL25naW54L2h0bWw
              environment: {}
              description: this is description
      responses:
        "200":
          description: OK
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ContainerStackDto"
              example:
                stackConfigId: 1e2ab7b2-4625-4556-92db-6f92f2ebde61
                stackRevisionId: 7199a9ae-7543-41d9-bd9d-d799f7deadb0
                stackName: no-duplicate-stack-name
                type: compose
                composeFileContent: dmVyc2lvbjogIjMuOCIKc2VydmljZXM6CiAgbmdpbng6CiAgICBpbWFnZTogbmdpbng6bGF0ZXN0CiAgICBwb3J0czoKICAgICAgLSAiODA6ODAiCiAgICB2b2x1bWVzOgogICAgICAtIC4vaHRtbDovdXNyL3NoYXJlL25naW54L2h0bWw
                environment: {}
                description: this is description
                creationTime: 2026-06-16T09:23:31.2496993Z
                orgId: aa1360bf-99dc-4915-b58a-e90d29911bfb
                version: 0
        "403":
          description: Forbidden
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ProblemDetails"
              example:
                code: InvalidYamlContent
                message: composeFileContent must contain valid base64 encoded YAML content
                details: null
                data: null
                validationErrors: null
        "500":
          description: Internal Server Error
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ProblemDetails"
              example:
                type: https://learn.advantech.com/WEDA/api/errorcode#InternalServerError
                title: Internal Server Error
                status: 500
                detail: An internal error occurred during your request!
      security:
        - Bearer: []
  /api/v1/orgs/{orgId}/stack-configs/{stackConfigId}/revisions:
    get:
      tags:
        - ___swagger_3-container-management_swagger_json_Container Stacks
      summary: List stack revisions
      description: >-
        
        Overview: Retrieves all revisions of a specific container stack
        configuration.


        • Exact match: Returns the stack configuration with the exact stack
        config ID
      parameters:
        - name: stackConfigId
          in: path
          description: An unique ID for the stack configuration.
          required: true
          schema:
            type: string
            format: uuid
        - name: maxResultCount
          in: query
          description: Maximum number of results to return. Must be between 1 and 1000.
          schema:
            maximum: 1000
            minimum: 1
            type: integer
            format: int32
        - name: skipCount
          in: query
          description: Number of results to skip for pagination.
          schema:
            type: integer
            format: int32
        - name: sorting
          in: query
          description: |-
            Sorting expression for the results.
            The allowed values are "CreationTime desc" and "CreationTime asc".
          schema:
            type: string
            default: CreationTime desc
        - name: orgId
          in: path
          description: Identity of the organization that owns the stack configuration.
          required: true
          schema:
            type: string
            format: uuid
      responses:
        "200":
          description: OK
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ContainerStackDto"
              example:
                totalCount: 1
                items:
                  - stackConfigId: a3e44d18-c9a5-4a3f-89f3-44459bc6c508
                    stackRevisionId: 38b213ff-2ff9-46c9-b28c-c918b29d24f5
                    stackName: no-duplicate-stack-name
                    type: compose
                    composeFileContent: dmVyc2lvbjogIjMuOCIKc2VydmljZXM6CiAgbmdpbng6CiAgICBpbWFnZTogbmdpbng6bGF0ZXN0CiAgICBwb3J0czoKICAgICAgLSAiODA6ODAiCiAgICB2b2x1bWVzOgogICAgICAtIC4vaHRtbDovdXNyL3NoYXJlL25naW54L2h0bWw
                    environment: {}
                    description: this is description
                    creationTime: 2026-06-16T09:23:31.3174902Z
                    orgId: 11b2671d-d47b-4a5d-a6c3-3f0d1f337f5e
                    version: 0
        "400":
          description: Bad Request
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ProblemDetails"
              example:
                type: https://learn.advantech.com/WEDA/api/errorcode#InternalServerError
                title: Internal Server Error
                status: 500
                detail: An internal error occurred during your request!
        "404":
          description: Not Found
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ProblemDetails"
              example:
                type: https://learn.advantech.com/WEDA/api/errorcode#InternalServerError
                title: Internal Server Error
                status: 500
                detail: An internal error occurred during your request!
        "500":
          description: Internal Server Error
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ProblemDetails"
              example:
                type: https://learn.advantech.com/WEDA/api/errorcode#InternalServerError
                title: Internal Server Error
                status: 500
                detail: An internal error occurred during your request!
      security:
        - Bearer: []
  /api/v1/orgs/{orgId}/ai-models/{modelId}/editions/{edition}:deploy:
    post:
      tags:
        - ___swagger_4-ai-model-management_swagger_json_Model Deployments
      summary: Create Deployment
      description: >-
        
        Deploys a specific model edition to one or more edge devices.


        • Each target group can specify ACL rules and pre/post lifecycle
        commands.


        • PreCmd.action meanings: NOOP (skip), CHECK_DISK_USAGE (validate
        capacity).


        • ValidateCmd.action meanings: NOOP (skip), CHECKSUM_VERIFY (hash
        check).


        • ApplyCmd.action meanings: NOOP (skip),
        ATOMIC_SWAP_AND_RESTART_CONTAINER (replace then restart runtime).


        • PostCmd.action meanings: NOOP (skip).


        • The model file is delivered via Secured Volume and NATS file delivery.


        • Returns 202 with per-device deployment IDs and initial state "SENT".


        • Returns 409 if the same fileId is already deployed to any target
        device.
      parameters:
        - name: orgId
          in: path
          description: Organization identifier (GUID or string alias).
          required: true
          schema:
            type: string
        - name: modelId
          in: path
          description: Identifier of the AI model to deploy.
          required: true
          schema:
            type: string
        - name: edition
          in: path
          description: Model edition string (e.g. "2-1-0").
          required: true
          schema:
            type: string
      requestBody:
        description: Deployment targets and optional lifecycle commands.
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/CreateModelDeploymentInput"
            example:
              targets:
                - deviceIdList:
                    - 74fe488d5d54
                  tasks:
                    - acl:
                        allowedSubnets:
                          - 0.0.0.0/0
                        allowedContainers: []
                      preCmd:
                        action: CHECK_DISK_USAGE
                        params:
                          maxUsagePercent: "95"
                      validateCmd:
                        action: CHECKSUM_VERIFY
                        params: {}
                      applyCmd:
                        action: ATOMIC_SWAP_AND_RESTART_CONTAINER
                        params: {}
                      postCmd:
                        action: NOOP
                        params: {}
        required: true
      responses:
        "202":
          description: Accepted
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ModelDeploymentCreateResultDto"
              example:
                modelDeploymentId: 3fa85f64-5717-4562-b3fc-2c963f66afa6
                modelId: 3a20e444-46be-ef86-bb20-5031f58d6fac
                edition: 1-0-0
                status: IN_PROGRESS
                createdAt: 2025-04-20T10:30:00Z
                createdBy: 2e701e62-0953-4dd3-910b-dc6cc93ccb0d
                updatedAt: 2025-04-20T10:30:00Z
                updatedBy: 2e701e62-0953-4dd3-910b-dc6cc93ccb0d
                targets:
                  - deviceId: 74fe488d5d54
                    deviceDeploymentId: 1fa85f64-5717-4562-b3fc-2c963f66afa6
                    state: SENT
        "400":
          description: Bad Request
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ProblemDetails"
              example:
                type: https://tools.ietf.org/html/rfc9110#section-15.5.1
                title: Bad Request - Invalid request parameters
                status: 400
                detail: The field Targets must have at least one element.
                instance: /api/v1/orgs/3a1b042d-40c3-64c0-5f5f-8aad7ae743da/ai-models/3a20e444-46be-ef86-bb20-5031f58d6fac/editions/1-0-0:deploy
        "404":
          description: Not Found
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ProblemDetails"
              example:
                type: https://tools.ietf.org/html/rfc9110#section-15.5.5
                title: Resource Not Found
                status: 404
                detail: Model '3a20e444-46be-ef86-bb20-5031f58d6fac' version '1-0-0' not found
                  in the model registry.
                instance: /api/v1/orgs/3a1b042d-40c3-64c0-5f5f-8aad7ae743da/ai-models/3a20e444-46be-ef86-bb20-5031f58d6fac/editions/1-0-0:deploy
        "409":
          description: Conflict
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ProblemDetails"
              example:
                type: https://tools.ietf.org/html/rfc9110#section-15.5.10
                title: Conflict
                status: 409
                detail: "Model '3a20e444-46be-ef86-bb20-5031f58d6fac' edition '1-0-0' is already
                  deployed to device(s): 74fe488d5d54."
                instance: /api/v1/orgs/3a1b042d-40c3-64c0-5f5f-8aad7ae743da/ai-models/3a20e444-46be-ef86-bb20-5031f58d6fac/editions/1-0-0:deploy
      security:
        - Bearer: []
  /api/v1/devices/{deviceId}/ai-models:
    get:
      tags:
        - ___swagger_4-ai-model-management_swagger_json_Model Deployments
      summary: List All AI Models for a Specific Device
      description: |-
        
        Returns all AI models currently deployed to the specified device.

        • Supports pagination via SkipCount and MaxResultCount.

        • Optional State filter narrows results to a specific deployment state.
      parameters:
        - name: deviceId
          in: path
          description: Edge device identifier (12-char hex, e.g. "74fe488d5d54").
          required: true
          schema:
            type: string
        - name: state
          in: query
          description: |-
            Optional filter by per-device deployment state.
            When specified, only devices matching this state are returned.
          schema:
            $ref: "#/components/schemas/DeploymentDeviceState"
        - name: skipCount
          in: query
          schema:
            maximum: 2147483647
            minimum: 0
            type: integer
            format: int32
        - name: maxResultCount
          in: query
          schema:
            maximum: 2147483647
            minimum: 1
            type: integer
            format: int32
      responses:
        "200":
          description: OK
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ModelDeploymentPagedResultDto of
                  ModelDeploymentByDeviceDto"
              example:
                skipCount: 0
                maxResultCount: 10
                totalPages: 1
                totalCount: 1
                items:
                  - modelId: 9b2e6c1a-7f43-4d8e-bf2a-1c5d9e0a3b7f
                    modelName: my-ai-model
                    edition: 1-0-0
                    orgId: 3a1b042d-40c3-64c0-5f5f-8aad7ae743da
                    deviceId: 74fe488d5d54
                    createdAt: 2025-04-20T10:30:00Z
                    createdBy: 2e701e62-0953-4dd3-910b-dc6cc93ccb0d
                    updatedAt: 2025-04-20T10:30:00Z
                    updatedBy: 2e701e62-0953-4dd3-910b-dc6cc93ccb0d
                    deploymentStartTime: 2025-04-20T10:30:00Z
                    deviceDeploymentId: 1fa85f64-5717-4562-b3fc-2c963f66afa6
                    edgeFilePath: /ai-models/my-ai-model/1-0-0/model.bin
                    state: DEPLOYED
      security:
        - Bearer: []
  /api/v1/orgs/{orgId}/ai-models/{modelId}/editions/{edition}/deployments:
    get:
      tags:
        - ___swagger_4-ai-model-management_swagger_json_Model Deployments
      summary: List Devices for a Specific Model Edition
      description: |-
        
        Returns all edge devices that have the specified model edition deployed.

        • Includes per-device state and last transition time.

        • Supports pagination and state filtering.
      parameters:
        - name: orgId
          in: path
          description: Organization identifier (GUID or string alias).
          required: true
          schema:
            type: string
        - name: modelId
          in: path
          description: Identifier of the AI model.
          required: true
          schema:
            type: string
        - name: edition
          in: path
          description: Model edition string to filter by (e.g. "1-0-0").
          required: true
          schema:
            type: string
        - name: state
          in: query
          description: |-
            Optional filter by per-device deployment state.
            When specified, only devices matching this state are returned.
          schema:
            $ref: "#/components/schemas/DeploymentDeviceState"
        - name: skipCount
          in: query
          schema:
            maximum: 2147483647
            minimum: 0
            type: integer
            format: int32
        - name: maxResultCount
          in: query
          schema:
            maximum: 2147483647
            minimum: 1
            type: integer
            format: int32
      responses:
        "200":
          description: OK
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ModelDeploymentPagedResultDto of
                  ModelDeploymentByModelVersionDto"
              example:
                skipCount: 0
                maxResultCount: 10
                totalPages: 1
                totalCount: 1
                items:
                  - deviceId: 74fe488d5d54
                    modelId: 3a20e444-46be-ef86-bb20-5031f58d6fac
                    modelName: my-ai-model
                    edition: 1-0-0
                    orgId: 3a1b042d-40c3-64c0-5f5f-8aad7ae743da
                    createdAt: 2025-04-20T10:30:00Z
                    createdBy: 2e701e62-0953-4dd3-910b-dc6cc93ccb0d
                    updatedAt: 2025-04-20T10:30:00Z
                    updatedBy: 2e701e62-0953-4dd3-910b-dc6cc93ccb0d
                    deploymentStartTime: 2025-04-20T10:30:00Z
                    deviceDeploymentId: 1fa85f64-5717-4562-b3fc-2c963f66afa6
                    edgeFilePath: /ai-models/my-ai-model/1-0-0/model.bin
                    state: DEPLOYED
                    lastTransitionTime: 2025-04-20T10:32:00Z
      security:
        - Bearer: []
    delete:
      tags:
        - ___swagger_4-ai-model-management_swagger_json_Model Deployments
      summary: Delete Model File from All Deployed Devices
      description: >-
        
        Removes the deployed model file from ALL devices that received this
        model edition.


        • Batch operation: triggers delete commands for every device in the
        deployment.


        • Returns 404 if no deployment exists for the model/edition combination.
      parameters:
        - name: orgId
          in: path
          description: Organization identifier (GUID or string alias).
          required: true
          schema:
            type: string
        - name: modelId
          in: path
          description: Identifier of the AI model to remove.
          required: true
          schema:
            type: string
        - name: edition
          in: path
          description: Model edition string to remove from all devices (e.g. "1-0-0").
          required: true
          schema:
            type: string
      responses:
        "202":
          description: Accepted
        "404":
          description: Not Found
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ProblemDetails"
              example:
                type: https://tools.ietf.org/html/rfc9110#section-15.5.5
                title: Resource Not Found
                status: 404
                detail: No active deployment found for device '74fe488d5d54', model
                  '3a20e444-46be-ef86-bb20-5031f58d6fac' version '1-0-0'.
                instance: /api/v1/devices/74fe488d5d54/ai-models/3a20e444-46be-ef86-bb20-5031f58d6fac/editions/1-0-0
      security:
        - Bearer: []
  /api/v1/devices/{deviceId}/ai-models/{modelId}/editions/{edition}:
    delete:
      tags:
        - ___swagger_4-ai-model-management_swagger_json_Model Deployments
      summary: Delete Model File from a Specific Device
      description: >-
        
        Removes the deployed model file from a specific device.


        • Triggers a NATS delete command to the device's Secured Volume.


        • Returns 404 if no active deployment exists for the
        device/model/edition combination.
      parameters:
        - name: deviceId
          in: path
          description: Edge device identifier (12-char hex, e.g. "74fe488d5d54").
          required: true
          schema:
            type: string
        - name: modelId
          in: path
          description: Identifier of the AI model to remove.
          required: true
          schema:
            type: string
        - name: edition
          in: path
          description: Model edition string to remove (e.g. "1-0-0").
          required: true
          schema:
            type: string
      responses:
        "202":
          description: Accepted
        "404":
          description: Not Found
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ProblemDetails"
              example:
                type: https://tools.ietf.org/html/rfc9110#section-15.5.5
                title: Resource Not Found
                status: 404
                detail: No active deployment found for device '74fe488d5d54', model
                  '3a20e444-46be-ef86-bb20-5031f58d6fac' version '1-0-0'.
                instance: /api/v1/devices/74fe488d5d54/ai-models/3a20e444-46be-ef86-bb20-5031f58d6fac/editions/1-0-0
      security:
        - Bearer: []
  /api/v1/orgs/{orgId}/ai-models/{modelId}/editions/{edition}:
    get:
      tags:
        - ___swagger_4-ai-model-management_swagger_json_Model Management
      summary: Get Model Edition Detail
      description: >-
        
        Returns the full metadata for a single model edition.


        - Includes file info (id, name, size, SHA-256 hash, storage URI),
        lifecycle status, change summary, and creation / integrity-verification
        timestamps.


        - Returns 404 if the model does not exist (ModelNotFound) or the edition
        string is not found under the model (EditionNotFound).
      parameters:
        - name: orgId
          in: path
          description: Organization identifier (GUID) that owns the model.
          required: true
          schema:
            type: string
            format: uuid
        - name: modelId
          in: path
          description: Identifier of the AI model.
          required: true
          schema:
            type: string
            format: uuid
        - name: edition
          in: path
          description: Edition string (e.g. "1-0-0").
          required: true
          schema:
            type: string
      responses:
        "200":
          description: OK
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/EditionDto"
      security:
        - Bearer: []
    patch:
      tags:
        - ___swagger_4-ai-model-management_swagger_json_Model Management
      summary: Update Edition Metadata
      description: >-
        
        Updates the editable metadata of an existing edition.


        - Only the edition `description` can be changed; the edition string,
        file content, and lifecycle status are immutable here.


        - Returns the full edition detail after the update, in the same shape as
        Get Model Edition Detail.


        - Returns 404 if the model does not exist (ModelNotFound) or the edition
        is not found (EditionNotFound).
      parameters:
        - name: orgId
          in: path
          description: Organization identifier (GUID) that owns the model.
          required: true
          schema:
            type: string
            format: uuid
        - name: modelId
          in: path
          description: Identifier of the AI model.
          required: true
          schema:
            type: string
            format: uuid
        - name: edition
          in: path
          description: Edition string to update (e.g. "1-0-0").
          required: true
          schema:
            type: string
      requestBody:
        description: |-
          Request body:
          - description – new description for the edition (required).
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/UpdateEditionInput"
      responses:
        "200":
          description: OK
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/EditionDto"
      security:
        - Bearer: []
    delete:
      tags:
        - ___swagger_4-ai-model-management_swagger_json_Model Management
      summary: Delete a Single Edition
      description: >-
        
        Permanently deletes the specified model edition.


        - The edition's underlying file will be removed from object storage.


        - Returns 404 if the model does not exist (ModelNotFound) or the edition
        is not found (EditionNotFound).
      parameters:
        - name: orgId
          in: path
          description: Organization identifier (GUID) that owns the model.
          required: true
          schema:
            type: string
            format: uuid
        - name: modelId
          in: path
          description: Identifier of the AI model.
          required: true
          schema:
            type: string
            format: uuid
        - name: edition
          in: path
          description: Edition string to delete (e.g. "1-0-0").
          required: true
          schema:
            type: string
      responses:
        "200":
          description: OK
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/DeleteEditionResultDto"
      security:
        - Bearer: []
  /api/v1/orgs/{orgId}/ai-models/{modelId}:
    patch:
      tags:
        - ___swagger_4-ai-model-management_swagger_json_Model Management
      summary: Update Model Basic Info
      description: >-
        
        Updates the basic, model-level metadata. Editions are unaffected.


        - At least one of `modelName` or `description` must be supplied; sending
        neither returns 400 (InvalidRequest).


        - A non-null field is applied; a null field leaves the existing value
        unchanged.


        - `modelName` must pass name-format validation and stay unique within
        the organization — returns 400 (InvalidNameFormat) or 409
        (ModelNameExists) otherwise.


        - Returns 403 if the model belongs to a different tenant
        (TenantMismatch), or 404 if it does not exist (ModelNotFound).
      parameters:
        - name: orgId
          in: path
          description: Organization identifier (GUID) that owns the model.
          required: true
          schema:
            type: string
            format: uuid
        - name: modelId
          in: path
          description: Identifier of the AI model to update.
          required: true
          schema:
            type: string
            format: uuid
      requestBody:
        description: >-
          Request body (at least one field required):

          - modelName – new model display name. Null leaves the existing name
          unchanged.

          - description – new model description. Null leaves the existing
          description unchanged.
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/UpdateModelInput"
      responses:
        "200":
          description: OK
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ModelDto"
      security:
        - Bearer: []
    delete:
      tags:
        - ___swagger_4-ai-model-management_swagger_json_Model Management
      summary: Delete a Model and All Its Editions
      description: |-
        
        Permanently deletes the model together with every one of its editions.

        - Each edition's underlying file will be removed from object storage.

        - Returns 404 if the model does not exist (ModelNotFound).
      parameters:
        - name: orgId
          in: path
          description: Organization identifier (GUID) that owns the model.
          required: true
          schema:
            type: string
            format: uuid
        - name: modelId
          in: path
          description: Identifier of the AI model to delete.
          required: true
          schema:
            type: string
            format: uuid
      responses:
        "200":
          description: OK
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/DeleteModelResultDto"
      security:
        - Bearer: []
  /api/v1/orgs/{orgId}/ai-models:
    post:
      tags:
        - ___swagger_4-ai-model-management_swagger_json_Model Management
      summary: Create Model
      description: >-
        
        Create a new AI model under the organization. The model holds no file
        yet — editions are registered and uploaded separately.


        - `modelName` must be unique within the organization and satisfy all of
        the following naming restrictions: allowed characters are English
        letters (a-z, A-Z), digits (0-9), hyphen (-), and underscore (_);
        forbidden characters are special symbols (such as *, ?, ", <, >, |, :,
        ;, ,, \, ., /), whitespace, and control characters; it MUST NOT exceed
        128 characters; and it MUST NOT end with .lock, .tmp, or .staging.


        - Returns 201 with the created model record (including the generated
        modelId).


        - Returns 400 for a missing orgId (MissingOrgId) or an invalid name
        (InvalidNameFormat), 403 if the org is not accessible to the caller's
        tenant (OrgNotInTenant), and 409 if the name already exists
        (ModelNameExists).
      parameters:
        - name: orgId
          in: path
          description: Organization identifier (GUID) that will own the model.
          required: true
          schema:
            type: string
            format: uuid
      requestBody:
        description: >-
          Request body:

          - modelName – model display name, unique within the organization
          (required).

          - description – optional the description of the model.
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/CreateModelInput"
      responses:
        "201":
          description: Created
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ModelDto"
        "400":
          description: Bad Request
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ProblemDetails"
              example:
                type: https://tools.ietf.org/html/rfc9110#section-15.5.5
                title: Resource Not Found
                status: 404
                detail: No active deployment found for device '74fe488d5d54', model
                  '3a20e444-46be-ef86-bb20-5031f58d6fac' version '1-0-0'.
                instance: /api/v1/devices/74fe488d5d54/ai-models/3a20e444-46be-ef86-bb20-5031f58d6fac/editions/1-0-0
        "409":
          description: Conflict
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ProblemDetails"
              example:
                type: https://tools.ietf.org/html/rfc9110#section-15.5.5
                title: Resource Not Found
                status: 404
                detail: No active deployment found for device '74fe488d5d54', model
                  '3a20e444-46be-ef86-bb20-5031f58d6fac' version '1-0-0'.
                instance: /api/v1/devices/74fe488d5d54/ai-models/3a20e444-46be-ef86-bb20-5031f58d6fac/editions/1-0-0
      security:
        - Bearer: []
    get:
      tags:
        - ___swagger_4-ai-model-management_swagger_json_Model Management
      summary: List Models for an Organization
      description: >-
        
        Returns a paginated list of all AI models owned by the organization.


        - Each item summarizes the model and its latest edition (latest edition
        string, file name, description) plus the total edition count.


        - Supports pagination via `skipCount` / `maxResultCount` and ordering
        via `sorting` (default "modelName asc").
      parameters:
        - name: orgId
          in: path
          description: Organization identifier (GUID).
          required: true
          schema:
            type: string
            format: uuid
        - name: sorting
          in: query
          schema:
            type: string
        - name: skipCount
          in: query
          schema:
            maximum: 2147483647
            minimum: 0
            type: integer
            format: int32
        - name: maxResultCount
          in: query
          schema:
            maximum: 2147483647
            minimum: 1
            type: integer
            format: int32
      responses:
        "200":
          description: OK
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/PagedResultDto of ModelListDto"
      security:
        - Bearer: []
  /api/v1/orgs/{orgId}/ai-models/{modelId}/editions:
    post:
      tags:
        - ___swagger_4-ai-model-management_swagger_json_Model Management
      summary: Register New Edition of an Existing Model
      description: >-
        
        Creates the edition (status `Pending`) and, when file info is supplied,
        opens an upload session — step 1 of the resumable upload flow.


        - The `edition` string must satisfy all of the following naming
        restrictions: allowed characters are English letters (a-z, A-Z), digits
        (0-9), hyphen (-), and underscore (_); forbidden characters are special
        symbols (such as *, ?, ", <, >, |, :, ;, ,, \, ., /), whitespace, and
        control characters; it MUST NOT exceed 255 characters; and it MUST NOT
        end with .lock, .tmp, or .staging.


        - Omit all of `fileName`/`fileSize`/`fileHash` to create an empty
        `Pending` edition with no upload (`uploadId`/`tusEndpoint`/`file` are
        null). Supplying only some of the three returns 400 (InvalidRequest).


        - When file info is supplied, returns a scoped `tusEndpoint` URL plus
        the `uploadId` to send (base64-encoded) in the `Upload-Metadata` header
        when creating the TUS upload.


        - The session expires 12 hours after registration (`uploadExpiresAt`);
        the actual bytes must be transferred before then.


        - `fileHash` must be a 64-char lowercase SHA-256 hex string; it is
        re-verified server-side after the transfer completes.


        - Re-registering an edition that is still `Pending` reuses it
        (resume/retry); returns 409 (EditionAlreadyExists) only if it already
        has a verified file.


        - Returns 400 for a missing orgId (MissingOrgId), an invalid edition
        string (InvalidEditionFormat), incomplete file info (InvalidRequest), or
        a malformed hash (InvalidClientHash); 413 if the file exceeds the
        maximum size (FileTooLarge); 403 on tenant mismatch (TenantMismatch);
        404 if the model is not found (ModelNotFound); and 409 if the edition
        already has a file (EditionAlreadyExists).
      parameters:
        - name: orgId
          in: path
          description: Organization identifier (GUID) that owns the model.
          required: true
          schema:
            type: string
            format: uuid
        - name: modelId
          in: path
          description: Identifier of the existing AI model to add an edition to.
          required: true
          schema:
            type: string
            format: uuid
      requestBody:
        description: |-
          Request body:
          - edition – edition string (e.g. "1-0-0", required).
          - fileName – original file name to upload (optional).
          - fileSize – file size in bytes (optional).
          - fileHash – client-computed SHA-256 hash, 64-char hex (optional).
          - description – optional edition description.
          - changeSummary – optional summary of changes in this edition.
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/RegisterUploadInput"
      responses:
        "201":
          description: Created
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/EditionDto"
        "400":
          description: Bad Request
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ProblemDetails"
              example:
                type: https://tools.ietf.org/html/rfc9110#section-15.5.5
                title: Resource Not Found
                status: 404
                detail: No active deployment found for device '74fe488d5d54', model
                  '3a20e444-46be-ef86-bb20-5031f58d6fac' version '1-0-0'.
                instance: /api/v1/devices/74fe488d5d54/ai-models/3a20e444-46be-ef86-bb20-5031f58d6fac/editions/1-0-0
        "404":
          description: Not Found
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ProblemDetails"
              example:
                type: https://tools.ietf.org/html/rfc9110#section-15.5.5
                title: Resource Not Found
                status: 404
                detail: No active deployment found for device '74fe488d5d54', model
                  '3a20e444-46be-ef86-bb20-5031f58d6fac' version '1-0-0'.
                instance: /api/v1/devices/74fe488d5d54/ai-models/3a20e444-46be-ef86-bb20-5031f58d6fac/editions/1-0-0
        "409":
          description: Conflict
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ProblemDetails"
              example:
                type: https://tools.ietf.org/html/rfc9110#section-15.5.5
                title: Resource Not Found
                status: 404
                detail: No active deployment found for device '74fe488d5d54', model
                  '3a20e444-46be-ef86-bb20-5031f58d6fac' version '1-0-0'.
                instance: /api/v1/devices/74fe488d5d54/ai-models/3a20e444-46be-ef86-bb20-5031f58d6fac/editions/1-0-0
      security:
        - Bearer: []
    get:
      tags:
        - ___swagger_4-ai-model-management_swagger_json_Model Management
      summary: List Editions of a Model
      description: >-
        
        Returns a paginated list of editions for the specified model.


        - Each item includes the edition string, description, lifecycle status,
        and file info.


        - Results are primarily ordered newest-first by creation time; `sorting`
        (edition / fileSize, asc or desc) applies as a secondary key.


        - `status` optionally filters by one or more lifecycle states
        (comma-separated); unrecognized values are ignored.


        - Returns 404 if the model does not exist under the organization
        (ModelNotFound).
      parameters:
        - name: orgId
          in: path
          description: Organization identifier (GUID) that owns the model.
          required: true
          schema:
            type: string
            format: uuid
        - name: modelId
          in: path
          description: Identifier of the AI model whose editions to list.
          required: true
          schema:
            type: string
            format: uuid
        - name: status
          in: query
          description: >-
            Optional lifecycle status filter (comma-separated to match
            multiple). Null returns all statuses. One of:

            - `Pending`: Registered but no hash-verified file yet (upload
            pending/in progress).

            - `Uploaded`: Successfully uploaded and hash-verified; the edition
            is available.
          schema:
            type: string
        - name: sorting
          in: query
          schema:
            type: string
        - name: skipCount
          in: query
          schema:
            maximum: 2147483647
            minimum: 0
            type: integer
            format: int32
        - name: maxResultCount
          in: query
          schema:
            maximum: 2147483647
            minimum: 1
            type: integer
            format: int32
      responses:
        "200":
          description: OK
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/PagedResultDto of ModelEditionListDto"
      security:
        - Bearer: []
  /api/v1/orgs/{orgId}/ai-models/{modelId}/editions/{edition}/uploads/{uploadId}/status:
    get:
      tags:
        - ___swagger_4-ai-model-management_swagger_json_Model Uploads
      summary: Get Upload Status
      description: >-
        
        Polls the status of an upload session — used by the client to track
        progress after registering and transferring a file.


        - `uploadExpiresAt` is returned only while the upload is still in
        progress (Pending or Uploading); it is omitted once the session reaches
        a terminal state.


        - Clients typically poll this endpoint until the status becomes
        `Uploaded` (success) or a `*Failed` state (`UploadFailed` /
        `VerifyFailed`).


        - Returns 404 if no upload session matches the given uploadId
        (UploadNotFound).
      parameters:
        - name: orgId
          in: path
          description: Organization identifier (GUID) that owns the model.
          required: true
          schema:
            type: string
            format: uuid
        - name: modelId
          in: path
          description: Identifier of the AI model.
          required: true
          schema:
            type: string
            format: uuid
        - name: edition
          in: path
          description: Edition string (e.g. "1-0-0").
          required: true
          schema:
            type: string
        - name: uploadId
          in: path
          description: Unique upload identifier returned by the Register New Edition API.
          required: true
          schema:
            type: string
            format: uuid
      responses:
        "200":
          description: OK
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/UploadStatusDto"
      security:
        - Bearer: []
  /api/v1/orgs/{orgId}/ai-models/{modelId}/editions/{edition}/uploads:
    post:
      tags:
        - ___swagger_4-ai-model-management_swagger_json_Model Uploads
      summary: Create a resumable upload
      description: >-
        Creates a new resumable upload session — step 2 of the resumable upload
        flow.


        • Call **Register New Edition** first to obtain an `uploadId`, then send
        it (base64-encoded) in the `Upload-Metadata` header.


        • Service will validate the `uploadId`, and that `Upload-Length` matches
        the registered file size.


        • On success the `Location` header points to the upload resource URL
        used for the subsequent `PATCH` requests.


        • The `uploadId` never expires: after a terminated (`DELETE`) or failed
        transfer, call this endpoint again with the same `uploadId` to retry
        from scratch. An in-progress session blocks re-creation only until its
        `uploadExpiresAt` passes — after that it is considered abandoned, and
        re-creating discards the stalled transfer's data and starts over. An
        already-uploaded session can never be re-created.


        • Returns 400 if the backend pre-create hook rejects the request
        (missing / completed / still-fresh in-progress upload, size mismatch).
      parameters:
        - name: Tus-Resumable
          in: header
          description: TUS protocol version. Defaults to `1.0.0` if omitted; if sent, must
            be `1.0.0`.
          schema:
            type: string
        - name: Upload-Length
          in: header
          description: Total size of the file in bytes.
          required: true
          schema:
            type: integer
        - name: Upload-Metadata
          in: header
          description: "The value must be in the format `uploadId <Base64-encoded
            uploadId>`, where the value after `uploadId` is the Base64-encoded
            ID returned by the Register New Version API. For example: `uploadId
            M2ZhODVmNjQtNTcxNy00NTYyLWIzZmMtMmM5NjNmNjZhZmE2`."
          required: true
          schema:
            type: string
      responses:
        "201":
          description: Upload created. The `Location` header contains the upload resource
            URL.
          headers:
            Location:
              description: URL of the created upload resource.
              schema:
                type: string
            Tus-Resumable:
              description: TUS protocol version.
              schema:
                type: string
        "400":
          description: "Validation failed (rejected by the backend pre-create hook):
            missing/expired upload, size mismatch, etc."
        "401":
          description: Missing or invalid Bearer token.
      security:
        - Bearer: []
    parameters:
      - name: orgId
        in: path
        description: Organization identifier (GUID) that owns the model.
        required: true
        schema:
          type: string
          format: uuid
      - name: modelId
        in: path
        description: Identifier of the AI model the edition belongs to.
        required: true
        schema:
          type: string
          format: uuid
      - name: edition
        in: path
        description: Edition string (e.g. `1-0-0`).
        required: true
        schema:
          type: string
  /api/v1/orgs/{orgId}/ai-models/{modelId}/editions/{edition}/uploads/{uploadId}:
    head:
      tags:
        - ___swagger_4-ai-model-management_swagger_json_Model Uploads
      summary: Get current upload offset
      description: >-
        Reports how many bytes service has already stored so the client can
        resume an interrupted transfer.


        • Returns the current `Upload-Offset` (and `Upload-Length`) so the
        client knows where to continue from.


        • Returns 404 if the upload resource is not found.
      parameters:
        - name: Tus-Resumable
          in: header
          description: TUS protocol version. Defaults to `1.0.0` if omitted; if sent, must
            be `1.0.0`.
          schema:
            type: string
      responses:
        "200":
          description: Returns the current offset.
          headers:
            Upload-Offset:
              description: Bytes already stored on the server.
              schema:
                type: string
            Upload-Length:
              description: Total size of the file in bytes.
              schema:
                type: string
        "404":
          description: Upload resource not found.
      security:
        - Bearer: []
    patch:
      tags:
        - ___swagger_4-ai-model-management_swagger_json_Model Uploads
      summary: Upload a file chunk
      description: >-
        Appends a chunk of file data to the upload — step 3 of the resumable
        upload flow, the actual byte-transfer step.


        • The request body is the raw bytes with `Content-Type:
        application/offset+octet-stream`, starting at the supplied
        `Upload-Offset`.


        • Returns 204 with the new `Upload-Offset` on success, 409 if the
        supplied `Upload-Offset` does not match the server state, or 404 if the
        upload resource is not found.
      parameters:
        - name: Tus-Resumable
          in: header
          description: TUS protocol version. Defaults to `1.0.0` if omitted; if sent, must
            be `1.0.0`.
          schema:
            type: string
        - name: Upload-Offset
          in: header
          description: Byte offset at which this chunk starts.
          required: true
          schema:
            type: integer
        - name: Content-Type
          in: header
          description: Must be `application/offset+octet-stream`.
          required: true
          schema:
            type: string
      requestBody:
        description: Raw chunk bytes.
        content:
          application/offset+octet-stream:
            schema:
              type: string
              format: binary
        required: true
      responses:
        "204":
          description: Chunk stored.
          headers:
            Upload-Offset:
              description: New offset after this chunk.
              schema:
                type: string
        "404":
          description: Upload resource not found.
        "409":
          description: Offset conflict — the supplied `Upload-Offset` does not match the
            server state.
      security:
        - Bearer: []
    delete:
      tags:
        - ___swagger_4-ai-model-management_swagger_json_Model Uploads
      summary: Terminate an upload
      description: >-
        Cancel and remove an in-progress upload.


        • The `uploadId` itself remains valid — create a new upload session with
        the same `uploadId` to retry.


        • Returns 204 on success, or 404 if the upload resource is not found.
      parameters:
        - name: Tus-Resumable
          in: header
          description: TUS protocol version. Defaults to `1.0.0` if omitted; if sent, must
            be `1.0.0`.
          schema:
            type: string
      responses:
        "204":
          description: Upload terminated.
        "404":
          description: Upload resource not found.
      security:
        - Bearer: []
    parameters:
      - name: orgId
        in: path
        description: Organization identifier (GUID) that owns the model.
        required: true
        schema:
          type: string
          format: uuid
      - name: modelId
        in: path
        description: Identifier of the AI model the edition belongs to.
        required: true
        schema:
          type: string
          format: uuid
      - name: edition
        in: path
        description: Edition string (e.g. `1-0-0`).
        required: true
        schema:
          type: string
      - name: uploadId
        in: path
        description: Identifier of the upload resource (from the `Location` header
          returned by the creation request).
        required: true
        schema:
          type: string
  /api/v1/orgs/{orgId}/devices/{deviceId}/data-streams:
    get:
      tags:
        - ___swagger_5-data-stream_swagger_json_DataStreams
      summary: List data streams
      description: >-
        Retrieve all data streams for a specific device. For user-managed
        streams (managedBy = User), dataSource

        can be null or absent when the stream is not yet bound to a source.
                    
        **Parameters**
                    
        * `deviceId` (string, required): Unique ID of the device. Example:
        `74fe488d5d35`

        * `skipCount` (int, optional): Number of records to skip for pagination
        (default: 0).

        * `maxResultCount` (int, optional): Maximum number of records to return
        (default: 10, max: 100).
                    
        **Responses**
                    
        * `200 OK`: Returns a paged list of data streams.
                    
        **Security**
                    
        * This API requires authentication.
      parameters:
        - name: orgId
          in: path
          description: Organization ID.
          required: true
          schema:
            type: string
            format: uuid
          example: 77ffccee-4f7a-46cd-a000-8a2c254edb53
        - name: deviceId
          in: path
          description: "Device unique ID. Example: 74fe488d5d35."
          required: true
          schema:
            type: string
        - name: managedBy
          in: query
          description: Filter by management ownership; omitted returns both System and User.
          schema:
            $ref: "#/components/schemas/ManagedBy"
          example: User
        - name: sorting
          in: query
          schema:
            type: string
        - name: skipCount
          in: query
          schema:
            maximum: 2147483647
            minimum: 0
            type: integer
            format: int32
        - name: maxResultCount
          in: query
          schema:
            maximum: 2147483647
            minimum: 1
            type: integer
            format: int32
      responses:
        "200":
          description: Returns a paged list of data streams.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/DataStreamDtoPagedResultDto"
      security:
        - Bearer: []
    post:
      tags:
        - ___swagger_5-data-stream_swagger_json_DataStreams
      summary: Create a data stream
      description: >-
        Create a new data stream for a specific device.
                    
        **Parameters**
                    
        * `deviceId` (string, required): Unique ID of the device. Example:
        `74fe488d5d35`
                    
        **Request Body**
                    
        * `dataStreamName` (string, required): Unique name of the data stream
        within the device.

        * `displayName` (string, optional): Human-readable label for the data
        stream.

        * `description` (string, optional): Description of the data stream.

        * `unitDisplay` (string, optional): Display unit of the measured value
        (e.g. °C, %).

        * `dataType` (string, required): Data type of the stream value (e.g.
        double, boolean, integer).

        * `recordToDataLake` (boolean, optional): Whether to persist values to
        the data lake.
                    
        **Responses**
                    
        * `201 Created`: Data stream created successfully. The stream is
        user-managed (managedBy = User) with no
          dataSource; bind a source later via the source-linking APIs.
        * `400 Bad Request`: Invalid request body.

        * `409 Conflict`: A data stream with the same name already exists on
        this device.
                    
        **Security**
                    
        * This API requires authentication.
      parameters:
        - name: orgId
          in: path
          description: Organization ID.
          required: true
          schema:
            type: string
            format: uuid
          example: 77ffccee-4f7a-46cd-a000-8a2c254edb53
        - name: deviceId
          in: path
          description: "Device unique ID. Example: 74fe488d5d35."
          required: true
          schema:
            type: string
      requestBody:
        description: Data stream creation payload.
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/CreateDataStreamDto"
            example:
              dataStreamName: cpu_temperature
              displayName: CPU Temperature Sensor
              description: CPU temperature sensor in Fahrenheit
              unitDisplay: °F
              dataType: double
              recordToDataLake: true
          text/json:
            schema:
              $ref: "#/components/schemas/CreateDataStreamDto"
            example:
              dataStreamName: cpu_temperature
              displayName: CPU Temperature Sensor
              description: CPU temperature sensor in Fahrenheit
              unitDisplay: °F
              dataType: double
              recordToDataLake: true
          application/*+json:
            schema:
              $ref: "#/components/schemas/CreateDataStreamDto"
            example:
              dataStreamName: cpu_temperature
              displayName: CPU Temperature Sensor
              description: CPU temperature sensor in Fahrenheit
              unitDisplay: °F
              dataType: double
              recordToDataLake: true
      responses:
        "201":
          description: >-
            Data stream created successfully. The stream is user-managed
            (managedBy = User) with no dataSource; bind

            a source later via the source-linking APIs.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/DataStreamDto"
        "400":
          description: Invalid request body.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ProblemDetails"
        "409":
          description: A data stream with the same name already exists on this device.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ProblemDetails"
      security:
        - Bearer: []
  /api/v1/orgs/{orgId}/devices/{deviceId}/data-streams/values/latest:
    get:
      tags:
        - ___swagger_5-data-stream_swagger_json_DataStreams
      summary: Get latest data
      description: >-
        Retrieve all latest data objects from data streams for the device within
        the system-defined retention

        period (default: 60 minutes).
                    
        **Parameters**
                    
        * `deviceId` (string, required): Unique ID of the device. Example:
        `74fe488d5d35`
                    
        **Responses**
                    
        * `200 OK`: Returns the latest data-objects data including value object,
        value type, timestamp, and data
          object name.
        * `204 No Content`: No latest data available from realtime cache or
        persistent storage for the specified
          device.


                    
        **Security**
                    
        * This API requires authentication.
      parameters:
        - name: orgId
          in: path
          description: Organization ID.
          required: true
          schema:
            type: string
            format: uuid
          example: 77ffccee-4f7a-46cd-a000-8a2c254edb53
        - name: deviceId
          in: path
          description: "Device unique ID. Example: 74fe488d5d35."
          required: true
          schema:
            type: string
      responses:
        "200":
          description: Returns the latest data-objects data including value object, value
            type, timestamp, and data object name.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/TelemetryResponseDataObjects"
        "204":
          description: No latest data available from realtime cache or persistent storage
            for the specified device.
      security:
        - Bearer: []
  /api/v1/orgs/{orgId}/devices/{deviceId}/data-streams/{dataStreamId}/values/latest:
    get:
      tags:
        - ___swagger_5-data-stream_swagger_json_DataStreams
      summary: Retrieve the latest value of a specific data stream.
      description: >-
        Retrieve latest value of assigned dataStreamId for the device within the
        system-defined retention period

        (default: 60 minutes).
                    
        **Parameters**
                    
        * `deviceId` (string, required): Unique ID of the device. Example:
        `74fe488d5d35`

        * `dataStreamId` (Guid, required): Unique ID of the data stream.
        Example: `3a217ee3-fb2c-617b-6ff6-7257537afade`
                    
        **Responses**
                    
        * `200 OK`: Returns the latest data-stream value including value object,
        value type, timestamp, and data
          stream name.
        * `204 No Content`: No latest data available for the specified data
        stream.

        * `404 Not Found`: Data stream not found.
                    
        **Security**
                    
        * This API requires authentication.
      parameters:
        - name: orgId
          in: path
          description: Organization ID.
          required: true
          schema:
            type: string
            format: uuid
          example: 77ffccee-4f7a-46cd-a000-8a2c254edb53
        - name: deviceId
          in: path
          description: "Device unique ID. Example: 74fe488d5d35."
          required: true
          schema:
            type: string
        - name: dataStreamId
          in: path
          description: Data stream unique ID.
          required: true
          schema:
            type: string
            format: uuid
          example: 3a217ee3-fb2c-617b-6ff6-7257537afade
      responses:
        "200":
          description: Returns the latest data-stream value including value object, value
            type, timestamp, and data stream name.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/DataStreamLatestValueResponse"
        "204":
          description: No latest data available for the specified data stream.
        "404":
          description: Data stream not found.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ProblemDetails"
      security:
        - Bearer: []
  /api/v1/orgs/{orgId}/devices/{deviceId}/data-streams/{dataStreamId}/values/historical:
    get:
      tags:
        - ___swagger_5-data-stream_swagger_json_DataStreams
      summary: Get data history
      description: |-
        Retrieve values of assigned dataStreamId for a device using cursor-based pagination for better performance.
                    
        **Why Cursor-based Pagination?**
        - **Much faster** than offset-based pagination, especially for large datasets
        - **Constant performance** regardless of page depth (page 1 and page 1000 have same speed)
        - **No expensive OFFSET** operations that skip thousands of records
        - **No totalCount calculation** - avoids heavy COUNT queries
                    
        **How to Use**:
        1. **First request**: Omit the `cursor` parameter
        2. **Subsequent requests**: Use `nextCursor` from previous response as `cursor` parameter
        3. **Continue** until `hasMore` is false
                    
        **Parameters**
                    
        * `deviceId` (string, required): Unique identifier of the device. Example: `74fe488d5d35`
        * `dataStreamId` (Guid, required): Unique ID of the data stream. Example: `3a217ee3-fb2c-617b-6ff6-7257537afade`
        * `start` (DateTime, required): Start timestamp of the query range. Example: `2025-09-01T00:00:00Z`
        * `end` (DateTime, required): End timestamp of the query range. Example: `2025-09-02T00:00:00Z`
        * `cursor` (long, optional): Cursor timestamp from previous page (Unix milliseconds). Omit for first page.
        * `limit` (int, optional): Maximum results per page (default: 17, max: 1000).
                    
        **Response Fields**:
        * `deviceId` (string): Device unique ID the samples belong to.
        * `dataStreamId` (Guid): Unique ID of the data stream the samples belong to.
        * `start` (DateTime): Start timestamp of the queried range in ISO 8601 UTC.
        * `end` (DateTime): End timestamp of the queried range in ISO 8601 UTC.
        * `dataType` (string): Data type of the stream values (e.g. double, boolean, integer, string).
        * `dataObjects` (array): Timestamped values, ordered by timestamp. Each item:
          - `timestamp` (DateTime): Sample time in ISO 8601 UTC. Example: `2025-09-01T08:00:00Z`
          - `value`: Sample value; its type is declared by `dataType`.
        * `nextCursor` (long): Timestamp to use for next page (null if no more data).
        * `hasMore` (boolean): Whether there are more pages available.
                    
        All timestamps are stored and returned in UTC. FR-14: a stream with `recordToDataLake=false` always
        returns an empty page (`items: []`, `nextCursor: null`, `hasMore: false`; 200), never an error.
                    
        **Example Usage**:
        ```
        # First page
        GET /orgs/77ffccee-4f7a-46cd-a000-8a2c254edb53/devices/74fe488d5d35/data-streams/3a217ee3-fb2c-617b-6ff6-7257537afade/values/historical?start=2025-01-01T00:00:00Z&end=2025-01-02T00:00:00Z&limit=100
                    
        # Second page (use nextCursor from first response)
        GET /orgs/77ffccee-4f7a-46cd-a000-8a2c254edb53/devices/74fe488d5d35/data-streams/3a217ee3-fb2c-617b-6ff6-7257537afade/values/historical?start=2025-01-01T00:00:00Z&end=2025-01-02T00:00:00Z&cursor=1704153600000&limit=100
        ```
                    
        **Responses**
                    
        * `200 OK`: returns cursor-based paginated data stream values.
        * `400 Bad Request`: Invalid query parameters.
        * `404 Not Found`: Data stream not found.
                    
        **Security**
                    
        * This API requires authentication.
      parameters:
        - name: orgId
          in: path
          description: Organization ID.
          required: true
          schema:
            type: string
            format: uuid
          example: 77ffccee-4f7a-46cd-a000-8a2c254edb53
        - name: deviceId
          in: path
          description: "Device unique ID. Example: 74fe488d5d35."
          required: true
          schema:
            type: string
        - name: dataStreamId
          in: path
          description: Data stream unique ID.
          required: true
          schema:
            type: string
            format: uuid
          example: 3a217ee3-fb2c-617b-6ff6-7257537afade
        - name: start
          in: query
          description: Start of the query range (inclusive).
          schema:
            type: string
            format: date-time
            example: 2025-09-01T00:00:00Z
          example: 2025-09-01T00:00:00Z
        - name: end
          in: query
          description: End of the query range (exclusive).
          schema:
            type: string
            format: date-time
            example: 2025-09-02T00:00:00Z
          example: 2025-09-02T00:00:00Z
        - name: cursor
          in: query
          description: The `nextCursor` returned by the previous page (Unix milliseconds);
            omit for the first page.
          schema:
            type: integer
            format: int64
            example: 1704153600000
          example: 1704153600000
        - name: limit
          in: query
          description: "Maximum number of records per page (default: 17, capped at 1000
            per the contract)."
          schema:
            type: integer
            format: int32
            example: 100
          example: 100
      responses:
        "200":
          description: Returns cursor-based paginated data stream values.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/DataStreamHistoricalResponse"
        "400":
          description: Invalid query parameters.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ProblemDetails"
        "404":
          description: Data stream not found.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ProblemDetails"
      security:
        - Bearer: []
  /api/v1/orgs/{orgId}/devices/{deviceId}/data-streams/{dataStreamId}/blobs/{blobKey}:
    get:
      tags:
        - ___swagger_5-data-stream_swagger_json_DataStreams
      summary: Get assigned device binary data.
      description: >-
        Retrieve blob binary of a specific object key of a data-stream for a
        device. This API can be used to

        retrieve images or other file blobs stored in MinIO/S3-compatible
        storage.
                    
        **Parameters**
                    
        * `deviceId` (string, required): Unique ID of the device. Example:
        `74fe488d5d35`

        * `dataStreamId` (Guid, required): Unique ID of the data stream.
        Example: `3a217ee3-fb2c-617b-6ff6-7257537afade`

        * `blobKey` (string, required): Object storage key/path of the blob.
        Example: `74fe488d5d35/cams/01/image.png`
                    
        **Responses**
                    
        * `200 OK`: Returns the requested blob content, such as an image or
        file.

        * `404 Not Found`: No blob was found for the specified device and blob
        key.
                    
        **Security**
                    
        * This API requires authentication.
      parameters:
        - name: orgId
          in: path
          description: Organization ID.
          required: true
          schema:
            type: string
            format: uuid
          example: 77ffccee-4f7a-46cd-a000-8a2c254edb53
        - name: deviceId
          in: path
          description: "Device unique ID. Example: 74fe488d5d35."
          required: true
          schema:
            type: string
        - name: dataStreamId
          in: path
          description: Data stream unique ID.
          required: true
          schema:
            type: string
            format: uuid
          example: 3a217ee3-fb2c-617b-6ff6-7257537afade
        - name: blobKey
          in: path
          description: Object storage key/path of the blob.
          required: true
          schema:
            type: string
          example: 74fe488d5d35/cams/01/image.png
      responses:
        "200":
          description: Returns the requested blob content, such as an image or file.
          content:
            application/json:
              schema:
                type: string
                format: binary
        "404":
          description: No blob was found for the specified device and blob key.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ProblemDetails"
      security:
        - Bearer: []
  /api/v1/orgs/{orgId}/devices/{deviceId}/data-streams/{dataStreamId}:
    get:
      tags:
        - ___swagger_5-data-stream_swagger_json_DataStreams
      summary: Get a data stream
      description: >-
        Retrieve details of a specific data stream by its ID. For user-managed
        streams (managedBy = User),

        dataSource can be null or absent when the stream is not yet bound to a
        source.
                    
        **Parameters**
                    
        * `deviceId` (string, required): Unique ID of the device. Example:
        `74fe488d5d35`

        * `dataStreamId` (Guid, required): Unique ID of the data stream.
        Example: `e033b4b3-36e0-4dbc-a6e4-1e77185402f4`
                    
        **Responses**
                    
        * `200 OK`: Returns the data stream details.

        * `404 Not Found`: Data stream not found.
                    
        **Security**
                    
        * This API requires authentication.
      parameters:
        - name: orgId
          in: path
          description: Organization ID.
          required: true
          schema:
            type: string
            format: uuid
          example: 77ffccee-4f7a-46cd-a000-8a2c254edb53
        - name: deviceId
          in: path
          description: "Device unique ID. Example: 74fe488d5d35."
          required: true
          schema:
            type: string
        - name: dataStreamId
          in: path
          description: Data stream unique ID.
          required: true
          schema:
            type: string
            format: uuid
          example: e033b4b3-36e0-4dbc-a6e4-1e77185402f4
      responses:
        "200":
          description: Returns the data stream details.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/DataStreamDto"
        "404":
          description: Data stream not found.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ProblemDetails"
      security:
        - Bearer: []
    put:
      tags:
        - ___swagger_5-data-stream_swagger_json_DataStreams
      summary: Update a data stream
      description: >-
        Replace all fields of a specific data stream. For system-managed streams
        (managedBy = System), only the

        fields listed in the editable fields (displayName, description,
        unitDisplay, recordToDataLake) may change;

        modifying any other field is rejected with 409.
                    
        **Parameters**
                    
        * `deviceId` (string, required): Unique ID of the device. Example:
        `74fe488d5d35`

        * `dataStreamId` (Guid, required): Unique ID of the data stream.
        Example: `e033b4b3-36e0-4dbc-a6e4-1e77185402f4`
                    
        **Responses**
                    
        * `200 OK`: Data stream updated successfully.

        * `400 Bad Request`: Invalid request body.

        * `404 Not Found`: Data stream not found.

        * `409 Conflict`: A field not editable on this stream was modified.
                    
        **Security**
                    
        * This API requires authentication.
      parameters:
        - name: orgId
          in: path
          description: Organization ID.
          required: true
          schema:
            type: string
            format: uuid
          example: 77ffccee-4f7a-46cd-a000-8a2c254edb53
        - name: deviceId
          in: path
          description: "Device unique ID. Example: 74fe488d5d35."
          required: true
          schema:
            type: string
        - name: dataStreamId
          in: path
          description: Data stream unique ID.
          required: true
          schema:
            type: string
            format: uuid
          example: e033b4b3-36e0-4dbc-a6e4-1e77185402f4
      requestBody:
        description: Data stream update payload.
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/UpdateDataStreamDto"
            example:
              dataStreamName: cpu_temperature
              displayName: CPU Temperature Sensor
              description: CPU temperature sensor in Fahrenheit
              unitDisplay: °F
              dataType: double
              recordToDataLake: true
          text/json:
            schema:
              $ref: "#/components/schemas/UpdateDataStreamDto"
            example:
              dataStreamName: cpu_temperature
              displayName: CPU Temperature Sensor
              description: CPU temperature sensor in Fahrenheit
              unitDisplay: °F
              dataType: double
              recordToDataLake: true
          application/*+json:
            schema:
              $ref: "#/components/schemas/UpdateDataStreamDto"
            example:
              dataStreamName: cpu_temperature
              displayName: CPU Temperature Sensor
              description: CPU temperature sensor in Fahrenheit
              unitDisplay: °F
              dataType: double
              recordToDataLake: true
      responses:
        "200":
          description: Data stream updated successfully.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/DataStreamDto"
        "400":
          description: Invalid request body.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ProblemDetails"
        "404":
          description: Data stream not found.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ProblemDetails"
        "409":
          description: A field not editable on this stream was modified.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ProblemDetails"
      security:
        - Bearer: []
    patch:
      tags:
        - ___swagger_5-data-stream_swagger_json_DataStreams
      summary: Partially update a data stream
      description: >-
        Update one or more fields of a specific data stream. Only the provided
        fields will be updated; omitted

        fields retain their current values. For system-managed streams
        (managedBy = System), only the fields

        listed in the editable fields (displayName, description, unitDisplay,
        recordToDataLake) may be sent; any

        other field is rejected with 409.
                    
        **Parameters**
                    
        * `deviceId` (string, required): Unique ID of the device. Example:
        `74fe488d5d35`

        * `dataStreamId` (Guid, required): Unique ID of the data stream.
        Example: `e033b4b3-36e0-4dbc-a6e4-1e77185402f4`
                    
        **Responses**
                    
        * `200 OK`: Data stream patched successfully.

        * `400 Bad Request`: Invalid request body.

        * `404 Not Found`: Data stream not found.

        * `409 Conflict`: A field not editable on this stream was modified.
                    
        **Security**
                    
        * This API requires authentication.
      parameters:
        - name: orgId
          in: path
          description: Organization ID.
          required: true
          schema:
            type: string
            format: uuid
          example: 77ffccee-4f7a-46cd-a000-8a2c254edb53
        - name: deviceId
          in: path
          description: "Device unique ID. Example: 74fe488d5d35."
          required: true
          schema:
            type: string
        - name: dataStreamId
          in: path
          description: Data stream unique ID.
          required: true
          schema:
            type: string
            format: uuid
          example: e033b4b3-36e0-4dbc-a6e4-1e77185402f4
      requestBody:
        description: Data stream partial update payload.
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/PatchDataStreamDto"
            example:
              displayName: CPU Temperature Sensor (Updated)
              recordToDataLake: true
          text/json:
            schema:
              $ref: "#/components/schemas/PatchDataStreamDto"
            example:
              displayName: CPU Temperature Sensor (Updated)
              recordToDataLake: true
          application/*+json:
            schema:
              $ref: "#/components/schemas/PatchDataStreamDto"
            example:
              displayName: CPU Temperature Sensor (Updated)
              recordToDataLake: true
      responses:
        "200":
          description: Data stream patched successfully.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/DataStreamDto"
        "400":
          description: Invalid request body.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ProblemDetails"
        "404":
          description: Data stream not found.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ProblemDetails"
        "409":
          description: A field not editable on this stream was modified.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ProblemDetails"
      security:
        - Bearer: []
    delete:
      tags:
        - ___swagger_5-data-stream_swagger_json_DataStreams
      summary: Delete a data stream
      description: >-
        Soft-delete a specific data stream from a device. The stream is marked
        as deleted and excluded from

        listings; its historical data is retained per the data retention policy.
                    
        Only user-managed streams (managedBy = User) can be deleted;
        system-managed streams (WedaNode /

        WedaSubNode sources) are synced automatically from the device and cannot
        be deleted.
                    
        The delete is blocked while the data stream is currently attached to a
        source (dataSource), used by an

        analyzer, or referenced by an alert policy; detach it from the source,
        remove it from the analyzer, and

        remove it from any alert policies first, then retry the delete. If the
        analyzer/alert policy service

        cannot be reached to verify these references, the delete is rejected
        (503) rather than proceeding without

        the check.
                    
        **Parameters**
                    
        * `deviceId` (string, required): Unique ID of the device. Example:
        `74fe488d5d35`

        * `dataStreamId` (Guid, required): Unique ID of the data stream.
        Example: `e033b4b3-36e0-4dbc-a6e4-1e77185402f4`
                    
        **Responses**
                    
        * `204 No Content`: Data stream soft-deleted successfully.

        * `404 Not Found`: Data stream not found.

        * `409 Conflict`: The data stream is system-managed, currently attached
        to a source, used by an analyzer,
          or referenced by an alert policy; detach/remove it first, then retry the delete.
        * `503 Service Unavailable`: Unable to verify analyzer/alert policy
        references because the dependent
          service did not respond in time.


                    
        **Security**
                    
        * This API requires authentication.
      parameters:
        - name: orgId
          in: path
          description: Organization ID.
          required: true
          schema:
            type: string
            format: uuid
          example: 77ffccee-4f7a-46cd-a000-8a2c254edb53
        - name: deviceId
          in: path
          description: "Device unique ID. Example: 74fe488d5d35."
          required: true
          schema:
            type: string
        - name: dataStreamId
          in: path
          description: Data stream unique ID.
          required: true
          schema:
            type: string
            format: uuid
          example: e033b4b3-36e0-4dbc-a6e4-1e77185402f4
      responses:
        "204":
          description: Data stream soft-deleted successfully.
        "404":
          description: Data stream not found.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ProblemDetails"
        "409":
          description: >-
            The data stream is system-managed, currently attached to a source,
            used by an analyzer, or referenced

            by an alert policy; detach/remove it first, then retry the delete.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ProblemDetails"
        "503":
          description: Unable to verify analyzer/alert policy references because the
            dependent service did not respond in time.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ProblemDetails"
      security:
        - Bearer: []
  /api/v1/orgs/{orgId}/devices/{deviceId}/analyzers:
    post:
      tags:
        - ___swagger_6-data-analyzer_swagger_json_Analyzers
      summary: Create device analyzer
      description: >-
        Create a new analyzer to transform input data stream values using a
        mathematical expression. Analyzers are always created disabled; use the
        enable/disable action to activate.


        **Request Body**


        * `name` (string, required): Human-readable analyzer name. Maximum
        length: 256.

        * `description` (string, optional): Analyzer description. Maximum
        length: 500.

        * `type` (AnalyzerType, required): Currently only `TransferFunction` is
        supported.

        * `inputParameters` (array, required): Binds input data streams to
        variable names used by the expression.

        * `config.expression` (string, required): Mathematical transformation
        expression.

        * `outputs` (array, required): Exactly one target data stream for a
        transfer function.


        **Responses**


        * `201 Created`: Analyzer created successfully.

        * `400 Bad Request`: Invalid request or expression syntax.

        * `404 Not Found`: Device or output data stream not found.

        * `409 Conflict`: The output data stream is already assigned to another
        analyzer.


        **Security**


        * This API requires authentication.
      parameters:
        - name: orgId
          in: path
          description: Organization ID.
          required: true
          schema:
            type: string
            format: uuid
        - name: deviceId
          in: path
          description: "Device unique ID. Example: `74fe488d5d35`."
          required: true
          schema:
            type: string
      requestBody:
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/AnalyzerCreateRequest"
            example:
              name: Temperature calibration
              description: Converts temperature values from Celsius to Fahrenheit.
              type: TransferFunction
              inputParameters:
                - parameterName: temperature
                  dataStreamId: 50b00fb7-a9f1-4b14-befa-c4c182d015a5
              config:
                expression: (temperature * 1.8) + 32
              outputs:
                - dataStreamId: 2cd839c3-f171-45b6-8734-7718f2eabbcd
      responses:
        "201":
          description: Created
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/AnalyzerDto"
              example:
                analyzerId: 3f2504e0-4f89-11d3-9a0c-0305e82c3301
                isEnabled: true
                name: Temperature calibration
                description: Converts temperature values from Celsius to Fahrenheit.
                type: TransferFunction
                inputParameters:
                  - parameterName: temperature
                    dataStreamId: 50b00fb7-a9f1-4b14-befa-c4c182d015a5
                config:
                  expression: (temperature * 1.8) + 32
                outputs:
                  - dataStreamId: 2cd839c3-f171-45b6-8734-7718f2eabbcd
                createdAt: 2026-02-06T08:30:00Z
                updatedAt: 2026-02-06T08:35:00Z
        "400":
          description: Invalid request or expression syntax.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ProblemDetails"
        "404":
          description: Device or output data stream not found.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ProblemDetails"
        "409":
          description: Output data stream already assigned.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ProblemDetails"
      security:
        - Bearer: []
    get:
      tags:
        - ___swagger_6-data-analyzer_swagger_json_Analyzers
      summary: List device analyzers
      description: >-
        Retrieve a paged list of all analyzers defined for a specific device.


        Use `sorting` to order results, `skipCount` to skip records, and
        `maxResultCount` to limit the page size.


        **Responses**


        * `200 OK`: Returns a paged list of analyzer definitions.

        * `404 Not Found`: Device not found.


        **Security**


        * This API requires authentication.
      parameters:
        - name: orgId
          in: path
          description: Organization ID.
          required: true
          schema:
            type: string
            format: uuid
        - name: deviceId
          in: path
          description: "Device unique ID. Example: `74fe488d5d35`."
          required: true
          schema:
            type: string
        - name: keyword
          in: query
          schema:
            type: string
        - name: sorting
          in: query
          schema:
            type: string
        - name: skipCount
          in: query
          schema:
            maximum: 2147483647
            minimum: 0
            type: integer
            format: int32
        - name: maxResultCount
          in: query
          schema:
            maximum: 2147483647
            minimum: 1
            type: integer
            format: int32
      responses:
        "200":
          description: OK
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/AnalyzerDtoPagedResultDto"
              example:
                totalCount: 2
                items:
                  - analyzerId: 3f2504e0-4f89-11d3-9a0c-0305e82c3301
                    isEnabled: true
                    name: Temperature calibration
                    description: null
                    type: TransferFunction
                    inputParameters:
                      - parameterName: temperature
                        dataStreamId: 50b00fb7-a9f1-4b14-befa-c4c182d015a5
                    config:
                      expression: (temperature * 1.8) + 32
                    outputs:
                      - dataStreamId: 2cd839c3-f171-45b6-8734-7718f2eabbcd
                    createdAt: 2026-02-06T08:30:00Z
                    updatedAt: 2026-02-06T08:35:00Z
                  - analyzerId: 7c9e6679-7425-40de-944b-e07fc1f90ae7
                    isEnabled: true
                    name: Pressure adjustment
                    description: null
                    type: TransferFunction
                    inputParameters:
                      - parameterName: pressure
                        dataStreamId: 230ce5ff-470e-47d9-b449-24b059c379d0
                    config:
                      expression: pressure * 1.01325
                    outputs:
                      - dataStreamId: abfd897d-88c5-4801-ac9d-74da299bbf9a
                    createdAt: 2026-02-06T09:00:00Z
                    updatedAt: null
        "404":
          description: Device not found.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ProblemDetails"
      security:
        - Bearer: []
  /api/v1/orgs/{orgId}/devices/{deviceId}/analyzers/{analyzerId}:
    get:
      tags:
        - ___swagger_6-data-analyzer_swagger_json_Analyzers
      summary: Get a device analyzer
      description: |-
        Retrieve details of a specific analyzer by its ID.

        **Responses**

        * `200 OK`: Returns the analyzer definition.
        * `404 Not Found`: Analyzer or device not found.

        **Security**

        * This API requires authentication.
      parameters:
        - name: orgId
          in: path
          description: Organization ID.
          required: true
          schema:
            type: string
            format: uuid
        - name: deviceId
          in: path
          description: "Device unique ID. Example: `74fe488d5d35`."
          required: true
          schema:
            type: string
        - name: analyzerId
          in: path
          description: Analyzer unique ID.
          required: true
          schema:
            type: string
            format: uuid
      responses:
        "200":
          description: OK
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/AnalyzerDto"
              example:
                analyzerId: 3f2504e0-4f89-11d3-9a0c-0305e82c3301
                isEnabled: true
                name: Temperature calibration
                description: Converts temperature values from Celsius to Fahrenheit.
                type: TransferFunction
                inputParameters:
                  - parameterName: temperature
                    dataStreamId: 50b00fb7-a9f1-4b14-befa-c4c182d015a5
                config:
                  expression: (temperature * 1.8) + 32
                outputs:
                  - dataStreamId: 2cd839c3-f171-45b6-8734-7718f2eabbcd
                createdAt: 2026-02-06T08:30:00Z
                updatedAt: 2026-02-06T08:35:00Z
        "404":
          description: Analyzer or device not found.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ProblemDetails"
      security:
        - Bearer: []
    put:
      tags:
        - ___swagger_6-data-analyzer_swagger_json_Analyzers
      summary: Update a device analyzer
      description: >-
        Replace all editable fields of a specific analyzer. The analyzer must be
        disabled first. Its enabled state is not part of this payload and
        remains unchanged.


        **Responses**


        * `200 OK`: Analyzer updated successfully.

        * `400 Bad Request`: Invalid request or expression syntax.

        * `404 Not Found`: Analyzer or output data stream not found.

        * `409 Conflict`: Analyzer is enabled, or an output stream is already
        used by another analyzer.


        **Security**


        * This API requires authentication.
      parameters:
        - name: orgId
          in: path
          description: Organization ID.
          required: true
          schema:
            type: string
            format: uuid
        - name: deviceId
          in: path
          description: "Device unique ID. Example: `74fe488d5d35`."
          required: true
          schema:
            type: string
        - name: analyzerId
          in: path
          description: Analyzer unique ID.
          required: true
          schema:
            type: string
            format: uuid
      requestBody:
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/AnalyzerUpdateRequest"
            example:
              name: Updated temperature calibration
              description: Uses the updated Celsius-to-Fahrenheit formula.
              type: TransferFunction
              inputParameters:
                - parameterName: temperature
                  dataStreamId: 50b00fb7-a9f1-4b14-befa-c4c182d015a5
              config:
                expression: ((temperature * 9) / 5) + 32
              outputs:
                - dataStreamId: 2cd839c3-f171-45b6-8734-7718f2eabbcd
      responses:
        "200":
          description: OK
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/AnalyzerDto"
              example:
                analyzerId: 3f2504e0-4f89-11d3-9a0c-0305e82c3301
                isEnabled: true
                name: Temperature calibration
                description: Converts temperature values from Celsius to Fahrenheit.
                type: TransferFunction
                inputParameters:
                  - parameterName: temperature
                    dataStreamId: 50b00fb7-a9f1-4b14-befa-c4c182d015a5
                config:
                  expression: (temperature * 1.8) + 32
                outputs:
                  - dataStreamId: 2cd839c3-f171-45b6-8734-7718f2eabbcd
                createdAt: 2026-02-06T08:30:00Z
                updatedAt: 2026-02-06T08:35:00Z
        "400":
          description: Invalid request or expression syntax.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ProblemDetails"
        "404":
          description: Analyzer or output data stream not found.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ProblemDetails"
        "409":
          description: Analyzer is enabled or output stream is already used.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ProblemDetails"
      security:
        - Bearer: []
    patch:
      tags:
        - ___swagger_6-data-analyzer_swagger_json_Analyzers
      summary: Partially update a device analyzer
      description: >-
        Update one or more fields of a specific analyzer. Only provided fields
        are updated; omitted fields retain their current values. The analyzer
        must be disabled first. Use the enable/disable action to change its
        enabled state.


        **Responses**


        * `200 OK`: Analyzer patched successfully.

        * `400 Bad Request`: Invalid request or expression syntax.

        * `404 Not Found`: Analyzer or output data stream not found.

        * `409 Conflict`: Analyzer is enabled, or an output stream is already
        used by another analyzer.


        **Security**


        * This API requires authentication.
      parameters:
        - name: orgId
          in: path
          description: Organization ID.
          required: true
          schema:
            type: string
            format: uuid
        - name: deviceId
          in: path
          description: "Device unique ID. Example: `74fe488d5d35`."
          required: true
          schema:
            type: string
        - name: analyzerId
          in: path
          description: Analyzer unique ID.
          required: true
          schema:
            type: string
            format: uuid
      requestBody:
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/AnalyzerPatchRequest"
      responses:
        "200":
          description: OK
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/AnalyzerDto"
              example:
                analyzerId: 3f2504e0-4f89-11d3-9a0c-0305e82c3301
                isEnabled: true
                name: Temperature calibration
                description: Converts temperature values from Celsius to Fahrenheit.
                type: TransferFunction
                inputParameters:
                  - parameterName: temperature
                    dataStreamId: 50b00fb7-a9f1-4b14-befa-c4c182d015a5
                config:
                  expression: (temperature * 1.8) + 32
                outputs:
                  - dataStreamId: 2cd839c3-f171-45b6-8734-7718f2eabbcd
                createdAt: 2026-02-06T08:30:00Z
                updatedAt: 2026-02-06T08:35:00Z
        "400":
          description: Invalid request or expression syntax.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ProblemDetails"
        "404":
          description: Analyzer or output data stream not found.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ProblemDetails"
        "409":
          description: Analyzer is enabled or output stream is already used.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ProblemDetails"
      security:
        - Bearer: []
    delete:
      tags:
        - ___swagger_6-data-analyzer_swagger_json_Analyzers
      summary: Delete a device analyzer
      description: >-
        Delete a specific analyzer from a device. The analyzer must be disabled
        first; use the enable/disable action before deleting it.


        **Responses**


        * `204 No Content`: Analyzer deleted successfully.

        * `404 Not Found`: Analyzer not found.

        * `409 Conflict`: Analyzer is enabled; disable it before deleting.


        **Security**


        * This API requires authentication.
      parameters:
        - name: orgId
          in: path
          description: Organization ID.
          required: true
          schema:
            type: string
            format: uuid
        - name: deviceId
          in: path
          description: "Device unique ID. Example: `74fe488d5d35`."
          required: true
          schema:
            type: string
        - name: analyzerId
          in: path
          description: Analyzer unique ID.
          required: true
          schema:
            type: string
            format: uuid
      responses:
        "204":
          description: No Content
        "404":
          description: Analyzer not found.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ProblemDetails"
        "409":
          description: Analyzer is enabled; disable it before deleting.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ProblemDetails"
      security:
        - Bearer: []
  /api/v1/orgs/{orgId}/devices/{deviceId}/analyzers/{analyzerId}:{action}:
    post:
      tags:
        - ___swagger_6-data-analyzer_swagger_json_Analyzers
      summary: Enable or disable an analyzer
      description: >-
        Set the enabled or disabled state of the specified analyzer.


        Valid actions are `enable` and `disable`. Command execution is tracked
        for audit purposes.


        **Responses**


        * `204 No Content`: Action executed successfully.

        * `404 Not Found`: Analyzer or device not found.

        * `409 Conflict`: Analyzer is already in the requested state.


        **Security**


        * This API requires authentication.
      parameters:
        - name: orgId
          in: path
          description: Organization ID.
          required: true
          schema:
            type: string
            format: uuid
        - name: deviceId
          in: path
          description: "Device unique ID. Example: `74fe488d5d35`."
          required: true
          schema:
            type: string
        - name: analyzerId
          in: path
          description: Analyzer unique ID.
          required: true
          schema:
            type: string
            format: uuid
        - name: action
          in: path
          description: "Analyzer lifecycle action. Possible values: `enable`, `disable`."
          required: true
          schema:
            $ref: "#/components/schemas/AnalyzerAction"
      responses:
        "204":
          description: No Content
        "404":
          description: Analyzer or device not found.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ProblemDetails"
        "409":
          description: Analyzer is already in the requested state.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ProblemDetails"
      security:
        - Bearer: []
  /api/v1/orgs/{orgId}/data-bridges:
    post:
      tags:
        - ___swagger_7-data-bridge_swagger_json_Data Bridges
      summary: Create bridge
      description: >-
        Create a bridge that subscribes to configured NATS bindings and
        publishes assembled JSON payloads to MQTT.


        Request body fields:

        - `mqtt.mqttBrokerConfigId`: existing MQTT broker configuration id.

        - `mqtt.outputTopic`: MQTT publish topic.

        - `mqtt.qos`: finite values `0`, `1`, `2`. Default: `0`.

        - `assemblyPolicy`: optional. Omit it to use all assembly defaults.

        - `assemblyPolicy.queueLimit`: default `100`.

        - `assemblyPolicy.timeoutSeconds`: default `5`.

        - `assemblyPolicy.onTimeout`: finite values `PublishPartial`,
        `DropPartial`. Default: `PublishPartial`.

        - `bindings[].deviceId`: required. Source device identifier (metadata;
        the enriched subject is keyed on `dataStreamId`).

        - `bindings[].dataStreamId`: required. Unique data stream identifier
        (GUID). Example: `e033b4b3-36e0-4dbc-a6e4-1e77185402f4`.

        - `bindings[].sourceFieldName`: default `valueObject`.

        - `bindings[].targetJsonPath`: rooted JSON path, for example
        `$.cpuTemp`.

        - `bindings[].dataType`: optional runtime type hint. Omit to use the
        source payload `valueType`. Supported values (case-insensitive):
        `number`, `double`, `float`, `decimal`, `integer`, `int`, `long`,
        `boolean`, `bool`, `datetime`, `string`. Unrecognized values keep the
        original JSON value.

        - `bindings[].requiredForAssembly`: finite values `true`, `false`.
        Default: `false`.


        Simple request example:

        ```json

        {
          "name": "bridge simple",
          "mqtt": {
            "mqttBrokerConfigId": "{{mqttConfigId}}",
            "outputTopic": "factory/site1/cpu"
          },
          "bindings": [
            {
              "deviceId": "{{deviceId}}",
              "dataStreamId": "e033b4b3-36e0-4dbc-a6e4-1e77185402f4",
              "targetJsonPath": "$.cpuTemp"
            }
          ]
        }

        ```
      parameters:
        - name: orgId
          in: path
          description: Organization identifier.
          required: true
          schema:
            type: string
            format: uuid
          example: 77ffccee-4f7a-46cd-a000-8a2c254edb53
      requestBody:
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/CreateBridgeRequest"
            example:
              name: bridge simple
              mqtt:
                mqttBrokerConfigId: 3fa85f64-5717-4562-b3fc-2c963f66afa6
                outputTopic: factory/site1/cpu
                qos: 0
              bindings:
                - deviceId: device-01
                  dataStreamId: e033b4b3-36e0-4dbc-a6e4-1e77185402f4
                  targetJsonPath: $.cpuTemp
                  requiredForAssembly: false
          text/json:
            schema:
              $ref: "#/components/schemas/CreateBridgeRequest"
            example:
              name: bridge simple
              mqtt:
                mqttBrokerConfigId: 3fa85f64-5717-4562-b3fc-2c963f66afa6
                outputTopic: factory/site1/cpu
                qos: 0
              bindings:
                - deviceId: device-01
                  dataStreamId: e033b4b3-36e0-4dbc-a6e4-1e77185402f4
                  targetJsonPath: $.cpuTemp
                  requiredForAssembly: false
          application/*+json:
            schema:
              $ref: "#/components/schemas/CreateBridgeRequest"
            example:
              name: bridge simple
              mqtt:
                mqttBrokerConfigId: 3fa85f64-5717-4562-b3fc-2c963f66afa6
                outputTopic: factory/site1/cpu
                qos: 0
              bindings:
                - deviceId: device-01
                  dataStreamId: e033b4b3-36e0-4dbc-a6e4-1e77185402f4
                  targetJsonPath: $.cpuTemp
                  requiredForAssembly: false
      responses:
        "201":
          description: Created
          content:
            text/plain:
              schema:
                $ref: "#/components/schemas/BridgeSummary"
            application/json:
              schema:
                $ref: "#/components/schemas/BridgeSummary"
            text/json:
              schema:
                $ref: "#/components/schemas/BridgeSummary"
        "400":
          description: Invalid bridge payload or validation error.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ProblemDetails"
              example:
                type: https://tools.ietf.org/html/rfc9110#section-15.5.1
                title: WEDA.Common.FormatError
                status: 400
                detail: Invalid bridge payload or validation error.
        "401":
          description: Authentication is missing or invalid.
        "403":
          description: The caller lacks the required role for this operation.
        "404":
          description: Referenced MQTT broker configuration was not found.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ProblemDetails"
              example:
                type: https://tools.ietf.org/html/rfc9110#section-15.5.5
                title: WEDA.DataBridge.BrokerConfigNotFound
                status: 404
                detail: Broker configuration with ID 3fa85f64-5717-4562-b3fc-2c963f66afa6 was
                  not found.
        "409":
          description: Bridge name, binding, or output schema conflicts with an existing
            bridge.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ProblemDetails"
              example:
                type: https://tools.ietf.org/html/rfc9110#section-15.5.10
                title: WEDA.DataBridge.DuplicateBridgeName
                status: 409
                detail: A bridge with name 'bridge simple' already exists in this tenant.
      security:
        - Bearer: []
    get:
      tags:
        - ___swagger_7-data-bridge_swagger_json_Data Bridges
      summary: List bridges
      description: >-
        Return bridges with paging.


        Query parameters:
          - `filter`: Optional name filter.
          - `skipCount`: Number of items to skip.
          - `maxResultCount`: Maximum number of items to return.
          - `sorting`: Optional sort expression in the form `PropertyName [ASC|DESC]`, for example `Name DESC`. Multiple properties are comma-separated. Sortable fields: `Name`, `IsEnabled`, `CreationTime`, `LastRuntimeStatus`. Default order is `Name ASC`. An unsupported sort field or direction returns `400 Bad Request`. Note: `LastRuntimeStatus` sorts alphabetically by status name, not by lifecycle order.
          Each item's `runtimeStatus` field is one of `Stopped`, `Starting`, `Running`, `Faulted`, `Stopping`.
      parameters:
        - name: orgId
          in: path
          description: Organization identifier.
          required: true
          schema:
            type: string
            format: uuid
          example: 77ffccee-4f7a-46cd-a000-8a2c254edb53
        - name: filter
          in: query
          schema:
            type: string
        - name: skipCount
          in: query
          schema:
            maximum: 2147483647
            minimum: 0
            type: integer
            format: int32
        - name: maxResultCount
          in: query
          schema:
            maximum: 100
            minimum: 1
            type: integer
            format: int32
        - name: sorting
          in: query
          schema:
            type: string
      responses:
        "200":
          description: OK
          content:
            text/plain:
              schema:
                $ref: "#/components/schemas/BridgeListItemPagedResult"
            application/json:
              schema:
                $ref: "#/components/schemas/BridgeListItemPagedResult"
            text/json:
              schema:
                $ref: "#/components/schemas/BridgeListItemPagedResult"
        "400":
          description: Invalid paging or filter values.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ProblemDetails"
              example:
                type: https://tools.ietf.org/html/rfc9110#section-15.5.1
                title: WEDA.Common.FormatError
                status: 400
                detail: Invalid paging or filter values.
        "401":
          description: Authentication is missing or invalid.
        "403":
          description: The caller lacks the required role for this operation.
      security:
        - Bearer: []
  /api/v1/orgs/{orgId}/data-bridges/{bridgeId}:
    get:
      tags:
        - ___swagger_7-data-bridge_swagger_json_Data Bridges
      summary: Get bridge
      description: >-
        Return the full bridge definition. The response mirrors the request
        shape with `mqtt`, `assemblyPolicy`, `bindings`, and `runtimeState`
        sections.


        The `runtimeState` section reports the current runtime snapshot:

        - `status`: one of `Stopped`, `Starting`, `Running`, `Faulted`,
        `Stopping`.

        - `lastPublishTime`: timestamp of the last published payload, or `null`
        if nothing has been published.

        - `queueDepth`: number of items currently buffered in memory.

        - `fault`: fault details, present only when `status` is `Faulted`;
        `null` otherwise.
      parameters:
        - name: orgId
          in: path
          description: Organization identifier.
          required: true
          schema:
            type: string
            format: uuid
          example: 77ffccee-4f7a-46cd-a000-8a2c254edb53
        - name: bridgeId
          in: path
          description: Bridge identifier.
          required: true
          schema:
            type: string
            format: uuid
      responses:
        "200":
          description: OK
          content:
            text/plain:
              schema:
                $ref: "#/components/schemas/BridgeDetail"
            application/json:
              schema:
                $ref: "#/components/schemas/BridgeDetail"
            text/json:
              schema:
                $ref: "#/components/schemas/BridgeDetail"
        "401":
          description: Authentication is missing or invalid.
        "403":
          description: The caller lacks the required role for this operation.
        "404":
          description: Bridge was not found.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ProblemDetails"
              example:
                type: https://tools.ietf.org/html/rfc9110#section-15.5.5
                title: WEDA.DataBridge.BridgeNotFound
                status: 404
                detail: Bridge with ID 3fa85f64-5717-4562-b3fc-2c963f66afa6 was not found.
      security:
        - Bearer: []
    put:
      tags:
        - ___swagger_7-data-bridge_swagger_json_Data Bridges
      summary: Update bridge
      description: >-
        Replace the bridge definition using the same nested request body as
        create bridge.


        Use:

        - `mqtt.mqttBrokerConfigId`, `mqtt.outputTopic`, `mqtt.qos`

        - `assemblyPolicy.queueLimit`, `assemblyPolicy.timeoutSeconds`,
        `assemblyPolicy.onTimeout`

        - `bindings[].deviceId`, `bindings[].dataStreamId`,
        `bindings[].targetJsonPath`, `bindings[].requiredForAssembly`


        Defaults and finite values are the same as create bridge:

        - `mqtt.qos`: `0`, `1`, `2`; default `0`

        - `assemblyPolicy`: optional; omit it to use all assembly defaults

        - `assemblyPolicy.onTimeout`: `PublishPartial`, `DropPartial`; default
        `PublishPartial`

        - `bindings[].deviceId`: required; source device identifier (metadata)

        - `bindings[].dataStreamId`: required; unique data stream identifier
        (GUID)

        - `bindings[].sourceFieldName`: default `valueObject`

        - `bindings[].dataType`: optional runtime type hint; omit to use source
        payload `valueType`. Supported values (case-insensitive): `number`,
        `double`, `float`, `decimal`, `integer`, `int`, `long`, `boolean`,
        `bool`, `datetime`, `string`. Unrecognized values keep the original JSON
        value

        - `bindings[].requiredForAssembly`: `true`, `false`; default `false`


        Example:

        ```json

        {
          "name": "bridge updated",
          "mqtt": {
            "mqttBrokerConfigId": "{{mqttConfigId}}",
            "outputTopic": "factory/site1/gpu-cpu",
            "qos": 1
          },
          "assemblyPolicy": {
            "queueLimit": 100,
            "timeoutSeconds": 30,
            "onTimeout": "PublishPartial"
          },
          "bindings": [
            {
              "deviceId": "{{deviceId}}",
              "dataStreamId": "e033b4b3-36e0-4dbc-a6e4-1e77185402f4",
              "sourceFieldName": "valueObject",
              "targetJsonPath": "$.cpuTemp",
              "dataType": "number",
              "requiredForAssembly": true
            }
          ]
        }

        ```
      parameters:
        - name: orgId
          in: path
          description: Organization identifier.
          required: true
          schema:
            type: string
            format: uuid
          example: 77ffccee-4f7a-46cd-a000-8a2c254edb53
        - name: bridgeId
          in: path
          description: Bridge identifier.
          required: true
          schema:
            type: string
            format: uuid
      requestBody:
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/UpdateBridgeRequest"
            example:
              name: bridge updated
              mqtt:
                mqttBrokerConfigId: 3fa85f64-5717-4562-b3fc-2c963f66afa6
                outputTopic: factory/site1/gpu-cpu
                qos: 1
              bindings:
                - deviceId: device-01
                  dataStreamId: e033b4b3-36e0-4dbc-a6e4-1e77185402f4
                  sourceFieldName: valueObject
                  targetJsonPath: $.cpuTemp
                  dataType: number
                  requiredForAssembly: true
              assemblyPolicy:
                queueLimit: 100
                timeoutSeconds: 30
                onTimeout: PublishPartial
          text/json:
            schema:
              $ref: "#/components/schemas/UpdateBridgeRequest"
            example:
              name: bridge updated
              mqtt:
                mqttBrokerConfigId: 3fa85f64-5717-4562-b3fc-2c963f66afa6
                outputTopic: factory/site1/gpu-cpu
                qos: 1
              bindings:
                - deviceId: device-01
                  dataStreamId: e033b4b3-36e0-4dbc-a6e4-1e77185402f4
                  sourceFieldName: valueObject
                  targetJsonPath: $.cpuTemp
                  dataType: number
                  requiredForAssembly: true
              assemblyPolicy:
                queueLimit: 100
                timeoutSeconds: 30
                onTimeout: PublishPartial
          application/*+json:
            schema:
              $ref: "#/components/schemas/UpdateBridgeRequest"
            example:
              name: bridge updated
              mqtt:
                mqttBrokerConfigId: 3fa85f64-5717-4562-b3fc-2c963f66afa6
                outputTopic: factory/site1/gpu-cpu
                qos: 1
              bindings:
                - deviceId: device-01
                  dataStreamId: e033b4b3-36e0-4dbc-a6e4-1e77185402f4
                  sourceFieldName: valueObject
                  targetJsonPath: $.cpuTemp
                  dataType: number
                  requiredForAssembly: true
              assemblyPolicy:
                queueLimit: 100
                timeoutSeconds: 30
                onTimeout: PublishPartial
      responses:
        "200":
          description: OK
          content:
            text/plain:
              schema:
                $ref: "#/components/schemas/BridgeSummary"
            application/json:
              schema:
                $ref: "#/components/schemas/BridgeSummary"
            text/json:
              schema:
                $ref: "#/components/schemas/BridgeSummary"
        "400":
          description: Invalid bridge payload or validation error.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ProblemDetails"
              example:
                type: https://tools.ietf.org/html/rfc9110#section-15.5.1
                title: WEDA.Common.FormatError
                status: 400
                detail: Invalid bridge payload or validation error.
        "401":
          description: Authentication is missing or invalid.
        "403":
          description: The caller lacks the required role for this operation.
        "404":
          description: Bridge or referenced MQTT broker configuration was not found.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ProblemDetails"
              example:
                type: https://tools.ietf.org/html/rfc9110#section-15.5.5
                title: WEDA.DataBridge.BridgeNotFound
                status: 404
                detail: Bridge with ID 3fa85f64-5717-4562-b3fc-2c963f66afa6 was not found.
        "409":
          description: Bridge name, binding, or output schema conflicts with an existing
            bridge.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ProblemDetails"
              example:
                type: https://tools.ietf.org/html/rfc9110#section-15.5.10
                title: WEDA.DataBridge.DuplicateBridgeName
                status: 409
                detail: A bridge with name 'bridge simple' already exists in this tenant.
      security:
        - Bearer: []
    patch:
      tags:
        - ___swagger_7-data-bridge_swagger_json_Data Bridges
      summary: Patch bridge
      description: >-
        Partially update a bridge using the same object shape and field names as
        update bridge. Include only the fields that should change.


        Supported sections:

        - `name`

        - `mqtt.mqttBrokerConfigId`

        - `mqtt.outputTopic`

        - `mqtt.qos`

        - `assemblyPolicy.queueLimit`

        - `assemblyPolicy.timeoutSeconds`

        - `assemblyPolicy.onTimeout`

        - `bindings`


        When `bindings` is included, it replaces the full bindings array.


        Defaults and finite values are the same as create/update bridge:

        - `mqtt.qos`: `0`, `1`, `2`

        - `assemblyPolicy.onTimeout`: `PublishPartial`, `DropPartial`

        - `bindings[].sourceFieldName`: default `valueObject`

        - `bindings[].dataType`: omit to use source payload `valueType`

        - `bindings[].requiredForAssembly`: `true`, `false`; default `false`


        Example:

        ```json

        {
          "mqtt": {
            "outputTopic": "factory/site1/new-topic"
          },
          "assemblyPolicy": {
            "timeoutSeconds": 30
          }
        }

        ```
      parameters:
        - name: orgId
          in: path
          description: Organization identifier.
          required: true
          schema:
            type: string
            format: uuid
          example: 77ffccee-4f7a-46cd-a000-8a2c254edb53
        - name: bridgeId
          in: path
          description: Bridge identifier.
          required: true
          schema:
            type: string
            format: uuid
      requestBody:
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/PatchBridgeRequest"
            example:
              mqtt:
                outputTopic: factory/site1/new-topic
              assemblyPolicy:
                timeoutSeconds: 30
      responses:
        "200":
          description: OK
          content:
            text/plain:
              schema:
                $ref: "#/components/schemas/BridgeSummary"
            application/json:
              schema:
                $ref: "#/components/schemas/BridgeSummary"
            text/json:
              schema:
                $ref: "#/components/schemas/BridgeSummary"
        "400":
          description: Invalid patch document, invalid value, or validation error.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ProblemDetails"
              example:
                type: https://tools.ietf.org/html/rfc9110#section-15.5.1
                title: WEDA.Common.FormatError
                status: 400
                detail: Invalid patch document, invalid value, or validation error.
        "401":
          description: Authentication is missing or invalid.
        "403":
          description: The caller lacks the required role for this operation.
        "404":
          description: Bridge or referenced MQTT broker configuration was not found.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ProblemDetails"
              example:
                type: https://tools.ietf.org/html/rfc9110#section-15.5.5
                title: WEDA.DataBridge.BridgeNotFound
                status: 404
                detail: Bridge with ID 3fa85f64-5717-4562-b3fc-2c963f66afa6 was not found.
        "409":
          description: Bridge name, binding, or output schema conflicts with an existing
            bridge.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ProblemDetails"
              example:
                type: https://tools.ietf.org/html/rfc9110#section-15.5.10
                title: WEDA.DataBridge.DuplicateBridgeName
                status: 409
                detail: A bridge with name 'bridge simple' already exists in this tenant.
      security:
        - Bearer: []
    delete:
      tags:
        - ___swagger_7-data-bridge_swagger_json_Data Bridges
      summary: Delete bridge
      description: Delete a bridge. Enabled bridges must be disabled before deletion.
      parameters:
        - name: orgId
          in: path
          description: Organization identifier.
          required: true
          schema:
            type: string
            format: uuid
          example: 77ffccee-4f7a-46cd-a000-8a2c254edb53
        - name: bridgeId
          in: path
          description: Bridge identifier.
          required: true
          schema:
            type: string
            format: uuid
      responses:
        "204":
          description: No Content
        "400":
          description: Bridge is enabled. Disable it before deleting.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ProblemDetails"
              example:
                type: https://tools.ietf.org/html/rfc9110#section-15.5.1
                title: WEDA.DataBridge.BridgeEnabled
                status: 400
                detail: Cannot modify bridge ID 3fa85f64-5717-4562-b3fc-2c963f66afa6 because it
                  is currently enabled. Disable it first.
        "401":
          description: Authentication is missing or invalid.
        "403":
          description: The caller lacks the required role for this operation.
        "404":
          description: Bridge was not found.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ProblemDetails"
              example:
                type: https://tools.ietf.org/html/rfc9110#section-15.5.5
                title: WEDA.DataBridge.BridgeNotFound
                status: 404
                detail: Bridge with ID 3fa85f64-5717-4562-b3fc-2c963f66afa6 was not found.
      security:
        - Bearer: []
  /api/v1/orgs/{orgId}/data-bridges/{bridgeId}:{action}:
    post:
      tags:
        - ___swagger_7-data-bridge_swagger_json_Data Bridges
      summary: Enable or disable bridge
      description: >-
        Execute an enable or disable action on the bridge.


        Valid actions:

        - `enable`: starts bridge runtime processing. The linked MQTT broker
        configuration and stored credentials are verified before the worker
        starts.

        - `disable`: stops bridge runtime processing and unsubscribes the worker
        from active NATS subjects.


        Returns `204 No Content` with no body. Use `GET
        orgs/{orgId}/data-bridges/{bridgeId}` to verify the current runtime
        state.
      parameters:
        - name: orgId
          in: path
          description: Organization identifier.
          required: true
          schema:
            type: string
            format: uuid
          example: 77ffccee-4f7a-46cd-a000-8a2c254edb53
        - name: bridgeId
          in: path
          description: Bridge identifier.
          required: true
          schema:
            type: string
            format: uuid
        - name: action
          in: path
          description: "Bridge lifecycle action to execute. Possible values: enable,
            disable"
          required: true
          schema:
            enum:
              - enable
              - disable
            type: string
          example: enable
      responses:
        "204":
          description: No Content
        "400":
          description: Unknown action, or linked MQTT broker configuration failed live
            connection validation.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ProblemDetails"
              example:
                type: https://tools.ietf.org/html/rfc9110#section-15.5.1
                title: WEDA.DataBridge.InvalidBrokerCredentials
                status: 400
                detail: Invalid broker credentials or authentication configuration provided.
        "401":
          description: Authentication is missing or invalid.
        "403":
          description: The caller lacks the required role for this operation.
        "404":
          description: Bridge or linked MQTT broker configuration was not found.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ProblemDetails"
              example:
                type: https://tools.ietf.org/html/rfc9110#section-15.5.5
                title: WEDA.DataBridge.BridgeNotFound
                status: 404
                detail: Bridge with ID 3fa85f64-5717-4562-b3fc-2c963f66afa6 was not found.
        "409":
          description: Bridge is already in the requested state or cannot transition in
            its current state.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ProblemDetails"
              example:
                type: https://tools.ietf.org/html/rfc9110#section-15.5.10
                title: WEDA.DataBridge.BridgeEnabled
                status: 409
                detail: Bridge is already enabled.
      security:
        - Bearer: []
  /api/v1/orgs/{orgId}/data-bridges/mqtt-broker-configs:
    post:
      tags:
        - ___swagger_7-data-bridge_swagger_json_Data Bridges Components
      summary: Create MQTT broker config
      description: |-
        Create a reusable MQTT broker configuration.

        Finite values:
        - `authType`: `UsernamePassword`
        - `mqttProtocolVersion`: `V310`, `V311`, `V500`
        - `checkConnection`: `true`, `false`

        Defaults:
        - `authType`: `UsernamePassword`
        - `mqttProtocolVersion`: `V311`
        - `checkConnection`: `false`
        - `keepAliveInterval`: omitted stores `null`; runtime uses `60s`
        - `reconnectInterval`: omitted stores `null`; runtime uses `5s`

        Example:
        ```json
        {
          "name": "mqtt local",
          "brokerEndpoint": "localhost:1883",
          "authType": "UsernamePassword",
          "brokerCredentials": {
            "username": "user",
            "password": "pass"
          },
          "keepAliveInterval": "60s",
          "reconnectInterval": "5s",
          "mqttProtocolVersion": "V311",
          "checkConnection": false
        }
        ```
      parameters:
        - name: orgId
          in: path
          description: Organization identifier.
          required: true
          schema:
            type: string
            format: uuid
          example: 77ffccee-4f7a-46cd-a000-8a2c254edb53
      requestBody:
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/CreateMqttBrokerConfigRequest"
            example:
              name: mqtt local
              brokerEndpoint: localhost:1883
              authType: UsernamePassword
              brokerCredentials:
                username: user
                password: pass
              keepAliveInterval: 60s
              reconnectInterval: 5s
              mqttProtocolVersion: 0
              checkConnection: false
          text/json:
            schema:
              $ref: "#/components/schemas/CreateMqttBrokerConfigRequest"
            example:
              name: mqtt local
              brokerEndpoint: localhost:1883
              authType: UsernamePassword
              brokerCredentials:
                username: user
                password: pass
              keepAliveInterval: 60s
              reconnectInterval: 5s
              mqttProtocolVersion: 0
              checkConnection: false
          application/*+json:
            schema:
              $ref: "#/components/schemas/CreateMqttBrokerConfigRequest"
            example:
              name: mqtt local
              brokerEndpoint: localhost:1883
              authType: UsernamePassword
              brokerCredentials:
                username: user
                password: pass
              keepAliveInterval: 60s
              reconnectInterval: 5s
              mqttProtocolVersion: 0
              checkConnection: false
      responses:
        "201":
          description: MQTT broker configuration created.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/MqttBrokerConfig"
        "400":
          description: Invalid configuration payload or connection check failed.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ProblemDetails"
              example:
                type: https://tools.ietf.org/html/rfc9110#section-15.5.1
                title: WEDA.DataBridge.InvalidBrokerCredentials
                status: 400
                detail: Invalid broker credentials or authentication configuration provided.
        "401":
          description: Authentication is missing or invalid.
        "403":
          description: The caller lacks the required role for this operation.
        "409":
          description: Broker configuration name already exists.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ProblemDetails"
              example:
                type: https://tools.ietf.org/html/rfc9110#section-15.5.10
                title: WEDA.DataBridge.DuplicateBrokerConfigName
                status: 409
                detail: A broker configuration with name 'mqtt local' already exists in this
                  tenant.
      security:
        - Bearer: []
    get:
      tags:
        - ___swagger_7-data-bridge_swagger_json_Data Bridges Components
      summary: List MQTT broker configs
      description: >-
        Return MQTT broker configurations with paging.


        Query parameters:

        - `filter`: Optional name filter.

        - `skipCount`: Number of items to skip.

        - `maxResultCount`: Maximum number of items to return.

        - `sorting`: Optional sort expression in the form `PropertyName
        [ASC|DESC]`, for example `Name DESC`. Multiple properties are
        comma-separated. Sortable fields: `Name`, `CreationTime`,
        `BrokerEndpoint`. Default order is `Name ASC`. An unsupported sort field
        or direction returns `400 Bad Request`.
      parameters:
        - name: orgId
          in: path
          description: Organization identifier.
          required: true
          schema:
            type: string
            format: uuid
          example: 77ffccee-4f7a-46cd-a000-8a2c254edb53
        - name: filter
          in: query
          schema:
            type: string
        - name: sorting
          in: query
          schema:
            type: string
        - name: skipCount
          in: query
          schema:
            maximum: 2147483647
            minimum: 0
            type: integer
            format: int32
        - name: maxResultCount
          in: query
          schema:
            maximum: 100
            minimum: 1
            type: integer
            format: int32
      responses:
        "200":
          description: OK
          content:
            text/plain:
              schema:
                $ref: "#/components/schemas/MqttBrokerConfigListItemPagedResult"
            application/json:
              schema:
                $ref: "#/components/schemas/MqttBrokerConfigListItemPagedResult"
            text/json:
              schema:
                $ref: "#/components/schemas/MqttBrokerConfigListItemPagedResult"
        "400":
          description: Invalid paging or sorting values.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ProblemDetails"
              example:
                type: https://tools.ietf.org/html/rfc9110#section-15.5.1
                title: WEDA.Common.FormatError
                status: 400
                detail: Invalid paging or sorting values.
        "401":
          description: Authentication is missing or invalid.
        "403":
          description: The caller lacks the required role for this operation.
      security:
        - Bearer: []
  /api/v1/orgs/{orgId}/data-bridges/mqtt-broker-configs/{mqttConfigId}:
    get:
      tags:
        - ___swagger_7-data-bridge_swagger_json_Data Bridges Components
      summary: Get MQTT broker config
      description: Return a single MQTT broker configuration. Credential secrets are
        not returned in clear text.
      parameters:
        - name: orgId
          in: path
          description: Organization identifier.
          required: true
          schema:
            type: string
            format: uuid
          example: 77ffccee-4f7a-46cd-a000-8a2c254edb53
        - name: mqttConfigId
          in: path
          description: MQTT broker configuration identifier.
          required: true
          schema:
            type: string
            format: uuid
      responses:
        "200":
          description: OK
          content:
            text/plain:
              schema:
                $ref: "#/components/schemas/MqttBrokerConfig"
            application/json:
              schema:
                $ref: "#/components/schemas/MqttBrokerConfig"
            text/json:
              schema:
                $ref: "#/components/schemas/MqttBrokerConfig"
        "401":
          description: Authentication is missing or invalid.
        "403":
          description: The caller lacks the required role for this operation.
        "404":
          description: MQTT broker configuration was not found.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ProblemDetails"
              example:
                type: https://tools.ietf.org/html/rfc9110#section-15.5.5
                title: WEDA.DataBridge.BrokerConfigNotFound
                status: 404
                detail: Broker configuration with ID 3fa85f64-5717-4562-b3fc-2c963f66afa6 was
                  not found.
      security:
        - Bearer: []
    put:
      tags:
        - ___swagger_7-data-bridge_swagger_json_Data Bridges Components
      summary: Update MQTT broker config
      description: >-
        Update broker endpoint and protocol settings for an existing MQTT broker
        configuration.


        Authentication type and credential secrets are updated only by the
        credentials endpoint.


        Finite values:

        - `mqttProtocolVersion`: `V310`, `V311`, `V500`

        - `checkConnection`: `true`, `false`


        When `checkConnection` is `true`, the updated endpoint and protocol are
        verified using the stored credentials. The request fails if credentials
        are missing or the broker cannot be reached.


        Defaults:

        - `mqttProtocolVersion`: `V311`

        - `checkConnection`: `false`

        - `keepAliveInterval`: omitted stores `null`; runtime uses `60s`

        - `reconnectInterval`: omitted stores `null`; runtime uses `5s`


        Example:

        ```json

        {
          "name": "mqtt local updated",
          "brokerEndpoint": "localhost:1883",
          "keepAliveInterval": "60s",
          "reconnectInterval": "5s",
          "mqttProtocolVersion": "V311",
          "checkConnection": false
        }

        ```
      parameters:
        - name: orgId
          in: path
          description: Organization identifier.
          required: true
          schema:
            type: string
            format: uuid
          example: 77ffccee-4f7a-46cd-a000-8a2c254edb53
        - name: mqttConfigId
          in: path
          description: MQTT broker configuration identifier.
          required: true
          schema:
            type: string
            format: uuid
      requestBody:
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/UpdateMqttBrokerConfigRequest"
            example:
              name: mqtt local updated
              brokerEndpoint: localhost:1883
              keepAliveInterval: 60s
              reconnectInterval: 5s
              mqttProtocolVersion: 0
              checkConnection: false
          text/json:
            schema:
              $ref: "#/components/schemas/UpdateMqttBrokerConfigRequest"
            example:
              name: mqtt local updated
              brokerEndpoint: localhost:1883
              keepAliveInterval: 60s
              reconnectInterval: 5s
              mqttProtocolVersion: 0
              checkConnection: false
          application/*+json:
            schema:
              $ref: "#/components/schemas/UpdateMqttBrokerConfigRequest"
            example:
              name: mqtt local updated
              brokerEndpoint: localhost:1883
              keepAliveInterval: 60s
              reconnectInterval: 5s
              mqttProtocolVersion: 0
              checkConnection: false
      responses:
        "200":
          description: OK
          content:
            text/plain:
              schema:
                $ref: "#/components/schemas/MqttBrokerConfig"
            application/json:
              schema:
                $ref: "#/components/schemas/MqttBrokerConfig"
            text/json:
              schema:
                $ref: "#/components/schemas/MqttBrokerConfig"
        "400":
          description: Invalid configuration payload or connection check failed.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ProblemDetails"
              example:
                type: https://tools.ietf.org/html/rfc9110#section-15.5.1
                title: WEDA.DataBridge.InvalidBrokerCredentials
                status: 400
                detail: Invalid broker credentials or authentication configuration provided.
        "401":
          description: Authentication is missing or invalid.
        "403":
          description: The caller lacks the required role for this operation.
        "404":
          description: MQTT broker configuration was not found.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ProblemDetails"
              example:
                type: https://tools.ietf.org/html/rfc9110#section-15.5.5
                title: WEDA.DataBridge.BrokerConfigNotFound
                status: 404
                detail: Broker configuration with ID 3fa85f64-5717-4562-b3fc-2c963f66afa6 was
                  not found.
        "409":
          description: Broker configuration name already exists.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ProblemDetails"
              example:
                type: https://tools.ietf.org/html/rfc9110#section-15.5.10
                title: WEDA.DataBridge.DuplicateBrokerConfigName
                status: 409
                detail: A broker configuration with name 'mqtt local' already exists in this
                  tenant.
      security:
        - Bearer: []
    delete:
      tags:
        - ___swagger_7-data-bridge_swagger_json_Data Bridges Components
      summary: Delete MQTT broker config
      description: Delete an MQTT broker configuration. Configurations linked to
        existing bridges cannot be removed.
      parameters:
        - name: orgId
          in: path
          description: Organization identifier.
          required: true
          schema:
            type: string
            format: uuid
          example: 77ffccee-4f7a-46cd-a000-8a2c254edb53
        - name: mqttConfigId
          in: path
          description: MQTT broker configuration identifier.
          required: true
          schema:
            type: string
            format: uuid
      responses:
        "204":
          description: No Content
        "400":
          description: MQTT broker configuration is still linked to one or more bridges.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ProblemDetails"
              example:
                type: https://tools.ietf.org/html/rfc9110#section-15.5.1
                title: WEDA.DataBridge.BrokerConfigIsBeingUsed
                status: 400
                detail: Broker configuration with ID 3fa85f64-5717-4562-b3fc-2c963f66afa6 is
                  currently being used.
        "401":
          description: Authentication is missing or invalid.
        "403":
          description: The caller lacks the required role for this operation.
        "404":
          description: MQTT broker configuration was not found.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ProblemDetails"
              example:
                type: https://tools.ietf.org/html/rfc9110#section-15.5.5
                title: WEDA.DataBridge.BrokerConfigNotFound
                status: 404
                detail: Broker configuration with ID 3fa85f64-5717-4562-b3fc-2c963f66afa6 was
                  not found.
      security:
        - Bearer: []
  /api/v1/orgs/{orgId}/data-bridges/mqtt-broker-configs/{mqttConfigId}/credentials:
    patch:
      tags:
        - ___swagger_7-data-bridge_swagger_json_Data Bridges Components
      summary: Update MQTT broker credentials
      description: >-
        Rotate stored credentials for an MQTT broker configuration.


        Finite values:

        - `authType`: `UsernamePassword`. This field is required and is reserved
        for future authentication types; `UsernamePassword` is currently the
        only supported value.

        - `checkConnection`: `true`, `false`


        Default:

        - `checkConnection`: `false`


        Example:

        ```json

        {
          "authType": "UsernamePassword",
          "brokerCredentials": {
            "username": "new-user",
            "password": "new-pass"
          },
          "checkConnection": false
        }

        ```
      parameters:
        - name: orgId
          in: path
          description: Organization identifier.
          required: true
          schema:
            type: string
            format: uuid
          example: 77ffccee-4f7a-46cd-a000-8a2c254edb53
        - name: mqttConfigId
          in: path
          description: MQTT broker configuration identifier.
          required: true
          schema:
            type: string
            format: uuid
      requestBody:
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/UpdateBrokerCredentialsRequest"
            example:
              authType: UsernamePassword
              brokerCredentials:
                username: new-user
                password: new-pass
              checkConnection: false
          text/json:
            schema:
              $ref: "#/components/schemas/UpdateBrokerCredentialsRequest"
            example:
              authType: UsernamePassword
              brokerCredentials:
                username: new-user
                password: new-pass
              checkConnection: false
          application/*+json:
            schema:
              $ref: "#/components/schemas/UpdateBrokerCredentialsRequest"
            example:
              authType: UsernamePassword
              brokerCredentials:
                username: new-user
                password: new-pass
              checkConnection: false
      responses:
        "204":
          description: No Content
        "400":
          description: Invalid credential payload or connection check failed.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ProblemDetails"
              example:
                type: https://tools.ietf.org/html/rfc9110#section-15.5.1
                title: WEDA.DataBridge.InvalidBrokerCredentials
                status: 400
                detail: Invalid broker credentials or authentication configuration provided.
        "401":
          description: Authentication is missing or invalid.
        "403":
          description: The caller lacks the required role for this operation.
        "404":
          description: MQTT broker configuration was not found.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ProblemDetails"
              example:
                type: https://tools.ietf.org/html/rfc9110#section-15.5.5
                title: WEDA.DataBridge.BrokerConfigNotFound
                status: 404
                detail: Broker configuration with ID 3fa85f64-5717-4562-b3fc-2c963f66afa6 was
                  not found.
      security:
        - Bearer: []
  /api/v1/orgs/{orgId}/alert-events:
    get:
      tags:
        - ___swagger_8-alert-policy_swagger_json_AlertEvents
      summary: List alert events
      description: >-
        Retrieve a paginated list of alert events (fired alerts) for an
        organization.

        An alert event is created when an alert policy's trigger condition holds
        for its configured debounce

        delay; it is later resolved automatically (once the reset condition
        holds for the delay) or

        acknowledged manually. All filters are optional and combined with
        logical AND.


        **Parameters**


        * `status` (enum, optional): Filter by event status. Valid values:
        `Firing` (currently active, not yet resolved), `Acknowledged` (manually
        acknowledged, still open), `Resolved` (closed, either automatically or
        manually).

        * `alertPolicyId` (UUID, optional): Filter by the alert policy that
        fired the event.

        * `deviceId` (string, optional): Filter by the device the triggering
        data stream belongs to.

        * `start` (datetime, optional): Return events fired on or after this
        timestamp (ISO 8601 UTC).

        * `end` (datetime, optional): Return events fired before this timestamp
        (ISO 8601 UTC).

        * `sorting` (string, optional, default: `FiredTime DESC`): Sort
        expression, e.g. `firedTime asc`.

        * `skipCount` (integer, optional, default: 0): Number of records to
        skip.

        * `maxResultCount` (integer, optional, default: 10): Maximum records to
        return.


        **Responses**


        * `200 OK`: Returns a paginated list of alert events. Each item includes
        `alertEventId`, `alertPolicyId`,

        `policyName` (a point-in-time snapshot of the policy name at fire time,
        unaffected by later renames),

        `deviceId`, `dataStreamId`, `status`, `triggeredValue` (the data stream
        value that caused the trigger),

        `alertLevel` (the trigger condition at fire time), `firedTime`, and —
        once applicable —

        `acknowledgedTime`/`acknowledgedBy` or `resolvedTime`/`resolvedBy`
        (`resolvedBy` is `null` when the

        event was resolved automatically rather than acknowledged by a person).
      parameters:
        - name: orgId
          in: path
          required: true
          schema:
            type: string
            format: uuid
        - name: status
          in: query
          description: Filter by event status
          schema:
            $ref: "#/components/schemas/AlertEventStatus"
        - name: alertPolicyId
          in: query
          description: Filter by alert policy ID
          schema:
            type: string
            description: Filter by alert policy ID
            format: uuid
        - name: deviceId
          in: query
          description: Filter by device ID
          schema:
            type: string
            description: Filter by device ID
        - name: start
          in: query
          description: Filter events fired at or after this timestamp (ISO 8601 UTC)
          schema:
            type: string
            description: Filter events fired at or after this timestamp (ISO 8601 UTC)
            format: date-time
        - name: end
          in: query
          description: Filter events fired before this timestamp (ISO 8601 UTC)
          schema:
            type: string
            description: Filter events fired before this timestamp (ISO 8601 UTC)
            format: date-time
        - name: sorting
          in: query
          schema:
            type: string
        - name: skipCount
          in: query
          schema:
            maximum: 2147483647
            minimum: 0
            type: integer
            format: int32
        - name: maxResultCount
          in: query
          schema:
            maximum: 2147483647
            minimum: 1
            type: integer
            format: int32
      responses:
        "200":
          description: OK
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/PagedResultDtoOfAlertEventDto"
              example:
                totalCount: 1
                items:
                  - alertEventId: 8f14e45f-ceea-4d6f-b4cf-8fef53ea6b98
                    alertPolicyId: 3f2504e0-4f89-11d3-9a0c-0305e82c3301
                    policyName: WaterLevel alert policy
                    deviceId: 9F75ABDA56C3
                    dataStreamId: 1b4e28ba-2fa1-11d2-883f-0016d3cca427
                    status: 2
                    triggeredValue: "78"
                    alertLevel: ">=70"
                    firedTime: 2026-07-16T09:00:00Z
                    acknowledgedTime: null
                    acknowledgedBy: null
                    resolvedTime: 2026-07-16T09:10:00Z
                    resolvedBy: null
      security:
        - Bearer: []
  /api/v1/orgs/{orgId}/alert-policies:
    post:
      tags:
        - ___swagger_8-alert-policy_swagger_json_AlertPolicies
      summary: Create alert policy
      description: >-
        Create a new alert policy definition. New policies always start
        disabled;

        call the enable/disable action afterwards to activate evaluation.
        Device/data-stream bindings are

        managed separately via the `data-streams` sub-resource, not part of this
        payload.


        **Request Body**


        * `policyName` (string, required): Policy name. Must be unique within
        the org (among non-deleted policies). Ex: `WaterLevel alert policy`.

        * `description` (string, optional): Policy description. Max length: 500.

        * `alertLevel` (string, required): Trigger threshold expression,
        evaluated against the incoming data stream value. Ex: `>=70`.

        * `alertResetLevel` (string, required): Reset/release threshold
        expression. Ex: `<65`.

        * `delay` (integer, optional, default: 0): Debounce delay in seconds.
        The condition must hold continuously for this many seconds before an
        alert is actually fired or released; `0` disables debouncing
        (fires/releases almost immediately). Must be non-negative.

        * `notification` (object, optional): Notification configuration for this
        policy. Omit to leave the policy without any notification target (no
        message is sent when it fires).
          * `channelIds` (string[], required): Existing channel IDs to notify. Ex: `channel_3fa85f64-5717-4562-b3fc-2c963f66afa6`. Every ID must belong to an existing channel in this org.
          * `recipients` (array, required): Recipients for the notification. Each item: `name` (string, optional), `target` (string, required), `type` (string, required — `to`/`cc`/`bcc`).
          * `templateId` (string, optional): Existing template ID to render. Ex: `tmpl_7fa85f64-5717-4562-b3fc-2c963f66afa6`. Use together with `variables`; mutually exclusive with `subject`/`content` (providing both results in `400`).
          * `variables` (object, optional): Key/value substitutions used when rendering the template. Ex: `{"threshold": "70"}`. Only meaningful together with `templateId`.
          * `subject` (string, optional): Literal subject line, used instead of a template. Mutually exclusive with `templateId`/`variables`.
          * `content` (string, optional): Literal message content, used instead of a template. Mutually exclusive with `templateId`/`variables`.

        **Responses**


        * `201 Created`: Alert policy created successfully.

        * `400 Bad Request`: Validation error (missing required field, invalid
        range, or `templateId`+`subject`/`content` both provided).

        * `404 Not Found`: A `channelIds` entry or `templateId` does not exist
        in this org.

        * `409 Conflict`: An alert policy with the same `policyName` already
        exists in this org.
      parameters:
        - name: orgId
          in: path
          required: true
          schema:
            type: string
            format: uuid
      requestBody:
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/AlertPolicyCreateRequest"
            example:
              policyName: WaterLevel alert policy
              description: Alerts when the water level exceeds the configured threshold.
              alertLevel: ">=70"
              alertResetLevel: <65
              delay: 5
              notification:
                channelIds:
                  - channel_3fa85f64-5717-4562-b3fc-2c963f66afa6
                templateId: tmpl_7fa85f64-5717-4562-b3fc-2c963f66afa6
                recipients:
                  - name: Ops Team
                    target: ops-team@example.com
                    type: to
                variables:
                  threshold: "70"
                subject: null
                content: null
      responses:
        "201":
          description: Created
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/AlertPolicyDto"
              example:
                alertPolicyId: 3f2504e0-4f89-11d3-9a0c-0305e82c3301
                policyName: WaterLevel alert policy
                description: Alerts when the water level exceeds the configured threshold.
                alertLevel: ">=70"
                alertResetLevel: <65
                delay: 5
                enabled: true
                createdAt: 2026-07-02T09:00:00Z
                createdBy: null
                updatedAt: 2026-07-02T09:30:00Z
                updatedBy: null
                notification:
                  channelIds:
                    - channel_3fa85f64-5717-4562-b3fc-2c963f66afa6
                  templateId: tmpl_7fa85f64-5717-4562-b3fc-2c963f66afa6
                  recipients:
                    - name: Ops Team
                      target: ops-team@example.com
                      type: to
                  variables:
                    threshold: "70"
                  subject: null
                  content: null
      security:
        - Bearer: []
    get:
      tags:
        - ___swagger_8-alert-policy_swagger_json_AlertPolicies
      summary: List alert policies
      description: >-
        Retrieve a paginated list of alert policies for the org.


        **Parameters**


        * `keyword` (string, optional): Fuzzy match against `policyName`.

        * `dataStreamId` (UUID, optional): Reverse lookup — return only the
        policies attached to this data stream, instead of filtering the policy's
        own fields.

        * `sorting` (string, optional, default: sorted by creation time): Sort
        expression using the same field names as the response body, e.g.
        `policyName desc` or `createdAt desc`. Supports comma-separated
        multi-field sorting, e.g. `createdAt desc, policyName`.

        * `skipCount` (integer, optional, default: 0): Number of records to
        skip.

        * `maxResultCount` (integer, optional, default: 10): Maximum records to
        return.


        **Responses**


        * `200 OK`: Returns a paginated list of alert policies.
      parameters:
        - name: orgId
          in: path
          required: true
          schema:
            type: string
            format: uuid
        - name: keyword
          in: query
          description: Keyword for fuzzy search across the PolicyName field
          schema:
            type: string
            description: Keyword for fuzzy search across the PolicyName field
        - name: dataStreamId
          in: query
          description: Return only policies attached to this data stream (reverse of the
            policy's data-streams list)
          schema:
            type: string
            description: Return only policies attached to this data stream (reverse of the
              policy's data-streams list)
            format: uuid
        - name: sorting
          in: query
          schema:
            type: string
        - name: skipCount
          in: query
          schema:
            maximum: 2147483647
            minimum: 0
            type: integer
            format: int32
        - name: maxResultCount
          in: query
          schema:
            maximum: 2147483647
            minimum: 1
            type: integer
            format: int32
      responses:
        "200":
          description: OK
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/PagedResultDtoOfAlertPolicyDto"
              example:
                totalCount: 2
                items:
                  - alertPolicyId: 3f2504e0-4f89-11d3-9a0c-0305e82c3301
                    policyName: WaterLevel alert policy
                    description: Alerts when the water level exceeds the configured threshold.
                    alertLevel: ">=70"
                    alertResetLevel: <65
                    delay: 5
                    enabled: true
                    createdAt: 2026-07-02T09:00:00Z
                    createdBy: null
                    updatedAt: 2026-07-02T09:30:00Z
                    updatedBy: null
                    notification:
                      channelIds:
                        - channel_3fa85f64-5717-4562-b3fc-2c963f66afa6
                      templateId: tmpl_7fa85f64-5717-4562-b3fc-2c963f66afa6
                      recipients:
                        - name: Ops Team
                          target: ops-team@example.com
                          type: to
                      variables: null
                      subject: null
                      content: null
                  - alertPolicyId: 7c9e6679-7425-40de-944b-e07fc1f90ae7
                    policyName: HighTemperature policy
                    description: null
                    alertLevel: ">=90"
                    alertResetLevel: <85
                    delay: 0
                    enabled: false
                    createdAt: 2026-06-28T12:00:00Z
                    createdBy: null
                    updatedAt: 2026-07-01T08:15:00Z
                    updatedBy: null
                    notification: null
      security:
        - Bearer: []
  /api/v1/orgs/{orgId}/alert-policies/{alertPolicyId}:
    get:
      tags:
        - ___swagger_8-alert-policy_swagger_json_AlertPolicies
      summary: Get alert policy by ID
      description: >-
        Retrieve detailed information of a specific alert policy.


        **Parameters**


        * `alertPolicyId` (UUID, required): Alert policy identifier.


        **Responses**


        * `200 OK`: Returns the alert policy, including its current `enabled`
        status and `notification` configuration.

        * `404 Not Found`: Alert policy not found in this org.
      parameters:
        - name: orgId
          in: path
          required: true
          schema:
            type: string
            format: uuid
        - name: alertPolicyId
          in: path
          description: Alert policy identifier
          required: true
          schema:
            type: string
            format: uuid
      responses:
        "200":
          description: OK
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/AlertPolicyDto"
              example:
                alertPolicyId: 3f2504e0-4f89-11d3-9a0c-0305e82c3301
                policyName: WaterLevel alert policy
                description: Alerts when the water level exceeds the configured threshold.
                alertLevel: ">=70"
                alertResetLevel: <65
                delay: 5
                enabled: true
                createdAt: 2026-07-02T09:00:00Z
                createdBy: null
                updatedAt: 2026-07-02T09:30:00Z
                updatedBy: null
                notification:
                  channelIds:
                    - channel_3fa85f64-5717-4562-b3fc-2c963f66afa6
                  templateId: tmpl_7fa85f64-5717-4562-b3fc-2c963f66afa6
                  recipients:
                    - name: Ops Team
                      target: ops-team@example.com
                      type: to
                  variables:
                    threshold: "70"
                  subject: null
                  content: null
      security:
        - Bearer: []
    patch:
      tags:
        - ___swagger_8-alert-policy_swagger_json_AlertPolicies
      summary: Update alert policy
      description: >-
        Partially update an existing alert policy. All fields are optional; only
        the

        fields provided are changed. Enable/disable status and data-stream
        bindings are managed by separate

        endpoints, not by this one.


        **Parameters**


        * `alertPolicyId` (UUID, required): Alert policy identifier.


        **Request Body**


        At least one field must be provided (an entirely empty body returns
        `400`).


        * `policyName` (string, optional): New policy name.

        * `description` (string, optional): New description.

        * `alertLevel` (string, optional): New trigger threshold expression. Ex:
        `>=70`.

        * `alertResetLevel` (string, optional): New reset threshold expression.
        Ex: `<65`.

        * `delay` (integer, optional): New debounce delay in seconds. Must be
        non-negative.

        * `notification` (object, optional): Replaces the entire notification
        configuration (same shape as create — `channelIds`, `recipients`, and
        either `templateId`+`variables` or `subject`+`content`). Providing this
        field replaces the whole object, it is not merged field-by-field with
        the existing configuration.


        **Responses**


        * `200 OK`: Alert policy updated successfully. If the policy is
        currently enabled, the updated definition is republished immediately for
        evaluation.

        * `400 Bad Request`: Empty request body, validation error, or
        `notification` provided with both `templateId` and `subject`/`content`.

        * `404 Not Found`: Alert policy not found, or a
        `notification.channelIds`/`templateId` entry does not exist in this org.
      parameters:
        - name: orgId
          in: path
          required: true
          schema:
            type: string
            format: uuid
        - name: alertPolicyId
          in: path
          description: Alert policy identifier
          required: true
          schema:
            type: string
            format: uuid
      requestBody:
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/AlertPolicyUpdateRequest"
            example:
              policyName: WaterLevel alert policy - revised
              description: Alerts when the water level exceeds the configured threshold.
                (revised)
              alertLevel: ">=75"
              alertResetLevel: <70
              delay: 10
              notification:
                channelIds:
                  - channel_3fa85f64-5717-4562-b3fc-2c963f66afa6
                  - channel_8f14e45f-ceea-4d6f-b4cf-8fef53ea6b98
                templateId: tmpl_7fa85f64-5717-4562-b3fc-2c963f66afa6
                recipients:
                  - name: Ops Team
                    target: ops-team@example.com
                    type: to
                variables: null
                subject: null
                content: null
      responses:
        "200":
          description: OK
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/AlertPolicyDto"
              example:
                alertPolicyId: 3f2504e0-4f89-11d3-9a0c-0305e82c3301
                policyName: WaterLevel alert policy
                description: Alerts when the water level exceeds the configured threshold.
                alertLevel: ">=70"
                alertResetLevel: <65
                delay: 5
                enabled: true
                createdAt: 2026-07-02T09:00:00Z
                createdBy: null
                updatedAt: 2026-07-02T09:30:00Z
                updatedBy: null
                notification:
                  channelIds:
                    - channel_3fa85f64-5717-4562-b3fc-2c963f66afa6
                  templateId: tmpl_7fa85f64-5717-4562-b3fc-2c963f66afa6
                  recipients:
                    - name: Ops Team
                      target: ops-team@example.com
                      type: to
                  variables:
                    threshold: "70"
                  subject: null
                  content: null
      security:
        - Bearer: []
    delete:
      tags:
        - ___swagger_8-alert-policy_swagger_json_AlertPolicies
      summary: Delete alert policy
      description: >-
        Delete an alert policy by ID. Only disabled policies can be deleted;
        disable

        the policy first via the enable/disable action.


        **Parameters**


        * `alertPolicyId` (UUID, required): Alert policy identifier.


        **Responses**


        * `204 No Content`: Alert policy deleted successfully.

        * `404 Not Found`: Alert policy not found in this org.

        * `409 Conflict`: The policy is currently enabled and cannot be deleted;
        disable it first.
      parameters:
        - name: orgId
          in: path
          required: true
          schema:
            type: string
            format: uuid
        - name: alertPolicyId
          in: path
          description: Alert policy identifier
          required: true
          schema:
            type: string
            format: uuid
      responses:
        "204":
          description: No Content
      security:
        - Bearer: []
  /api/v1/orgs/{orgId}/alert-policies/{alertPolicyId}:{action}:
    post:
      tags:
        - ___swagger_8-alert-policy_swagger_json_AlertPolicies
      summary: Enable or disable alert policy
      description: >-
        Execute an enable or disable action on the alert policy. Policies are
        created

        disabled and must be enabled before they evaluate attached data streams.
        Enabling publishes the

        policy's current definition for evaluation; disabling withdraws it
        (attached data streams stop being

        evaluated for this policy, but existing fired alert events are left
        untouched).


        **Parameters**


        * `alertPolicyId` (UUID, required): Alert policy identifier.

        * `action` (enum, required, path segment after `:`): Lifecycle action.
        Valid values: `enable`, `disable`.


        **Responses**


        * `204 No Content`: Alert policy status updated successfully.

        * `404 Not Found`: Alert policy not found in this org.

        * `400 Bad Request`: `action` is not one of `enable`/`disable`.
      parameters:
        - name: orgId
          in: path
          required: true
          schema:
            type: string
            format: uuid
        - name: alertPolicyId
          in: path
          description: Alert policy identifier
          required: true
          schema:
            type: string
            format: uuid
        - name: action
          in: path
          description: "Alert policy lifecycle action. Possible values: enable, disable"
          required: true
          schema:
            $ref: "#/components/schemas/AlertPolicyAction"
      responses:
        "204":
          description: No Content
      security:
        - Bearer: []
  /api/v1/orgs/{orgId}/alert-policies/{alertPolicyId}/data-streams:
    get:
      tags:
        - ___swagger_8-alert-policy_swagger_json_AlertPolicies
      summary: List data streams attached to policy
      description: >-
        Return the data streams currently attached (bound) to the alert policy,
        paginated.


        **Parameters**


        * `alertPolicyId` (UUID, required): Alert policy identifier.

        * `skipCount` (integer, optional, default: 0): Number of records to
        skip.

        * `maxResultCount` (integer, optional, default: 10): Maximum records to
        return.


        **Responses**


        * `200 OK`: Returns a paginated list of `{ deviceId, dataStreamId }`
        pairs currently attached to the policy.

        * `404 Not Found`: Alert policy not found in this org.
      parameters:
        - name: orgId
          in: path
          required: true
          schema:
            type: string
            format: uuid
        - name: alertPolicyId
          in: path
          description: Alert policy identifier
          required: true
          schema:
            type: string
            format: uuid
        - name: skipCount
          in: query
          schema:
            maximum: 2147483647
            minimum: 0
            type: integer
            format: int32
        - name: maxResultCount
          in: query
          schema:
            maximum: 2147483647
            minimum: 1
            type: integer
            format: int32
      responses:
        "200":
          description: OK
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/PagedResultDtoOfDataStreamAttachmentDto"
      security:
        - Bearer: []
    put:
      tags:
        - ___swagger_8-alert-policy_swagger_json_AlertPolicies
      summary: Set the data streams attached to policy (attach / detach)
      description: >-
        Send the full desired list of attached data streams. This is a
        full-replace

        operation, not an incremental add: streams included in the payload that
        were not previously attached

        are attached; streams that were previously attached but are left out of
        the payload are detached.

        Sending an empty array detaches all data streams from the policy.


        **Request Body**


        An array of device/data-stream pairs — the complete desired binding list
        for this policy:


        * `deviceId` (string, required): Device identifier. Ex: `9F75ABDA56C3`.

        * `dataStreamId` (UUID, required): Data stream identifier. Must exist
        (both the device and the specific data stream are validated).


        **Parameters**


        * `alertPolicyId` (UUID, required): Alert policy identifier.


        **Responses**


        * `200 OK`: Returns the final attached list (each item includes
        `alertPolicyId`, `deviceId`, `dataStreamId`), reflecting the desired
        state that was just applied.

        * `404 Not Found`: Alert policy not found, a `deviceId` does not exist,
        or a `(deviceId, dataStreamId)` pair does not exist.
      parameters:
        - name: orgId
          in: path
          required: true
          schema:
            type: string
            format: uuid
        - name: alertPolicyId
          in: path
          description: Alert policy identifier
          required: true
          schema:
            type: string
            format: uuid
      requestBody:
        content:
          application/json:
            schema:
              type: array
              items:
                $ref: "#/components/schemas/DataStreamAttachmentDto"
            example:
              - deviceId: 9f75abda56c3
                dataStreamId: 1b4e28ba-2fa1-11d2-883f-0016d3cca427
              - deviceId: 9f75abda56c3
                dataStreamId: 6fa459ea-ee8a-3ca4-894e-db77e160355e
      responses:
        "200":
          description: OK
          content:
            text/plain:
              schema:
                type: array
                items:
                  $ref: "#/components/schemas/DataStreamAttachmentResponseDto"
            application/json:
              schema:
                type: array
                items:
                  $ref: "#/components/schemas/DataStreamAttachmentResponseDto"
            text/json:
              schema:
                type: array
                items:
                  $ref: "#/components/schemas/DataStreamAttachmentResponseDto"
      security:
        - Bearer: []
  /api/v1/orgs/{orgId}/notifications/channels:
    post:
      tags:
        - ___swagger_8-alert-policy_swagger_json_Notifications
      summary: Create channel
      description: >-
        Create a new notification channel with configuration.


        **Request Body**


        * `name` (string, required): Channel name. Max length: 100. Must not
        contain whitespace.

        * `channelType` (enum, required): Channel type. Valid values: `email`,
        `teams`, `linemessage`, `webhook`.

        * `description` (string, optional): Channel description. Max length:
        500.

        * `isEnabled` (boolean, optional): Whether the channel is active.
        Default: `true`.

        * `commonSettings` (object, optional): Common settings including
        `timeout`, `retryAttempts`, `retryDelay`.

        * `config` (object, required): Channel-type-specific configuration (see
        per-type structure below).

        * `templateId` (string, optional): Template identifier associated with
        this channel.

        * `recipients` (array, optional): Default recipients for this channel.

        * `tags` (array, optional): Tags for categorization.


        **Config Structure by channelType**


        | channelType | Required Fields | Optional Fields |

        |---|---|---|

        | `email` | `host`, `port` (1-65535), `username`, `password`,
        `senderEmail` (email format) | `senderName`, `secure` (bool): Set to
        `true` to use TLS/SSL for the SMTP connection. Default: `false`. |

        | `teams` | `url` (URL format) | - |

        | `linemessage` | `accessToken`, `sendMode` (`push` or `multicast`) | -
        |

        | `webhook` | `url` (URL format), `method`
        (`GET`/`POST`/`PUT`/`DELETE`), `contentType`
        (`applicationJson`/`applicationFormUrlEncoded`/`textPlain`) | - |


        **Recipients Validation (email channel)**


        * `target`: must be valid email format

        * `type`: must be `to` or `cc`


        **Responses**


        * `201 Created`: Channel created successfully.

        * `400 Bad Request`: Validation error.

        * `409 Conflict`: Channel with same name already exists.

        * `404 Not Found`: Channel type not found.

        * `503 Service Unavailable`: Channel validation failed.
      parameters:
        - name: orgId
          in: path
          required: true
          schema:
            type: string
            format: uuid
      requestBody:
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/CreateChannelDto"
            examples:
              Email Channel:
                value:
                  name: company-email-alert
                  channelType: email
                  description: Company notification email channel
                  isEnabled: true
                  commonSettings:
                    timeout: 30
                    retryAttempts: 3
                    retryDelay: 1000
                  config:
                    host: smtp.gmail.com
                    port: 465
                    username: your_account@gmail.com
                    password: your_app_password
                    senderEmail: no-reply@your-company.com
                    senderName: Notification System
                    secure: true
                  recipients:
                    - name: Administrator
                      target: admin@example.com
                      type: to
                    - name: Supervisor
                      target: manager@example.com
                      type: cc
                  tags:
                    - notification
                    - email
              Teams Channel:
                value:
                  name: Dev-Team-Notification
                  channelType: teams
                  description: Teams channel for dev team system notifications
                  isEnabled: true
                  commonSettings:
                    timeout: 30
                    retryAttempts: 3
                    retryDelay: 1000
                  config:
                    url: https://your-tenant.logic.azure.com:443/workflows/your-workflow-id/triggers/manual/paths/invoke
              LINE Message Channel:
                value:
                  name: LINE_Push_Channel
                  channelType: linemessage
                  description: null
                  isEnabled: true
                  commonSettings:
                    timeout: 30
                    retryAttempts: 1
                    retryDelay: 1000
                  config:
                    accessToken: <your LINE Channel Access Token>
                    sendMode: push
                  recipients:
                    - name: Morris
                      target: <LINE userId>
                  tags:
                    - line
                    - push
              Webhook Channel:
                value:
                  name: qa-webhook-basic
                  channelType: webhook
                  description: null
                  isEnabled: true
                  commonSettings:
                    timeout: 30
                    retryAttempts: 3
                    retryDelay: 1000
                  config:
                    url: https://webhook.site/bcd0ae88-19bd-421b-b525-98a305727032
                    method: POST
                    contentType: applicationJson
                  templateId: tmpl_7fa85f64-5717-4562-b3fc-2c963f66afa6
                  recipients:
                    - name: QA Webhook Endpoint
                      target: https://webhook.site/bcd0ae88-19bd-421b-b525-98a305727032
                      type: to
                  tags:
                    - webhook
                    - qa
      responses:
        "201":
          description: Channel created successfully
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ChannelDetailDto"
              example:
                channelId: channel_abc12345-6789-0abc-def0-123456789abc
                name: EmailChannel
                channelType: email
                description: System notification email channel
                isEnabled: true
                commonSettings:
                  timeout: 5000
                  retryAttempts: 3
                  retryDelay: 1000
                config:
                  host: smtp.example.com
                  port: 587
                  username: noreply@example.com
                  senderEmail: noreply@example.com
                  secure: true
                recipients: []
                tags: []
                templateId: tmpl_7fa85f64-5717-4562-b3fc-2c963f66afa6
                createdAt: 2026-08-03T03:52:59.5719991Z
                updatedAt: 2026-08-03T03:52:59.5719992Z
        "400":
          description: Bad Request
          content:
            application/json:
              schema: {}
              example:
                type: WEDA.Common.PropertyRequire
                title: Bad Request
                status: 400
                detail: The property 'channelName' is required.
                instance: /notification/channels
        "404":
          description: Not Found
          content:
            application/json:
              schema: {}
              example:
                type: CommonError.NotFound
                title: Not Found
                status: 404
                detail: Channel type 'invalid-type' not found
                instance: /notification/channels/registry-info/types/invalid-type
        "409":
          description: Conflict
          content:
            application/json:
              schema: {}
              example:
                type: CommonError.AlreadyExists
                title: Conflict
                status: 409
                detail: Channel with name 'MyChannel' already exists
                instance: /notification/channels
        "503":
          description: Service Unavailable
          content:
            application/json:
              schema: {}
              example:
                type: WEDA.Notification.Channel.ConnectionFailed
                title: Service Unavailable
                status: 503
                detail: Failed to validate channel configuration
                instance: /notification/channels
      security:
        - Bearer: []
    get:
      tags:
        - ___swagger_8-alert-policy_swagger_json_Notifications
      summary: List channels
      description: >-
        List all channels with optional filtering and pagination.


        **Parameters**


        * `skipCount` (integer, optional, default: 0): Number of records to skip

        * `maxResultCount` (integer, optional, default: 20, max: 100): Maximum
        records to return

        * `name` (string, optional): Filter by channel name

        * `channelType` (string, optional): Filter by channel type

        * `isEnabled` (boolean, optional): Filter by enabled status


        **Responses**


        * `200 OK`: Channels retrieved successfully. Each item includes
        `channelId`, `name`, `channelType`, `isEnabled`, `tags`, `createdAt`,
        and `updatedAt`.

        * `400 Bad Request`: Invalid pagination parameters.
      parameters:
        - name: orgId
          in: path
          required: true
          schema:
            type: string
            format: uuid
        - name: channelType
          in: query
          schema:
            type: string
        - name: isEnabled
          in: query
          schema:
            type: boolean
        - name: name
          in: query
          schema:
            type: string
        - name: skipCount
          in: query
          schema:
            maximum: 2147483647
            minimum: 0
            type: integer
            format: int32
        - name: maxResultCount
          in: query
          schema:
            maximum: 2147483647
            minimum: 1
            type: integer
            format: int32
      responses:
        "200":
          description: Channels retrieved successfully
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/PagedResultDtoOfChannelListItemDto"
        "400":
          description: Bad Request
          content:
            application/json:
              schema: {}
              example:
                type: WEDA.Common.PropertyFormatError
                title: Bad Request
                status: 400
                detail: "Invalid format for property 'maxResultCount'. Expected format: integer
                  between 1 and 100"
                instance: /notification/channels
      security:
        - Bearer: []
  /api/v1/orgs/{orgId}/notifications/channels/{channelId}:
    get:
      tags:
        - ___swagger_8-alert-policy_swagger_json_Notifications
      summary: Get channel
      description: >-
        Retrieve detailed information for a specific channel.


        **Parameters**


        * `channelId` (string, required): Channel identifier (format:
        channel_xxx)


        **Responses**


        * `200 OK`: Channel details retrieved successfully.

        * `404 Not Found`: Channel not found.

        * `400 Bad Request`: Invalid channel ID format.
      parameters:
        - name: orgId
          in: path
          required: true
          schema:
            type: string
            format: uuid
        - name: channelId
          in: path
          description: "Channel identifier (format: channel_xxx)"
          required: true
          schema:
            type: string
      responses:
        "200":
          description: Channel retrieved successfully
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ChannelDetailDto"
              example:
                channelId: channel_abc12345-6789-0abc-def0-123456789abc
                name: EmailChannel
                channelType: email
                description: System notification email channel
                isEnabled: true
                commonSettings:
                  timeout: 5000
                  retryAttempts: 3
                  retryDelay: 1000
                config:
                  host: smtp.example.com
                  port: 587
                  username: noreply@example.com
                  senderEmail: noreply@example.com
                  secure: true
                recipients: []
                tags: []
                templateId: tmpl_7fa85f64-5717-4562-b3fc-2c963f66afa6
                createdAt: 2026-08-03T03:52:59.5835414Z
                updatedAt: 2026-08-03T03:52:59.5835415Z
        "400":
          description: Bad Request
          content:
            application/json:
              schema: {}
              example:
                type: WEDA.Common.PropertyFormatError
                title: Bad Request
                status: 400
                detail: "Invalid format for property 'maxResultCount'. Expected format: integer
                  between 1 and 100"
                instance: /notification/channels
        "404":
          description: Not Found
          content:
            application/json:
              schema: {}
              example:
                type: CommonError.NotFound
                title: Not Found
                status: 404
                detail: Resource with ID 'abc12345-6789-0abc-def0-123456789abc' not found
                instance: /notification/channels/abc12345-6789-0abc-def0-123456789abc
      security:
        - Bearer: []
    patch:
      tags:
        - ___swagger_8-alert-policy_swagger_json_Notifications
      summary: Update channel
      description: >-
        Update channel configuration (partial update supported).


        **Parameters**


        * `channelId` (string, required): Channel identifier (format:
        channel_xxx)


        **Request Body**


        All fields are optional. Only provided fields will be updated.


        * `name` (string): Channel name.

        * `channelType` (enum): Valid values: `email`, `teams`, `linemessage`,
        `webhook`.

        * `description` (string): Channel description.

        * `isEnabled` (boolean): Enable or disable the channel.

        * `commonSettings` (object): `timeout`, `retryAttempts`, `retryDelay`.

        * `config` (object): Channel-type-specific configuration (same structure
        as create).

        * `templateId` (string): Template identifier.

        * `recipients` (array): Default recipients.

        * `tags` (array): Tags for categorization.


        **Responses**


        * `200 OK`: Channel updated successfully.

        * `404 Not Found`: Channel not found.

        * `400 Bad Request`: Validation error.

        * `503 Service Unavailable`: Channel validation failed.
      parameters:
        - name: orgId
          in: path
          required: true
          schema:
            type: string
            format: uuid
        - name: channelId
          in: path
          description: "Channel identifier (format: channel_xxx)"
          required: true
          schema:
            type: string
      requestBody:
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/UpdateChannelDto"
            example:
              name: UpdatedEmailChannel
              channelType: null
              description: Updated system notification email channel
              isEnabled: false
              commonSettings:
                timeout: 10000
                retryAttempts: 5
                retryDelay: 2000
              config:
                host: smtp-new.example.com
                port: 465
                username: noreply@example.com
                password: new-password
                senderEmail: noreply@example.com
                senderName: null
                secure: true
              templateId: null
              recipients:
                - name: Administrator
                  target: admin@example.com
                  type: to
              tags:
                - notification
                - email
      responses:
        "200":
          description: Channel updated successfully
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ChannelDetailDto"
              example:
                channelId: channel_abc12345-6789-0abc-def0-123456789abc
                name: EmailChannel
                channelType: email
                description: System notification email channel
                isEnabled: true
                commonSettings:
                  timeout: 5000
                  retryAttempts: 3
                  retryDelay: 1000
                config:
                  host: smtp.example.com
                  port: 587
                  username: noreply@example.com
                  senderEmail: noreply@example.com
                  secure: true
                recipients: []
                tags: []
                templateId: tmpl_7fa85f64-5717-4562-b3fc-2c963f66afa6
                createdAt: 2026-08-03T03:52:59.6662141Z
                updatedAt: 2026-08-03T03:52:59.6662142Z
        "400":
          description: Bad Request
          content:
            application/json:
              schema: {}
              example:
                type: WEDA.Common.PropertyFormatError
                title: Bad Request
                status: 400
                detail: Invalid format for property 'config'
                instance: /notification/channels/abc12345-6789-0abc-def0-123456789abc
        "404":
          description: Not Found
          content:
            application/json:
              schema: {}
              example:
                type: CommonError.NotFound
                title: Not Found
                status: 404
                detail: Resource with ID 'abc12345-6789-0abc-def0-123456789abc' not found
                instance: /notification/channels/abc12345-6789-0abc-def0-123456789abc
        "503":
          description: Service Unavailable
          content:
            application/json:
              schema: {}
              example:
                type: WEDA.Notification.Channel.ConnectionFailed
                title: Service Unavailable
                status: 503
                detail: Failed to validate channel configuration
                instance: /notification/channels
      security:
        - Bearer: []
    delete:
      tags:
        - ___swagger_8-alert-policy_swagger_json_Notifications
      summary: Delete channel
      description: >-
        Delete a channel permanently.


        **Parameters**


        * `channelId` (string, required): Channel identifier (format:
        channel_xxx)


        **Responses**


        * `204 No Content`: Channel deleted successfully.

        * `404 Not Found`: Channel not found.

        * `400 Bad Request`: Invalid channel ID format.
      parameters:
        - name: orgId
          in: path
          required: true
          schema:
            type: string
            format: uuid
        - name: channelId
          in: path
          description: "Channel identifier (format: channel_xxx)"
          required: true
          schema:
            type: string
      responses:
        "204":
          description: Channel deleted successfully
        "400":
          description: Bad Request
          content:
            text/plain:
              schema: {}
              example:
                type: WEDA.Common.PropertyFormatError
                title: Bad Request
                status: 400
                detail: "Invalid format for property 'maxResultCount'. Expected format: integer
                  between 1 and 100"
                instance: /notification/channels
            application/json:
              schema: {}
              example:
                type: WEDA.Common.PropertyFormatError
                title: Bad Request
                status: 400
                detail: "Invalid format for property 'maxResultCount'. Expected format: integer
                  between 1 and 100"
                instance: /notification/channels
            text/json:
              schema: {}
              example:
                type: WEDA.Common.PropertyFormatError
                title: Bad Request
                status: 400
                detail: "Invalid format for property 'maxResultCount'. Expected format: integer
                  between 1 and 100"
                instance: /notification/channels
        "404":
          description: Not Found
          content:
            text/plain:
              schema: {}
              example:
                type: CommonError.NotFound
                title: Not Found
                status: 404
                detail: Resource with ID 'abc12345-6789-0abc-def0-123456789abc' not found
                instance: /notification/channels/abc12345-6789-0abc-def0-123456789abc
            application/json:
              schema: {}
              example:
                type: CommonError.NotFound
                title: Not Found
                status: 404
                detail: Resource with ID 'abc12345-6789-0abc-def0-123456789abc' not found
                instance: /notification/channels/abc12345-6789-0abc-def0-123456789abc
            text/json:
              schema: {}
              example:
                type: CommonError.NotFound
                title: Not Found
                status: 404
                detail: Resource with ID 'abc12345-6789-0abc-def0-123456789abc' not found
                instance: /notification/channels/abc12345-6789-0abc-def0-123456789abc
      security:
        - Bearer: []
  /api/v1/orgs/{orgId}/notifications/channels/{channelId}/status:
    put:
      tags:
        - ___swagger_8-alert-policy_swagger_json_Notifications
      summary: Enable/Disable channel
      description: >-
        Toggle channel enabled status.


        **Parameters**


        * `channelId` (string, required): Channel identifier (format:
        channel_xxx)


        **Request Body**


        * `isEnabled` (boolean, required): true to enable, false to disable


        **Responses**


        * `200 OK`: Channel status updated successfully.

        * `404 Not Found`: Channel not found.

        * `400 Bad Request`: Invalid parameters.
      parameters:
        - name: orgId
          in: path
          required: true
          schema:
            type: string
            format: uuid
        - name: channelId
          in: path
          description: "Channel identifier (format: channel_xxx)"
          required: true
          schema:
            type: string
      requestBody:
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/ChannelUpdateStatusRequest"
            example:
              isEnabled: true
      responses:
        "200":
          description: Channel status updated successfully
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ChannelStatusResponseDto"
              example:
                channelId: channel_abc12345-6789-0abc-def0-123456789abc
                isEnabled: true
                updatedAt: 2026-08-03T03:52:59.6798129Z
        "400":
          description: Bad Request
          content:
            application/json:
              schema: {}
              example:
                type: WEDA.Common.PropertyFormatError
                title: Bad Request
                status: 400
                detail: "Invalid format for property 'maxResultCount'. Expected format: integer
                  between 1 and 100"
                instance: /notification/channels
        "404":
          description: Not Found
          content:
            application/json:
              schema: {}
              example:
                type: CommonError.NotFound
                title: Not Found
                status: 404
                detail: Resource with ID 'abc12345-6789-0abc-def0-123456789abc' not found
                instance: /notification/channels/abc12345-6789-0abc-def0-123456789abc
      security:
        - Bearer: []
  /api/v1/orgs/{orgId}/notifications/channels/registry-info/types:
    get:
      tags:
        - ___swagger_8-alert-policy_swagger_json_Notifications
      summary: List available channel types
      description: >-
        Retrieve all available channel types and their status.


        **Parameters**


        None


        **Responses**


        * `200 OK`: Returns a list of available channel types with their status
        and configuration information.
      parameters:
        - name: orgId
          in: path
          required: true
          schema:
            type: string
            format: uuid
      responses:
        "200":
          description: Success
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/PagedResultDtoOfChannelTypeDto"
            "{\n  \"items\": [\n    {\n      \"channelType\": \"email\",\n      \"name\": \"Email\",\n      \"description\": \"Send emails via SMTP\",\n      \"status\": \"loaded\",\n      \"version\": \"2.0.0\"\n    }\n  ],\n  \"totalCount\": 1\n}":
              schema:
                $ref: "#/components/schemas/PagedResultDtoOfChannelTypeDto"
      security:
        - Bearer: []
  /api/v1/orgs/{orgId}/notifications/channels/registry-info/types/{channelType}:
    get:
      tags:
        - ___swagger_8-alert-policy_swagger_json_Notifications
      summary: Get channel type info
      description: >-
        Get detailed configuration schema for a specific channel type.


        **Parameters**


        * `channelType` (enum, required): Channel type identifier (e.g.,
        'email', 'teamplus')


        **Responses**


        * `200 OK`: Returns detailed channel type configuration schema.

        * `404 Not Found`: Channel type not found.

        * `400 Bad Request`: Invalid channel type format.
      parameters:
        - name: orgId
          in: path
          required: true
          schema:
            type: string
            format: uuid
        - name: channelType
          in: path
          description: Channel type identifier (e.g., 'email', 'teamplus')
          required: true
          schema:
            $ref: "#/components/schemas/ChannelType"
      responses:
        "200":
          description: Channel type info retrieved successfully
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ChannelTypeDetailDto"
              example:
                configSchema:
                  type: object
                  properties:
                    host:
                      type: string
                      description: SMTP server host
                    port:
                      type: integer
                      default: 587
                    username:
                      type: string
                    password:
                      type: string
                      format: password
                    senderEmail:
                      type: string
                      format: email
                    secure:
                      type: boolean
                      description: Set to true to use TLS/SSL for the SMTP connection
                      default: false
                  required:
                    - host
                    - username
                    - password
                    - senderEmail
                examples:
                  - host: smtp.gmail.com
                    port: 587
                    username: notifications@example.com
                    password: app-password-here
                    senderEmail: notifications@example.com
                    secure: true
                channelType: email
                name: Email
                description: Send emails via SMTP
                status: loaded
                version: 2.0.0
        "400":
          description: Bad Request
          content:
            application/json:
              schema: {}
              example:
                type: WEDA.Common.FormatError
                title: Bad Request
                status: 400
                detail: Data validation failed
                instance: /notification/channels
        "404":
          description: Not Found
          content:
            application/json:
              schema: {}
              example:
                type: CommonError.NotFound
                title: Not Found
                status: 404
                detail: Resource with ID 'abc12345-6789-0abc-def0-123456789abc' not found
                instance: /notification/channels/abc12345-6789-0abc-def0-123456789abc
      security:
        - Bearer: []
  /api/v1/orgs/{orgId}/notifications/messages/{messageId}:
    get:
      tags:
        - ___swagger_8-alert-policy_swagger_json_Notifications
      summary: Get message status
      description: |-
        Get message delivery status and details.

        **Parameters**

        * `messageId` (string, required): Message identifier (format: msg_xxx)

        **Responses**

        * `200 OK`: Message status retrieved successfully.
        * `404 Not Found`: Message not found.
        * `400 Bad Request`: Invalid message ID format.

        **Status Values**: `pending`, `sent`, `failed`, `partial`, `success`
      parameters:
        - name: orgId
          in: path
          required: true
          schema:
            type: string
            format: uuid
        - name: messageId
          in: path
          description: "Message identifier (format: msg_xxx)"
          required: true
          schema:
            type: string
      responses:
        "200":
          description: Message status retrieved successfully
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/MessageDetailDto"
              example:
                messageId: msg_abc12345-6789-0abc-def0-123456789abc
                channelIds:
                  - channel_abc12345-6789-0abc-def0-123456789abc
                templateId: tmpl_abc12345
                recipients:
                  - name: null
                    target: user@example.com
                    type: to
                subject: Welcome
                content: Dear user, welcome to join us!
                variables:
                  userName: user
                status: success
                results:
                  - channelId: channel_abc12345-6789-0abc-def0-123456789abc
                    name: Production Email
                    status: success
                    message: Message sent successfully
                    sentAt: 2026-08-03T03:52:59.8342457Z
                successCount: 1
                failureCount: 0
                totalCount: 1
                settings:
                  timeout: 30
                  retryAttempts: 3
                  retryDelay: 1000
                attachments:
                  - filename: report.pdf
                    contentType: application/pdf
                sentAt: 2026-08-03T03:52:59.8342467Z
                createdAt: 2026-08-03T03:52:59.8342468Z
        "400":
          description: Bad Request
          content:
            application/json:
              schema: {}
              example:
                type: WEDA.Common.PropertyFormatError
                title: Bad Request
                status: 400
                detail: "Invalid format for property 'maxResultCount'. Expected format: integer
                  between 1 and 100"
                instance: /notification/channels
        "404":
          description: Not Found
          content:
            application/json:
              schema: {}
              example:
                type: CommonError.NotFound
                title: Not Found
                status: 404
                detail: Message with ID 'abc12345-6789-0abc-def0-123456789abc' not found
                instance: /notification/messages/abc12345-6789-0abc-def0-123456789abc
      security:
        - Bearer: []
  /api/v1/orgs/{orgId}/notifications/messages:
    get:
      tags:
        - ___swagger_8-alert-policy_swagger_json_Notifications
      summary: List message records
      description: >-
        
        List message records with filtering and pagination. All query parameters
        are optional and may be combined. When multiple parameters are provided,
        filters are combined using logical AND. Common usage patterns include
        createdAtStart/createdAtEnd and sentAtStart/sentAtEnd, but any
        combination is supported.


        **Parameters**


        * `skipCount` (integer, optional, default: 0): Number of records to skip

        * `maxResultCount` (integer, optional, default: 20): Maximum records to
        return

        * `channelId` (string, optional): Filter by channel ID (format:
        channel_<guid>)

        * `status` (enum, optional): Filter by status (`pending`, `sent`,
        `failed`, `partial`, `success`)

        * `createdAtStart` (datetime, optional): Filter messages created on or
        after this time (ISO 8601, e.g. `2026-05-01T00:00:00Z`)

        * `createdAtEnd` (datetime, optional): Filter messages created on or
        before this time (ISO 8601)

        * `sentAtStart` (datetime, optional): Filter messages sent on or after
        this time (ISO 8601)

        * `sentAtEnd` (datetime, optional): Filter messages sent on or before
        this time (ISO 8601)


        **Responses**


        * `200 OK`: Messages retrieved successfully.

        * `400 Bad Request`: Invalid query parameter format.
      parameters:
        - name: orgId
          in: path
          required: true
          schema:
            type: string
            format: uuid
        - name: channelId
          in: query
          schema:
            type: string
        - name: status
          in: query
          schema:
            $ref: "#/components/schemas/MessageStatus"
        - name: createdAtStart
          in: query
          schema:
            type: string
            format: date-time
        - name: createdAtEnd
          in: query
          schema:
            type: string
            format: date-time
        - name: sentAtStart
          in: query
          schema:
            type: string
            format: date-time
        - name: sentAtEnd
          in: query
          schema:
            type: string
            format: date-time
        - name: skipCount
          in: query
          schema:
            maximum: 2147483647
            minimum: 0
            type: integer
            format: int32
        - name: maxResultCount
          in: query
          schema:
            maximum: 2147483647
            minimum: 1
            type: integer
            format: int32
      responses:
        "200":
          description: Messages retrieved successfully
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/PagedResultDtoOfMessageListItemDto"
        "400":
          description: Bad Request
          content:
            application/json:
              schema: {}
              example:
                type: WEDA.Common.InvalidQueryParam
                title: Bad Request
                status: 400
                detail: "Invalid value for query parameter 'channelId'. Expected format:
                  channel_<guid>"
                instance: /api/v1/notifications/messages
      security:
        - Bearer: []
  /api/v1/orgs/{orgId}/notifications/templates:
    post:
      tags:
        - ___swagger_8-alert-policy_swagger_json_Notifications
      summary: Create template
      description: >-
        Create a new message template with variable support.


        **Request Body**


        * `name` (string, required): Template name. Max length: 200.

        * `subject` (string, optional): Message subject. Max length: 500. Used
        only by the `email` channel type as the email subject line.

        * `content` (string, required): Message body. Max length: 50000.

        * `channelTypes` (array, required): One or more channel types this
        template targets (e.g., `email`, `teams`, `linemessage`, `webhook`).

        * `tags` (array, optional): Tags for categorization.


        **Variable Syntax**: `{variableName}`


        **Per-Channel Template Constraints**


        | channelType | `subject` | `content` |

        |---|---|---|

        | `email` | Used as the email subject line; supports `{variableName}`
        substitution | Used as the email body; supports plain text or HTML with
        `{variableName}` substitution |

        | `teams` | Ignored | Used as the Teams message body |

        | `linemessage` | Ignored | Used as the LINE message text |

        | `webhook` | Ignored | Used as the HTTP request body payload |


        **Responses**


        * `201 Created`: Template created successfully.

        * `400 Bad Request`: Validation error or invalid template variable
        syntax.

        * `409 Conflict`: Template with same name exists.

        * `404 Not Found`: Channel type not found.
      parameters:
        - name: orgId
          in: path
          required: true
          schema:
            type: string
            format: uuid
      requestBody:
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/CreateTemplateDto"
            example:
              name: Welcome Email Template
              subject: Welcome to {companyName}
              content: |-
                Dear {userName},

                Welcome to our platform!

                Your account: {email}
              channelTypes:
                - email
              tags:
                - welcome
                - onboarding
      responses:
        "201":
          description: Template created successfully
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/TemplateResponseDto"
              example:
                templateId: template_abc12345-6789-0abc-def0-123456789abc
                name: Welcome Email Template
                subject: Welcome to {companyName}
                content: |-
                  Dear {userName},

                  Welcome to our platform!
                channelTypes:
                  - email
                tags:
                  - welcome
                  - onboarding
                createdAt: 2026-08-03T03:52:59.878233Z
        "400":
          description: Bad Request
          content:
            application/json:
              schema: {}
              example:
                type: WEDA.Notification.InvalidTemplateVariable
                title: Bad Request
                status: 400
                detail: "Invalid template variable syntax: '{{userName' - missing closing
                  braces"
                instance: /notification/templates
        "404":
          description: Not Found
          content:
            application/json:
              schema: {}
              example:
                type: CommonError.NotFound
                title: Not Found
                status: 404
                detail: Channel type 'invalid-type' not found
                instance: /notification/channels/registry-info/types/invalid-type
        "409":
          description: Conflict
          content:
            application/json:
              schema: {}
              example:
                type: CommonError.AlreadyExists
                title: Conflict
                status: 409
                detail: Template with name 'WelcomeEmail' already exists
                instance: /notification/templates
      security:
        - Bearer: []
    get:
      tags:
        - ___swagger_8-alert-policy_swagger_json_Notifications
      summary: List templates
      description: >-
        List templates with optional filtering and pagination.


        **Parameters**


        * `skipCount` (integer, optional, default: 0): Number of records to skip

        * `maxResultCount` (integer, optional, default: 20, max: 100): Maximum
        records to return

        * `name` (string, optional): Filter by template name

        * `channelType` (enum, optional): Filter by channel type

        * `tags` (string[], optional): Filter by tags


        **Responses**


        * `200 OK`: Templates retrieved successfully.

        * `400 Bad Request`: Invalid pagination parameters.
      parameters:
        - name: orgId
          in: path
          required: true
          schema:
            type: string
            format: uuid
        - name: name
          in: query
          schema:
            type: string
        - name: channelType
          in: query
          schema:
            $ref: "#/components/schemas/ChannelType"
        - name: tags
          in: query
          schema:
            type: array
            items:
              type: string
        - name: skipCount
          in: query
          schema:
            maximum: 2147483647
            minimum: 0
            type: integer
            format: int32
        - name: maxResultCount
          in: query
          schema:
            maximum: 2147483647
            minimum: 1
            type: integer
            format: int32
      responses:
        "200":
          description: Templates retrieved successfully
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/PagedResultDtoOfTemplateListItemDto"
        "400":
          description: Bad Request
          content:
            application/json:
              schema: {}
              example:
                type: WEDA.Common.PropertyFormatError
                title: Bad Request
                status: 400
                detail: "Invalid format for property 'maxResultCount'. Expected format: integer
                  between 1 and 100"
                instance: /notification/channels
      security:
        - Bearer: []
  /api/v1/orgs/{orgId}/notifications/templates/{templateId}:
    get:
      tags:
        - ___swagger_8-alert-policy_swagger_json_Notifications
      summary: Get template
      description: >-
        Retrieve template details.


        **Parameters**


        * `templateId` (string, required): Template identifier (format:
        template_xxx)


        **Responses**


        * `200 OK`: Template retrieved successfully.

        * `404 Not Found`: Template not found.

        * `400 Bad Request`: Invalid template ID format.
      parameters:
        - name: orgId
          in: path
          required: true
          schema:
            type: string
            format: uuid
        - name: templateId
          in: path
          description: "Template identifier (format: template_xxx)"
          required: true
          schema:
            type: string
      responses:
        "200":
          description: Template retrieved successfully
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/TemplateDetailDto"
              example:
                templateId: template_abc12345-6789-0abc-def0-123456789abc
                name: Welcome Email Template
                subject: Welcome to {companyName}
                content: |-
                  Dear {userName},

                  Welcome to our platform!
                channelTypes:
                  - email
                tags:
                  - welcome
                  - onboarding
                createdAt: 2026-08-03T03:52:59.9302306Z
                updatedAt: 2026-08-03T03:52:59.9302307Z
        "400":
          description: Bad Request
          content:
            application/json:
              schema: {}
              example:
                type: WEDA.Common.PropertyFormatError
                title: Bad Request
                status: 400
                detail: "Invalid format for property 'maxResultCount'. Expected format: integer
                  between 1 and 100"
                instance: /notification/channels
        "404":
          description: Not Found
          content:
            application/json:
              schema: {}
              example:
                type: CommonError.NotFound
                title: Not Found
                status: 404
                detail: Template with ID 'abc12345-6789-0abc-def0-123456789abc' not found
                instance: /notification/templates/abc12345-6789-0abc-def0-123456789abc
      security:
        - Bearer: []
    patch:
      tags:
        - ___swagger_8-alert-policy_swagger_json_Notifications
      summary: Update template
      description: >-
        Update template content (partial update supported).


        **Parameters**


        * `templateId` (string, required): Template identifier (format:
        template_xxx)


        **Request Body**


        All fields are optional; only the fields provided are changed. Same
        per-channel `subject`/`content`

        interpretation as create (see the table on `Create template`).


        * `name` (string, optional, max length 200): New template name.

        * `subject` (string, optional, max length 500): New subject. Used only
        by the `email` channel type.

        * `content` (string, optional, max length 50000): New message body.

        * `channelTypes` (array, optional): Replaces the entire channel type
        list this template targets. Valid values: `email`, `teams`,
        `linemessage`, `webhook`.

        * `tags` (array, optional): Replaces the entire tag list.


        **Responses**


        * `200 OK`: Template updated successfully.

        * `404 Not Found`: Template not found.

        * `400 Bad Request`: Validation error or invalid template variable
        syntax.
      parameters:
        - name: orgId
          in: path
          required: true
          schema:
            type: string
            format: uuid
        - name: templateId
          in: path
          description: "Template identifier (format: template_xxx)"
          required: true
          schema:
            type: string
      requestBody:
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/UpdateTemplateDto"
            example:
              name: null
              subject: Welcome to {companyName} - Updated
              content: |-
                Dear {userName},

                Welcome to our updated platform!
              channelTypes: null
              tags:
                - welcome
                - onboarding
                - v2
      responses:
        "200":
          description: Template updated successfully
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/TemplateDetailDto"
              example:
                templateId: template_abc12345-6789-0abc-def0-123456789abc
                name: Welcome Email Template
                subject: Welcome to {companyName}
                content: |-
                  Dear {userName},

                  Welcome to our platform!
                channelTypes:
                  - email
                tags:
                  - welcome
                  - onboarding
                createdAt: 2026-08-03T03:52:59.9572387Z
                updatedAt: 2026-08-03T03:52:59.9572389Z
        "400":
          description: Bad Request
          content:
            application/json:
              schema: {}
              example:
                type: WEDA.Notification.InvalidTemplateVariable
                title: Bad Request
                status: 400
                detail: "Invalid template variable syntax: '{{userName' - missing closing
                  braces"
                instance: /notification/templates
        "404":
          description: Not Found
          content:
            application/json:
              schema: {}
              example:
                type: CommonError.NotFound
                title: Not Found
                status: 404
                detail: Template with ID 'abc12345-6789-0abc-def0-123456789abc' not found
                instance: /notification/templates/abc12345-6789-0abc-def0-123456789abc
      security:
        - Bearer: []
    delete:
      tags:
        - ___swagger_8-alert-policy_swagger_json_Notifications
      summary: Delete template
      description: >-
        Delete a template permanently.


        **Parameters**


        * `templateId` (string, required): Template identifier (format:
        template_xxx)


        **Responses**


        * `204 No Content`: Template deleted successfully.

        * `404 Not Found`: Template not found.

        * `400 Bad Request`: Invalid template ID format.
      parameters:
        - name: orgId
          in: path
          required: true
          schema:
            type: string
            format: uuid
        - name: templateId
          in: path
          description: "Template identifier (format: template_xxx)"
          required: true
          schema:
            type: string
      responses:
        "204":
          description: Template deleted successfully
        "400":
          description: Bad Request
          content:
            text/plain:
              schema: {}
              example:
                type: WEDA.Common.PropertyFormatError
                title: Bad Request
                status: 400
                detail: "Invalid format for property 'maxResultCount'. Expected format: integer
                  between 1 and 100"
                instance: /notification/channels
            application/json:
              schema: {}
              example:
                type: WEDA.Common.PropertyFormatError
                title: Bad Request
                status: 400
                detail: "Invalid format for property 'maxResultCount'. Expected format: integer
                  between 1 and 100"
                instance: /notification/channels
            text/json:
              schema: {}
              example:
                type: WEDA.Common.PropertyFormatError
                title: Bad Request
                status: 400
                detail: "Invalid format for property 'maxResultCount'. Expected format: integer
                  between 1 and 100"
                instance: /notification/channels
        "404":
          description: Not Found
          content:
            text/plain:
              schema: {}
              example:
                type: CommonError.NotFound
                title: Not Found
                status: 404
                detail: Template with ID 'abc12345-6789-0abc-def0-123456789abc' not found
                instance: /notification/templates/abc12345-6789-0abc-def0-123456789abc
            application/json:
              schema: {}
              example:
                type: CommonError.NotFound
                title: Not Found
                status: 404
                detail: Template with ID 'abc12345-6789-0abc-def0-123456789abc' not found
                instance: /notification/templates/abc12345-6789-0abc-def0-123456789abc
            text/json:
              schema: {}
              example:
                type: CommonError.NotFound
                title: Not Found
                status: 404
                detail: Template with ID 'abc12345-6789-0abc-def0-123456789abc' not found
                instance: /notification/templates/abc12345-6789-0abc-def0-123456789abc
      security:
        - Bearer: []
  /api/v1/reports/usage-jobs:
    post:
      tags:
        - ___swagger_9-reports_swagger_json_Reports
      summary: Create a new usage summary task
      description: "This task will automatically send a usage summary request for each
        specified period until the end time.\r

        A unique task usageJobId will be generated when the task is created.\r

        \r

        You can use the search API to retrieve the task usageJobId and then use
        the usageJobId to download the report.\r

        \r

        The endTime must be later than setting date at least one period.\r

        \r

        **Limitations**\r

        - repeatPeriod: Daily, Weekly, or Monthly\r

        - endTime: ISO8601 format YYYY-MM-DD\r

        - timeZone: +08:30\r

        - jobs: ActiveDeviceCount or DataPointCount\r

        {\r

        \    message: end time format error.\r

        }\r

        \r\n"
      requestBody:
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/CreateScheduledJobRequestDto"
      responses:
        "201":
          description: Created
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/CreateScheduleResultDto"
      security:
        - Bearer: []
    get:
      tags:
        - ___swagger_9-reports_swagger_json_Reports
      summary: Get all usage summary tasks
      description: "This API retrieves information about all tasks, including schedule
        IDs and detailed settings.\r

        \r

        You can use skipCount to control the starting point of the returned
        results.\r

        Use maxResultCount to limit the number of results returned.\r\n"
      parameters:
        - name: skipCount
          in: query
          schema:
            type: integer
            format: int32
            default: 0
        - name: maxResultCount
          in: query
          schema:
            type: integer
            format: int32
            default: 10
      responses:
        "200":
          description: OK
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: "#/components/schemas/GetScheduledJobResponseDto"
      security:
        - Bearer: []
  /api/v1/reports/usage-jobs/{usageJobId}:
    get:
      tags:
        - ___swagger_9-reports_swagger_json_Reports
      summary: Retrieve a single usage summary task
      description: "This API retrieves the details of a single usage summary task
        identified by usageJobId.\r

        \r

        The response includes all settings and configuration details of the
        task, such as schedule information, repeat period, end time, time zone,
        and job sorting options.\r

        \r

        If the specified task does not exist or an error occurs while fetching
        the task, a 500 status code is returned with an error message containing
        the taskusageJobIdand the error description.\r

        \r

        **Parameters**\r

        - usageJobId: The unique identifier of the usage summary task to
        retrieve (required).\r

        \r

        **Notes**\r

        - Ensure the usageJobId is correct.\r

        - The API only retrieves the task information; it does not modify or
        delete the task.\r

        - The returned object can be used to review or update the task via the
        update API.\r\n"
      parameters:
        - name: usageJobId
          in: path
          required: true
          schema:
            type: string
            format: uuid
      responses:
        "200":
          description: OK
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/GetScheduledJobResponseDto"
      security:
        - Bearer: []
    put:
      tags:
        - ___swagger_9-reports_swagger_json_Reports
      summary: Update an existing usage summary task
      description: "This API updates an existing usage summary task using the provided
        usageJobId and new settings.\r

        \r

        The task will continue to send usage summary requests according to the
        updated schedule until the end time.\r

        A unique task usageJobId is associated with the task and remains
        unchanged.\r

        \r

        The endTime must be later than the setting date by at least one
        period.\r

        \r

        * Limitations:\r

        - usageJobId: The unique identifier of the usage summary task to
        retrieve (required).\r

        - repeatPeriod: Daily, Weekly, or Monthly\r

        - endTime: ISO8601 format YYYY-MM-DD\r

        - timeZone: +08:30\r

        - Job sorting options: ActiveDeviceCount or DataPointCount\r\n"
      parameters:
        - name: usageJobId
          in: path
          required: true
          schema:
            type: string
            format: uuid
      requestBody:
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/UpdatePutScheduledJobRequestDto"
      responses:
        "200":
          description: OK
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/GetScheduledJobResponseDto"
      security:
        - Bearer: []
    delete:
      tags:
        - ___swagger_9-reports_swagger_json_Reports
      summary: Delete a single usage summary task
      description: "This API deletes an existing usage summary task identified by the
        provided usageJobId.\r

        \r

        When the task is successfully deleted, it will no longer send any usage
        summary requests.\r

        \r

        If the specified usageJobId does not exist, an error message will be
        returned.\r

        \r

        **Notes**\r

        - Make sure the usageJobId is correct before calling this API.\r

        - Deleting a task is irreversible.\r\n"
      parameters:
        - name: usageJobId
          in: path
          required: true
          schema:
            type: string
            format: uuid
      responses:
        "204":
          description: No Content
      security:
        - Bearer: []
  /api/v1/reports/usage-jobs/{usageJobId}/summaries:
    get:
      tags:
        - ___swagger_9-reports_swagger_json_Reports
      summary: Download an usage summary report
      description: "This API downloads a usage summary report for a specified task
        identified by usageJobId.\r

        \r

        You can provide a startTime and endTime in yyyy-MM-dd format to define
        the reporting period.\r

        The format parameter specifies the download file format, currently only
        json is supported.\r

        \r

        Upon success, the API returns the report file as a downloadable JSON
        file named summary-report-{usageJobId}.json.\r

        \r

        If the task does not exist or an error occurs during report generation,
        a 500 status code is returned with an error message.\r

        \r

        **Parameters**\r

        1. usageJobId: The unique identifier of the usage summary task to
        retrieve (required).\r

        2. startTime: Start date of the report in yyyy-MM-dd format
        (required).\r

        3. endTime: End date of the report in yyyy-MM-dd format (required).\r

        4. format: File format for download, default is json.\r

        \r

        **Notes**\r

        - Ensure the usageJobId is correct and the task exists.\r

        - The report includes data points for the specified period only.\r

        - Downloading a report does not modify or delete the task.\r\n"
      parameters:
        - name: usageJobId
          in: path
          required: true
          schema:
            type: string
            format: uuid
        - name: startTime
          in: query
          description: Start date in yyyy-MM-dd format 2025-01-01
          required: true
          schema:
            type: string
            description: Start date in yyyy-MM-dd format 2025-01-01
            default: 2025-01-01
        - name: endTime
          in: query
          description: End date in yyyy-MM-dd format 2026-01-01
          required: true
          schema:
            type: string
            description: End date in yyyy-MM-dd format 2026-01-01
            default: 2026-01-01
        - name: format
          in: query
          description: Download file format, json
          schema:
            type: string
            description: Download file format, json
            default: json
      responses:
        "200":
          description: OK
      security:
        - Bearer: []
  /api/v1/devices/{deviceId}/tunnels/sessions:
    post:
      tags:
        - ___swagger_10-tunnel-management_swagger_json_Tunnels
      summary: Create tunnel session
      description: >-
        If no client connects to a tunnel within 120 seconds of its creation,
        the tunnel will be closed automatically. 

        In addition, a tunnel's maximum lifetime is 3600 seconds, after which it
        is closed regardless of activity.
                    
        **Required fields:**

        - `serviceType` — Protocol to tunnel (e.g. `"ssh"`, `"http"`, `"vnc"`).
        Default: `"ssh"`.

        - `applicationHost` — The intranet IP address of the edge device's
        target service (e.g. `"192.168.1.100"`). Must be a valid IPv4/IPv6
        address or hostname reachable from the device's local network.

        - `applicationPort` — Port the target service is listening on (e.g. `22`
        for SSH). Range: 0–65535.

        - `purpose` — Brief justification for creating the tunnel (e.g. `"Remote
        maintenance"`).

        - `tags` — A list of free-form labels for categorization, filtering, and
        auditing (e.g. `["ops", "critical"]`). Use tags to group related
        tunnels, identify ownership, or enable dashboard filtering.
      parameters:
        - name: deviceId
          in: path
          description: The unique identifier of the target device.
          required: true
          schema:
            type: string
      requestBody:
        description: The details required to create the tunnel session.
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/CreateTunnelDto"
            example:
              serviceType: ssh
              applicationHost: 192.168.1.100
              applicationPort: 22
              purpose: Remote maintenance
              tags:
                - ops
                - critical
      responses:
        "202":
          description: Accepted
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/TunnelDto"
              example:
                tunnelSessionId: 8145286f-ba59-4ca8-961e-6338a795b98e
                deviceId: 74fe488d5d54
                serviceType: ssh
                applicationPort: 22
                applicationHost: 192.168.1.100
                creationTime: 2025-11-18T02:28:33.7315762Z
                purpose: Remote maintenance
                tags:
                  - ops
                  - critical
                sessionStatus: ESTABLISHING
                tunnelEndpoint: null
                webSsh: null
                estimatedReadyTime: null
                lastHeartbeatTime: null
                terminatedTime: null
                lastModificationTime: null
                terminationSource: null
                terminationReason: null
                links:
                  self:
                    href: https://localhost:44375/api/v1/devices/74fe488d5d54/tunnels/8145286f-ba59-4ca8-961e-6338a795b98e
                    method: GET
                  update:
                    href: https://localhost:44375/api/v1/devices/74fe488d5d54/tunnels/8145286f-ba59-4ca8-961e-6338a795b98e
                    method: PATCH
                  terminate:
                    href: https://localhost:44375/api/v1/devices/74fe488d5d54/tunnels/8145286f-ba59-4ca8-961e-6338a795b98e
                    method: DELETE
                  list:
                    href: https://localhost:44375/api/v1/devices/74fe488d5d54/tunnels
                    method: GET
        "400":
          description: Bad Request
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ProblemDetails"
              example:
                error:
                  code: ValidationError
                  message: Bad Request - Invalid request parameters
                  details: null
                  data: null
                  validationErrors:
                    - message: Request body is invalid.
                      members: []
                    - message: ApplicationHost is invalid.
                      members:
                        - ApplicationHost
        "500":
          description: Internal Server Error
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ProblemDetails"
              example:
                error:
                  code: null
                  message: An internal error occurred during your request!
                  details: null
                  data: null
                  validationErrors: null
      security:
        - Bearer: []
    get:
      tags:
        - ___swagger_10-tunnel-management_swagger_json_Tunnels
      summary: List device tunnels
      parameters:
        - name: deviceId
          in: path
          description: The unique identifier of the target device.
          required: true
          schema:
            type: string
        - name: sessionStatus
          in: query
          description: >-
            Filter by tunnel session status (ESTABLISHING, ESTABLISHED,
            TERMINATING, TERMINATED).

            If null, no status filtering is applied.
          schema:
            $ref: "#/components/schemas/TunnelSessionStatus"
        - name: serviceType
          in: query
          description: |-
            Filter by service type being tunneled (e.g., SSH, RDP).
            If null, no service type filtering is applied.
          schema:
            $ref: "#/components/schemas/ServiceType"
        - name: tags
          in: query
          description: |-
            Filter by tags. Returns tunnels that have any of the specified tags.
            Empty list means no tag filtering is applied.
          schema:
            type: array
            items:
              type: string
        - name: maxResultCount
          in: query
          description: Maximum number of results to return. Must be between 1 and 1000.
          schema:
            maximum: 1000
            minimum: 1
            type: integer
            format: int32
        - name: skipCount
          in: query
          description: Number of results to skip for pagination.
          schema:
            type: integer
            format: int32
        - name: sorting
          in: query
          description: >-
            Sorting expression for the results (e.g.,
            creationTime,sessionStatus,tags).

            Default is "CreationTime desc".
          schema:
            type: string
            default: creationTime desc
      responses:
        "200":
          description: OK
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/PagedResultDto of TunnelDto"
              example:
                totalCount: 1
                items:
                  - tunnelSessionId: 8145286f-ba59-4ca8-961e-6338a795b98e
                    deviceId: 74fe488d5d54
                    serviceType: ssh
                    applicationPort: 22
                    applicationHost: 192.168.1.100
                    creationTime: 2025-11-27T01:15:20.325367Z
                    purpose: Remote maintenance
                    tags:
                      - ops
                      - critical
                    sessionStatus: ESTABLISHED
                    tunnelEndpoint: 172.22.23.10:11100
                    webSsh: http://172.22.23.10:2222/ssh/host/172.22.23.10?port=11100
                    estimatedReadyTime: 2025-11-27T01:15:21.587Z
                    lastHeartbeatTime: 2025-11-27T01:15:21.587Z
                    terminatedTime: null
                    lastModificationTime: null
                    terminationSource: null
                    terminationReason: null
                    links:
                      self:
                        href: https://localhost:44375/api/v1/devices/74fe488d5d54/tunnels/8145286f-ba59-4ca8-961e-6338a795b98e
                        method: GET
                      update:
                        href: https://localhost:44375/api/v1/devices/74fe488d5d54/tunnels/8145286f-ba59-4ca8-961e-6338a795b98e
                        method: PATCH
                      terminate:
                        href: https://localhost:44375/api/v1/devices/74fe488d5d54/tunnels/8145286f-ba59-4ca8-961e-6338a795b98e
                        method: DELETE
                      list:
                        href: https://localhost:44375/api/v1/devices/74fe488d5d54/tunnels
                        method: GET
        "400":
          description: Bad Request
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ProblemDetails"
        "403":
          description: Forbidden
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ProblemDetails"
              example:
                error:
                  code: InvalidSortingPropertyError
                  message: "Invalid sorting property: 'creationTim'. Valid properties are:
                    CreationTime, SessionStatus, Tags"
                  details: null
                  data: null
                  validationErrors: null
        "500":
          description: Internal Server Error
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ProblemDetails"
              example:
                error:
                  code: null
                  message: An internal error occurred during your request!
                  details: null
                  data: null
                  validationErrors: null
      security:
        - Bearer: []
  /api/v1/devices/{deviceId}/tunnels/sessions/{tunnelSessionId}:
    delete:
      tags:
        - ___swagger_10-tunnel-management_swagger_json_Tunnels
      summary: Terminates an existing tunnel session
      description: >-
        Initiates a graceful or immediate shutdown of the specified tunnel
        session.
                    
        **Preconditions:** The session must be in `REQUESTED`, `ESTABLISHING`,
        `ESTABLISHED`, or `RECONNECTING` state.

        A 400 error is returned if the current `sessionStatus` is not one of the
        above.
                    
        **Request body:**

        - `reason` — Human-readable explanation for the termination.

        - `graceful` — When `true`, the agent honours the `forceTimeout` before
        hard-closing existing connections.

        - `forceTimeout` — Maximum seconds to wait for graceful closure before
        forcing (only applies when `graceful=true`).
      parameters:
        - name: deviceId
          in: path
          description: The unique identifier of the target device.
          required: true
          schema:
            type: string
        - name: tunnelSessionId
          in: path
          description: The unique identifier of the tunnel session.
          required: true
          schema:
            type: string
            format: uuid
      requestBody:
        description: Termination options and reason.
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/TerminateTunnelDto"
            example:
              reason: No longer needed
              graceful: true
              forceTimeout: 30
      responses:
        "202":
          description: Accepted
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/TunnelDto"
              example:
                tunnelSessionId: 8145286f-ba59-4ca8-961e-6338a795b98e
                deviceId: 74fe488d5d54
                serviceType: ssh
                applicationPort: 22
                applicationHost: 192.168.1.100
                creationTime: 2025-11-27T01:15:20.325367Z
                purpose: Remote maintenance
                tags:
                  - ops
                  - critical
                sessionStatus: TERMINATING
                tunnelEndpoint: 172.22.23.10:11100
                webSsh: http://172.22.23.10:2222/ssh/host/172.22.23.10?port=11100
                estimatedReadyTime: 2025-11-27T01:15:21.587Z
                lastHeartbeatTime: 2025-11-27T01:15:21.587Z
                terminatedTime: null
                lastModificationTime: null
                terminationSource: null
                terminationReason: null
                links:
                  self:
                    href: https://localhost:44375/api/v1/devices/74fe488d5d54/tunnels/8145286f-ba59-4ca8-961e-6338a795b98e
                    method: GET
                  update:
                    href: https://localhost:44375/api/v1/devices/74fe488d5d54/tunnels/8145286f-ba59-4ca8-961e-6338a795b98e
                    method: PATCH
                  terminate:
                    href: https://localhost:44375/api/v1/devices/74fe488d5d54/tunnels/8145286f-ba59-4ca8-961e-6338a795b98e
                    method: DELETE
                  list:
                    href: https://localhost:44375/api/v1/devices/74fe488d5d54/tunnels
                    method: GET
        "404":
          description: Not Found
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ProblemDetails"
              example:
                error:
                  code: ResourceNotFound
                  message: "Tunnel Session Not Found. Input tunnelSessionId:
                    3f3c1618-a6fb-4b4a-92ee-818b99491ba7"
                  details: null
                  data: null
                  validationErrors: null
        "500":
          description: Internal Server Error
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ProblemDetails"
              example:
                error:
                  code: null
                  message: An internal error occurred during your request!
                  details: null
                  data: null
                  validationErrors: null
      security:
        - Bearer: []
    get:
      tags:
        - ___swagger_10-tunnel-management_swagger_json_Tunnels
      summary: Get tunnel detail information
      parameters:
        - name: deviceId
          in: path
          description: The unique identifier of the target device.
          required: true
          schema:
            type: string
        - name: tunnelSessionId
          in: path
          description: The unique identifier of the tunnel session.
          required: true
          schema:
            type: string
            format: uuid
      responses:
        "200":
          description: OK
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/TunnelDetailDto"
              example:
                healthStatus: HEALTHY
                tunnelSessionId: 8145286f-ba59-4ca8-961e-6338a795b98e
                deviceId: 74fe488d5d54
                serviceType: ssh
                applicationPort: 22
                applicationHost: 192.168.1.100
                creationTime: 2025-11-27T01:15:20.325367Z
                purpose: Remote maintenance
                tags:
                  - ops
                  - critical
                sessionStatus: ESTABLISHED
                tunnelEndpoint: 172.22.23.10:11100
                webSsh: http://172.22.23.10:2222/ssh/host/172.22.23.10?port=11100
                estimatedReadyTime: 2025-11-27T01:15:21.587Z
                lastHeartbeatTime: 2025-11-27T01:15:21.587Z
                terminatedTime: null
                lastModificationTime: 2025-11-27T01:15:22.587Z
                terminationSource: null
                terminationReason: null
                links:
                  self:
                    href: https://localhost:44375/api/v1/devices/74fe488d5d54/tunnels/8145286f-ba59-4ca8-961e-6338a795b98e
                    method: GET
                  update:
                    href: https://localhost:44375/api/v1/devices/74fe488d5d54/tunnels/8145286f-ba59-4ca8-961e-6338a795b98e
                    method: PATCH
                  terminate:
                    href: https://localhost:44375/api/v1/devices/74fe488d5d54/tunnels/8145286f-ba59-4ca8-961e-6338a795b98e
                    method: DELETE
                  list:
                    href: https://localhost:44375/api/v1/devices/74fe488d5d54/tunnels
                    method: GET
        "403":
          description: Forbidden
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ProblemDetails"
              example:
                error:
                  code: ValidationError
                  message: Bad Request - Invalid request parameters
                  details: null
                  data: null
                  validationErrors: null
        "404":
          description: Not Found
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ProblemDetails"
              example:
                error:
                  code: ResourceNotFound
                  message: "Tunnel Session Not Found. Input tunnelSessionId:
                    3f3c1618-a6fb-4b4a-92ee-818b99491ba7"
                  details: null
                  data: null
                  validationErrors: null
        "500":
          description: Internal Server Error
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ProblemDetails"
              example:
                error:
                  code: null
                  message: An internal error occurred during your request!
                  details: null
                  data: null
                  validationErrors: null
      security:
        - Bearer: []
components:
  schemas:
    AdminInfoDto:
      type: object
      properties:
        userId:
          type: string
          description: Admin user's unique identifier
          nullable: true
        name:
          type: string
          description: Admin user's name
          nullable: true
        email:
          type: string
          description: Admin user's email address
          nullable: true
      additionalProperties: false
    AdminUserDto:
      required:
        - userId
      type: object
      properties:
        userId:
          minLength: 1
          type: string
          description: |-
            Admin user's ID.  
                Example : 783707f1-0659-4892-a872-8f506d225d7b
      additionalProperties: false
    AppUserDisplayDto:
      type: object
      properties:
        userId:
          type: string
          description: User's id
          nullable: true
        firstName:
          type: string
          description: User's first name
          nullable: true
        lastName:
          type: string
          description: User's last name
          nullable: true
        name:
          type: string
          description: User's name
          nullable: true
        email:
          type: string
          description: User's email address
          nullable: true
        role:
          type: string
          description: User role in the current system
          nullable: true
        account:
          type: string
          description: User role in the current system
          nullable: true
      additionalProperties: false
    AppUserDisplayDtoPagedResultDto:
      type: object
      properties:
        items:
          type: array
          items:
            $ref: "#/components/schemas/AppUserDisplayDto"
          nullable: true
        totalCount:
          type: integer
          format: int64
      additionalProperties: false
    CreateOrgDto:
      required:
        - name
      type: object
      properties:
        name:
          maxLength: 100
          minLength: 1
          type: string
          description: "Organization's name. Example : MainOrg"
        description:
          maxLength: 200
          minLength: 0
          type: string
          description: Organization's description. Optional, max length 200.
          nullable: true
        parentOrgId:
          type: string
          description: |2-
            
                Parent organization ID, if applicable  
                Example : 783707f1-0659-4892-a872-8f506d225d7b
          nullable: true
        admins:
          type: array
          items:
            $ref: "#/components/schemas/AdminUserDto"
          description: |-
            Organization's Admins.  
                Example : [{"userId": "admin1"}, {"userId": "admin2"}]
          nullable: true
      additionalProperties: false
    CreateOrgResponseDto:
      type: object
      properties:
        name:
          type: string
          description: Organization's name
          nullable: true
        orgId:
          type: string
          description: Organization's unique identifier
          format: uuid
        parentOrgId:
          type: string
          description: Parent organization ID, if applicable
          format: uuid
          nullable: true
        description:
          type: string
          description: Organization's description
          nullable: true
        admins:
          type: array
          items:
            $ref: "#/components/schemas/OrgUserCreateResponseDto"
          description: Organization's Admins
          nullable: true
        dateCreated:
          type: string
          description: Organization's creation time
          format: date-time
        dateModified:
          type: string
          description: Organization's last modification time
          format: date-time
          nullable: true
      additionalProperties: false
    CreatePatDto:
      required:
        - name
      type: object
      properties:
        name:
          minLength: 1
          type: string
          description: "Display name of the Client Credential. Example: my-device-token"
        expiredAt:
          type: string
          description: "Expiration time in ISO 8601 format. Example: 2025-09-01T00:00:00Z"
          format: date-time
          nullable: true
        scopes:
          minItems: 1
          type: array
          items:
            type: string
          description: "List of access scopes granted to this credential. Each scope maps
            to a JWT 'scope' claim. Example: 'dataobject.read', 'object.write',
            'telemetry.write'."
          nullable: true
        deviceIds:
          type: array
          items:
            type: string
          description: List of device IDs associated with this credential. Each ID becomes
            a 'device_id' claim in the issued JWT. Optional.
          nullable: true
      additionalProperties: false
    CreateUpdateOrgDto:
      required:
        - name
      type: object
      properties:
        name:
          maxLength: 100
          minLength: 1
          type: string
          description: "Organization's name. Example : MainOrg"
        description:
          maxLength: 200
          minLength: 0
          type: string
          description: Organization's description. Optional, max length 200.
          nullable: true
      additionalProperties: false
    CreateUpdateOrgUserDtoNoOrg:
      required:
        - orgRole
        - userId
      type: object
      properties:
        userId:
          minLength: 1
          type: string
          description: "The ID of the user to be added to the organization. Example :
            783707f1-0659-4892-a872-8f506d225d7b"
        orgRole:
          minLength: 1
          type: string
          description: The user's role within the organization. Accepts 'admin'
            (case-insensitive).
      additionalProperties: false
    OrgDto:
      type: object
      properties:
        name:
          type: string
          description: Organization's name
          nullable: true
        orgId:
          type: string
          description: Organization's unique identifier
          format: uuid
        parentOrgId:
          type: string
          description: Parent organization ID, if applicable
          format: uuid
          nullable: true
      additionalProperties: false
    OrgDtoPagedResultDto:
      type: object
      properties:
        items:
          type: array
          items:
            $ref: "#/components/schemas/OrgDto"
          nullable: true
        totalCount:
          type: integer
          format: int64
      additionalProperties: false
    OrgTreeDetailDto:
      type: object
      properties:
        orgId:
          type: string
          description: Organization's unique identifier
          format: uuid
        parentOrgId:
          type: string
          description: Parent organization ID, if applicable
          format: uuid
          nullable: true
        name:
          type: string
          description: Organization's name
          nullable: true
        description:
          type: string
          description: Organization's description
          nullable: true
        admins:
          type: array
          items:
            $ref: "#/components/schemas/AdminInfoDto"
          description: List of admin users for the organization
          nullable: true
        orgRole:
          $ref: "#/components/schemas/OrgUserRole"
        dateCreated:
          type: string
          description: Date when the organization was created
          format: date-time
        dateModified:
          type: string
          description: Date when the organization was last modified
          format: date-time
          nullable: true
        children:
          type: array
          items:
            $ref: "#/components/schemas/OrgTreeDetailDto"
          description: Child organizations under this organization
          nullable: true
      additionalProperties: false
    OrgTreeDetailDtoPagedResultDto:
      type: object
      properties:
        items:
          type: array
          items:
            $ref: "#/components/schemas/OrgTreeDetailDto"
          nullable: true
        totalCount:
          type: integer
          format: int64
      additionalProperties: false
    OrgTreeDto:
      type: object
      properties:
        orgId:
          type: string
          description: Organization's unique identifier
          format: uuid
        name:
          type: string
          description: Organization's name
          nullable: true
        parentOrgId:
          type: string
          description: Parent organization ID, if applicable
          format: uuid
          nullable: true
        children:
          type: array
          items:
            $ref: "#/components/schemas/OrgTreeDto"
          description: Child organizations under this organization
          nullable: true
      additionalProperties: false
    OrgUserCreateResponseDto:
      type: object
      properties:
        userId:
          type: string
          description: The ID of the user to be added to the organization
          nullable: true
        orgRole:
          $ref: "#/components/schemas/OrgUserRole"
        name:
          type: string
          description: User's name
          nullable: true
      additionalProperties: false
    OrgUserDeskDto:
      required:
        - orgId
        - userId
      type: object
      properties:
        userId:
          type: string
          description: The ID of the user to be added to the organization
          nullable: true
        orgRole:
          $ref: "#/components/schemas/OrgUserRole"
        name:
          type: string
          description: User's name
          nullable: true
        email:
          type: string
          description: User's email address
          nullable: true
        role:
          type: string
          description: User's role
          nullable: true
        orgId:
          type: string
          description: The ID of the organization
          nullable: true
        createdAt:
          type: string
          description: The time when the user was added to this organization
          format: date-time
        updatedAt:
          type: string
          description: The last time this user's settings were modified in this organization
          format: date-time
          nullable: true
      additionalProperties: false
    OrgUserDeskDtoCustomPagedResultDto:
      type: object
      properties:
        items:
          type: array
          items:
            $ref: "#/components/schemas/OrgUserDeskDto"
          nullable: true
        totalCount:
          type: integer
          format: int64
        skipCount:
          type: integer
          description: Number of items to skip
          format: int32
        maxResultCount:
          type: integer
          description: Maximum number of items to return
          format: int32
        totalPages:
          type: integer
          description: Total number of pages available based on the total count and max
            result count
          format: int32
          readOnly: true
      additionalProperties: false
    OrgUserDto:
      required:
        - userId
      type: object
      properties:
        id:
          type: string
          format: uuid
        orgId:
          type: string
          description: The ID of the organization
          format: uuid
        userId:
          type: string
          description: The ID of the user to be added to the organization
          nullable: true
        orgRole:
          $ref: "#/components/schemas/OrgUserRole"
        name:
          type: string
          description: User's name
          nullable: true
      additionalProperties: false
    OrgUserRole:
      enum:
        - super_admin
        - admin
        - operator_
        - viewer
      type: string
    PatDetailDto:
      type: object
      properties:
        clientCredentialId:
          type: string
          format: uuid
        name:
          type: string
          nullable: true
        clientId:
          type: string
          nullable: true
        clientSecret:
          type: string
          nullable: true
        createdAt:
          type: string
          format: date-time
        expiredAt:
          type: string
          format: date-time
          nullable: true
      additionalProperties: false
    PatDto:
      type: object
      properties:
        clientCredentialId:
          type: string
          format: uuid
        name:
          type: string
          nullable: true
        clientId:
          type: string
          nullable: true
        createdAt:
          type: string
          description: "timestamp in ISO 8601 format. Example: 2025-09-01T00:00:00Z"
          format: date-time
        expiredAt:
          type: string
          description: "timestamp in ISO 8601 format. Example: 2025-09-01T00:00:00Z"
          format: date-time
          nullable: true
        scopes:
          type: array
          items:
            type: string
          nullable: true
        deviceIds:
          type: array
          items:
            type: string
          nullable: true
      additionalProperties: false
    RefreshGrantType:
      enum:
        - refresh_token
      type: string
    RemoteServiceErrorInfo:
      type: object
      properties:
        code:
          type: string
          nullable: true
        message:
          type: string
          nullable: true
        details:
          type: string
          nullable: true
        data:
          type: object
          additionalProperties: {}
          nullable: true
        validationErrors:
          type: array
          items:
            $ref: "#/components/schemas/RemoteServiceValidationErrorInfo"
          nullable: true
      additionalProperties: false
    RemoteServiceErrorResponse:
      type: object
      properties:
        error:
          $ref: "#/components/schemas/RemoteServiceErrorInfo"
      additionalProperties: false
    RemoteServiceValidationErrorInfo:
      type: object
      properties:
        message:
          type: string
          nullable: true
        members:
          type: array
          items:
            type: string
          nullable: true
      additionalProperties: false
    Success:
      type: object
      additionalProperties: false
    TokenBodyDto:
      type: object
      properties:
        token:
          type: string
          nullable: true
        refreshToken:
          type: string
          nullable: true
      additionalProperties: false
    TokenResultDto:
      type: object
      properties:
        accessToken:
          type: string
          nullable: true
        refreshToken:
          type: string
          nullable: true
        expiresIn:
          type: integer
          format: int32
        tokenType:
          type: string
          nullable: true
      additionalProperties: false
    UpdateOrgResponseDto:
      type: object
      properties:
        orgId:
          type: string
          description: Organization's unique identifier
          format: uuid
        name:
          type: string
          description: Updated organization name
          nullable: true
        description:
          type: string
          description: Updated organization description
          nullable: true
        dateModified:
          type: string
          description: Last modification time in ISO 8601 format
          format: date-time
          nullable: true
      additionalProperties: false
    ViewType:
      enum:
        - page
        - list
        - tree
      type: string
    BasicInfoDto:
      type: object
      properties:
        basicInfoId:
          type: string
          description: Node cache unique identifier
          format: uuid
        deviceName:
          type: string
          description: Node name
          nullable: true
        type:
          $ref: "#/components/schemas/DeviceType"
        status:
          $ref: "#/components/schemas/EdgeSyncDeviceStatus"
        deviceId:
          type: string
          description: Node identifier (DeviceId or VirtualNodeId)
          nullable: true
        creationTime:
          type: string
          description: Node creation time
          format: date-time
      additionalProperties: false
      description: Node basic information cache data transfer object
    BasicInfoDtoPagedResultDto:
      type: object
      properties:
        items:
          type: array
          items:
            $ref: "#/components/schemas/BasicInfoDto"
          nullable: true
        totalCount:
          type: integer
          format: int64
      additionalProperties: false
    DeviceCapContainerDto:
      type: object
      properties:
        image:
          type: string
          nullable: true
        resourceName:
          type: string
          nullable: true
        containerName:
          type: string
          nullable: true
        deviceResourceId:
          type: string
          nullable: true
      additionalProperties: false
    DeviceCapCpuDto:
      type: object
      properties:
        numOfCores:
          type: integer
          format: int32
        resourceName:
          type: string
          nullable: true
        deviceResourceId:
          type: string
          nullable: true
        processorArchitecture:
          type: string
          nullable: true
        processorManufacturer:
          type: string
          nullable: true
      additionalProperties: false
    DeviceCapDataDto:
      type: object
      properties:
        deviceCapsDto:
          type: array
          items:
            $ref: "#/components/schemas/DeviceCapsDto"
          nullable: true
      additionalProperties: false
    DeviceCapDesiredDto:
      type: object
      additionalProperties: false
    DeviceCapDiskDto:
      type: object
      properties:
        diskType:
          type: string
          nullable: true
        totalSize:
          type: number
          format: double
        resourceName:
          type: string
          nullable: true
        deviceResourceId:
          type: string
          nullable: true
      additionalProperties: false
    DeviceCapMainboardExtensionDto:
      type: object
      properties:
        deviceId:
          type: string
          nullable: true
        updatedAt:
          type: string
          format: date-time
          nullable: true
        sensorCount:
          type: integer
          format: int32
      additionalProperties: false
    DeviceCapNetworkInterfaceDto:
      type: object
      properties:
        macAddress:
          type: string
          nullable: true
        resourceName:
          type: string
          nullable: true
        interfaceType:
          type: string
          nullable: true
        deviceResourceId:
          type: string
          nullable: true
      additionalProperties: false
    DeviceCapRamDto:
      type: object
      properties:
        totalMemory:
          type: number
          format: double
        resourceName:
          type: string
          nullable: true
        deviceResourceId:
          type: string
          nullable: true
      additionalProperties: false
    DeviceCapReportedDto:
      type: object
      properties:
        osName:
          type: string
          nullable: true
        manufacturer:
          type: string
          nullable: true
        model:
          type: string
          nullable: true
        serialNumber:
          type: string
          nullable: true
        swVersion:
          type: string
          nullable: true
        timestamp:
          type: string
          nullable: true
        cpu:
          $ref: "#/components/schemas/DeviceCapCpuDto"
        ram:
          $ref: "#/components/schemas/DeviceCapRamDto"
        disks:
          type: array
          items:
            $ref: "#/components/schemas/DeviceCapDiskDto"
          nullable: true
        networkInterfaces:
          type: array
          items:
            $ref: "#/components/schemas/DeviceCapNetworkInterfaceDto"
          nullable: true
        sensors:
          type: array
          items:
            $ref: "#/components/schemas/DeviceCapSensorDto"
          nullable: true
        subNodes:
          type: array
          items:
            $ref: "#/components/schemas/DeviceCapSubNodeDto"
          nullable: true
        containers:
          type: array
          items:
            $ref: "#/components/schemas/DeviceCapContainerDto"
          nullable: true
        mainboardExtension:
          $ref: "#/components/schemas/DeviceCapMainboardExtensionDto"
      additionalProperties: false
    DeviceCapResponseDto:
      type: object
      properties:
        cmd:
          type: string
          nullable: true
        seqId:
          type: integer
          format: int64
        reqSeqId:
          type: string
          nullable: true
        rspSeqId:
          type: string
          nullable: true
        timestamp:
          type: integer
          format: int64
        data:
          $ref: "#/components/schemas/DeviceCapDataDto"
      additionalProperties: false
    DeviceCapSensorDto:
      type: object
      properties:
        dtmi:
          type: string
          nullable: true
        name:
          type: string
          nullable: true
        resourceId:
          type: string
          nullable: true
        resourceShortId:
          type: string
          nullable: true
        deviceResourceId:
          type: string
          nullable: true
      additionalProperties: false
    DeviceCapShadowDataDto:
      type: object
      properties:
        reported:
          $ref: "#/components/schemas/DeviceCapReportedDto"
        desired:
          $ref: "#/components/schemas/DeviceCapDesiredDto"
      additionalProperties: false
    DeviceCapSubNodeDto:
      type: object
      properties:
        deviceId:
          type: string
          nullable: true
        updatedAt:
          type: string
          format: date-time
          nullable: true
        deviceName:
          type: string
          nullable: true
        deviceType:
          type: string
          nullable: true
      additionalProperties: false
    DeviceCapsDto:
      type: object
      properties:
        creationTime:
          type: string
          format: date-time
        groupId:
          type: string
          nullable: true
        deviceId:
          type: string
          nullable: true
        data:
          $ref: "#/components/schemas/DeviceCapShadowDataDto"
      additionalProperties: false
    DeviceCustomInfoDto:
      required:
        - deviceId
      type: object
      properties:
        deviceId:
          type: string
          description: Device id
          nullable: true
        key:
          type: string
          description: custom info key
          nullable: true
        value:
          type: string
          description: custom info value
          nullable: true
        datatype:
          type: string
          description: custom info data type
          nullable: true
      additionalProperties: false
      description: Device custom info
    DeviceCustomInfoPatchDto:
      type: object
      properties:
        value:
          type: string
          description: new value for the custom info entry
          nullable: true
      additionalProperties: false
      description: JSON object containing the new value for the specified key
    DeviceToggle:
      enum:
        - activate
        - deactivate
      type: string
    DeviceType:
      enum:
        - WedaNode
        - SubNode
        - CustomDevice
      type: string
    EdgeSyncDeviceCreateDto:
      required:
        - deviceId
        - hwModel
      type: object
      properties:
        deviceId:
          type: string
          description: Device UID
          nullable: true
        hwModel:
          type: string
          description: Device hardware model
          nullable: true
        deviceName:
          type: string
          description: Device name
          nullable: true
      additionalProperties: false
      description: Device data transfer object
    EdgeSyncDeviceDto:
      required:
        - deviceId
        - hwModel
        - orgId
      type: object
      properties:
        deviceId:
          type: string
          description: Device id
          nullable: true
        hwModel:
          type: string
          description: Device hardware model
          nullable: true
        orgId:
          type: string
          description: Organization id
          nullable: true
        status:
          type: string
          description: Device current status.
          nullable: true
        deviceName:
          type: string
          description: Device name.
          nullable: true
      additionalProperties: false
      description: Device data transfer object
    EdgeSyncDeviceGetResponseDto:
      required:
        - deviceId
        - hwModel
      type: object
      properties:
        deviceId:
          type: string
          description: Device id
          nullable: true
        hwModel:
          type: string
          description: Device hardware model
          nullable: true
        orgId:
          type: string
          description: Org id
          nullable: true
        status:
          type: string
          description: Device current status.
          nullable: true
        creationTime:
          type: string
          description: Device creation time.
          format: date-time
          nullable: true
        deviceName:
          type: string
          description: Device name.
          nullable: true
      additionalProperties: false
      description: Device data transfer object
    EdgeSyncDeviceGetResponseDtoPagedResultDto:
      type: object
      properties:
        items:
          type: array
          items:
            $ref: "#/components/schemas/EdgeSyncDeviceGetResponseDto"
          nullable: true
        totalCount:
          type: integer
          format: int64
      additionalProperties: false
    EdgeSyncDeviceStatus:
      enum:
        - Registered
        - Activated
        - Deactivated
      type: string
    EdgeSyncDeviceUpdateRequestDto:
      type: object
      properties:
        orgId:
          type: string
          description: Organization ID
          nullable: true
        deviceName:
          type: string
          description: Device name
          nullable: true
      additionalProperties: false
      description: Payload to update device
    EdgeSyncDeviceUpdateResponseDto:
      required:
        - hwModel
      type: object
      properties:
        deviceId:
          type: string
          description: Device id
          nullable: true
        orgId:
          type: string
          description: Org id
          nullable: true
        hwModel:
          type: string
          description: Device hardware model
          nullable: true
        status:
          $ref: "#/components/schemas/EdgeSyncDeviceStatus"
        deviceName:
          type: string
          description: Device name
          nullable: true
      additionalProperties: false
      description: Device data transfer object
    ProblemDetails:
      type: object
      properties:
        type:
          type: string
          nullable: true
        title:
          type: string
          nullable: true
        status:
          type: integer
          format: int32
          nullable: true
        detail:
          type: string
          nullable: true
        instance:
          type: string
          nullable: true
      additionalProperties: {}
    ProvisionServiceType:
      enum:
        - MQTT
        - NATS
      type: string
    SensorInfo:
      required:
        - description
        - displayName
        - schema
      type: object
      properties:
        schema:
          type: string
          nullable: true
        displayName:
          type: string
          nullable: true
        description:
          type: string
          nullable: true
      additionalProperties: false
    SubNodeDeviceConfigForEndUserDto:
      required:
        - deviceName
      type: object
      properties:
        enabled:
          type: boolean
          description: Indicates if all sub-nodes sensors are enabled
        deviceName:
          minLength: 1
          pattern: .*\S.*
          type: string
          description: Name of the device for identification
        sensors:
          type: array
          items:
            $ref: "#/components/schemas/SubNodeSensorConfigForUserDto"
          description: List of sensor configurations for the device
          nullable: true
      additionalProperties: false
    SubNodeSensorConfigForUserDto:
      type: object
      properties:
        name:
          type: string
          description: Unique identifier for the sensor (e.g., AI_0, DI_0, DO_0)
          nullable: true
        config:
          $ref: "#/components/schemas/SubNodeSensorRuntimeConfigForUserDto"
        sensorInfo:
          $ref: "#/components/schemas/SensorInfo"
      additionalProperties: false
    SubNodeSensorRuntimeConfigForUserDto:
      type: object
      properties:
        enabled:
          type: boolean
          description: Indicates if the sensor is actively collecting data
        interval:
          type: integer
          description: Data collection interval in milliseconds (e.g., 1000 = 1 second)
          format: int32
      additionalProperties: false
    CommandExecutionResultCacheDto:
      type: object
      properties:
        deviceId:
          type: string
          description: The unique identifier of the device that executed the command.
          nullable: true
        seqId:
          type: integer
          description: Sequential identifier of the original command request that was
            executed.
          format: int64
        reqSeqId:
          type: string
          description: Unique request sequence identifier from the original command for
            correlation.
          nullable: true
        rspSeqId:
          type: string
          description: Unique response sequence identifier generated by the device for
            this execution result.
          nullable: true
        cmd:
          type: string
          description: The command type identifier. Default value is "deviceCmd" for
            device commands.
          nullable: true
        data:
          $ref: "#/components/schemas/CommandExecutionResultDataCacheDto"
      additionalProperties: false
      description: >-
        Cached result of a device command execution. Stores both protocol
        metadata and execution result data

        for tracking and request/response correlation.
                    
        - `deviceId`: Edge device identifier that executed the command (e.g.
        "74fe488d5d54").

        - `seqId`: Sequential identifier of the original command request.

        - `reqSeqId`: Original request sequence ID (UUID) for correlation.

        - `rspSeqId`: Response sequence ID (UUID) generated by the device for
        this execution result.

        - `cmd`: Command type identifier (default "deviceCmd").

        - `data`: Detailed execution result data including status, timing, and
        output.
    CommandExecutionResultDataCacheDto:
      type: object
      properties:
        deviceCmd:
          type: string
          description: >-
            The specific device command that was executed.

            Possible values include: stack, stack.start, stack.stop,
            stack.restart, stack.pause, stack.resume
          nullable: true
        status:
          type: integer
          description: >-
            The execution status code indicating success or failure.

            Typically follows HTTP status code conventions (e.g., 200 for
            success, 400+ for errors).
          format: int32
        message:
          type: string
          description: Human-readable message describing the execution result, error
            details, or status information.
          nullable: true
        resultData:
          type: object
          additionalProperties: {}
          description: >-
            Additional result data produced by the command execution, such as
            container states,

            stack information, or error details in key-value format.
          nullable: true
        executedAt:
          type: string
          description: ISO 8601 format timestamp indicating when the command execution
            began on the device.
          nullable: true
        completedAt:
          type: string
          description: ISO 8601 format timestamp indicating when the command execution
            completed on the device.
          nullable: true
      additionalProperties: false
      description: >-
        Detailed execution result data for a device command, including status,
        timing, and any result data.
                    
        - `deviceCmd`: The specific device command that was executed. Possible
        values include: "stack", "stack.start", "stack.stop", "stack.restart",
        "stack.pause", "stack.resume".

        - `status`: Execution status code following HTTP-like conventions (200 =
        success, 400+ = errors).

        - `message`: Human-readable message describing the execution result,
        error details, or status.

        - `resultData`: Additional result data in key-value format (e.g.
        container states, error details).

        - `executedAt`: ISO 8601 timestamp when execution began on the device.

        - `completedAt`: ISO 8601 timestamp when execution completed on the
        device.
    CommandRequest:
      type: object
      properties:
        stackConfigId:
          type: string
          description: An unique ID for the stack configuration.
          format: uuid
      additionalProperties: false
      description: >-
        Marker payload for a stack-targeted device command request.
                    
        - `stackConfigId`: Unique stack configuration ID (GUID) the command
        targets.
    ContainerDto:
      type: object
      properties:
        id:
          type: string
          nullable: true
        name:
          type: string
          nullable: true
        state:
          $ref: "#/components/schemas/ContainerState"
        error:
          $ref: "#/components/schemas/ContainerErrorDto"
      additionalProperties: false
      description: >-
        Identifies a container instance within a deployed stack and reports its
        current runtime state.

        State reflects what the device last reported and is updated on lifecycle
        events (start, stop, restart, error).
                    
        - `id`: Container ID (Docker container ID format, e.g. "abc123def456").

        - `name`: Container name as defined in the Docker Compose file (e.g.
        "inference-service").

        - `state`: Current runtime state. Values: "created", "running",
        "paused", "restarting", "exited", "dead".

        - `error`: Most recent error reported by the device for this container;
        null if healthy.
    ContainerErrorDto:
      type: object
      properties:
        code:
          type: string
          description: |-
            Error code identifying the type of error. Common values include
            `OOMKilled`, `ImagePullBackOff`, `ErrImagePull`, `CrashLoopBackOff`,
            `ContainerCannotRun`, `Created`, `Unhealthy`. Treat unknown codes as
            informational and rely on `message` / `details` for context.
          nullable: true
        message:
          type: string
          description: Human-readable error message describing the issue.
          nullable: true
        timestamp:
          type: string
          description: UTC timestamp (ISO 8601) when the error was observed by the device.
          format: date-time
        details:
          type: object
          additionalProperties: {}
          description: >-
            Additional error details and context (e.g., `exitCode`, `image`,

            `container`, `logSnippet`). Schema is intentionally open — keys
            depend

            on the error `code`.
          nullable: true
      additionalProperties: false
      description: >-
        Structured error information for a container, as last reported by the
        device.
                    
        - `code`: Error code (e.g. "OOMKilled", "ImagePullBackOff",
        "ErrImagePull", "CrashLoopBackOff", "ContainerCannotRun", "Created",
        "Unhealthy"). Treat unknown codes as informational.

        - `message`: Human-readable error message describing the issue.

        - `timestamp`: UTC timestamp (ISO 8601) when the error was observed by
        the device.

        - `details`: Open-schema additional context whose keys depend on `code`.
        Example: { "exitCode": 137, "image": "nginx:latest", "container":
        "web-1", "logSnippet": "..." }.
    ContainerStackDto:
      type: object
      properties:
        stackConfigId:
          type: string
          format: uuid
        stackRevisionId:
          type: string
          format: uuid
        stackName:
          type: string
          nullable: true
        type:
          type: string
          nullable: true
        composeFileContent:
          type: string
          nullable: true
        environment:
          type: object
          additionalProperties: {}
          nullable: true
        description:
          type: string
          nullable: true
        creationTime:
          type: string
          format: date-time
        orgId:
          type: string
          format: uuid
        version:
          type: integer
          format: int32
      additionalProperties: false
      description: >-
        Data transfer object representing a container stack with its
        configuration and runtime information.

        Used for transferring stack data between API endpoints and client
        applications.
                    
        Behavior:

        - Immutable versions: each version of a stack is immutable once created.

        - Auto-increment versioning: version numbers are automatically assigned
        and incremented.

        - Base64 content: ComposeFileContent must be Base64-encoded Docker
        Compose YAML.

        - Status values: Pending, Deploying, Enabled, Stopped, Error.
                    
        Properties:

        - `stackConfigId`: Stack series ID (GUID). Constant across all versions
        of the same logical stack.

        - `stackRevisionId`: Specific revision/version ID (GUID). Primary key
        for API operations.

        - `stackName`: Human-readable stack name. Max 128 chars; case-sensitive
        uniqueness across versions.

        - `type`: Container stack type (e.g. "compose"). Max 128 chars.

        - `composeFileContent`: Base64-encoded Docker Compose YAML content.
        Decoded content must be valid docker-compose.yml.

        - `environment`: Optional environment variables (key-value). Keys are
        valid env var names; values may be strings, numbers, booleans, or JSON
        objects. Example: { "MODEL_PATH": "/opt/models/yolo.onnx",
        "GPU_ENABLED": "true", "LOG_LEVEL": "info" }.

        - `description`: Optional free-form description (max 1024 chars).

        - `creationTime`: Auto-generated creation time (ISO 8601 UTC).

        - `orgId`: Owning organization identifier (GUID).

        - `version`: Auto-incremented revision number. Combination of stack-name
        + version is unique.
    ContainerState:
      enum:
        - unknown
        - created
        - running
        - paused
        - restarting
        - removing
        - exited
        - dead
        - unhealthy
        - error
      type: string
      description: >-
        Runtime state of a single container, as reported by the device.
                    
        - `unknown`: State could not be determined or the device did not report
        a recognized value.

        - `created`: Container has been created but not yet started. Transient —
        the daemon has provisioned the container but the entrypoint has not run.

        - `running`: Container process is up. Healthy steady state.

        - `paused`: Container is paused (SIGSTOP-equivalent). Set by
        `stack.pause`.

        - `restarting`: Container is being restarted, typically by the restart
        policy. Repeated visits here while `restartCount` climbs indicate
        flapping.

        - `removing`: Container is being torn down. Transient; expected during
        undeploy / update / device reset.

        - `exited`: Container process has terminated. Inspect
        `errors[].details.exitCode` (when populated) to classify clean exit vs
        crash.

        - `dead`: Daemon could not stop the container cleanly and has marked it
        as dead. Operator intervention required (typically `docker rm -f` on the
        device, or device reset).

        - `unhealthy`: Healthcheck has reported failure. Container is up but not
        serving.

        - `error`: Generic error state reported by the agent when the daemon
        returns a non-standard state. Read `reason` at the deployment level for
        context.
    CreateContainerStackDto:
      required:
        - composeFileContent
        - stackName
        - type
      type: object
      properties:
        stackName:
          maxLength: 63
          minLength: 1
          type: string
          default: my-first-stack
        type:
          minLength: 1
          type: string
          format: Enumeration
          default: compose
        composeFileContent:
          minLength: 1
          type: string
          default: dmVyc2lvbjogIjMuOCIKc2VydmljZXM6CiAgbmdpbng6CiAgICBpbWFnZTogbmdpbng6bGF0ZXN0CiAgICBwb3J0czoKICAgICAgLSAiODA6ODAiCiAgICB2b2x1bWVzOgogICAgICAtIC4vaHRtbDovdXNyL3NoYXJlL25naW54L2h0bWw=
        environment:
          type: object
          additionalProperties: {}
          nullable: true
        description:
          type: string
          nullable: true
      additionalProperties: false
      description: |-
        Data transfer object for creating a new container stack.
                    
        Business rules:
        - No duplicate stack names allowed: Stack name must be unique across all versions.
        - Auto-versioning: Version is automatically assigned starting from 1.
        - Base64 encoding required: ComposeFileContent must be valid Base64-encoded Docker Compose YAML.
        - Validation: All required fields are validated before stack creation.
                    
        Properties:
        - `StackName` (required): Stack name. Max 63 chars; allowed chars are lowercase letters, digits and hyphens (-) only; must start and end with a letter or digit; no consecutive hyphens; case-sensitive uniqueness across all stacks. Example: "my-first-stack".
        - `Type` (required): Container stack deployment type. Currently the only supported value is "compose".
        - `ComposeFileContent` (required): Base64-encoded Docker Compose YAML. Decoded content must be a valid docker-compose.yml defining services, images, ports, volumes, etc. Example default value (Base64): "dmVyc2lvbjogIjMuOCIKc2VydmljZXM6CiAgbmdpbng6CiAgICBpbWFnZTogbmdpbng6bGF0ZXN0Li4u" which decodes to a simple nginx service exposing port 80.
        - `Environment` (optional): Environment variables and configuration parameters for the stack. Keys must be valid env var names (alphanumeric, case-sensitive); values may be strings, numbers, booleans, or JSON objects (must be JSON-serializable); referenced inside the compose file via ${VARIABLE_NAME}. Example: { "MODEL_PATH": "/opt/models/yolo.onnx", "GPU_ENABLED": "true", "LOG_LEVEL": "info", "REPLICA_COUNT": 3, "FEATURE_FLAGS": { "enableTracing": true, "maxBatchSize": 16 } }.
        - `Description` (optional): Free-form description of the stack. Max 1024 characters.
    CreateRegistryDto:
      required:
        - registryCredentials
        - registryName
        - registryUrl
      type: object
      properties:
        registryName:
          maxLength: 32
          minLength: 0
          type: string
          description: Name of the registry. Must be unique within the organization.
          default: harbor-ecr-sync
        registryUrl:
          minLength: 1
          type: string
          description: URL of the container registry.
          format: uri
          default: https://registry.dev.company.com
        registryCredentials:
          $ref: "#/components/schemas/RegistryCredentials"
      additionalProperties: false
      description: >-
        Data transfer object for creating a new container registry
        configuration.
                    
        - `RegistryName` (required): Registry display name. Max 32 chars; must
        be unique within the organization. Example: "harbor-ecr-sync".

        - `RegistryUrl` (required): URL of the container registry. Must be a
        valid HTTP/HTTPS URL following Docker registry conventions. Example:
        "https://registry.dev.company.com".

        - `RegistryCredentials` (required): Credentials for the registry.
        Polymorphic type by `registryType` discriminator: "DockerHub", "AwsECR",
        "AzureACR", "Custom".
    CreateUpdateStackDeploymentsDto:
      required:
        - deviceIds
      type: object
      properties:
        deviceIds:
          maxItems: 128
          minItems: 1
          type: array
          items:
            type: string
      additionalProperties: false
      description: >-
        Data transfer object for deploying a container stack to multiple devices
        simultaneously.
                    
        Behavior:

        - Batch deployment: deploys one stack to multiple devices in a single
        operation.

        - Intelligent conflict resolution per device: Skip (same version already
        deployed), Update (different version of same stack), Add (no version of
        this stack).

        - Parallel processing: devices are processed in parallel.

        - Shared deployment ID: all devices share the same StackDeploymentId for
        batch tracking.

        - Comprehensive reporting: returns detailed statistics and per-device
        action results.
                    
        Properties:

        - `DeviceIds` (required): List of edge device identifiers (12-char hex,
        e.g. "74fe488d5d54"). Min 1, max 128 entries; case-sensitive; duplicates
        are de-duplicated.
    EncryptedCredentials:
      type: object
      additionalProperties: false
      description: >-
        Polymorphic base class for encrypted registry credentials.

        The concrete type is selected by the `registryType` JSON discriminator.
                    
        - `RegistryType`: Registry kind discriminator. Allowed values: "Custom",
        "DockerHub", "AzureACR", "AwsECR". Required; cannot be null/empty.
    PagedResultDto  of  CommandExecutionResultCacheDto:
      type: object
      properties:
        items:
          type: array
          items:
            $ref: "#/components/schemas/CommandExecutionResultCacheDto"
          nullable: true
        totalCount:
          type: integer
          format: int64
      additionalProperties: false
    PagedResultDto  of  ContainerStackDto:
      type: object
      properties:
        items:
          type: array
          items:
            $ref: "#/components/schemas/ContainerStackDto"
          nullable: true
        totalCount:
          type: integer
          format: int64
      additionalProperties: false
    PagedResultDto  of  RegistryDto:
      type: object
      properties:
        items:
          type: array
          items:
            $ref: "#/components/schemas/RegistryDto"
          nullable: true
        totalCount:
          type: integer
          format: int64
      additionalProperties: false
    RegistryCredentials:
      type: object
      additionalProperties: false
      description: >-
        Polymorphic base class for plain-text registry credentials submitted via
        API.

        The concrete type is selected by the `registryType` JSON discriminator.

        Allowed registryType values: "DockerHub", "AwsECR", "AzureACR",
        "Custom".

        Subclasses provide their own validation rules.
    RegistryDto:
      type: object
      properties:
        registryId:
          type: string
          description: Identifier of the registry.
          format: uuid
        registryName:
          type: string
          nullable: true
        registryUrl:
          type: string
          nullable: true
        creationTime:
          type: string
          format: date-time
        registryEncryptedCredentials:
          $ref: "#/components/schemas/EncryptedCredentials"
        orgId:
          type: string
          nullable: true
      additionalProperties: false
      description: >-
        Data transfer object representing a container registry configuration.
                    
        - `registryId`: Unique identifier of the registry (GUID).

        - `registryName`: Registry display name (max 32 chars, ASCII printable,
        unique within the organization).

        - `registryUrl`: HTTP/HTTPS URL of the registry following Docker
        registry conventions (e.g. "https://registry.dev.company.com").

        - `creationTime`: Auto-generated registry creation time (ISO 8601 UTC).

        - `registryEncryptedCredentials`: Server-side encrypted credentials
        (polymorphic by registryType).

        - `orgId`: Owning organization identifier.
    StackAction:
      enum:
        - start
        - stop
        - pause
        - resume
        - restart
      type: string
      description: >-
        Runtime lifecycle commands that can be issued to a deployed stack on an
        edge device.
                    
        - `start`: Start all containers in the stack (from stopped state). Maps
        to "stack.start".

        - `stop`: Stop all running containers in the stack gracefully. Maps to
        "stack.stop".

        - `pause`: Pause (freeze) all containers in the stack without removing
        them. Maps to "stack.pause".

        - `resume`: Resume (unpause) all paused containers in the stack. Maps to
        "stack.resume".

        - `restart`: Stop then start all containers in the stack. Maps to
        "stack.restart".
    StackDeploymentDto:
      type: object
      properties:
        stackConfigId:
          type: string
          description: Unique identifier for the stack series, used for grouping different
            versions of the same stack.
          format: uuid
        stackRevisionId:
          type: string
          description: Gets or sets the unique identifier for the deployment revision.
          format: uuid
        deploymentId:
          type: string
          description: Gets or sets the unique identifier for the deployment.
          format: uuid
        taskId:
          type: string
          description: Gets or sets the unique identifier for the deployment task.
          format: uuid
        stackName:
          type: string
          description: Gets or sets the name of the stack being deployed.
          nullable: true
        deviceId:
          type: string
          description: Gets or sets the identifier of the target device for deployment.
          nullable: true
        version:
          type: string
          description: Gets or sets the version of the stack being deployed.
          nullable: true
        status:
          $ref: "#/components/schemas/StackDeploymentStatus"
        containers:
          type: array
          items:
            $ref: "#/components/schemas/ContainerDto"
          description: Gets or sets the collection of containers that are part of this
            stack deployment.
          nullable: true
        error:
          type: object
          additionalProperties: {}
          description: >-
            Gets or sets the error information if the deployment encountered any
            issues.

            Contains key-value pairs with error details.
          nullable: true
        operationAction:
          type: string
          nullable: true
        operationStatus:
          type: string
          nullable: true
        reason:
          type: string
          nullable: true
        active:
          type: boolean
          description: Gets or sets a value indicating whether this deployment is
            currently active.
        creationTime:
          type: string
          format: date-time
      additionalProperties: false
      description: >-
        Data transfer object representing a stack deployment instance with its
        associated containers, status, and metadata.
                    
        - `stackConfigId`: Stack series ID (GUID). Groups different versions of
        the same stack.

        - `stackRevisionId`: Specific revision/version ID of the stack (GUID).

        - `deploymentId`: Unique deployment ID (GUID) for this device's
        instance.

        - `taskId`: Task ID (GUID) within a batch deployment.

        - `stackName`: Stack name (e.g. "ai-inference-stack").

        - `deviceId`: Target edge device identifier (e.g. "74fe488d5d54").

        - `version`: Stack revision version (e.g. "1", "2").

        - `status`: Aggregate deployment status as last reported by the device.
        Values: "Pending", "Deploying", "Deployed", "Error", "Stopped",
        "Removing".

        - `containers`: Containers within the stack and their runtime state.

        - `error`: Error details if any (key-value pairs). Example: { "code":
        "ImagePullBackOff", "message": "..." }.

        - `operationAction`: Current operation action (e.g. "deploy", "update",
        "remove", "start", "stop").

        - `operationStatus`: Status of the current operation (e.g.
        "in_progress", "completed", "failed").

        - `reason`: Human-readable reason for the current status.

        - `active`: Whether this deployment is currently active.

        - `creationTime`: Deployment creation time (UTC).
    StackDeploymentStatus:
      enum:
        - unknown
        - pending
        - deploying
        - awaitingDeployedStatus
        - running
        - deployed
        - completed
        - exited
        - paused
        - stopped
        - removing
        - awaitingRemovedStatus
        - awaitingCleanup
        - retry
        - error
      type: string
      description: >-
        Aggregate lifecycle status of a stack deployment on a device.
                    
        - `unknown`: Status could not be determined or the device reported a
        value that is not in the documented set.

        - `pending`: Agent has accepted the desired state but has not yet
        started any pipeline phase. Transient — set when a new revision is
        queued or an existing stack is marked for update or removal.

        - `deploying`: A pipeline phase is in flight: validating the compose,
        pulling images, or running compose-up.

        - `awaitingDeployedStatus`: Compose-up has completed; the agent is
        polling the deployer for `running` (or `completed` for one-shot stacks).

        - `running`: At least one container in the stack is up. Steady-state
        running stack.

        - `deployed`: All declared services have been started successfully — the
        stack is fully up.

        - `completed`: The stack ran to completion (one-shot stacks, e.g. an
        updater job).

        - `exited`: All containers in the stack have exited. Inspect each
        container's `error` field — non-zero exit codes (e.g. `OOMKilled`,
        `exitCode 137`) indicate a crash; a clean exit on a one-shot stack is
        closer to `completed`.

        - `paused`: All containers in the stack are paused. Set after a
        successful `stack.pause` runtime command. Resume with `POST
        .../commands:resume`.

        - `stopped`: All containers in the stack are stopped (containers exist
        but are not running). Set after a successful `stack.stop` runtime
        command. Start with `POST .../commands:start`.

        - `removing`: The agent is tearing the stack down (compose-down). Set
        during `deleteStack` (undeploy or device reset).

        - `awaitingRemovedStatus`: Compose-down has completed; the agent is
        polling for `removed`.

        - `awaitingCleanup`: The deployer reported `removed`; the agent is now
        removing the stack's local files and bookkeeping. After cleanup the
        deployment record is deleted and the stack disappears from the
        device-stacks listing.

        - `retry`: A pipeline phase failed transiently; the agent has scheduled
        an exponential-backoff retry. If `retry` persists indefinitely, treat as
        a partial failure and inspect `reason`.

        - `error`: A pipeline phase failed. Covers both transient (agent will
        keep retrying) and terminal failures (auth denied, manifest unknown,
        malformed YAML, port collision, platform mismatch). Read `reason` and
        the agent's `retryStopped` projection to disambiguate.
    StackDeploymentsDto:
      type: object
      properties:
        stackDeployments:
          type: array
          items:
            $ref: "#/components/schemas/StackDeploymentDto"
          description: The list of individual stack deployments.
          nullable: true
        totalDevices:
          type: integer
          description: The total number of devices involved in the deployment process.
          format: int32
        skippedDevices:
          type: integer
          description: The number of devices that were skipped during deployment.
          format: int32
        newlyDeployedDevices:
          type: integer
          description: The number of devices that received new deployments.
          format: int32
        deviceActions:
          type: object
          additionalProperties:
            type: string
          description: >-
            A dictionary that maps each device ID to its corresponding action
            (skip/update/add).

            The key is the device ID and the value is the action performed on
            that device.
          nullable: true
      additionalProperties: false
      description: >-
        Data transfer object representing a batch stack deployment result.

        Provides overall statistics and a per-device action summary.

        The `deviceActions` dictionary preserves the original order of input
        DeviceIds.
                    
        - `stackDeployments`: List of individual stack deployment results, one
        per device.

        - `totalDevices`: Total number of devices involved in the deployment.

        - `skippedDevices`: Number of devices that were skipped (already had the
        same version).

        - `newlyDeployedDevices`: Number of devices that received new
        deployments.

        - `deviceActions`: Map of deviceId → action performed. Action values:
        "skip", "update", "add". Example: { "74fe488d5d54": "add",
        "74fe488d5d55": "skip" }.
    UpdateRegistryDto:
      required:
        - registryName
        - registryUrl
      type: object
      properties:
        registryName:
          maxLength: 32
          minLength: 0
          type: string
          description: Name of the registry. Must be unique within the organization.
        registryUrl:
          minLength: 1
          type: string
          description: URL of the container registry.
          format: uri
        registryCredentials:
          $ref: "#/components/schemas/RegistryCredentials"
      additionalProperties: false
      description: >-
        Data transfer object for updating an existing container registry
        configuration.
                    
        - `RegistryName` (required): Registry display name. Max 32 chars; must
        remain unique within the organization.

        - `RegistryUrl` (required): HTTP/HTTPS URL of the registry following
        Docker registry conventions.

        - `RegistryCredentials`: New credentials for the registry. Polymorphic
        by `registryType`. Null preserves existing credentials.
    UpdateStackDto:
      type: object
      properties:
        composeFileContent:
          type: string
          default: c2VydmljZXM6CiAgdGVzdDoKICAgIGltYWdlOiB0ZXN0
          nullable: true
        environment:
          type: object
          additionalProperties: {}
          nullable: true
        description:
          type: string
          nullable: true
      additionalProperties: false
      description: >-
        Data transfer object for partially updating a stack series. Each update
        creates a new revision;

        previous revisions remain immutable and existing deployments continue
        using the old revision until redeployed.

        Stack name cannot be changed via this DTO.
                    
        - `ComposeFileContent`: Optional Base64-encoded Docker Compose YAML for
        the new revision. Null preserves the existing content. Decoded content
        must be a valid docker-compose.yml.

        - `Environment`: Optional environment variables for this revision. Keys
        must be valid env var names (alphanumeric, case-sensitive); values may
        be strings, numbers, booleans, or JSON objects; referenced inside
        compose via ${VARIABLE_NAME}. Example: { "MODEL_PATH":
        "/opt/models/yolo.onnx", "GPU_ENABLED": "true", "LOG_LEVEL": "info" }.

        - `Description`: Optional free-form description (max 1024 characters).
    ActionObject of ApplyCmdAction:
      type: object
      properties:
        action:
          $ref: "#/components/schemas/ApplyCmdAction"
        params:
          type: object
          additionalProperties:
            type: string
          description: >-
            Optional action-specific parameters. Edge validates against
            per-action schema.


            - `NOOP`: Takes no params.

            - `ATOMIC_SWAP_AND_RESTART_CONTAINER`: `name` (required; alias
            `containerName`) — Docker container to restart after the swap;
            charset restricted to A–Z a–z 0–9 _ - . @.
          nullable: true
      additionalProperties: false
      description: >-
        Represents a command hook action with a strongly-typed enum action
        identifier and optional parameters.

        Follows the WEDA RemoteFileDelivery ShadowConfig Design — §4 Enum Action
        Model.

        Supports both string format (backward compatible with existing DB data)
        and object format with params.
    ActionObject of PostCmdAction:
      type: object
      properties:
        action:
          $ref: "#/components/schemas/PostCmdAction"
        params:
          type: object
          additionalProperties:
            type: string
          description: >-
            Optional action-specific parameters. Edge validates against
            per-action schema.


            - `NOOP`: Takes no params.
          nullable: true
      additionalProperties: false
      description: >-
        Represents a command hook action with a strongly-typed enum action
        identifier and optional parameters.

        Follows the WEDA RemoteFileDelivery ShadowConfig Design — §4 Enum Action
        Model.

        Supports both string format (backward compatible with existing DB data)
        and object format with params.
    ActionObject of PreCmdAction:
      type: object
      properties:
        action:
          $ref: "#/components/schemas/PreCmdAction"
        params:
          type: object
          additionalProperties:
            type: string
          description: >-
            Optional action-specific parameters. Edge validates against
            per-action schema.


            - `NOOP`: Takes no params.

            - `CHECK_DISK_USAGE`: `maxUsagePercent` (required) — maximum allowed
            root-filesystem usage in percent, a decimal string in the range (0,
            100]; the deployment is rejected when current usage already exceeds
            it.
          nullable: true
      additionalProperties: false
      description: >-
        Represents a command hook action with a strongly-typed enum action
        identifier and optional parameters.

        Follows the WEDA RemoteFileDelivery ShadowConfig Design — §4 Enum Action
        Model.

        Supports both string format (backward compatible with existing DB data)
        and object format with params.
    ActionObject of ValidateCmdAction:
      type: object
      properties:
        action:
          $ref: "#/components/schemas/ValidateCmdAction"
        params:
          type: object
          additionalProperties:
            type: string
          description: >-
            Optional action-specific parameters. Edge validates against
            per-action schema.


            - `NOOP`: Takes no params.

            - `CHECKSUM_VERIFY`: `expectedChecksum` (required) — expected hex
            digest, compared case-insensitively; `algorithm` (optional, default
            `sha256`) — `sha256` or `sha512`.
          nullable: true
      additionalProperties: false
      description: >-
        Represents a command hook action with a strongly-typed enum action
        identifier and optional parameters.

        Follows the WEDA RemoteFileDelivery ShadowConfig Design — §4 Enum Action
        Model.

        Supports both string format (backward compatible with existing DB data)
        and object format with params.
    ApplyCmdAction:
      enum:
        - NOOP
        - ATOMIC_SWAP_AND_RESTART_CONTAINER
      type: string
      description: >-
        Allowed actions for the applyCmd hook, executed on the edge device to
        activate/install the

        validated model file into its final runtime location.
                    
        - `NOOP`: Skip the apply step entirely; the file remains in the staging
        directory without activation.

        - `ATOMIC_SWAP_AND_RESTART_CONTAINER`: Atomically replace the currently
        active model file, then restart the container/runtime to pick up the new
        model (brief downtime acceptable).
    CreateModelDeploymentInput:
      required:
        - targets
      type: object
      properties:
        targets:
          type: array
          items:
            $ref: "#/components/schemas/ModelDeploymentTargetInput"
          description: List of deployment targets, each specifying devices and optional
            lifecycle commands.
        description:
          type: string
          description: Optional human-readable description of this deployment.
          nullable: true
      additionalProperties: false
      description: Request body for creating a model deployment.
    CreateModelInput:
      required:
        - modelName
      type: object
      properties:
        modelName:
          maxLength: 255
          minLength: 0
          type: string
          description: >-
            Model name. Unique within the tenant.
                        
            The modelName MUST satisfy all of the following restrictions:

            - Allowed characters: English letters (a-z, A-Z), digits (0-9),
            hyphen (-), underscore (_).

            - Forbidden characters: special symbols (such as *, ?, ", <, >, |,
            :, ;, ,, \, ., /), whitespace, control characters.

            - MUST NOT exceed 255 characters.

            - MUST NOT end with .lock, .tmp, or .staging.
        description:
          maxLength: 2048
          minLength: 0
          type: string
          description: Optional model description.
          nullable: true
      additionalProperties: false
      description: Create Model.
    DeleteEditionResultDto:
      type: object
      properties:
        modelId:
          type: string
          description: Identifier of the model the deleted edition belonged to.
          format: uuid
        edition:
          type: string
          description: Edition (version) string that was deleted.
          nullable: true
        deleted:
          type: boolean
          description: True when the edition was deleted.
        deletedAt:
          type: string
          description: Timestamp when the edition was deleted.
          format: date-time
        deletedBy:
          type: string
          description: User identifier that performed the deletion.
          nullable: true
        storageFreedBytes:
          type: integer
          description: Storage reclaimed by the deletion, in bytes.
          format: int64
        note:
          type: string
          description: Optional note about the deletion (e.g. why storage was not freed).
          nullable: true
      additionalProperties: false
      description: Result of deleting a single model edition.
    DeleteModelResultDto:
      type: object
      properties:
        modelId:
          type: string
          description: Identifier of the deleted model.
          format: uuid
        modelName:
          type: string
          description: Name of the deleted model.
          nullable: true
        deleted:
          type: boolean
          description: True when the model was deleted.
        deletedAt:
          type: string
          description: Timestamp when the model was deleted.
          format: date-time
        deletedBy:
          type: string
          description: User identifier that performed the deletion.
          nullable: true
        editionsDeleted:
          type: integer
          description: Number of editions removed as part of the model deletion.
          format: int32
        storageFreedBytes:
          type: integer
          description: Storage reclaimed by the deletion, in bytes.
          format: int64
        note:
          type: string
          description: Optional note about the deletion.
          nullable: true
      additionalProperties: false
      description: Result of deleting a model and all its editions.
    DeploymentAggregateState:
      enum:
        - IN_PROGRESS
        - COMPLETED
        - PARTIAL_FAILED
        - FAILED
      type: string
      description: >-
        Overall aggregate status of a model deployment across all target
        devices.

        Computed from the individual
        EdgeSync.AiModelMgmt.ModelDeployments.Dtos.DeploymentDeviceState values
        of every device in the deployment.
                    
        - `IN_PROGRESS`: At least one device is still in a non-terminal state
        (SENT through VALIDATED). The rollout is ongoing.

        - `COMPLETED`: Every target device has reached DEPLOYED; the model is
        live on all intended devices.

        - `PARTIAL_FAILED`: Some devices reached DEPLOYED while others were
        REJECTED; partial rollout success.

        - `FAILED`: All target devices were REJECTED; the deployment entirely
        failed.
    DeploymentDeviceState:
      enum:
        - SENT
        - SERVERFILEPATH_OBTAINED
        - EDGERECEIVED
        - MODEL_STORAGE_CHECKED
        - CAPACITY_CHECKED
        - DOWNLOADED
        - VALIDATED
        - DEPLOYED
        - REJECTED
        - DELETED
      type: string
      description: >-
        Per-device deployment state exposed in public API responses.

        Represents the progression of a model file delivery to an edge device.
                    
        Happy path: SENT → SERVERFILEPATH_OBTAINED → EDGERECEIVED →
        MODEL_STORAGE_CHECKED → CAPACITY_CHECKED → DOWNLOADED → VALIDATED →
        DEPLOYED

        Failure at any stage: REJECTED (inspect rejectReason field for cause).
                    
        - `SENT`: Cloud has published the deployment command to the device via
        NATS; awaiting acknowledgement.

        - `SERVERFILEPATH_OBTAINED`: Device resolved the server file URI needed
        to begin download.

        - `EDGERECEIVED`: Device acknowledged receipt of the deployment
        instruction and started processing.

        - `MODEL_STORAGE_CHECKED`: Device verified the model storage directory
        exists and is writable.

        - `CAPACITY_CHECKED`: Device confirmed sufficient free disk space for
        the incoming model file.

        - `DOWNLOADED`: Device completed downloading the model file from Secured
        Volume.

        - `VALIDATED`: Device passed the validation hook (checksum, file size,
        or signature verification).

        - `DEPLOYED`: Model file successfully activated on the device; model is
        live and serving.

        - `REJECTED`: Device rejected the deployment at some stage; see
        rejectReason for the specific failure cause.

        - `DELETED`: Model file has been successfully removed from the device
        after a delete request.
    EditionDto:
      type: object
      properties:
        uploadId:
          type: string
          description: Unique upload identifier; used to poll upload status. Null when the
            edition has no upload session.
          format: uuid
          nullable: true
        modelId:
          type: string
          description: Identifier of the model this edition belongs to.
          format: uuid
        modelName:
          type: string
          description: Model name.
          nullable: true
        edition:
          type: string
          description: Edition (version) string being uploaded.
          nullable: true
        description:
          type: string
          description: Edition description.
          nullable: true
        tenantId:
          type: string
          description: Owning tenant identifier.
          format: uuid
          nullable: true
        orgId:
          type: string
          description: Owning organization identifier.
          format: uuid
        changeSummary:
          type: string
          description: Summary of changes for this edition.
          nullable: true
        status:
          type: string
          description: >-
            Edition lifecycle status. One of:

            - `Pending`: Registered but no hash-verified file yet (upload
            pending/in progress).

            - `Uploaded`: Successfully uploaded and hash-verified; the edition
            is available.
          nullable: true
        file:
          $ref: "#/components/schemas/FileInfoDto"
        tusEndpoint:
          type: string
          description: TUS endpoint URL the client uploads the file bytes to. Null when no
            upload session is active (e.g. reading/updating an existing
            edition).
          nullable: true
        maxFileSize:
          type: integer
          description: Maximum allowed file size in bytes. Populated only by the
            register-upload flow; null (omitted) when reading/updating an
            existing edition.
          format: int64
          nullable: true
        uploadExpiresAt:
          type: string
          description: Expiry time after which the upload session/token is no longer
            valid. Null when no upload session is active.
          format: date-time
          nullable: true
      additionalProperties: false
      description: >-
        Unified edition response, returned by create-edition (register upload),
        get-edition detail, and

        update-edition. The upload/TUS session fields
        (EdgeSync.AiModelMgmt.Models.Dtos.EditionDto.TusEndpoint,
        EdgeSync.AiModelMgmt.Models.Dtos.EditionDto.UploadExpiresAt)

        are populated only by the register-upload flow; they are null when
        reading or updating an

        already-registered edition.
    FileInfoDto:
      type: object
      properties:
        fileId:
          type: string
          description: Unique file identifier; null until the file has been uploaded and
            hash-verified (e.g. while a registered upload is still Pending and
            no file row exists yet).
          format: uuid
          nullable: true
        fileName:
          type: string
          description: Original file name.
          nullable: true
        fileSize:
          type: integer
          description: File size in bytes.
          format: int64
        fileHash:
          type: string
          description: File hash with `sha256:` prefix.
          nullable: true
        hashAlg:
          type: string
          description: Hash algorithm name. Fixed to SHA-256.
          nullable: true
        fileUri:
          type: string
          description: Object storage path; not an external download URL.
          nullable: true
      additionalProperties: false
      description: Nested `file` object used by edition-related responses.
    ModelDeploymentAclInput:
      type: object
      properties:
        allowedSubnets:
          type: array
          items:
            type: string
          description: CIDR subnets allowed to access the deployed model file (e.g.
            "192.168.1.0/24").
          nullable: true
        allowedContainers:
          type: array
          items:
            type: string
          description: Container names permitted to access the deployed model file.
          nullable: true
      additionalProperties: false
      description: Access control list input restricting file access on the edge device.
    ModelDeploymentByDeviceDto:
      type: object
      properties:
        modelId:
          type: string
          description: Identifier of the AI model.
          nullable: true
        modelName:
          type: string
          description: Display name of the AI model.
          nullable: true
        edition:
          type: string
          description: Edition (version) of the deployed model (e.g. "1-0-0").
          nullable: true
        tenantId:
          type: string
          description: Tenant identifier, if multi-tenancy is enabled.
          nullable: true
        orgId:
          type: string
          description: Organization identifier that owns this deployment.
          nullable: true
        deviceId:
          type: string
          description: Identifier of the target edge device.
          nullable: true
        createdAt:
          type: string
          description: Timestamp when the deployment was created by a user API call.
          format: date-time
        createdBy:
          type: string
          description: User ID who created the deployment.
          nullable: true
        updatedAt:
          type: string
          description: Timestamp of the last user-initiated API operation on this
            deployment.
          format: date-time
          nullable: true
        updatedBy:
          type: string
          description: User ID of the last user-initiated API operation on this deployment.
          nullable: true
        deploymentStartTime:
          type: string
          description: >-
            Timestamp when the first device reported DEPLOYED (ACTIVATED)
            status.

            Null until at least one device reaches the DEPLOYED state.

            This is set by device-side reporting, not by the user API call.
          format: date-time
          nullable: true
        deploymentEndTime:
          type: string
          description: >-
            Timestamp when a device removed this deployment from its reported
            state (device reported DELETED).

            Null until at least one device reports DELETED.

            This is set by device-side reporting, not by user API calls.
          format: date-time
          nullable: true
        deviceDeploymentId:
          type: string
          description: Unique identifier for this device-level deployment task.
          format: uuid
        edgeFilePath:
          type: string
          description: >-
            File path on the edge device where the model is stored.

            Null when the deployment state is not DEPLOYED (file not yet
            available on device).
          nullable: true
        state:
          $ref: "#/components/schemas/DeploymentDeviceState"
        rejectedReason:
          type: string
          description: Reason the device rejected the deployment, when state is REJECTED.
          nullable: true
      additionalProperties: false
      description: Response item for listing all deployed models on a specific device
        (API 1.2).
    ModelDeploymentByModelVersionDto:
      type: object
      properties:
        deviceId:
          type: string
          description: Identifier of the target edge device.
          nullable: true
        modelId:
          type: string
          description: Identifier of the AI model.
          nullable: true
        modelName:
          type: string
          description: Display name of the AI model.
          nullable: true
        edition:
          type: string
          description: Edition (version) of the deployed model (e.g. "1-0-0").
          nullable: true
        tenantId:
          type: string
          description: Tenant identifier, if multi-tenancy is enabled.
          nullable: true
        orgId:
          type: string
          description: Organization identifier that owns this deployment.
          nullable: true
        createdAt:
          type: string
          description: Timestamp when the deployment was created by a user API call.
          format: date-time
        createdBy:
          type: string
          description: User ID who created the deployment.
          nullable: true
        updatedAt:
          type: string
          description: Timestamp of the last user-initiated API operation on this
            deployment.
          format: date-time
          nullable: true
        updatedBy:
          type: string
          description: User ID of the last user-initiated API operation on this deployment.
          nullable: true
        deploymentStartTime:
          type: string
          description: >-
            Timestamp when the first device reported DEPLOYED (ACTIVATED)
            status.

            Null until at least one device reaches the DEPLOYED state.

            This is set by device-side reporting, not by the user API call.
          format: date-time
          nullable: true
        deploymentEndTime:
          type: string
          description: >-
            Timestamp when a device removed this deployment from its reported
            state (device reported DELETED).

            Null until at least one device reports DELETED.

            This is set by device-side reporting, not by user API calls.
          format: date-time
          nullable: true
        deviceDeploymentId:
          type: string
          description: Unique identifier for this device-level deployment task.
          format: uuid
        edgeFilePath:
          type: string
          description: >-
            File path on the edge device where the model is stored.

            Null when the deployment state is not DEPLOYED (file not yet
            available on device).
          nullable: true
        state:
          $ref: "#/components/schemas/DeploymentDeviceState"
        rejectedReason:
          type: string
          description: Reason the device rejected the deployment, when state is REJECTED.
          nullable: true
        lastTransitionTime:
          type: string
          description: Timestamp of the most recent state transition for this device.
          format: date-time
      additionalProperties: false
      description: Response item for listing devices that have a specific model
        version deployed (API 1.3).
    ModelDeploymentCreateResultDto:
      type: object
      properties:
        modelDeploymentId:
          type: string
          description: >-
            Unique identifier of the created model deployment.

            Omitted from the response when empty (e.g. an all-rejected result
            that created no deployment).
          format: uuid
        modelId:
          type: string
          description: Identifier of the AI model being deployed.
          nullable: true
        edition:
          type: string
          description: Edition (version) of the deployed model (e.g. "1-0-0").
          nullable: true
        status:
          $ref: "#/components/schemas/DeploymentAggregateState"
        createdAt:
          type: string
          description: Timestamp when the user called the create deployment API.
          format: date-time
        createdBy:
          type: string
          description: User identifier of the caller who created this deployment.
          nullable: true
        updatedAt:
          type: string
          description: >-
            Timestamp of the last user-initiated API operation (create, delete)
            on this deployment.

            Updated only by user API calls, not by device-reported events.
          format: date-time
          nullable: true
        updatedBy:
          type: string
          description: >-
            User identifier of the last caller who performed any API operation
            on this deployment.

            Updated only by user API calls, not by device-reported events.
          nullable: true
        targets:
          type: array
          items:
            $ref: "#/components/schemas/ModelDeploymentTargetResultDto"
          description: Per-device deployment results for each target device.
          nullable: true
      additionalProperties: false
      description: Response DTO for the Create Deployment API (1.1), returning the
        newly created deployment and per-device status.
    ModelDeploymentPagedResultDto of ModelDeploymentByDeviceDto:
      type: object
      properties:
        items:
          type: array
          items:
            $ref: "#/components/schemas/ModelDeploymentByDeviceDto"
          nullable: true
        totalCount:
          type: integer
          format: int64
        skipCount:
          type: integer
          description: Number of items skipped (offset).
          format: int32
        maxResultCount:
          type: integer
          description: Maximum number of items per page.
          format: int32
        totalPages:
          type: integer
          description: Total number of pages available.
          format: int32
      additionalProperties: false
      description: >-
        Paginated result wrapper extending the base paged result (which supplies

        `Items` and `TotalCount`) with the offset, page size and total page
        count

        required by the API specification.
    ModelDeploymentPagedResultDto of ModelDeploymentByModelVersionDto:
      type: object
      properties:
        items:
          type: array
          items:
            $ref: "#/components/schemas/ModelDeploymentByModelVersionDto"
          nullable: true
        totalCount:
          type: integer
          format: int64
        skipCount:
          type: integer
          description: Number of items skipped (offset).
          format: int32
        maxResultCount:
          type: integer
          description: Maximum number of items per page.
          format: int32
        totalPages:
          type: integer
          description: Total number of pages available.
          format: int32
      additionalProperties: false
      description: >-
        Paginated result wrapper extending the base paged result (which supplies

        `Items` and `TotalCount`) with the offset, page size and total page
        count

        required by the API specification.
    ModelDeploymentTargetInput:
      required:
        - deviceIdList
      type: object
      properties:
        deviceIdList:
          type: array
          items:
            type: string
          description: List of device identifiers (12-char hex) to deploy the model to.
        tasks:
          type: array
          items:
            $ref: "#/components/schemas/ModelDeploymentTaskInput"
          description: Optional lifecycle tasks (ACL, pre/post commands) applied to each
            device in this target group.
          nullable: true
      additionalProperties: false
      description: Specifies a set of target devices and optional lifecycle tasks for
        a deployment.
    ModelDeploymentTargetResultDto:
      type: object
      properties:
        deviceId:
          type: string
          description: Identifier of the target edge device (12-char hex).
          nullable: true
        deviceDeploymentId:
          type: string
          description: >-
            Unique identifier for this device-level deployment task.

            Omitted from the response when empty (e.g. a device rejected before
            any task was created).
          format: uuid
        edgeFilePath:
          type: string
          description: >-
            File path on the edge device where the model is stored.

            Null when the deployment state is not DEPLOYED (file not yet
            available on device).
          nullable: true
        state:
          $ref: "#/components/schemas/DeploymentDeviceState"
      additionalProperties: false
      description: Per-device result within a deployment, indicating file path and
        delivery state.
    ModelDeploymentTaskInput:
      type: object
      properties:
        acl:
          $ref: "#/components/schemas/ModelDeploymentAclInput"
        preCmd:
          $ref: "#/components/schemas/ActionObject of PreCmdAction"
        validateCmd:
          $ref: "#/components/schemas/ActionObject of ValidateCmdAction"
        applyCmd:
          $ref: "#/components/schemas/ActionObject of ApplyCmdAction"
        postCmd:
          $ref: "#/components/schemas/ActionObject of PostCmdAction"
      additionalProperties: false
      description: Lifecycle task configuration for a deployment target, including ACL
        and hook commands.
    ModelDto:
      type: object
      properties:
        modelId:
          type: string
          description: Unique model identifier.
          format: uuid
        modelName:
          type: string
          description: Model name.
          nullable: true
        description:
          type: string
          description: Model description.
          nullable: true
        tenantId:
          type: string
          description: Owning tenant identifier.
          format: uuid
          nullable: true
        orgId:
          type: string
          description: Owning organization identifier.
          format: uuid
      additionalProperties: false
      description: Model record response.
    ModelEditionListDto:
      type: object
      properties:
        modelId:
          type: string
          description: Identifier of the model this edition belongs to.
          format: uuid
        modelName:
          type: string
          description: Model name.
          nullable: true
        edition:
          type: string
          description: Edition (version) string, e.g. "1-0-0".
          nullable: true
        tenantId:
          type: string
          description: Owning tenant identifier.
          format: uuid
          nullable: true
        orgId:
          type: string
          description: Owning organization identifier.
          format: uuid
        description:
          type: string
          description: Edition description.
          nullable: true
        status:
          type: string
          description: >-
            Edition lifecycle status. One of:

            - `Pending`: Registered but no hash-verified file yet (upload
            pending/in progress).

            - `Uploaded`: Successfully uploaded and hash-verified; the edition
            is available.
          nullable: true
        file:
          $ref: "#/components/schemas/FileInfoDto"
      additionalProperties: false
      description: Edition list item.
    ModelListDto:
      type: object
      properties:
        modelId:
          type: string
          description: Unique model identifier.
          format: uuid
        modelName:
          type: string
          description: Model name.
          nullable: true
        tenantId:
          type: string
          description: Owning tenant identifier.
          format: uuid
          nullable: true
        orgId:
          type: string
          description: Owning organization identifier.
          format: uuid
        description:
          type: string
          description: Model description (falls back to the latest edition's description).
          nullable: true
      additionalProperties: false
      description: Model list item.
    PagedResultDto of ModelEditionListDto:
      type: object
      properties:
        items:
          type: array
          items:
            $ref: "#/components/schemas/ModelEditionListDto"
          nullable: true
        totalCount:
          type: integer
          format: int64
      additionalProperties: false
    PagedResultDto of ModelListDto:
      type: object
      properties:
        items:
          type: array
          items:
            $ref: "#/components/schemas/ModelListDto"
          nullable: true
        totalCount:
          type: integer
          format: int64
      additionalProperties: false
    PostCmdAction:
      enum:
        - NOOP
      type: string
      description: >-
        Allowed actions for the postCmd hook, executed on the edge device AFTER
        the model file

        has been activated/applied, used to verify deployment success.
                    
        - `NOOP`: Skip post-deployment health check; assume activation success.
    PreCmdAction:
      enum:
        - NOOP
        - CHECK_DISK_USAGE
      type: string
      description: >-
        Allowed actions for the preCmd hook, executed on the edge device BEFORE
        file download begins.
                    
        - `NOOP`: Skip the pre-command step entirely; proceed directly to
        download.

        - `CHECK_DISK_USAGE`: Validate that the device has sufficient free disk
        space to accommodate the incoming model file.
    RegisterUploadInput:
      required:
        - edition
      type: object
      properties:
        edition:
          maxLength: 255
          minLength: 0
          type: string
          description: >-
            Edition (version) string for the new upload, e.g. "1-0-0".
                        
            The edition MUST satisfy all of the following restrictions:

            - Allowed characters: English letters (a-z, A-Z), digits (0-9),
            hyphen (-), underscore (_).

            - Forbidden characters: special symbols (such as *, ?, ", <, >, |,
            :, ;, ,, \, ., /), whitespace, control characters.

            - MUST NOT exceed 255 characters.

            - MUST NOT end with .lock, .tmp, or .staging.
        fileName:
          maxLength: 256
          minLength: 0
          type: string
          description: >-
            Original file name to upload. Optional: omit all of
            fileName/fileSize/fileHash to

            create an empty Pending edition without starting an upload.
          nullable: true
        fileSize:
          maximum: 53687091200
          minimum: 0
          type: integer
          description: File size in bytes (within the allowed range). Optional — omit for
            an empty edition.
          format: int64
        description:
          maxLength: 2048
          minLength: 0
          type: string
          description: Optional edition description.
          nullable: true
        changeSummary:
          maxLength: 1024
          minLength: 0
          type: string
          description: Optional summary of changes in this edition.
          nullable: true
        fileHash:
          maxLength: 256
          minLength: 0
          type: string
          description: Client-computed SHA-256 hash, 64-char hex (no prefix). Optional —
            omit for an empty edition.
          nullable: true
      additionalProperties: false
      description: Register an upload (first step before TUS transfer).
    UpdateEditionInput:
      required:
        - description
      type: object
      properties:
        description:
          maxLength: 2048
          minLength: 0
          type: string
          description: New edition description.
      additionalProperties: false
      description: Update edition metadata (description only).
    UpdateModelInput:
      type: object
      properties:
        modelName:
          maxLength: 255
          minLength: 0
          type: string
          description: New model name. Null leaves the existing name unchanged.
          nullable: true
        description:
          maxLength: 2048
          minLength: 0
          type: string
          description: New model description. Null leaves the existing description
            unchanged.
          nullable: true
      additionalProperties: false
      description: Update Model basic info. At least one field must be provided.
    UploadStatus:
      enum:
        - Uploading
        - Verifying
        - Uploaded
        - UploadFailed
        - Pending
        - VerifyFailed
      type: string
      description: >-
        Lifecycle state of a file upload process via the TUS-based upload API.

        Int values are persisted in the database; keep existing numeric
        assignments stable across versions.
                    
        Happy path: Pending → Uploading → Verifying → Uploaded

        Failure paths: Uploading → UploadFailed, Verifying → VerifyFailed
                    
        - `Pending`: Upload registered (pre-create); the TUS transfer has not
        yet started. The server is awaiting the first PATCH request.

        - `Uploading`: TUS pre-create hook passed; file transfer is in progress.
        Chunks are being received.

        - `Verifying`: Transfer complete; the server is computing SHA-256 over
        the received bytes for integrity verification against the
        client-provided hash.

        - `Uploaded`: Hash verified successfully and the model edition record
        has been created. The file is ready for deployment.

        - `UploadFailed`: Upload was cancelled by the client, the transfer
        stream was interrupted, or the session expired before completion.

        - `VerifyFailed`: Hash mismatch between the computed SHA-256 and the
        client-provided hash, or an I/O error occurred during hash calculation.
    UploadStatusDto:
      type: object
      properties:
        status:
          $ref: "#/components/schemas/UploadStatus"
        uploadExpiresAt:
          type: string
          description: Only present while status is `Pending` or `Uploading`.
          format: date-time
          nullable: true
      additionalProperties: false
      description: Upload status. Trimmed to status + uploadExpiresAt only.
    ValidateCmdAction:
      enum:
        - NOOP
        - CHECKSUM_VERIFY
      type: string
      description: >-
        Allowed actions for the validateCmd hook, executed on the edge device
        AFTER file download completes

        but BEFORE activation/apply.
                    
        - `NOOP`: Skip validation entirely; trust the downloaded file as-is.

        - `CHECKSUM_VERIFY`: Compute a hash (e.g. SHA-256) of the downloaded
        file and compare against the expected value from the model registry.
    CreateDataStreamDto:
      required:
        - dataStreamName
        - dataType
      type: object
      properties:
        dataStreamName:
          maxLength: 128
          minLength: 0
          type: string
          description: Unique name of the data stream within the device.
          example: cpu_temperature
        displayName:
          maxLength: 200
          minLength: 0
          type: string
          description: Human-readable label for the data stream.
          nullable: true
          example: CPU Temperature Sensor
        description:
          maxLength: 500
          minLength: 0
          type: string
          description: Description of the data stream.
          nullable: true
          example: CPU temperature sensor in Fahrenheit
        unitDisplay:
          maxLength: 50
          minLength: 0
          type: string
          description: Display unit of the measured value.
          nullable: true
          example: °F
        dataType:
          $ref: "#/components/schemas/DataStreamDataType"
        recordToDataLake:
          type: boolean
          description: "Whether to persist values to the data lake (default: true)."
          example: true
      additionalProperties: false
      description: >-
        Request DTO for creating a DataStream (POST /data-streams).

        A publicly created data stream is always managedBy=User, dataSource=null
        (ownership is claimed by an

        Analyzer, not specified by this endpoint); therefore it does
        not include managedBy or

        dataSource fields.
    DataStreamDataType:
      enum:
        - double
        - integer
        - boolean
        - string
        - long
        - application/json
        - application/octet-stream
        - image/png
        - image/jpeg
        - image/jpg
      type: string
      description: |-
        Data type of a DataStream.
        In addition to scalar types, this also covers binary/blob MIME types.
    DataStreamDto:
      type: object
      properties:
        dataStreamId:
          type: string
          description: Unique identifier of the data stream.
          format: uuid
          example: e033b4b3-36e0-4dbc-a6e4-1e77185402f4
        dataStreamName:
          type: string
          description: Unique name of the data stream within the device.
          nullable: true
          example: cpu_temperature
        displayName:
          type: string
          description: Human-readable label for the data stream.
          nullable: true
          example: CPU Temperature Sensor
        description:
          type: string
          description: Description of the data stream.
          nullable: true
          example: CPU temperature sensor in Fahrenheit
        unitDisplay:
          type: string
          description: Display unit of the measured value (e.g. °C, °F, %, KG).
          nullable: true
          example: °F
        dataType:
          $ref: "#/components/schemas/DataStreamDataType"
        recordToDataLake:
          type: boolean
          description: Whether to persist values to the data lake.
          example: true
        managedBy:
          $ref: "#/components/schemas/ManagedBy"
        dataSource:
          $ref: "#/components/schemas/DataStreamSourceDto"
      additionalProperties: false
      description: Read/list response DTO for a DataStream. The primary key is named
        dataStreamId.
    DataStreamDtoPagedResultDto:
      type: object
      properties:
        items:
          type: array
          items:
            $ref: "#/components/schemas/DataStreamDto"
          nullable: true
        totalCount:
          type: integer
          format: int64
      additionalProperties: false
    DataStreamHistoricalResponse:
      type: object
      properties:
        deviceId:
          type: string
          description: Device unique ID the samples belong to.
          nullable: true
          example: 74fe488d5d35
        dataStreamId:
          type: string
          description: Unique ID of the data stream the samples belong to.
          format: uuid
          example: 3a217ee3-fb2c-617b-6ff6-7257537afade
        start:
          type: string
          description: Start timestamp of the queried range in ISO 8601 UTC.
          format: date-time
          example: 2025-09-01T00:00:00Z
        end:
          type: string
          description: End timestamp of the queried range in ISO 8601 UTC.
          format: date-time
          example: 2025-09-02T00:00:00Z
        dataType:
          $ref: "#/components/schemas/DataStreamDataType"
        dataObjects:
          type: array
          items:
            $ref: "#/components/schemas/HistoricalDataObject"
          description: Timestamped values ordered by timestamp.
          nullable: true
        nextCursor:
          type: integer
          description: Next cursor for pagination (Unix milliseconds). Null if no more data.
          format: int64
          nullable: true
          example: 1756713660000
        hasMore:
          type: boolean
          description: Whether there are more pages available.
      additionalProperties: false
      description: >-
        Response DTO for the historical query (cursor-based pagination). An
        empty dataObjects list

        (hasMore=false) means the data stream has recordToDataLake=false and has
        no history to query; it is not

        an error.
    DataStreamLatestValue:
      type: object
      properties:
        dataStreamId:
          type: string
          description: Data stream ID.
          format: uuid
        dataStreamName:
          type: string
          description: Data stream name.
          nullable: true
          example: temperature
        dataType:
          type: string
          description: Data type of dataObject's value.
          nullable: true
          example: double
        displayName:
          type: string
          description: Human-readable display name.
          nullable: true
        unitDisplay:
          type: string
          description: Display unit (e.g. °C).
          nullable: true
        dataObject:
          $ref: "#/components/schemas/HistoricalDataObject"
      additionalProperties: false
      description: Latest-value entry for a single data stream, used by
        TelemetryResponseDataObjects.dataStreams.
    DataStreamLatestValueResponse:
      type: object
      properties:
        deviceId:
          type: string
          description: Device ID.
          nullable: true
          example: 74fe488d5d35
        dataStreamId:
          type: string
          description: Data stream ID.
          format: uuid
        dataStreamName:
          type: string
          description: Data stream name.
          nullable: true
          example: temperature
        dataType:
          type: string
          description: Data type of dataObject's value.
          nullable: true
          example: double
        dataObject:
          $ref: "#/components/schemas/HistoricalDataObject"
      additionalProperties: false
      description: >-
        Response DTO for a single data stream's latest-value query. Unlike
        TelemetryResponseDataObjects, which is

        shared by the batch endpoint, this DTO is a flat structure that only
        returns the latest value for the

        single dataStreamId already known to the caller.
    DataStreamSourceDto:
      type: object
      properties:
        type:
          $ref: "#/components/schemas/DataStreamSourceType"
        sourceEntityId:
          type: string
          description: >-
            Identifier of the source entity. For WedaNode and WedaSubNode
            sources, the auto-generated resource ID of

            the source sensor; for Analyzer sources, the analyzerId; for
            CustomDevice sources, the custom device

            identifier. Assigned by the system and cannot be set or modified by
            the client.
          nullable: true
          example: a1b2c3d4-0000-1111-2222-333344445555
      additionalProperties: false
      description: >-
        Response DTO for a DataStream's lineage information (read-only).

        type may be null, meaning this DataStream has not yet been claimed by
        any source.
    DataStreamSourceType:
      enum:
        - CustomDevice
        - Analyzer
        - WedaNode
        - WedaSubNode
      type: string
      description: >-
        Kind of DataStream lineage source.

        WedaNode/WedaSubNode correspond to a sensor's resourceId; Analyzer
        corresponds to an analyzerId;

        CustomDevice corresponds to a custom device identifier.
    HistoricalDataObject:
      type: object
      properties:
        timestamp:
          type: string
          description: Sample time in ISO 8601 UTC.
          format: date-time
          example: 2025-09-01T08:00:00Z
        value:
          description: Sample value. Its type is declared by the containing response's
            dataType field.
          nullable: true
          example: 23.5
      additionalProperties: false
      description: A single timestamped data sample, used in historical-query
        responses (maps to the HistoricalDataObject schema).
    ManagedBy:
      enum:
        - System
        - User
      type: string
      description: >-
        Management ownership of a DataStream.

        System: automatically synced by the device (WedaNode/WedaSubNode); only

        displayName/description/unitDisplay/recordToDataLake may be edited by
        the user.

        User: fully managed by the user.
    PatchDataStreamDto:
      type: object
      properties:
        displayName:
          maxLength: 200
          minLength: 0
          type: string
          description: Human-readable label for the data stream.
          nullable: true
          example: CPU Temperature Sensor (Updated)
        description:
          maxLength: 500
          minLength: 0
          type: string
          description: Description of the data stream.
          nullable: true
        unitDisplay:
          maxLength: 50
          minLength: 0
          type: string
          description: Display unit of the measured value.
          nullable: true
        recordToDataLake:
          type: boolean
          description: Whether to persist values to the data lake.
          nullable: true
          example: true
      additionalProperties: false
      description: >-
        Request DTO for partially updating a DataStream (PATCH
        /data-streams/{dataStreamId}). Only

        displayName / description / unitDisplay / recordToDataLake can be
        partially updated

        (dataStreamName / dataType are not included). All fields may be null;
        null means "not provided, keep the

        current value".
    TelemetryResponseDataObjects:
      type: object
      properties:
        deviceId:
          type: string
          description: Device ID.
          nullable: true
          example: 74fe488d5d35
        time:
          type: string
          description: Response generation timestamp.
          format: date-time
          example: 2025-09-01T08:00:00Z
        dataStreams:
          type: array
          items:
            $ref: "#/components/schemas/DataStreamLatestValue"
          description: Latest values, one entry per data stream.
          nullable: true
      additionalProperties: false
      description: >-
        Response DTO for the latest-value query (shared by the single and batch
        endpoints). dataStreams lists

        the latest value for each data stream. time is the response generation
        time, not the individual sample's

        timestamp (see DataStreamLatestValue.dataObject for the per-sample
        timestamp).
    UpdateDataStreamDto:
      required:
        - dataStreamName
        - dataType
      type: object
      properties:
        dataStreamName:
          maxLength: 128
          minLength: 0
          type: string
          description: Unique name of the data stream within the device.
          example: cpu_temperature
        displayName:
          maxLength: 200
          minLength: 0
          type: string
          description: Human-readable label for the data stream.
          nullable: true
          example: CPU Temperature Sensor
        description:
          maxLength: 500
          minLength: 0
          type: string
          description: Description of the data stream.
          nullable: true
          example: CPU temperature sensor in Fahrenheit
        unitDisplay:
          maxLength: 50
          minLength: 0
          type: string
          description: Display unit of the measured value.
          nullable: true
          example: °F
        dataType:
          $ref: "#/components/schemas/DataStreamDataType"
        recordToDataLake:
          type: boolean
          description: Whether to persist values to the data lake.
          example: true
      additionalProperties: false
      description: >-
        Request DTO for fully updating a DataStream (PUT
        /data-streams/{dataStreamId}).

        The restriction that only
        displayName/description/unitDisplay/recordToDataLake may change for

        System-managed streams (dataStreamName/dataType are rejected when
        managedBy=System) is enforced by the

        domain layer; the DTO itself carries the full set of editable fields.
    AnalyzerAction:
      enum:
        - Enable
        - Disable
      type: string
    AnalyzerConfigTransferFunction:
      required:
        - expression
      type: object
      properties:
        expression:
          minLength: 1
          type: string
          description: "Mathematical transformation expression. Example: (raw_temperature
            - 32) * 5/9."
      additionalProperties: false
      description: Type-specific computation settings for AnalyzerType.TransferFunction.
    AnalyzerCreateRequest:
      required:
        - config
        - inputParameters
        - name
        - outputs
        - type
      type: object
      properties:
        name:
          maxLength: 256
          minLength: 1
          type: string
          description: "Human-readable name of the analyzer. Example: F to C converter."
        description:
          maxLength: 500
          type: string
          description: Description of the analyzer.
          nullable: true
        type:
          $ref: "#/components/schemas/AnalyzerType"
        inputParameters:
          minItems: 1
          type: array
          items:
            $ref: "#/components/schemas/AnalyzerInputStream"
          description: Input mappings that bind data streams to expression variables.
        config:
          $ref: "#/components/schemas/AnalyzerConfigTransferFunction"
        outputs:
          maxItems: 1
          minItems: 1
          type: array
          items:
            $ref: "#/components/schemas/AnalyzerOutputDto"
          description: Output bindings. TransferFunction emits exactly one output.
      additionalProperties: false
      description: Payload for creating a new analyzer.
    AnalyzerDto:
      required:
        - analyzerId
        - config
        - createdAt
        - isEnabled
        - type
      type: object
      properties:
        analyzerId:
          type: string
          description: Unique identifier of the analyzer.
          format: uuid
        isEnabled:
          type: boolean
          description: Whether the analyzer is enabled. Use the enable/disable action to
            change this state.
        name:
          type: string
          description: Human-readable name of the analyzer.
          nullable: true
        description:
          type: string
          description: Description of the analyzer.
          nullable: true
        type:
          $ref: "#/components/schemas/AnalyzerType"
        inputParameters:
          type: array
          items:
            $ref: "#/components/schemas/AnalyzerInputStream"
          description: Input parameter mappings used by the analyzer expression.
          nullable: true
        config:
          $ref: "#/components/schemas/IAnalyzerConfigDto"
        outputs:
          type: array
          items:
            $ref: "#/components/schemas/AnalyzerOutputDto"
          description: Target output data-stream bindings.
          nullable: true
        createdAt:
          type: string
          description: UTC timestamp when the analyzer was created.
          format: date-time
        updatedAt:
          type: string
          description: UTC timestamp when the analyzer was last updated.
          format: date-time
          nullable: true
      additionalProperties: false
      description: A device analyzer definition.
    AnalyzerDtoPagedResultDto:
      type: object
      properties:
        items:
          type: array
          items:
            $ref: "#/components/schemas/AnalyzerDto"
          nullable: true
        totalCount:
          type: integer
          format: int64
      additionalProperties: false
    AnalyzerInputStream:
      required:
        - dataStreamId
        - parameterName
      type: object
      properties:
        parameterName:
          minLength: 1
          type: string
          description: Variable name used in the expression to represent this input's value.
        dataStreamId:
          type: string
          description: Unique identifier of the input data stream.
          format: uuid
      additionalProperties: false
      description: An input binding between a data stream and an expression variable.
    AnalyzerOutputDto:
      required:
        - dataStreamId
      type: object
      properties:
        dataStreamId:
          type: string
          description: Unique identifier of the target output data stream.
          format: uuid
      additionalProperties: false
      description: An output binding that maps the analyzer result to a target data stream.
    AnalyzerPatchConfig:
      type: object
      properties:
        expression:
          type: string
          description: Mathematical expression for the transformation.
          nullable: true
      additionalProperties: false
      description: Partial TransferFunction computation settings. Only provided fields
        are updated.
    AnalyzerPatchRequest:
      type: object
      properties:
        name:
          maxLength: 256
          type: string
          description: "Human-readable name of the analyzer. Example: F to C converter."
          nullable: true
        description:
          maxLength: 500
          type: string
          description: Description of the analyzer.
          nullable: true
        inputParameters:
          minItems: 1
          type: array
          items:
            $ref: "#/components/schemas/AnalyzerInputStream"
          description: Input mappings. Replaces existing mappings when provided.
          nullable: true
        config:
          $ref: "#/components/schemas/AnalyzerPatchConfig"
        outputs:
          maxItems: 1
          minItems: 1
          type: array
          items:
            $ref: "#/components/schemas/AnalyzerOutputDto"
          description: Output bindings. Replaces existing outputs when provided;
            TransferFunction emits exactly one output.
          nullable: true
      additionalProperties: false
      description: Payload for partially updating an analyzer. Only provided fields
        are updated.
    AnalyzerType:
      enum:
        - TransferFunction
      type: string
    AnalyzerUpdateRequest:
      required:
        - config
        - inputParameters
        - name
        - outputs
        - type
      type: object
      properties:
        name:
          maxLength: 256
          minLength: 1
          type: string
          description: "Human-readable name of the analyzer. Example: F to C converter."
        description:
          maxLength: 500
          type: string
          description: Description of the analyzer.
          nullable: true
        type:
          $ref: "#/components/schemas/AnalyzerType"
        inputParameters:
          minItems: 1
          type: array
          items:
            $ref: "#/components/schemas/AnalyzerInputStream"
          description: Input mappings that bind data streams to expression variables.
        config:
          $ref: "#/components/schemas/AnalyzerConfigTransferFunction"
        outputs:
          maxItems: 1
          minItems: 1
          type: array
          items:
            $ref: "#/components/schemas/AnalyzerOutputDto"
          description: Output bindings. TransferFunction emits exactly one output.
      additionalProperties: false
      description: Payload for replacing all editable fields of an analyzer.
    IAnalyzerConfigDto:
      type: object
      additionalProperties: false
    BridgeAssemblyPolicy:
      required:
        - onTimeout
      type: object
      properties:
        queueLimit:
          maximum: 2147483647
          minimum: 1
          type: integer
          format: int32
        timeoutSeconds:
          maximum: 300
          minimum: 1
          type: integer
          format: int32
        onTimeout:
          maxLength: 64
          minLength: 0
          type: string
      additionalProperties: false
    BridgeBinding:
      required:
        - dataStreamId
        - deviceId
        - targetJsonPath
      type: object
      properties:
        deviceId:
          maxLength: 256
          minLength: 0
          type: string
        dataStreamId:
          type: string
          format: uuid
        sourceFieldName:
          maxLength: 256
          minLength: 0
          type: string
          nullable: true
        targetJsonPath:
          maxLength: 256
          minLength: 0
          type: string
        dataType:
          maxLength: 64
          minLength: 0
          type: string
          nullable: true
        requiredForAssembly:
          type: boolean
      additionalProperties: false
    BridgeDetail:
      type: object
      properties:
        bridgeId:
          type: string
          format: uuid
        name:
          type: string
          nullable: true
        isEnabled:
          type: boolean
        mqtt:
          $ref: "#/components/schemas/BridgeMqttDetail"
        assemblyPolicy:
          $ref: "#/components/schemas/BridgeAssemblyPolicy"
        bindings:
          type: array
          items:
            $ref: "#/components/schemas/BridgeBinding"
          nullable: true
        runtimeState:
          $ref: "#/components/schemas/BridgeRuntimeState"
      additionalProperties: false
    BridgeFaultInfo:
      type: object
      properties:
        code:
          type: string
          nullable: true
        message:
          type: string
          nullable: true
        willRetry:
          type: boolean
        maxRetryAttempts:
          type: integer
          format: int32
      additionalProperties: false
    BridgeListItem:
      type: object
      properties:
        bridgeId:
          type: string
          format: uuid
        name:
          type: string
          nullable: true
        isEnabled:
          type: boolean
        mqttBrokerConfigName:
          type: string
          nullable: true
        hasStoredBrokerCredentials:
          type: boolean
        brokerEndpoint:
          type: string
          nullable: true
        runtimeStatus:
          type: string
          nullable: true
      additionalProperties: false
    BridgeListItemPagedResult:
      type: object
      properties:
        items:
          type: array
          items:
            $ref: "#/components/schemas/BridgeListItem"
          nullable: true
        totalCount:
          type: integer
          format: int64
      additionalProperties: false
    BridgeMqtt:
      required:
        - mqttBrokerConfigId
        - outputTopic
      type: object
      properties:
        mqttBrokerConfigId:
          type: string
          format: uuid
        outputTopic:
          maxLength: 512
          minLength: 0
          type: string
        qos:
          maximum: 2
          minimum: 0
          type: integer
          format: int32
      additionalProperties: false
    BridgeMqttDetail:
      type: object
      properties:
        mqttConfigId:
          type: string
          format: uuid
        mqttBrokerConfigName:
          type: string
          nullable: true
        hasStoredBrokerCredentials:
          type: boolean
        brokerEndpoint:
          type: string
          nullable: true
        authType:
          type: string
          nullable: true
        keepAliveInterval:
          type: string
          nullable: true
        reconnectInterval:
          type: string
          nullable: true
        outputTopic:
          type: string
          nullable: true
        qos:
          type: integer
          format: int32
      additionalProperties: false
    BridgeRuntimeState:
      type: object
      properties:
        status:
          type: string
          nullable: true
        lastPublishTime:
          type: string
          format: date-time
          nullable: true
        queueDepth:
          type: integer
          format: int32
        fault:
          $ref: "#/components/schemas/BridgeFaultInfo"
      additionalProperties: false
    BridgeSummary:
      type: object
      properties:
        bridgeId:
          type: string
          format: uuid
        name:
          type: string
          nullable: true
        isEnabled:
          type: boolean
        mqttConfigId:
          type: string
          format: uuid
        mqttBrokerConfigName:
          type: string
          nullable: true
        hasStoredBrokerCredentials:
          type: boolean
        brokerEndpoint:
          type: string
          nullable: true
        outputTopic:
          type: string
          nullable: true
      additionalProperties: false
    BrokerCredentials:
      required:
        - password
        - username
      type: object
      properties:
        username:
          minLength: 1
          type: string
        password:
          minLength: 1
          type: string
      additionalProperties: false
    CreateBridgeRequest:
      required:
        - mqtt
        - name
      type: object
      properties:
        name:
          maxLength: 256
          minLength: 0
          type: string
        mqtt:
          $ref: "#/components/schemas/BridgeMqtt"
        bindings:
          minItems: 1
          type: array
          items:
            $ref: "#/components/schemas/BridgeBinding"
          nullable: true
        assemblyPolicy:
          $ref: "#/components/schemas/BridgeAssemblyPolicy"
      additionalProperties: false
    CreateMqttBrokerConfigRequest:
      required:
        - authType
        - brokerEndpoint
        - name
      type: object
      properties:
        name:
          minLength: 1
          type: string
        brokerEndpoint:
          minLength: 1
          type: string
        authType:
          minLength: 1
          type: string
        brokerCredentials:
          $ref: "#/components/schemas/BrokerCredentials"
        keepAliveInterval:
          type: string
          nullable: true
        reconnectInterval:
          type: string
          nullable: true
        mqttProtocolVersion:
          $ref: "#/components/schemas/MqttProtocolVersion"
        checkConnection:
          type: boolean
      additionalProperties: false
    MqttBrokerConfig:
      type: object
      properties:
        mqttConfigId:
          type: string
          format: uuid
        name:
          type: string
          nullable: true
        brokerEndpoint:
          type: string
          nullable: true
        authType:
          type: string
          nullable: true
        keepAliveInterval:
          type: string
          nullable: true
        reconnectInterval:
          type: string
          nullable: true
        mqttProtocolVersion:
          type: string
          nullable: true
        hasStoredCredentials:
          type: boolean
        isInUse:
          type: boolean
      additionalProperties: false
    MqttBrokerConfigListItem:
      type: object
      properties:
        mqttConfigId:
          type: string
          format: uuid
        name:
          type: string
          nullable: true
        brokerEndpoint:
          type: string
          nullable: true
        hasStoredCredentials:
          type: boolean
        isInUse:
          type: boolean
      additionalProperties: false
    MqttBrokerConfigListItemPagedResult:
      type: object
      properties:
        items:
          type: array
          items:
            $ref: "#/components/schemas/MqttBrokerConfigListItem"
          nullable: true
        totalCount:
          type: integer
          format: int64
      additionalProperties: false
    MqttProtocolVersion:
      enum:
        - V311
        - V500
        - V310
      type: string
    PatchBridgeAssemblyPolicy:
      type: object
      properties:
        queueLimit:
          maximum: 2147483647
          minimum: 1
          type: integer
          format: int32
          nullable: true
        timeoutSeconds:
          maximum: 300
          minimum: 1
          type: integer
          format: int32
          nullable: true
        onTimeout:
          maxLength: 64
          minLength: 0
          type: string
          nullable: true
      additionalProperties: false
    PatchBridgeMqtt:
      type: object
      properties:
        mqttBrokerConfigId:
          type: string
          format: uuid
          nullable: true
        outputTopic:
          maxLength: 512
          minLength: 0
          type: string
          nullable: true
        qos:
          maximum: 2
          minimum: 0
          type: integer
          format: int32
          nullable: true
      additionalProperties: false
    PatchBridgeRequest:
      type: object
      properties:
        name:
          maxLength: 256
          minLength: 0
          type: string
          nullable: true
        mqtt:
          $ref: "#/components/schemas/PatchBridgeMqtt"
        bindings:
          minItems: 1
          type: array
          items:
            $ref: "#/components/schemas/BridgeBinding"
          nullable: true
        assemblyPolicy:
          $ref: "#/components/schemas/PatchBridgeAssemblyPolicy"
      additionalProperties: false
    UpdateBridgeRequest:
      required:
        - mqtt
        - name
      type: object
      properties:
        name:
          maxLength: 256
          minLength: 0
          type: string
        mqtt:
          $ref: "#/components/schemas/BridgeMqtt"
        bindings:
          minItems: 1
          type: array
          items:
            $ref: "#/components/schemas/BridgeBinding"
          nullable: true
        assemblyPolicy:
          $ref: "#/components/schemas/BridgeAssemblyPolicy"
      additionalProperties: false
    UpdateBrokerCredentialsRequest:
      required:
        - authType
      type: object
      properties:
        authType:
          minLength: 1
          type: string
        brokerCredentials:
          $ref: "#/components/schemas/BrokerCredentials"
        checkConnection:
          type: boolean
      additionalProperties: false
    UpdateMqttBrokerConfigRequest:
      required:
        - brokerEndpoint
        - name
      type: object
      properties:
        name:
          minLength: 1
          type: string
        brokerEndpoint:
          minLength: 1
          type: string
        keepAliveInterval:
          type: string
          nullable: true
        reconnectInterval:
          type: string
          nullable: true
        mqttProtocolVersion:
          $ref: "#/components/schemas/MqttProtocolVersion"
        checkConnection:
          type: boolean
      additionalProperties: false
    AlertEventDto:
      type: object
      properties:
        alertEventId:
          type: string
          description: Unique identifier of the alert event
          format: uuid
        alertPolicyId:
          type: string
          description: Alert policy that fired this event
          format: uuid
        policyName:
          type: string
          description: Name of the alert policy at fire time
          nullable: true
        deviceId:
          type: string
          description: Device the triggering data stream belongs to
          nullable: true
        dataStreamId:
          type: string
          description: Data stream whose value triggered the event
          format: uuid
        status:
          $ref: "#/components/schemas/AlertEventStatus"
        triggeredValue:
          type: string
          description: Data stream value that triggered the alert condition
          nullable: true
        alertLevel:
          type: string
          description: "Alert condition of the policy at fire time. Example: >=70"
          nullable: true
        firedTime:
          type: string
          description: Time the alert condition fired, ISO 8601 UTC
          format: date-time
        acknowledgedTime:
          type: string
          description: Time the event was acknowledged. Null if not acknowledged.
          format: date-time
          nullable: true
        acknowledgedBy:
          type: string
          description: User who acknowledged the event. Null if not acknowledged.
          nullable: true
        resolvedTime:
          type: string
          description: Time the event was resolved. Null if not resolved.
          format: date-time
          nullable: true
        resolvedBy:
          type: string
          description: User who resolved the event. Null if auto-resolved or not resolved.
          nullable: true
      additionalProperties: false
      description: A fired alert instance produced by an alert policy
    AlertEventStatus:
      enum:
        - Firing
        - Acknowledged
        - Resolved
      type: string
    AlertPolicyAction:
      enum:
        - enable
        - disable
      type: string
    AlertPolicyCreateRequest:
      required:
        - alertLevel
        - alertResetLevel
        - policyName
      type: object
      properties:
        policyName:
          minLength: 1
          type: string
          description: "Policy name. Ex: WaterLevel alert policy"
        description:
          maxLength: 500
          type: string
          description: Policy description
          nullable: true
        alertLevel:
          minLength: 1
          type: string
          description: "Alert event threshold level. Ex: >=70"
        alertResetLevel:
          minLength: 1
          type: string
          description: "Alert event reset threshold level. Ex: <70"
        delay:
          maximum: 9223372036854776000
          minimum: 0
          type: integer
          description: "Seconds to delay publish event. Ex: 5"
          format: int64
        notification:
          $ref: "#/components/schemas/AlertPolicyNotificationRequest"
      additionalProperties: false
      description: Create alert policy payload
    AlertPolicyDto:
      required:
        - alertLevel
        - alertResetLevel
        - policyName
      type: object
      properties:
        alertPolicyId:
          type: string
          description: Alert policy ID
          format: uuid
        policyName:
          type: string
          description: Policy name
          nullable: true
        description:
          type: string
          description: Policy description
          nullable: true
        alertLevel:
          type: string
          description: "Alert event threshold level. Ex: >=70"
          nullable: true
        alertResetLevel:
          type: string
          description: "Alert event reset threshold level. Ex: <50"
          nullable: true
        delay:
          type: integer
          description: "Seconds to delay publish event. Ex: 5"
          format: int64
        enabled:
          type: boolean
          description: Policy enabled/disabled status
        createdAt:
          type: string
          description: Creation time of the policy
          format: date-time
          nullable: true
        createdBy:
          type: string
          description: Creator of the policy
          nullable: true
        updatedAt:
          type: string
          description: Last update time of the policy
          format: date-time
          nullable: true
        updatedBy:
          type: string
          description: Last updater of the policy
          nullable: true
        notification:
          $ref: "#/components/schemas/AlertPolicyNotificationDto"
      additionalProperties: false
      description: Alert policy data transfer object
    AlertPolicyNotificationDto:
      required:
        - channelIds
        - recipients
      type: object
      properties:
        channelIds:
          type: array
          items:
            type: string
          description: "Channel ID for publish event. Ex:
            channel_3fa85f64-5717-4562-b3fc-2c963f66afa6"
          nullable: true
        templateId:
          type: string
          description: "Template ID for publish event. Use together with variables. Do not
            use together with subject and content. Ex:
            tmpl_7fa85f64-5717-4562-b3fc-2c963f66afa6"
          nullable: true
        recipients:
          type: array
          items:
            $ref: "#/components/schemas/RecipientDto"
          description: Recipients for publish event.
          nullable: true
        variables:
          type: object
          additionalProperties:
            type: string
          description: 'Variables used in the template for publish event. Use together
            with templateId. Do not use together with subject and content. Ex:
            {"key1": "value1"}'
          nullable: true
        subject:
          type: string
          description: Subject for publish event. Use together with content. Do not use
            together with templateId and variables.
          nullable: true
        content:
          type: string
          description: Content for publish event. Use together with subject. Do not use
            together with templateId and variables.
          nullable: true
      additionalProperties: false
      description: Notification configuration for the alert policy
    AlertPolicyNotificationRequest:
      required:
        - channelIds
        - recipients
      type: object
      properties:
        channelIds:
          type: array
          items:
            type: string
          description: "Existed channel ID for publish event. Reference Get
            /notifications/channels. Ex:
            channel_3fa85f64-5717-4562-b3fc-2c963f66afa6"
          nullable: true
        templateId:
          type: string
          description: "Existed template ID for publish event. Use together with
            variables. Do not use together with subject and content. Reference
            Get /notifications/templates. Ex:
            tmpl_7fa85f64-5717-4562-b3fc-2c963f66afa6"
          nullable: true
        recipients:
          type: array
          items:
            $ref: "#/components/schemas/RecipientDto"
          description: Recipients for publish event.
          nullable: true
        variables:
          type: object
          additionalProperties:
            type: string
          description: 'Variables used in the template for publish event. Use together
            with templateId. Do not use together with subject and content. Ex:
            {"key1": "value1", "key2": "value2"}'
          nullable: true
        subject:
          type: string
          description: Subject for publish event. Use together with content. Do not use
            together with templateId and variables.
          nullable: true
        content:
          type: string
          description: Content for publish event. Use together with subject. Do not use
            together with templateId and variables.
          nullable: true
      additionalProperties: false
      description: "Notification configuration. Use exactly one pair: templateId with
        variables, or subject with content."
    AlertPolicyUpdateRequest:
      type: object
      properties:
        policyName:
          type: string
          description: Policy name
          nullable: true
        description:
          type: string
          description: Policy description
          nullable: true
        alertLevel:
          type: string
          description: "Alert event threshold level. Ex: >=70"
          nullable: true
        alertResetLevel:
          type: string
          description: "Alert event reset threshold level. Ex: <=50"
          nullable: true
        delay:
          type: integer
          description: "Seconds to delay publish event. Ex: 5"
          format: int64
          nullable: true
        notification:
          $ref: "#/components/schemas/AlertPolicyNotificationRequest"
      additionalProperties: false
      description: Update alert policy payload
    AttachmentDto:
      type: object
      properties:
        filename:
          type: string
          nullable: true
        contentType:
          type: string
          nullable: true
      additionalProperties: false
    ChannelDetailDto:
      type: object
      properties:
        channelId:
          type: string
          nullable: true
        name:
          type: string
          nullable: true
        channelName:
          type: string
          nullable: true
          writeOnly: true
        channelType:
          type: string
          nullable: true
        description:
          type: string
          nullable: true
        isEnabled:
          type: boolean
        enabled:
          type: boolean
          writeOnly: true
        commonSettings:
          $ref: "#/components/schemas/CommonSettingsDto"
        config:
          nullable: true
        recipients:
          type: array
          items:
            $ref: "#/components/schemas/ChannelRecipientDto"
          nullable: true
        tags:
          type: array
          items:
            type: string
          nullable: true
        templateId:
          type: string
          nullable: true
        createdAt:
          type: string
          format: date-time
        updatedAt:
          type: string
          format: date-time
      additionalProperties: false
    ChannelListItemDto:
      type: object
      properties:
        channelId:
          type: string
          nullable: true
        name:
          type: string
          nullable: true
        channelName:
          type: string
          nullable: true
          writeOnly: true
        channelType:
          type: string
          nullable: true
        tags:
          type: array
          items:
            type: string
          nullable: true
        isEnabled:
          type: boolean
        enabled:
          type: boolean
          writeOnly: true
        createdAt:
          type: string
          format: date-time
        updatedAt:
          type: string
          format: date-time
      additionalProperties: false
    ChannelRecipientDto:
      required:
        - target
      type: object
      properties:
        name:
          type: string
          nullable: true
        target:
          minLength: 1
          type: string
        type:
          type: string
          nullable: true
      additionalProperties: false
    ChannelStatusResponseDto:
      type: object
      properties:
        channelId:
          type: string
          nullable: true
        isEnabled:
          type: boolean
        enabled:
          type: boolean
          writeOnly: true
        updatedAt:
          type: string
          format: date-time
      additionalProperties: false
    ChannelType:
      enum:
        - email
        - teams
        - linemessage
        - webhook
      type: string
    ChannelTypeDetailDto:
      type: object
      properties:
        channelType:
          type: string
          nullable: true
        name:
          type: string
          nullable: true
        description:
          type: string
          nullable: true
        status:
          type: string
          nullable: true
        version:
          type: string
          nullable: true
        configSchema:
          nullable: true
        examples:
          type: array
          items: {}
          nullable: true
      additionalProperties: false
    ChannelTypeDto:
      type: object
      properties:
        channelType:
          type: string
          nullable: true
        name:
          type: string
          nullable: true
        description:
          type: string
          nullable: true
        status:
          type: string
          nullable: true
        version:
          type: string
          nullable: true
      additionalProperties: false
    ChannelUpdateStatusRequest:
      required:
        - isEnabled
      type: object
      properties:
        isEnabled:
          type: boolean
      additionalProperties: false
    CommonSettingsDto:
      type: object
      properties:
        timeout:
          maximum: 300000
          minimum: 0
          type: integer
          format: int32
          nullable: true
        retryAttempts:
          maximum: 10
          minimum: 0
          type: integer
          format: int32
          nullable: true
        retryDelay:
          maximum: 60000
          minimum: 0
          type: integer
          format: int32
          nullable: true
      additionalProperties: false
    CreateChannelDto:
      required:
        - channelType
        - config
        - name
      type: object
      properties:
        name:
          maxLength: 100
          minLength: 1
          pattern: ^\S+$
          type: string
        channelType:
          $ref: "#/components/schemas/ChannelType"
        description:
          maxLength: 500
          type: string
          nullable: true
        isEnabled:
          type: boolean
        commonSettings:
          $ref: "#/components/schemas/CommonSettingsDto"
        config:
          description: >-
            Channel-type-specific configuration object. Structure depends on
            channelType:


            **email**: `{ host* (string), port* (1-65535), username* (string),
            password* (string), senderEmail* (email), senderName (string),
            secure (bool) }`


            **teams**: `{ url* (URL) }`


            **linemessage**: `{ accessToken* (string), sendMode* ('push' |
            'multicast') }`


            **webhook**: `{ url* (URL), method*
            ('GET'|'POST'|'PUT'|'PATCH'|'DELETE'), contentType*
            ('applicationJson'|'applicationFormUrlEncoded'|'textPlain') }`


            Fields marked with * are required.
        templateId:
          type: string
          nullable: true
        recipients:
          type: array
          items:
            $ref: "#/components/schemas/ChannelRecipientDto"
          nullable: true
        tags:
          type: array
          items:
            type: string
          nullable: true
      additionalProperties: false
    CreateTemplateDto:
      required:
        - channelTypes
        - content
        - name
      type: object
      properties:
        name:
          maxLength: 200
          minLength: 1
          type: string
        subject:
          maxLength: 500
          type: string
          nullable: true
        content:
          maxLength: 50000
          minLength: 1
          type: string
        channelTypes:
          type: array
          items:
            type: string
        tags:
          type: array
          items:
            type: string
          nullable: true
      additionalProperties: false
    DataStreamAttachmentDto:
      required:
        - deviceId
      type: object
      properties:
        deviceId:
          type: string
          description: "Device ID. Ex: 9F75ABDA56C3"
          nullable: true
        dataStreamId:
          type: string
          description: Data stream unique identifier
          format: uuid
      additionalProperties: false
      description: A device + data stream pair attached to an alert policy
    DataStreamAttachmentResponseDto:
      required:
        - deviceId
      type: object
      properties:
        alertPolicyId:
          type: string
          description: Alert policy the data stream is attached to
          format: uuid
        deviceId:
          type: string
          description: "Device ID. Ex: 9F75ABDA56C3"
          nullable: true
        dataStreamId:
          type: string
          description: Data stream unique identifier
          format: uuid
      additionalProperties: false
      description: A device + data stream pair after being attached to an alert policy
    MessageDetailDto:
      type: object
      properties:
        messageId:
          type: string
          nullable: true
        channelIds:
          type: array
          items:
            type: string
          nullable: true
        templateId:
          type: string
          nullable: true
        recipients:
          type: array
          items:
            $ref: "#/components/schemas/RecipientDto"
          nullable: true
        subject:
          type: string
          nullable: true
        content:
          type: string
          nullable: true
        variables:
          type: object
          additionalProperties: {}
          nullable: true
        status:
          $ref: "#/components/schemas/MessageStatus"
        results:
          type: array
          items:
            $ref: "#/components/schemas/MessageResultDto"
          nullable: true
        successCount:
          type: integer
          format: int32
        failureCount:
          type: integer
          format: int32
        totalCount:
          type: integer
          format: int32
        settings:
          $ref: "#/components/schemas/MessageSettingsDto"
        attachments:
          type: array
          items:
            $ref: "#/components/schemas/AttachmentDto"
          nullable: true
        sentAt:
          type: string
          format: date-time
          nullable: true
        createdAt:
          type: string
          format: date-time
      additionalProperties: false
    MessageListItemDto:
      type: object
      properties:
        messageId:
          type: string
          nullable: true
        channelIds:
          type: array
          items:
            type: string
          nullable: true
        status:
          $ref: "#/components/schemas/MessageStatus"
        successCount:
          type: integer
          format: int32
        failureCount:
          type: integer
          format: int32
        totalCount:
          type: integer
          format: int32
        createdAt:
          type: string
          format: date-time
        sentAt:
          type: string
          format: date-time
          nullable: true
      additionalProperties: false
    MessageResultDto:
      type: object
      properties:
        channelId:
          type: string
          nullable: true
        name:
          type: string
          nullable: true
        channelName:
          type: string
          nullable: true
          writeOnly: true
        status:
          type: string
          nullable: true
        message:
          type: string
          nullable: true
        sentAt:
          type: string
          format: date-time
          nullable: true
      additionalProperties: false
    MessageSettingsDto:
      type: object
      properties:
        timeout:
          type: integer
          format: int32
        retryAttempts:
          type: integer
          format: int32
        retryDelay:
          type: integer
          format: int32
      additionalProperties: false
    MessageStatus:
      enum:
        - pending
        - sent
        - failed
        - partial
        - success
      type: string
    PagedResultDtoOfAlertEventDto:
      type: object
      properties:
        items:
          type: array
          items:
            $ref: "#/components/schemas/AlertEventDto"
          nullable: true
        totalCount:
          type: integer
          format: int64
      additionalProperties: false
    PagedResultDtoOfAlertPolicyDto:
      type: object
      properties:
        items:
          type: array
          items:
            $ref: "#/components/schemas/AlertPolicyDto"
          nullable: true
        totalCount:
          type: integer
          format: int64
      additionalProperties: false
    PagedResultDtoOfChannelListItemDto:
      type: object
      properties:
        items:
          type: array
          items:
            $ref: "#/components/schemas/ChannelListItemDto"
          nullable: true
        totalCount:
          type: integer
          format: int64
      additionalProperties: false
    PagedResultDtoOfChannelTypeDto:
      type: object
      properties:
        items:
          type: array
          items:
            $ref: "#/components/schemas/ChannelTypeDto"
          nullable: true
        totalCount:
          type: integer
          format: int64
      additionalProperties: false
    PagedResultDtoOfDataStreamAttachmentDto:
      type: object
      properties:
        items:
          type: array
          items:
            $ref: "#/components/schemas/DataStreamAttachmentDto"
          nullable: true
        totalCount:
          type: integer
          format: int64
      additionalProperties: false
    PagedResultDtoOfMessageListItemDto:
      type: object
      properties:
        items:
          type: array
          items:
            $ref: "#/components/schemas/MessageListItemDto"
          nullable: true
        totalCount:
          type: integer
          format: int64
      additionalProperties: false
    PagedResultDtoOfTemplateListItemDto:
      type: object
      properties:
        items:
          type: array
          items:
            $ref: "#/components/schemas/TemplateListItemDto"
          nullable: true
        totalCount:
          type: integer
          format: int64
      additionalProperties: false
    RecipientDto:
      required:
        - target
        - type
      type: object
      properties:
        name:
          type: string
          nullable: true
        target:
          minLength: 1
          type: string
        type:
          minLength: 1
          type: string
          description: "Recipient type: to, cc, bcc"
      additionalProperties: false
    TemplateDetailDto:
      type: object
      properties:
        templateId:
          type: string
          nullable: true
        name:
          type: string
          nullable: true
        templateName:
          type: string
          nullable: true
          writeOnly: true
        subject:
          type: string
          nullable: true
        content:
          type: string
          nullable: true
        channelTypes:
          type: array
          items:
            type: string
          nullable: true
        tags:
          type: array
          items:
            type: string
          nullable: true
        createdAt:
          type: string
          format: date-time
        updatedAt:
          type: string
          format: date-time
      additionalProperties: false
    TemplateListItemDto:
      type: object
      properties:
        templateId:
          type: string
          nullable: true
        name:
          type: string
          nullable: true
        templateName:
          type: string
          nullable: true
          writeOnly: true
        subject:
          type: string
          nullable: true
        channelTypes:
          type: array
          items:
            type: string
          nullable: true
        tags:
          type: array
          items:
            type: string
          nullable: true
        createdAt:
          type: string
          format: date-time
      additionalProperties: false
    TemplateResponseDto:
      type: object
      properties:
        templateId:
          type: string
          nullable: true
        name:
          type: string
          nullable: true
        templateName:
          type: string
          nullable: true
          writeOnly: true
        subject:
          type: string
          nullable: true
        content:
          type: string
          nullable: true
        channelTypes:
          type: array
          items:
            type: string
          nullable: true
        tags:
          type: array
          items:
            type: string
          nullable: true
        createdAt:
          type: string
          format: date-time
      additionalProperties: false
    UpdateChannelDto:
      type: object
      properties:
        name:
          type: string
          nullable: true
        channelType:
          $ref: "#/components/schemas/ChannelType"
        description:
          type: string
          nullable: true
        isEnabled:
          type: boolean
          nullable: true
        commonSettings:
          $ref: "#/components/schemas/CommonSettingsDto"
        config:
          description: >-
            Channel-type-specific configuration object. Structure depends on
            channelType:


            **email**: `{ host* (string), port* (1-65535), username* (string),
            password* (string), senderEmail* (email), senderName (string),
            secure (bool) }`


            **teams**: `{ url* (URL) }`


            **linemessage**: `{ accessToken* (string), sendMode* ('push' |
            'multicast') }`


            **webhook**: `{ url* (URL), method*
            ('GET'|'POST'|'PUT'|'PATCH'|'DELETE'), contentType*
            ('applicationJson'|'applicationFormUrlEncoded'|'textPlain') }`


            Fields marked with * are required.
          nullable: true
        templateId:
          type: string
          nullable: true
        recipients:
          type: array
          items:
            $ref: "#/components/schemas/ChannelRecipientDto"
          nullable: true
        tags:
          type: array
          items:
            type: string
          nullable: true
      additionalProperties: false
    UpdateTemplateDto:
      type: object
      properties:
        name:
          maxLength: 200
          type: string
          nullable: true
        subject:
          maxLength: 500
          type: string
          nullable: true
        content:
          maxLength: 50000
          type: string
          nullable: true
        channelTypes:
          type: array
          items:
            $ref: "#/components/schemas/ChannelType"
          nullable: true
        tags:
          type: array
          items:
            type: string
          nullable: true
      additionalProperties: false
    CreateScheduleResultDto:
      type: object
      properties:
        usageJobId:
          type: string
          format: uuid
        name:
          type: string
          nullable: true
        repeatPeriod:
          $ref: "#/components/schemas/RepeatPeriod"
        endTime:
          type: string
          nullable: true
        timeZone:
          type: string
          nullable: true
        jobs:
          type: array
          items:
            type: string
          nullable: true
      additionalProperties: false
    CreateScheduledJobRequestDto:
      required:
        - endTime
        - jobs
        - name
        - repeatPeriod
        - timeZone
      type: object
      properties:
        name:
          minLength: 1
          type: string
          description: active device count report
          default: active device count report
        repeatPeriod:
          $ref: "#/components/schemas/RepeatPeriod"
        endTime:
          minLength: 1
          type: string
          description: 2025-12-31
          default: 2025-12-31
        timeZone:
          minLength: 1
          type: string
          description: +08:30
          default: +08:30
        jobs:
          type: array
          items:
            type: string
          description: DataPointCount, ActiveDeviceCount
          default:
            - ActiveDeviceCount
            - DataPointCount
      additionalProperties: false
    GetScheduledJobResponseDto:
      type: object
      properties:
        usageJobId:
          type: string
          format: uuid
          nullable: true
        name:
          type: string
          nullable: true
        repeatPeriod:
          type: string
          nullable: true
        endTime:
          type: string
          nullable: true
        timeZone:
          type: string
          nullable: true
        jobs:
          type: array
          items:
            type: string
          nullable: true
      additionalProperties: false
    RepeatPeriod:
      enum:
        - Daily
        - Weekly
        - Monthly
      type: string
    UpdatePutScheduledJobRequestDto:
      required:
        - endTime
        - jobs
        - name
        - timeZone
      type: object
      properties:
        name:
          minLength: 1
          type: string
          description: active device count report
          default: active device count report
        repeatPeriod:
          $ref: "#/components/schemas/RepeatPeriod"
        endTime:
          minLength: 1
          type: string
          description: 2026-12-31
          default: 2026-12-31
        timeZone:
          minLength: 1
          type: string
          description: Custom Time Zone
          default: +08:30
        jobs:
          type: array
          items:
            type: string
          description: DataPointCount, ActiveDeviceCount
          default:
            - ActiveDeviceCount
            - DataPointCount
      additionalProperties: false
    CreateTunnelDto:
      required:
        - applicationHost
        - applicationPort
        - purpose
        - serviceType
        - tags
      type: object
      properties:
        serviceType:
          minLength: 1
          type: string
          description: '**The type of service being tunneled**, e.g., "ssh", "http",
            "https", "vnc", "rdp", "mqtt".'
          format: Enumeration
          default: ssh
        applicationHost:
          minLength: 1
          type: string
          description: |-
            **The target application host address**.
            Can be an IP address or a domain name.
        applicationPort:
          maximum: 65535
          minimum: 0
          type: integer
          description: >-
            **The target application port**.

            This is the port on the target host that the service is listening
            on.
          format: int32
        purpose:
          minLength: 1
          type: string
          description: |-
            **The purpose or justification for the tunnel**.
            A brief description of why this tunnel is being created.
        tags:
          type: array
          items:
            type: string
          description: |-
            **A list of tags for the tunnel**.
            Used for categorization or identification purposes.
      additionalProperties: false
      description: Data Transfer Object (DTO) required to create a new Tunnel.
    HealthStatus:
      enum:
        - HEALTHY
        - DEGRADED
        - UNHEALTHY
        - UNKNOWN
      type: string
    PagedResultDto of TunnelDto:
      type: object
      properties:
        items:
          type: array
          items:
            $ref: "#/components/schemas/TunnelDto"
          nullable: true
        totalCount:
          type: integer
          format: int64
      additionalProperties: false
    ServiceType:
      enum:
        - ssh
        - http
        - https
        - vnc
        - rdp
        - mqtt
      type: string
    TerminateTunnelDto:
      type: object
      properties:
        reason:
          type: string
          description: |-
            The reason for terminating the tunnel.
            This should provide context for why the tunnel is being closed.
          nullable: true
        graceful:
          type: boolean
          description: >-
            Whether to perform a graceful shutdown.

            If true, the tunnel will attempt to close existing connections
            cleanly.

            If false, the tunnel will be terminated immediately.
        forceTimeout:
          type: integer
          description: >-
            Maximum time in seconds to wait for graceful termination before
            forcing closure.

            Only applies when graceful is true.
          format: int32
      additionalProperties: false
      description: Data Transfer Object for terminating a tunnel session.
    TunnelDetailDto:
      required:
        - applicationHost
        - purpose
        - tags
      type: object
      properties:
        tunnelSessionId:
          type: string
          description: Unique identifier for the tunnel session.
          format: uuid
        deviceId:
          type: string
          description: The device ID associated with this tunnel.
          nullable: true
        serviceType:
          $ref: "#/components/schemas/ServiceType"
        applicationPort:
          type: integer
          description: Target application port on the device.
          format: int32
        applicationHost:
          type: string
          description: Target application host address (IP or domain name).
          nullable: true
        creationTime:
          type: string
          description: The date and time when the tunnel was created.
          format: date-time
        purpose:
          type: string
          description: The purpose or justification for creating this tunnel.
          nullable: true
        tags:
          type: array
          items:
            type: string
          description: List of tags for categorization and identification.
          nullable: true
        sessionStatus:
          $ref: "#/components/schemas/TunnelSessionStatus"
        tunnelEndpoint:
          type: string
          description: Full tunnel endpoint URL for accessing the tunnel.
          nullable: true
        webSsh:
          type: string
          description: WebSsh access URL if available.
          nullable: true
        estimatedReadyTime:
          type: string
          description: Estimated time when the tunnel will be ready for use.
          format: date-time
          nullable: true
        lastHeartbeatTime:
          type: string
          description: Last time a heartbeat was received from the tunnel.
          format: date-time
          nullable: true
        terminatedTime:
          type: string
          description: The date and time when the tunnel was terminated.
          format: date-time
          nullable: true
        lastModificationTime:
          type: string
          description: The date and time when the tunnel was last modified.
          format: date-time
          nullable: true
        terminationSource:
          $ref: "#/components/schemas/TunnelTerminationSource"
        terminationReason:
          description: >-
            The reason for termination. For User-initiated terminations, this
            contains the parsed JSON payload.

            For TunnelServer or TunnelMgmt terminations, this contains a
            descriptive message.
          nullable: true
        links:
          description: >-
            HATEOAS links for related resources following HAL (Hypertext
            Application Language) format.

            Contains navigational links to related operations such as self,
            update, terminate, and list.
          nullable: true
        healthStatus:
          $ref: "#/components/schemas/HealthStatus"
      additionalProperties: false
      description: >-
        Detailed tunnel session information including health status and
        modification history.

        Extends EdgeSync.TunnelMgmt.Dtos.TunnelDto with additional detail
        fields.
    TunnelDto:
      required:
        - applicationHost
        - purpose
        - tags
      type: object
      properties:
        tunnelSessionId:
          type: string
          description: Unique identifier for the tunnel session.
          format: uuid
        deviceId:
          type: string
          description: The device ID associated with this tunnel.
          nullable: true
        serviceType:
          $ref: "#/components/schemas/ServiceType"
        applicationPort:
          type: integer
          description: Target application port on the device.
          format: int32
        applicationHost:
          type: string
          description: Target application host address (IP or domain name).
          nullable: true
        creationTime:
          type: string
          description: The date and time when the tunnel was created.
          format: date-time
        purpose:
          type: string
          description: The purpose or justification for creating this tunnel.
          nullable: true
        tags:
          type: array
          items:
            type: string
          description: List of tags for categorization and identification.
          nullable: true
        sessionStatus:
          $ref: "#/components/schemas/TunnelSessionStatus"
        tunnelEndpoint:
          type: string
          description: Full tunnel endpoint URL for accessing the tunnel.
          nullable: true
        webSsh:
          type: string
          description: WebSsh access URL if available.
          nullable: true
        estimatedReadyTime:
          type: string
          description: Estimated time when the tunnel will be ready for use.
          format: date-time
          nullable: true
        lastHeartbeatTime:
          type: string
          description: Last time a heartbeat was received from the tunnel.
          format: date-time
          nullable: true
        terminatedTime:
          type: string
          description: The date and time when the tunnel was terminated.
          format: date-time
          nullable: true
        lastModificationTime:
          type: string
          description: The date and time when the tunnel was last modified.
          format: date-time
          nullable: true
        terminationSource:
          $ref: "#/components/schemas/TunnelTerminationSource"
        terminationReason:
          description: >-
            The reason for termination. For User-initiated terminations, this
            contains the parsed JSON payload.

            For TunnelServer or TunnelMgmt terminations, this contains a
            descriptive message.
          nullable: true
        links:
          description: >-
            HATEOAS links for related resources following HAL (Hypertext
            Application Language) format.

            Contains navigational links to related operations such as self,
            update, terminate, and list.
          nullable: true
      additionalProperties: false
      description: Tunnel session data transfer object containing basic tunnel information.
    TunnelSessionStatus:
      enum:
        - REQUESTED
        - ESTABLISHING
        - ESTABLISHED
        - RECONNECTING
        - TERMINATING
        - TERMINATED
        - FAILED
      type: string
    TunnelTerminationSource:
      enum:
        - User
        - TunnelServer
        - TunnelMgmt
      type: string
  securitySchemes:
    Bearer:
      type: apiKey
      description: "JWT token in the format: Bearer {your token}"
      name: Authorization
      in: header
x-tagGroups:
  - name: Public APIs
    tags:
      - ___swagger_1-iam_swagger_json_Identity & Access
      - ___swagger_2-device-management_swagger_json_Devices
      - ___swagger_2-device-management_swagger_json_WEDA Node Credentials
      - ___swagger_3-container-management_swagger_json_Container Commands
      - ___swagger_3-container-management_swagger_json_Container Deployments
      - ___swagger_3-container-management_swagger_json_Container Registries
      - ___swagger_3-container-management_swagger_json_Container Stacks
      - ___swagger_4-ai-model-management_swagger_json_Model Deployments
      - ___swagger_4-ai-model-management_swagger_json_Model Management
      - ___swagger_4-ai-model-management_swagger_json_Model Uploads
      - ___swagger_5-data-stream_swagger_json_DataStreams
      - ___swagger_6-data-analyzer_swagger_json_Analyzers
      - ___swagger_7-data-bridge_swagger_json_Data Bridges
      - ___swagger_7-data-bridge_swagger_json_Data Bridges Components
      - ___swagger_8-alert-policy_swagger_json_AlertEvents
      - ___swagger_8-alert-policy_swagger_json_AlertPolicies
      - ___swagger_8-alert-policy_swagger_json_Notifications
      - ___swagger_9-reports_swagger_json_Reports
      - ___swagger_10-tunnel-management_swagger_json_Tunnels
