openapi: 3.0.3
info:
  title: Mainflux Things Service
  description: |
    This is the Things Server based on the OpenAPI 3.0 specification.  It is the HTTP API for managing platform things and channels. You can now help us improve the API whether it's by making changes to the definition itself or to the code.
    Some useful links:
    - [The Mainflux repository](https://github.com/mainflux/mainflux)
  contact:
    email: info@mainflux.com
  license:
    name: Apache 2.0
    url: https://github.com/mainflux/mainflux/blob/master/LICENSE
  version: 0.14.0

servers:
  - url: http://localhost:9000
  - url: https://localhost:9000

tags:
  - name: Things
    description: Everything about your Things
    externalDocs:
      description: Find out more about things
      url: http://docs.mainflux.io/
  - name: Channels
    description: Everything about your Channels
    externalDocs:
      description: Find out more about things channels
      url: http://docs.mainflux.io/
  - name: Policies
    description: Access to things policies
    externalDocs:
      description: Find out more about things policies
      url: http://docs.mainflux.io/

paths:
  /things:
    post:
      tags:
        - Things
      summary: Adds new thing
      description: |
        Adds new thing to the list of things owned by user identified using
        the provided access token.
      requestBody:
        $ref: "#/components/requestBodies/ThingCreateReq"
      responses:
        "201":
          $ref: "#/components/responses/ThingCreateRes"
        "400":
          description: Failed due to malformed JSON.
        "401":
          description: Missing or invalid access token provided.
        "409":
          description: Failed due to using an existing identity.
        "415":
          description: Missing or invalid content type.
        "422":
          description: Database can't process request.
        "500":
          $ref: "#/components/responses/ServiceError"

    get:
      tags:
        - Things
      summary: Retrieves things
      description: |
        Retrieves a list of things. Due to performance concerns, data
        is retrieved in subsets. The API things must ensure that the entire
        dataset is consumed either by making subsequent requests, or by
        increasing the subset size of the initial request.
      parameters:
        - $ref: "#/components/parameters/Limit"
        - $ref: "#/components/parameters/Offset"
        - $ref: "#/components/parameters/Metadata"
        - $ref: "#/components/parameters/Status"
        - $ref: "#/components/parameters/ThingName"
        - $ref: "#/components/parameters/Tags"
        - $ref: "#/components/parameters/Owner"
      security:
        - bearerAuth: []
      responses:
        "200":
          $ref: "#/components/responses/ThingPageRes"
        "400":
          description: Failed due to malformed query parameters.
        "401":
          description: |
            Missing or invalid access token provided.
        "404":
          description: A non-existent entity request.
        "422":
          description: Database can't process request.
        "500":
          $ref: "#/components/responses/ServiceError"

  /things/bulk:
    post:
      summary: Bulk provisions new things
      description: |
        Adds new things to the list of things owned by user identified using
        the provided access token.
      tags:
        - Things
      requestBody:
        $ref: "#/components/requestBodies/ThingsCreateReq"
      responses:
        "201":
          $ref: "#/components/responses/ThingPageRes"
        "400":
          description: Failed due to malformed JSON.
        "401":
          description: Missing or invalid access token provided.
        "415":
          description: Missing or invalid content type.
        "500":
          $ref: "#/components/responses/ServiceError"

  /things/{thingID}:
    get:
      summary: Retrieves thing info
      description: |
        Retrieves a specific thing that is identifier by the thing ID.
      tags:
        - Things
      parameters:
        - $ref: "#/components/parameters/ThingID"
      security:
        - bearerAuth: []
      responses:
        "200":
          $ref: "#/components/responses/ThingRes"
        "401":
          description: Missing or invalid access token provided.
        "404":
          description: A non-existent entity request.
        "422":
          description: Database can't process request.
        "500":
          $ref: "#/components/responses/ServiceError"

    patch:
      summary: Updates name and metadata of the thing.
      description: |
        Update is performed by replacing the current resource data with values
        provided in a request payload. Note that the thing's type and ID
        cannot be changed.
      tags:
        - Things
      parameters:
        - $ref: "#/components/parameters/ThingID"
      requestBody:
        $ref: "#/components/requestBodies/ThingUpdateReq"
      security:
        - bearerAuth: []
      responses:
        "200":
          $ref: "#/components/responses/ThingRes"
        "400":
          description: Failed due to malformed JSON.
        "401":
          description: Missing or invalid access token provided.
        "404":
          description: Failed due to non existing thing.
        "415":
          description: Missing or invalid content type.
        "500":
          $ref: "#/components/responses/ServiceError"

  /things/{thingID}/tags:
    patch:
      summary: Updates tags the thing.
      description: |
        Updates tags of the thing with provided ID. Tags is updated using
        authorization token and the new tags received in request.
      tags:
        - Things
      parameters:
        - $ref: "#/components/parameters/ThingID"
      requestBody:
        $ref: "#/components/requestBodies/ThingUpdateTagsReq"
      security:
        - bearerAuth: []
      responses:
        "200":
          $ref: "#/components/responses/ThingRes"
        "400":
          description: Failed due to malformed JSON.
        "404":
          description: Failed due to non existing thing.
        "401":
          description: Missing or invalid access token provided.
        "500":
          $ref: "#/components/responses/ServiceError"

  /things/{thingID}/owner:
    patch:
      summary: Updates the thing owner.
      description: |
        Updates owner for the thing with provided ID. Owner is updated using
        authorization token and a new owner identifier received in request.
      tags:
        - Things
      parameters:
        - $ref: "#/components/parameters/ThingID"
      requestBody:
        $ref: "#/components/requestBodies/ThingUpdateOwnerReq"
      security:
        - bearerAuth: []
      responses:
        "200":
          $ref: "#/components/responses/ThingRes"
        "400":
          description: Failed due to malformed JSON.
        "404":
          description: Failed due to non existing thing.
        "401":
          description: Missing or invalid access token provided.
        "500":
          $ref: "#/components/responses/ServiceError"

  /things/{thingID}/secret:
    patch:
      summary: Updates Secret of the identified thing.
      description: |
        Updates secret of the identified in thing. Secret is updated using
        authorization token and the new received info. Update is performed by replacing current key with a new one.
      tags:
        - Things
      parameters:
        - $ref: "#/components/parameters/ThingID"
      requestBody:
        $ref: "#/components/requestBodies/ThingUpdateSecretReq"
      security:
        - bearerAuth: []
      responses:
        "200":
          $ref: "#/components/responses/ThingRes"
        "400":
          description: Failed due to malformed JSON.
        "401":
          description: Missing or invalid access token provided.
        "404":
          description: Failed due to non existing thing.
        "409":
          description: Specified key already exists.
        "415":
          description: Missing or invalid content type.
        "500":
          $ref: "#/components/responses/ServiceError"

  /things/{thingID}/disable:
    post:
      summary: Disables a thing
      description: |
        Disables a specific thing that is identifier by the thing ID.
      tags:
        - Things
      parameters:
        - $ref: "#/components/parameters/ThingID"
      security:
        - bearerAuth: []
      responses:
        "200":
          $ref: "#/components/responses/ThingRes"
        "400":
          description: Failed due to malformed thing's ID.
        "401":
          description: Missing or invalid access token provided.
        "404":
          description: A non-existent entity request.
        "422":
          description: Database can't process request.
        "500":
          $ref: "#/components/responses/ServiceError"

  /things/{thingID}/enable:
    post:
      summary: Enables a thing
      description: |
        Enables a specific thing that is identifier by the thing ID.
      tags:
        - Things
      parameters:
        - $ref: "#/components/parameters/ThingID"
      security:
        - bearerAuth: []
      responses:
        "200":
          $ref: "#/components/responses/ThingRes"
        "400":
          description: Failed due to malformed thing's ID.
        "401":
          description: Missing or invalid access token provided.
        "404":
          description: A non-existent entity request.
        "422":
          description: Database can't process request.
        "500":
          $ref: "#/components/responses/ServiceError"

  /things/{thingID}/share:
    post:
      summary: Shares a thing
      description: |
        Shares a specific thing that is identifier by the thing ID.
      tags:
        - Things
      parameters:
        - $ref: "#/components/parameters/ThingID"
      requestBody:
        $ref: "#/components/requestBodies/ShareThingReq"
      security:
        - bearerAuth: []
      responses:
        "200":
          description: Thing shared.
        "400":
          description: Failed due to malformed thing's ID.
        "401":
          description: Missing or invalid access token provided.
        "404":
          description: A non-existent entity request.
        "422":
          description: Database can't process request.
        "500":
          $ref: "#/components/responses/ServiceError"

  /things/{thingID}/unshare:
    post:
      summary: Unshares a thing
      description: |
        Unshares a specific thing that is identifier by the thing ID.
      tags:
        - Things
      parameters:
        - $ref: "#/components/parameters/ThingID"
      requestBody:
        $ref: "#/components/requestBodies/ShareThingReq"
      security:
        - bearerAuth: []
      responses:
        "200":
          description: Thing unshared.
        "400":
          description: Failed due to malformed thing's ID.
        "401":
          description: Missing or invalid access token provided.
        "404":
          description: A non-existent entity request.
        "422":
          description: Database can't process request.
        "500":
          $ref: "#/components/responses/ServiceError"

  /channels/{chanID}/things:
    get:
      summary: List of things connected to specified channel
      description: |
        Retrieves list of things connected to specified channel with pagination
        metadata.
      tags:
        - Things
      parameters:
        - $ref: "#/components/parameters/chanID"
        - $ref: "#/components/parameters/Offset"
        - $ref: "#/components/parameters/Limit"
        - $ref: "#/components/parameters/Connected"
      responses:
        "200":
          $ref: "#/components/responses/ThingsPageRes"
        "400":
          description: Failed due to malformed query parameters.
        "401":
          description: Missing or invalid access token provided.
        "404":
          description: A non-existent entity request.
        "422":
          description: Database can't process request.
        "500":
          $ref: "#/components/responses/ServiceError"

  /channels:
    post:
      tags:
        - Channels
      summary: Creates new channel
      description: |
        Creates new channel. User identified by the provided access token will
        be the channel's owner.
      requestBody:
        $ref: "#/components/requestBodies/ChannelCreateReq"
      security:
        - bearerAuth: []
      responses:
        "201":
          $ref: "#/components/responses/ChannelCreateRes"
        "400":
          description: Failed due to malformed JSON.
        "401":
          description: Missing or invalid access token provided.
        "409":
          description: Failed due to using an existing identity.
        "415":
          description: Missing or invalid content type.
        "500":
          $ref: "#/components/responses/ServiceError"

    get:
      summary: Lists channels.
      description: |
        Retrieves a list of channels. Due to performance concerns, data
        is retrieved in subsets. The API things must ensure that the entire
        dataset is consumed either by making subsequent requests, or by
        increasing the subset size of the initial request.
      tags:
        - Channels
      security:
        - bearerAuth: []
      parameters:
        - $ref: "#/components/parameters/Limit"
        - $ref: "#/components/parameters/Offset"
        - $ref: "#/components/parameters/Metadata"
        - $ref: "#/components/parameters/ChannelName"
        - $ref: "#/components/parameters/OwnerId"
      responses:
        "200":
          $ref: "#/components/responses/ChannelPageRes"
        "400":
          description: Failed due to malformed query parameters.
        "401":
          description: Missing or invalid access token provided.
        "404":
          description: Channel does not exist.
        "422":
          description: Database can't process request.
        "500":
          $ref: "#/components/responses/ServiceError"

  /channels/{chanID}:
    get:
      summary: Retrieves channel info.
      description: |
        Gets info on a channel specified by id.
      tags:
        - Channels
      parameters:
        - $ref: "#/components/parameters/chanID"
      security:
        - bearerAuth: []
      responses:
        "200":
          $ref: "#/components/responses/ChannelRes"
        "400":
          description: Failed due to malformed channel's ID.
        "401":
          description: Missing or invalid access token provided.
        "404":
          description: Channel does not exist.
        "422":
          description: Database can't process request.
        "500":
          $ref: "#/components/responses/ServiceError"

    put:
      summary: Updates channel data.
      description: |
        Update is performed by replacing the current resource data with values
        provided in a request payload. Note that the channel's ID will not be
        affected.
      tags:
        - Channels
      parameters:
        - $ref: "#/components/parameters/chanID"
      security:
        - bearerAuth: []
      requestBody:
        $ref: "#/components/requestBodies/ChannelUpdateReq"
      responses:
        "200":
          $ref: "#/components/responses/ChannelRes"
        "400":
          description: Failed due to malformed query parameters.
        "401":
          description: Missing or invalid access token provided.
        "404":
          description: Channel does not exist.
        "415":
          description: Missing or invalid content type.
        "500":
          $ref: "#/components/responses/ServiceError"

  /channels/{chanID}/enable:
    post:
      summary: Enables a channel
      description: |
        Enables a specific channel that is identifier by the channel ID.
      tags:
        - Channels
      parameters:
        - $ref: "#/components/parameters/chanID"
      security:
        - bearerAuth: []
      responses:
        "200":
          $ref: "#/components/responses/ChannelRes"
        "400":
          description: Failed due to malformed query parameters.
        "401":
          description: Missing or invalid access token provided.
        "404":
          description: A non-existent entity request.
        "422":
          description: Database can't process request.
        "500":
          $ref: "#/components/responses/ServiceError"

  /channels/{chanID}/disable:
    post:
      summary: Disables a channel
      description: |
        Disables a specific channel that is identifier by the channel ID.
      tags:
        - Channels
      parameters:
        - $ref: "#/components/parameters/chanID"
      security:
        - bearerAuth: []
      responses:
        "200":
          $ref: "#/components/responses/ChannelRes"
        "400":
          description: Failed due to malformed channel's ID.
        "401":
          description: Missing or invalid access token provided.
        "404":
          description: A non-existent entity request.
        "422":
          description: Database can't process request.
        "500":
          $ref: "#/components/responses/ServiceError"

  /channels/{chanID}/users/assign:
    post:
      summary: Assigns a member to a channel
      description: |
        Assigns a specific member to a channel that is identifier by the channel ID.
      tags:
        - Channels
      parameters:
        - $ref: "#/components/parameters/chanID"
      requestBody:
        $ref: "#/components/requestBodies/AssignUserReq"
      security:
        - bearerAuth: []
      responses:
        "200":
          description: Thing shared.
        "400":
          description: Failed due to malformed thing's ID.
        "401":
          description: Missing or invalid access token provided.
        "404":
          description: A non-existent entity request.
        "422":
          description: Database can't process request.
        "500":
          $ref: "#/components/responses/ServiceError"

  /channels/{chanID}/users/unassign:
    post:
      summary: Unassigns a member from a channel
      description: |
        Unassigns a specific member from a channel that is identifier by the channel ID.
      tags:
        - Channels
      parameters:
        - $ref: "#/components/parameters/chanID"
      requestBody:
        $ref: "#/components/requestBodies/AssignUserReq"
      security:
        - bearerAuth: []
      responses:
        "200":
          description: Thing unshared.
        "400":
          description: Failed due to malformed thing's ID.
        "401":
          description: Missing or invalid access token provided.
        "404":
          description: A non-existent entity request.
        "422":
          description: Database can't process request.
        "500":
          $ref: "#/components/responses/ServiceError"

  /channels/{chanID}/groups/assign:
    post:
      summary: Assigns a member to a channel
      description: |
        Assigns a specific member to a channel that is identifier by the channel ID.
      tags:
        - Channels
      parameters:
        - $ref: "#/components/parameters/chanID"
      requestBody:
        $ref: "#/components/requestBodies/AssignUsersReq"
      security:
        - bearerAuth: []
      responses:
        "200":
          description: Thing shared.
        "400":
          description: Failed due to malformed thing's ID.
        "401":
          description: Missing or invalid access token provided.
        "404":
          description: A non-existent entity request.
        "422":
          description: Database can't process request.
        "500":
          $ref: "#/components/responses/ServiceError"

  /channels/{chanID}/groups/unassign:
    post:
      summary: Unassigns a member from a channel
      description: |
        Unassigns a specific member from a channel that is identifier by the channel ID.
      tags:
        - Channels
      parameters:
        - $ref: "#/components/parameters/chanID"
      requestBody:
        $ref: "#/components/requestBodies/AssignUsersReq"
      security:
        - bearerAuth: []
      responses:
        "200":
          description: Thing unshared.
        "400":
          description: Failed due to malformed thing's ID.
        "401":
          description: Missing or invalid access token provided.
        "404":
          description: A non-existent entity request.
        "422":
          description: Database can't process request.
        "500":
          $ref: "#/components/responses/ServiceError"

  /things/{thingID}/channels:
    get:
      summary: List of channels connected to specified thing
      description: |
        Retrieves list of channels connected to specified thing with pagination
        metadata.
      tags:
        - Channels
      parameters:
        - $ref: "#/components/parameters/ThingID"
        - $ref: "#/components/parameters/Offset"
        - $ref: "#/components/parameters/Limit"
      responses:
        "200":
          $ref: "#/components/responses/ChannelPageRes"
        "400":
          description: Failed due to malformed query parameters.
        "401":
          description: Missing or invalid access token provided.
        "404":
          description: Thing does not exist.
        "422":
          description: Database can't process request.
        "500":
          $ref: "#/components/responses/ServiceError"

  /users/{memberID}/channels:
    get:
      summary: List of channels connected to specified user
      description: |
        Retrieves list of channels connected to specified user with pagination
        metadata.
      tags:
        - Channels
      parameters:
        - $ref: "#/components/parameters/MemberID"
        - $ref: "#/components/parameters/Offset"
        - $ref: "#/components/parameters/Limit"
      responses:
        "200":
          $ref: "#/components/responses/ChannelPageRes"
        "400":
          description: Failed due to malformed query parameters.
        "401":
          description: Missing or invalid access token provided.
        "404":
          description: Thing does not exist.
        "422":
          description: Database can't process request.
        "500":
          $ref: "#/components/responses/ServiceError"

  /groups/{memberID}/channels:
    get:
      summary: List of channels connected to specified group
      description: |
        Retrieves list of channels connected to specified group with pagination
        metadata.
      tags:
        - Channels
      parameters:
        - $ref: "#/components/parameters/MemberID"
        - $ref: "#/components/parameters/Offset"
        - $ref: "#/components/parameters/Limit"
      responses:
        "200":
          $ref: "#/components/responses/ChannelPageRes"
        "400":
          description: Failed due to malformed query parameters.
        "401":
          description: Missing or invalid access token provided.
        "404":
          description: Thing does not exist.
        "422":
          description: Database can't process request.
        "500":
          $ref: "#/components/responses/ServiceError"

  /connect:
    post:
      summary: Connects thing and channel.
      description: |
        Connect things specified by IDs to channels specified by IDs.
        Channel and thing are owned by user identified using the provided access token.
      tags:
        - Policies
      requestBody:
        $ref: "#/components/requestBodies/ConnCreateReq"
      responses:
        "201":
          $ref: "#/components/responses/ConnCreateRes"
        "400":
          description: Failed due to malformed JSON.
        "401":
          description: Missing or invalid access token provided.
        "404":
          description: A non-existent entity request.
        "409":
          description: Entity already exist.
        "415":
          description: Missing or invalid content type.
        "500":
          $ref: "#/components/responses/ServiceError"

  /disconnect:
    post:
      summary: Disconnect things and channels using lists of IDs.
      description: |
        Disconnect things from channels specified by lists of IDs.
        Channels and things are owned by user identified using the provided access token.
      tags:
        - Policies
      requestBody:
        $ref: "#/components/requestBodies/DisconnReq"
      responses:
        "204":
          $ref: "#/components/responses/DisconnRes"
        "400":
          description: Failed due to malformed JSON.
        "401":
          description: Missing or invalid access token provided.
        "404":
          description: A non-existent entity request.
        "415":
          description: Missing or invalid content type.
        "500":
          $ref: "#/components/responses/ServiceError"

  /channels/{chanID}/things/{thingID}/connect:
    post:
      summary: Connects a thing to a channel
      description: |
        Connects a specific thing to a channel that is identifier by the channel ID.
      tags:
        - Policies
      parameters:
        - $ref: "#/components/parameters/chanID"
        - $ref: "#/components/parameters/ThingID"
      responses:
        "200":
          description: Thing connected.
        "400":
          description: Failed due to malformed thing's ID.
        "401":
          description: Missing or invalid access token provided.
        "404":
          description: A non-existent entity request.
        "422":
          description: Database can't process request.
        "500":
          $ref: "#/components/responses/ServiceError"

  /channels/{chanID}/things/{thingID}/disconnect:
    post:
      summary: Disconnects a thing to a channel
      description: |
        Disconnects a specific thing to a channel that is identifier by the channel ID.
      tags:
        - Policies
      parameters:
        - $ref: "#/components/parameters/chanID"
        - $ref: "#/components/parameters/ThingID"
      responses:
        "200":
          description: Thing connected.
        "400":
          description: Failed due to malformed thing's ID.
        "401":
          description: Missing or invalid access token provided.
        "404":
          description: A non-existent entity request.
        "422":
          description: Database can't process request.
        "500":
          $ref: "#/components/responses/ServiceError"

  /health:
    get:
      summary: Retrieves service health check info.
      tags:
        - health
      responses:
        "200":
          $ref: "#/components/responses/HealthRes"
        "500":
          $ref: "#/components/responses/ServiceError"

components:
  schemas:
    ThingReqObj:
      type: object
      properties:
        name:
          type: string
          example: thingName
          description: Thing name.
        tags:
          type: array
          minItems: 0
          items:
            type: string
          example: ["tag1", "tag2"]
          description: Thing tags.
        credentials:
          type: object
          properties:
            identity:
              type: string
              example: "thingidentity"
              description: Thing's identity will be used as its unique identifier
            secret:
              type: string
              format: password
              example: bb7edb32-2eac-4aad-aebe-ed96fe073879
              minimum: 8
              description: Free-form account secret used for acquiring auth token(s).
        owner:
          type: string
          format: uuid
          example: bb7edb32-2eac-4aad-aebe-ed96fe073879
          description: Thing owner must be exsiting in the databse.
        metadata:
          type: object
          example: { "domain": "example.com" }
          description: Arbitrary, object-encoded thing's data.
        status:
          type: string
          description: Thing Status
          format: string
          example: enabled
      required:
        - credentials

    ChannelReqObj:
      type: object
      properties:
        name:
          type: string
          example: channelName
          description: Free-form channel name. Channel name is unique on the given hierarchy level.
        description:
          type: string
          example: long channel description
          description: Channel description, free form text.
        parent_id:
          type: string
          example: bb7edb32-2eac-4aad-aebe-ed96fe073879
          description: Id of parent channel, it must be existing channel.
        metadata:
          type: object
          example: { "domain": "example.com" }
          description: Arbitrary, object-encoded channels's data.
        status:
          type: string
          description: Channel Status
          format: string
          example: enabled
        owner_id:
          type: string
          format: uuid
          example: bb7edb32-2eac-4aad-aebe-ed96fe073879
          description: Channel owner ID must be exsiting in the databse.
      required:
        - name

    PolicyReqObj:
      type: object
      properties:
        user_ids:
          type: array
          minItems: 0
          items:
            type: string
          description: User IDs
          example:
            [
              "bb7edb32-2eac-4aad-aebe-ed96fe073879",
              "bb7edb32-2eac-4aad-aebe-ed96fe073879",
            ]
        relation:
          type: array
          minItems: 0
          items:
            type: string
          example: ["m_write", "g_add"]
          description: Policy relations.
      required:
        - user_ids
        - relation

    AssignReqObj:
      type: object
      properties:
        members:
          type: array
          minItems: 0
          items:
            type: string
          description: Members IDs
          example:
            [
              "bb7edb32-2eac-4aad-aebe-ed96fe073879",
              "bb7edb32-2eac-4aad-aebe-ed96fe073879",
            ]
        relation:
          type: string
          example: "m_write"
          description: Policy relations.
        member_kind:
          type: string
          example: "user"
          description: Member kind.
      required:
        - members
        - relation
        - member_kind

    AssignUserReqObj:
      type: object
      properties:
        users_ids:
          type: array
          minItems: 0
          items:
            type: string
          description: Users IDs
          example:
            [
              "bb7edb32-2eac-4aad-aebe-ed96fe073879",
              "bb7edb32-2eac-4aad-aebe-ed96fe073879",
            ]
        relation:
          type: string
          example: "m_write"
          description: Policy relations.
      required:
        - users_ids
        - relation

    AssignUsersReqObj:
      type: object
      properties:
        group_ids:
          type: array
          minItems: 0
          items:
            type: string
          description: Group IDs
          example:
            [
              "bb7edb32-2eac-4aad-aebe-ed96fe073879",
              "bb7edb32-2eac-4aad-aebe-ed96fe073879",
            ]
      required:
        - group_ids

    Thing:
      type: object
      properties:
        id:
          type: string
          format: uuid
          example: bb7edb32-2eac-4aad-aebe-ed96fe073879
          description: Thing unique identifier.
        name:
          type: string
          example: thingName
          description: Thing name.
        tags:
          type: array
          minItems: 0
          items:
            type: string
          example: ["tag1", "tag2"]
          description: Thing tags.
        owner:
          type: string
          format: uuid
          example: bb7edb32-2eac-4aad-aebe-ed96fe073879
          description: Thing owner identifier.
        credentials:
          type: object
          properties:
            identity:
              type: string
              example: thingidentity
              description: Thing Identity for example email address.
            secret:
              type: string
              example: bb7edb32-2eac-4aad-aebe-ed96fe073879
              description: Thing secret password.
        metadata:
          type: object
          example: { "domain": "example.com" }
          description: Arbitrary, object-encoded thing's data.
        status:
          type: string
          description: Thing Status
          format: string
          example: enabled
        created_at:
          type: string
          format: date-time
          example: "2019-11-26 13:31:52"
          description: Time when the channel was created.
        updated_at:
          type: string
          format: date-time
          example: "2019-11-26 13:31:52"
          description: Time when the channel was created.
      xml:
        name: thing

    ThingWithEmptySecret:
      type: object
      properties:
        id:
          type: string
          format: uuid
          example: bb7edb32-2eac-4aad-aebe-ed96fe073879
          description: Thing unique identifier.
        name:
          type: string
          example: thingName
          description: Thing name.
        tags:
          type: array
          minItems: 0
          items:
            type: string
          example: ["tag1", "tag2"]
          description: Thing tags.
        owner:
          type: string
          format: uuid
          example: bb7edb32-2eac-4aad-aebe-ed96fe073879
          description: Thing owner identifier.
        credentials:
          type: object
          properties:
            identity:
              type: string
              example: thingidentity
              description: Thing Identity for example email address.
            secret:
              type: string
              example: ""
              description: Thing secret password.
        metadata:
          type: object
          example: { "domain": "example.com" }
          description: Arbitrary, object-encoded thing's data.
        status:
          type: string
          description: Thing Status
          format: string
          example: enabled
        created_at:
          type: string
          format: date-time
          example: "2019-11-26 13:31:52"
          description: Time when the channel was created.
        updated_at:
          type: string
          format: date-time
          example: "2019-11-26 13:31:52"
          description: Time when the channel was created.
      xml:
        name: thing

    Channel:
      type: object
      properties:
        id:
          type: string
          format: uuid
          example: bb7edb32-2eac-4aad-aebe-ed96fe073879
          description: Unique channel identifier generated by the service.
        name:
          type: string
          example: channelName
          description: Free-form channel name. Channel name is unique on the given hierarchy level.
        owner_id:
          type: string
          format: uuid
          example: bb7edb32-2eac-4aad-aebe-ed96fe073879
          description: Channel owner identifier of thing that created the channel..
        parent_id:
          type: string
          format: uuid
          example: bb7edb32-2eac-4aad-aebe-ed96fe073879
          description: Channel parent identifier.
        description:
          type: string
          example: long channel description
          description: Channel description, free form text.
        metadata:
          type: object
          example: { "role": "general" }
          description: Arbitrary, object-encoded channels's data.
        path:
          type: string
          example: bb7edb32-2eac-4aad-aebe-ed96fe073879.bb7edb32-2eac-4aad-aebe-ed96fe073879
          description: Hierarchy path, concatenated ids of channel ancestors.
        level:
          type: integer
          description: Level in hierarchy, distance from the root channel.
          format: int32
          example: 2
          maximum: 5
        created_at:
          type: string
          format: date-time
          example: "2019-11-26 13:31:52"
          description: Datetime when the channel was created.
        updated_at:
          type: string
          format: date-time
          example: "2019-11-26 13:31:52"
          description: Datetime when the channel was created.
        status:
          type: string
          description: Channel Status
          format: string
          example: enabled
      xml:
        name: channel

    Policy:
      type: object
      properties:
        owner_id:
          type: string
          format: uuid
          example: bb7edb32-2eac-4aad-aebe-ed96fe073879
          description: Policy owner identifier.
        subject:
          type: string
          format: uuid
          example: bb7edb32-2eac-4aad-aebe-ed96fe073879
          description: Policy subject identifier.
        object:
          type: string
          format: uuid
          example: bb7edb32-2eac-4aad-aebe-ed96fe073879
          description: Policy object identifier.
        actions:
          type: array
          minItems: 0
          items:
            type: string
          example: ["m_write", "g_add"]
          description: Policy actions.
        created_at:
          type: string
          format: date-time
          example: "2019-11-26 13:31:52"
          description: Time when the policy was created.
        updated_at:
          type: string
          format: date-time
          example: "2019-11-26 13:31:52"
          description: Time when the policy was updated.
      xml:
        name: policy

    ThingsPage:
      type: object
      properties:
        things:
          type: array
          minItems: 0
          uniqueItems: true
          items:
            $ref: "#/components/schemas/ThingWithEmptySecret"
        total:
          type: integer
          example: 1
          description: Total number of items.
        offset:
          type: integer
          description: Number of items to skip during retrieval.
        limit:
          type: integer
          example: 10
          description: Maximum number of items to return in one page.
      required:
        - things
        - total
        - offset

    ChannelsPage:
      type: object
      properties:
        channels:
          type: array
          minItems: 0
          uniqueItems: true
          items:
            $ref: "#/components/schemas/Channel"
        total:
          type: integer
          example: 1
          description: Total number of items.
        offset:
          type: integer
          description: Number of items to skip during retrieval.
        limit:
          type: integer
          example: 10
          description: Maximum number of items to return in one page.
      required:
        - channels
        - total
        - level

    PoliciesPage:
      type: object
      properties:
        policies:
          type: array
          minItems: 0
          uniqueItems: true
          items:
            $ref: "#/components/schemas/Policy"
        total:
          type: integer
          example: 1
          description: Total number of items.
        offset:
          type: integer
          description: Number of items to skip during retrieval.
        limit:
          type: integer
          example: 10
          description: Maximum number of items to return in one page.
      required:
        - policies
        - total
        - offset

    ThingUpdate:
      type: object
      properties:
        name:
          type: string
          example: thingName
          description: Thing name.
        metadata:
          type: object
          example: { "role": "general" }
          description: Arbitrary, object-encoded thing's data.
      required:
        - name
        - metadata

    ThingTags:
      type: object
      properties:
        tags:
          type: array
          example: ["tag1", "tag2"]
          description: Thing tags.
          minItems: 0
          uniqueItems: true
          items:
            type: string

    ThingSecret:
      type: object
      properties:
        secret:
          type: string
          example: bb7edb32-2eac-4aad-aebe-ed96fe073879
          description: New thing secret.
      required:
        - secret

    ThingOwner:
      type: object
      properties:
        owner:
          type: string
          example: bb7edb32-2eac-4aad-aebe-ed96fe073879
          description: Thing owner for example email address.
      required:
        - owner

    ChannelUpdate:
      type: object
      properties:
        name:
          type: string
          example: channelName
          description: Free-form channel name. Channel name is unique on the given hierarchy level.
        description:
          type: string
          example: long description but not too long
          description: Channel description, free form text.
        metadata:
          type: object
          example: { "role": "general" }
          description: Arbitrary, object-encoded channels's data.
      required:
        - name
        - metadata
        - description

    ConnectionReqSchema:
      type: object
      properties:
        objects:
          type: array
          description: Channel IDs.
          items:
            example: bb7edb32-2eac-4aad-aebe-ed96fe073879
        subjects:
          type: array
          description: Thing IDs
          items:
            example: bb7edb32-2eac-4aad-aebe-ed96fe073879
        permission:
          type: array
          description: policy actions
          items:
            example: publish

    DisConnectionReqSchema:
      type: object
      properties:
        objects:
          type: array
          description: Channel IDs.
          items:
            example: bb7edb32-2eac-4aad-aebe-ed96fe073879
        subjects:
          type: array
          description: Thing IDs
          items:
            example: bb7edb32-2eac-4aad-aebe-ed96fe073879

    Error:
      type: object
      properties:
        error:
          type: string
          description: Error message
      example: { "error": "malformed entity specification" }

    HealthRes:
      type: object
      properties:
        status:
          type: string
          description: Service status.
          enum:
            - pass
        version:
          type: string
          description: Service version.
          example: 0.14.0
        commit:
          type: string
          description: Service commit hash.
          example: 7d6f4dc4f7f0c1fa3dc24eddfb18bb5073ff4f62
        description:
          type: string
          description: Service description.
          example: things service
        build_time:
          type: string
          description: Service build time.
          example: 1970-01-01_00:00:00

  parameters:
    ThingID:
      name: thingID
      description: Unique thing identifier.
      in: path
      schema:
        type: string
        format: uuid
      required: true
      example: bb7edb32-2eac-4aad-aebe-ed96fe073879

    MemberID:
      name: memberID
      description: Unique member identifier.
      in: path
      schema:
        type: string
        format: uuid
      required: true
      example: bb7edb32-2eac-4aad-aebe-ed96fe073879

    ThingName:
      name: name
      description: Thing's name.
      in: query
      schema:
        type: string
      required: false
      example: "thingName"

    ThingIdentity:
      name: identity
      description: Thing's identity.
      in: query
      schema:
        type: string
      required: false
      example: "admin@example.com"

    Owner:
      name: owner_id
      description: Thing's owner.
      in: query
      schema:
        type: string
        format: uuid
      required: false
      example: bb7edb32-2eac-4aad-aebe-ed96fe073879

    ThingOwner:
      name: owner
      description: Unique owner identifier for a thing.
      in: query
      schema:
        type: string
        format: uuid
      required: false
      example: bb7edb32-2eac-4aad-aebe-ed96fe073879

    Status:
      name: status
      description: Thing account status.
      in: query
      schema:
        type: string
        default: enabled
      required: false
      example: enabled

    Tags:
      name: tags
      description: Thing tags.
      in: query
      schema:
        type: array
        minItems: 0
        uniqueItems: true
        items:
          type: string
      required: false
      example: ["yello", "orange"]

    ChannelName:
      name: name
      description: Channel's name.
      in: query
      schema:
        type: string
      required: false
      example: "channelName"

    ChannelDescription:
      name: name
      description: Channel's description.
      in: query
      schema:
        type: string
      required: false
      example: "channel description"

    chanID:
      name: chanID
      description: Unique channel identifier.
      in: path
      schema:
        type: string
        format: uuid
      required: true
      example: bb7edb32-2eac-4aad-aebe-ed96fe073879

    ParentId:
      name: parentId
      description: Unique parent identifier for a channel.
      in: query
      schema:
        type: string
        format: uuid
      required: false
      example: bb7edb32-2eac-4aad-aebe-ed96fe073879

    Level:
      name: level
      description: Level of hierarchy up to which to retrieve channels from given channel id.
      in: query
      schema:
        type: integer
        minimum: 1
        maximum: 5
      required: false

    Tree:
      name: tree
      description: Specify type of response, JSON array or tree.
      in: query
      required: false
      schema:
        type: boolean
        default: false

    OwnerId:
      name: ownerId
      description: Unique owner identifier for a channel.
      in: query
      schema:
        type: string
        format: uuid
      required: false
      example: bb7edb32-2eac-4aad-aebe-ed96fe073879

    Metadata:
      name: metadata
      description: Metadata filter. Filtering is performed matching the parameter with metadata on top level. Parameter is json.
      in: query
      schema:
        type: string
        minimum: 0
      required: false

    Limit:
      name: limit
      description: Size of the subset to retrieve.
      in: query
      schema:
        type: integer
        default: 10
        maximum: 100
        minimum: 1
      required: false
      example: "100"

    Offset:
      name: offset
      description: Number of items to skip during retrieval.
      in: query
      schema:
        type: integer
        default: 0
        minimum: 0
      required: false
      example: "0"

    Connected:
      name: connected
      description: Connection state of the subset to retrieve.
      in: query
      schema:
        type: boolean
        default: true
      required: false

  requestBodies:
    ThingCreateReq:
      description: JSON-formatted document describing the new thing to be registered
      required: true
      content:
        application/json:
          schema:
            $ref: "#/components/schemas/ThingReqObj"

    ThingUpdateReq:
      description: JSON-formated document describing the metadata and name of thing to be update
      required: true
      content:
        application/json:
          schema:
            $ref: "#/components/schemas/ThingUpdate"

    ThingUpdateTagsReq:
      description: JSON-formated document describing the tags of thing to be update
      required: true
      content:
        application/json:
          schema:
            $ref: "#/components/schemas/ThingTags"

    ThingUpdateSecretReq:
      description: Secret change data. Thing can change its secret.
      required: true
      content:
        application/json:
          schema:
            $ref: "#/components/schemas/ThingSecret"

    ThingUpdateOwnerReq:
      description: JSON-formated document describing the owner of thing to be update
      required: true
      content:
        application/json:
          schema:
            $ref: "#/components/schemas/ThingOwner"

    ShareThingReq:
      description: JSON-formated document describing the policy related to sharing things
      required: true
      content:
        application/json:
          schema:
            $ref: "#/components/schemas/PolicyReqObj"

    AssignReq:
      description: JSON-formated document describing the policy related to assigning members to a channel
      required: true
      content:
        application/json:
          schema:
            $ref: "#/components/schemas/AssignReqObj"

    AssignUserReq:
      description: JSON-formated document describing the policy related to assigning members to a channel
      required: true
      content:
        application/json:
          schema:
            $ref: "#/components/schemas/AssignUserReqObj"

    AssignUsersReq:
      description: JSON-formated document describing the policy related to assigning members to a channel
      required: true
      content:
        application/json:
          schema:
            $ref: "#/components/schemas/AssignUsersReqObj"

    ChannelCreateReq:
      description: JSON-formatted document describing the new channel to be registered
      required: true
      content:
        application/json:
          schema:
            $ref: "#/components/schemas/ChannelReqObj"

    ChannelUpdateReq:
      description: JSON-formated document describing the metadata and name of channel to be update
      required: true
      content:
        application/json:
          schema:
            $ref: "#/components/schemas/ChannelUpdate"

    ThingsCreateReq:
      description: JSON-formatted document describing the new things.
      required: true
      content:
        application/json:
          schema:
            type: array
            items:
              $ref: "#/components/schemas/ThingReqObj"

    ConnCreateReq:
      description: JSON-formatted document describing the new connection.
      required: true
      content:
        application/json:
          schema:
            $ref: "#/components/schemas/ConnectionReqSchema"

    DisconnReq:
      description: JSON-formatted document describing the entities for disconnection.
      required: true
      content:
        application/json:
          schema:
            $ref: "#/components/schemas/DisConnectionReqSchema"

  responses:
    ThingCreateRes:
      description: Registered new thing.
      headers:
        Location:
          schema:
            type: string
            format: url
          description: Registered thing relative URL in the format `/things/<thing_id>`
      content:
        application/json:
          schema:
            $ref: "#/components/schemas/Thing"

    ThingRes:
      description: Data retrieved.
      content:
        application/json:
          schema:
            $ref: "#/components/schemas/Thing"

    ThingPageRes:
      description: Data retrieved.
      content:
        application/json:
          schema:
            $ref: "#/components/schemas/ThingsPage"

    ThingsPageRes:
      description: Data retrieved.
      content:
        application/json:
          schema:
            $ref: "#/components/schemas/ThingsPage"

    ChannelCreateRes:
      description: Registered new channel.
      headers:
        Location:
          schema:
            type: string
            format: url
          description: Registered channel relative URL in the format `/channels/<channel_id>`
      content:
        application/json:
          schema:
            $ref: "#/components/schemas/Channel"

    ChannelRes:
      description: Data retrieved.
      content:
        application/json:
          schema:
            $ref: "#/components/schemas/Channel"

    ChannelPageRes:
      description: Data retrieved.
      content:
        application/json:
          schema:
            $ref: "#/components/schemas/ChannelsPage"

    ConnCreateRes:
      description: Thing registered.
      content:
        application/json:
          schema:
            $ref: "#/components/schemas/PoliciesPage"

    DisconnRes:
      description: Things disconnected.

    HealthRes:
      description: Service Health Check.
      content:
        application/health+json:
          schema:
            $ref: "#/components/schemas/HealthRes"

    ServiceError:
      description: Unexpected server-side error occurred.
      content:
        application/json:
          schema:
            $ref: "#/components/schemas/Error"

  securitySchemes:
    bearerAuth:
      type: http
      scheme: bearer
      bearerFormat: JWT
      description: |
        * Thing access: "Authorization: Bearer <user_access_token>"

security:
  - bearerAuth: []
