> 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/checkout-api/resources/tutorials/delivery-options.md).

# Delivery Options

The Order Confirmation request supports two parallel delivery option fields — `deliveryOption` and `retailerDeliveryOption` — that serve different purposes and carry different levels of configuration responsibility.

Checkout API also exposes three delivery modifier flags — `isShipToStore`, `isMultiOrigin`, and `isPriceOverrideFromRetailer` — and supports per-line-item delivery option overrides for orders where different products ship via different methods.

***

{% stepper %}
{% step %}

### Step 1 — The Fundamental Distinction

The Checkout API models two different delivery ownership models:

|                                   | `deliveryOption`              | `retailerDeliveryOption`               |
| --------------------------------- | ----------------------------- | -------------------------------------- |
| Who owns the option?              | ESW                           | Retailer                               |
| Who sets the code?                | ESW — agreed at onboarding    | Retailer — agreed with ESW             |
| Who controls the price?           | ESW (by default)              | Retailer                               |
| Code length limit                 | **15 characters**             | No limit                               |
| Title required?                   | No                            | **Yes**                                |
| Estimated delivery date required? | No                            | **Yes (`dateTo` minimum)**             |
| Price info required?              | No                            | **Yes**                                |
| When to use                       | Standard ESW-managed delivery | Custom delivery configured by retailer |

Only one of the two should be populated for any given order. Populating both on the same request is not supported.
{% endstep %}

{% step %}

### &#x20;`deliveryOption`&#x20;

Use `deliveryOption` when the delivery option is managed by ESW — ESW owns the code, the pricing configuration, and the delivery rules for this option.

#### Structure

```json
"deliveryOption": {
  "deliveryOption": "STD_US",
  "isShipToStore": false,
  "isMultiOrigin": false,
  "isPriceOverrideFromRetailer": false
}
```

<details>

<summary>Field reference</summary>

| Field                         | Type    | Required | Constraint            | Description                                                                     |
| ----------------------------- | ------- | -------- | --------------------- | ------------------------------------------------------------------------------- |
| `deliveryOption`              | string  | ✅        | Max **15 characters** | The ESW delivery option code as agreed during integration. Case-sensitive.      |
| `isShipToStore`               | boolean | ❌        | —                     | `true` if the shopper elected to collect from a store rather than home delivery |
| `isMultiOrigin`               | boolean | ❌        | —                     | `true` if this order ships from multiple origin warehouses                      |
| `isPriceOverrideFromRetailer` | boolean | ❌        | —                     | `true` if the retailer is overriding ESW's configured delivery price            |
| `deliveryOptionPriceInfo`     | object  | ❌        | —                     | The delivery price — required only when `isPriceOverrideFromRetailer` is `true` |
| `metadataItems`               | array   | ❌        | —                     | Key-value pairs agreed with ESW                                                 |

</details>

#### The 15-character code limit

The `deliveryOption` code has a maximum of 15 characters. ESW-agreed codes are always within this limit. If you find yourself with a code longer than 15 characters, you are likely using a retailer-side identifier and should use `retailerDeliveryOption` instead.

#### Minimal example

```json
"deliveryOption": {
  "deliveryOption": "STD_US"
}
```

When using `deliveryOption` without a price override, this is all that is required. ESW applies its configured price for that code automatically.
{% endstep %}

{% step %}

### &#x20;`retailerDeliveryOption`&#x20;

Use `retailerDeliveryOption` when the retailer is providing their own delivery option definition — including the option code, a display title, the estimated delivery window, and the price.

#### Structure

{% code expandable="true" %}

```json
"retailerDeliveryOption": {
  "deliveryOption": "RETAILER_EXPRESS_AU_COURIER_DHL",
  "title": "DHL Express Courier (2–4 business days)",
  "estimatedDeliveryDateToShopper": {
    "dateFrom": "2024-11-18T00:00:00Z",
    "dateTo":   "2024-11-20T00:00:00Z"
  },
  "deliveryOptionPriceInfo": {
    "price": {
      "retailer": { "currency": "EUR", "amount": "18.00" },
      "shopper":  { "currency": "AUD", "amount": "29.70" }
    }
  },
  "metadataItems": [
    { "name": "carrier", "value": "DHL" },
    { "name": "serviceLevel", "value": "EXPRESS" }
  ]
}
```

