> 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/grp-returns-api/use-cases.md).

# Use Cases

End-to-end use case scenarios showing how GRP Returns API could be used.

***

## 01 — Standard Shopper-Initiated Postal Return

Shopper visits the returns portal, looks up their order, selects an item to return, chooses postal as the return method, creates the return, and downloads their return label.

{% stepper %}
{% step %}

#### Check country configuration (GET)

Before the portal renders the return form, it fetches the country-level configuration for the shopper's delivery country. This tells the portal: how many return days are allowed, whether reason codes are mandatory, which locales to offer, and whether dangerous-goods returns should be blocked. The `countryIso` comes from the shopper's delivery address stored in the outbound order.

#### Request

{% code expandable="true" %}

```http
GET /ACMEUS/configuration/countries/US
```

{% endcode %}

{% code title="GET /{identifier}/configuration/countries/{countryIso}" expandable="true" %}

```json
// Path parameters only — no request body
```

{% endcode %}

{% code title="Response 200 OK" expandable="true" %}

```json
{
  "organisationId": "esw",
  "tenantCode":     "ACMEUS",
  "brandCode":      "ACM",
  "brandName":      "Acme US",
  "countryIso":     "US",
  "returnsOmsEnabled": true,
  "portalSettings": {
    "returnsPortalConfigurationSettings": {
      "noOfDaysAllowedForReturn":    30,   
      "returnReasonMandatory":        true, // Reason code UI must be shown and required
      "showLabel":                    true, // Render the label download step
      "showRefund":                   true,
      "numberOfDeliveryDaysRequired":  2,
      "shippedPeriodDays":            5,
      "cancelOrderNoOfDays":          14,
      "isCancelOrderAllowed":          true
    },
    "customerReturnReasonCodes": [
      { "code": "WrongItemShipped", "description": "Wrong item was shipped", "isRetailerAtFault": true },
      { "code": "DoesNotFit",       "description": "Item does not fit",         "isRetailerAtFault": false },
      { "code": "Defective",        "description": "Item is defective",        "isRetailerAtFault": true }
    ],
    "blockDefectiveDangerGoods": false
  },
  "locales": [
    { "name": "English (US)", "cultureInfoCode": "en-US" }
  ]
}
```

{% endcode %}
{% endstep %}

{% step %}

#### Retrieve the outbound order (GET)

The shopper enters their order reference. The portal fetches the order to display the items eligible for return. The `orderItems` query parameter filters what is returned — use `not-returned` to show only items that haven't already been returned.

#### Request

{% code title="GET /ACMEUS/orders/ORD-20240315-88821?orderItems=not-returned" expandable="true" %}

```json
{
  "countryIso":                      "US",
  "orderDate":                       "2024-02-14T09:30:00+00:00",
  "noOfArticlesAvailableForReturn":   2,   // Portal renders these
  "noOfArticlesUnavailableForReturn": 1,   // e.g. personalized — show greyed out
  "returnPeriodExpired":             false,// 30-day window still open
  "orderQualifiesForCancel":         false,
  "items": [
    {
      "id":                    "74f82404-d541-4604-8c24-8f74400f614b",
      "productCode":          "SKU-JEANS-32-INDIGO",
      "lineItemId":           "1",
      "productDescription":   "Slim Fit Indigo Jeans",
      "color":                 "Indigo",
      "size":                  "32",
      "category":             "Denim",
      "unitPrice":            { "amount": 89.99, "currency": "USD" },
      "availableForReturns":  true,     // Show as selectable
      "prohibitedForReturns": false,
      "personalized":         false,
      "dangerousGoods":       false
    },
    {
      "id":                    "a3c12091-f2e3-47a1-b832-2d501ef23100",
      "productCode":          "SKU-BELT-BLK-M",
      "lineItemId":           "2",
      "productDescription":   "Classic Leather Belt - Black",
      "color":                 "Black",
      "size":                  "M",
      "category":             "Accessories",
      "unitPrice":            { "amount": 34.99, "currency": "USD" },
      "availableForReturns":  true,
      "prohibitedForReturns": false,
      "personalized":         false
    }
  ],
  "shopperDetails": {
    "firstName": "Sarah", "lastName": "Mitchell", "email": "sarah.m@email.com",
    "address": { "address1": "420 Park Ave", "city": "New York", "postalCode": "10022", "countryName": "United States" }
  }
}
```

{% endcode %}
{% endstep %}

{% step %}

#### Search available return methods (POST)

