openapi: 3.1.0
info:
  title: Draft Returns API
  version: 'v1'
  description: |
    # Overview

    The Draft Returns API provides a **state-aware, HATEOAS-driven interface** for building returns.
    This API guides clients through the return creation process using hypermedia links that describe
    available actions at each step.

    ## HATEOAS Architecture

    Every response includes a `links` array containing available actions you can take based on the
    current state of the draft return. These links are:

    - **Self-describing**: Each link includes a description and field metadata
    - **State-aware**: Only valid actions for the current state are returned
    - **Discoverable**: Follow the links to build the return without hardcoding workflows

    ### Basic Workflow

    1. **Initialize** a draft return with order information
    2. **Review** the response to see available actions in the `links` array
    3. **Take action** by calling one of the provided link endpoints
    4. **Repeat** until the return is ready to submit

    The draft return is ready to submit when the `submit-draft-return` link (HAL-Forms: the
    `submit-draft-return` template) is present. Use it as the single readiness signal rather
    than working it out from other actions: Loop only offers it once every required step is
    complete.

    Each link in the `links` array provides:
    - `rel`: The relationship/action type
    - `href`: The URL to call
    - `method`: The HTTP method to use
    - `description`: Human-readable explanation of the action
    - `fields`: Array of required and optional fields with type information
    - `is_required`: Whether this action must be completed to progress

    Whether an action's link is present, and its `is_required` flag (HAL-Forms: the template
    and its `required` flag), describe only that one action, not the draft return as a whole.
    The only reliable signal that the draft return is ready to submit is the presence of the
    `submit-draft-return` link (HAL-Forms: the `submit-draft-return` template).

    ### Example Links Array

    ```json
    {
      "links": [
        {
          "rel": "add-returning-item",
          "href": "https://api.loopreturns.com/api/v1/draft-returns/123/returning-items",
          "method": "POST",
          "description": "Add a line item to the return",
          "fields": [
            {
              "name": "order_line_item_id",
              "type": "int",
              "description": "ID of the line item to return",
              "is_required": true
            }
          ],
          "is_required": true
        }
      ]
    }
    ```

    ## State Machine

    Draft returns progress through these states:

    ```
    created → finalize-items → items-finalized → submit → submitted
       ↓                              ↓
       ↓← ← unfinalize-items ← ← ← ← ↓
       ↓                              ↓
       └→ cancel → cancelled     expired
    ```

    ### States

    - **created**: Initial state where items are added and customer information is set
    - **items-finalized**: Items are locked in, credit type and return method can be selected
    - **submitted**: Terminal state - draft has been converted to an actual return
    - **cancelled**: Terminal state - draft was explicitly cancelled
    - **expired**: Terminal state - draft timed out due to inactivity

    ### Available Actions by State

    #### Created State

    When a draft return is in the `created` state, the following actions may be available in the `links` array:

    - `add-returning-item`: Add an item from the order to the return
    - `remove-returning-item`: Remove an item from the return
    - `set-returning-item-return-reason`: Set why an item is being returned
    - `set-returning-item-return-type`: Set the return type for an item. Send only a value from
      that item's link `allowed_values`
    - `add-returning-item-exchange-item`: Add an exchange product for a returning item
    - `add-returning-item-user-input`: Provide additional information requested by merchant
    - `remove-cart-item`: Remove an exchange or shop-now item
    - `set-customer`: Set customer email and name
    - `set-address`: Set return shipping address
    - `finalize-items`: Lock in item selections and proceed to return method selection
    - `cancel-draft-return`: Cancel this draft return

    #### Items-Finalized State

    When a draft return is in the `items-finalized` state, the following actions may be available:

    - `set-credit-type`: Choose how to receive the refund (refund, gift card, or exchange)
    - `set-processing-type`: Choose `regular` or `instant` processing. See Processing type below
    - `select-return-method`: Select the shipping method for the return
    - `add-payment-intent`: Attach a payment intent when the draft return requires a payment.
      Not offered when the shop has no usable Stripe connection.
    - `submit-draft-return`: Submit the draft and convert it to an actual return
    - `unfinalize-items`: Go back to add/remove items
    - `cancel-draft-return`: Cancel this draft return

    #### Terminal States

    When a draft return reaches a terminal state (`submitted`, `cancelled`, `expired`), no further
    actions are available and the `links` array will be empty.

    ## User input

    Each unanswered merchant question on a returning item has its own
    `add-returning-item-user-input` link. The link `prompt` is the question. After the shopper
    answers, the question is in `returning_items[].user_inputs[]` with the same `prompt`.

    Merchants can format a question with bold text, links, and more than one paragraph. Requests
    without the HAL Forms `Accept` header get `prompt` and `system_message` as plain text. If the
    merchant formatted the value, you get only the text before the first formatting change or new
    paragraph. Match on this text to find the question.

    To get the formatted HTML, send `Accept: application/prs.hal-forms+json`. The response then
    uses the HAL Forms format. The `unstable` version always uses the HAL Forms format.

    ## Processing type

    `draft_return.processing_type` is `regular` or `instant`. Every draft return starts as
    `regular`.

    In the `items-finalized` state, `context.processing_type_options` shows whether each
    processing type is available, and the amounts for Instant. To change the processing type,
    call the `set-processing-type` link and send only a value from its `allowed_values`.

    When the draft has an exchange item, Instant runs as Instant Exchange. It stays available
    even when the credit type is `refund`.

    ### Instant reset

    While the draft is in `items-finalized`, Loop checks again on every request (including
    `GET` and submit) whether Instant is still available. If it is not, Loop:

    - sets `draft_return.processing_type` to `regular`
    - removes the payment intent, so `draft_return.payment_intent` is `null`

    Before you submit, read `processing_type` and `payment_intent` in the latest response. If you
    still want Instant and it is available again, set it again and attach a new payment intent.

    `unfinalize-items` also sets `processing_type` back to `regular`.

    ## Payment

    A draft return can require a payment, for example when the shopper owes money after
    exchanging into a pricier item, or when `processing_type` is `instant`. Loop collects it
    through the shop's Stripe connection:

    - If the shop has a usable Stripe connection, the `add-payment-intent` link is offered and
      marked required. Call it before you submit.
    - If the shop has no usable Stripe connection, Loop cannot collect the payment. The
      `add-payment-intent` link is not offered, and `draft_return.requires_uncollectible_payment`
      is `true`. The draft return cannot be submitted in this state. To continue, change the
      draft so no payment is needed, for example by changing items or the return method.

    If Instant stops being available, Loop resets `processing_type` to `regular` and removes the
    payment intent, so `draft_return.payment_intent` comes back `null`. Check `processing_type`
    and `payment_intent` before you submit. If a payment is still needed, the
    `add-payment-intent` link is offered again.

    ## Workflow Examples

    These examples demonstrate how the `links` array evolves as a draft return progresses through states.

    ### Example 1: Simple Refund Return

    This example shows a complete workflow for returning a single item for a refund.

    #### Step 1: Initialize Draft Return

    **Request:**
    ```http
    POST /api/v1/draft-returns
    Content-Type: application/json

    {
      "order_name": "#1001",
      "secondary_input": "customer@example.com"
    }
    ```

    **Response:**
    ```json
    {
      "draft_return": {
        "id": 123,
        "state": "created",
        "currency": "USD",
        "returning_items": [],
        "cart_items": []
      },
      "context": {
        "order": {
          "id": 42,
          "original_payment_transactions": [
            {
              "type": "sale",
              "gateway": "shopify_payments",
              "amount": 2500,
              "currency": "USD",
              "brand": "visa",
              "last4": 4242
            }
          ],
          "line_items": [
            {
              "id": 74,
              "title": "Blue Shirt",
              "price": 2500
            }
          ]
        },
        "items_eligible_to_return": [
          {"order_line_item_id": 74}
        ]
      },
      "links": [
        {
          "rel": "add-returning-item",
          "href": "https://api.loopreturns.com/api/v1/draft-returns/123/returning-items",
          "method": "POST",
          "description": "Add a line item to the return",
          "fields": [
            {
              "name": "order_line_item_id",
              "type": "int",
              "description": "ID of the line item to return",
              "is_required": true
            }
          ],
          "is_required": true
        }
      ],
      "errors": []
    }
    ```

    **Key observations:**
    - State is `created`
    - `context.items_eligible_to_return` shows available items
    - `links` array contains `add-returning-item` action marked as required

    #### Step 2: Add Returning Item

    **Request:**
    ```http
    POST /api/v1/draft-returns/123/returning-items
    Content-Type: application/json

    {
      "order_line_item_id": 74
    }
    ```

    **Response:**
    ```json
    {
      "draft_return": {
        "id": 123,
        "state": "created",
        "returning_items": [
          {
            "order_line_item_id": 74,
            "reason": null
          }
        ]
      },
      "context": {
        "return_reasons": [
          {"id": 1, "name": "Too small"},
          {"id": 2, "name": "Changed mind"}
        ]
      },
      "links": [
        {
          "rel": "set-returning-item-return-reason-74",
          "href": "https://api.loopreturns.com/api/v1/draft-returns/123/returning-items/74/return-reason",
          "method": "POST",
          "description": "Set the return reason for this item",
          "fields": [
            {
              "name": "reason_id",
              "type": "int",
              "description": "ID of the return reason",
              "is_required": true
            }
          ],
          "is_required": true
        },
        {
          "rel": "finalize-items",
          "href": "https://api.loopreturns.com/api/v1/draft-returns/123/finalize-items",
          "method": "POST",
          "description": "Lock in item selections and proceed",
          "fields": [],
          "is_required": false
        }
      ],
      "errors": []
    }
    ```

    **Key observations:**
    - Item was added to `returning_items`
    - New link appeared: `set-returning-item-return-reason` (marked required)
    - `context.return_reasons` provides available reasons
    - `finalize-items` link is available but not required

    #### Step 3: Set Return Reason

    **Request:**
    ```http
    POST /api/v1/draft-returns/123/returning-items/74/return-reason
    Content-Type: application/json

    {
      "reason_id": 2,
      "comment": "The fit wasn't right"
    }
    ```

    **Response:**
    ```json
    {
      "draft_return": {
        "id": 123,
        "state": "created",
        "returning_items": [
          {
            "order_line_item_id": 74,
            "reason": {
              "id": 2,
              "name": "Changed mind",
              "comment": "The fit wasn't right"
            }
          }
        ]
      },
      "links": [
        {
          "rel": "finalize-items",
          "href": "https://api.loopreturns.com/api/v1/draft-returns/123/finalize-items",
          "method": "POST",
          "description": "Lock in item selections and proceed",
          "fields": [],
          "is_required": false
        }
      ],
      "errors": []
    }
    ```

    **Key observations:**
    - Return reason was added
    - No more required actions - can now finalize

    #### Step 4: Finalize Items

    **Request:**
    ```http
    POST /api/v1/draft-returns/123/finalize-items
    ```

    **Response:**
    ```json
    {
      "draft_return": {
        "id": 123,
        "state": "items-finalized",
        "selected_return_method": null,
        "credit_type": null
      },
      "context": {
        "return_methods": [
          {"id": 1, "name": "UPS Ground", "cost": 0},
          {"id": 2, "name": "USPS Priority", "cost": 0}
        ]
      },
      "links": [
        {
          "rel": "set-credit-type",
          "href": "https://api.loopreturns.com/api/v1/draft-returns/123/credit-type",
          "method": "POST",
          "description": "Choose how you want your refund",
          "fields": [
            {
              "name": "credit_type",
              "type": "enum",
              "description": "Type of credit",
              "allowed_values": ["refund", "gift", "exchange"],
              "is_required": true
            }
          ],
          "is_required": true
        },
        {
          "rel": "select-return-method",
          "href": "https://api.loopreturns.com/api/v1/draft-returns/123/return-method",
          "method": "POST",
          "description": "Select shipping method",
          "fields": [
            {
              "name": "return_method_id",
              "type": "int",
              "description": "ID of return method",
              "is_required": true
            }
          ],
          "is_required": true
        }
      ],
      "errors": []
    }
    ```

    **Key observations:**
    - **State changed to `items-finalized`**
    - `links` array completely changed - different actions available
    - Two required actions: set credit type and select return method
    - `context.return_methods` provides available shipping options

    #### Step 5: Set Credit Type

    **Request:**
    ```http
    POST /api/v1/draft-returns/123/credit-type
    Content-Type: application/json

    {
      "credit_type": "refund"
    }
    ```

    **Response:**
    ```json
    {
      "draft_return": {
        "id": 123,
        "state": "items-finalized",
        "credit_type": "refund"
      },
      "links": [
        {
          "rel": "select-return-method",
          "href": "https://api.loopreturns.com/api/v1/draft-returns/123/return-method",
          "method": "POST",
          "description": "Select shipping method",
          "fields": [
            {
              "name": "return_method_id",
              "type": "int",
              "is_required": true
            }
          ],
          "is_required": true
        }
      ],
      "errors": []
    }
    ```

    #### Step 6: Select Return Method

    **Request:**
    ```http
    POST /api/v1/draft-returns/123/return-method
    Content-Type: application/json

    {
      "return_method_id": 1
    }
    ```

    **Response:**
    ```json
    {
      "draft_return": {
        "id": 123,
        "state": "items-finalized",
        "credit_type": "refund",
        "selected_return_method": {
          "id": 1,
          "name": "UPS Ground",
          "type": "box-and-ship",
          "title": "UPS Ground"
        }
      },
      "links": [
        {
          "rel": "submit-draft-return",
          "href": "https://api.loopreturns.com/api/v1/draft-returns/123/submit",
          "method": "POST",
          "description": "Submit the return for processing",
          "fields": [],
          "is_required": false
        }
      ],
      "errors": []
    }
    ```

    **Key observations:**
    - All required actions completed
    - `submit-draft-return` link now available
    - Ready for final submission

    #### Step 7: Submit Draft Return

    **Request:**
    ```http
    POST /api/v1/draft-returns/123/submit
    ```

    **Response:**
    ```json
    {
      "draft_return": {
        "id": 123,
        "state": "submitted",
        "return_id": 456
      },
      "links": [],
      "errors": []
    }
    ```

    **Key observations:**
    - **State changed to `submitted` (terminal)**
    - `return_id` populated - draft converted to actual return
    - `links` array is empty - no further actions available

    ### Example 2: Exchange Return

    This example demonstrates returning an item and selecting an exchange product.

    #### Step 1-3: Initialize and Add Item

    (Same as Example 1, steps 1-3)

    #### Step 4: Set Return Type to Exchange

    **Request:**
    ```http
    POST /api/v1/draft-returns/123/returning-items/74/return-type
    Content-Type: application/json

    {
      "return_type": "exchange"
    }
    ```

    **Response:**
    ```json
    {
      "draft_return": {
        "id": 123,
        "state": "created",
        "returning_items": [
          {
            "order_line_item_id": 74,
            "return_type": "exchange"
          }
        ]
      },
      "context": {
        "cart_products": [
          {
            "id": 100,
            "title": "Red Shirt",
            "variants": [
              {"id": 501, "title": "Small", "price": 2500}
            ]
          }
        ]
      },
      "links": [
        {
          "rel": "add-returning-item-exchange-item-74",
          "href": "https://api.loopreturns.com/api/v1/draft-returns/123/returning-items/74/exchange-item",
          "method": "POST",
          "description": "Add exchange product for this item",
          "fields": [
            {
              "name": "variant_id",
              "type": "int",
              "description": "Product variant to exchange for",
              "is_required": true
            }
          ],
          "is_required": true
        }
      ],
      "errors": []
    }
    ```

    **Key observations:**
    - Return type set to `exchange`
    - `context.cart_products` provides available exchange products
    - New link appeared: `add-returning-item-exchange-item`

    #### Step 5: Add Exchange Item

    **Request:**
    ```http
    POST /api/v1/draft-returns/123/returning-items/74/exchange-item
    Content-Type: application/json

    {
      "variant_id": 501
    }
    ```

    **Response:**
    ```json
    {
      "draft_return": {
        "id": 123,
        "state": "created",
        "returning_items": [
          {
            "order_line_item_id": 74,
            "return_type": "exchange"
          }
        ],
        "cart_items": [
          {
            "id": 201,
            "variant_id": 501,
            "title": "Red Shirt",
            "variant_title": "Small",
            "price": 2500
          }
        ]
      },
      "links": [
        {
          "rel": "finalize-items",
          "href": "https://api.loopreturns.com/api/v1/draft-returns/123/finalize-items",
          "method": "POST",
          "fields": [],
          "is_required": false
        }
      ],
      "errors": []
    }
    ```

    **Key observations:**
    - Exchange item added to `cart_items`
    - Can now proceed to finalize

    #### Step 6-8: Finalize and Submit

    After finalizing, the workflow continues with:
    - Set credit type to `exchange`
    - Select return method
    - Submit draft return

    The response structure is the same as Example 1, steps 4-7.