{% endcode %}

<details>

<summary>Field reference</summary>

| Field                            | Type   | Required | Description                                                        |
| -------------------------------- | ------ | -------- | ------------------------------------------------------------------ |
| `deliveryOption`                 | string | ✅        | The retailer's delivery option code. No length limit.              |
| `title`                          | string | ✅        | Human-readable label for the delivery option, shown to the shopper |
| `estimatedDeliveryDateToShopper` | object | ✅        | The estimated delivery window (see below)                          |
| `deliveryOptionPriceInfo`        | object | ✅        | The delivery price in both currencies                              |
| `metadataItems`                  | array  | ❌        | Key-value pairs agreed with ESW                                    |

</details>

#### `estimatedDeliveryDateToShopper` fields

| Field      | Type                  | Required | Description                                                      |
| ---------- | --------------------- | -------- | ---------------------------------------------------------------- |
| `dateTo`   | ISO 8601 UTC datetime | ✅        | Latest estimated delivery date — the outer bound of the window   |
| `dateFrom` | ISO 8601 UTC datetime | ❌        | Earliest estimated delivery date — the inner bound of the window |

`dateTo` is the only required field. Always include `dateFrom` when a delivery window is known rather than a single target date — it gives ESW and the shopper a complete and accurate delivery expectation.

```json
"estimatedDeliveryDateToShopper": {
  "dateFrom": "2024-11-18T00:00:00Z",
  "dateTo":   "2024-11-20T00:00:00Z"
}
```

For a single target date rather than a window, populate only `dateTo`:

```json
"estimatedDeliveryDateToShopper": {
  "dateTo": "2024-11-20T00:00:00Z"
}
```

#### `deliveryOptionPriceInfo` for `retailerDeliveryOption`

`deliveryOptionPriceInfo` is required on `retailerDeliveryOption` — the retailer is providing the price, so it must always be present. The `price` field within it is required; `discounts` is optional.

{% code expandable="true" %}

```json
"deliveryOptionPriceInfo": {
  "price": {
    "retailer": { "currency": "EUR", "amount": "18.00" },
    "shopper":  { "currency": "AUD", "amount": "29.70" }
  },
  "discounts": [
    {
      "title": "Free express upgrade",
      "discount": {
        "retailer": { "currency": "EUR", "amount": "5.00" },
        "shopper":  { "currency": "AUD", "amount": "8.25" }
      },
      "beforeDiscount": {
        "retailer": { "currency": "EUR", "amount": "23.00" },
        "shopper":  { "currency": "AUD", "amount": "37.95" }
      }
    }
  ]
}
```

{% endcode %}

The `price` in `deliveryOptionPriceInfo` is the **final price after any delivery discounts have been applied**. If a delivery discount exists, include it in the `discounts` array with `discount` (amount removed) and `beforeDiscount` (original price) so ESW has a full audit trail.
{% endstep %}

{% step %}

### Delivery Price and Discounts

#### When using `deliveryOption` (ESW-managed)

Price info is **optional** on `deliveryOption`. Only include it when `isPriceOverrideFromRetailer` is `true`. In all other cases, ESW applies the price configured for the option code.

```json
"deliveryOption": {
  "deliveryOption": "EXPRESS_US",
  "isPriceOverrideFromRetailer": true,
  "deliveryOptionPriceInfo": {
    "price": {
      "retailer": { "currency": "EUR", "amount": "12.00" },
      "shopper":  { "currency": "USD", "amount": "13.05" }
    }
  }
}
```

#### When using `retailerDeliveryOption`

Price info is **required** — the retailer owns the pricing, so it must be provided in every request.

#### Reconciliation with `charges.delivery`

