openapi: 3.0.0
info:
  title: Recordings
  description: >-
    This API exposes a set of functions to interact with completed recordings
  version: 2025.Winter.1
servers:
  - url: 'http://{host}/fw/Apps/Recorder/WebAPI/Recordings'
    description: UCX Suite server
    variables:
      host:
        default: localhost
        description: The UCX Suite server hostname or IP address
security:
  - basic: []
paths:
  /:
    get:
      summary: Returns a collection of recordings
      tags: [Recordings]
      security: [basic: []]
      parameters:
        - name: page
          description: The 0-based page index you want to be returned
          in: query
          schema:
            type: integer
            example: 2
        - name: pageSize
          description: >
            Number of records in a single page.


            **Note**: If no page size is given, all the recordings matching the filters will be returned. This could affect the performaces of the Suite.
          in: query
          schema:
            type: integer
            example: 25
        - name: startTime
          description: Filter the returned recordings according to their start time. See [RHS-Colon:datetime](#/%20) for more details on the format.
          in: query
          schema:
            type: string
            format: RHS-Colon:datetime
            example: "after:2023-01-01T00:00:00Z"
        - name: endTime
          description: Filter the returned recordings according to their end time. See [RHS-Colon:datetime](#/%20) for more details on the format.
          in: query
          schema:
            type: string
            format: RHS-Colon:datetime
            example: "before:2023-01-02T00:00:00Z"
        - name: localPartyNumber
          description: Filter the recordings having given local party number
          in: query
          schema:
            type: string
            example: '225'
        - name: remoteParty
          description: Filter the recordings whose remote party number is or contains given value. See [RHS-Colon:string](#/%20) for more details on the format.
          in: query
          schema:
            type: string
            format: RHS-Colon:string
            example: 'contains:+1234'
        - name: ownerUsername
          description: Filter the recordings of the given user
          in: query
          schema:
            type: string
            example: 'john_doe'
        - name: direction
          description: Filter the recordings having given direction
          in: query
          schema:
            $ref: '#/components/schemas/Direction'
      responses:
        '200':
          description: Returning the filtered list of recordings, sorted by most recent first
          content:
            application/json:
              schema:
                properties:
                  totalCount:
                    description: The total number of recordings that match given filters
                    type: integer
                    example: 123
                  recordings:
                    description: An array containing the requested recordings page or all the matching recordings if no paging is requested
                    type: array
                    items:
                      $ref: '#/components/schemas/Recording'
        '400':
          description: One or more of the given parameters are invalid
          content:
            application/json:
              schema:
                properties:
                  reason:
                    type: integer
                    description: >
                      The reason why the request has been rejected

                      * `0`: Some of the filtering parameters are invalid

                      * `1`: Some of the paging parameters are invalid
                    enum: [0, 1]
                  message:
                    type: string
                    description: A human readable error description
        '401':
          $ref: '#/components/responses/401'
        '403':
          $ref: '#/components/responses/403'
        '500':
          $ref: '#/components/responses/500'
        '504':
          $ref: '#/components/responses/504'
    post:
      summary: Upload a new recording
      tags: [Recordings]
      security: [basic: []]
      requestBody:
        description: The request body is a `multipart/form-data` containing a part that describes the recording information and a part as the audio file attachment you want to upload.
        required: true
        content:
          multipart/form-data:
            schema:
              type: object
              required:
                - jsondata
                - attachment
              properties:
                jsondata:
                  allOf:
                    - $ref: '#/components/schemas/UploadRecordingMetadata'
                    - description: |
                        The first part of the multipart body, with `Content-Type` set to `application/json`.

                        * It must contain a JSON object as described in the [UploadRecordingMetadata](#model-UploadRecordingMetadata) schema below
                attachment:
                  description: |
                    The second part of the multipart body, with `Content-Type` set according to the audio file format.

                    * It must contain the audio file of the recording you want to upload.

                    * The supported audio formats are:
                      * `audio/wave` &rarr; _WAV (PCM-8, PCM-16, A-Law, u-Law)_
                      * `audio/mpeg` &rarr; _MP3_

                    * The maximum audio file size is _256 MB_
                  type: string
                  format: binary
            encoding:
              jsondata:
                contentType: application/json
              attachment:
                contentType: audio/wave, audio/mpeg
            examples:
              WAV:
                summary: "Containing a WAV File"
                value: |
                  Content-Type: multipart/form-data; boundary=8d0d51ed-3539-48fa-a239-fb4ee91b3b99

                  --8d0d51ed-3539-48fa-a239-fb4ee91b3b99
                  Content-Type: application/json
                  Content-Disposition: form-data; name=jsondata

                  {
                    "direction": 2,
                    "localParty": {
                      "phoneNumber": "376",
                      "username": "john_doe"
                    },
                    "preserved": true,
                    "duration": "PT1M30S",
                    "notes": "text describing recording content",
                    "startDateTime": "2018-09-25T13:00:00.0000000Z",
                    "remoteParty": {
                      "phoneNumber": "123456"
                    },
                    "pbxInfo": {
                        "type": "generic",
                        "localCallId": "ab123",
                        "remoteCallId": "xy987",
                        "sessionId": "xy123"
                    }
                  }
                  --8d0d51ed-3539-48fa-a239-fb4ee91b3b99
                  Content-Type: audio/wave
                  Content-Disposition: form-data; name=attachment; filename=sample.wav; filename*=utf-8''sample.wav

                  ♫
                  --8d0d51ed-3539-48fa-a239-fb4ee91b3b99--
              MP3:
                summary: "Containing an MP3 File"
                value: |
                  Content-Type: multipart/form-data; boundary=61e3a227-3050-4eb8-8ddf-e1e470ec7dd1

                  --61e3a227-3050-4eb8-8ddf-e1e470ec7dd1
                  Content-Type: application/json
                  Content-Disposition: form-data; name=jsondata

                  {
                    "direction": 2,
                    "localParty": {
                      "phoneNumber": "1234",
                      "username": "test"
                    },
                    "preserved": true,
                    "duration": "PT1M30S",
                    "notes": "text describing recording content",
                    "startDateTime": "2024-09-26T11:00:00.0000000Z",
                    "remoteParty": {
                      "phoneNumber": "11111"
                    },
                    "pbxInfo": {
                        "type": "generic",
                        "localCallId": "ab123",
                        "remoteCallId": "xy987",
                        "sessionId": "xy123"
                    }
                  }
                  --61e3a227-3050-4eb8-8ddf-e1e470ec7dd1
                  Content-Type: audio/mpeg
                  Content-Disposition: form-data; name=attachment; filename=sample.mp3; filename*=utf-8''sample.mp3

                  ♫
                  --61e3a227-3050-4eb8-8ddf-e1e470ec7dd1--
      responses:
        '201':
          description: Returning the ID of the newly created recording
          content:
            application/json:
              schema:
                properties:
                  id:
                    $ref: '#/components/parameters/id/schema'
        '400':
          description: One or more of the given parameters are invalid
          content:
            application/json:
              schema:
                properties:
                  reason:
                    type: integer
                    description: >
                      The reason why the request has been rejected

                      * `0`: Body is null or cannot be parsed

                      * `1`: Given recording metadata are not valid

                      * `2`: Given recording audio file is not valid
                    enum: [0, 1, 2]
                  message:
                    type: string
                    description: A human readable error description
        '401':
          $ref: '#/components/responses/401'
        '403':
          $ref: '#/components/responses/403'
        '409':
          description: The recording start date is out of the retention period
        '500':
          $ref: '#/components/responses/500'
        '501':
          description: The Imagicle Call Recording license is invalid
        '504':
          $ref: '#/components/responses/504'
  /{id}:
    get:
      summary: Retrieve detailed information of a single recording
      tags: [Recordings]
      security: [basic: []]
      parameters:
        - $ref: '#/components/parameters/id'
      responses:
        '200':
          description: Returning an object containing detailed information of a single recording
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/RecordingDetail'
        '400':
          description: Given identifier is not a valid UUID
        '401':
          $ref: '#/components/responses/401'
        '403':
          $ref: '#/components/responses/403'
        '404':
          description: No recording has been found having given identifier
        '500':
          $ref: '#/components/responses/500'
        '504':
          $ref: '#/components/responses/504'
  /{id}/Media:
    get:
      summary: Retrieves the unencrypted MP3 media for a single recording
      tags: [Recordings]
      security: [basic: []]
      parameters:
        - $ref: '#/components/parameters/id'
      responses:
        '200':
          description: The response body is a stream containing the MP3 encoded recording audio
          content:
            audio/mpeg:
              schema:
                type: string
                format: binary
                example: "♫"
        '400':
          description: Given identifier is not a valid UUID
        '401':
          $ref: '#/components/responses/401'
        '403':
          $ref: '#/components/responses/403'
        '404':
          description: No recording has been found having given identifier
        '500':
          $ref: '#/components/responses/500'
        '504':
          $ref: '#/components/responses/504'
tags:
  - name: Recordings
  - name: " "
    description: >
      # Right Hand Side (RHS) Colon

      Some of the query parameters in this API is using the RHS Colon syntax. Here is a deeper explanation of what it looks like and how to use it.

      ## RHS-Colon:datetime

      This syntax can be used for parameters using the `RHS-Colon:datetime` format.


      **Note**: Date and time values must use the [ISO-8601](https://en.wikipedia.org/wiki/ISO_8601) format.

      <table>
        <thead>
          <tr>
            <th>Operator</th>
            <th>Examples</th>
            <th>Notes</th>
          </tr>
        </thead>
        <tbody>
          <tr>
            <td>equals</td>
            <td><code>param=equals:2018-11-01T00:00:00Z</code><br/><br/><code>param=2018-11-01T00:00:00Z</code><br/>&nbsp;</td>
            <td>The operator can be omitted since it is the default one</td>
          </tr>
          <tr>
            <td>before</td>
            <td><code>param=before:2018-10-10T13:05:34Z</code><br/>&nbsp;</td>
            <td>The upper limit is excluded</td>
          </tr>
          <tr>
            <td>after</td>
            <td><code>param=after:2018-11-05T09:12:24Z</code><br/>&nbsp;</td>
            <td>The lower limit is excluded</td>
          </tr>
          <tr>
            <td>between</td>
            <td><code>param=between:2018-11-01T00:00:00Z;2018-11-02T00:00:00Z</code><br/>&nbsp;</td>
            <td>The lower limit is included and the upper one is not.<br/>The two limits are separated by a semicolon symbol (<code>;</code>)</td>
          </tr>
        </tbody>
      </table>


      ## RHS-Colon:string

      This syntax can be used for parameters using the `RHS-Colon:string` format.


      **Note**: If the searched string contains a semicolon or a backslash, they must be escaped by prepending a backslash character.

      <table>
        <thead>
          <tr>
            <th>Operator</th>
            <th>Examples</th>
            <th>Notes</th>
          </tr>
        </thead>
        <tbody>
          <tr>
            <td>equals</td>
            <td><code>param=equals:some value</code><br/><br/><code>param=something</code><br/><br/><code>param=semi\;colon-back\\slash</code><br/>&nbsp;</td>
            <td>The operator can be omitted since it is the default one</td>
          </tr>
          <tr>
            <td>contains</td>
            <td><code>param=contains:val</code><br/>&nbsp;</td>
            <td>Any items whose filtered parameter contains the searched sub-string will be matched</td>
          </tr>
        </tbody>
      </table>
components:
  securitySchemes:
    basic:
      type: http
      scheme: basic
  parameters:
    id:
      name: id
      description: The id of the recording
      in: path
      required: true
      schema:
        type: string
        format: uuid
        example: e0c77c5d-7807-4d9b-9d8d-92a38370af5e
  responses:
    '400':
      description: The request is missing some required fields or caused some validation errors
    '401':
      description: No authentication provided or wrong user credentials
    '403':
      description: The authenticated user is unauthorized to perform this request
    '404':
      description: The specified resource could not be found
    '500':
      description: An unexpected error occurred while processing the request
    '504':
      description: The Imagicle Call Recording service is not running
  schemas:
    Direction:
      type: integer
      example: 1
      enum: [0, 1, 2]
      format: "0: Unknown, 1: Incoming, 2: Outgoing"
      description: >
        * `0`: Unknown

        * `1`: Incoming

        * `2`: Outgoing
    RecordingBase:
      type: object
      properties:
        id:
          description: Unique identifier of the recording
          type: string
          format: uuid
          example: e0c77c5d-7807-4d9b-9d8d-92a38370af5e
        referenceNumber:
          description: A unique, friendly, identifier generated by Imagicle Call Recording of the recording
          type: string
          example: "2015200000023"
        startTime:
          description: The starting time of this recording in [ISO-8601](https://en.wikipedia.org/wiki/ISO_8601) format
          type: string
          format: datetime
          example: "2017-07-05T23:59:59.000Z"
        duration:
          description: The duration of this recording in [ISO-8601](https://en.wikipedia.org/wiki/ISO_8601#Durations) format
          type: string
          format: duration
          example: PT1M31.87S
        direction:
          description: Direction of the recorded call
          allOf:
          - $ref: '#/components/schemas/Direction'
        localPartyNumber:
          description: The telephone number of the phone recording the call
          type: string
          example: "256"
        remotePartyNumber:
          description: The telephone number of the remote participant of this recording
          type: string
          example: "+391234567"
    Recording:
      allOf:
        - $ref: '#/components/schemas/RecordingBase'
        - type: object
          properties:
            ownerUsername:
              description: The username of the user who recorded the call
              type: string
              example: john_doe
    RecordingDetail:
      allOf:
        - $ref: '#/components/schemas/RecordingBase'
        - type: object
          properties:
            pbxCallId:
              deprecated: true
              description: Use `pbxInfo` instead
              type: string
              example: null
            pbxInfo:
                $ref: '#/components/schemas/PbxInfo'
            owner:
              allOf:
                - $ref: '#/components/schemas/User'
                - description: The user who recorded the call
            preservingUser:
              allOf:
                - $ref: '#/components/schemas/User'
                - description: The user who preserved the recording (if any)
            note:
              description: User defined note for the recording
              type: object
              properties:
                owner:
                  allOf:
                    - $ref: '#/components/schemas/User'
                    - description: The last user who edited the note
                text:
                  description: The current content of the note
                  type: string
                  example: Ref. invoice No.1234ABC
            size:
              description: Size in bytes of the recording
              type: integer
              example: 356112
            hash:
              type: object
              properties:
                SHA256:
                  description: The SHA-256 hash of the recording
                  type: string
                  example: 1DDAE20272E67699E325C31C8813720B770AC04BC1604C9B3B8967FEAEE1037F
    User:
      type: object
      properties:
        username:
          description: User's username
          type: string
          example: john_doe
        firstName:
          description: User's first name
          type: string
          example: John
        lastName:
          description: User's last name
          type: string
          example: Doe
        phoneNumber:
          description: User's phone number
          type: string
          example: "202"
        group:
          description: Recording group of the user at the time of the recording
          type: string
          example: "Group1"
        department:
          description: Department of the user at the time of the recording
          type: string
          example: "Sales"
    UploadRecordingMetadata:
      type: object
      required:
        - startDateTime
        - duration
        - direction
        - localParty
      properties:
        startDateTime:
          description: The starting time of this recording in [ISO-8601](https://en.wikipedia.org/wiki/ISO_8601) format
          type: string
          format: datetime
          example: "2017-07-05T23:59:59.000Z"
        duration:
          description: The duration of this recording in [ISO-8601](https://en.wikipedia.org/wiki/ISO_8601#Durations) format
          type: string
          format: duration
          example: PT1M31.87S
        direction:
          description: Direction of the recorded call
          allOf:
          - $ref: '#/components/schemas/Direction'
        localParty:
          type: object
          description: The recording local party info
          required:
            - username
            - phoneNumber
          properties:
            username:
              type: string
              description: The username of the user that recorded the call
              example: john_doe
            phoneNumber:
              type: string
              description: The local party phone number of the recording
              example: "205"
        remoteParty:
          type: object
          description: The recording remote party info
          properties:
            phoneNumber:
              type: string
              description: The remote party phone number of the recording
              example: "+391234567"
        notes:
          type: string
          description: Initial note for this recording
          example: Ref. invoice No.1234ABC
        preserved:
          type: boolean
          description: Set this to `true` if you want this recording to be preserved regardless of the retention period
          example: false
        pbxCallId:
          deprecated: true
          type: string
          description: Use `pbxInfo` instead
        pbxInfo:
          $ref: '#/components/schemas/PbxInfo'
    PbxInfo:
      description: Infromation provided by the PBX to identify recordings which belong to the same conversation
      oneOf:
        - $ref: '#/components/schemas/GenericPbxInfo'
        - $ref: '#/components/schemas/MediaForkingPbxInfo'
      discriminator:
        propertyName: type
        mapping:
          generic: '#/components/schemas/GenericPbxInfo'
          media-forking: '#/components/schemas/MediaForkingPbxInfo'
      example: {
        type: generic,
        localCallId: ab123,
        remoteCallId: xy987
      }
    GenericPbxInfo:
      type: object
      title: GenericPbxInfo
      required:
        - type
      properties:
        type:
          type: string
          enum: [generic]
        localCallId:
          type: string
          example: ab123
        remoteCallId:
          type: string
          example: xy987
    MediaForkingPbxInfo:
      type: object
      title: MediaForkingPbxInfo
      required:
        - type
      properties:
        type:
          type: string
          enum: [media-forking]
        localCallId:
          type: string
          example: ab123
        remoteCallId:
          type: string
          example: xy987
        sessionId:
          type: string
          example: xy123