The shopper selects which items to return. The portal calls `SearchReturnMethods`, passing only the items the shopper wants to return. The API evaluates carrier routes and returns which methods (Postal, PUDO, Collections) are available for this specific order+item combination. The response also gives `carrierServiceRouteId` — needed when creating the return order.

#### Request

{% code title="POST /ACMEUS/return-methods/ORD-20240315-88821" expandable="true" %}

```json
{
  "returnItems": [
    // Pass the id and productCode + lineItemId
    // Only include items the shopper has selected for return
    {
      "id":          "74f82404-d541-4604-8c24-8f74400f614b",
      "productCode": "SKU-JEANS-32-INDIGO",
      "lineItemId":  "1"
    }
  ]
}
```

{% endcode %}

{% code title="Response 200 OK" expandable="true" %}

```json
{
  "orderReference":              "ORD-20240315-88821",
  "originCountryIso":             "IE",          
  "destinationCountryIso":        "US",          
  "selectedReturnAdminCentreCode": "JFKDC",      // DC that will process this return
  "returnMethods": [
    {
      "returnMethod": "Postal",        // Enum: "Postal" | "PUDO" | "Collections"
      "paidBy":       "Retailer",      // Enum: "Retailer" | "Shopper" | "Unpaid"
      "carrierServiceRoute": {
        "carrierServiceRouteId": "US_IE_POSTAL",
        "eswCarrierIdentifier": "FedEx",
        "carrierName":          "FedEx",
        "serviceType":          "Post",  // Enum: "Express" | "Post" | "PUDO"
        "carrierServiceCode":   "FEDEX_GROUND",
        "isPaperlessRoute":     false,  
        "isLocationRequired":   false 
      }
    }
  ]
}
```

{% endcode %}

{% hint style="info" icon="lightbulb" %}
Store the `selectedReturnAdminCentreCode` and the chosen method's `carrierServiceRouteId` in session state. If `isLocationRequired` is `true`, branch to the PUDO location-search flow (see use case 02).
{% endhint %}
{% endstep %}

{% step %}

#### Create the return order (POST)

Shopper confirms selections, provides the reason code (mandatory in this config), and submits. The portal creates the return order. The response includes the `returnOrderNumber` and `returnsListingsGuid` for tracking.

#### Request

{% code title="POST /ACMEUS/orders/ORD-20240315-88821/return-orders" expandable="true" %}

```json
{
  "consumerEmailAddress": "sarah.m@email.com",  
  "cultureLanguageIso":   "en-US",              

  "returnMethod": "Postal",     // Enum: "Postal" | "PUDO" | "Collections"
  "returnType":   "Normal",     // Enum: "Normal" | "Undeliverable" | "BlindReturn" | "EUCoolingOff"
  "paidBy":       "Retailer",   
  "isPaperlessRoute": false,   
  "carrierIdentifier": "FedEx", 

  "returnItems": [
    {
      "id":            "74f82404-d541-4604-8c24-8f74400f614b", 
      "productCode":   "SKU-JEANS-32-INDIGO",
      "lineItemId":    "1",
      "reasonCode":    "DoesNotFit",           // Must match a code from country config
      "reasonComment": "Waist too large"       // Free-text; optional but helpful for ops
    }
  ],

  // weight is optional but helps the carrier pre-calculate postage
  "weight": {
    "weightTotal": 0.6,
    "weightUnit":  "Kg"     // Enum: "Kg" | "Lb"
  }

  // dropOffLocation: omit for Postal; required when returnMethod is "PUDO"
  // returnAdminCentreCodeOverride: omit unless you need to override DC routing
}
```

{% endcode %}

{% code title="Response 201 Created " expandable="true" %}

```json
{
  "returnOrderNumber":  "5000032891",              
  "returnsListingsGuid": "4c071f76-e27b-4291-a29h1",// Use for tracking events lookup
  "returnType":          "Normal",
  "returnMethod":        "Postal",
  "paidBy":              "Retailer",
  "carrierIdentifier":   "FedEx",
  "isPaperlessRoute":    false,
  "returnItems": [
    {
      "id":                 "0013db57-885d-462b-a24f-80312a9g3207",
      "productCode":       "SKU-JEANS-32-INDIGO",
      "lineItemId":        "1",
      "productDescription":"Slim Fit Indigo Jeans",
      "color":             "Indigo",
      "size":              "32",
      "reasonCode":        "DoesNotFit",
      "reasonComment":     "Waist too large"
    }
  ],
  "weight": { "weightTotal": 0.6, "weightUnit": "Kg" }
}
```

{% endcode %}

{% hint style="warning" icon="bug-slash" %}

#### Error Handling

