> ## 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 Draft Returns

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




## OpenAPI

````yaml draft-returns-hal-forms get /draft-returns
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:
    get:
      summary: List Draft Returns
      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.
      operationId: listDraftReturnsHalForms
      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'
      security:
        - api_key: []
components:
  parameters:
    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
  schemas:
    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>
    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.
    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.
  responses:
    UnauthorizedError:
      description: API key is missing or invalid.
      content:
        application/json:
          schema:
            type: object
            properties:
              errors:
                type: array
                items:
                  type: object
                  properties:
                    code:
                      type: string
                      enum:
                        - unauthorized
                    message:
                      type: string
                      example: Unauthorized.
    ValidationError:
      description: Validation error occurred.
      content:
        application/json:
          schema:
            type: object
            properties:
              errors:
                type: array
                items:
                  type: object
                  properties:
                    code:
                      type: string
                      enum:
                        - validation-failed
                    message:
                      type: string
                      example: Validation failed.
  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.