Whichever delivery option field you use, the price within it must match `charges.delivery` on the order-level charges:

```
deliveryOption.deliveryOptionPriceInfo.price
  ==
charges.delivery

retailerDeliveryOption.deliveryOptionPriceInfo.price
  ==
charges.delivery
```

This is not enforced by a schema constraint but is validated by ESW during processing. A mismatch will result in a `409 Conflict`.
{% endstep %}

{% step %}

### `isShipToStore`

Set `isShipToStore: true` when the shopper elected to collect their order from a physical store rather than receive a home delivery.

```json
"deliveryOption": {
  "deliveryOption": "STS_UK",
  "isShipToStore": true
}
```

#### What changes with ship-to-store

* The delivery address in `contactDetails[IsDelivery]` should be the store's address, not the shopper's home address
* The delivery charge in `charges.delivery` reflects the ship-to-store fulfilment cost (which may be zero for free in-store collection)
* ESW uses this flag to apply the correct customs and carrier routing for store-bound shipments

#### Ship-to-store with a zero delivery charge

When ship-to-store is free for the shopper, include `charges.delivery` as a zero amount rather than omitting it — this explicitly confirms that no delivery charge was applied:

```json
"charges": {
  "total": {
    "retailer": { "currency": "GBP", "amount": "95.50" },
    "shopper":  { "currency": "GBP", "amount": "95.50" }
  },
  "delivery": {
    "retailer": { "currency": "GBP", "amount": "0.00" },
    "shopper":  { "currency": "GBP", "amount": "0.00" }
  }
}
```

#### Store address in `contactDetails`

```json
"contactDetails": [
  {
    "contactDetailType": "IsDelivery",
    "firstName": "James",
    "lastName": "Carter",
    "address1": "Flagship Store — 150 Oxford Street",
    "city": "London",
    "postalCode": "W1D 1LL",
    "country": "GB",
    "email": "james.carter@example.com",
    "isSelected": true,
    "status": "Added"
  }
]
```

{% endstep %}

{% step %}

### &#x20;`isMultiOrigin`

Set `isMultiOrigin: true` when the order ships from more than one origin warehouse or fulfilment centre. This flag tells ESW that the order cannot be consolidated into a single shipment from a single location.

```json
"deliveryOption": {
  "deliveryOption": "STD_DE",
  "isMultiOrigin": true
}
```

#### When to use `isMultiOrigin`

* Products in the same order are fulfilled from warehouses in different countries
* Different product categories use different regional distribution centres
* Some items ship from a main warehouse and others ship directly from a supplier

#### Relationship with `lineItems[].fulfilmentCountryIso`

When `isMultiOrigin` is `true`, use the `fulfilmentCountryIso` field on each line item to record which country each product is fulfilled from:

{% code expandable="true" %}

```json
"lineItems": [
  {
    "quantity": 1,
    "lineItemId": 1,
    "fulfilmentCountryIso": "IT",
    "product": { ... },
    "charges": { ... }
  },
  {
    "quantity": 1,
    "lineItemId": 2,
    "fulfilmentCountryIso": "FR",
    "product": { ... },
    "charges": { ... }
  }
]
```

{% endcode %}

Each line item may produce a separate customs declaration and carrier booking when `isMultiOrigin` is `true`. ESW uses `fulfilmentCountryIso` on each line to route each shipment correctly.

#### Multi-origin and delivery dates

When products ship from different origins, their estimated delivery dates may differ. Use the `estimatedDeliveryDate` on each line item to capture the expected delivery window per product, rather than relying solely on the order-level delivery option dates:

{% code expandable="true" %}

```json
"lineItems": [
  {
    "lineItemId": 1,
    "fulfilmentCountryIso": "IT",
    "estimatedDeliveryDate": {
      "fromEShopWorldRangeFrom": "2024-11-18T00:00:00Z",
      "fromEShopWorldRangeTo":   "2024-11-21T00:00:00Z"
    }
  },
  {
    "lineItemId": 2,
    "fulfilmentCountryIso": "FR",
    "estimatedDeliveryDate": {
      "fromEShopWorldRangeFrom": "2024-11-20T00:00:00Z",
      "fromEShopWorldRangeTo":   "2024-11-22T00:00:00Z"
    }
  }
]
```

