openapi: 3.0.1
info:
  title: Ows-assets API specifications
  version: 1.0.0
servers:
- url: https://ows-assets.theorchard.io/
paths:
  /hello:
    get:
      description: Health check
      responses:
        "200":
          description: 200 OK
          content:
            application/json:
              schema:
                type: object
                example:
                  status: ok
  /image/{image_type}/{image_format}/{entity_id}/location:
    get:
      description: |
        Request an image asset url by image format for an entity.
      parameters:
      - name: image_type
        in: path
        description: Alias for entity_type (artist|product)
        required: true
        schema:
          type: string
      - name: image_format
        in: path
        description: "For a product, this could be \"large_cover\""
        required: true
        schema:
          type: string
      - name: entity_id
        in: path
        description: The id for the entity referenced in image_type
        required: true
        schema:
          type: integer
      - name: force_uncorrected
        in: query
        description: Only return non-correction images
        schema:
          type: string
      - name: Correlation-Id
        in: header
        schema:
          type: string
      - name: Orchard-User-Id
        in: header
        schema:
          type: string
      - name: Grass-Account-Id
        in: header
        schema:
          type: integer
      - name: Grass-Account-Type
        in: header
        schema:
          type: string
          enum:
          - vendor
          - subaccount
      responses:
        "200":
          description: 200 OK
          content:
            text/plain:
              schema:
                type: string
              example: https://qa-images.theorchard.io/product/large_cover/7676e1dbdc46b259143a3e7d149fcf3a.jpg
        "403":
          description: 403 Entity not owned
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
            code:
              example: not_owned
            message:
              example: Entity not owned by account
        "404":
          description: 404 Entity not found
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
            code:
              example: not_found_error
            message:
              example: Entity not found for provided entity id.
        "500":
          description: 500 Internal server error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
            code:
              example: internal_error
            message:
              example: Could not connect to MySQL
  /image/vendor/{vendor_id}/asset/{asset_id}:
    get:
      description: |
        Request a vendor image by vendor id and asset id.
      parameters:
      - name: vendor_id
        in: path
        description: The id of the vendor
        required: true
        schema:
          type: integer
      - name: asset_id
        in: path
        description: The image_asset_id for the image
        required: true
        schema:
          type: integer
      - name: Correlation-Id
        in: header
        schema:
          type: string
      responses:
        "200":
          description: 200 OK
          content:
            text/plain:
              schema:
                type: string
              example: https://images.qaorch.com/vendor/vendor_icon/21989/21989/2323234.jpg
        "404":
          description: 404 Entity not found
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
            code:
              example: not_found_error
            message:
              example: Entity not found for provided entity id.
        "500":
          description: 500 Internal server error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
            code:
              example: internal_error
            message:
              example: Could not connect to MySQL
  /image/{image_type}/{image_format}/location:
    get:
      description: |
        Request image asset urls by image format for list of entities.
      parameters:
      - name: image_type
        in: path
        description: Alias for entity_type (artist|product)
        required: true
        schema:
          type: string
      - name: image_format
        in: path
        description: "For a product, this could be \"large_cover\""
        required: true
        schema:
          type: string
      - name: ids
        in: query
        description: The ids for entities referenced in image_type
        required: true
        schema:
          type: string
      - name: Correlation-Id
        in: header
        schema:
          type: string
      - name: Orchard-User-Id
        in: header
        schema:
          type: string
      - name: Grass-Account-Id
        in: header
        schema:
          type: integer
      - name: Grass-Account-Type
        in: header
        schema:
          type: string
          enum:
          - vendor
          - subaccount
      responses:
        "200":
          description: 200 OK
          content:
            application/json:
              schema:
                type: object
                additionalProperties:
                  type: string
                  example: https://qa-images.theorchard.io/product/cover/123.jpg
                example:
                  "123": https://qa-images.theorchard.io/product/cover/123.jpg
                  "456": https://qa-images.theorchard.io/product/cover/456.jpg
        "500":
          description: 500 Internal server error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
            code:
              example: internal_error
            message:
              example: Could not connect to MySQL
    post:
      description: |
        Request image asset urls by image format for list of products.
      parameters:
      - name: image_type
        in: path
        description: Alias for product
        required: true
        schema:
          type: string
      - name: image_format
        in: path
        description: "For a product, this could be \"large_cover\""
        required: true
        schema:
          type: string
      - name: Correlation-Id
        in: header
        schema:
          type: string
      - name: Orchard-User-Id
        in: header
        schema:
          type: string
      - name: Grass-Account-Id
        in: header
        schema:
          type: integer
      - name: Grass-Account-Type
        in: header
        schema:
          type: string
          enum:
          - vendor
          - subaccount
      requestBody:
        description: The product ids and upcs for products referenced in image_type
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/PostImageLocationBulk'
        required: false
      responses:
        "200":
          description: 200 OK
          content:
            application/json:
              schema:
                type: object
                additionalProperties:
                  type: string
                  example: https://qa-images.theorchard.io/product/cover/123.jpg
                example:
                  "123": https://qa-images.theorchard.io/product/cover/123.jpg
                  "456": https://qa-images.theorchard.io/product/cover/456.jpg
        "500":
          description: 500 Internal server error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
            code:
              example: internal_error
            message:
              example: Could not connect to MySQL
      x-codegen-request-body-name: body
  /image/{from_pid}/copy/{to_pid}:
    post:
      description: |
        Creates a copy of the product image asset
        (copy artwork assets from product with unique id <from_pid>
        to product with unique id <to_pid>).
      parameters:
      - name: from_pid
        in: path
        required: true
        schema:
          type: string
      - name: to_pid
        in: path
        required: true
        schema:
          type: string
      - name: Correlation-Id
        in: header
        schema:
          type: string
      - name: Orchard-User-Id
        in: header
        schema:
          type: string
      - name: Grass-Account-Id
        in: header
        schema:
          type: integer
      - name: Grass-Account-Type
        in: header
        schema:
          type: string
          enum:
          - vendor
          - subaccount
      responses:
        "200":
          description: 200 OK
          content:
            application/json:
              schema:
                required:
                - status
                type: object
                properties:
                  status:
                    type: string
                example:
                  message: Product artwork has been copied successfully.
                  status: OK
        "403":
          description: 403 Product not owned
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
            code:
              example: not_owned
            message:
              example: Product not owned by account
        "404":
          description: 404 Product not found
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
            code:
              example: not_found_error
            message:
              example: Product not found for provided product id.
        "500":
          description: 500 Internal server error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
            code:
              example: internal_error
            message:
              example: Could not connect to MySQL
  /stream/track/{track_id}/hls:
    get:
      description: Returns an HLS URL to a stream for the track
      parameters:
      - name: track_id
        in: path
        required: true
        schema:
          type: number
      - name: Correlation-Id
        in: header
        schema:
          type: string
      - name: Orchard-User-Id
        in: header
        schema:
          type: string
      responses:
        "200":
          description: 200 OK
          content:
            application/json:
              schema:
                required:
                - url
                type: object
                properties:
                  url:
                    type: string
                example:
                  url: https://wowza.theorchard.io/...
        "404":
          description: 404 File not found
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
            code:
              example: not_found_error
            message:
              example: Track not found
        "500":
          description: 500 Internal server error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
            code:
              example: internal_error
            message:
              example: Could not connect to MySQL
  /stream/track/{track_id}/hls/clear-cache:
    post:
      description: Clear a track from the HLS (Wowza) cache
      parameters:
      - name: track_id
        in: path
        required: true
        schema:
          type: number
      - name: Correlation-Id
        in: header
        schema:
          type: string
      - name: Orchard-User-Id
        in: header
        schema:
          type: string
      responses:
        "200":
          description: 200 OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  host_1:
                    type: object
                    properties: {}
                  host_2:
                    type: object
                    properties: {}
                example:
                  host_1:
                    message: success
                    status: 200
                  host_2:
                    message: success
                    status: 200
        "404":
          description: 404 File not found
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
            code:
              example: not_found_error
            message:
              example: Track not found
        "500":
          description: 500 Internal server error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
            code:
              example: internal_error
            message:
              example: Could not connect to MySQL
  /track/{from_tuid}/copy/{to_tuid}:
    post:
      description: |
        Creates a copy of the track assets
        (copy assets from track with unique id <from_tuid>
        to track with unique id <to_tuid>).
      parameters:
      - name: from_tuid
        in: path
        required: true
        schema:
          type: string
      - name: to_tuid
        in: path
        required: true
        schema:
          type: string
      - name: Correlation-Id
        in: header
        schema:
          type: string
      - name: Orchard-User-Id
        in: header
        schema:
          type: string
      - name: Grass-Account-Id
        in: header
        schema:
          type: integer
      - name: Grass-Account-Type
        in: header
        schema:
          type: string
          enum:
          - vendor
          - subaccount
      responses:
        "200":
          description: 200 OK
          content:
            application/json:
              schema:
                required:
                - status
                type: object
                properties:
                  status:
                    type: string
                example:
                  status: ok
        "404":
          description: 404 Product not found
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
            code:
              example: not_found_error
            message:
              example: Product not found
        "500":
          description: 500 Internal server error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
            code:
              example: internal_error
            message:
              example: Could not connect to MySQL
  /validators/product/{product_id}/desired-bit-depth/{bit_depth}:
    get:
      description: Check uniform bit depth for provided product.
      parameters:
      - name: product_id
        in: path
        required: true
        schema:
          type: integer
      - name: bit_depth
        in: path
        required: true
        schema:
          type: integer
      - name: physical_location_id
        in: query
        schema:
          type: string
      - name: asset_type_id
        in: query
        schema:
          type: string
      responses:
        "200":
          description: 200 OK
          content:
            text/plain:
              example: Desired bit depth found for provided product.
        "400":
          description: 400 Desired bit depth not found for provided product.
          content:
            text/plain:
              example: Desired bit depth not found for provided product.
        "404":
          description: 404 Value for bits per sample not found for provided product
            id.
          content:
            text/plain:
              example: Value for bits per sample not found for provided product id.
        "500":
          description: Internal server error
          content: {}
  /v2/assets/upload:
    post:
      description: |
        Create an asset upload.
        An asset upload record will be created and associated with a track and/or product. The asset upload will have status "uploading".
        Returns unique filename for the asset upload.
      parameters:
      - name: Orchard-User-Id
        in: header
        required: true
        schema:
          type: string
      - name: Grass-Account-Type
        in: header
        schema:
          type: string
          enum:
          - vendor
          - subaccount
      - name: Grass-Account-Id
        in: header
        schema:
          type: integer
      requestBody:
        content:
          application/json:
            schema:
              required:
              - original_filename
              - product_id
              - track_unique_id
              type: object
              properties:
                product_id:
                  minimum: 1
                  type: integer
                track_unique_id:
                  minimum: 0
                  type: integer
                original_filename:
                  type: string
        required: true
      responses:
        "200":
          description: 200 OK
          content:
            application/json:
              schema:
                required:
                - filename
                type: object
                properties:
                  filename:
                    type: string
                    format: uuid
        "400":
          description: 400 Bad Request
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        "403":
          description: 403 Forbidden
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
      x-codegen-request-body-name: body
  /v2/assets/upload/{filename}:
    get:
      description: |
        Get presigned urls for asset upload.
        Returns a map from part number to presigned url.
      parameters:
      - name: Orchard-User-Id
        in: header
        required: true
        schema:
          type: string
      - name: Grass-Account-Type
        in: header
        schema:
          type: string
          enum:
          - vendor
          - subaccount
      - name: Grass-Account-Id
        in: header
        schema:
          type: integer
      - name: filename
        in: path
        description: The filename to look up.
        required: true
        schema:
          type: string
      - name: part_numbers
        in: query
        description: Comma separated list of part numbers.
        required: true
        schema:
          type: string
      responses:
        "200":
          description: 200 OK
          content:
            application/json:
              schema:
                required:
                - part_number_to_presigned_url
                type: object
                properties:
                  part_number_to_presigned_url:
                    type: object
                    additionalProperties:
                      type: string
                      format: url
                    description: Part number key to presigned url value.
        "404":
          description: 404 Not Found
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
    patch:
      description: |
        Complete a multipart upload.
      parameters:
      - name: Orchard-User-Id
        in: header
        required: true
        schema:
          type: string
      - name: Grass-Account-Type
        in: header
        schema:
          type: string
          enum:
          - vendor
          - subaccount
      - name: Grass-Account-Id
        in: header
        schema:
          type: integer
      - name: filename
        in: path
        description: The filename to look up.
        required: true
        schema:
          type: string
      requestBody:
        content:
          application/json:
            schema:
              required:
              - parts
              type: object
              properties:
                parts:
                  type: array
                  items:
                    required:
                    - etag
                    - part_number
                    type: object
                    properties:
                      part_number:
                        type: integer
                      etag:
                        type: string
        required: true
      responses:
        "200":
          description: 200 OK
          content: {}
        "404":
          description: 404 Not Found
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
      x-codegen-request-body-name: body
  /upload-token/:
    get:
      description: Generate credentials for raw assets upload.
      responses:
        "200":
          description: 200 OK
          content:
            application/json:
              schema:
                type: object
                example:
                  bucket: TEST-orcd-raw-assets
                  credentials:
                    aws_access_key_id: AKIAIOSFODNN7EXAMPLE
                    aws_secret_access_key: wJalrXUtnFEMI/K7MDENG/bPxRfiCYzEXAMPLEKEY
                    expiration: 2016-01-25T19:55:29.611Z
                    token: AQoEXAMPLEH4aoAH0gNCAPyJxz4BlCFFxWNE1OPTgk5TthT+FvwqnKwRcOIfrRh3c/L
                  filename: hjhj45_rfwri_424524
  /upload-token/{entity}/{entity_id}:
    get:
      description: Returns data required for vendor or artist assets upload.
      parameters:
      - name: entity
        in: path
        description: name of the entity(vendor/artist) that need access.
        required: true
        schema:
          type: string
      - name: entity_id
        in: path
        description: id of artist_info or vendor.
        required: true
        schema:
          type: integer
      - name: Grass-Account-Id
        in: header
        schema:
          type: integer
      - name: Grass-Account-Type
        in: header
        schema:
          type: string
          enum:
          - vendor
          - subaccount
      responses:
        "200":
          description: 200 OK
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/EntityAssetsToken'
        "404":
          description: 404 Entity not found
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
            code:
              example: not_found_error
            message:
              example: Entity not found
        "500":
          description: 500 Internal server error
          content: {}
  /v2/assets-bulk:
    get:
      description: Get assets info by many products.
      parameters:
      - name: product_ids
        in: query
        required: true
        schema:
          type: string
      - name: asset_types
        in: query
        required: false
        schema:
          type: string
      responses:
        "200":
          description: 200 OK
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/GetAssetInfoList'
        "400":
          description: 400 Bad request
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
            code:
              example: error_query_validation
            message:
              example:
                cover:
                  code: error_query_validation
                  message: string
        "404":
          description: 404 Asset not found
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
            code:
              example: not_found_error
            message:
              example:
                cover:
                  code: not_found_error
                  message: string
  /v2/asset:
    get:
      description: Get asset info by raw or final name.
      parameters:
      - name: filename
        in: query
        required: true
        schema:
          type: string
      - name: state
        in: query
        required: true
        schema:
          type: string
          enum:
          - raw
          - final
      - name: Correlation-Id
        in: header
        schema:
          type: string
      responses:
        "200":
          description: 200 OK
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/GetAssetV2'
        "400":
          description: 400 Bad request
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
            code:
              example: error_query_validation
            message:
              example:
                cover:
                  code: error_query_validation
                  message: string
        "404":
          description: 404 Asset not found
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
            code:
              example: not_found_error
            message:
              example:
                cover:
                  code: not_found_error
                  message: string
        "500":
          description: 500 Internal server error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
            code:
              example: internal_error
            message:
              example:
                cover:
                  code: internal_error
                  message: Could not connect to database
    post:
      description: |
        Called by the acknowledge lambda:
        https://github.com/theorchard/lambda-assets/tree/a161ad5f51b6568917b996421244b90adc0af53d/lambda/acknowledge
        as part of the assets-transcoding-v2 sfn:
        https://github.com/theorchard/terraform-infra/blob/7a8fc01f41885a52a6677daa02f346c6d0d2d976/prod/assets-transcoding-v2/state-machine-definition.json#L7

        When asset uploads are initiated by POST /upload-token, metadata like product_id and track_unique_id isn't stored in the asset_upload table initially.
        The uploader, typically a frontend like frontend-distribution, attaches metadata to the S3 object for the uploaded asset.
        When the acknowledge lambda is triggered, it will pull the metadata from the S3 object and send it to this endpoint.
        
        When asset uploads are initiated by POST /v2/assets/upload, metadata is stored in the asset_upload table right away.
        When the acknowledge lambda is triggered, it will send only the filename of the S3 object to this endpoint.
        
        This is how this endpoint behaves based on the metadata sent and the existing metadata set on the asset_upload record:
        | Metadata Sent | Existing Metadata | Request Succeeds | Action                       |
        |---------------|-------------------|------------------|------------------------------|
        | Yes           | No                | Yes              | Metadata set on asset_upload |
        | No            | Yes               | Yes              | Validation only, no update   |
        | Yes           | Yes               | No               | Request fails                |
        | No            | No                | No               | Request fails                |
      parameters:
      - name: Correlation-Id
        in: header
        schema:
          type: string
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/PostAssetV2'
        required: false
      responses:
        "200":
          description: 200 OK
          content:
            application/json:
              schema:
                required:
                - status
                type: object
                properties:
                  status:
                    type: string
                example:
                  status: ok
        "400":
          description: 400 Bad request
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
            code:
              example: error_body_validation
            message:
              example:
                cover:
                  code: error_body_validation
                  message: string
        "404":
          description: 404 Asset upload not found
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
            code:
              example: not_found_error
            message:
              example:
                cover:
                  code: not_found_error
                  message: string
        "500":
          description: 500 Internal server error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
            code:
              example: internal_error
            message:
              example:
                cover:
                  code: internal_error
                  message: Could not connect to database
      x-codegen-request-body-name: body
  /v2/asset/info:
    get:
      description: Get asset info by asset_final_id.
      parameters:
      - name: asset_final_id
        in: query
        required: true
        schema:
          type: integer
      responses:
        "200":
          description: 200 OK
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/GetAssetV2'
        "400":
          description: 400 Bad request
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
            code:
              example: error_query_validation
            message:
              example:
                cover:
                  code: error_query_validation
                  message: string
        "404":
          description: 404 Asset not found
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
            code:
              example: not_found_error
            message:
              example:
                cover:
                  code: not_found_error
                  message: string
        "500":
          description: 500 Internal server error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
            code:
              example: internal_error
            message:
              example:
                cover:
                  code: internal_error
                  message: Could not connect to database
  /v2/asset/final:
    post:
      description: Saves the encoding status and encoded assets location.
      parameters:
      - name: Correlation-Id
        in: header
        schema:
          type: string
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/PostAssetFinalV2'
        required: false
      responses:
        "200":
          description: 200 OK
          content:
            application/json:
              schema:
                type: string
                example: 200 OK
        "404":
          description: 404 Asset not found
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
            code:
              example: not_found_error
            message:
              example:
                cover:
                  code: not_found_error
                  message: string
        "500":
          description: 500 Internal server error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
            code:
              example: internal_error
            message:
              example:
                cover:
                  code: internal_error
                  message: Could not connect to database or something
      x-codegen-request-body-name: body
  /asset/product/{product_id}:
    get:
      description: |
        Returns a set of general information for all assets
        (across all asset types) for a particular release, which can be used for
        tracking assets status or/and assets streaming.
      parameters:
      - name: product_id
        in: path
        required: true
        schema:
          type: integer
      - name: Correlation-Id
        in: header
        schema:
          type: string
      - name: Orchard-User-Id
        in: header
        schema:
          type: string
      responses:
        "200":
          description: 200 OK
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/GetProductAssetsV2'
        "404":
          description: 404 Product not found
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
            code:
              example: not_found_error
            message:
              example: Product not found
        "500":
          description: 500 Internal server error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
  /v2/asset/product/{product_id}:
    $ref: '#/paths/~1asset~1product~1{product_id}/get'
  /v2/asset/status:
    post:
      description: Saves the current status of the asset
      parameters:
      - name: Correlation-Id
        in: header
        schema:
          type: string
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/PostAssetStatusV2'
        required: false
      responses:
        "200":
          description: 200 OK
          content:
            application/json:
              schema:
                type: string
                example: 200 OK
        "404":
          description: 404 Asset not found
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
            code:
              example: not_found_error
            message:
              example:
                cover:
                  code: not_found_error
                  message: string
        "500":
          description: 500 Internal server error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
            code:
              example: internal_error
            message:
              example:
                cover:
                  code: internal_error
                  message: Could not connect to database or something
      x-codegen-request-body-name: body
  /v2/asset/status/{filename}:
    get:
      description: Returns the current status of the asset
      parameters:
      - name: filename
        in: path
        required: true
        schema:
          type: string
      - name: Correlation-Id
        in: header
        schema:
          type: string
      - name: Orchard-User-Id
        in: header
        schema:
          type: string
      - name: Grass-Account-Id
        in: header
        schema:
          type: integer
      - name: Grass-Account-Type
        in: header
        schema:
          type: string
          enum:
          - vendor
          - subaccount
      responses:
        "200":
          description: 200 OK
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/GetAssetStatusV2'
        "403":
          description: Forbidden
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        "404":
          description: 404 Asset not found
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        "500":
          description: 500 Internal server error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
  /internal/v2/asset/{filename}/owner:
    get:
      description: |
        Returns the owner of an asset identified by its filename.
        Resolves the asset's product id and queries ows-product for the owner
        information (vendor id and subaccount id).
      parameters:
      - name: filename
        in: path
        required: true
        schema:
          type: string
      - name: Correlation-Id
        in: header
        schema:
          type: string
      responses:
        "200":
          description: 200 OK
          content:
            application/json:
              schema:
                required:
                - vendor_id
                - subaccount_id
                type: object
                properties:
                  vendor_id:
                    type: integer
                    description: Vendor id that owns the asset's product, or 0 when not set.
                    example: 42
                  subaccount_id:
                    type: integer
                    description: Subaccount id that owns the asset's product, or 0 when not set.
                    example: 0
        "404":
          description: |
            404 Not Found.
            Returned when the asset does not exist, has been deleted, or its
            product id is missing.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
              example:
                code: not_found_error
                message: Asset upload not found or already deleted
        "500":
          description: 500 Internal server error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
  /internal/assets/{asset_upload_filename}/stereo:
    get:
      description: |
        Returns the latest non-deleted stereo asset_upload's asset_final FLAC
        for the track that the input asset belongs to (corrections included).
        The input asset's own type does not matter — the lookup pivots through
        its `(product_id, track_unique_id)` pair to find the track's stereo.
      parameters:
      - name: asset_upload_filename
        in: path
        required: true
        schema:
          type: string
      - name: Correlation-Id
        in: header
        schema:
          type: string
      responses:
        "200":
          description: 200 OK
          content:
            application/json:
              schema:
                required:
                - bucket
                - key
                type: object
                properties:
                  bucket:
                    type: string
                    description: S3 bucket containing the stereo FLAC.
                    example: prod-encoded-assets
                  key:
                    type: string
                    description: S3 key of the stereo FLAC.
                    example: 01234567-89ab-cdef-0123-456789abcdef.flac
        "401":
          description: |
            401 Unauthorized.
            Returned when no JWT is provided.
        "403":
          description: |
            403 Forbidden.
            Returned when the JWT identity is not in the allowlist.
        "404":
          description: |
            404 Not Found. The `message` field distinguishes the cause:

            - `"Asset upload not found or already deleted"` — the input
              filename does not match any active asset_upload, or no stereo
              upload exists for the input asset's product+track pair.
            - `"Final asset not found"` — the stereo asset_upload was found
              but has no FLAC asset_final yet.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        "500":
          description: 500 Internal server error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
  /v2/image/{product_id}:
    delete:
      description: |
        Removes image assets for product with id <product_id>.
        Product should NOT have “in_content” status.
      parameters:
      - name: product_id
        in: path
        required: true
        schema:
          type: integer
      - name: Correlation-Id
        in: header
        schema:
          type: string
      - name: Orchard-User-Id
        in: header
        schema:
          type: string
      - name: Grass-Account-Id
        in: header
        schema:
          type: integer
      - name: Grass-Account-Type
        in: header
        schema:
          type: string
          enum:
          - vendor
          - subaccount
      responses:
        "200":
          description: 200 OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  status:
                    type: string
                example:
                  status: ok
        "404":
          description: 404 Product not found
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        "500":
          description: 500 Internal server error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
  /v2/product/{product_id}:
    delete:
      description: |
        Removes all files associcated with a product by finding
        related asset upload (source file and transcoded files) from s3.
        Upload Asset should have 'encoding_complete' status.
        Also, removes entries related to transcoded files
        from the 'asset_final' table also creates a new entry
        in 'asset_status' table with 'deleted' status.
      parameters:
      - name: product_id
        in: path
        required: true
        schema:
          type: integer
      - name: Correlation-Id
        in: header
        schema:
          type: string
      - name: Orchard-User-Id
        in: header
        schema:
          type: string
      - name: Grass-Account-Id
        in: header
        schema:
          type: integer
      - name: Grass-Account-Type
        in: header
        schema:
          type: string
          enum:
          - vendor
          - subaccount
      responses:
        "200":
          description: 200 OK
          content:
            application/json:
              schema:
                required:
                - status
                type: object
                properties:
                  status:
                    type: string
                example:
                  status: ok
        "404":
          description: 404 Product not found
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
            code:
              example: not_found_error
            message:
              example: Product not found
        "500":
          description: 500 Internal server error due to
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
            code:
              example: internal_error
            message:
              example: Could not connect to MySQL
  /v2/track/{tuid}:
    delete:
      description: |
        Removes files which related to asset upload
        (source file and transcoded files) from s3.
        Upload Asset should have 'encoding_complete' status.
        Also, removes entries related to transcoded files
        from the  'asset_final' table also creates a new entry
        in 'asset_status' table with 'deleted' status.
      parameters:
      - name: tuid
        in: path
        required: true
        schema:
          type: integer
      - name: Correlation-Id
        in: header
        schema:
          type: string
      - name: Orchard-User-Id
        in: header
        schema:
          type: string
      - name: Grass-Account-Id
        in: header
        schema:
          type: integer
      - name: Grass-Account-Type
        in: header
        schema:
          type: string
          enum:
          - vendor
          - subaccount
      - name: asset_upload_type
        in: query
        required: false
        description: |
          Optional filter to delete only assets of a specific upload type.
          When omitted, all asset uploads for the track are deleted.
        schema:
          type: string
          enum:
          - stereo
          - static_artwork
          - atmos
      responses:
        "200":
          description: 200 OK
          content:
            application/json:
              schema:
                required:
                - status
                type: object
                properties:
                  status:
                    type: string
                example:
                  status: ok
        "400":
          description: 400 Bad Request — invalid asset_upload_type value
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        "404":
          description: 404 Track not found
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
            code:
              example: not_found_error
            message:
              example: Track not found
        "500":
          description: 500 Internal server error due to
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
            code:
              example: internal_error
            message:
              example: Could not connect to MySQL
  /v2/validators/product/{product_id}/artwork:
    get:
      description: Retrieve the location of an image to verify it is present.
      parameters:
      - name: product_id
        in: path
        required: true
        schema:
          type: integer
      - name: require_v1
        in: query
        description: |
          If set to '1', this option will force the endpoint to always validate v1
          artwork in addition to v2. By default, v1 is only checked as a fallback if no v2 art exists.
        schema:
          type: string
      responses:
        "200":
          description: 200 OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  status:
                    type: string
              example:
                status: ok
        "404":
          description: 404 Product not found
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        "500":
          description: 500 Internal server error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
  /v2/validators/product/{product_id}/audio:
    get:
      description: Retrieve audio assets for a product to see if they are present.
      parameters:
      - name: product_id
        in: path
        required: true
        schema:
          type: integer
      responses:
        "200":
          description: 200 OK
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/GetProductAudioValidateV2'
  /v2/product/{product_id}/corrections:
    delete:
      description: Marks asset_upload records with is_correction set as deleted. Does
        not delete files from S3
      parameters:
      - name: product_id
        in: path
        required: true
        schema:
          type: integer
      - name: Correlation-Id
        in: header
        schema:
          type: string
      - name: Orchard-User-Id
        in: header
        schema:
          type: string
      - name: Grass-Account-Id
        in: header
        schema:
          type: integer
      - name: Grass-Account-Type
        in: header
        schema:
          type: string
          enum:
          - vendor
          - subaccount
      - name: check_ownership
        in: query
        description: Paramter indicating whether to conduct an ownernship check of
          the product.
        schema:
          type: string
      responses:
        "200":
          description: 200 OK
          content:
            application/json:
              schema:
                required:
                - status
                type: object
                properties:
                  status:
                    type: string
                example:
                  status: ok
        "404":
          description: 404 Correction assets not found
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
            code:
              example: not_found_error
            message:
              example: Cant discard correction given there no active corrections for
                product 123
        "500":
          description: 500 Internal server error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
            code:
              example: internal_error
            message:
              example: Could not connect to MySQL