* <mark style="color:$warning;">`409`</mark> A return order with the same items already exists — present the existing return order number to the shopper instead of creating a duplicate.
* <mark style="color:$warning;">`400`</mark> Validation failure — commonly a `reasonCode` not present in the country configuration. Re-fetch config and validate client-side before submission.
* <mark style="color:$warning;">`404`</mark> Tenant code or order reference doesn't exist. Verify `identifier` path param and `orderReference`.
  {% endhint %}
  {% endstep %}

{% step %}

#### Retrieve the return label document (GET)

After creation, the portal polls for the return label. Label generation is asynchronous — `documentStatus` will be `Processing` until the carrier label service responds. Poll until `Ready`. The `label` field contains base64-encoded PDF content.

#### Request

{% code title="GET /ACMEUS/return-orders/5000032891/ReturnLabel" expandable="true" %}

```json
// documentType path param enum: "ReturnLabel" | "LastMileLabel"
// ReturnLabel = the label the shopper affixes to their parcel
// LastMileLabel = used internally for hub/DC last-mile routing
```

{% endcode %}

{% code title="Response 200 OK " expandable="true" %}

```json
{
  "orderReference":    "ORD-20240315-88821",
  "returnOrderNumber": "5000032891",
  "contentType":       "application/pdf",
  "documentStatus":    "Ready",   // Enum: "Processing" | "Ready" | "Failed"
  "documentType":      "ReturnLabel",
  "label":             "JVBERi0xLjQKJ...", // Base64-encoded PDF — decode and offer download
  "cultureLanguageIso": "en-US",
  "documentId":        "d82a4c1e-3f7b-4e2a-a91d-0058c3b7e220",
  "carrierInfoDetails": {
    "carrierId":              "fedex-us",
    "carrierName":            "FedEx",
    "carrierReference":       "794683571234",        // Carrier's shipment ref
    "carrierTrackingReference":"794683571234"         // Use this for tracking page
  }
}
```

{% endcode %}
{% endstep %}
{% endstepper %}

***

## 02 — PUDO Drop-Off Return with Location Search

Shopper chooses a PUDO return method. The portal must search nearby drop-off points, then create the return order with the selected `dropOffLocation`.

Example tenant: `LUXFR`

{% stepper %}
{% step %}

#### Search available return methods (POST)

After the shopper selects items, the portal checks available methods. The response includes a PUDO method with `isLocationRequired: true`. This triggers the location-search flow.

#### Request

{% code title="POST /LUXFR/return-methods/LUX-20240301-44190" expandable="true" %}

```json
{
  "returnItems": [
    {
      "id": "c4a91023-bb20-4f3a-9d5e-1a2034567b88",
      "productCode": "SKU-SCARF-SILK-BLU",
      "lineItemId": "1"
    }
  ]
}
```

{% endcode %}

{% code title="Response 200 OK" expandable="true" %}

```json
{
  "orderReference": "LUX-20240301-44190",
  "originCountryIso": "FR",
  "destinationCountryIso": "FR",
  "selectedReturnAdminCentreCode": "CDGDC",
  "returnMethods": [
    {
      "returnMethod": "PUDO",
      "paidBy": "Retailer",
      "carrierServiceRoute": {
        "carrierServiceRouteId": "FR_FR_PUDO_CHRONO",
        "eswCarrierIdentifier": "Chronopost",
        "carrierName": "Chronopost",
        "serviceType": "PUDO",
        "carrierServiceCode": "CHR_RELAIS",
        "isPaperlessRoute": true,
        "isLocationRequired": true
      }
    }
  ]
}
```

{% endcode %}

{% hint style="info" icon="lightbulb" %}
When `isLocationRequired` is `true`, always render a location picker before CreateReturnOrder. If `dropOffLocation` is missing, CreateReturnOrder returns `400`.
{% endhint %}
{% endstep %}

{% step %}

#### Find nearby PUDO drop-off locations (GET)

The portal prompts the shopper for their postcode (pre-filled from their delivery address). It calls the Location API with the `carrierServiceRouteId` from the previous step, the shopper's `PostalCode` and `CountryCode`, and a max distance/number cap to keep the list manageable. `RouteType=Inbound` means the shopper is returning goods&#x20;

#### Request

{% code expandable="true" %}

```http
GET /location/?identifier=LUXFR&CountryCode=FR&PostalCode=75008&RouteType=Inbound&CarrierServiceRouteId=FR_FR_PUDO_CHRONO&MaxDistanceInKms=5&MaxLocations=10&City=Paris
```

{% endcode %}

{% code title="GET /location/ (query parameters)" expandable="true" %}