{% endcode %}
{% endstep %}

{% step %}

### &#x20;`isPriceOverrideFromRetailer`

Set `isPriceOverrideFromRetailer: true` when you are using an ESW-agreed delivery option code but providing your own delivery price rather than using the price ESW has configured for that option.

```json
"deliveryOption": {
  "deliveryOption": "EXPRESS_JP",
  "isPriceOverrideFromRetailer": true,
  "deliveryOptionPriceInfo": {
    "price": {
      "retailer": { "currency": "EUR", "amount": "15.00" },
      "shopper":  { "currency": "JPY", "amount": "2438" }
    }
  }
}
```

#### When to use this flag

* Your checkout shows a custom or promotional delivery price for an ESW-managed option
* A loyalty programme provides free or reduced delivery on an otherwise-paid ESW option
* Your system has negotiated a specific delivery price that differs from ESW's default

#### When NOT to use this flag

* If you are providing a fully retailer-defined delivery option — use `retailerDeliveryOption` instead
* If the price matches ESW's configured price exactly — omit `isPriceOverrideFromRetailer` (it defaults to `false`) and omit `deliveryOptionPriceInfo`

#### Delivery discount via `isPriceOverrideFromRetailer`

When the override is the result of a discount applied to the standard delivery price, record the discount in `deliveryOptionPriceInfo.discounts` so ESW has a clear audit trail:

{% code expandable="true" %}

```json
"deliveryOption": {
  "deliveryOption": "EXPRESS_JP",
  "isPriceOverrideFromRetailer": true,
  "deliveryOptionPriceInfo": {
    "price": {
      "retailer": { "currency": "EUR", "amount": "0.00" },
      "shopper":  { "currency": "JPY", "amount": "0" }
    },
    "discounts": [
      {
        "title": "Loyalty Free Delivery",
        "description": "Gold tier members receive free express delivery",
        "beforeDiscount": {
          "retailer": { "currency": "EUR", "amount": "15.00" },
          "shopper":  { "currency": "JPY", "amount": "2438" }
        },
        "discount": {
          "retailer": { "currency": "EUR", "amount": "15.00" },
          "shopper":  { "currency": "JPY", "amount": "2438" }
        }
      }
    ]
  }
}
```

{% endcode %}
{% endstep %}

{% step %}

### Per-Line-Item Delivery Option Overrides

Individual line items can carry their own delivery option identifier via the `deliveryOption` string field on `OrderConfirmationLineItemRequestDto`. This is used when different products in the same order ship via different delivery methods — for example, when a standard item and a click-and-collect item are purchased in the same cart.

{% code expandable="true" %}

```json
"lineItems": [
  {
    "quantity": 1,
    "lineItemId": 1,
    "deliveryOption": "STD_UK",
    "product": { ... },
    "estimatedDeliveryDate": { ... },
    "charges": { ... }
  },
  {
    "quantity": 1,
    "lineItemId": 2,
    "deliveryOption": "STS_UK",
    "product": { ... },
    "estimatedDeliveryDate": { ... },
    "charges": { ... }
  }
]
```

{% endcode %}

#### How line item `deliveryOption` relates to the order-level option

The order-level `deliveryOption` or `retailerDeliveryOption` represents the **primary** or **default** delivery method for the order. The line item `deliveryOption` is an **override** for a specific line when it differs from the order-level method.

If all line items use the same delivery method, the line item `deliveryOption` field can be omitted entirely — the order-level delivery option applies to all lines by default.

#### Line item `deliveryOption` is a plain string

Unlike the order-level `deliveryOption` object (which has flags and price info), the line item `deliveryOption` field is simply a string — the delivery option code. There are no flags or price fields at this level.

```json
"deliveryOption": "EXPRESS_UK"   ← just the code string, nothing else
```