components:
  schemas:
    ErrorResponse:
      required:
      - code
      - message
      type: object
      properties:
        code:
          type: string
        message:
          type: object
          properties: {}
      example:
        code: not_found_error
        message: Product not found
    EntityAssetsToken:
      type: object
      properties:
        items:
          type: object
          properties:
            bucket:
              type: string
            filename:
              type: string
      example:
        bucket: TEST-orcd-raw-assets
        path:
          logo: images/vendor/logo
          icon: images/vendor/icon
        filename: unique_filename_2
        credentials:
          token: 10.1
          aws_access_key_id: 2232323232
          aws_secret_access_key: rtmp://prefix/1/wav/100075/100075236325_2232323232
          expiration: 2232323232
    GetAssetV2:
      type: object
      properties:
        filename:
          type: string
        original_filename:
          type: string
        track_unique_id:
          type: number
        upc:
          pattern: "^[0-9]+$"
          type: string
        asset_upload_type:
          type: string
      example:
        filename: f162c463_ff5c_4ab8_9a1e_60a4f8266b07
        original_filename: a1.wav
        track_unique_id: 123
        upc: "321"
        asset_upload_type: stereo
    PostAssetV2:
      anyOf:
        - type: object
          required:
          - filename
          - product_id
          - track_unique_id
          - upc
          properties:
            filename:
              type: string
            upc:
              pattern: "^[0-9]+$"
              type: string
            product_id:
              type: integer
            track_unique_id:
              type: integer
            original_filename:
              type: string
            is_correction:
              type: boolean
          example:
            filename: 5cb9990f_d15d_4904_abef_24f166821d30.wav
            original_filename: original_filename.wav
            product_id: 12345
            track_unique_id: 54321
            upc: "12345678901286"
            is_correction: false
        - type: object
          required:
            - filename
          properties:
            filename:
              type: 'string'
          additionalProperties: false
          example:
            filename: 5cb9990f_d15d_4904_abef_24f166821d30
    PostAssetFinalV2:
      type: object
      properties:
        status:
          pattern: encoding_complete
          type: string
        filename:
          type: string
        description:
          type: string
        timestamp:
          pattern: '%Y-%m-%dT%H:%M:%S.%fZ'
          type: string
        final_assets:
          type: array
          items:
            type: object
            properties:
              bucket:
                type: string
              key:
                type: string
              asset_type:
                type: string
              asset_subtype:
                type: string
              container:
                type: string
                enum:
                - wave
                - flac
                - mpeg audio
                - mpeg-4
              duration:
                type: number
        message:
          type: object
          properties:
            function:
              type: string
            status:
              type: string
            results_assets:
              type: array
              items:
                type: object
                properties:
                  bucket:
                    type: string
                  key:
                    type: string
                  asset_type:
                    type: string
                  asset_subtype:
                    type: string
                  container:
                    type: string
                    enum:
                    - wave
                    - flac
                    - mpeg audio
                    - mpeg-4
                  duration:
                    type: number
            input_key:
              type: object
              properties:
                key:
                  type: string
                input:
                  type: string
        status_details:
          type: string
      example:
        description: Success description
        filename: unique_filename.ext
        final_assets:
        - bucket: encoded_asset_bucket_1
          key: encoded_asset_key_1.ext_1
          asset_type: wav
          asset_subtype: none
        - bucket: encoded_asset_bucket_2
          key: encoded_asset_key_2.ext_2
          asset_type: jpg
          asset_subtype: large_cover
        message:
          description: Success description
          function: some_function
          input:
            key: unique_filename.ext
            bucket: some-bucket
          status: success
        status: success
    GetProductAssetsV2:
      type: object
      properties:
        product_id:
          type: number
        upc:
          type: number
        assets:
          type: array
          items:
            type: object
            properties:
              filename:
                type: string
              original_filename:
                type: string
              track_unique_id:
                type: number
              asset_upload_type:
                type: string
                enum:
                - stereo
                - static_artwork
                - atmos
              status:
                type: string
                enum:
                - acknowledge_complete
                - acknowledge_error
                - encoding_completed
                - encoding_error
                - encoding_progressing
                - encoding_route_complete
                - encoding_route_error
                - images_encoding_error
                - upload_complete
                - upload_error
                - validation_complete
                - validation_error
                - validation_warning
            example:
              filename: f162c463_ff5c_4ab8_9a1e_60a4f8266b07
              original_filename: a1.wav
              track_unique_id: 123
              asset_upload_type: stereo
              upc: "321"
              status: encoding_completed
    PostAssetStatusV2:
      type: object
      properties:
        timestamp:
          pattern: '%Y-%m-%dT%H:%M:%S.%fZ'
          type: string
        status:
          type: string
          enum:
          - acknowledge_complete
          - acknowledge_error
          - encoding_error
          - encoding_progressing
          - encoding_route_complete
          - encoding_route_error
          - images_encoding_error
          - upload_complete
          - upload_error
          - validation_complete
          - validation_error
          - validation_warning
        description:
          type: string
        input:
          type: object
          properties:
            key:
              type: string
            input:
              type: string
    GetAssetStatusV2:
      type: object
      properties:
        id:
          type: number
        asset_upload_id:
          type: number
        description:
          type: string
        status:
          type: string
          enum:
          - acknowledge_complete
          - acknowledge_error
          - encoding_error
          - encoding_progressing
          - encoding_route_complete
          - encoding_route_error
          - images_encoding_error
          - upload_complete
          - upload_error
          - validation_complete
          - validation_error
          - validation_warning
        status_time:
          pattern: '%Y-%m-%dT%H:%M:%S.%f'
          type: string
        message:
          type: object
          properties:
            function:
              type: string
            status:
              type: string
            results_assets:
              type: array
              items:
                type: object
                properties:
                  bucket:
                    type: string
                  key:
                    type: string
                  asset_type:
                    type: string
                  asset_subtype:
                    type: string
                  container:
                    type: string
                    enum:
                    - wave
                    - flac
                    - mpeg audio
                    - mpeg-4
                  duration:
                    type: number
            input_key:
              type: object
              properties:
                key:
                  type: string
                input:
                  type: string
    GetProductAudioValidateV2:
      type: object
      properties:
        errorMsgs:
          type: array
          items:
            type: string
            enum:
            - "This product has missing audio assets, please contact the label user."
            - "This product has in-progress audio asset updates, please contact the\
              \ label user."
    PostImageLocationBulk:
      type: object
      properties:
        entities:
          type: array
          items:
            type: object
            properties:
              product_id:
                type: number
              upc:
                type: string
    GetAssetInfo:
      type: object
      properties:
        tuid:
          type: integer
        product_id:
          type: integer
        asset_type:
          type: string
        s3_bucket:
          type: string
        s3_key:
          type: string
        updated_timestamp:
          type: string
        updated_timestamp_us_east:
          type: string
        duration:
          type: number
    GetAssetInfoList:
      type: array
      items:
        $ref: '#/components/schemas/GetAssetInfo'
  parameters:
    correlationId:
      name: Correlation-Id
      in: header
      schema:
        type: string
    orchardUserId:
      name: Orchard-User-Id
      in: header
      schema:
        type: string
    grassAccountId:
      name: Grass-Account-Id
      in: header
      schema:
        type: integer
    grassAccountType:
      name: Grass-Account-Type
      in: header
      schema:
        type: string
        enum:
        - vendor
        - subaccount
