> ## Documentation Index
> Fetch the complete documentation index at: https://docs.loopreturns.com/llms.txt
> Use this file to discover all available pages before exploring further.

# List Order Line Items

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




## OpenAPI

````yaml draft-returns-hal-forms get /draft-returns/{draft_return_id}/order/items
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)
security: []
paths:
  /draft-returns/{draft_return_id}/order/items:
    get:
      summary: List Order Line Items
      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.
      operationId: getDraftReturnOrderItemsHalForms
      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'
      security:
        - api_key: []
components:
  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
    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
    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
  schemas:
    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'
    HalLink:
      type: object
      properties:
        href:
          type: string
          description: The fully-qualified URL for this link relation.
      required:
        - href
  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.
  securitySchemes:
    api_key:
      type: apiKey
      in: header
      name: X-Authorization

````

This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.