{% endstep %}

{% step %}

### `estimatedDeliveryDate` on Line Items

Each line item has an `estimatedDeliveryDate` object (`OrderConfirmationEstimatedDeliveryDateRequestDto`) with four optional fields representing different sources of delivery date information.

```json
"estimatedDeliveryDate": {
  "fromRetailer":             "2024-11-20T00:00:00Z",
  "fromEShopWorld":           "2024-11-19T00:00:00Z",
  "fromEShopWorldRangeFrom":  "2024-11-18T00:00:00Z",
  "fromEShopWorldRangeTo":    "2024-11-21T00:00:00Z"
}
```

| Field                     | Source            | Type                  | Description                                                           |
| ------------------------- | ----------------- | --------------------- | --------------------------------------------------------------------- |
| `fromRetailer`            | Retailer-provided | ISO 8601 UTC datetime | Single estimated delivery date from the retailer's own logistics data |
| `fromEShopWorld`          | ESW-provided      | ISO 8601 UTC datetime | Single estimated delivery date calculated by ESW                      |
| `fromEShopWorldRangeFrom` | ESW-provided      | ISO 8601 UTC datetime | Start of ESW's estimated delivery window                              |
| `fromEShopWorldRangeTo`   | ESW-provided      | ISO 8601 UTC datetime | End of ESW's estimated delivery window                                |

```json
"estimatedDeliveryDate": {}
```

{% endstep %}

{% step %}

### Worked Examples

#### Example A — Standard ESW-managed delivery, no overrides

```json
"deliveryOption": {
  "deliveryOption": "STD_US"
}
```

Minimal. ESW uses its configured price, routing, and rules for `STD_US`.

***

#### Example B — ESW delivery option with free delivery override (loyalty benefit)

json

{% code expandable="true" %}

```json
"deliveryOption": {
  "deliveryOption": "EXPRESS_US",
  "isPriceOverrideFromRetailer": true,
  "deliveryOptionPriceInfo": {
    "price": {
      "retailer": { "currency": "EUR", "amount": "0.00" },
      "shopper":  { "currency": "USD", "amount": "0.00" }
    },
    "discounts": [
      {
        "title": "Gold Loyalty: Free Express Delivery",
        "beforeDiscount": {
          "retailer": { "currency": "EUR", "amount": "12.00" },
          "shopper":  { "currency": "USD", "amount": "13.04" }
        },
        "discount": {
          "retailer": { "currency": "EUR", "amount": "12.00" },
          "shopper":  { "currency": "USD", "amount": "13.04" }
        }
      }
    ]
  }
}
```

{% endcode %}

`charges.delivery` should also be `0.00` / `0.00` to match.

#### Example C — Retailer-configured express delivery

{% code expandable="true" %}

```json
"retailerDeliveryOption": {
  "deliveryOption": "MYBRAND_EXPRESS_DE_FEDEX",
  "title": "FedEx International Priority (1–2 business days)",
  "estimatedDeliveryDateToShopper": {
    "dateFrom": "2024-11-16T00:00:00Z",
    "dateTo":   "2024-11-17T00:00:00Z"
  },
  "deliveryOptionPriceInfo": {
    "price": {
      "retailer": { "currency": "EUR", "amount": "22.00" },
      "shopper":  { "currency": "EUR", "amount": "22.00" }
    }
  }
}
```

{% endcode %}

#### Example D — Ship-to-store with zero delivery charge

{% code expandable="true" %}

```json
"deliveryOption": {
  "deliveryOption": "STS_FR",
  "isShipToStore": true,
  "isPriceOverrideFromRetailer": true,
  "deliveryOptionPriceInfo": {
    "price": {
      "retailer": { "currency": "EUR", "amount": "0.00" },
      "shopper":  { "currency": "EUR", "amount": "0.00" }
    }
  }
}
```

{% endcode %}

Contact details delivery address points to the store:

{% code expandable="true" %}