```json
// Required params: identifier, CountryCode (max 2 chars), PostalCode, RouteType, CarrierServiceRouteId
// Optional: City, Latitude, Longitude, MaxDistanceInKms, MaxLocations
// RouteType enum: "Inbound" (return) | "Outbound" (delivery)
// Always pass "Inbound" for return flows
```

{% endcode %}

{% code title="Response 200 OK" expandable="true" %}

```json
{
  "locations": [
    {
      "id": "CHR-PAR-0491",
      "type": "Pudo",
      "name": "Tabac du Faubourg",
      "address1": "38 Rue du Faubourg Saint-Honoré",
      "city": "Paris",
      "postalCode": "75008",
      "countryCode": "FR",
      "country": "France",
      "distanceInKms": 0.4,
      "openingTimesDescription": "Mon–Sat 08:00–20:00",
      "openingTimes": [
        {
          "day": "Monday",
          "opens": "08:00",
          "closes": "20:00"
        },
        {
          "day": "Tuesday",
          "opens": "08:00",
          "closes": "20:00"
        }
      ],
      "carrierServiceRouteId": "FR_FR_PUDO_CHRONO",
      "latitude": 48.8698,
      "longitude": 2.3093
    }
  ]
}
```

{% endcode %}
{% endstep %}

{% step %}

#### Create the return order with selected drop-off location (POST)

Shopper selects a PUDO point. The portal creates the return order, embedding the full `dropOffLocation` object from the selected location result. Since `isPaperlessRoute` is `true`, no PDF label is generated.

#### Request

{% code title="POST /LUXFR/orders/LUX-20240301-44190/return-orders" expandable="true" %}

```json
{
  "consumerEmailAddress": "claire.d@email.fr",
  "cultureLanguageIso":   "fr-FR",
  "returnMethod":         "PUDO",
  "returnType":           "Normal",
  "paidBy":               "Retailer",
  "isPaperlessRoute":     true,
  "carrierIdentifier":    "Chronopost",

  "returnItems": [
    {
      "id":            "c4a91023-bb20-4f3a-9d5e-1a2034567b88",
      "productCode":   "SKU-SCARF-SILK-BLU",
      "lineItemId":    "1",
      "reasonCode":    "WrongItemShipped",
      "reasonComment": "Received the wrong colour"
    }
  ],

  // dropOffLocation: required when isLocationRequired was true
  // Map from LocationResponseDto fields to DropOffLocationDto
  "dropOffLocation": {
    "id":      "CHR-PAR-0491",           // location id from /location/ response
    "type":    "Pudo",                   // Enum: "Store" | "Pudo"
    "name":    "Tabac du Faubourg",
    "address1":"38 Rue du Faubourg Saint-Honoré",
    "city":    "Paris",
    "postcode":"75008",
    "country": "France",
    "openingTimesDescription": "Mon–Sat 08:00–20:00"
  }
}
```

{% endcode %}

{% code title="Response 201 Created" expandable="true" %}

```json
{
  "returnOrderNumber": "5000033017",
  "returnsListingsGuid": "9f2c3a7d-1b88-4e90-b334-cc091d42a1fe",
  "returnMethod": "PUDO",
  "isPaperlessRoute": true,
  "dropOffLocation": {
    "id": "CHR-PAR-0491",
    "name": "Tabac du Faubourg",
    "type": "Pudo"
  },
  "returnItems": [ /* ... */ ]
}
```

{% endcode %}
{% endstep %}
{% endstepper %}

Sequence summary: `POST /return-methods/{ref}` → `GET /location/` → `POST /orders/{ref}/return-orders` (with `dropOffLocation`)

***

## 03 — Retailer Order Ingestion + Shipment Confirmation

When an order ships from the retailer's warehouse, two Ingestion API calls register it in GRP: creating the outbound order, then confirming the shipment. Both are required so GRP can qualify the order for returns.

Example tenant: `SPORUS`

{% stepper %}
{% step %}

#### Create the outbound order (POST)

Triggered when the retailer's OMS dispatches the order to the warehouse. This call registers the order, items, shopper address, and product metadata in GRP. The `canOverwrite` flag controls idempotency — set to `true` to allow re-sending updated data without a 409 conflict (e.g. if product descriptions need correcting). `prohibitedForReturns` at the item level prevents that item from being returned via GRP.

#### Request

{% code title="POST /SPORUS/outbound-orders" expandable="true" %}

