openapi: 3.1.0
info:
  title: Dispositioning API
  description: Grade item conditions and assess return line item dispositions
  version: 'v1'
servers:
  - url: https://api.loopreturns.com/api/2026-10
    description: 2026-10 (Stable)
  - url: https://api.loopreturns.com/api/2026-07
    description: 2026-07
  - url: https://api.loopreturns.com/api/unstable
    description: Unstable (Preview)
tags:
  - name: Grade Items
  - name: Assess Dispositions
paths:
  /dispositioning/grade:
    summary: Conditions
    post:
      tags:
        - Grade Items
      summary: Grade Items
      operationId: gradeItems
      security:
        - api_key: []
      description: |
        Grade the condition of return line items.

        ### Required API key scope
        - Returns
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/GradeRequest'
      responses:
        "200":
          description: Success
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/GradeResponse'
        "401":
          description: Unauthorized
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/UnauthorizedResponse'
        "403":
          description: Forbidden — one or more line items do not belong to the authenticated shop.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ForbiddenResponse'
        "422":
          description: Unprocessable
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/UnprocessableResponse'
  /dispositioning/assess:
    summary: Dispositions
    post:
      tags:
        - Assess Dispositions
      summary: Assess Dispositions
      operationId: assessDispositions
      security:
        - api_key: []
      description: |
        Assess return line item dispositions.

        ### Required API key scope
        - Returns
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/AssessDispositionRequest'
      responses:
        "200":
          description: Success
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/AssessDispositionResponse'
        "401":
          description: Unauthorized
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/UnauthorizedResponse'
        "403":
          description: Forbidden — one or more line items do not belong to the authenticated shop.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ForbiddenResponse'
        "422":
          description: Unprocessable
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/UnprocessableResponse'
components:
  schemas:
    GradeResponse:
      type: array
      maxItems: 30
      items:
        $ref: '#/components/schemas/ItemCondition'
    GradeRequest:
      type: object
      required:
        - items
      properties:
        items:
          type: array
          minItems: 1
          maxItems: 30
          description: An array of items to grade.
          items:
            $ref: '#/components/schemas/ItemCondition'
    ItemCondition:
      type: object
      required:
        - line_item_id
        - description
      properties:
        line_item_id:
          type: integer
          example: 1
          description: The unique identifier associated with the line item.
        description:
          type: string
          maxLength: 255
          example: 'Grade A: No refurbishment needed'
          description: The description of the item's condition.
        condition_category:
          type: [object, "null"]
          description: >
            The condition of the returned item, represented as a category object. On grade requests,
            `subject` and `title` are required when this object is provided; `grade`, `category_name`,
            and `category_parent` are optional.

            **Breaking change (2026-10)**: This field changed from a string to an object in both
            requests and responses. Clients using API version `2026-10` or later must send an object
            with `subject` and `title` properties; a plain string returns `422`. The category is
            matched by `subject` and `title`, and a new category is created if no match exists.
            Clients on `2026-07` send and receive the legacy string, for example `grade_a`.
          example:
            subject: Item condition grade
            title: Grade A
            grade: grade_a
            category_name: grade_a
            category_parent: Grade
          properties:
            subject:
              type: [string, "null"]
              maxLength: 100
              description: The condition category subject.
            title:
              type: [string, "null"]
              maxLength: 100
              description: The condition category title.
            grade:
              type: [string, "null"]
              maxLength: 100
              description: The condition grade.
            category_name:
              type: [string, "null"]
              maxLength: 100
              description: The condition category name.
            category_parent:
              type: [string, "null"]
              maxLength: 100
              description: The parent condition category.
        return_processor:
          type: string
          maxLength: 100
          example: 'warehouse-operator@example.com'
          description: The email address of the warehouse partner used to process returns.
        note:
          type: string
          maxLength: 65535
          example: >
            This item is missing the original packaging.
            Light refurbishment required. Scuff marks on the back of the item.
          description: Any additional notes on the item's condition.
        images:
          type: array
          maxItems: 5
          description: An array of links to images of the item.
          items:
            $ref: '#/components/schemas/Image'
        inspected_at:
          type: string
          format: date-time
          example: '2024-03-31T23:59:59+00:00'
          description: >
            The date and time at which the item was inspected, in RFC 3339 (ISO 8601) format
            with a UTC offset (DATE_ATOM), e.g. 2024-03-31T23:59:59+00:00.
    Image:
      type: string
      format: uri
      maxLength: 2048
      example: 'https://example.com/image.jpg'
    AssessDispositionResponse:
      type: array
      maxItems: 30
      items:
        $ref: '#/components/schemas/Disposition'
    AssessDispositionRequest:
      type: object
      required:
        - items
      properties:
        items:
          description: An array of items to be dispositioned.
          type: array
          minItems: 1
          maxItems: 30
          items:
            $ref: '#/components/schemas/Disposition'
    Disposition:
      type: object
      required:
        - line_item_id
        - disposition_outcome
      properties:
        line_item_id:
          type: integer
          example: 1
          description: The unique identifier associated with the line item.
        disposition_outcome:
          type: string
          enum:
            - back_to_stock
            - resale_hold
            - recycle
            - donate
            - missing
          description: The final state of the returned item.
        return_processor:
          type: string
          maxLength: 100
          example: 'warehouse-operator@example.com'
          description: The email address of the warehouse partner used to process returns.
        note:
          type: string
          maxLength: 65535
          example: 'This item will be returned to stock after bagging and tagging.'
          description: Any additional notes on the item's final state.
        inspected_at:
          type: string
          format: date-time
          example: '2024-03-31T23:59:59+00:00'
          description: >
            The date and time at which the item was inspected, in RFC 3339 (ISO 8601) format
            with a UTC offset (DATE_ATOM), e.g. 2024-03-31T23:59:59+00:00.
    UnauthorizedResponse:
      type: object
      required:
        - errors
      properties:
        errors:
          type: string
          example: 'Unauthorized.'
    ForbiddenResponse:
      type: object
      properties:
        message:
          type: string
          example: 'This action is unauthorized.'
    UnprocessableResponse:
      type: object
      properties:
        message:
          type: string
          example: 'The items.0.images.0 must not be greater than 2048 characters.'
        errors:
          type: object
  securitySchemes:
    api_key:
      type: 'apiKey'
      name: 'X-Authorization'
      in: 'header'