```json
"contactDetails": [
  {
    "contactDetailType": "IsDelivery",
    "firstName": "Marie",
    "lastName":  "Dupont",
    "address1":  "MYBRAND Paris — 12 Rue du Faubourg Saint-Honoré",
    "city":      "Paris",
    "postalCode": "75008",
    "country":   "FR",
    "email":     "marie.dupont@example.com",
    "isSelected": true,
    "status":    "Added"
  }
]
```

{% endcode %}

#### Example E — Multi-origin order, two products from different countries

{% code expandable="true" %}

```json
"deliveryOption": {
  "deliveryOption": "STD_AU",
  "isMultiOrigin": true
},

"lineItems": [
  {
    "quantity": 1,
    "lineItemId": 1,
    "fulfilmentCountryIso": "IT",
    "deliveryOption": "STD_AU",
    "estimatedDeliveryDate": {
      "fromEShopWorldRangeFrom": "2024-11-20T00:00:00Z",
      "fromEShopWorldRangeTo":   "2024-11-24T00:00:00Z"
    },
    "product": { ... },
    "charges": { ... }
  },
  {
    "quantity": 1,
    "lineItemId": 2,
    "fulfilmentCountryIso": "DE",
    "deliveryOption": "STD_AU",
    "estimatedDeliveryDate": {
      "fromEShopWorldRangeFrom": "2024-11-22T00:00:00Z",
      "fromEShopWorldRangeTo":   "2024-11-26T00:00:00Z"
    },
    "product": { ... },
    "charges": { ... }
  }
]
```

{% endcode %}

Both lines use the same delivery option code but ship from different countries, producing separate customs declarations. Note the different delivery windows per line — the German fulfilment centre has a slightly later estimated dispatch.

#### Example F — Mixed delivery methods in one order (standard + click-and-collect)

{% code expandable="true" %}

```json
"deliveryOption": {
  "deliveryOption": "STD_UK"
},

"lineItems": [
  {
    "quantity": 1,
    "lineItemId": 1,
    "deliveryOption": "STD_UK",
    "estimatedDeliveryDate": {
      "fromEShopWorldRangeFrom": "2024-11-18T00:00:00Z",
      "fromEShopWorldRangeTo":   "2024-11-20T00:00:00Z"
    },
    "product": { ... },
    "charges": { ... }
  },
  {
    "quantity": 2,
    "lineItemId": 2,
    "deliveryOption": "STS_UK",
    "estimatedDeliveryDate": {
      "fromEShopWorldRangeFrom": "2024-11-17T00:00:00Z",
      "fromEShopWorldRangeTo":   "2024-11-17T00:00:00Z"
    },
    "product": { ... },
    "charges": { ... }
  }
]
```

{% endcode %}

Line 1 ships to the shopper's home. Line 2 ships to a store for click-and-collect. The order-level `deliveryOption` is `STD_UK` (the primary method). Line 2 overrides it with `STS_UK`.
{% endstep %}
{% endstepper %}

***

### Summary&#x20;

{% code expandable="true" %}

```ruby
Order uses a delivery option code?
        │
        ├── Code was agreed with ESW at integration onboarding
        │     → deliveryOption
        │     → Code ≤ 15 chars
        │           │
        │           ├── ESW manages the price → no deliveryOptionPriceInfo needed
        │           │
        │           └── Retailer overrides the price
        │                 → isPriceOverrideFromRetailer: true
        │                 → include deliveryOptionPriceInfo
        │
        └── Code was defined by the retailer
              → retailerDeliveryOption
              → Must include: title, estimatedDeliveryDateToShopper (dateTo), deliveryOptionPriceInfo

Additional flags (on deliveryOption only):
  Shopper collects from store?  → isShipToStore: true
  Multiple fulfilment origins?  → isMultiOrigin: true + fulfilmentCountryIso on each line item

Per-line overrides:
  Different delivery method per line? → lineItems[n].deliveryOption (string code)
```

{% endcode %}


---

# 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/checkout-api/resources/tutorials/delivery-options.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.