```json
{
  "orderReference": "SPR-20240320-10042",
  "canOverwrite": true,
  "contactInformation": {
    "firstName": "Marcus",
    "lastName": "Johnson",
    "address1": "1200 Harbor Blvd",
    "city": "Anaheim",
    "region": "CA",
    "postalCode": "92805",
    "countryIso": "US",
    "email": "marcus.j@email.com",
    "telephone": "17145550199",
    "cultureLanguageIso": "en-US"
  },
  "orderItems": [
    {
      "productCode": "SKU-SNEAKER-R10-WHT-9",
      "lineItemId": "1",
      "quantity": 1,
      "productDescription": "Runner 10 Sneaker - White",
      "productCustomsDescription": "Athletic Footwear",
      "composition": "Mesh upper, rubber sole",
      "countryOfOriginIso": "VN",
      "hsCode": "6404110000",
      "color": "White",
      "size": "9",
      "category": "Footwear",
      "personalized": false,
      "dangerousGoods": false,
      "prohibitedForReturns": false,
      "weight": {
        "weightTotal": 0.85,
        "weightUnit": "Kg"
      },
      "unitPrice": {
        "amount": 129.99,
        "currency": "USD"
      },
      "productImageUrl": "https://cdn.sporus.com/img/r10-wht.jpg"
    },
    {
      "productCode": "SKU-SOCK-3PK-WHT",
      "lineItemId": "2",
      "quantity": 2,
      "productDescription": "Performance Sock 3-Pack",
      "productCustomsDescription": "Socks",
      "composition": "75% Cotton, 20% Polyester, 5% Elastane",
      "countryOfOriginIso": "CN",
      "hsCode": "6115960090",
      "color": "White",
      "size": "M",
      "category": "Accessories",
      "personalized": false,
      "dangerousGoods": false,
      "prohibitedForReturns": false,
      "weight": {
        "weightTotal": 0.12,
        "weightUnit": "Kg"
      },
      "unitPrice": {
        "amount": 14.99,
        "currency": "USD"
      }
    }
  ],
  "customFields": {
    "retailer": {
      "promoCode": "SPRING24",
      "channelType": "direct-web"
    }
  }
}
```

{% endcode %}

{% code title="Response 201 Created" expandable="true" %}

```json
{
  "id": "SPORUS-SPR-20240320-10042",
  "orderItems": [
    {
      "id": "a7b3c901-1234-4a5b-8c6d-000000000001",
      "productCode": "SKU-SNEAKER-R10-WHT-9",
      "lineItemId": "1",
      "productDescription": "Runner 10 Sneaker - White"
    },
    {
      "id": "a7b3c901-1234-4a5b-8c6d-000000000002",
      "productCode": "SKU-SOCK-3PK-WHT",
      "lineItemId": "2",
      "productDescription": "Performance Sock 3-Pack"
    }
  ]
}
```

{% endcode %}

{% hint style="warning" icon="bug-slash" %}

#### Error Handling

* <mark style="color:$warning;">`409`</mark> Order already exists and `canOverwrite` was `false`. Set `canOverwrite: true` on re-sends, or treat `409` as a no-op if data is unchanged.
  {% endhint %}
  {% endstep %}

{% step %}

#### Update outbound order if contact details change (PUT) — optional

If the shopper updates their delivery address before dispatch, the OMS should send an update. Only changed fields need to be sent.

#### Request

{% code title="PUT /SPORUS/outbound-orders/SPR-20240320-10042" expandable="true" %}

```json
{
  "contactInformation": {
    "firstName":  "Marcus",
    "lastName":   "Johnson",
    "address1":   "500 West Broadway",  // Changed delivery address
    "city":       "Anaheim",
    "region":     "CA",
    "postalCode": "92805",
    "email":      "marcus.j@email.com",
    "telephone":  "17145550199",
    "cultureLanguageIso": "en-US"
  }
  // orderItems and customFields can also be updated here if needed
}
```

{% endcode %}

{% code title="Response 200 OK" expandable="true" %}

```json
{ /* returns the full updated contactInformation, orderItems, and customFields */ }
```

{% endcode %}
{% endstep %}

{% step %}

#### Submit outbound shipment (POST)

Triggered when the warehouse hands the parcel to the carrier and a tracking number is generated. The `shippingReference` is the retailer's shipment ID; the `barcodeReference` is the carrier-assigned barcode/tracking number. The `shippingDate` seeds the return-window calculation.

#### Request

{% code title="POST /SPORUS/outbound-shipments" expandable="true" %}

