swagger: '2.0'
info:
  title: Project Manager API
  version: 1.0.0
host: qa-ows-project-manager.theorchard.io
basePath: /
schemes:
  - https
paths:
  '/ownership/{accountType}/{accountId}/project/{projectId}':
    head:
      tags: ['ownership']
      parameters:
        - in: path
          name: accountType
          required: true
          type: string
        - in: path
          name: accountId
          required: true
          type: string
        - in: path
          name: projectId
          required: true
          type: string
        - description: UUID
          in: header
          name: Correlation-Id
          type: string
        - description: Grass account type.
          enum:
            - vendor
            - subaccount
          in: header
          name: Grass-Account-Type
          type: string
        - description: Grass account id.
          in: header
          name: Grass-Account-Id
          pattern: ^\d+$
          type: string
      responses:
        '200':
          description: Project is owned by account.
        '400':
          description: Request parameter/header validation failure.
        '403':
          description: >-
            Project not owned by account. or Not authorized to check ownership
            for account.
        '404':
          description: Could not find project with projectId.
      description: Verify a project is owned by a vendor.
  /product/genres:
    get:
      tags: ['product']
      parameters:
        - description: UUID
          in: header
          name: Correlation-Id
          required: false
          type: string
      responses:
        '200':
          examples:
            default:
              - id: 20
                name: Blues
              - id: 13
                name: Children's
              - id: 19
                name: Christian
              - id: 12
                name: Classical
              - id: 9
                name: Country
              - id: 24
                name: Educational
              - id: 2
                name: Electronic
              - id: 5
                name: Folk
              - id: 6
                name: Hip-hop/Rap
              - id: 15
                name: Holiday
              - id: 8
                name: Jazz
              - id: 18
                name: Latin Music
              - id: 3
                name: Metal
              - id: 14
                name: New Age
              - id: 7
                name: Pop
              - id: 4
                name: Punk
              - id: 25
                name: R&B
              - id: 21
                name: Reggae
              - id: 1
                name: Rock
              - id: 27
                name: Soundtracks
              - id: 16
                name: Spoken Word
              - id: 17
                name: Video
              - id: 11
                name: World Music
          description: OK
      description: Get the list of genre options for a product
  /public/product/genres:
    get:
      tags: ['product']
      parameters:
        - description: UUID
          in: header
          name: Correlation-Id
          required: false
          type: string
      responses:
        '200':
          examples:
            default:
              - id: 20
                name: Blues
              - id: 13
                name: Children's
              - id: 19
                name: Christian
              - id: 12
                name: Classical
              - id: 9
                name: Country
              - id: 24
                name: Educational
              - id: 2
                name: Electronic
              - id: 5
                name: Folk
              - id: 6
                name: Hip-hop/Rap
              - id: 15
                name: Holiday
              - id: 8
                name: Jazz
              - id: 18
                name: Latin Music
              - id: 3
                name: Metal
              - id: 14
                name: New Age
              - id: 7
                name: Pop
              - id: 4
                name: Punk
              - id: 25
                name: R&B
              - id: 21
                name: Reggae
              - id: 1
                name: Rock
              - id: 27
                name: Soundtracks
              - id: 16
                name: Spoken Word
              - id: 17
                name: Video
              - id: 11
                name: World Music
          description: OK
      description: Get the list of genre options for a product
  '/product/genres/{genreId}/subgenres':
    get:
      tags: ['product']
      parameters:
        - in: path
          name: genreId
          required: true
          type: string
        - description: UUID
          in: header
          name: Correlation-Id
          required: false
          type: string
      responses:
        '200':
          examples:
            default:
              - id: 511
                composer: false
                name: 80's
              - id: 512
                composer: false
                name: Adult Alternative
              - id: 513
                composer: false
                name: Adult Contemporary
              - id: 129
                composer: false
                name: Alternative
              - id: 1034
                composer: false
                name: American Trad Rock
              - id: 1
                composer: false
                name: Americana
              - id: 1035
                composer: false
                name: Arena Rock
              - id: 5
                composer: false
                name: Boogie Rock
              - id: 10
                composer: false
                name: Brit-Pop
              - id: 514
                composer: false
                name: British Invasion
              - id: 3
                composer: false
                name: Classic Rock
              - id: 1036
                composer: false
                name: College Rock
              - id: 515
                composer: false
                name: Commercial Alternative
              - id: 1037
                composer: false
                name: Contemporary Singer/Songwriter
              - id: 9
                composer: false
                name: Country-Rock
              - id: 162
                composer: false
                name: Drone
              - id: 760
                composer: false
                name: Duro
              - id: 516
                composer: false
                name: Folk Rock
              - id: 517
                composer: false
                name: Foreign Language Rock
              - id: 11
                composer: false
                name: Funk Rock
              - id: 518
                composer: false
                name: Garage Rock
              - id: 16
                composer: false
                name: Glam Rock
              - id: 21
                composer: false
                name: Goth
              - id: 519
                composer: false
                name: Grunge
              - id: 520
                composer: false
                name: Hard Rock
              - id: 7
                composer: false
                name: Indie Rock
              - id: 521
                composer: false
                name: Industrial Rock
              - id: 522
                composer: false
                name: Instrumental Rock
              - id: 14
                composer: false
                name: Jam Band
              - id: 523
                composer: false
                name: Jam Rock
              - id: 524
                composer: false
                name: Krautrock
              - id: 525
                composer: false
                name: Live Rock
              - id: 8
                composer: false
                name: Lo-fi
              - id: 526
                composer: false
                name: Math Rock
              - id: 126
                composer: false
                name: Modern Rock
              - id: 527
                composer: false
                name: New Wave
              - id: 528
                composer: false
                name: Noise-Rock
              - id: 529
                composer: false
                name: Oldies
              - id: 763
                composer: false
                name: Other
              - id: 125
                composer: false
                name: Pop-Rock
              - id: 6
                composer: false
                name: Post-Punk
              - id: 48
                composer: false
                name: Post-Rock / Experimental
              - id: 19
                composer: false
                name: Power-Pop
              - id: 1038
                composer: false
                name: Prog-Rock/Art Rock
              - id: 20
                composer: false
                name: Progressive
              - id: 530
                composer: false
                name: Proto-Punk
              - id: 12
                composer: false
                name: Psychedelic Rock
              - id: 761
                composer: false
                name: Psychobilly
              - id: 762
                composer: false
                name: Radical
              - id: 1039
                composer: false
                name: Rock
              - id: 531
                composer: false
                name: Rock 'n' Roll
              - id: 532
                composer: false
                name: Rock Singer/Songwriter
              - id: 13
                composer: false
                name: Rockabilly
              - id: 2
                composer: false
                name: Roots Rock
              - id: 533
                composer: false
                name: Soft Rock
              - id: 4
                composer: false
                name: Southern Rock
              - id: 17
                composer: false
                name: Surf
              - id: 534
                composer: false
                name: Tex-Mex
              - id: 764
                composer: false
                name: Urbano
          description: OK
      description: |
        Get the subgenre options for a given $genreId.
  '/public/product/genres/{genreId}/subgenres':
    get:
      tags: ['product']
      parameters:
        - in: path
          name: genreId
          required: true
          type: string
        - description: UUID
          in: header
          name: Correlation-Id
          required: false
          type: string
      responses:
        '200':
          examples:
            default:
              - id: 511
                composer: false
                name: 80's
              - id: 512
                composer: false
                name: Adult Alternative
              - id: 513
                composer: false
                name: Adult Contemporary
              - id: 129
                composer: false
                name: Alternative
              - id: 1034
                composer: false
                name: American Trad Rock
              - id: 1
                composer: false
                name: Americana
              - id: 1035
                composer: false
                name: Arena Rock
              - id: 5
                composer: false
                name: Boogie Rock
              - id: 10
                composer: false
                name: Brit-Pop
              - id: 514
                composer: false
                name: British Invasion
              - id: 3
                composer: false
                name: Classic Rock
              - id: 1036
                composer: false
                name: College Rock
              - id: 515
                composer: false
                name: Commercial Alternative
              - id: 1037
                composer: false
                name: Contemporary Singer/Songwriter
              - id: 9
                composer: false
                name: Country-Rock
              - id: 162
                composer: false
                name: Drone
              - id: 760
                composer: false
                name: Duro
              - id: 516
                composer: false
                name: Folk Rock
              - id: 517
                composer: false
                name: Foreign Language Rock
              - id: 11
                composer: false
                name: Funk Rock
              - id: 518
                composer: false
                name: Garage Rock
              - id: 16
                composer: false
                name: Glam Rock
              - id: 21
                composer: false
                name: Goth
              - id: 519
                composer: false
                name: Grunge
              - id: 520
                composer: false
                name: Hard Rock
              - id: 7
                composer: false
                name: Indie Rock
              - id: 521
                composer: false
                name: Industrial Rock
              - id: 522
                composer: false
                name: Instrumental Rock
              - id: 14
                composer: false
                name: Jam Band
              - id: 523
                composer: false
                name: Jam Rock
              - id: 524
                composer: false
                name: Krautrock
              - id: 525
                composer: false
                name: Live Rock
              - id: 8
                composer: false
                name: Lo-fi
              - id: 526
                composer: false
                name: Math Rock
              - id: 126
                composer: false
                name: Modern Rock
              - id: 527
                composer: false
                name: New Wave
              - id: 528
                composer: false
                name: Noise-Rock
              - id: 529
                composer: false
                name: Oldies
              - id: 763
                composer: false
                name: Other
              - id: 125
                composer: false
                name: Pop-Rock
              - id: 6
                composer: false
                name: Post-Punk
              - id: 48
                composer: false
                name: Post-Rock / Experimental
              - id: 19
                composer: false
                name: Power-Pop
              - id: 1038
                composer: false
                name: Prog-Rock/Art Rock
              - id: 20
                composer: false
                name: Progressive
              - id: 530
                composer: false
                name: Proto-Punk
              - id: 12
                composer: false
                name: Psychedelic Rock
              - id: 761
                composer: false
                name: Psychobilly
              - id: 762
                composer: false
                name: Radical
              - id: 1039
                composer: false
                name: Rock
              - id: 531
                composer: false
                name: Rock 'n' Roll
              - id: 532
                composer: false
                name: Rock Singer/Songwriter
              - id: 13
                composer: false
                name: Rockabilly
              - id: 2
                composer: false
                name: Roots Rock
              - id: 533
                composer: false
                name: Soft Rock
              - id: 4
                composer: false
                name: Southern Rock
              - id: 17
                composer: false
                name: Surf
              - id: 534
                composer: false
                name: Tex-Mex
              - id: 764
                composer: false
                name: Urbano
          description: OK
      description: |
        Get the subgenre options for a given $genreId.
  /product/types:
    get:
      tags: ['product']
      parameters:
        - description: UUID
          in: header
          name: Correlation-Id
          required: false
          type: string
      responses:
        '200':
          examples:
            default:
              - name: New
                display_name: New Release
              - name: Catalog
                display_name: Catalog
          description: OK
      description: >
        Get the available options for product type. These values come from
        `releases`.`new_release` in `art_relations` database.
  /project:
    get:
      tags: ['project']
      parameters:
        - in: query
          name: project_code
          required: false
          type: string
        - description: UUID
          in: header
          name: Correlation-Id
          required: false
          type: string
        - description: Grass account type
          in: header
          name: Grass-Account-Type
          pattern: ^(vendor|subaccount)$
          required: false
          type: string
        - description: Grass account id
          in: header
          name: Grass-Account-Id
          pattern: ^\d+$
          required: false
          type: string
      responses:
        '200':
          description: >
            HTTP 200 OK

            ---------------

            JSON object representing the project plus the number of
            products in the project (product_count).
        '404':
          description: |
            HTTP 404 Not found
            --------------------
            Record was not found
        '400':
            description: |
                HTTP 400 Bad Request
                --------------------
                Parameters not included.
      description: Retrieve basic data for a single project by parameter.
    post:
      tags: ['project']
      parameters:
        - description: UUID
          in: header
          name: Correlation-Id
          required: false
          type: string
        - description: Grass account type
          in: header
          name: Grass-Account-Type
          pattern: ^(vendor|subaccount)$
          required: true
          type: string
        - description: Grass account id
          in: header
          name: Grass-Account-Id
          pattern: ^\d+$
          required: true
          type: string
        - in: header
          name: Content-Type
          pattern: ^application/json$
          required: true
          type: string
        - in: body
          name: body
          required: true
          schema:
            $ref: '#/definitions/ProjectPost'
      responses:
        '201':
          description: |
            HTTP 201 OK
            ---------------
            JSON object representing the newly-created project.
        '400':
          description: >
            HTTP 400 Bad Request

            --------------------

            The body contains the fields that did not pass validation with a
            validation context message.
      description: Create a new project.
  '/project/{projectId}':
    get:
      tags: ['project']
      parameters:
        - in: path
          name: projectId
          required: true
          type: string
        - description: UUID
          in: header
          name: Correlation-Id
          required: false
          type: string
        - description: Grass account type
          in: header
          name: Grass-Account-Type
          pattern: ^(vendor|subaccount)$
          required: false
          type: string
        - description: Grass account id
          in: header
          name: Grass-Account-Id
          pattern: ^\d+$
          required: false
          type: string
      responses:
        '200':
          description: >
            HTTP 200 OK

            ---------------

            JSON object representing the updated project plus the number of
            products in the project (product_count).
        '404':
          description: |
            HTTP 404 Not found
            --------------------
            Record was not found
      description: Retrieve basic data for a single project.
    put:
      tags: ['project']
      parameters:
        - in: path
          name: projectId
          required: true
          type: string
        - description: UUID
          in: header
          name: Correlation-Id
          required: false
          type: string
        - description: Grass account type
          in: header
          name: Grass-Account-Type
          pattern: ^(vendor|subaccount)$
          required: true
          type: string
        - description: Grass account id
          in: header
          name: Grass-Account-Id
          pattern: ^\d+$
          required: true
          type: string
        - in: header
          name: Content-Type
          pattern: ^application/json$
          required: true
          type: string
        - in: body
          name: body
          required: true
          schema:
            $ref: '#/definitions/ProjectProjectIdPut'
      responses:
        '200':
          examples:
            default:
              project_id: 136
              project_code: test_project_code
              project_name: test_project_name_updated
              vendor_id: 12353
              vendor_name: 'Bighit'
              subaccount_id: 0
              subaccount_name: 'A Subaccount'
              created_date_utc: '2016-03-10 18:14:36.418956Z'
              updated_date_utc: '2016-03-10 18:27:29.171495Z'
              product_count: 0
              description: test project description
              deletions: 'N'
          description: >
            HTTP 200 OK

            ---------------

            JSON object representing the updated project plus the number of
            products in the project (product_count).
        '400':
          examples:
            default:
              message:
                project_name: None is not of type 'string'
                project_code: None is not of type 'string'
              code: validation_error
          description: >
            HTTP 400 Bad Request

            --------------------

            The body contains the fields that did not pass validation with a
            validation context message.
      description: >-
        Update an existing project. Project_id is the unique identifier for a
        project and is automatically generated by the database.
  '/project/{projectId}/document':
    get:
      tags: ['project']
      consumes:
      - application/json
      description: Get a fully-hydrated document-store representation of a project.
      parameters:
      - name: projectId
        in: path
        required: true
        type: string
      - name: Correlation-Id
        description: UUID
        in: header
        required: false
        type: string
      - name: Grass-Account-Type
        in: header
        description: Grass account type.
        enum: ["vendor", "subaccount"]
        type: string
        required: false
      - name: Grass-Account-Id
        in: header
        description: Grass account id.
        pattern: ^\d+$
        type: string
        required: false
      - name: Orchard-User-Id
        in: header
        description: Orchard User Id
        type: string
        required: false
      responses:
        200:
          description: |
            HTTP 200 OK
            -----------
            Return the JSON document of the project.
          schema:
            $ref: "#/definitions/ProjectDocumentResponse"
        404:
          description: |
            HTTP 404 Not Found
            ------------------
            The project does not exist.
  '/project/{projectId}/product/imprints':
    get:
      tags: ['project']
      parameters:
        - in: path
          name: projectId
          required: true
          type: string
        - description: UUID
          in: header
          name: Correlation-Id
          required: false
          type: string
        - description: Grass account type
          in: header
          name: Grass-Account-Type
          pattern: ^(vendor|subaccount)$
          required: false
          type: string
        - description: Grass account id
          in: header
          name: Grass-Account-Id
          pattern: ^\d+$
          required: false
          type: string
      responses:
        '200':
          examples:
            default:
              - id: Cantora Records
                name: Cantora Records
              - id: Full Effect Records
                name: Full Effect Records
              - id: Ibex Moon P&D
                name: Ibex Moon P&D
              - id: Invisible DJ
                name: Invisible DJ
              - id: Knitting Factory
                name: Knitting Factory
              - id: MRI
                name: MRI
              - id: Megaforce
                name: Megaforce
              - id: Partisan Records
                name: Partisan Records
              - id: Transdreamer
                name: Transdreamer
              - id: Trippin N' Rhythm Records
                name: Trippin N' Rhythm Records
          description: OK
      description: |
        Get the list of imprint options for products belonging to
        the project with id $projectId
  '/project/{projectId}/product/{productId}':
    get:
      tags: ['project']
      parameters:
        - in: path
          name: projectId
          required: true
          type: string
        - in: path
          name: productId
          required: true
          type: string
        - description: UUID
          in: header
          name: Correlation-Id
          required: false
          type: string
        - description: Grass account type
          in: header
          name: Grass-Account-Type
          pattern: ^(vendor|subaccount)$
          required: false
          type: string
        - description: Grass account id
          in: header
          name: Grass-Account-Id
          pattern: ^\d+$
          required: false
          type: string
      responses:
        '200':
          examples:
            default:
              artist_names:
                - Mike Jones
              product_type: Music
              product_type_id: 1
              product_id: 1001
              release_name: Something Strange Here
              release_status: error_correction
              display_upc: '888831283041'
              upc: 888831283041
              version: Deluxe
              distribution_format:
                id: 1
                name: DIGITAL
                context: digital
              format: Single
              not_for_distribution: 'N'
          description: >
            HTTP 200 OK

            ---------------

            If the project and product ids are valid: JSON object representing
            the product.
        '404':
          examples:
            default:
              code: not_found_error
              message: Unable to find product_id 0
          description: |
            HTTP 404 Not found
            --------------------
            Record was not found
      description: >-
        Retrieve basic data for a single digital or physical product for a
        project.
  '/project/{projectId}/products':
    get:
      tags: ['project']
      parameters:
        - in: path
          name: projectId
          required: true
          type: string
        - description: UUID
          in: header
          name: Correlation-Id
          required: false
          type: string
        - description: Grass account type
          in: header
          name: Grass-Account-Type
          pattern: ^(vendor|subaccount)$
          required: false
          type: string
        - description: Grass account id
          in: header
          name: Grass-Account-Id
          pattern: ^\d+$
          required: false
          type: string
      responses:
        '200':
          examples:
            default:
              items:
                - artist_names:
                    - Mike Jones
                  product_type: Music
                  product_type_id: 1
                  product_id: 1001
                  release_name: Something Strange Here
                  release_status: error_correction
                  display_upc: '888831283041'
                  upc: 888831283041
                  version: Deluxe
                  distribution_format:
                    id: 1
                    name: DIGITAL
                    context: digital
                  format: EP
                  not_for_distribution: 'N'
                - artist_names:
                    - Mike Jones
                  product_type: Music
                  product_type_id: 1
                  product_id: 1002
                  release_name: Something Strange Here
                  release_status: action_required
                  display_upc: '889845667810'
                  upc: 889845667810
                  version: Unremarkable
                  distribution_format:
                    id: 2
                    name: CD
                    context: physical
                  format: Single
                  not_for_distribution: 'N'
                - artist_names:
                    - Mike Jones
                  product_type: Music
                  product_type_id: 1
                  product_id: 1003
                  release_name: Something Strange Here
                  release_status: transfer_to_content
                  display_upc: '889845667872'
                  upc: 889845667872
                  version: Target Special Edition
                  distribution_format:
                    id: 1
                    name: DIGITAL
                    context: digital
                  format: Full Length
                  not_for_distribution: 'N'
          description: |
            HTTP 200 OK
            ---------------
            JSON List of product objects associated with the project_id.
        '404':
          examples:
            default:
              code: not_found_error
              message: Unable to find product_id 0
          description: |
            HTTP 404 Not found
            --------------------
            Record was not found
      description: >-
        Get a list of digital and physical products for a project, or empty list
        if no product.
  /projects:
    get:
      tags: ['project']
      parameters:
        - description: 'Project to start at (integer, where first record is 0).'
          in: query
          name: offset
          required: false
          type: integer
        - default: 50
          description: Number of projects to retrieve in single request (integer)
          in: query
          name: limit
          required: false
          type: integer
        - description: Subaccount id to filter by
          in: query
          name: subaccount_id
          required: false
          type: integer
        - description: UUID
          in: header
          name: Correlation-Id
          required: false
          type: string
        - description: Grass account type
          in: header
          name: Grass-Account-Type
          pattern: ^(vendor|subaccount)$
          required: true
          type: string
        - description: Grass account id
          in: header
          name: Grass-Account-Id
          pattern: ^\d+$
          required: true
          type: string
      responses:
        '200':
          examples:
            default:
              pagination:
                offset: 0
                limit: 50
                total_records: 1
              items:
                - project_id: 136
                  project_code: test_project_code
                  project_name: test_project_name_updated
                  vendor_id: 12353
                  vendor_name: 'A vendor name'
                  subaccount_id: 1
                  subaccount_name: 'A subaccount name'
                  created_date_utc: '2016-03-10 18:14:36.418956Z'
                  updated_date_utc: '2016-03-10 18:27:29.171495Z'
                  product_count: 0
                  description: test project description
                  subaccount:
                    subaccount_name: A Label Name
                    description: Description of subaccount
                    subaccount_id: 1
                    vendor_id: 12353
          description: >
            HTTP 200 OK

            ---------------

            JSON object containing a list of projects (items) and pagination
            info. Project will have subaccount data if there is a subaccount.
        '404':
          description: |
            HTTP 404 Not found
            --------------------
            Projects not found
      description: >-
        Retrieve a paginated list of projects for the logged-in user. Pagination
        info will be used to retrieve the next subset of projects for the user.
  '/report/{projectId}':
    get:
      tags: ['report']
      parameters:
        - in: path
          name: projectId
          required: true
          type: string
        - description: UUID
          in: header
          name: Correlation-Id
          required: false
          type: string
        - description: Grass account type
          in: header
          name: Grass-Account-Type
          pattern: ^(vendor|subaccount)$
          required: false
          type: string
        - description: Grass account id
          in: header
          name: Grass-Account-Id
          pattern: ^\d+$
          required: false
          type: string
        - description: Orchard user id
          in: header
          name: Orchard-User-Id
          pattern: '^(oa:|alw:)'
          required: false
          type: string
      responses:
        '200':
          examples:
            default:
              download_url: 'https://s3.amazonaws.com/some-bucket/some-csv.csv'
              timestamp: '2016-12-21T12:08:28.402480'
          description: >
            HTTP 200 OK

            ---------------

            JSON object containing a tokenized s3 link to project metadata and
            timestamp when metadata was generated.
        '404':
          description: |
            HTTP 404 Not found
            --------------------
            Report for this project doesn't exist.
      description: >-
        Get tokenized s3 link to project metadata in .csv format for provided
        project id.
    post:
      tags: ['report']
      parameters:
        - in: path
          name: projectId
          required: true
          type: string
        - description: UUID
          in: header
          name: Correlation-Id
          required: false
          type: string
        - description: Grass account type
          in: header
          name: Grass-Account-Type
          pattern: ^(vendor|subaccount)$
          required: false
          type: string
        - description: Grass account id
          in: header
          name: Grass-Account-Id
          pattern: ^\d+$
          required: false
          type: string
        - description: Orchard user id
          in: header
          name: Orchard-User-Id
          pattern: '^(oa:|alw:)'
          required: false
          type: string
      responses:
        '200':
          examples:
            default:
              project_id: 123
          description: >
            HTTP 200 OK

            ---------------

            JSON object containing id of project, for which report generation
            has been started.
        '400':
          description: |
            HTTP 400 Bad Request
            --------------------
            Invalid data was provided in request.
        '403':
          examples:
            default:
              status: 403
              errors:
                code: FORBIDDEN
                message: Project id 456 does not belong to account 1923
          description: >
            HTTP 403 Forbidden

            --------------------

            Project with provided id doesn't belong to account which tried to
            initiate generation.
        '404':
          examples:
            default:
              status: 404
              errors:
                code: INVALID_PROJECT_ID
                message: Project id 456 does not exist
          description: |
            HTTP 404 Not found
            --------------------
            Project with provided id doesn't exist.
      description: >-
        Initialize the generation metadata in .csv format for provided project
        id.
  /transfer/jobs:
    get:
      tags: ['transfer']
      description: >-
        List product transfer jobs scoped to the caller's Grass vendor
        account. Soft-deleted jobs are excluded.
      parameters:
        - description: UUID
          in: header
          name: Correlation-Id
          required: false
          type: string
        - description: Grass account type
          in: header
          name: Grass-Account-Type
          pattern: ^(vendor|subaccount)$
          required: true
          type: string
        - description: Grass account id
          in: header
          name: Grass-Account-Id
          pattern: ^\d+$
          required: true
          type: string
        - in: query
          name: status
          required: false
          type: string
          enum: [QUEUED, PROCESSING, COMPLETED, FAILED]
        - in: query
          name: originating_vendor_id
          required: false
          type: integer
        - in: query
          name: destination_vendor_id
          required: false
          type: integer
        - in: query
          name: project_id
          required: false
          type: integer
        - in: query
          name: limit
          required: false
          type: integer
          default: 100
        - in: query
          name: offset
          required: false
          type: integer
          default: 0
      responses:
        '200':
          description: |
            HTTP 200 OK
            ---------------
            JSON object with `items` (list of job dicts) and `total_count`.
        '400':
          description: HTTP 400 Bad Request
        '403':
          description: HTTP 403 Forbidden
  /transfer/job:
    post:
      tags: ['transfer']
      description: >-
        Create a new transfer job. A product_transfer_history row is
        snapshotted for every release in the project, with
        destination_artist_id NULL until the SFN populates it.
      parameters:
        - description: UUID
          in: header
          name: Correlation-Id
          required: false
          type: string
        - description: Grass account type
          in: header
          name: Grass-Account-Type
          pattern: ^(vendor|subaccount)$
          required: true
          type: string
        - description: Grass account id
          in: header
          name: Grass-Account-Id
          pattern: ^\d+$
          required: true
          type: string
        - in: header
          name: Content-Type
          pattern: ^application/json$
          required: true
          type: string
        - in: body
          name: body
          required: true
          schema:
            $ref: '#/definitions/TransferJobPost'
      responses:
        '201':
          description: |
            HTTP 201 Created
            ---------------
            The newly-created job, including its snapshotted products list.
        '400':
          description: HTTP 400 Bad Request
        '401':
          description: HTTP 401 Unauthorized (missing or invalid JWT identity)
        '403':
          description: HTTP 403 Forbidden (caller does not own the project)
        '404':
          description: HTTP 404 Not Found (project does not exist)
  '/transfer/job/{jobId}':
    get:
      tags: ['transfer']
      description: Return a single transfer job with nested products.
      parameters:
        - in: path
          name: jobId
          required: true
          type: integer
        - description: UUID
          in: header
          name: Correlation-Id
          required: false
          type: string
        - description: Grass account type
          in: header
          name: Grass-Account-Type
          pattern: ^(vendor|subaccount)$
          required: true
          type: string
        - description: Grass account id
          in: header
          name: Grass-Account-Id
          pattern: ^\d+$
          required: true
          type: string
      responses:
        '200':
          description: HTTP 200 OK
        '403':
          description: HTTP 403 Forbidden
        '404':
          description: HTTP 404 Not found
    patch:
      tags: ['transfer']
      description: >-
        SFN-only. Partially update mutable fields on a transfer job.
        Accepted fields: status (PROCESSING, COMPLETED, FAILED),
        failure_reason (required when status=FAILED), revenue_cutoff_date,
        transfer_completed_on (auto-set to now when status=COMPLETED if
        omitted), sfn_execution_arn. Jobs in COMPLETED or FAILED status
        are terminal and cannot be updated. Service-to-service: requires
        a valid JWT identity but no Grass headers.
      parameters:
        - in: path
          name: jobId
          required: true
          type: integer
        - description: UUID
          in: header
          name: Correlation-Id
          required: false
          type: string
        - in: header
          name: Content-Type
          pattern: ^application/json$
          required: true
          type: string
        - in: body
          name: body
          required: true
          schema:
            $ref: '#/definitions/TransferJobPatch'
      responses:
        '200':
          description: HTTP 200 OK (updated job dict)
        '400':
          description: HTTP 400 Bad Request (invalid field or terminal-state job)
        '401':
          description: HTTP 401 Unauthorized
        '404':
          description: HTTP 404 Not found
    delete:
      tags: ['transfer']
      description: >-
        Soft-delete a QUEUED transfer job. The soft-delete cascades to all
        of the job's product_transfer_history rows. Jobs in any other
        status (PROCESSING, COMPLETED, FAILED) cannot be deleted.
      parameters:
        - in: path
          name: jobId
          required: true
          type: integer
        - description: UUID
          in: header
          name: Correlation-Id
          required: false
          type: string
        - description: Grass account type
          in: header
          name: Grass-Account-Type
          pattern: ^(vendor|subaccount)$
          required: true
          type: string
        - description: Grass account id
          in: header
          name: Grass-Account-Id
          pattern: ^\d+$
          required: true
          type: string
      responses:
        '204':
          description: HTTP 204 No Content (soft-deleted)
        '400':
          description: HTTP 400 Bad Request (job is not QUEUED)
        '401':
          description: HTTP 401 Unauthorized
        '403':
          description: HTTP 403 Forbidden
        '404':
          description: HTTP 404 Not found
  '/transfer/job/{jobId}/products':
    get:
      tags: ['transfer']
      description: >-
        Return product_transfer_history rows for a job. Soft-deleted
        snapshot rows are excluded.
      parameters:
        - in: path
          name: jobId
          required: true
          type: integer
        - description: UUID
          in: header
          name: Correlation-Id
          required: false
          type: string
        - description: Grass account type
          in: header
          name: Grass-Account-Type
          pattern: ^(vendor|subaccount)$
          required: true
          type: string
        - description: Grass account id
          in: header
          name: Grass-Account-Id
          pattern: ^\d+$
          required: true
          type: string
      responses:
        '200':
          description: HTTP 200 OK
        '403':
          description: HTTP 403 Forbidden
        '404':
          description: HTTP 404 Not found
    patch:
      tags: ['transfer']
      description: >-
        SFN-only. Bulk-set destination_artist_id on snapshot rows for a
        job. The SFN can batch all release updates for a job into a
        single call. All updates apply atomically: if any release_id in
        the batch has no live snapshot row for the job, the whole batch
        is rejected (404) and no rows are updated. The SFN uses
        destination_artist_id NULL/NOT NULL as its own idempotency
        check; calling with already-populated values is a no-op from
        the SFN's perspective. Service-to-service: requires a valid JWT
        identity but no Grass headers (the lambdas do not act on behalf
        of an end user).
      parameters:
        - in: path
          name: jobId
          required: true
          type: integer
        - description: UUID
          in: header
          name: Correlation-Id
          required: false
          type: string
        - in: header
          name: Content-Type
          pattern: ^application/json$
          required: true
          type: string
        - in: body
          name: body
          required: true
          schema:
            $ref: '#/definitions/SetDestinationArtists'
      responses:
        '200':
          description: HTTP 200 OK (rows updated)
        '400':
          description: HTTP 400 Bad Request
        '401':
          description: HTTP 401 Unauthorized
        '403':
          description: HTTP 403 Forbidden
        '404':
          description: HTTP 404 Not found (job or any snapshot row missing)
  '/transfer/job/{jobId}/execute-content-transfer':
    post:
      tags: ['transfer']
      description: >-
        SFN-only. Execute Step 5 of the content-transfer workflow: re-parents
        the project, its releases, and product_video rows to the destination
        vendor/subaccount/artist in a single transaction. Requires that all
        product_transfer_history rows for the job have destination_artist_id
        populated (EnsureDestinationArtists must run first). Gated by the
        project_transfer.execute_batch action (transfer_operator derived role).
        Service-to-service: requires a valid JWT identity but no Grass headers.
      parameters:
        - in: path
          name: jobId
          required: true
          type: integer
        - description: UUID
          in: header
          name: Correlation-Id
          required: false
          type: string
      responses:
        '200':
          description: HTTP 200 OK (transfer applied; returns updated job dict)
        '400':
          description: HTTP 400 Bad Request (no products found for job)
        '401':
          description: HTTP 401 Unauthorized (missing or invalid JWT identity)
        '403':
          description: HTTP 403 Forbidden
        '404':
          description: HTTP 404 Not Found (job does not exist)
        '422':
          description: >-
            HTTP 422 Unprocessable Entity (one or more releases are missing
            destination_artist_id; EnsureDestinationArtists must run first)
  /transfer/batch/execute:
    post:
      tags: ['transfer']
      description: >-
        Trigger the Step Functions execution that processes all QUEUED
        transfer jobs. Backs the operator "Process all jobs" button. Gated
        by the project_transfer.execute_batch action, which maps to the
        any-tenant transfer_operator derived role. The SFN trigger itself
        is not yet implemented; this endpoint currently returns 501 once
        authorization succeeds, until the state machine ARN is provisioned.
      parameters:
        - description: UUID
          in: header
          name: Correlation-Id
          required: false
          type: string
      responses:
        '401':
          description: HTTP 401 Unauthorized
        '403':
          description: HTTP 403 Forbidden
        '501':
          description: HTTP 501 Not Implemented
  '/transfer/job/{jobId}/attachments':
    get:
      tags: ['transfer']
      description: >-
        SFN-only. Resolve UPCs and ISRCs for every release attached to
        the transfer job. Used by the accounting lambda (Step 7) to drive
        bulk-remove on the originating account's contract terms and
        bulk-add on the destination contracts in ows-royalties. UPCs are
        returned as strings (CAST of bigint releases.upc; releases with
        upc = 0 are excluded). ISRCs come from art_relations.track joined
        on release_id. Gated by the project_transfer.execute_batch action
        (transfer_operator derived role). Service-to-service: no Grass
        headers required.
      parameters:
        - in: path
          name: jobId
          required: true
          type: integer
        - description: UUID
          in: header
          name: Correlation-Id
          required: false
          type: string
      responses:
        '200':
          description: |
            HTTP 200 OK. JSON object with two string lists: `upcs` and
            `isrcs`. Either list may be empty if the job has no matching
            releases or no tracks with non-null ISRCs.
        '401':
          description: HTTP 401 Unauthorized
        '403':
          description: HTTP 403 Forbidden
        '404':
          description: HTTP 404 Not Found
