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

    The Draft Returns API lets you build a complete return-creation flow by managing draft
    returns through a state machine. Endpoints allow you to initialize a draft, add or remove
    items, set customer and address details, finalize selections, and submit the completed return.

    This document describes the API as of version `2026-10`. Use
    `/api/2026-10/draft-returns/...` for production or `/api/unstable/draft-returns/...` to test upcoming changes.

    ## Response architecture

    Successful responses include `draft_return`, `context`, `errors`, plus hypermedia controls.

    ### `_links`

    An object keyed by relation name. Each value includes `href` and optional metadata:

    ```json
    {
      "_links": {
        "self": {
          "href": "https://api.loopreturns.com/api/2026-10/draft-returns/123"
        },
        "add-returning-item": {
          "href": "https://api.loopreturns.com/api/2026-10/draft-returns/123/returning-items"
        },
        "finalize-items": {
          "href": "https://api.loopreturns.com/api/2026-10/draft-returns/123/finalize-items"
        }
      }
    }
    ```

    ### `_templates`

    Each available action is described by a template in the `_templates` object:

    ```json
    {
      "_templates": {
        "add-returning-item": {
          "method": "POST",
          "title": "Add a line item to the return",
          "contentType": "application/json",
          "properties": [
            {
              "name": "order_line_item_id",
              "type": "number",
              "required": true,
              "prompt": "ID of the line item to return"
            }
          ]
        },
        "finalize-items": {
          "method": "POST",
          "title": "Lock in item selections and proceed",
          "contentType": "application/json",
          "properties": []
        }
      }
    }
    ```

    Each template may include:
    - `method`: The HTTP method (`POST`, `DELETE`, etc.)
    - `title`: Human-readable description of the action
    - `contentType`: The request content type (typically `application/json`)
    - `properties`: Array of field descriptors with `name`, `type`, `required`,
      `prompt`, and optionally `options` (for enum-like fields)
    - `required`: `true` when the action must be completed before the draft return can
      progress, for example while a label format still has to be picked. This flag belongs
      to the template. It is separate from `required` on each entry in `properties`, which
      only says whether that field must be sent in the request body
    - `systemMessage`: Only on a yes/no `add-returning-item-user-input` template, when the
      merchant turned on a "Response if yes" message. See User input below

    Whether an action's template is present, 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` template.

    ### `client_application`

    Responses include a `client_application` object describing how the client should
    identify itself on subsequent requests.

    ### Content type

    | Header | Value |
    |---|---|
    | `Accept` (request) | `application/prs.hal-forms+json` |
    | `Content-Type` (response) | `application/prs.hal-forms+json` |
    | `Content-Type` (request body) | `application/json` |

    Requests to version `2026-10` or later always return HAL-Forms format regardless of the
    `Accept` header, on every endpoint including `GET /draft-returns` (List). On earlier versions
    such as `2026-07`, send `Accept: application/prs.hal-forms+json` to get HAL-Forms; without that
    header, those versions respond with `application/json` and send merchant questions and messages
    as plain text. On those earlier versions, List is the exception: it requires the HAL-FORMS
    `Accept` header and returns `422` `unsupported-feature` when the header is missing or is
    `application/json`.

    ### Shopper token

    Shopper-portal draft responses include `shopper_token`.
    Send that value as `X-Loop-Shopper-Token` on later shopper-portal requests that include a
    draft return id. Merchant public API responses omit this field and do not require the header.
    A missing, empty, or non-matching token on those draft-id requests returns `404`.
    Create, initialize, and list do not require the header.

    ## State Machine

    ```
    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 Templates by State

    #### Created State

    `_templates` may include:

    - `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 template `options`
    - `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

    `_templates` may include:

    - `set-credit-type`: Choose how to receive the refund
    - `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`),
    `_templates` and `_links` will be empty objects.

    ## User input

    Each unanswered merchant question on a returning item has its own
    `add-returning-item-user-input` template. Its `title` is the question as HTML, because
    merchants can format questions. After the shopper answers, the question is in
    `returning_items[].user_inputs[]` with the same HTML in `prompt`. Sanitize this HTML before
    you show it.

    A yes/no template can include `systemMessage`, the merchant's "Response if yes" message.
    It is only present when the merchant turned that response on. Show it when the shopper
    answers `Yes`. If the merchant's rule rejects the item on `Yes`, the item is removed from the
    draft return and the next response does not include the message. Keep it from the template
    before you submit the answer, show it, then return the shopper to item selection.

    ```json
    {
      "_templates": {
        "add-returning-item-user-input:1:10": {
          "method": "POST",
          "title": "<p>Have the seals been broken?</p>",
          "systemMessage": "<p>Used cartridges cannot be returned.</p>"
        }
      }
    }
    ```

    ## Processing type

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

    In the `items-finalized` state, `_embedded.processing_type_options` shows whether each
    processing type is available, and the amounts for Instant. To change the processing type,
    use the `set-processing-type` template and send only a value from its `options`.

    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 `processing_type` to `regular`
    - removes the payment intent, so `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` template 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` template and link are not offered, and `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 `payment_intent` comes back `null`. Check `processing_type` and
    `payment_intent` before you submit. If a payment is still needed, `add-payment-intent` is
    offered again.

servers:
  - url: https://api.loopreturns.com/api/2026-10
    description: 2026-10 (Stable)
  - url: https://api.loopreturns.com/api/unstable
    description: Unstable (Preview)

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.

    HalLink:
      type: object
      properties:
        href:
          type: string
          description: The fully-qualified URL for this link relation.
      required:
        - href

    HalFormsTemplateProperty:
      type: object
      properties:
        name:
          type: string
          description: The property name (snake_case).
        type:
          type: string
          description: |
            The property type. Common types: `number`, `text`, `boolean`, `hidden`.
        required:
          type: boolean
          description: Whether this property is required.
        prompt:
          type: string
          description: Human-readable prompt/description of the property.
        options:
          type: object
          description: |
            For enum-like fields, an object with `inline` containing the list of valid values.
            Send only a value from this list.
          properties:
            inline:
              type: array
              description: |
                Each item is either a value string or an object with `prompt` and `value`.
                When it is an object, send its `value`.
              items:
                oneOf:
                  - type: string
                  - type: object
                    properties:
                      prompt:
                        type: string
                        description: Human-readable label for the value.
                      value:
                        type: string
                        description: The value to send in the request body.

    HalFormsTemplate:
      type: object
      properties:
        method:
          type: string
          description: The HTTP method for this action (POST, DELETE, etc.).
        title:
          type: string
          description: Human-readable title/description of the action.
        contentType:
          type: string
          description: The content type of the request body.
          default: application/json
        required:
          type: boolean
          description: |
            `true` when this action must be completed before the draft return can progress.
            For `select-return-method-carrier`, it is `true` while a label format still has to
            be picked and `false` once one is selected.

            This flag belongs to the template. It is separate from `required` on each entry in
            `properties`, which only says whether that field must be sent in the request body.
        properties:
          type: array
          description: Property descriptors for the action's fields.
          items:
            $ref: '#/components/schemas/HalFormsTemplateProperty'
        systemMessage:
          type: string
          description: |
            Only on an unanswered yes/no `add-returning-item-user-input` template. The merchant's
            "Response if yes" message in the draft return's language. When that language has no
            translation, it is the merchant's first configured message. It may contain HTML.
            Omitted when the merchant has not turned the response on or has no message.

            Show this message when the shopper answers `Yes`. If that answer removes the item
            from the draft return, the next response no longer has the item or its answered
            input, so keep this value from the template before you submit the answer.
          example: "<p>Used cartridges cannot be returned.</p>"

    HalFormsLinks:
      type: object
      description: |
        HAL `_links` object. Always includes `self`. Other keys are relation names
        corresponding to available actions for the current draft return state.
      properties:
        self:
          $ref: '#/components/schemas/HalLink'
      additionalProperties:
        $ref: '#/components/schemas/HalLink'

    HalFormsTemplates:
      type: object
      description: |
        `_templates` object. Each key is a template/action name matching a
        relation in `_links`. Templates describe the method, fields, and constraints
        for the action.
      additionalProperties:
        $ref: '#/components/schemas/HalFormsTemplate'

    DraftReturn:
      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` template. `_embedded.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
              example: "Jane Doe"
            company:
              type: [string, 'null']
              example: null
            address1:
              type: string
              example: "123 Main St"
            address2:
              type: [string, 'null']
              example: "Apt 4"
            city:
              type: string
              example: "Chicago"
            state:
              type: string
              example: "Illinois"
            zip:
              type: string
              example: "60622"
            country:
              type: string
              example: "United States"
            country_code:
              type: string
              example: "US"
            phone:
              type: [string, 'null']
              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']
                enum:
                  - credit
                  - exchange
                  - null
                example: "credit"
              resolution:
                type: [string, 'null']
                enum:
                  - return
                  - keep
                  - donate
                  - reject
                  - exchange
                  - null
                example: "return"
              return_reason:
                type: [object, 'null']
                properties:
                  name:
                    type: string
                    example: "Item didn't fit"
                  comment:
                    type: [string, 'null']
                    example: null
              user_inputs:
                type: array
                items:
                  type: object
                  properties:
                    id:
                      type: integer
                      example: 1
                    type:
                      type: string
                      example: "yes-no"
                    prompt:
                      type: string
                      description: The merchant's question as HTML.
                      example: "<p>Is the item still in its original packaging?</p>"
                    value:
                      type: [string, boolean, 'null']
                      example: true
              image_uploads:
                type: array
                items:
                  type: string
                  example: "https://cdn.example.com/return-images/abc123.jpg"
        cart_items:
          type: array
          description: The items in the cart (exchange items or shop-now items).
          items:
            type: object
            properties:
              id:
                type: integer
                example: 201
              variant_id:
                type: integer
                example: 501
              product_id:
                type: [integer, 'null']
                example: 100
              sku:
                type: [string, 'null']
                example: "SHIRT-RED-S"
              title:
                type: [string, 'null']
                example: "Red Shirt"
              variant_title:
                type: [string, 'null']
                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 in minor units (e.g. cents).
                example: 2500
              image:
                type: [string, 'null']
                example: "https://cdn.example.com/products/red-shirt.jpg"
              exchange_type:
                type: [string, 'null']
                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']
                example: 1
        selected_return_method:
          type: [object, 'null']
          description: The selected return shipping method.
          properties:
            id:
              type: integer
            name:
              type: string
            type:
              type: string
              enum:
                - box-and-ship
                - carrier-choice
                - drop-off
                - pick-up
                - in-store
            title:
              type: string
            logo_url:
              type: string
            location_url:
              type: string
        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
            provider_intent_id:
              type: string
        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` template
            and link are 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

    DraftReturnContext:
      type: object
      description: |
        Contextual data for building the return UI. Keys are omitted when their value is null.
      properties:
        languages:
          type: [array, 'null']
          items:
            type: object
            properties:
              name:
                type: string
              abbreviation:
                type: string
        order:
          type: [object, 'null']
          properties:
            id:
              type: integer
            currency:
              type: string
            original_payment_transactions:
              type: array
              items:
                type: object
                properties:
                  type:
                    type: string
                  gateway:
                    type: [string, 'null']
                  amount:
                    type: integer
                  currency:
                    type: string
                  brand:
                    type: [string, 'null']
                  last4:
                    type: [integer, 'null']
            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']
                  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']
          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']
          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']
          items:
            type: object
            properties:
              order_line_item_id:
                type: integer
              ineligibility_code:
                type: string
              expiration:
                type: [string, 'null']
        return_reason_options:
          type: [array, 'null']
          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']
          items:
            type: object
            properties:
              product_options:
                type: [array, 'null']
                items:
                  type: object
                  properties:
                    name:
                      type: string
                    values:
                      type: array
                    position:
                      type: [integer, 'null']
                      description: |
                        The 1-based Shopify product option position this dimension maps to.
                        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
                items:
                  type: object
                  properties:
                    product_id:
                      type: [integer, 'null']
                    variant_id:
                      type: integer
                    title:
                      type: [string, 'null']
                    variant_title:
                      type: [string, 'null']
                    product_type:
                      type: [string, 'null']
                    options:
                      type: object
                      additionalProperties:
                        type: string
                    image:
                      type: [string, 'null']
                    price:
                      type: [integer, 'null']
                    currency:
                      type: [string, 'null']
                    is_available:
                      type: boolean
                    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']
          items:
            type: object
            properties:
              id:
                type: integer
              name:
                type: string
              type:
                type: string
                enum:
                  - box-and-ship
                  - carrier-choice
                  - drop-off
                  - pick-up
                  - in-store
              fee:
                type: integer
              title:
                type: string
              logo_url:
                type: string
              location_url:
                type: string
        processing_type_options:
          $ref: '#/components/schemas/ProcessingTypeOptions'

    ProcessingTypeOptions:
      type: object
      description: |
        Which processing types the draft return can use. In HAL-Forms responses this object is
        at `_embedded.processing_type_options`.

        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

    DraftReturnError:
      type: object
      properties:
        code:
          type: string
          description: The error code.
          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.

  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

    ShopperToken:
      name: X-Loop-Shopper-Token
      in: header
      required: false
      description: |
        Shopper-portal only. The `shopper_token` from a shopper-portal draft response.
        Required on shopper-portal requests that include a draft return id.
        A missing, empty, or non-matching value returns `404`.
        Merchant public API requests ignore this header.
      schema:
        type: string

    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

    AcceptHalForms:
      name: Accept
      in: header
      required: false
      description: |
        Optional. Responses use `Content-Type: application/prs.hal-forms+json`. Ignored on `2026-10`
        and later. On earlier versions, send it to receive HAL-Forms, and it is required for
        `GET /draft-returns` (List).
      schema:
        type: string
        enum:
          - application/prs.hal-forms+json


  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."

    ShopperDraftReturnNotFound:
      description: |
        Not found. On shopper-portal draft-id requests, also returned when
        `X-Loop-Shopper-Token` is missing, empty, or does not match the draft.

    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."

    HalFormsDraftReturnResponse:
      description: |
        Successful response with draft return data.

        The response uses `Content-Type: application/prs.hal-forms+json` and includes hypermedia
        controls in `_links` and `_templates` instead of the standard `links` array.
      content:
        application/prs.hal-forms+json:
          schema:
            type: object
            properties:
              _links:
                $ref: '#/components/schemas/HalFormsLinks'
              _templates:
                $ref: '#/components/schemas/HalFormsTemplates'
              client_application:
                type: object
                description: |
                  Client-application header specification. Describes how the client should
                  identify itself in subsequent requests.
              shopper_token:
                type: string
                description: |
                  Shopper-portal only. Present on shopper-portal draft responses.
                  Send this value as `X-Loop-Shopper-Token` on later shopper-portal requests
                  that include a draft return id.
                  Merchant public API responses omit this field.
              draft_return:
                $ref: '#/components/schemas/DraftReturn'
              context:
                $ref: '#/components/schemas/DraftReturnContext'
              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:
                  $ref: '#/components/schemas/DraftReturnError'