```json
{
  "orderReference": "SPR-20240320-10042",
  "shippingReference": "SPR_SHIP_20240320_99112",
  "barcodeReference": "1Z999AA10123456784",
  "shippingDate": "2024-03-20T14:30:00+00:00",
  "contactInformation": {
    "firstName": "Marcus",
    "lastName": "Johnson",
    "address1": "500 West Broadway",
    "city": "Anaheim",
    "region": "CA",
    "postalCode": "92805",
    "countryIso": "US",
    "email": "marcus.j@email.com",
    "telephone": "17145550199",
    "cultureLanguageIso": "en-US"
  },
  "shippingItems": [
    {
      "productCode": "SKU-SNEAKER-R10-WHT-9",
      "lineItemId": "1",
      "quantity": 1,
      "productDescription": "Runner 10 Sneaker - White",
      "productCustomsDescription": "Athletic Footwear",
      "composition": "Mesh upper, rubber sole",
      "countryOfOriginIso": "VN",
      "hsCode": "6404110000",
      "color": "White",
      "size": "9",
      "category": "Footwear",
      "personalized": false,
      "dangerousGoods": false,
      "prohibitedForReturns": false,
      "weight": {
        "weightTotal": 0.85,
        "weightUnit": "Kg"
      },
      "unitPrice": {
        "amount": 129.99,
        "currency": "USD"
      }
    },
    {
      "productCode": "SKU-SOCK-3PK-WHT",
      "lineItemId": "2",
      "quantity": 2,
      "productDescription": "Performance Sock 3-Pack",
      "productCustomsDescription": "Socks",
      "composition": "75% Cotton, 20% Polyester, 5% Elastane",
      "countryOfOriginIso": "CN",
      "hsCode": "6115960090",
      "color": "White",
      "size": "M",
      "category": "Accessories",
      "personalized": false,
      "dangerousGoods": false,
      "prohibitedForReturns": false,
      "weight": {
        "weightTotal": 0.12,
        "weightUnit": "Kg"
      },
      "unitPrice": {
        "amount": 14.99,
        "currency": "USD"
      }
    }
  ]
}
```

{% endcode %}

{% code title="Response 200 OK" expandable="true" %}

```json
{
  "id": "SPORUS-SPR-20240320-10042",
  "shippingItems": [
    {
      "id": "a7b3c901-1234-4a5b-8c6d-000000000001",
      "productCode": "SKU-SNEAKER-R10-WHT-9",
      "lineItemId": "1",
      "productDescription": "Runner 10 Sneaker - White"
    },
    {
      "id": "a7b3c901-1234-4a5b-8c6d-000000000002",
      "productCode": "SKU-SOCK-3PK-WHT",
      "lineItemId": "2",
      "productDescription": "Performance Sock 3-Pack"
    }
  ]
}
```

{% endcode %}

{% hint style="warning" %}
Always submit `SubmitOutboundShipment` even when the order uses a pre-printed return label. GRP needs the `shippingDate` to calculate the return-window expiry.
{% endhint %}
{% endstep %}
{% endstepper %}

Sequence summary: `POST /outbound-orders` → `PUT /outbound-orders/{ref}` (optional) → `POST /outbound-shipments`

***

## 04 — Pre-Printed Return Label Request

Example tenant: `PREMUK`

{% stepper %}
{% step %}

#### Request the pre-printed label (POST)

Made at pack time, typically right after `SubmitOutboundShipment`. `outboundOrderReference` links the label to the GRP order. A successful 200 means GRP queued label generation; label PDF is dispatched asynchronously.

#### Request

{% code title="POST /PREMUK/label-requests" expandable="true" %}

```json
{
  "outboundOrderReference": "PREM-20240325-77231",
  "shippingReference": "PREM_SHIP_77231_A",
  "shopperAddress": {
    "firstName": "Emma",
    "lastName": "Clarke",
    "address1": "14 Victoria Street",
    "city": "Edinburgh",
    "region": "Scotland",
    "postalCode": "EH1 2AB",
    "countryIso": "GB",
    "email": "emma.c@email.co.uk",
    "telephone": "441312550100",
    "cultureLanguageIso": "en-GB"
  },
  "orderItems": [
    {
      "id": "bc8a1234-0011-4ef2-8910-aabbcc001122",
      "productCode": "SKU-COAT-WOOL-BLK-12",
      "lineItemId": "1",
      "quantity": 1,
      "productDescription": "Merino Wool Overcoat - Black",
      "productCustomsDescription": "Coat",
      "composition": "100% Merino Wool",
      "countryOfOriginIso": "IT",
      "hsCode": "6201920000",
      "hsCodeRegion": "GB",
      "colour": "Black",
      "size": "12",
      "category": "Outerwear",
      "categoryDescription": "Ladies Coats",
      "dangerousGoods": false,
      "prohibitedForReturns": false,
      "personalized": false,
      "unitPrice": {
        "amount": 349.00,
        "currency": "GBP"
      },
      "source": "Order",
      "material": "Wool",
      "gender": "F",
      "ageGroup": "Adult"
    }
  ]
}
```