definitions:
  ProjectPost:
    additionalProperties: false
    description: Validate Incoming POST JSON
    properties:
      artist_id:
        description: Artist identifier for the project
        type: integer
      description:
        description: User-generated free-text description of the project
        type: string
      project_code:
        description: >-
          User-generated identifier for a project. This identifier is
          unique within a vendor_id/subaccount_id combination
        maxLength: 20
        type: string
      project_highlights:
        type: string
      project_name:
        description: User-generated free-text name of the project
        maxLength: 255
        type: string
      subaccount_id:
        description: >-
          Included only if user is a distributor acting on behalf of a
          subaccount
        type: integer
      subaccount_name:
        description: Name of the subaccount that the project belongs to
        maxLength: 255
        type: string
      vendor_id:
        description: Unique identifier for vendor owning project
        type: integer
      vendor_name:
        description: Name of the vendor that the project belongs to
        maxLength: 255
        type: string
    required:
      - project_code
      - project_name
      - artist_id
    title: Project Manager POST JSON Validation
    type: object
  ProjectProjectIdPut:
    additionalProperties: false
    description: Validate Incoming PUT JSON
    properties:
      artist_id:
        description: Artist identifier for the project
        type: integer
      description:
        description: User-generated free-text description of the project
        type: string
      project_code:
        description: >-
          User-generated identifier for a project. This identifier is
          unique within a vendor_id/subaccount_id combination
        maxLength: 20
        type: string
      project_highlights:
        type: string
      project_name:
        description: User-generated free-text name of the project
        maxLength: 255
        type: string
      subaccount_name:
        description: Name of the subaccount that the project belongs to
        maxLength: 255
        type: string
      vendor_name:
        description: Name of the vendor that the project belongs to
        maxLength: 255
        type: string
      deletions:
        description: deletion status of the project
        type: string
    title: Project Manager PUT JSON Validation
    type: object
  ProjectDocumentResponse:
    type: object
    properties:
      project_id:
        type: integer
        example: 1234
      project_code:
        type: string
        example: ABC123
      vendor_id:
        type: integer
        example: 7123
      vendor_name:
        type: string
        example: Bighit
      subaccount_id:
        type: integer
        example: 5656
      subaccount_name:
        type: string
        example: Bighit
      project_name:
        type: string
        example: Project Name
      created_date_utc:
        type: string
        example: "2018-01-01"
      updated_date_utc:
        type: string
        example: "2018-01-02"
      correlation_id:
        type: string
        example: 298374298374923847
      artist_id:
        type: integer
        example: 77777
      description:
        type: string
        example: description of the project
      artist_name:
        type: string
        example: Artist 555
        description: artist_info.name
      artist_description:
        type: string
        example: description of the artist
        description: artist_info.description
      artist_url:
        type: string
        example: https://artist555.com
        description: artist_info.url
      deletions:
        type: string
        example: "N"
  TransferJobPost:
    additionalProperties: false
    description: >-
      Body for POST /transfer/job. Originating vendor/subaccount are
      resolved server-side from the project's current owner; the caller's
      Grass account must own the project.
    type: object
    required:
      - project_id
      - destination_vendor_id
    properties:
      project_id:
        type: integer
        description: art_relations.project.project_id of the project being transferred
      destination_vendor_id:
        type: integer
        description: Destination vendor id
      destination_subaccount_id:
        type: integer
        x-nullable: true
      revenue_cutoff_date:
        type: string
        format: date
        x-nullable: true
        description: ISO date (YYYY-MM-DD); revenue earned on or before this date stays with the originating vendor.
  TransferJobPatch:
    additionalProperties: false
    description: >-
      Body for PATCH /transfer/job/{jobId}. At least one field must be
      provided. Jobs in COMPLETED or FAILED status are terminal and reject
      all updates.
    type: object
    properties:
      status:
        type: string
        enum: [PROCESSING, COMPLETED, FAILED]
        description: New status. QUEUED is not a valid transition via this endpoint.
      failure_reason:
        type: string
        x-nullable: true
        description: Required when status is FAILED.
      revenue_cutoff_date:
        type: string
        format: date
        x-nullable: true
        description: ISO date (YYYY-MM-DD).
      transfer_completed_on:
        type: string
        format: date-time
        x-nullable: true
        description: >-
          ISO datetime. Auto-set to now when status=COMPLETED and this
          field is omitted.
      sfn_execution_arn:
        type: string
        maxLength: 2048
        x-nullable: true
        description: ARN of the SFN execution managing this job.
  SetDestinationArtists:
    additionalProperties: false
    description: Body for PATCH /transfer/job/{jobId}/products (bulk)
    type: object
    required:
      - updates
    properties:
      updates:
        type: array
        minItems: 1
        items:
          additionalProperties: false
          type: object
          required:
            - release_id
            - destination_artist_id
          properties:
            release_id:
              type: integer
            destination_artist_id:
              type: integer
              description: Resolved or newly-created artist_id on the destination vendor.
securityDefinitions: {}
