> For the complete documentation index, see [llms.txt](https://developer.esw.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://developer.esw.com/returns-api/resources/tutorials/updating-a-return-order.md).

# Updating a Return Order

The return order update endpoint is the primary mechanism through which warehouse staff and CS agents record what happened to a return after it was created. It allows updating the overall order status, the outcome of individual returned items (accepted or rejected), and the physical weight of the received parcel.

```http
PUT /{identifier}/orders/{orderReference}/return-orders/{returnOrderNumber}
Authorization: Bearer <token>
Content-Type: application/json
```

***

{% stepper %}
{% step %}

### Who Calls This Endpoint and When

The update endpoint is called by:

* **Warehouse processing systems** — when a return parcel arrives and is inspected, the WMS records the outcome per item (`Accepted` or `Rejected`)
* **Customer service agents** — when an order needs to be placed on hold, released from hold, or cancelled
* **ESW operations** — when manifest and admin centre processing updates the order status

***

{% endstep %}

{% step %}

### Request Structure

All fields in `UpdateReturnOrderWebRequest` are optional. Provide only the fields you need to update — unmentioned fields are not changed.

{% code expandable="true" %}

```json
PUT /MYBRAND/orders/ORD-2024-78542/return-orders/5000002303

{
  "status": "Received",
  "statusReason": null,
  "returnItems": [ ... ],
  "weight": {
    "weightTotal": 0.28,
    "weightUnit": "KG"
  }
}
```

{% endcode %}

| Field          | Type                                | When to provide                                   |
| -------------- | ----------------------------------- | ------------------------------------------------- |
| `status`       | `ReturnOrderStatus` enum            | When the overall order status changes             |
| `statusReason` | string                              | When placing on hold — explains why               |
| `returnItems`  | array of `UpdateReturnOrderItemDto` | When recording warehouse inspection outcomes      |
| `weight`       | `WeightDto`                         | When actual parcel weight is confirmed on arrival |

***

{% endstep %}

{% step %}

### Updating `status`&#x20;

Not every status can be set via a retailer PUT call. Some transitions are triggered by ESW's internal systems (manifest processing, financial settlement). The following are the statuses you would typically set via the API:

#### `"Received"` — parcel arrived at warehouse

```json
"status": "Received"
```

Set this when the return parcel has been physically received and scanned in at ESW's returns warehouse. This transitions the order from `Created` (in transit) to `Received` (at warehouse, awaiting inspection).

**Who sets it:** Warehouse WMS or ESW warehouse system.

***

#### `"OnHold"`&#x20;

```json
"status": "OnHold",
"statusReason": "Parcel received but contents unrecognisable — awaiting CS investigation"
```

Set this when processing must be paused — typically because there is a problem requiring investigation. Always include `statusReason` when setting `OnHold` so the reason is visible to CS agents.

**Who sets it:** Warehouse staff (escalation), CS agents.

***

#### `"Released"`&#x20;

```json
"status": "Released"
```

Set this when a hold has been resolved and the return can continue through the normal processing flow.

**Who sets it:** CS agents after resolving the hold issue.

***

#### `"Processed"`&#x20;

```json
"status": "Processed"
```

Set this when all items in the return have been inspected and their outcomes recorded (accepted/rejected), and the return is ready to be added to the outbound manifest for return to the retailer.

**Who sets it:** Warehouse WMS after all items are processed.

***

#### `"Cancelled"`&#x20;

```json
"status": "Cancelled",
"statusReason": "Shopper requested cancellation before parcel was dispatched"
```

Set this when the return order should no longer be processed. Include `statusReason` to explain why.

**Who sets it:** CS agents on shopper request, or automated systems for expired returns.

**Note:** Cancellation is only valid before the parcel has been physically received. Once `status` is `Received` or beyond, cancellation may not be permitted.

***

#### ESW-managed statuses&#x20;

| Status                | Set by                                 |
| --------------------- | -------------------------------------- |
| `AddedToManifest`     | ESW manifest system                    |
| `SentToRetailer`      | ESW logistics                          |
| `ReceivedByRetailer`  | Retailer confirmation or ESW logistics |
| `RemovedFromManifest` | ESW manifest system                    |
| `Refunded`            | ESW financial systems                  |

***

{% endstep %}

{% step %}

### `statusReason`&#x20;

`statusReason` is a free-text string that provides context for a status change. It is most important when `status` is `"OnHold"` or `"Cancelled"`.

```json
"statusReason": "On hold due to suspected counterfeit product — Brand Protection team reviewing"
```

Best practices:

* Always include `statusReason` when setting `OnHold`
* Keep the reason concise but specific — it will be read by CS agents and ESW operations
* Include who raised the hold and why
* When releasing (`Released`), you can omit `statusReason` or include a brief note on resolution

***

{% endstep %}

{% step %}

### Updating `returnItems`&#x20;

`returnItems` in the update request records what happened to each item when the warehouse inspected it. Provide one entry per item whose status is changing.

{% code expandable="true" %}

```json
"returnItems": [
  {
    "id": "653995b0-d9e6-4018-9b85-d66d051b57e7",
    "productCode": "SKU-00123",
    "lineItemId": "1",
    "returnItemStatus": "Accepted"
  },
  {
    "id": "7a4c12e1-f3b2-4891-c73d-e88f162a9b45",
    "productCode": "SKU-00456",
    "lineItemId": "2",
    "returnItemStatus": "Rejected",
    "rejectionReason": "UsedItem",
    "reasonCodeOverride": "Defective"
  }
]
```

{% endcode %}

<details>

<summary><code>UpdateReturnOrderItemDto</code> fields</summary>

| Field                | Type          | Description                                                                   |
| -------------------- | ------------- | ----------------------------------------------------------------------------- |
| `id`                 | string (UUID) | The return item UUID — from `returnItems[n].id` in the GET response           |
| `returnItemStatus`   | enum          | `"Accepted"` or `"Rejected"` — see Step 6                                     |
| `rejectionReason`    | string        | Why the item was rejected — required when `returnItemStatus` is `"Rejected"`  |
| `reasonCodeOverride` | string        | Override the shopper-supplied reason code with the warehouse-confirmed reason |
| `reasonCode`         | string        | The reason code as recorded by the warehouse                                  |
| `productCode`        | string        | Product SKU — for reference/validation                                        |
| `lineItemId`         | string        | Line item ID — for reference/validation                                       |

</details>

#### Item targeting by `id`

The `id` UUID is the most reliable way to target a specific item in the update. Always use it rather than `productCode` or `lineItemId` — if the same product appears more than once in the return, the UUID is the only unambiguous identifier.

***

{% endstep %}

{% step %}

### &#x20;`UpdateReturnItemStatus`&#x20;

The update endpoint uses a **restricted** item status enum with only two values. This is intentionally narrower than the full `ReturnItemStatus` enum read in GET responses.

| Update value | Read status equivalent              | Meaning                                       |
| ------------ | ----------------------------------- | --------------------------------------------- |
| `"Accepted"` | `Accepted`                          | Item inspected and accepted — refund eligible |
| `"Rejected"` | `Rejected` or `RejectedNotReturned` | Item inspected and rejected                   |

#### Why only two values?

The update enum represents the warehouse inspector's decision. The full status enum includes states like `InProgress` (initial state), `Cancelled` (set by system), and `RejectedNotReturned` (set based on brand disposal policy). These transitions are managed by ESW's systems, not by direct warehouse API calls.

#### `"Accepted"` — item accepted for processing

```json
"returnItemStatus": "Accepted"
```

The warehouse inspector has determined:

* The item matches what was expected
* The item is in acceptable condition
* The return is valid under the brand's returns policy

**Effect:** ESW will proceed with a refund for this item.

#### `"Rejected"`&#x20;

```json
"returnItemStatus": "Rejected",
"rejectionReason": "WrongProduct"
```

The warehouse inspector has determined that the return is not valid — either the wrong item was sent, the item is not in returnable condition, or it does not match the return order.

**Effect:** ESW will not issue a refund for this item. Depending on brand policy and the `rejectionReason`, the item may be returned to the shopper or disposed of.

**Always include `rejectionReason`** when setting `Rejected`. Without it, downstream systems cannot determine the appropriate action.

***

{% endstep %}

{% step %}

### `rejectionReason` and `reasonCodeOverride`

#### `rejectionReason`

A string identifying why the specific item was rejected. This is set by the warehouse inspector and becomes part of the return record.

<details>

<summary>Common rejection reasons:</summary>

| Reason              | Meaning                                                                    |
| ------------------- | -------------------------------------------------------------------------- |
| `"WrongProduct"`    | The item in the parcel is not the product that was ordered                 |
| `"Damaged"`         | The item arrived in an unsellable condition due to damage                  |
| `"UsedItem"`        | The item shows signs of wear and is not in new condition                   |
| `"MissingTags"`     | Required labels or tags have been removed                                  |
| `"NotOriginalItem"` | The item does not match the brand's original product                       |
| `"PolicyViolation"` | The return violates the brand's return policy (e.g. outside return window) |

</details>

#### `reasonCodeOverride`

When the warehouse's inspection reveals a different reason from what the shopper stated, `reasonCodeOverride` records the warehouse-confirmed reason.

**Example:** the shopper said `"DoesNotFit"` (changed mind about size), but the warehouse inspector found the item was actually damaged.

```json
{
  "returnItemStatus": "Rejected",
  "rejectionReason": "Damaged",
  "reasonCodeOverride": "Damaged"
}
```

`reasonCodeOverride` does not replace `rejectionReason` — they serve different purposes:

* `rejectionReason` — why the item was rejected (the decision)
* `reasonCodeOverride` — the corrected return reason code (the classification)

***

{% endstep %}

{% step %}

### Updating `weight`

When the parcel arrives at the warehouse, the actual weight can be confirmed and updated. This is important for customs reconciliation and financial settlement.

```json
"weight": {
  "weightTotal": 0.28,
  "weightUnit": "KG"
}
```

Provide the actual weighed-on-arrival value. If the original weight was an estimate (as is typical when the shopper creates the return), the warehouse-confirmed weight is more accurate for records.

***

{% endstep %}

{% step %}

### Partial Updates

The update request supports partial updates — you do not need to provide all fields in every <mark style="color:$warning;">`PUT`</mark>. This allows the warehouse WMS to make targeted updates without re-sending the entire order state.

#### Update status only (no item changes)

```json
PUT /MYBRAND/orders/ORD-2024-78542/return-orders/5000002303

{
  "status": "Received",
  "weight": {
    "weightTotal": 0.28,
    "weightUnit": "KG"
  }
}
```

#### Update items only (status already set)

```json
PUT /MYBRAND/orders/ORD-2024-78542/return-orders/5000002303

{
  "returnItems": [
    {
      "id": "653995b0-d9e6-4018-9b85-d66d051b57e7",
      "returnItemStatus": "Accepted"
    }
  ]
}
```

#### Place on hold (no item changes needed)

```json
PUT /MYBRAND/orders/ORD-2024-78542/return-orders/5000002303

{
  "status": "OnHold",
  "statusReason": "Item has no barcode — cannot verify product identity"
}
```

***

{% endstep %}

{% step %}

### Update Response

A successful `PUT` returns `200 OK` with `UpdateReturnOrderWebResponse` — which has the same structure as the `GetReturnOrderWebResponse` (see Tutorial 8 Step 3). The full updated return order is returned, not just the changed fields.

{% code expandable="true" %}

```json
{
  "id": "MYBRAND-5000002303",
  "status": "Received",
  "returnAdminCentreCode": "IEDUB",
  "returnsListingsGuid": "4039312f-868d-4c64-ae6a-b6c9be74d07b",
  "returnType": "Normal",
  "returnOrderNumber": "5000002303",
  "returnMethod": "Postal",
  "isPaperlessRoute": false,
  "paidBy": "Retailer",
  "carrierIdentifier": "Ascendia",
  "orderReference": "ORD-2024-78542",
  "createdOn": "2024-11-10T09:20:51.172Z",
  "lastUpdated": "2024-11-14T11:45:00.000Z",
  "returnItems": [
    {
      "id": "653995b0-d9e6-4018-9b85-d66d051b57e7",
      "returnItemStatus": "InProgress",
      "productCode": "SKU-00123",
      ...
    }
  ],
  "weight": {
    "weightTotal": 0.28,
    "weightUnit": "KG"
  }
}
```

{% endcode %}

Verify the response `status` and `returnItems[n].returnItemStatus` match your intended update before treating the operation as complete.

***

{% endstep %}

{% step %}

### Examples

{% hint style="info" icon="arrow-progress" %}

#### Example A — Parcel received, weight updated

{% endhint %}

```json
PUT /MYBRAND/orders/ORD-2024-78542/return-orders/5000002303

{
  "status": "Received",
  "weight": {
    "weightTotal": 0.28,
    "weightUnit": "KG"
  }
}
```

***

{% hint style="info" icon="arrow-progress" %}

#### Example B — All items accepted after inspection

{% endhint %}

{% code expandable="true" %}

```json
PUT /MYBRAND/orders/ORD-2024-78542/return-orders/5000002303

{
  "returnItems": [
    {
      "id": "653995b0-d9e6-4018-9b85-d66d051b57e7",
      "productCode": "SKU-00123",
      "lineItemId": "1",
      "returnItemStatus": "Accepted"
    },
    {
      "id": "7a4c12e1-f3b2-4891-c73d-e88f162a9b45",
      "productCode": "SKU-00456",
      "lineItemId": "2",
      "returnItemStatus": "Accepted"
    }
  ]
}
```

{% endcode %}

***

{% hint style="info" icon="arrow-progress" %}

#### Example C — Mixed outcome: one accepted, one rejected

{% endhint %}

One wallet accepted; one belt rejected because it was used.

{% code expandable="true" %}

```json
PUT /MYBRAND/orders/ORD-2024-78543/return-orders/5000002351

{
  "returnItems": [
    {
      "id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
      "productCode": "SKU-00123",
      "lineItemId": "1",
      "returnItemStatus": "Accepted"
    },
    {
      "id": "b2c3d4e5-f6a7-8901-bcde-f12345678901",
      "productCode": "SKU-00456",
      "lineItemId": "2",
      "returnItemStatus": "Rejected",
      "rejectionReason": "UsedItem",
      "reasonCodeOverride": "Defective"
    }
  ]
}
```

{% endcode %}

***

{% hint style="info" icon="arrow-progress" %}

#### Example D — Item rejected: wrong product in parcel

{% endhint %}

The shopper returned a different item to what was in the order.

{% code expandable="true" %}

```json
PUT /MYBRAND/orders/ORD-2024-78544/return-orders/5000002399

{
  "returnItems": [
    {
      "id": "c3d4e5f6-a7b8-9012-cdef-234567890123",
      "productCode": "SKU-00789",
      "lineItemId": "3",
      "returnItemStatus": "Rejected",
      "rejectionReason": "WrongProduct",
      "reasonCodeOverride": "NotOriginalItem"
    }
  ]
}
```

{% endcode %}

***

{% hint style="info" icon="arrow-progress" %}

#### Example E — Place on hold for investigation

{% endhint %}

Parcel received but contents are suspicious — escalated to Brand Protection team.

```json
PUT /MYBRAND/orders/ORD-2024-78545/return-orders/5000002421

{
  "status": "OnHold",
  "statusReason": "Suspected counterfeit product — item does not match authentication markers. Escalated to Brand Protection on 2024-11-14."
}
```

***

{% hint style="info" icon="arrow-progress" %}

#### Example F — Release from hold after investigation cleared

{% endhint %}

Investigation complete — item confirmed authentic, proceeding with acceptance.

{% code expandable="true" %}

```json
PUT /MYBRAND/orders/ORD-2024-78545/return-orders/5000002421

{
  "status": "Released",
  "statusReason": "Brand Protection confirmed authentic — proceeding to accept",
  "returnItems": [
    {
      "id": "d4e5f6a7-b8c9-0123-defg-345678901234",
      "productCode": "SKU-00789",
      "lineItemId": "3",
      "returnItemStatus": "Accepted"
    }
  ]
}
```

{% endcode %}

***

{% hint style="info" icon="arrow-progress" %}

#### Example G — Mark order as processed (all items handled)

{% endhint %}

All inspection decisions recorded, order ready for manifest.

```json
PUT /MYBRAND/orders/ORD-2024-78542/return-orders/5000002303

{
  "status": "Processed"
}
```

***

{% hint style="info" icon="arrow-progress" %}

#### Example H — Cancel before parcel dispatched

{% endhint %}

Shopper changed their mind and cancelled the return within the cancellation window.

```json
PUT /MYBRAND/orders/ORD-2024-78546/return-orders/5000002455

{
  "status": "Cancelled",
  "statusReason": "Shopper requested cancellation via CS portal on 2024-11-14 — parcel not yet dispatched"
}
```

{% endstep %}
{% endstepper %}

### Common Errors

| Status                             | Cause                                                                   | Fix                                                                             |
| ---------------------------------- | ----------------------------------------------------------------------- | ------------------------------------------------------------------------------- |
| `404`                              | `returnOrderNumber` or `orderReference` not found                       | Verify both path parameters are correct                                         |
| `400` — invalid `status`           | Unknown `ReturnOrderStatus` value                                       | Use one of the 11 defined enum values                                           |
| `400` — invalid `returnItemStatus` | Value not in `UpdateReturnItemStatus`                                   | Use only `"Accepted"` or `"Rejected"` — not `"InProgress"`, `"Cancelled"`, etc. |
| `400` — item `id` not found        | UUID does not match any item on this return order                       | Retrieve the current return order to get accurate item UUIDs                    |
| `400` — invalid status transition  | Attempting to set a status that is not reachable from the current state | Check Tutorial 12 for valid status transitions                                  |
| `400` — `weightUnit` invalid       | Unknown enum value                                                      | Use `"KG"` or `"LB"`                                                            |
| `400` — missing `rejectionReason`  | `returnItemStatus` is `"Rejected"` but no reason provided               | Always include `rejectionReason` with `"Rejected"` items                        |

### Update Scenarios

| Scenario                        | Fields to update                                                  |
| ------------------------------- | ----------------------------------------------------------------- |
| Parcel arrived at warehouse     | `status: "Received"`, `weight`                                    |
| Parcel arrived — unknown weight | `status: "Received"` only                                         |
| Item inspected, accepted        | `returnItems[n].returnItemStatus: "Accepted"`                     |
| Item inspected, rejected        | `returnItems[n].returnItemStatus: "Rejected"`, `rejectionReason`  |
| Wrong item received             | `returnItemStatus: "Rejected"`, `rejectionReason: "WrongProduct"` |
| Issue requires investigation    | `status: "OnHold"`, `statusReason` (required)                     |
| Hold resolved                   | `status: "Released"`                                              |
| All items processed             | `status: "Processed"`                                             |
| Return cancelled                | `status: "Cancelled"`, `statusReason`                             |

### Full Status Reference Card

```
Status               Phase         Who sets           Terminal?
────────────────────────────────────────────────────────────
Created              In transit    Retailer/Portal    No
Received             Warehouse     Warehouse/ESW      No
OnHold               Paused        Warehouse/CS       No
Released             Processing    CS                 No
Processed            Complete      Warehouse/ESW      No
AddedToManifest      Logistics     ESW                No
SentToRetailer       In transit    ESW                No
ReceivedByRetailer   Complete      Retailer/ESW       YES
RemovedFromManifest  Exception     ESW                No
Cancelled            Terminated    CS/Shopper/Auto    YES
Refunded             Financial     ESW                YES
```


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://developer.esw.com/returns-api/resources/tutorials/updating-a-return-order.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