{% endcode %}

{% code title="Response 200 OK" expandable="true" %}

```json
// 200 with no response body = label request accepted and queued for generation
// The label will be dispatched asynchronously
// (e.g. emailed to shopper, or pushed to label printer integration)
```

{% endcode %}

{% hint style="warning" icon="bug-slash" %}

#### Error Handling

* <mark style="color:$warning;">`409`</mark> A label request with the same `outboundOrderReference` + `shippingReference` already exists. Do not retry.
* <mark style="color:$warning;">`400`</mark> Validation error. Verify `outboundOrderReference` exists in GRP and `shopperAddress` is populated.
  {% endhint %}

{% hint style="warning" %}
The `outboundOrderReference` must exist in GRP before calling `/label-requests`. Sequence: `CreateOutboundOrder` → `SubmitOutboundShipment` → `RequestPrePrintedLabel`. Out-of-order calls return `400` or `404`.
{% endhint %}
{% endstep %}
{% endstepper %}

Sequence summary: `POST /outbound-orders` → `POST /outbound-shipments` → `POST /label-requests`

***

## 05 — Customer Service Return Management

A CS agent uses the ops dashboard to investigate an in-transit return, place it on hold pending QC review, then release and accept/reject items once parcel arrives. Tracking events are fetched to keep the shopper informed.

Example tenant: `GOCAS`

{% stepper %}
{% step %}

#### List return orders by status and date range (GET)

CS dashboard shows a queue. Query by `status=OnHold` within a date window. All params are optional query strings — omit filters to get all returns for the tenant. `returnType` can further narrow to `Normal`, `BlindReturn`, etc.

#### Request

{% code expandable="true" %}

```http
GET /GOCAS/return-orders?status=Received&startUtc=2024-03-25T00:00:00Z&endUtc=2024-03-25T23:59:59Z&returnType=Normal
```

{% endcode %}

{% code title="Response 200 OK" expandable="true" %}

```json
[
  {
    "id":                  "GOCAS-5000032891",
    "returnOrderNumber":  "5000032891",
    "orderReference":     "ORD-20240315-88821",
    "status":              "Received",
    "returnAdminCentreCode":"JFKDC",
    "returnType":          "Normal",
    "returnMethod":        "Postal",
    "isPaperlessRoute":    false,
    "paidBy":              "Retailer",
    "carrierIdentifier":   "FedEx",
    "createdOn":           "2024-03-15T11:22:00+00:00",
    "lastUpdated":         "2024-03-25T08:14:00+00:00",
    "returnsListingsGuid": "4c071f76-e27b-4291-a29h1",
    "returnItems": [
      {
        "id":                 "0013db57-885d-462b-a24f-80312a9g3207",
        "productCode":       "SKU-JEANS-32-INDIGO",
        "lineItemId":        "1",
        "returnItemStatus":  "InProgress",  // Enum: "InProgress"|"Accepted"|"Rejected"|"RejectedNotReturned"|"Cancelled"
        "productDescription":"Slim Fit Indigo Jeans"
      }
    ]
  }
]
```

{% endcode %}
{% endstep %}

{% step %}

#### Get full detail of a specific return order (GET)

Agent opens a return to view weight, reasons, and shipping info.

#### Request

{% code expandable="true" %}

```http
GET /GOCAS/orders/ORD-20240315-88821/return-orders/5000032891
```

{% endcode %}

{% code title="Response 200 OK" expandable="true" %}

```json
{
  "id":                 "GOCAS-5000032891",
  "returnOrderNumber": "5000032891",
  "status":             "Received",
  "weight": { "weightTotal": 0.6, "weightUnit": "Kg" },
  "returnItems": [
    {
      "id":                   "0013db57-885d-462b-a24f-80312a9g3207",
      "returnItemStatus":     "InProgress",
      "productCode":          "SKU-JEANS-32-INDIGO",
      "lineItemId":           "1",
      "productDescription":   "Slim Fit Indigo Jeans",
      "unitPrice":            { "amount": 89.99, "currency": "USD" },
      "returnReasons": [
        {
          "reasonCode":       "DoesNotFit",
          "description":     "Item does not fit",
          "reasonComment":   "Waist too large",
          "isRetailerAtFault":false,
          "suppliedBy":       "Shopper"  // Enum: "Shopper" | "CustomerService"
        }
      ]
    }
  ]
}
```

