swagger: '2.0'
info:
  title: IoT File API
  description: The IoT File API enables storing and retrieving files for asset (entity) instances.
  version: "3.2.4"
  x-visibility: "external"

schemes:
  - https

basePath: /api/iotfile/v3

securityDefinitions:
  fileservice:
    type: oauth2
    flow: accessCode
    authorizationUrl: https://oauth.simple.api/authorization
    tokenUrl: https://oauth.simple.api/token
    scopes:
      iot.fil.r: read files
      iot.fil.w: write files
      iot.fil.d: delete files

paths:
  /files/{entityId}/{filepath}:
    put:
      summary: write a file
      tags:
        - File Service
      description: |
        Create or update a file for the specified asset (entity) and path, with the provided content.
      operationId: putFile
      security:
        - fileservice:
            - iot.fil.w
      parameters:
        - name: file
          in: body
          description: the file attached content
          required: true
          schema:
            type: string
            format: binary
        - name: entityId
          in: path
          description: unique identifier of the asset (entity)
          required: true
          type: string
          minLength: 32
          maxLength: 32
          pattern: "[a-f0-9]{32}"
        - name: filepath
          in: path
          description: url path of the file along with filename
          required: true
          type: string
        - name: part
          in: query
          description: Part number to upload
          required: false
          type: integer
          minimum: 1
          maximum: 1000
        - name: upload
          in: query
          type: string
          enum: [start, complete, abort]
          description: upload status to start, complete, and abort multi-part uploads
          required: false
        - name: If-Match
          in: header
          description: etag of the latest version for optimistic locking
          required: false
          type: integer
        - name: timestamp
          in: header
          description: file timestamp
          required: false
          type: string
          format: date-time
        - name: description
          in: header
          description: description of the file
          required: false
          type: string
          minLength: 1
          maxLength: 100
        - name: type
          in: header
          description: type of the file
          required: false
          type: string
          minLength: 1
          maxLength: 191
      consumes:
            - application/octet-stream
      responses:
        '201':
          description: created
          headers:
            Location:
              type: string
              description: URL of the file
            etag:
              type: integer
              description: etag of the file
        '204':
          description: updated
          headers:
            Location:
              type: string
              description: URL of the file
            etag:
              type: integer
              description: etag of the file
        '400':
          description: bad request
          schema:
            $ref: '#/definitions/badrequest'
        '401':
          description: unauthorized
          schema:
            $ref: '#/definitions/unauthorized'
        '404':
          description: not found
          schema:
            $ref: '#/definitions/notfound'
        '409':
          description: conflict
          schema:
            $ref: '#/definitions/conflict'
        default:
          description: Unexpected error
          schema:
            $ref: '#/definitions/error'
    get:
        summary: read a file
        tags:
          - File Service
        description: Read a file for the specified asset (entity) and path
        operationId: getFile
        security:
          - fileservice:
            - iot.fil.r
        produces:
        - application/octet-stream
        - application/json
        parameters:
        - name: entityId
          in: path
          description: Id to instance of asset (entity)
          required: true
          type: string
          minLength: 32
          maxLength: 32
          pattern: "[a-f0-9]{32}"
        - name: filepath
          in: path
          description: path of the file along with filename
          required: true
          type: string
        - name: If-None-Match
          in: header
          description: etag of the latest version (not supported in this release)
          required: false
          type: integer
        - name: range
          in: header
          description: Part of a file to return in Bytes, eg bytes=200-600
          required: false
          type: string
          minLength: 1
          maxLength: 32
        responses:
          '200':
            description: file content
            headers:
              timestamp:
                type: string
              description:
                type: string
                description: description of the file
              etag:
                type: integer
                description: etag of the file
            schema:
              type: string
              format: binary
          '206':
            description: Partial Content of the file
            schema:
              type: string
              format: binary
          '304':
            description: not modfied
            schema:
              $ref: '#/definitions/notmodified'
          '401':
            description: unauthorized
            schema:
              $ref: '#/definitions/unauthorized'
          '404':
            description: not found
            schema:
              $ref: '#/definitions/notfound'
          '416':
            description: Range Not Satisfiable
            schema:
              $ref: '#/definitions/rangenotsatisfiable'
          default:
            description: unexpected error
            schema:
              $ref: '#/definitions/error'
    delete:
      summary: delete a file
      tags:
        - File Service
      description: Delete a file for the specified asset (entity) and path.
      operationId: deleteFile
      security:
        - fileservice:
            - iot.fil.d
      parameters:
        - name: entityId
          in: path
          description: unique identifier of the asset (entity)
          required: true
          type: string
          minLength: 32
          maxLength: 32
          pattern: "[a-f0-9]{32}"
        - name: filepath
          in: path
          description: unique identifier of the file
          required: true
          type: string
          minLength: 1
          maxLength: 100
      responses:
        '204':
          description: deleted
        '401':
          description: unauthorized
          schema:
            $ref: '#/definitions/unauthorized'
        '404':
          description: not found
          schema:
            $ref: '#/definitions/notfound'
        default:
          description: unexpected error
          schema:
            $ref: '#/definitions/error'
  /files/{entityId}:
    get:
      tags:
      - File Service
      summary: search files
      description: Search files for the specified asset (entity).
      operationId: searchFiles
      security:
        - fileservice:
          - iot.fil.r
      produces:
      - application/json
      parameters:
      - name: entityId
        in: path
        description: asset (entity) instance id
        required: true
        type: string
        minLength: 32
        maxLength: 32
        pattern: "[a-f0-9]{32}"
      - name: offset
        in: query
        description: number of files to skip
        required: false
        type: number
        format: int32
        minimum: 0
      - name: limit
        in: query
        description: maximum number of files to return (max 200)
        required: false
        type: integer
        minimum: 1
        maximum: 200
      - name: count
        in: query
        description: return total number of matching files
        required: false
        type: boolean
      - name: order
        in: query
        description: sort based on supported fields - see order syntax for more details
          (name, path, type, size, timestamp, created, updated)
        required: false
        type: string
      - name: filter
        in: query
        description: filter based on supported fields - see filter syntax for more details
          (name, path, type, size, timestamp, created, updated)
        required: false
        type: string
      responses:
        '200':
          description: successful operation
          headers:
            X-Total-Count:
              type: integer
              description: number of files matching the filter criteria
          schema:
            type: array
            items:
              $ref: "#/definitions/file"
        '400':
          description: bad request
          schema:
            $ref: '#/definitions/badrequest'
        '401':
          description: unauthorized
          schema:
            $ref: '#/definitions/unauthorized'
        default:
          description: unexpected error
          schema:
            $ref: '#/definitions/error'
  /fileslist/{entityId}/{filepath}:
    get:
        summary: list multi part uploads
        tags:
          - File Service
        description: List multi part uploads
        operationId: getFileList
        security:
          - fileservice:
            - iot.fil.r
        produces:
        - application/json
        parameters:
        - name: entityId
          in: path
          description: Id to instance of asset (entity)
          required: true
          type: string
          minLength: 32
          maxLength: 32
          pattern: "[a-f0-9]{32}"
        - name: filepath
          in: path
          description: path of the file
          required: true
          type: string
        responses:
          '200':
            description: multi part list
            schema:
              type: array
              items:
                $ref: "#/definitions/fileslist"
          '400':
            description: bad request
            schema:
              $ref: '#/definitions/badrequest'
          '401':
            description: unauthorized
            schema:
              $ref: '#/definitions/unauthorized'
          '404':
            description: not found
            schema:
              $ref: '#/definitions/notfound'
          default:
            description: unexpected error
            schema:
              $ref: '#/definitions/error'
  /files/deleteJobs:
    post:
        summary: initiate job to delete all files for the given asset identifier
        tags:
          - File Bulk Delete Jobs
        description: |
          1. Delete all the files for a given asset identifier
          2. Files created or updated before the job submission are considered for delete operation.
          3. Supports single asset
          4. There can be only one job with status "IN_PROGRESS" for a given asset. HTTP Error 409 (duplicate request) will be thrown if more jobs are submitted for the same asset with IN_PROGRESS status.
          5. <i>timeFrom</i> and <i>timeTo</i> window should not exceed 90 days.
          6. If time range is provided, files are deleted whose updated time falls in between <i>timeFrom</i> and <i>timeTo</i> range. Time range is granular to second with format "yyyy-MM-dd'T'HH:mm:ss.SSS" => Time fields i.e. <i>timeFrom</i> & <i>timeTo</i> supports second level granularity with format "yyyy-MM-dd'T'HH:mm:ss.SSS"
          7. If time range is not provided, all the files created before 90 days of submission of delete job for given asset will be deleted.
          <br/>
          <b>**Using <i>timeFrom</i> and <i>timeTo</i> fields</b>
          - <i>timeFrom</i> values should be less than (<) <i>timeTo</i> values and <i>timeTo</i> values should be less than equal to (<=) deleteJob submission time
          - If only <i>timeFrom</i> is provided, files created within 90 days after that time are considered in delete job.
          - If only <i>timeTo</i> is provided, all the files created on or before 90 days of that time are considered for deletion.
          - If <i>timeFrom</i> and <i>timeTo</i> is provided, then files created between the two are considered for deletion.
          - <i>timeFrom</i> and <i>timeTo</i> are inclusive
        operationId: submitDeleteJob
        security:
          - fileservice:
            - iot.fil.d
        produces:
        - application/json
        parameters:
        - name: bulk delete request
          in: body
          description: bulk delete request
          required: true
          schema:
            $ref: '#/definitions/bulkDeleteRequest'
        responses:
          '202':
            description: bulk delete request has been accepted for processing
            schema:
              $ref: "#/definitions/bulkDeleteResponse"
          '400':
            description: |
              Bad request. Possible errors:
              <br>
              <table>
                <colgroup>
                  <col span="1" style="width: 30%;">
                  <col span="1" style="width: 70%;">
                </colgroup>
                <tr>
                  <th align="left">Code Suffix</th>
                  <th align="left">Message (parametrized)</th>
                </tr>
                <tr>
                  <td>assetIdNullOrEmpty</td>
                  <td>Asset id cannot be null or empty.</td>
                </tr>
                <tr>
                  <td>invalidTimeRange</td>
                  <td>timeFrom cannot be graeter than timeTo parameter</td>
                </tr>
                <tr>
                  <td>timeRangeExceeded</td>
                  <td>Time range greater than 90 days is not allowed</td>
                </tr>
                <tr>
                  <td>futureDateNowAllowed</td>
                  <td>timeFrom and timeTo parameter cannot be greater than current time.</td>
                </tr>
              </table>
            schema:
              $ref: '#/definitions/iotFileError'
          '409':
            description: |
              <b>duplicate request</b>: Request is already submitted for asset id
            schema:
              $ref: '#/definitions/iotFileError'
          '401':
            description: |
              <b>unauthorized</b>: Not Authorized to perform this action
            schema:
              $ref: '#/definitions/iotFileError'
          '429':
            description: |
              <b>TooManyRequests</b>: Too Many Requests
            schema:
              $ref: '#/definitions/iotFileError'
    get:
        summary: get all bulk delete jobs
        tags:
          - File Bulk Delete Jobs
        description: get all bulk delete jobs submitted by tenant
        operationId: getDeleteJobs
        security:
          - fileservice:
            - iot.fil.d
        produces:
        - application/json
        responses:
          '200':
            description: |
              return all bulk delete jobs submitted by the tenant
              1. <b>id</b>: Job Id created when bulk delete job is accepted
              2. <b>timestamp</b>: Timestamp when the job was created
              3. <b>status</b>: current status of the job. Possible values can be <br><b>[IN_PROGRESS, COMPLETED_WITH_ERRORS, COMPLETED, FAILED]</b>
            schema:
              $ref: "#/definitions/deleteJobsResponse"
          '401':
            description: |
              <b>unauthorized</b>: Not Authorized to perform this action
            schema:
              $ref: '#/definitions/iotFileError'
          '429':
            description: |
              <b>TooManyRequests</b>: Too Many Requests
            schema:
              $ref: '#/definitions/iotFileError'
  /files/deleteJobs/{id}:
    get:
        summary: get the job status of bulk delete operation
        tags:
          - File Bulk Delete Jobs
        description: |
          1. Fetch the status of bulk delete jobs
          2. timeFrom and timeTo will be part of response if provided in request body while submitting the job.
          3. Status is provide for each asset
          4. Total files to be deleted is mapped against filesToBeDeleted
          5. Total files deleted successfully is mapped against filesDeleted
          6. Files in progress and failed are mapped against filesRemaining.
          7. Files in progress and failed can be differentiated by status.i.e, if status is IN_PROGRESS and filesRemaining is not zero then deletion is in progress for those files and if status is FAILED and filesRemaining in not zero that deletion if failed for those files.
          8. error field will be part of response only if there is some error while deleting the files.
          9. If path is not provided in delete jobs request then path value is considered as root by default and return value is going to be '/'.
        operationId: getDeleteJobStatus
        security:
          - fileservice:
            - iot.fil.d
        produces:
        - application/json
        parameters:
        - name: id
          in: path
          description: Job Id of bulk delete operation
          required: true
          type: string
          minLength: 32
          maxLength: 32
          pattern: "[a-f0-9]{32}"
        responses:
          '200':
            description: |
              return bulk delete job by job id submitted by the tenant
              1. <b>id</B>: Job Id created when bulk delete job is accepted
              2. <b>timestamp</b>: Timestamp when the job was created
              3. <b>status</b>: current status of the job. Possible values can be<br><b>[IN_PROGRESS, COMPLETED_WITH_ERRORS, COMPLETED, FAILED]</b>
            schema:
              $ref: "#/definitions/bulkDeleteJobResponse"
          '404':
            description: |
              <b>id not found</b>: specified JobId not found
            schema:
              $ref: '#/definitions/iotFileError'
          '401':
            description: |
              <b>unauthorized</b>: Not Authorized to perform this action
            schema:
              $ref: '#/definitions/iotFileError'
          '429':
            description: |
              <b>TooManyRequests</b>: Too Many Requests
            schema:
              $ref: '#/definitions/iotFileError'