paths:
  /draft-returns/{draft_return_id}:
    get:
      summary: Get Draft Return
      operationId: getDraftReturnHalForms
      description: |
        Retrieves a draft return as a draft return.

        The response includes the draft return data, context, and hypermedia controls
        (`_links` and `_templates`) describing available actions based on the current state.

      security:
        - api_key: []
      parameters:
        - $ref: '#/components/parameters/DraftReturnId'
        - $ref: '#/components/parameters/ShopId'
        - $ref: '#/components/parameters/LoopLocale'
        - $ref: '#/components/parameters/AcceptHalForms'
        - $ref: '#/components/parameters/ShopperToken'
      responses:
        "200":
          $ref: '#/components/responses/HalFormsDraftReturnResponse'
        "401":
          $ref: '#/components/responses/UnauthorizedError'
        "404":
          $ref: '#/components/responses/ShopperDraftReturnNotFound'
        "422":
          $ref: '#/components/responses/ValidationError'

  /draft-returns/{draft_return_id}/order/items:
    get:
      summary: List Order Line Items
      operationId: getDraftReturnOrderItemsHalForms
      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/AcceptHalForms'
        - $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
        - $ref: '#/components/parameters/ShopperToken'
      responses:
        "200":
          description: OK
          content:
            application/prs.hal-forms+json:
              schema:
                type: object
                properties:
                  _links:
                    $ref: '#/components/schemas/HalFormsLinks'
                  _embedded:
                    type: object
                    properties:
                      items:
                        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":
          $ref: '#/components/responses/ShopperDraftReturnNotFound'

  /draft-returns/{draft_return_id}/totals:
    get:
      summary: Get Draft Return Totals
      operationId: getDraftReturnTotalsHalForms
      description: |
        Returns the computed monetary totals for the draft return. 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'
        - $ref: '#/components/parameters/AcceptHalForms'
        - $ref: '#/components/parameters/ShopperToken'
      responses:
        "200":
          description: OK
          content:
            application/prs.hal-forms+json:
              schema:
                type: object
                properties:
                  _links:
                    $ref: '#/components/schemas/HalFormsLinks'
                  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
                      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":
          $ref: '#/components/responses/ShopperDraftReturnNotFound'

  /draft-returns:
    get:
      summary: List Draft Returns
      operationId: listDraftReturnsHalForms
      description: |
        Returns a collection describing the draft-return actions available for
        the shop.

        On `2026-10` and later, the `Accept` header is ignored and the response is always HAL-Forms.
        On earlier versions such as `2026-07`, **this endpoint requires
        `Accept: application/prs.hal-forms+json`**; any other Accept value returns an
        `unsupported-feature` error. This is the entry point for clients
        to discover available actions and initialize new draft returns.

        The response includes `_templates` describing available operations (e.g. `initialize`)
        and `_embedded` containing any existing draft returns for the shop.
      security:
        - api_key: []
      parameters:
        - $ref: '#/components/parameters/ShopId'
        - $ref: '#/components/parameters/AcceptHalForms'
      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
                        description: Existing draft returns for this shop, if any.
                        items:
                          type: object
                  client_application:
                    type: object
                    description: The client-application header specification.
                  _templates:
                    type: object
                    description: |
                      templates for the available actions, keyed by template name.
                      Typically includes an `initialize` template for creating a new draft return.
                    additionalProperties:
                      $ref: '#/components/schemas/HalFormsTemplate'
                  errors:
                    type: array
                    items:
                      $ref: '#/components/schemas/DraftReturnError'
        "401":
          $ref: '#/components/responses/UnauthorizedError'
        "422":
          $ref: '#/components/responses/ValidationError'

    post:
      summary: Initialize Draft Return
      operationId: initializeDraftReturnHalForms
      description: |
        Initialize a new draft return and receive a response.

        The return created using this endpoint can be configured and modified using
        the other draft return API endpoints. This endpoint should be the first
        one called. The response includes the initial state of the draft return
        and `_links` / `_templates` describing the next available actions.

      security:
        - api_key: []
      parameters:
        - $ref: '#/components/parameters/ShopId'
        - $ref: '#/components/parameters/AcceptHalForms'
        - $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.
                  examples:
                    - false
      responses:
        "200":
          $ref: '#/components/responses/HalFormsDraftReturnResponse'
        "401":
          $ref: '#/components/responses/UnauthorizedError'
        "422":
          $ref: '#/components/responses/ValidationError'

  /draft-returns/{draft_return_id}/accept-return-policy:
    post:
      summary: Accept Return Policy
      operationId: acceptReturnPolicyHalForms
      description: |
        Records the customer's acceptance of the return policy.

      security:
        - api_key: []
      parameters:
        - $ref: '#/components/parameters/DraftReturnId'
        - $ref: '#/components/parameters/ShopId'
        - $ref: '#/components/parameters/AcceptHalForms'
        - $ref: '#/components/parameters/LoopLocale'
        - $ref: '#/components/parameters/ShopperToken'
      responses:
        "200":
          $ref: '#/components/responses/HalFormsDraftReturnResponse'
        "401":
          $ref: '#/components/responses/UnauthorizedError'
        "404":
          $ref: '#/components/responses/ShopperDraftReturnNotFound'
        "422":
          $ref: '#/components/responses/ValidationError'

  /draft-returns/{draft_return_id}/cancel:
    post:
      summary: Cancel Draft Return
      operationId: cancelDraftReturnHalForms
      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/AcceptHalForms'
        - $ref: '#/components/parameters/LoopLocale'
        - $ref: '#/components/parameters/ShopperToken'
      responses:
        "200":
          $ref: '#/components/responses/HalFormsDraftReturnResponse'
        "401":
          $ref: '#/components/responses/UnauthorizedError'
        "404":
          $ref: '#/components/responses/ShopperDraftReturnNotFound'
        "422":
          $ref: '#/components/responses/ValidationError'

  /draft-returns/{draft_return_id}/customer:
    post:
      summary: Set Customer
      operationId: setCustomerHalForms
      description: |
        Sets the customer information for the draft return.

      security:
        - api_key: []
      parameters:
        - $ref: '#/components/parameters/DraftReturnId'
        - $ref: '#/components/parameters/ShopId'
        - $ref: '#/components/parameters/AcceptHalForms'
        - $ref: '#/components/parameters/LoopLocale'
        - $ref: '#/components/parameters/ShopperToken'
      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/HalFormsDraftReturnResponse'
        "401":
          $ref: '#/components/responses/UnauthorizedError'
        "404":
          $ref: '#/components/responses/ShopperDraftReturnNotFound'
        "422":
          $ref: '#/components/responses/ValidationError'

  /draft-returns/{draft_return_id}/address:
    post:
      summary: Set Address
      operationId: setAddressHalForms
      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/AcceptHalForms'
        - $ref: '#/components/parameters/LoopLocale'
        - $ref: '#/components/parameters/ShopperToken'
      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/HalFormsDraftReturnResponse'
        "401":
          $ref: '#/components/responses/UnauthorizedError'
        "404":
          $ref: '#/components/responses/ShopperDraftReturnNotFound'
        "422":
          $ref: '#/components/responses/ValidationError'

  /draft-returns/{draft_return_id}/returning-items:
    post:
      summary: Add Returning Item
      operationId: addReturningItemHalForms
      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/AcceptHalForms'
        - $ref: '#/components/parameters/LoopLocale'
        - $ref: '#/components/parameters/ShopperToken'
      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/HalFormsDraftReturnResponse'
        "401":
          $ref: '#/components/responses/UnauthorizedError'
        "404":
          $ref: '#/components/responses/ShopperDraftReturnNotFound'
        "422":
          $ref: '#/components/responses/ValidationError'

  /draft-returns/{draft_return_id}/returning-items/{returning_item_id}:
    delete:
      summary: Remove Returning Item
      operationId: removeReturningItemHalForms
      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/AcceptHalForms'
        - $ref: '#/components/parameters/LoopLocale'
        - $ref: '#/components/parameters/ShopperToken'
      responses:
        "200":
          $ref: '#/components/responses/HalFormsDraftReturnResponse'
        "401":
          $ref: '#/components/responses/UnauthorizedError'
        "404":
          $ref: '#/components/responses/ShopperDraftReturnNotFound'
        "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: setReturningItemReturnReasonHalForms
      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/AcceptHalForms'
        - $ref: '#/components/parameters/LoopLocale'
        - $ref: '#/components/parameters/ShopperToken'
      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/HalFormsDraftReturnResponse'
        "401":
          $ref: '#/components/responses/UnauthorizedError'
        "404":
          $ref: '#/components/responses/ShopperDraftReturnNotFound'
        "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: addReturningItemUserInputHalForms
      description: |
        Adds user input for a specific returning item. This allows collecting additional
        information from the customer about their return.

        For a yes/no question, the `add-returning-item-user-input` template can include
        `systemMessage`, the merchant's "Response if yes" message. Show it when the shopper
        answers `Yes`. If that answer removes the item from the draft return, this response no
        longer has the item, so read `systemMessage` from the template before you call this
        endpoint.

      security:
        - api_key: []
      parameters:
        - $ref: '#/components/parameters/DraftReturnId'
        - $ref: '#/components/parameters/ReturningItemId'
        - $ref: '#/components/parameters/UserInputId'
        - $ref: '#/components/parameters/ShopId'
        - $ref: '#/components/parameters/AcceptHalForms'
        - $ref: '#/components/parameters/LoopLocale'
        - $ref: '#/components/parameters/ShopperToken'
      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/HalFormsDraftReturnResponse'
        "401":
          $ref: '#/components/responses/UnauthorizedError'
        "404":
          $ref: '#/components/responses/ShopperDraftReturnNotFound'
        "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: setReturningItemReturnTypeHalForms
      description: |
        Sets the return type for a specific returning item.

        The allowed values depend on the item. Send only a value from the `options` of that
        item's `set-returning-item-return-type` template. 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.
        - `inline-exchange` is offered with `exchange` unless a workflow excludes inline
          exchanges for the item. Allowlisted orders ignore that exclusion. The number of
          variants does not matter, so a single-variant item gets `inline-exchange` too. Loop
          saves `inline-exchange` as `exchange`, so `return_type` reads `exchange` afterward.

          Offer a same-product exchange, to another variant or to the purchased variant, only
          when `inline-exchange` is offered. `exchange` alone still covers Advanced Exchange.
        - `replace` is offered for warranty replacements. Loop saves it as `exchange`, so
          `return_type` reads `exchange` afterward. Like `inline-exchange`, it is not offered
          when a workflow excludes inline exchanges, unless the order is allowlisted.
        - On a warranty claim, `exchange` and `replace` are not offered for an item with no
          catalog product or variant, such as a deleted product or a custom line item. If that
          leaves the warranty with no outcome, the item is not eligible for the warranty claim.
        - `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/AcceptHalForms'
        - $ref: '#/components/parameters/LoopLocale'
        - $ref: '#/components/parameters/ShopperToken'
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required:
                - return_type
              properties:
                return_type:
                  type: string
                  enum: [credit, exchange, inline-exchange, replace]
                  description: |
                    The type of return for the line item. Must be one of the values in the item's
                    template `options`.
      responses:
        "200":
          $ref: '#/components/responses/HalFormsDraftReturnResponse'
        "401":
          $ref: '#/components/responses/UnauthorizedError'
        "404":
          $ref: '#/components/responses/ShopperDraftReturnNotFound'
        "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: addReturningItemExchangeItemHalForms
      description: |
        Adds an exchange item for a specific returning item to the cart.

        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'
        - $ref: '#/components/parameters/AcceptHalForms'
        - $ref: '#/components/parameters/ShopperToken'
      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/HalFormsDraftReturnResponse'
        "401":
          $ref: '#/components/responses/UnauthorizedError'
        "404":
          $ref: '#/components/responses/ShopperDraftReturnNotFound'
        "422":
          $ref: '#/components/responses/ValidationError'

  /draft-returns/{draft_return_id}/finalize-items:
    post:
      summary: Finalize Items
      operationId: finalizeItemsHalForms
      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/AcceptHalForms'
        - $ref: '#/components/parameters/LoopLocale'
        - $ref: '#/components/parameters/ShopperToken'
      responses:
        "200":
          $ref: '#/components/responses/HalFormsDraftReturnResponse'
        "401":
          $ref: '#/components/responses/UnauthorizedError'
        "404":
          $ref: '#/components/responses/ShopperDraftReturnNotFound'
        "422":
          $ref: '#/components/responses/ValidationError'

  /draft-returns/{draft_return_id}/unfinalize-items:
    post:
      summary: Unfinalize Items
      operationId: unfinalizeItemsHalForms
      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/AcceptHalForms'
        - $ref: '#/components/parameters/LoopLocale'
        - $ref: '#/components/parameters/ShopperToken'
      responses:
        "200":
          $ref: '#/components/responses/HalFormsDraftReturnResponse'
        "401":
          $ref: '#/components/responses/UnauthorizedError'
        "404":
          $ref: '#/components/responses/ShopperDraftReturnNotFound'
        "422":
          $ref: '#/components/responses/ValidationError'

  /draft-returns/{draft_return_id}/cart/items/{cart_item_id}:
    delete:
      summary: Remove Cart Item
      operationId: removeCartItemHalForms
      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/AcceptHalForms'
        - $ref: '#/components/parameters/LoopLocale'
        - $ref: '#/components/parameters/ShopperToken'
      responses:
        "200":
          $ref: '#/components/responses/HalFormsDraftReturnResponse'
        "401":
          $ref: '#/components/responses/UnauthorizedError'
        "404":
          $ref: '#/components/responses/ShopperDraftReturnNotFound'
        "422":
          $ref: '#/components/responses/ValidationError'

  /draft-returns/{draft_return_id}/cart/items:
    post:
      summary: Add Cart Item
      operationId: addCartItemHalForms
      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'
        - $ref: '#/components/parameters/AcceptHalForms'
        - $ref: '#/components/parameters/ShopperToken'
      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/HalFormsDraftReturnResponse'
        "401":
          $ref: '#/components/responses/UnauthorizedError'
        "404":
          $ref: '#/components/responses/ShopperDraftReturnNotFound'
        "422":
          $ref: '#/components/responses/ValidationError'

  /draft-returns/{draft_return_id}/credit-type:
    post:
      summary: Set Credit Type
      operationId: setCreditTypeHalForms
      description: |
        Sets the credit type for the draft return.

      security:
        - api_key: []
      parameters:
        - $ref: '#/components/parameters/DraftReturnId'
        - $ref: '#/components/parameters/ShopId'
        - $ref: '#/components/parameters/AcceptHalForms'
        - $ref: '#/components/parameters/LoopLocale'
        - $ref: '#/components/parameters/ShopperToken'
      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/HalFormsDraftReturnResponse'
        "401":
          $ref: '#/components/responses/UnauthorizedError'
        "404":
          $ref: '#/components/responses/ShopperDraftReturnNotFound'
        "422":
          $ref: '#/components/responses/ValidationError'

    delete:
      summary: Unset Credit Type
      operationId: unsetCreditTypeHalForms
      description: |
        Removes the credit type selection from the draft return.

      security:
        - api_key: []
      parameters:
        - $ref: '#/components/parameters/DraftReturnId'
        - $ref: '#/components/parameters/ShopId'
        - $ref: '#/components/parameters/AcceptHalForms'
        - $ref: '#/components/parameters/LoopLocale'
        - $ref: '#/components/parameters/ShopperToken'
      responses:
        "200":
          $ref: '#/components/responses/HalFormsDraftReturnResponse'
        "401":
          $ref: '#/components/responses/UnauthorizedError'
        "404":
          $ref: '#/components/responses/ShopperDraftReturnNotFound'
        "422":
          $ref: '#/components/responses/ValidationError'

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

        Only call this when the `set-processing-type` template 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 template's `options`.

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

        Setting `regular` removes any payment intent, so `payment_intent` is `null`. Setting
        `instant` means the draft needs a payment intent before you submit. See
        [Create Payment Intent](/api-reference/unreleased/draft-returns/create-payment-intent).

        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 `_embedded.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/AcceptHalForms'
        - $ref: '#/components/parameters/LoopLocale'
        - $ref: '#/components/parameters/ShopperToken'
      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` template `options`.
      responses:
        "200":
          $ref: '#/components/responses/HalFormsDraftReturnResponse'
        "401":
          $ref: '#/components/responses/UnauthorizedError'
        "404":
          $ref: '#/components/responses/ShopperDraftReturnNotFound'
        "422":
          $ref: '#/components/responses/ValidationError'

  /draft-returns/{draft_return_id}/return-method:
    post:
      summary: Select Return Method
      operationId: selectReturnMethodHalForms
      description: |
        Selects a return method for the draft return.

      security:
        - api_key: []
      parameters:
        - $ref: '#/components/parameters/DraftReturnId'
        - $ref: '#/components/parameters/ShopId'
        - $ref: '#/components/parameters/AcceptHalForms'
        - $ref: '#/components/parameters/LoopLocale'
        - $ref: '#/components/parameters/ShopperToken'
      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/HalFormsDraftReturnResponse'
        "401":
          $ref: '#/components/responses/UnauthorizedError'
        "404":
          $ref: '#/components/responses/ShopperDraftReturnNotFound'
        "422":
          $ref: '#/components/responses/ValidationError'

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

        The `select-return-method-carrier` template stays in `_templates` after a label format
        is selected, so the format can be changed until the draft return is submitted. Its
        template-level `required` flag (see `HalFormsTemplate`) 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, `required` is `true` until one is selected. If it
        offers only one, Loop selects that format and `required` is `false`.

      security:
        - api_key: []
      parameters:
        - $ref: '#/components/parameters/DraftReturnId'
        - $ref: '#/components/parameters/ShopId'
        - $ref: '#/components/parameters/AcceptHalForms'
        - $ref: '#/components/parameters/LoopLocale'
        - $ref: '#/components/parameters/ShopperToken'
      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/HalFormsDraftReturnResponse'
        "401":
          $ref: '#/components/responses/UnauthorizedError'
        "404":
          $ref: '#/components/responses/ShopperDraftReturnNotFound'
        "422":
          $ref: '#/components/responses/ValidationError'

  /draft-returns/{draft_return_id}/language:
    post:
      summary: Set Language
      operationId: setLanguageHalForms
      description: |
        Sets the display language for the draft return.

      security:
        - api_key: []
      parameters:
        - $ref: '#/components/parameters/DraftReturnId'
        - $ref: '#/components/parameters/ShopId'
        - $ref: '#/components/parameters/AcceptHalForms'
        - $ref: '#/components/parameters/LoopLocale'
        - $ref: '#/components/parameters/ShopperToken'
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required:
                - language_code
              properties:
                language_code:
                  type: string
                  description: The language code (e.g. en, fr, de).
      responses:
        "200":
          $ref: '#/components/responses/HalFormsDraftReturnResponse'
        "401":
          $ref: '#/components/responses/UnauthorizedError'
        "404":
          $ref: '#/components/responses/ShopperDraftReturnNotFound'
        "422":
          $ref: '#/components/responses/ValidationError'

  /draft-returns/{draft_return_id}/currency:
    post:
      summary: Set Presentment Currency
      operationId: setPresentmentCurrencyHalForms
      description: |
        Sets the presentment currency for the draft return.

      security:
        - api_key: []
      parameters:
        - $ref: '#/components/parameters/DraftReturnId'
        - $ref: '#/components/parameters/ShopId'
        - $ref: '#/components/parameters/AcceptHalForms'
        - $ref: '#/components/parameters/LoopLocale'
        - $ref: '#/components/parameters/ShopperToken'
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required:
                - currency_code
              properties:
                currency_code:
                  type: string
                  description: The ISO 4217 currency code.
      responses:
        "200":
          $ref: '#/components/responses/HalFormsDraftReturnResponse'
        "401":
          $ref: '#/components/responses/UnauthorizedError'
        "404":
          $ref: '#/components/responses/ShopperDraftReturnNotFound'
        "422":
          $ref: '#/components/responses/ValidationError'

  /draft-returns/{draft_return_id}/cart:
    post:
      summary: Set Cart
      operationId: setCartHalForms
      description: |
        Sets the entire cart for the draft return in a single request.

        Returns a `422` when the cart adds Shop Now items (cart items 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/AcceptHalForms'
        - $ref: '#/components/parameters/LoopLocale'
        - $ref: '#/components/parameters/ShopperToken'
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                items:
                  type: array
                  items:
                    type: object
                    required:
                      - variant_id
                    properties:
                      variant_id:
                        type: integer
                      quantity:
                        type: integer
      responses:
        "200":
          $ref: '#/components/responses/HalFormsDraftReturnResponse'
        "401":
          $ref: '#/components/responses/UnauthorizedError'
        "404":
          $ref: '#/components/responses/ShopperDraftReturnNotFound'
        "422":
          $ref: '#/components/responses/ValidationError'

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

        Only call this when the `add-payment-intent` template is offered. The template is not
        offered when the shop has no usable Stripe connection, because the payment cannot be
        collected. In that case `requires_uncollectible_payment` is `true`.

      security:
        - api_key: []
      parameters:
        - $ref: '#/components/parameters/DraftReturnId'
        - $ref: '#/components/parameters/ShopId'
        - $ref: '#/components/parameters/AcceptHalForms'
        - $ref: '#/components/parameters/LoopLocale'
        - $ref: '#/components/parameters/ShopperToken'
      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/HalFormsDraftReturnResponse'
        "401":
          $ref: '#/components/responses/UnauthorizedError'
        "404":
          $ref: '#/components/responses/ShopperDraftReturnNotFound'
        "422":
          $ref: '#/components/responses/ValidationError'

  /draft-returns/{draft_return_id}/payment-intent/{payment_intent_id}:
    delete:
      summary: Remove Payment Intent
      operationId: deletePaymentIntentHalForms
      description: |
        Removes a payment intent from the draft return.

      security:
        - api_key: []
      parameters:
        - $ref: '#/components/parameters/DraftReturnId'
        - $ref: '#/components/parameters/ShopId'
        - $ref: '#/components/parameters/AcceptHalForms'
        - 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'
        - $ref: '#/components/parameters/ShopperToken'
      responses:
        "200":
          $ref: '#/components/responses/HalFormsDraftReturnResponse'
        "401":
          $ref: '#/components/responses/UnauthorizedError'
        "404":
          $ref: '#/components/responses/ShopperDraftReturnNotFound'
        "422":
          $ref: '#/components/responses/ValidationError'

  /draft-returns/{draft_return_id}/submit:
    post:
      summary: Submit Draft Return
      operationId: submitDraftReturnHalForms
      description: |
        Submits the draft return.

        This finalizes the return and initiates any necessary workflows.
        Once submitted, the `draft_return.return_id` is populated and the state moves to
        `submitted`.

        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/AcceptHalForms'
        - $ref: '#/components/parameters/LoopLocale'
        - $ref: '#/components/parameters/ShopperToken'
      responses:
        "200":
          $ref: '#/components/responses/HalFormsDraftReturnResponse'
        "401":
          $ref: '#/components/responses/UnauthorizedError'
        "404":
          $ref: '#/components/responses/ShopperDraftReturnNotFound'
        "422":
          $ref: '#/components/responses/ValidationError'