{% endcode %}
{% endstep %}

{% step %}

#### Fetch tracking events for the return shipment (POST)

Agent checks the tracking timeline to confirm parcel arrival. `trackingReference` is the carrier tracking number.

#### Request

{% code title="POST /GOCAS/tracking-events" %}

```json
{
  "trackingReference": 794683571234,
  "emailAddress": "sarah.m@email.com"
}
```

{% endcode %}

{% code title="Response 200 OK" expandable="true" %}

```json
{
  "carrier": "FedEx",
  "milestones": [
    {
      "code": "ReturnCreated",
      "dateTime": "2024-03-15T11:22:00+00:00",
      "isCurrentMilestone": false,
      "location": ""
    },
    {
      "code": "InTransit",
      "dateTime": "2024-03-20T08:00:00+00:00",
      "isCurrentMilestone": false,
      "location": "New York, US"
    },
    {
      "code": "Received",
      "dateTime": "2024-03-25T07:45:00+00:00",
      "isCurrentMilestone": true,
      "location": "JFKDC, New York, US"
    }
  ],
  "events": [
    {
      "code": "ESW0000001",
      "dateTime": "2024-03-15T11:22:00+00:00",
      "location": ""
    },
    {
      "code": "ESW0000044",
      "dateTime": "2024-03-25T07:45:00+00:00",
      "location": "JFKDC, New York"
    }
  ]
}
```

{% endcode %}

{% hint style="info" %}
Surface `milestones` (with `isCurrentMilestone`) on the shopper-facing tracking page. Surface raw `events` only in the ops dashboard.
{% endhint %}
{% endstep %}

{% step %}

#### Put return order on hold pending QC (PUT)

Agent sets the return to `OnHold` with a reason to prevent automated downstream processing. Only the `status` and `statusReason` fields need to be sent — `returnItems` is omitted since item-level status isn't being changed yet.

#### Request

{% code title="PUT /GOCAS/orders/ORD-20240315-88821/return-orders/5000032891" %}

```json
{
  // UpdateReturnOrderWebRequest
  "status":       "OnHold",
  "statusReason": "Parcel received — held pending QC inspection. Possible fabric damage visible."
  // returnItems: omit if not changing item-level status
  // weight: omit if not updating — useful if actual weight differs from declared
}
```

{% endcode %}

<mark style="color:$success;">`200`</mark> OK
{% endstep %}

{% step %}

#### Release and grade return items (Accept / Reject) (PUT)

QC inspection complete. Agent releases the hold and grades items. Accepted items are `Accepted`; damaged items are `Rejected` with `rejectionReason`. `reasonCodeOverride` can correct shopper-declared reason.

#### Request

{% code title="PUT /GOCAS/orders/ORD-20240315-88821/return-orders/5000032891" expandable="true" %}

```json
{
  "status":       "Released",     // Move from OnHold → Released to resume processing
  "statusReason": "QC complete — item graded",

  "returnItems": [
    {
      // UpdateReturnOrderItemDto
      "id":            "0013db57-885d-462b-a24f-80312a9g3207",
      "productCode":   "SKU-JEANS-32-INDIGO",
      "lineItemId":    "1",

      "returnItemStatus": "Accepted",  // Enum: "Accepted" | "Rejected"

      // reasonCode: the shopper-declared reason (carry through from CreateReturnOrder)
      "reasonCode":         "DoesNotFit",
      // reasonCodeOverride: set when the physical inspection reveals a different reason than declared
      // here it matches, so both are the same — omit entirely if no override needed
      "reasonCodeOverride": "DoesNotFit"

      // rejectionReason: only include when returnItemStatus is "Rejected" — omit entirely for Accepted
    }
  ],

  // Update actual weighed weight if different from declared
  "weight": { "weightTotal": 0.62, "weightUnit": "Kg" }
}
```

{% endcode %}

<mark style="color:$success;">`200`</mark> OK

{% hint style="success" %}
Once an item reaches `Accepted` or `Rejected`, downstream automation (manifest generation, refund trigger) is unblocked. Typical lifecycle: `Released` → `Processed` → `AddedToManifest` → `SentToRetailer` → `ReceivedByRetailer` → `Refunded`.
{% endhint %}
{% endstep %}
{% endstepper %}

Sequence summary: `GET /return-orders` → `GET /orders/{ref}/return-orders/{num}` → `POST /tracking-events` → `PUT /orders/{ref}/return-orders/{num}` (OnHold) → `PUT /orders/{ref}/return-orders/{num}` (Released + grades)

***


---

# 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/grp-returns-api/use-cases.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.