servers:
  - url: https://api.loopreturns.com/api/2026-07
    description: 2026-07

components:
  schemas:
    DraftReturnMoney:
      type: object
      properties:
        amount:
          type: integer
          description: The monetary amount in minor units (e.g. cents).
        currencyCode:
          type: string
          description: The three-character ISO 4217 currency code.

    ProcessingTypeOptions:
      type: object
      description: |
        Which processing types the draft return can use.

        Present only in the `items-finalized` state. Omitted in other states.
      properties:
        required:
          type: boolean
          description: |
            `true` when the return policy requires Instant. In that case the `regular` option has
            `available: false` with `unavailability_reason: instant-required`.
          example: false
        options:
          type: array
          description: One entry for `regular` and one for `instant`.
          items:
            $ref: '#/components/schemas/ProcessingTypeOption'

    ProcessingTypeOption:
      type: object
      properties:
        type:
          type: string
          description: The processing type this entry describes.
          enum:
            - regular
            - instant
        available:
          type: boolean
          description: |
            Whether you can set this processing type now. Send only an available type to
            `set-processing-type`.

            When the draft has an exchange item, Instant runs as Instant Exchange and stays
            available even when the credit type is `refund`.
        unavailability_reason:
          type: [string, 'null']
          description: |
            Why this type is not available. `null` when `available` is `true`.

            - `not-enabled`: Instant is not turned on for this shop or return policy, or the shop
              cannot take the payment.
            - `not-applicable`: Instant does not apply to this draft, for example an in-store
              return, a return where every item is kept, or a return with nothing to charge.
            - `excluded`: An item in the draft is excluded from Instant.
            - `instant-required`: Only on `regular`. The return policy requires Instant.
          enum:
            - not-enabled
            - not-applicable
            - excluded
            - instant-required
            - null
        authorization_amount:
          description: |
            Only on an available `instant` option. The amount Loop holds (authorizes) on the
            shopper's payment method for Instant. `null` otherwise.
          oneOf:
            - $ref: '#/components/schemas/ProcessingTypeMoney'
            - type: 'null'
        charge_amount:
          description: |
            Only on an available `instant` option. The amount Loop charges for Instant. `null`
            otherwise.
          oneOf:
            - $ref: '#/components/schemas/ProcessingTypeMoney'
            - type: 'null'
        window_days:
          type: [integer, 'null']
          description: |
            Only on an available `instant` option. The Instant window, in days, from the return
            policy. `null` otherwise.
          example: 14
        hold_window_days:
          type: [integer, 'null']
          description: |
            Only on an available `instant` option when Instant applies to a refund rather than an
            exchange. The hold window, in days, from the return policy. `null` otherwise.
          example: null

    ProcessingTypeMoney:
      type: object
      properties:
        amount:
          type: integer
          description: The amount in minor units (e.g. cents).
          example: 5000
        currency_code:
          type: string
          description: The three-character ISO 4217 currency code.
          example: USD

  securitySchemes:
    api_key:
      type: apiKey
      in: header
      name: X-Authorization

  parameters:
    DraftReturnId:
      name: draft_return_id
      in: path
      description: The unique identifier of the draft return.
      required: true
      schema:
        type: integer

    ShopId:
      name: X-Shop-Id
      in: header
      description: |
        The unique identifier of the shop associated with the draft return.

        This header is not required, as the merchant's shop is identified by the API key present in the request.
      schema:
        type: integer

    LoopLocale:
      name: X-Loop-Locale
      in: header
      required: false
      description: |
        The shopper's locale: a two-letter language code with an optional two-letter region,
        for example `fr` or `fr-CA`.

        When the value is valid and product translations are enabled for the shop, the response includes translated
        product text in the operation's translated fields. Otherwise those fields are not populated.
      schema:
        type: string
        example: fr-CA

    ReturningItemId:
      name: returning_item_id
      in: path
      description: The unique identifier of the returning item.
      required: true
      schema:
        type: integer

    CartItemId:
      name: cart_item_id
      in: path
      description: The unique identifier of the cart item.
      required: true
      schema:
        type: integer

    UserInputId:
      name: user_input_id
      in: path
      description: The unique identifier of the user input answer.
      required: true
      schema:
        type: integer

  responses:
    UnauthorizedError:
      description: API key is missing or invalid.
      content:
        application/json:
          schema:
            type: object
            properties:
              errors:
                type: array
                items:
                  type: object
                  properties:
                    code:
                      type: string
                      enum: ['unauthorized']
                    message:
                      type: string
                      example: "Unauthorized."

    ValidationError:
      description: Validation error occurred.
      content:
        application/json:
          schema:
            type: object
            properties:
              errors:
                type: array
                items:
                  type: object
                  properties:
                    code:
                      type: string
                      enum: ['validation-failed']
                    message:
                      type: string
                      example: "Validation failed."

    DraftReturnResponse:
      description: Successful response with draft return data.
      content:
        application/json:
          schema:
            type: object
            properties:
              draft_return:
                type: object
                description: The draft return object.
                properties:
                  id:
                    type: integer
                    description: The unique identifier of the draft return.
                    example: 12345
                  return_id:
                    type: [integer, 'null']
                    description: The unique identifier of the return, if the draft return has been submitted.
                    example: 67890
                  state:
                    type: string
                    description: The current state of the draft return.
                    enum:
                      - "created"
                      - "items-finalized"
                      - "submitted"
                      - "cancelled"
                      - "expired"
                  currency:
                    type: string
                    description: The three-character ISO 4217 currency code.
                    examples:
                      - USD
                      - EUR
                  language:
                    type: string
                    description: The language code for the draft return.
                    example: "en"
                  credit_type:
                    type: [string, 'null']
                    description: The type of credit for the return.
                    enum:
                      - refund
                      - gift
                      - exchange
                      - null
                    example: null
                  processing_type:
                    type: string
                    description: |
                      How the return should be processed. Every draft return starts as `regular`.
                      Change it with the `set-processing-type` link.
                      `context.processing_type_options` shows which values are available.

                      While the draft is in `items-finalized`, Loop checks on every request whether
                      Instant is still available. If it is not, Loop sets `processing_type` to
                      `regular` and removes the payment intent, so `payment_intent` is `null`.
                      Check `processing_type` and `payment_intent` again before you submit.
                    enum:
                      - regular
                      - instant
                    example: "regular"
                  customer:
                    type: object
                    description: The customer information associated with the draft return.
                    properties:
                      email:
                        type: string
                        format: email
                        description: The email address of the customer.
                        example: "someone@test.com"
                  shipping_address:
                    type: object
                    description: The shipping address for the return.
                    properties:
                      name:
                        type: string
                        description: The full name of the recipient.
                        example: "Jane Doe"
                      company:
                        type: [string, 'null']
                        description: The company name at the address.
                        example: null
                      address1:
                        type: string
                        description: The primary address line.
                        example: "123 Main St"
                      address2:
                        type: [string, 'null']
                        description: The secondary address line.
                        example: "Apt 4"
                      city:
                        type: string
                        description: The city name.
                        example: "Chicago"
                      state:
                        type: string
                        description: The state or province name.
                        example: "Illinois"
                      zip:
                        type: string
                        description: The postal code.
                        example: "60622"
                      country:
                        type: string
                        description: The full country name.
                        example: "United States"
                      country_code:
                        type: string
                        description: The two-letter country code.
                        example: "US"
                      phone:
                        type: [string, 'null']
                        description: The phone number.
                        example: "555-555-5555"
                  returning_items:
                    type: array
                    description: The items being returned.
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                          description: The unique identifier of this returning item within the draft return.
                          example: 1
                        order_line_item_id:
                          type: integer
                          description: |
                            The unique identifier created by Loop of the order line item being returned.
                          example: 12346
                        return_type:
                          type: [string, 'null']
                          description: Whether this item is being returned for credit or exchange.
                          enum:
                            - credit
                            - exchange
                            - null
                          example: "credit"
                        resolution:
                          type: [string, 'null']
                          description: The final resolution for this item (computed based on return_type and
                            merchant actions).
                          enum:
                            - return
                            - keep
                            - donate
                            - reject
                            - exchange
                            - null
                          example: "return"
                        return_reason:
                          type: [object, 'null']
                          description: The return reason information.
                          properties:
                            name:
                              type: string
                              description: The name of the return reason.
                              example: "Item didn't fit"
                            comment:
                              type: [string, 'null']
                              description: Any additional comments about the return reason.
                              example: null
                        user_inputs:
                          type: array
                          description: Additional information requested by the merchant (e.g., questions about
                            item condition).
                          items:
                            type: object
                            properties:
                              id:
                                type: integer
                                description: The unique identifier of the user input.
                                example: 1
                              type:
                                type: string
                                description: The user input type.
                                example: "yes-no"
                              prompt:
                                type: string
                                description: |
                                  The merchant's question as plain text. If the merchant formatted the question,
                                  this is only the text before the first formatting change or new paragraph.
                                  See User input.
                                example: "Is the item still in its original packaging?"
                              value:
                                type: [string, boolean, 'null']
                                description: The value provided by the user.
                                example: true
                              system_message:
                                type: string
                                description: |
                                  The merchant's "Response if yes" message as plain text, in the same form as
                                  `prompt`. Only present when the merchant turned that response on.
                                example: "Used cartridges cannot be returned."
                        image_uploads:
                          type: array
                          description: URLs of images uploaded by the customer for this item.
                          items:
                            type: string
                            example: "https://cdn.example.com/return-images/abc123.jpg"
                  cart_items:
                    type: array
                    description: The items in the cart for the return (exchange items or shop-now items).
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                          description: The unique identifier of the cart item.
                          example: 201
                        variant_id:
                          type: integer
                          description: The product variant identifier.
                          example: 501
                        product_id:
                          type: [integer, 'null']
                          description: The product identifier.
                          example: 100
                        sku:
                          type: [string, 'null']
                          description: The SKU of the product variant.
                          example: "SHIRT-RED-S"
                        title:
                          type: [string, 'null']
                          description: The product title.
                          example: "Red Shirt"
                        variant_title:
                          type: [string, 'null']
                          description: The variant title (e.g., size, color).
                          example: "Small"
                        translated_title:
                          type: [string, 'null']
                          description: |
                            The product title in the shopper's locale, set when the item is added.
                            `null` when no locale was sent, product translations are not enabled for the shop,
                            or no translation exists.
                          example: "Chemise rouge"
                        translated_variant_title:
                          type: [string, 'null']
                          description: |
                            The variant title in the shopper's locale, set when the item is added.
                            `null` under the same conditions as `translated_title`.
                          example: "Petit"
                        price:
                          type: [integer, 'null']
                          description: The price of this item in minor units (e.g. cents).
                          example: 2500
                        image:
                          type: [string, 'null']
                          description: URL of the product image.
                          example: "https://cdn.example.com/products/red-shirt.jpg"
                        exchange_type:
                          type: [string, 'null']
                          description: The type of exchange (if this is an exchange item).
                          enum:
                            - storefront
                            - pos-storefront
                            - variant-storefront
                            - advanced-storefront
                            - advanced
                            - exchange
                            - pos-exchange
                            - recommended
                            - recommended-storefront
                            - null
                          example: "exchange"
                        exchange_for_returning_item_id:
                          type: [integer, 'null']
                          description: The ID of the returning item this cart item is exchanging for.
                          example: 1
                  selected_return_method:
                    type: [object, 'null']
                    description: |
                      The selected return shipping method. Set via the select-return-method action.
                      Available methods are provided in context.return_methods.
                    properties:
                      id:
                        type: integer
                        description: The unique identifier of the selected return method.
                      name:
                        type: string
                        description: The name of the selected return method.
                      type:
                        type: string
                        description: The type of the selected return method.
                        enum:
                          - box-and-ship
                          - carrier-choice
                          - drop-off
                          - pick-up
                          - in-store
                      title:
                        type: string
                        description: |
                          The display title of the selected return method.
                          Falls back to the method name when no title is set.
                      logo_url:
                        type: string
                        description: The logo URL of the selected return method, when available.
                      location_url:
                        type: string
                        description: The location URL of the selected return method, when available.
                  payment_intent:
                    type: [object, 'null']
                    description: |
                      The payment intent attached to the draft return, if any.

                      Loop removes it, and this field becomes `null`, when you set
                      `processing_type` to `regular` or when Loop resets Instant to `regular`
                      because Instant is no longer available.
                    properties:
                      id:
                        type: integer
                      provider:
                        type: string
                        description: The payment provider.
                      provider_intent_id:
                        type: string
                        description: The payment provider's intent identifier.
                  return_key:
                    type: [string, 'null']
                    description: The unique key for the resulting return once submitted.
                  requires_uncollectible_payment:
                    type: boolean
                    description: |
                      `true` when the draft return requires a payment but the shop has no usable
                      Stripe connection, so Loop cannot collect it. When `true`, the
                      `add-payment-intent` link is not offered and the draft return cannot be
                      submitted. Change the draft so no payment is needed, for example by changing
                      items or the return method.
                    example: false

              context:
                type: object
                description: |
                  Contextual data for building the return UI — available languages, the order's line
                  items, return reasons, eligibility, exchange options, and return methods. Keys are
                  omitted when their value is null.
                properties:
                  languages:
                    type: [array, 'null']
                    description: The languages available for this shop.
                    items:
                      type: object
                      properties:
                        name:
                          type: string
                        abbreviation:
                          type: string
                  order:
                    type: [object, 'null']
                    description: The order information.
                    properties:
                      id:
                        type: integer
                      currency:
                        type: string
                        description: The three-character ISO 4217 currency code.
                      original_payment_transactions:
                        type: array
                        description: |
                          The original payment transactions on the order, excluding refunds,
                          voids, and authorizations. Useful for identifying which payment
                          methods the customer used when placing the order.
                        items:
                          type: object
                          properties:
                            type:
                              type: string
                              description: The transaction type (e.g. "sale", "capture").
                            gateway:
                              type: [string, 'null']
                              description: The payment gateway used for the transaction.
                            amount:
                              type: integer
                              description: The transaction amount in minor units (e.g. cents).
                            currency:
                              type: string
                              description: The three-character ISO 4217 currency code.
                            brand:
                              type: [string, 'null']
                              description: The card brand (e.g. "visa", "mastercard"), if applicable.
                            last4:
                              type: [integer, 'null']
                              description: The last four digits of the card number, if applicable.
                      line_items:
                        type: array
                        items:
                          type: object
                          properties:
                            id:
                              type: integer
                            provider_product_id:
                              type: integer
                            provider_variant_id:
                              type: integer
                            title:
                              type: string
                            variant_title:
                              type: [string, 'null']
                            sku:
                              type: [string, 'null']
                            description:
                              type: [string, 'null']
                            price:
                              type: [integer, 'null']
                              description: The price in minor units.
                            image:
                              type: [string, 'null']
                            parent_line_item_id:
                              type: [integer, 'null']
                            options:
                              type: array
                              items:
                                type: object
                                properties:
                                  name:
                                    type: string
                                  value:
                                    type: string
                  return_reason_groups:
                    type: [array, 'null']
                    description: Groups of return reasons.
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        return_reasons:
                          type: array
                          items:
                            type: object
                            properties:
                              id:
                                type: integer
                              name:
                                type: string
                              parent_return_reason_id:
                                type: [integer, 'null']
                              parent_return_reason_name:
                                type: [string, 'null']
                              is_commentable:
                                type: boolean
                              requires_comments:
                                type: boolean
                  items_eligible_to_return:
                    type: [array, 'null']
                    description: |
                      Line items that can be returned. Use order_line_item_id when calling the
                      add-returning-item action; cross-reference context.order.line_items for details.
                    items:
                      type: object
                      properties:
                        order_line_item_id:
                          type: integer
                        return_reason_group_id:
                          type: integer
                        expiration:
                          type: [string, 'null']
                  items_not_eligible_to_return:
                    type: [array, 'null']
                    description: Line items that cannot be returned, with the reason why.
                    items:
                      type: object
                      properties:
                        order_line_item_id:
                          type: integer
                        ineligibility_code:
                          type: string
                        expiration:
                          type: [string, 'null']
                  return_reason_options:
                    type: [array, 'null']
                    description: Return-reason option groups (an array of arrays of options).
                    items:
                      type: array
                      items:
                        type: object
                        properties:
                          id:
                            type: integer
                          name:
                            type: string
                          is_commentable:
                            type: boolean
                          requires_comments:
                            type: boolean
                  exchange_options:
                    type: [array, 'null']
                    description: Products and variants available for exchange.
                    items:
                      type: object
                      properties:
                        product_options:
                          type: [array, 'null']
                          description: |
                            The product's option dimensions (for example, Size or Color),
                            used to build the variant selection UI.
                          items:
                            type: object
                            properties:
                              name:
                                type: string
                                description: The option name, for example "Size".
                              values:
                                type: array
                                description: The available values for this option, for example ["S", "M", "L"].
                              position:
                                type: [integer, 'null']
                                description: |
                                  The 1-based Shopify product option position this dimension maps to
                                  (for example, 2 when Size is option2). Clients should read variant
                                  option values by this position, not by array index, because
                                  single-value options may be omitted from this list.
                        product_variants:
                          type: array
                          description: The variants available to exchange into for this product.
                          items:
                            type: object
                            properties:
                              product_id:
                                type: [integer, 'null']
                                description: The unique identifier of the product.
                              variant_id:
                                type: integer
                                description: The unique identifier of the variant.
                              title:
                                type: [string, 'null']
                                description: The product title.
                              variant_title:
                                type: [string, 'null']
                                description: The variant title, for example "Medium / Blue".
                              product_type:
                                type: [string, 'null']
                                description: The product type.
                              options:
                                type: object
                                description: A map of option name to the value selected for this variant.
                                additionalProperties:
                                  type: string
                              image:
                                type: [string, 'null']
                                description: The variant image URL.
                              price:
                                type: [integer, 'null']
                                description: The variant price in minor units.
                              currency:
                                type: [string, 'null']
                                description: The ISO currency code for the price.
                              is_available:
                                type: boolean
                                description: Whether the variant is in stock and available for exchange.
                              translated_title:
                                type: [string, 'null']
                                description: |
                                  The product title in the shopper's locale. `null` when no locale was sent,
                                  product translations are not enabled for the shop, or no translation exists.
                                  `title` always stays in the default language.
                              translated_variant_title:
                                type: [string, 'null']
                                description: |
                                  The variant title in the shopper's locale. `null` under the same conditions as
                                  `translated_title`. `variant_title` always stays in the default language.
                              translated_options:
                                type: array
                                description: |
                                  The variant's options in the shopper's locale, one entry per option in
                                  `product_options` and in the same order. Each name and value falls back to its
                                  default-language text. Empty when no option name or value is translated.
                                items:
                                  type: object
                                  properties:
                                    name:
                                      type: string
                                      description: The option name, for example "Taille".
                                    value:
                                      type: string
                                      description: The value selected for this variant, for example "Petit".
                  return_method_options:
                    type: [array, 'null']
                    description: Available return shipping methods for this draft return.
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                          description: The unique identifier of the return method.
                        name:
                          type: string
                          description: The name of the return method.
                        type:
                          type: string
                          description: The type of the return method.
                          enum:
                            - box-and-ship
                            - carrier-choice
                            - drop-off
                            - pick-up
                            - in-store
                        fee:
                          type: integer
                          description: The fee in minor units.
                        title:
                          type: string
                          description: |
                            The display title of the return method.
                            Falls back to the method name when no title is set.
                        logo_url:
                          type: string
                          description: The logo URL of the return method, when available.
                        location_url:
                          type: string
                          description: The location URL of the return method, when available.
                  processing_type_options:
                    $ref: '#/components/schemas/ProcessingTypeOptions'
              links:
                type: array
                description: |
                  HATEOAS links representing available actions for the current draft return state.

                  **How to use links:**
                  1. Check the `rel` field to identify the action
                  2. Review the `fields` array to see what data is required
                  3. Make an HTTP request to the `href` using the specified `method`
                  4. Include all fields marked with `is_required: true`

                  **State-based availability:**
                  - In `created` state: Links for adding items, setting customer, finalizing items
                  - In `items-finalized` state: Links for setting credit type, setting processing type,
                    selecting return method, submitting
                  - In terminal states (`submitted`, `cancelled`, `expired`): No action links (empty array)

                  The links array dynamically changes based on:
                  - Current draft return state
                  - Available context (eligible items, return reasons, return methods, etc.)
                  - Merchant policy configuration
                items:
                  type: object
                  properties:
                    rel:
                      type: string
                      description: |
                        The relationship type/action key. This identifies the specific action this link represents.
                        For actions on specific items, the rel may include the item ID
                        (e.g., "set-returning-item-return-reason-74").
                      examples:
                        - "add-returning-item"
                        - "set-address"
                        - "set-customer"
                        - "finalize-items"
                        - "set-credit-type"
                        - "submit-draft-return"
                        - "cancel-draft-return"
                    href:
                      type: string
                      description: |
                        The fully-qualified URL to call for this action.
                      examples:
                        - "https://api.loopreturns.com/api/v1/draft-returns/123/returning-items"
                        - "https://api.loopreturns.com/api/v1/draft-returns/123/address"
                    method:
                      type: string
                      description: |
                        The HTTP method to use when calling this link.
                      examples:
                        - "POST"
                        - "DELETE"
                    description:
                      type: string
                      description: |
                        Human-readable description of what this action does.
                      example: "Add a line item to the return"
                    prompt:
                      type: string
                      description: |
                        Optional user-facing prompt text for this action. On
                        `add-returning-item-user-input` links, this is the merchant's question as plain
                        text. See User input.
                      example: "Which item would you like to return?"
                    fields:
                      type: array
                      description: |
                        Field metadata describing the parameters needed for this action.

                        Each field includes:
                        - **name**: Parameter name (snake_case)
                        - **type**: Data type (int, string, bool, enum, etc.)
                        - **description**: Human-readable explanation
                        - **is_required**: Whether this field must be provided
                        - **allowed_values**: (Optional) Valid enum values for enum types

                        **Using field metadata:**
                        - Check `is_required` to determine mandatory vs optional fields
                        - Use `type` for client-side validation
                        - Display `description` to end users for guidance
                        - For enum types, use `allowed_values` to populate dropdowns
                      items:
                        type: object
                        properties:
                          name:
                            type: string
                            description: The parameter name (snake_case).
                            example: "order_line_item_id"
                          type:
                            type: string
                            description: |
                              The data type of the field. Common types: int, string, bool, enum.
                            example: "int"
                          description:
                            type: string
                            description: Human-readable description of the field.
                            example: "ID of the line item to return"
                          allowed_values:
                            type: array
                            description: |
                              For enum type fields, this contains the list of valid values.
                            items:
                              type: string
                            example: ["refund", "gift", "exchange"]
                          is_required:
                            type: boolean
                            description: |
                              Whether this field is required for the action to succeed.
                            example: true
                    is_required:
                      type: boolean
                      description: |
                        Whether this action is required to progress the draft return.
                        If true, the draft return cannot be submitted until this action is completed.
                      example: true
              errors:
                type: array
                description: |
                  An array of error codes. In the event of a partial failure, the API will return all possible data
                  as well as any error codes that were thrown.

                  See [Error codes](/api-reference/error-codes#draft-returns-specific-errors) for a full list of
                  possible errors.
                items:
                  type: object
                  properties:
                    code:
                      type: string
                      description: The error code associated with the issue.
                      enum:
                        - draft-returns-not-enabled
                        - validation-failed
                        - action-validation-failed
                        - shop-not-found
                        - order-lookup-failed
                        - order-not-found
                        - error-retrieving-order
                        - secondary-input-mismatch
                        - returns-unavailable-for-order
                        - order-has-been-cancelled
                        - order-line-item-get-data-failed
                        - draft-return-not-found
                        - draft-return-version-mismatch
                        - draft-return-not-actionable
                        - items-not-finalizable
                        - totals-calculation-failed
                        - return-creation-failed
                        - terminal-state
                        - context-generation-failed
                        - action-generation-failed
                        - no-eligible-return-methods
                        - invalid-return-method
                        - product-variant-not-found
                        - product-variant-unavailable
                        - return-reason-not-found
                        - currency-mismatch
                        - unsupported-feature
                        - internal-error
                    message:
                      type: string
                      description: Optional error message.

paths:
  /draft-returns/{draft_return_id}:
    get:
      summary: Get Draft Return
      operationId: getDraftReturn
      description: |
        Retrieves the details of a draft return, including its current state, returning items, cart items, and
        available actions. The response includes the draft return data, context information, and any available
        actions based on the current state.
      security:
        - api_key: []
      parameters:
        - $ref: '#/components/parameters/DraftReturnId'
        - $ref: '#/components/parameters/ShopId'
        - $ref: '#/components/parameters/LoopLocale'
      responses:
        "200":
          $ref: '#/components/responses/DraftReturnResponse'
        "401":
          $ref: '#/components/responses/UnauthorizedError'
        "422":
          $ref: '#/components/responses/ValidationError'

  /draft-returns/{draft_return_id}/order/items:
    get:
      summary: List Order Line Items
      operationId: getDraftReturnOrderItems
      description: |
        Returns the order's line items in the context of the draft return, including
        return and warranty eligibility, available return reasons, variant details, and
        advanced-exchange options. Prices are integers in minor units (e.g. cents).

        Send `X-Loop-Locale` to receive translated product titles and variant options alongside the
        default-language fields (`translated_title`, `variant.translated_title`,
        `variant.translated_options`). The default-language fields never change.

        Each item's `available_outcomes` lists the outcomes the item can get, one object per outcome.
        Ignore any `type` value or object key you do not recognise: new ones can be added without notice.
        The `shop-now` value in each item's `capabilities` is deprecated: read `available_outcomes` instead.
      security:
        - api_key: []
      parameters:
        - $ref: '#/components/parameters/DraftReturnId'
        - $ref: '#/components/parameters/ShopId'
        - $ref: '#/components/parameters/LoopLocale'
        - name: page
          in: query
          description: The page number to return (default 1).
          schema:
            type: integer
            minimum: 1
            default: 1
        - name: limit
          in: query
          description: |
            Number of order line items per page. Must be between 1 and 250 (inclusive). Defaults to 250,
            so leaving it out returns up to 250 line items in one page.
          schema:
            type: integer
            minimum: 1
            maximum: 250
            default: 250
      responses:
        "200":
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        description:
                          type: [string, "null"]
                        image:
                          type: [string, "null"]
                        parent_line_item_id:
                          type: [integer, "null"]
                        price:
                          type: [integer, "null"]
                        discount:
                          type: integer
                        discounted_price:
                          type: [integer, "null"]
                        compare_at_price:
                          type: [integer, "null"]
                        price_original:
                          type: [integer, "null"]
                        current_variant_price:
                          type: [integer, "null"]
                        outcome:
                          type: string
                        available_outcomes:
                          type: array
                          description: |
                            The outcomes the item can get after Loop applies the return policy, workflow
                            exclusions, warranty claims and merchant exceptions, one object per outcome.

                            **Ignore any `type` value you do not recognise, and any key you do not recognise on
                            an object.** New values and new keys can be added without notice.

                            Only available outcomes are listed. An empty array means no outcome is available for
                            the item. `return` is never listed: whether the item can be returned is in
                            `eligibility.return`. The list does not depend on `eligibility.return`, so check that
                            first: an item that cannot be returned can still list outcomes, for example `shop-now`
                            on an item that is unfulfilled or past its return window.

                            The list reflects the item's own eligibility, including workflows evaluated with the
                            draft return's context (for example, a workflow with a gift-return condition). It does
                            not apply draft-level credit rules, so an item on a gift return or on an order paid in
                            cash can still list `refund`. The `set-credit-type` action stays the authority for the
                            draft's credit type: it drops refund for gift returns and cash-paid orders even when an
                            item lists it, and the credit types it accepts can be narrower than an item's list in
                            other cases too, such as a cart that mixes items with different outcomes.
                          items:
                            type: object
                            required:
                              - type
                            properties:
                              type:
                                type: string
                                description: |
                                  The outcome. Known values, always in this order: `refund`, `exchange`, `replace`,
                                  `store-credit`, `shop-now`. `replace` appears only when a warranty claim is
                                  active. `store-credit` corresponds to `gift` in `set-credit-type`, whose
                                  `credit_type` values are `refund`, `gift` and `exchange`.
                          examples:
                            - [{type: refund}, {type: exchange}, {type: store-credit}]
                        return_reasons:
                          type: array
                          items:
                            type: object
                            required:
                              - id
                              - name
                            properties:
                              id:
                                type: integer
                              name:
                                type: string
                              parent_return_reason_id:
                                type: [integer, "null"]
                              parent_return_reason_name:
                                type: [string, "null"]
                        eligibility:
                          type: object
                          properties:
                            return:
                              type: object
                              properties:
                                status:
                                  type: boolean
                                reason:
                                  type: string
                                expiration:
                                  type: [string, "null"]
                            warranty:
                              type: object
                              properties:
                                status:
                                  type: boolean
                                reason:
                                  type: string
                                expiration:
                                  type: [string, "null"]
                        title:
                          type: string
                        translated_title:
                          type: [string, "null"]
                          description: |
                            The product title in the shopper's locale. `null` when no `X-Loop-Locale` header was
                            sent, product translations are not enabled for the shop, or no translation exists.
                            `title` always stays in the default language.
                        provider_product_id:
                          type: integer
                        variant:
                          type: object
                          properties:
                            id:
                              type: integer
                            title:
                              type: [string, "null"]
                            options:
                              type: array
                              items:
                                type: object
                                properties:
                                  name:
                                    type: string
                                  value:
                                    type: [string, "null"]
                            translated_title:
                              type: [string, "null"]
                              description: |
                                The variant title in the shopper's locale. `null` when no `X-Loop-Locale` header was
                                sent, when product translations are not enabled for the shop, or when no option value
                                has a translation. For a product with only the default `Title` option, it is the
                                translated variant name, or `null` when that name has no translation. `variant.title`
                                always stays in the default language.
                            translated_options:
                              type: [array, "null"]
                              description: |
                                The variant's options in the shopper's locale, one entry per entry of `options`,
                                in the same order, so the two lists can be paired by index. Each name and value
                                falls back to its default-language text. `null` when no option name or value is
                                translated, and for a product with only the default `Title` option.
                              items:
                                type: object
                                properties:
                                  name:
                                    type: string
                                    description: The option name, for example "Taille".
                                  value:
                                    type: [string, "null"]
                                    description: The value selected for this variant, for example "Petit".
                        advanced_exchange:
                          type: [object, "null"]
                          properties:
                            id:
                              type: integer
                            title:
                              type: string
                            title_visible:
                              type: boolean
                            options:
                              type: array
                              items:
                                type: object
                        capabilities:
                          type: array
                          description: |
                            Features the item supports. Known values: `shop-now`, `warranties` and `smart-exchanges`.
                            Ignore any value you do not recognise.

                            **`shop-now` is deprecated. Read `available_outcomes` instead.** `shop-now` is listed
                            exactly when `available_outcomes` has an object whose `type` is `shop-now`. It stays in
                            this list so existing integrations keep working.
                          items:
                            type: string
        "401":
          $ref: '#/components/responses/UnauthorizedError'
        "404":
          description: Not Found

  /draft-returns/{draft_return_id}/totals:
    get:
      summary: Get Draft Return Totals
      operationId: getDraftReturnTotals
      description: |
        Returns the computed monetary totals for the draft return. Totals are calculated
        on demand and cached per draft-return version. Money values are objects with an
        integer `amount` in minor units and a `currencyCode`.
      security:
        - api_key: []
      parameters:
        - $ref: '#/components/parameters/DraftReturnId'
        - $ref: '#/components/parameters/ShopId'
      responses:
        "200":
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      return_total:
                        $ref: '#/components/schemas/DraftReturnMoney'
                      new_item_total:
                        $ref: '#/components/schemas/DraftReturnMoney'
                      total_bonus_offered:
                        $ref: '#/components/schemas/DraftReturnMoney'
                      bonus_used:
                        $ref: '#/components/schemas/DraftReturnMoney'
                      fees:
                        type: object
                        properties:
                          applied:
                            $ref: '#/components/schemas/DraftReturnMoney'
                          refund:
                            $ref: '#/components/schemas/DraftReturnMoney'
                          credit:
                            $ref: '#/components/schemas/DraftReturnMoney'
                          exchange:
                            $ref: '#/components/schemas/DraftReturnMoney'
                      amount_due:
                        $ref: '#/components/schemas/DraftReturnMoney'
                      credit:
                        $ref: '#/components/schemas/DraftReturnMoney'
                      net:
                        $ref: '#/components/schemas/DraftReturnMoney'
                      returning_item_subtotal:
                        $ref: '#/components/schemas/DraftReturnMoney'
                      returning_item_tax:
                        $ref: '#/components/schemas/DraftReturnMoney'
                      purchasing_item_tax:
                        $ref: '#/components/schemas/DraftReturnMoney'
                      settings:
                        type: object
                        properties:
                          stripe_min:
                            type: integer
                            description: The Stripe minimum charge amount in minor units.
                      is_difference_covered:
                        type: boolean
                        description: |
                          `true` when the shopper does not pay a price difference that exists, because the
                          merchant covers it. This happens in two cases:

                          - The amount the shopper owes is below `settings.stripe_min`, so it is waived.
                          - Nothing is due, and at least one new item costs more than the item it replaces.

                          A discount carried over from the original order does not count as a difference. An
                          even exchange returns `false`, even when the new item's price includes that discount.
                        example: false
                      qualifies_for_return_coverage:
                        type: boolean
                        description: |
                          `true` when at least one returned item is covered by the order's Returns Coverage, so
                          the handling fee is waived. One covered item covers the whole return. The `fees`
                          amounts still show the configured fee, but `amount_due` and `net` already leave it
                          out. Do not subtract the fee from them again.

                          `false` when the order has no Returns Coverage, or when every returned item is
                          excluded from it by an excluded product tag or discount code.
                        example: false
                      new_item_prices:
                        type: array
                        description: |
                          The price the shopper pays for each new item, with any discount carried over from the
                          original order. Use it to show the shopper what each new item costs them.

                          - There is one entry per new item, so two returned items exchanged for the same variant
                            each have their own entry. Match entries on `order_line_item_id`, not `variant_id`.
                          - When the shopper pays the price difference for an exchange, that item has no entry.
                            The shopper pays the catalog price, so show that.
                          - The list is empty when the draft return has no new items.
                        items:
                          type: object
                          properties:
                            order_line_item_id:
                              type: [integer, 'null']
                              description: |
                                The order line item being returned that this new item replaces. `null` for an
                                item added from the shop rather than exchanged for a returned item.
                              example: 11
                            variant_id:
                              type: string
                              description: |
                                The product variant of the new item. Sent as a string, not a number, so large
                                ids stay exact.
                              example: '1234567890123456789'
                            price:
                              type: integer
                              description: |
                                What the shopper pays for the item, in minor units of the same currency as
                                the other totals in this response.
                              example: 800
                          required:
                            - order_line_item_id
                            - variant_id
                            - price
                        example:
                          - order_line_item_id: 11
                            variant_id: '9999'
                            price: 800
                          - order_line_item_id: null
                            variant_id: '1234567890123456789'
                            price: 900
        "401":
          $ref: '#/components/responses/UnauthorizedError'
        "404":
          description: Not Found

  /draft-returns:
    get:
      summary: List Draft Returns (HAL-Forms)
      operationId: listDraftReturns
      description: |
        Returns a HAL-Forms collection describing the draft-return actions available for
        the shop. Requires `Accept: application/prs.hal-forms+json`; any other Accept value
        returns an `unsupported-feature` error.
      security:
        - api_key: []
      parameters:
        - $ref: '#/components/parameters/ShopId'
        - name: Accept
          in: header
          required: true
          description: Must be `application/prs.hal-forms+json`.
          schema:
            type: string
            enum:
              - application/prs.hal-forms+json
      responses:
        "200":
          description: OK
          content:
            application/prs.hal-forms+json:
              schema:
                type: object
                properties:
                  _links:
                    type: object
                    properties:
                      self:
                        type: object
                        properties:
                          href:
                            type: string
                  _embedded:
                    type: object
                    properties:
                      draft-returns:
                        type: array
                        items:
                          type: object
                  client_application:
                    type: object
                    description: The client-application header specification.
                  _templates:
                    type: object
                    description: HAL-Forms templates for the available actions, keyed by template name.
                    additionalProperties:
                      type: object
                  errors:
                    type: array
                    items:
                      type: object
                      properties:
                        code:
                          type: string
                        message:
                          type: string
        "401":
          $ref: '#/components/responses/UnauthorizedError'
    post:
      summary: Initialize Draft Return
      operationId: initializeDraftReturn
      description: |
        Initialize a new draft return.

        The return created using this endpoint can be configured and modified using
        the other draft return API endpoints.

        When integrating the draft return APIs, this endpoint should be the first
        one called. The response includes the initial state of the draft return
        as well as links to the next available actions.
      security:
        - api_key: []
      parameters:
        - $ref: '#/components/parameters/ShopId'
        - $ref: '#/components/parameters/LoopLocale'
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required:
                - order_name
                - secondary_input
              properties:
                order_name:
                  type: string
                  description: "The order name (the merchant's order identifier, for example an order number)."
                  examples:
                    - "#1001"
                secondary_input:
                  type: string
                  description: |
                    Any secondary input included by the shopper when looking up their order (for example, ZIP/postal
                    code, email address, or phone number). A phone number matches the order's shipping address phone.
                    If the order has no shipping address (for example, a local pickup order), it matches the billing
                    address phone or the customer's phone instead.
                is_gift:
                  type: boolean
                  description: |
                    Whether or not the return will use Loop's Gift flow. For details, see
                    [Gift Returns](https://help.loopreturns.com/en/articles/1911041).
                  examples:
                    - false
      responses:
        "200":
          $ref: '#/components/responses/DraftReturnResponse'
        "401":
          $ref: '#/components/responses/UnauthorizedError'
        "422":
          $ref: '#/components/responses/ValidationError'

  /draft-returns/create:
    post:
      summary: Create Draft Return (Declarative)
      operationId: createDraftReturn
      description: |
        Creates a draft return in a single declarative request — specifying the order,
        returning items, exchange cart items, return method, and credit options up front —
        rather than building it up through incremental mutation calls.
      security:
        - api_key: []
      parameters:
        - $ref: '#/components/parameters/ShopId'
        - $ref: '#/components/parameters/LoopLocale'
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required:
                - order_id
              properties:
                order_id:
                  type: integer
                  minimum: 1
                  description: The Loop identifier of the order to create the draft return for.
                accepts_policy_conditions:
                  type: boolean
                  description: Whether the customer accepts the return policy conditions.
                is_gift:
                  type: boolean
                  description: Whether the return is created as a gift return.
                language_code:
                  type: string
                  description: The display language for the draft return (e.g. en-US).
                currency_code:
                  type: string
                  description: The presentment currency for the draft return (ISO 4217).
                customer:
                  type: object
                  required:
                    - email
                  properties:
                    email:
                      type: string
                      format: email
                      description: The customer's email address.
                shipping_address:
                  type: object
                  required:
                    - address1
                    - city
                    - state
                    - zip
                    - country
                    - country_code
                  properties:
                    name:
                      type: string
                    company:
                      type: [string, "null"]
                    address1:
                      type: string
                    address2:
                      type: string
                    city:
                      type: string
                    state:
                      type: string
                    zip:
                      type: string
                    country:
                      type: string
                    country_code:
                      type: string
                    phone:
                      type: string
                returning_items:
                  type: array
                  items:
                    type: object
                    required:
                      - order_line_item_id
                    properties:
                      order_line_item_id:
                        type: integer
                        minimum: 1
                      return_type:
                        type: string
                        enum: [credit, exchange]
                      return_reason:
                        type: object
                        required:
                          - id
                        properties:
                          id:
                            type: integer
                            minimum: 1
                          comment:
                            type: string
                      user_inputs:
                        type: array
                        items:
                          type: object
                          required:
                            - question_id
                            - value
                          properties:
                            question_id:
                              type: string
                            value:
                              type: boolean
                      image_uploads:
                        type: array
                        items:
                          type: string
                          minLength: 1
                cart_items:
                  type: array
                  items:
                    type: object
                    required:
                      - variant_id
                    properties:
                      variant_id:
                        type: integer
                        minimum: 1
                      exchange_type:
                        type: string
                        enum:
                          - storefront
                          - pos-storefront
                          - variant-storefront
                          - advanced-storefront
                          - advanced
                          - exchange
                          - pos-exchange
                          - recommended
                          - recommended-storefront
                      exchange_for_order_line_item_id:
                        type: integer
                        minimum: 1
                return_method:
                  type: object
                  required:
                    - name
                    - type
                  properties:
                    name:
                      type: string
                    type:
                      type: string
                      enum: [box-and-ship, carrier-choice, drop-off, pick-up, in-store]
                credit_type:
                  type: string
                  enum: [refund, gift, exchange]
                processing_type:
                  type: string
                  enum: [regular, instant]
                store_credit_type:
                  type: string
                  enum: [gift-card, reshop]
      responses:
        "200":
          $ref: '#/components/responses/DraftReturnResponse'
        "401":
          $ref: '#/components/responses/UnauthorizedError'
        "422":
          $ref: '#/components/responses/ValidationError'

  /draft-returns/{draft_return_id}/accept-return-policy:
    post:
      summary: Accept Return Policy
      operationId: acceptReturnPolicy
      description: Records the customer's acceptance of the return policy for the draft return.
      security:
        - api_key: []
      parameters:
        - $ref: '#/components/parameters/DraftReturnId'
        - $ref: '#/components/parameters/ShopId'
        - $ref: '#/components/parameters/LoopLocale'
      responses:
        "200":
          $ref: '#/components/responses/DraftReturnResponse'
        "401":
          $ref: '#/components/responses/UnauthorizedError'
        "422":
          $ref: '#/components/responses/ValidationError'

  /draft-returns/{draft_return_id}/cancel:
    post:
      summary: Cancel Draft Return
      operationId: cancelDraftReturn
      description: |
        Cancel a draft return.

        Cancelled draft returns can't be reopened.
      security:
        - api_key: []
      parameters:
        - $ref: '#/components/parameters/DraftReturnId'
        - $ref: '#/components/parameters/ShopId'
        - $ref: '#/components/parameters/LoopLocale'
      responses:
        "200":
          $ref: '#/components/responses/DraftReturnResponse'
        "401":
          $ref: '#/components/responses/UnauthorizedError'
        "422":
          $ref: '#/components/responses/ValidationError'

  /draft-returns/{draft_return_id}/customer:
    post:
      summary: Set Customer
      operationId: setCustomer
      description: Sets the customer information for the draft return.
      security:
        - api_key: []
      parameters:
        - $ref: '#/components/parameters/DraftReturnId'
        - $ref: '#/components/parameters/ShopId'
        - $ref: '#/components/parameters/LoopLocale'
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required:
                - email
              properties:
                email:
                  type: string
                  format: email
                  description: The customer's email address.
      responses:
        "200":
          $ref: '#/components/responses/DraftReturnResponse'
        "401":
          $ref: '#/components/responses/UnauthorizedError'
        "422":
          $ref: '#/components/responses/ValidationError'

  /draft-returns/{draft_return_id}/address:
    post:
      summary: Set Address
      operationId: setAddress
      description: Sets the return shipping address for the draft return.
      security:
        - api_key: []
      parameters:
        - $ref: '#/components/parameters/DraftReturnId'
        - $ref: '#/components/parameters/ShopId'
        - $ref: '#/components/parameters/LoopLocale'
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required:
                - address1
                - city
                - state
                - country
                - country_code
                - zip
              properties:
                name:
                  type: string
                  description: The recipient name.
                company:
                  type: string
                  description: The company name.
                address1:
                  type: string
                  description: The primary address line.
                address2:
                  type: string
                  description: The secondary address line.
                city:
                  type: string
                  description: The city name.
                state:
                  type: string
                  description: The province or state name.
                country:
                  type: string
                  description: The country name.
                country_code:
                  type: string
                  description: The two-character ISO country code.
                  maxLength: 2
                zip:
                  type: string
                  description: The postal code.
                phone:
                  type: string
                  description: The phone number.
      responses:
        "200":
          $ref: '#/components/responses/DraftReturnResponse'
        "401":
          $ref: '#/components/responses/UnauthorizedError'
        "422":
          $ref: '#/components/responses/ValidationError'

  /draft-returns/{draft_return_id}/returning-items:
    post:
      summary: Add Returning Item
      operationId: addReturningItem
      description: Adds a specific item to the draft return's ReturningItems.
      security:
        - api_key: []
      parameters:
        - $ref: '#/components/parameters/DraftReturnId'
        - $ref: '#/components/parameters/ShopId'
        - $ref: '#/components/parameters/LoopLocale'
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required:
                - order_line_item_id
              properties:
                order_line_item_id:
                  type: integer
                  description: |
                    The unique identifier created by Loop of the order line item to add.
      responses:
        "200":
          $ref: '#/components/responses/DraftReturnResponse'
        "401":
          $ref: '#/components/responses/UnauthorizedError'
        "422":
          $ref: '#/components/responses/ValidationError'

  /draft-returns/{draft_return_id}/returning-items/{returning_item_id}:
    delete:
      summary: Remove Returning Item
      operationId: removeReturningItem
      description: Removes a specific item from the draft return's ReturningItems.
      security:
        - api_key: []
      parameters:
        - $ref: '#/components/parameters/DraftReturnId'
        - $ref: '#/components/parameters/ReturningItemId'
        - $ref: '#/components/parameters/ShopId'
        - $ref: '#/components/parameters/LoopLocale'
      responses:
        "200":
          $ref: '#/components/responses/DraftReturnResponse'
        "401":
          $ref: '#/components/responses/UnauthorizedError'
        "422":
          $ref: '#/components/responses/ValidationError'

  /draft-returns/{draft_return_id}/returning-items/{returning_item_id}/return-reason:
    post:
      summary: Set Returning Item Return Reason
      operationId: setReturningItemReturnReason
      description: Sets the return reason for a specific returning item.
      security:
        - api_key: []
      parameters:
        - $ref: '#/components/parameters/DraftReturnId'
        - $ref: '#/components/parameters/ReturningItemId'
        - $ref: '#/components/parameters/ShopId'
        - $ref: '#/components/parameters/LoopLocale'
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required:
                - reason_id
              properties:
                reason_id:
                  type: integer
                  description: The unique identifier of the return reason.
                comment:
                  type: string
                  description: Optional comment about the return reason.
      responses:
        "200":
          $ref: '#/components/responses/DraftReturnResponse'
        "401":
          $ref: '#/components/responses/UnauthorizedError'
        "422":
          $ref: '#/components/responses/ValidationError'

  /draft-returns/{draft_return_id}/returning-items/{returning_item_id}/user-input/{user_input_id}:
    post:
      summary: Add Returning Item User Input
      operationId: addReturningItemUserInput
      description: |
        Adds user input for a specific returning item.
        This allows collecting additional information from the customer about their return.
      security:
        - api_key: []
      parameters:
        - $ref: '#/components/parameters/DraftReturnId'
        - $ref: '#/components/parameters/ReturningItemId'
        - $ref: '#/components/parameters/UserInputId'
        - $ref: '#/components/parameters/ShopId'
        - $ref: '#/components/parameters/LoopLocale'
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required:
                - value
              properties:
                value:
                  type: string
                  description: The value of the user's input for the prompt.
      responses:
        "200":
          $ref: '#/components/responses/DraftReturnResponse'
        "401":
          $ref: '#/components/responses/UnauthorizedError'
        "422":
          $ref: '#/components/responses/ValidationError'

  /draft-returns/{draft_return_id}/returning-items/{returning_item_id}/return-type:
    post:
      summary: Set Returning Item Return Type
      operationId: setReturningItemReturnType
      description: |
        Sets the return type for a specific returning item.

        The allowed values depend on the item. Send only a value from the `allowed_values` of
        that item's `set-returning-item-return-type` link. A return type the item does not
        allow is rejected with a `422` and `errors[0].code` set to `action-validation-failed`.

        - `exchange` is offered only when exchanges are allowed for the item. It is not offered
          when the item's return policy turns exchanges off, even if Shop Now is on.
        - `credit` is offered when the item can be returned for credit.
        - On a warranty claim, only the outcomes the warranty allows are offered, even when the
          item is still within its return window.
      security:
        - api_key: []
      parameters:
        - $ref: '#/components/parameters/DraftReturnId'
        - $ref: '#/components/parameters/ReturningItemId'
        - $ref: '#/components/parameters/ShopId'
        - $ref: '#/components/parameters/LoopLocale'
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required:
                - return_type
              properties:
                return_type:
                  type: string
                  enum: [credit, exchange]
                  description: |
                    The type of return for the line item. Must be one of the values in the item's
                    link `allowed_values`.
      responses:
        "200":
          $ref: '#/components/responses/DraftReturnResponse'
        "401":
          $ref: '#/components/responses/UnauthorizedError'
        "422":
          $ref: '#/components/responses/ValidationError'

  /draft-returns/{draft_return_id}/returning-items/{returning_item_id}/exchange-item:
    post:
      summary: Add Returning Item Exchange Item
      operationId: addReturningItemExchangeItem
      description: |
        Adds an exchange item for a specific returning item to the cart.
        This endpoint is used when a customer is exchanging one item for another.

        A variant that is out of stock is rejected with a `422` and `errors[0].code` set to
        `product-variant-unavailable`. One exception: on a warranty claim that allows `replace`,
        the item's own variant is accepted out of stock when the shop has Automate out-of-stock
        scenarios turned on. Loop then refunds or credits the item once it is received.
      security:
        - api_key: []
      parameters:
        - $ref: '#/components/parameters/DraftReturnId'
        - $ref: '#/components/parameters/ReturningItemId'
        - $ref: '#/components/parameters/ShopId'
        - $ref: '#/components/parameters/LoopLocale'
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required:
                - variant_id
              properties:
                variant_id:
                  type: integer
                  description: The unique identifier of the product variant to exchange for.
                  example: 12345
      responses:
        "200":
          $ref: '#/components/responses/DraftReturnResponse'
        "401":
          $ref: '#/components/responses/UnauthorizedError'
        "422":
          $ref: '#/components/responses/ValidationError'

  /draft-returns/{draft_return_id}/finalize-items:
    post:
      summary: Finalize Items
      operationId: finalizeItems
      description: Finalizes the returning items and cart items of the draft return.
      security:
        - api_key: []
      parameters:
        - $ref: '#/components/parameters/DraftReturnId'
        - $ref: '#/components/parameters/ShopId'
        - $ref: '#/components/parameters/LoopLocale'
      responses:
        "200":
          $ref: '#/components/responses/DraftReturnResponse'
        "401":
          $ref: '#/components/responses/UnauthorizedError'
        "422":
          $ref: '#/components/responses/ValidationError'

  /draft-returns/{draft_return_id}/unfinalize-items:
    post:
      summary: Unfinalize Items
      operationId: unfinalizeItems
      description: Reopens the returning items and cart items of the draft return for modification.
      security:
        - api_key: []
      parameters:
        - $ref: '#/components/parameters/DraftReturnId'
        - $ref: '#/components/parameters/ShopId'
        - $ref: '#/components/parameters/LoopLocale'
      responses:
        "200":
          $ref: '#/components/responses/DraftReturnResponse'
        "401":
          $ref: '#/components/responses/UnauthorizedError'
        "422":
          $ref: '#/components/responses/ValidationError'

  /draft-returns/{draft_return_id}/cart/items/{cart_item_id}:
    delete:
      summary: Remove Cart Item
      operationId: removeCartItem
      description: Removes a specific item from the draft return's cart.
      security:
        - api_key: []
      parameters:
        - $ref: '#/components/parameters/DraftReturnId'
        - $ref: '#/components/parameters/CartItemId'
        - $ref: '#/components/parameters/ShopId'
        - $ref: '#/components/parameters/LoopLocale'
      responses:
        "200":
          $ref: '#/components/responses/DraftReturnResponse'
        "401":
          $ref: '#/components/responses/UnauthorizedError'
        "422":
          $ref: '#/components/responses/ValidationError'

  /draft-returns/{draft_return_id}/cart/items:
    post:
      summary: Add Cart Item
      operationId: addCartItem
      description: |
        Adds an item to the draft return's cart.

        Returns a `422` when adding a Shop Now item (a cart item not linked to a returning item)
        while a credit item's excluded outcomes (as returned on its line item) include Shop Now.
        Exchange items linked to a returning item and in-store (point of sale) returns are unaffected.
      security:
        - api_key: []
      parameters:
        - $ref: '#/components/parameters/DraftReturnId'
        - $ref: '#/components/parameters/ShopId'
        - $ref: '#/components/parameters/LoopLocale'
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required:
                - variant_id
              properties:
                variant_id:
                  type: integer
                  description: The unique identifier of the product variant to add.
                quantity:
                  type: integer
                  description: The quantity of the item to add.
      responses:
        "200":
          $ref: '#/components/responses/DraftReturnResponse'
        "401":
          $ref: '#/components/responses/UnauthorizedError'
        "422":
          $ref: '#/components/responses/ValidationError'

  /draft-returns/{draft_return_id}/credit-type:
    post:
      summary: Set Credit Type
      operationId: setCreditType
      description: Sets the credit type for the draft return.
      security:
        - api_key: []
      parameters:
        - $ref: '#/components/parameters/DraftReturnId'
        - $ref: '#/components/parameters/ShopId'
        - $ref: '#/components/parameters/LoopLocale'
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required:
                - credit_type
              properties:
                credit_type:
                  type: string
                  enum: [refund, gift, exchange]
                  description: The type of credit to apply to the return.
      responses:
        "200":
          $ref: '#/components/responses/DraftReturnResponse'
        "401":
          $ref: '#/components/responses/UnauthorizedError'
        "422":
          $ref: '#/components/responses/ValidationError'

  /draft-returns/{draft_return_id}/processing-type:
    post:
      summary: Set Processing Type
      operationId: setProcessingType
      description: |
        Sets the processing type (`regular` or `instant`) of the draft return.

        Only call this when the `set-processing-type` link is offered. It is offered in the
        `items-finalized` state when Instant is available, or when `processing_type` is
        `instant` and `regular` is available. Send only a value from the link's
        `allowed_values`.

        The link is marked required when the return policy requires Instant and
        `processing_type` is not `instant` yet.

        Setting `regular` removes any payment intent, so `draft_return.payment_intent` is
        `null`. Setting `instant` means the draft needs a payment intent before you submit. Use
        the `add-payment-intent` link.

        Loop can also reset `instant` to `regular` on a later request if Instant stops being
        available. Check `processing_type` and `payment_intent` before you submit.

        Errors (`422`):

        - `validation-failed`: `processing_type` is missing or not `regular` or `instant`.
        - `action-validation-failed`: The draft is not in `items-finalized`, or the
          requested type is not available in `context.processing_type_options`.
        - `terminal-state`: The draft is submitted, cancelled, or expired.
      security:
        - api_key: []
      parameters:
        - $ref: '#/components/parameters/DraftReturnId'
        - $ref: '#/components/parameters/ShopId'
        - $ref: '#/components/parameters/LoopLocale'
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required:
                - processing_type
              properties:
                processing_type:
                  type: string
                  enum: [regular, instant]
                  description: |
                    The processing type to set. Must be one of the values in the
                    `set-processing-type` link `allowed_values`.
      responses:
        "200":
          $ref: '#/components/responses/DraftReturnResponse'
        "401":
          $ref: '#/components/responses/UnauthorizedError'
        "422":
          $ref: '#/components/responses/ValidationError'

  /draft-returns/{draft_return_id}/return-method:
    post:
      summary: Select Return Method
      operationId: selectReturnMethod
      description: Selects a return method for the draft return.
      security:
        - api_key: []
      parameters:
        - $ref: '#/components/parameters/DraftReturnId'
        - $ref: '#/components/parameters/ShopId'
        - $ref: '#/components/parameters/LoopLocale'
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required:
                - return_method_id
              properties:
                return_method_id:
                  type: integer
                  description: The ID of the return method to select.
      responses:
        "200":
          $ref: '#/components/responses/DraftReturnResponse'
        "401":
          $ref: '#/components/responses/UnauthorizedError'
        "422":
          $ref: '#/components/responses/ValidationError'

  /draft-returns/{draft_return_id}/return-method/carrier:
    post:
      summary: Select Return Method Carrier
      operationId: selectReturnMethodCarrier
      description: |
        Selects the carrier label format for a previously selected return method.

        This action stays in the available actions after a label format is selected, so the
        format can be changed until the draft return is submitted. Its `is_required` flag is
        `true` only while no label format is selected for the current return method.

        Selecting a different return method clears the label format. If the new return method
        offers more than one label format, `is_required` is `true` until one is selected. If
        it offers only one, Loop selects that format and `is_required` is `false`.
      security:
        - api_key: []
      parameters:
        - $ref: '#/components/parameters/DraftReturnId'
        - $ref: '#/components/parameters/ShopId'
        - $ref: '#/components/parameters/LoopLocale'
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required:
                - return_method_id
                - label_format
              properties:
                return_method_id:
                  type: integer
                  minimum: 1
                  description: The ID of the return method to select a carrier for.
                label_format:
                  type: string
                  maxLength: 191
                  description: The shipping label format.
      responses:
        "200":
          $ref: '#/components/responses/DraftReturnResponse'
        "401":
          $ref: '#/components/responses/UnauthorizedError'
        "422":
          $ref: '#/components/responses/ValidationError'

  /draft-returns/{draft_return_id}/payment-intent:
    post:
      summary: Create Payment Intent
      operationId: createPaymentIntent
      description: |
        Creates a payment intent for the draft return.

        Only call this when the `add-payment-intent` link is offered. The link is not offered
        when the shop has no usable Stripe connection, because the payment cannot be collected.
        In that case `draft_return.requires_uncollectible_payment` is `true`.
      security:
        - api_key: []
      parameters:
        - $ref: '#/components/parameters/DraftReturnId'
        - $ref: '#/components/parameters/ShopId'
        - $ref: '#/components/parameters/LoopLocale'
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required:
                - payment_source_type
                - provider_intent_id
              properties:
                payment_source_type:
                  type: string
                  enum: [stripe, shopify_payments]
                  description: The payment source type.
                provider_intent_id:
                  type: string
                  maxLength: 191
                  description: The payment provider's intent identifier.
                token:
                  type: [object, "null"]
                  description: Optional provider token payload.
      responses:
        "200":
          $ref: '#/components/responses/DraftReturnResponse'
        "401":
          $ref: '#/components/responses/UnauthorizedError'
        "422":
          $ref: '#/components/responses/ValidationError'

  /draft-returns/{draft_return_id}/payment-intent/{payment_intent_id}:
    delete:
      summary: Remove Payment Intent
      operationId: deletePaymentIntent
      description: Removes a payment intent from the draft return.
      security:
        - api_key: []
      parameters:
        - $ref: '#/components/parameters/DraftReturnId'
        - $ref: '#/components/parameters/ShopId'
        - name: payment_intent_id
          in: path
          description: The unique identifier of the payment intent to delete.
          required: true
          schema:
            type: integer
        - $ref: '#/components/parameters/LoopLocale'
      responses:
        "200":
          $ref: '#/components/responses/DraftReturnResponse'
        "401":
          $ref: '#/components/responses/UnauthorizedError'
        "422":
          $ref: '#/components/responses/ValidationError'

  /draft-returns/{draft_return_id}/submit:
    post:
      summary: Submit Draft Return
      operationId: submitDraftReturn
      description: |
        Submits the draft return.
        This finalizes the return and initiates any necessary workflows.
        Once the return has been submitted, it can be processed.

        If no return policy covers the address on the draft return, the response is a `422`
        with `errors[0].code` set to `returns-unavailable-for-order`. The draft return stays
        open. Do not retry the submit; ask the shopper for a different address or stop the return.

        If the cart still has Shop Now items while a credit item's excluded outcomes (as returned on its
        line item) include Shop Now, the response is a `422` with the message "Shop Now is not available
        for the items in this return. Remove the new items to continue." Remove those cart
        items and submit again. In-store (point of sale) returns are unaffected.

        The draft return is ready to submit when the `submit-draft-return` link (HAL-Forms: the
        `submit-draft-return` template) is present. Use it as the single readiness signal rather
        than working it out from other actions: Loop only offers it once every required step is
        complete.
      security:
        - api_key: []
      parameters:
        - $ref: '#/components/parameters/DraftReturnId'
        - $ref: '#/components/parameters/ShopId'
        - $ref: '#/components/parameters/LoopLocale'
      responses:
        "200":
          $ref: '#/components/responses/DraftReturnResponse'
        "401":
          $ref: '#/components/responses/UnauthorizedError'
        "422":
          $ref: '#/components/responses/ValidationError'