definitions:
  unauthorized:
    type: object
    properties:
      id:
        type: string
        format: uuid
      message:
        type: string
        example: Not authorized to access this resource.
  badrequest:
    type: object
    properties:
      id:
        type: string
        format: uuid
      message:
        type: string
        example: The request is not valid.
  rangenotsatisfiable:
    type: object
    properties:
      id:
        type: string
        format: uuid
      message:
        type: string
        example: Requested range not satisfiable
  notmodified:
    type: object
    properties:
      id:
        type: string
        format: uuid
      message:
        type: string
        example: Resource not modified.
  notfound:
    type: object
    properties:
      id:
        type: string
        format: uuid
      message:
        type: string
        example: Resource not found.
  conflict:
    type: object
    properties:
      id:
        type: string
        format: uuid
      message:
        type: string
        example: A newer resource version is available.

  error:
    type: object
    properties:
      id:
        type: string
        format: uuid
      message:
        type: string
  file:
    type: object
    properties:
      name:
        type: string
        example: filename
      path:
        type: string
        example: directory1
      type:
        type: string
        example: image
      size:
        type: integer
        format: int64
        example: 1048576
      timestamp:
        type: string
        format: date-time
        example: "2017-10-01T00:00:00.001Z"
      created:
        type: string
        format: date-time
        example: "2017-10-01T00:00:00.001Z"
      updated:
        type: string
        format: date-time
        example: "2017-10-01T00:00:00.001Z"
      createdBy:
        type: string
        example: user ID
      updatedBy:
        type: string
        example: user ID
      description:
        type: string
        example: some description
      etag:
        type: integer
        example: 1

  fileslist:
    type: object
    properties:
      objectKey:
        type: string
        example: aznfriot/fdf4cc6a51e0411389020dcf8a9936c5/xyz1
      partNo:
        type: integer
        example: 1
      created:
        type: string
        format: date-time
        example: "2017-10-01T00:00:00.001Z"
  bulkDeleteRequest:
    type: object
    properties:
      assets:
        $ref: "#/definitions/bulkDeleteAssetsArray"
  bulkDeleteAssetsArray:
    type: array
    minItems: 1
    maxItems: 1
    items:
      $ref: '#/definitions/bulkDeleteAsset'
  bulkDeleteAsset:
    type: object
    properties:
      id:
        type: string
        description: 'Unique identifier for asset instance'
        minLength: 32
        maxLength: 32
        pattern: "[0-9a-f]+"
        example: 089336872ce342aba1a847f53d515dc7
      timeFrom:
        type: string
        description: |
          files created after this time are considered for deletion, If not provided, all the files created before submittion of job get deleted.
          UTC aligned date-time with ISO date format is supported.
          "2020-03-01Z"
          "2020-03-01T09Z"
          "2020-03-01T09:12Z"
          "2020-03-01T09:12:28Z"
          "2020-03-01T09:12:28.110Z"
        format: date-time
        example: "2020-03-01T09:12:28.110Z"
      timeTo:
        type: string
        description: |
          files created before this time are considered for deletion, If not provided, all the files created before submittion of job get deleted. UTC aligned date-time with ISO date format is supported.
          UTC aligned date-time with ISO date format is supported.
          "2020-06-01Z"
          "2020-06-01T09Z"
          "2020-06-01T09:12Z"
          "2020-06-01T09:12:28Z"
          "2020-06-01T09:12:28.110Z"
        format: date-time
        example: "2020-06-01T09:12:28.110Z"
    required:
      - id
  bulkDeleteResponse:
    type: object
    properties:
      id:
        type: string
        description: unique Identifier for the delete job
        example: a87d8d68-9d6d-42f8-9eb9-8899fa90bb3f
      timestamp:
        type: string
        description: time when the delete job submitted
        format: date-time
        example: "2020-06-08T09:12:28Z"
      status:
        type: string
        description: overall status of delete job
        enum: [IN_PROGRESS, COMPLETED_WITH_ERRORS, COMPLETED, FAILED]
    required:
    - id
    - timestamp
    - status
  deleteJobsResponse:
    type: object
    properties:
      deleteJobs:
        $ref: '#/definitions/bulkDeleteResponseArray'
  bulkDeleteResponseArray:
    type: array
    items:
      $ref: "#/definitions/bulkDeleteResponse"
  iotFileError:
    type: object
    properties:
      errors:
        type: array
        items:
          $ref: '#/definitions/errorBody'
  errorBody:
    type: object
    properties:
      code:
        type: string
        example: mdsp.iot.iotfile.error
      logref:
        type: string
        example: 22f316b4-81c6-4658-aad1-96d2dae494a3
      message:
        type: string
        example: error message
  bulkDeleteJobResponse:
    type: object
    properties:
      id:
        type: string
        description: unique Identifier for delete job
        example: a87d8d68-9d6d-42f8-9eb9-8899fa90bb3f
      timestamp:
        type: string
        description: time when the delete job submitted
        format: date-time
        example: "2020-06-08T09:12:28Z"
      status:
        type: string
        description: overall status of the job
        enum: [COMPLETED_WITH_ERRORS, IN_PROGRESS, COMPLETED, FAILED]
      assets:
        type: array
        minItems: 1
        maxItems: 1
        items:
          $ref: '#/definitions/assetStatus'
    required:
     - id
     - timestamp
     - status
     - assets
  assetStatus:
    type: object
    properties:
      id:
        type: string
        description: asset id
        example: 089336872ce342aba1a847f53d515dc7
      path:
        type: string
        description: path from which the files are getting deleted. Default value is '/' considered as root path.
        default: /
        example: /
      timeFrom:
        type: string
        description: files created after this time are considered for deletion
        format: date-time
        example: "2020-03-01T09:12:28.110Z"
      timeTo:
        type: string
        description: files created before this time are considered for deletion
        format: date-time
        example: "2020-06-01T09:12:28.110Z"
      status:
        type: string
        description: status of file deletion for this asset id
        enum: [FAILED, COMPLETED_WITH_ERRORS, COMPLETED, IN_PROGRESS]
      filesToBeDeleted:
        type: integer
        description: total number of files to be deleted
        example: 500
      filesDeleted:
        type: integer
        description: total files delete
        example: 400
      filesRemaining:
        type: integer
        description: total files remaining for deletion due to either the job is still in progress or job failed due to some error
        example: 100
      error:
        type: string
        description: error due to which file deletion failed for this asset id. if files deletion is successful then this field will be null.
        example: "Something went wrong while deleting some files"
    required:
      - id
      - path
      - status
      - filesToBeDeleted
      - filesDeleted
      - filesRemaining

