> 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/package-api/resources/workflows.md).

# Workflows

## 01 - Package Lifecycle — Create, Retrieve, Update & Delete

Use the Package API to create a package, retrieve it by reference, update it while it is still pending, and delete it using its unique identifiers. In V4, the lifecycle is `POST /api/v4/Package`, `GET /api/v4/Package`, `PUT /api/v4/Package`, and `DELETE /api/v4/Package`. A package can only be updated when its current `shippingStatus` is `Pending`. If `shippingStatus` is omitted on create, `Complete` is assumed.

{% stepper %}
{% step %}

#### Create a package

{% code expandable="true" %}

```http
POST /api/v4/Package
```

{% endcode %}

Minimum required create payload

* `brandCode`
* `orderReference`
* `packageReference`
* `orderType`
* `weight` packageapi

{% code title="Minimum viable payload — checkout order" %}

```json
{
  "brandCode": "ESW",
  "orderReference": "ORD-20240315-001",
  "packageReference": "PKG-20240315-001",
  "orderType": "CHECKOUT",
  "weight": {
    "weight": 1.5,
    "weightUnit": "KG"
  }
}
```

{% endcode %}

For checkout orders, fields such as `shippingDocumentationRequested`, `returnDocumentationRequested`, `consignee`, `dimensions`, `distributionCentre`, `serviceLevel`, and `packageItems` are optional.

{% hint style="danger" %}
If `packageItems` is not supplied, ESW assumes all items in the order are contained in the package.
{% endhint %}

\ <mark style="color:$success;">`200`</mark>`OK` returns `PackageCreateResponse`, which contains:

* `outcome`
* `statusMessage`
* `package`

Typical create errors include `400 Validation failure`, `422 Validation failure`, `404 Invalid request`, and `409 Conflict - package already exists`.
{% endstep %}

{% step %}

#### Create a non-checkout package

{% code expandable="true" %}

```http
POST /api/v4/Package
```

{% endcode %}

Supported order types: `CHECKOUT`, `NONCHECKOUT`, `RETURN`, `OFFLINE`, and `NONCHECKOUTECOMMERCE`.

When you send `packageItems`, each item requires `productCode`, `quantity`, and `weight`. For non-checkout orders, these fields are required: `productDescription`, `productCustomsDescription`, `countryOfOrigin`, `unitPrice`, and `hsCode`. Dangerous-goods flags are optional unless your operational process requires them.

{% code title="Example — non-checkout / cross-border package" expandable="true" %}

```json
{
  "brandCode": "ESW",
  "orderReference": "ORD-NC-20240315-009",
  "packageReference": "PKG-NC-20240315-009",
  "orderType": "NONCHECKOUT",
  "weight": {
    "weight": 1.2,
    "weightUnit": "KG"
  },
  "additionalImportInformation": "Certificate of Origin attached",
  "dangerousGoods": false,
  "packageItems": [
    {
      "productCode": "SKU-PERFUME-50ML",
      "quantity": 2,
      "weight": {
        "weight": 0.6,
        "weightUnit": "KG"
      },
      "productDescription": "Eau de Parfum 50ml",
      "productCustomsDescription": "Fragrance, alcohol base, glass bottle",
      "countryOfOrigin": "FR",
      "unitPrice": {
        "amount": 89.00,
        "currency": "USD"
      },
      "hsCode": "3303.00.10",
      "fta": false,
      "dangerousGoods": false
    }
  ]
}
```

{% endcode %}
{% endstep %}

{% step %}

#### Retrieve a package

{% code expandable="true" %}

```http
GET /api/v4/Package
```

{% endcode %}

Retrieve the current package record using `BrandCode` and `PackageReference`. `OrderReference` is optional and can be used as an additional filter. A successful response returns the full `Package` object.

**Example**

```http
GET /api/v4/Package?BrandCode=ESW&PackageReference=PKG-20240315-001
```

**Query parameters**

| Parameter          | Type   | Required | Notes                                 |
| ------------------ | ------ | -------- | ------------------------------------- |
| `BrandCode`        | string | Yes      | ESW three-letter brand identifier     |
| `PackageReference` | string | Yes      | Retailer’s unique package reference   |
| `OrderReference`   | string | No       | Optional filter for the related order |

**Response**\
`200 OK` — `Package`
{% endstep %}

{% step %}

#### Update a package

{% code expandable="true" %}

```http
PUT /api/v4/Package
```

{% endcode %}

Use update when you need to change package details after creation. The spec explicitly says a package can only be updated if its current `Shipping Status` is `Pending`. The update request requires:

* `brandCode`
* `orderReference`
* `packageReference` packageapi packageapi

This matters because if you create a package without `shippingStatus`, ESW assumes `Complete`, and no further `PUT` updates can be processed. If you expect a later update, create the package with `shippingStatus: "Pending"` first.

{% code title="Example — mark package as ready to ship" %}

```
{
  "brandCode": "ESW",
  "orderReference": "ORD-20240315-001",
  "packageReference": "PKG-20240315-001",
  "shippingStatus": "Complete",
  "carrierId": 21,
  "carrierReference": "TRACK-123456789",
  "distributionCentre": "IEDUB",
  "serviceLevel": "POST"
}
```

{% endcode %}

**Response**\
`201 Created` — updated `Package`

Typical update errors include `400 Validation failure`, `404 Could not find package`, and `409 Package is not in a valid state for updating`.
{% endstep %}

{% step %}

#### Delete a package

{% code expandable="true" %}

```http
DELETE /api/v4/Package
```

{% endcode %}

Delete uses the package’s unique identifiers. All three query parameters are required:

* `BrandCode`
* `OrderReference`
* `PackageReference`

**Example**

```http
DELETE /api/v4/Package?BrandCode=ESW&OrderReference=ORD-20240315-001&PackageReference=PKG-20240315-001
```

**Response**\
`200 OK` — Package deleted. packageapi

`409 Conflict` is returned when the package is “not in a valid state for deletion.

{% hint style="info" %}

#### Notes

* Create the package with `shippingStatus: "Pending"` if more shipping details will arrive later.
* Retrieve the package as needed to inspect current values and references.
* Update the package with carrier or shipment details while it is still pending.
* Delete only when the package is still in a valid deletable state.
  {% endhint %}
  {% endstep %}
  {% endstepper %}

***

## 02 - Package Update

*Caption: Original wording preserved. Reformatted for scanning only.*

Use this operation to update an existing package’s information, such as carrier details, weight, dimensions, consignee details, distribution centre, service level, pallet ID, or shipping status. The Package API only allows updates when the package’s current `shippingStatus` is `Pending`.

<div data-with-frame="true"><figure><img src="/files/cjdzTfpRSA2oQGWZW9lY" alt=""><figcaption></figcaption></figure></div>

{% stepper %}
{% step %}

#### Check the current package status

Before sending an update, it is recommended to retrieve the package and confirm that its current `shippingStatus` is `Pending`. This is a best-practice validation step. If the package is already `Complete`, no further `PUT` updates can be processed.

Example request:

```http
GET /api/v4/Package?BrandCode=ESW&PackageReference=PKG-001
```

Valid `shippingStatus` values are `Pending` and `Complete`. `Pending` means ESW expects a later update, while `Complete` means no further `PUT` updates can be processed.
{% endstep %}

{% step %}

#### Update package details

Send a `PUT` request with the package identifiers and any fields you need to update. The required identifiers are `brandCode`, `orderReference`, and `packageReference`. These values are used to identify the existing package and cannot be changed.

Example request:

```http
PUT /api/v4/Package
```

{% code title="Example payload" expandable="true" %}

```json
{
  "brandCode": "ESW",
  "orderReference": "ORD-20240315-001",
  "packageReference": "PKG-20240315-001",
  "carrierId": 42,
  "carrierReference": "DHL-TRK-9900123",
  "carrierServiceDescription": "DHL Express Worldwide",
  "weight": {
    "weight": 1.8,
    "weightUnit": "KG"
  },
  "dimensions": {
    "dimHeight": "22",
    "dimLength": "32",
    "dimWidth": "16",
    "dimMeasurementUnit": "CM"
  },
  "consignee": {
    "address1": "15 New Address Road",
    "city": "Manchester",
    "postalCode": "M1 1AA",
    "country": "GB"
  },
  "distributionCentre": "IEDUB",
  "palletId": "PLT-2024-007"
}
```

{% endcode %}

This example is valid in principle because `PackageUpdate` supports fields such as `shippingStatus`, `weight`, `carrierId`, `carrierReference`, `carrierServiceDescription`, `distributionCentre`, `consignee`, `dimensions`, `serviceLevel`, and `palletId`. The consignee update object can also be supplied partially.

#### Responses

{% code title="" expandable="true" %}

```http
On success, the API returns 201 Created with the updated Package object.
```

{% endcode %}

Possible error responses include:

* `400 Validation failure`
* `404 Could not find package`
* `409 Package is not in a valid state for updating`

#### Pending-only rule

The `PUT /api/v4/Package` endpoint can only update a package whose current `shippingStatus` is `Pending`. If the package is not in a valid state for updating, such as when it is already `Complete`, the API can return `409`.
{% endstep %}
{% endstepper %}

***

## 03 - Label Configuration

Use the `LabelConfig` endpoints to download the current label configuration file for a tenant, upload a new configuration file, retrieve configuration history for a tenant, and download a historical configuration file by its history record ID.

{% stepper %}
{% step %}

#### Download current label config

Retrieve the current label configuration file for a tenant.

`GET /api/v4/LabelConfig/{tenantCode}/excel`

Path parameter:

* `tenantCode` — required string path parameter.

Response:

* `200 OK` — binary file response
* `500 Internal Server Error`
  {% endstep %}

{% step %}

#### Upload updated label config

Upload a label configuration file for the tenant using multipart form data.

`POST /api/v4/LabelConfig/{tenantCode}/excel`

Path parameter:

* `tenantCode` — required string path parameter

Request body:

* `multipart/form-data`
* field: `file` — binary

Response:

* `200 OK`
* `400 Bad Request` — `ProblemDetails`
* `500 Internal Server Error`
  {% endstep %}

{% step %}

#### Review config version history

Retrieve label configuration history for a tenant.

`GET /api/v4/LabelConfig/{tenantCode}/history`

Response:

* `200 OK` — `LabelConfigHistoryListResponse`
* `500 Internal Server Error`

Each history record can include:

* `id`
* `tenantCode`
* `fileName`
* `uploadedByName`
* `uploadedByEmail`
* `createdOn`
  {% endstep %}

{% step %}

#### Download a historical config version

Download a historical configuration file by history record ID.

`GET /api/v4/LabelConfig/history/{id}`

Path parameter:

* `id` — required string path parameter, described as the record ID.

Response:

* `200 OK` — binary file response
* `500 Internal Server Error`

#### **Rollback guidance**

A practical rollback approach is to download a previous historical file and upload it again as a new label configuration version.
{% endstep %}
{% endstepper %}

***

## 04 - Manifest Management

*Caption: Original wording preserved. Reformatted for scanning only.*

Use the Manifest API to submit manifest information in a single request. The endpoint is `POST /api/v4/Manifest`, and its request body is `ManifestRequest`. The request can include a manifest number, origin and destination airport codes, a carrier ID, a ground handling agent, flight details, and a list of pallets. The operation summary in the spec is simply **“Manifest information update.”** packageapi packageapi

{% stepper %}
{% step %}

#### Submit manifest

Submit manifest data when you need to associate pallet information and flight details with a manifest record.

```http
POST /api/v4/Manifest
```

The `ManifestRequest` schema can include:

* `manifestNumber`
* `originAirportCode`
* `destinationAirportCode`
* `carrierId`
* `groundHandlingAgent`
* `flight`
* `pallets`

#### Flight details

The `flight` object uses these field names:

* `carrierCode`
* `flightNumber`
* `estimatedTimeOfDeparture`
* `estimatedTimeOfArrival`

#### Pallet details

Each pallet uses these field names:

* `palletReference`
* `eShopPackageReferences`

#### Example payload

This example uses the field names defined in the spec. In particular, the pallet object uses `palletReference` rather than `palletId`, and package entries are `eShopPackageReferences` rather than `packageReferences`. The flight object also uses `estimatedTimeOfDeparture` and `estimatedTimeOfArrival`, not `departureDateTime` and `arrivalDateTime`. packageapi packageapi

#### Responses

Possible responses for `POST /api/v4/Manifest` are:

* `200` — Manifest information updated
* `204` — No content found
* `400` — Validation failure
* `404` — Could not find manifest
* `401` — The request failed as a bad request

{% code expandable="true" %}

```json
{
  "manifestNumber": "MAN-20240315-LHR-001",
  "originAirportCode": "DUB",
  "destinationAirportCode": "LHR",
  "carrierId": 42,
  "groundHandlingAgent": "Swissport",
  "flight": {
    "carrierCode": "EI",
    "flightNumber": "EI105",
    "estimatedTimeOfDeparture": "2024-03-15T14:30:00Z",
    "estimatedTimeOfArrival": "2024-03-15T15:50:00Z"
  },
  "pallets": [
    {
      "palletReference": "PLT-2024-007",
      "eShopPackageReferences": [
        6001020171566,
        6001020203244,
        6001020203245
      ]
    },
    {
      "palletReference": "PLT-2024-008",
      "eShopPackageReferences": [
        6001020203246
      ]
    }
  ]
}
```

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

## 05 - Package Dimension Management

Use the PackageDimension API to retrieve, create or update, and delete master package dimension records for a brand or tenant. The V4 spec exposes three operations on `/api/v4/PackageDimension`: `GET`, `POST`, and `DELETE`.

{% stepper %}
{% step %}

#### Retrieve master dimensions

Retrieve configured master package dimensions using `GET /api/v4/PackageDimension`. The endpoint supports the query parameters `BrandCode` and `TenantCode`. In the spec, `BrandCode` is described as ESW’s unique three-letter identifier for the retailer’s brand, and `TenantCode` is described as ESW’s unique six-letter identifier for the retailer’s brand. A successful response returns `MasterPackageDimensionDto`.

```http
GET /api/v4/PackageDimension?BrandCode=ESW&TenantCode=ESWGB1
```

Example response:

```json
{
  "masterPackageDimensions": [
    {
      "id": "9d675783-2a9e-40f6-bc9d-06cd9b7f459f",
      "brandCode": "ESW",
      "tenantCode": "ESWGB1",
      "boxCode": "SMALL",
      "width": 10,
      "height": 15,
      "length": 20,
      "measurement": 0
    }
  ]
}
```

The response model is a list of `MasterPackageDimension` records. Each record uses flat fields such as `id`, `brandCode`, `tenantCode`, `boxCode`, `width`, `height`, `length`, and `measurement`. The spec does not model this as a nested `measurement` object and does not include a `weight` field in this schema.&#x20;
{% endstep %}

{% step %}

#### Create or update dimension profiles

Use `POST /api/v4/PackageDimension` to submit an array of `PackageDimensionRequest` objects. The request model supports `masterPackageDimensionId`, `brandCode`, `tenantCode`, `boxCode`, `width`, `height`, `length`, and `measurement`. The operation response is documented as `200 PackageDimension updated`.&#x20;

```http
POST /api/v4/PackageDimension
```

Example payload:

```json
[
  {
    "masterPackageDimensionId": "9d675783-2a9e-40f6-bc9d-06cd9b7f459f",
    "brandCode": "ESW",
    "tenantCode": "ESWGB1",
    "boxCode": "SMALL",
    "width": 20,
    "height": 15,
    "length": 32,
    "measurement": 0
  },
  {
    "masterPackageDimensionId": "11111111-2222-3333-4444-555555555555",
    "brandCode": "ESW",
    "tenantCode": "ESWGB1",
    "boxCode": "LARGE",
    "width": 35,
    "height": 25,
    "length": 50,
    "measurement": 0
  }
]
```

A successful response returns a `PackageDimension` entity. The spec also documents `400 Validation failure`, `401`, and a default error response for this operation.&#x20;
{% endstep %}

{% step %}

#### Delete a dimension profile

Use `DELETE /api/v4/PackageDimension` to delete a master package dimension by `brandCode` and `id`.&#x20;

```http
DELETE /api/v4/PackageDimension?brandCode=ESW&id=9d675783-2a9e-40f6-bc9d-06cd9b7f459f
```

The documented responses are:

* `200` — Package deleted
* `400` — Validation failure
* `404` — Could not find package
* `409` — Package is not in a valid state for deletion
* `401` — The request failed as a bad request
* `403` — The request is forbidden
  {% endstep %}
  {% endstepper %}

***

## 06 - Ship From Anywhere (SFA) Configuration

Use the SfaConfig API to retrieve, create, update, delete, and migrate Ship From Anywhere configuration records. The V4 spec exposes `GET /api/v4/SfaConfig`, `POST /api/v4/SfaConfig`, `PUT /api/v4/SfaConfig`, `DELETE /api/v4/SfaConfig`, and `POST /api/v4/SfaConfig/MigrateCurrentConfiguration`. The main SFA entity is `Package.Data.CosmosDb.Entities.SfaConfig`, and that schema requires `tenantCode`.

{% stepper %}
{% step %}

#### Get SFA configuration

Retrieve the current SFA configuration using `GET /api/v4/SfaConfig` with the `tenantCode` query parameter. The spec documents `200 SfaConfig found`, `400 Validation failure`, `404 SfaConfig not found`, `401`, and a default error response. This endpoint does not document returning `null`; the not-found case is modeled as `404`. packageapi

```http
GET /api/v4/SfaConfig?tenantCode=ESWGB1
```

Example response:

{% code expandable="true" %}

```json
{
  "id": "sfaconf_abc123",
  "tenantCode": "ESWGB1",
  "createBulkPackagesLimitNumber": 100,
  "countryISO": ["GB", "IE", "DE"],
  "shipFromAnywhereFields": [
    {
      "name": "storeCode",
      "display": true,
      "mandatory": true
    },
    {
      "name": "storeName",
      "display": true,
      "mandatory": false
    }
  ],
  "dimensionsInfo": {
    "length": 40,
    "width": 20,
    "height": 30,
    "dimensionUnit": "CM"
  },
  "weightInfo": {
    "weight": 25.0,
    "weightUnit": "KG"
  },
  "ttl": 86400
}
```

{% endcode %}

The `SfaConfig` schema includes `id`, `tenantCode`, `createBulkPackagesLimitNumber`, `countryISO`, `shipFromAnywhereFields`, `dimensionsInfo`, `weightInfo`, and `ttl`. The field objects use `name`, `display`, and `mandatory`; dimensions use `length`, `width`, `height`, and `dimensionUnit`; and weight uses `weight` and `weightUnit`.
{% endstep %}

{% step %}

#### Create SFA configuration

Create a new SFA configuration using `POST /api/v4/SfaConfig`. The request body is the `SfaConfig` entity, and the success response is `200 SfaConfig Created`. The spec also documents `400 Validation failure`, `401`, and a default error response.

```http
POST /api/v4/SfaConfig
```

Example payload:

{% code expandable="true" %}

```json
{
  "tenantCode": "ESWGB1",
  "createBulkPackagesLimitNumber": 50,
  "countryISO": ["GB", "IE", "DE", "FR"],
  "shipFromAnywhereFields": [
    {
      "name": "storeCode",
      "display": true,
      "mandatory": true
    },
    {
      "name": "storeName",
      "display": true,
      "mandatory": false
    }
  ],
  "dimensionsInfo": {
    "length": 40,
    "width": 25,
    "height": 30,
    "dimensionUnit": "CM"
  },
  "weightInfo": {
    "weight": 25.0,
    "weightUnit": "KG"
  },
  "ttl": -1
}
```

{% endcode %}

This example uses the field names defined in the schema. In particular, `dimensionsInfo` uses `dimensionUnit`, and `weightInfo` uses a single `weight` field rather than `minWeight` and `maxWeight`.
{% endstep %}

{% step %}

#### Update SFA configuration

Update an existing SFA configuration using `PUT /api/v4/SfaConfig`. The request body is the same `SfaConfig` entity used by the create endpoint, and the success response is `200 SfaConfig Updated`. The spec also documents `400 Validation failure`, `401`, and a default error response.

```http
PUT /api/v4/SfaConfig
```

Example payload:

{% code expandable="true" %}

```json
{
  "id": "sfaconf_abc123",
  "tenantCode": "ESWGB1",
  "createBulkPackagesLimitNumber": 75,
  "countryISO": ["GB", "IE", "DE", "FR", "NL"],
  "shipFromAnywhereFields": [
    {
      "name": "storeCode",
      "display": true,
      "mandatory": true
    },
    {
      "name": "storeName",
      "display": true,
      "mandatory": false
    }
  ],
  "dimensionsInfo": {
    "length": 40,
    "width": 25,
    "height": 30,
    "dimensionUnit": "CM"
  },
  "weightInfo": {
    "weight": 30.0,
    "weightUnit": "KG"
  },
  "ttl": -1
}
```

{% endcode %}

The schema allows an `id` field, but the only formally required property on `SfaConfig` is `tenantCode`.
{% endstep %}

{% step %}

#### Migrate existing configuration

Use `POST /api/v4/SfaConfig/MigrateCurrentConfiguration` to migrate current front-end JSON configuration into SFA config records. The request body is an array of `SfaConfigBatchDto` objects, and the success response is `200 SfaConfig Migration`. The migration DTO includes `createBulkPackagesLimitNumber`, `brandCountryCombination`, `shipFromAnywhereFields`, `dimensionsInfo`, and `weightInfo`.

```http
POST /api/v4/SfaConfig/MigrateCurrentConfiguration
```

Example payload:

{% code expandable="true" %}

```json
[
  {
    "createBulkPackagesLimitNumber": 50,
    "brandCountryCombination": [
      {
        "tenantCode": "ESWGB1",
        "brandCode": "ESW",
        "countryIso": ["GB", "IE", "DE", "FR"]
      }
    ],
    "shipFromAnywhereFields": [
      {
        "name": "storeCode",
        "display": true,
        "mandatory": true
      },
      {
        "name": "storeName",
        "display": true,
        "mandatory": false
      }
    ],
    "dimensionsInfo": {
      "length": 40,
      "width": 25,
      "height": 30,
      "dimensionUnit": "CM"
    },
    "weightInfo": {
      "weight": 25.0,
      "weightUnit": "KG"
    }
  }
]
```

{% endcode %}

In the migration model, tenant and country data are nested under `brandCountryCombination`; they are not top-level properties on `SfaConfigBatchDto`.
{% endstep %}

{% step %}

#### Delete SFA configuration

Delete an SFA configuration using `DELETE /api/v4/SfaConfig` with query parameters `id` and `tenantCode`. The documented responses are `200 Package deleted`, `400 Validation failure`, `404 Could not find SfaConfig`, `409 SfaConfig is not in a valid state for deletion`, `401`, and a default error response.

```http
DELETE /api/v4/SfaConfig?id=sfaconf_abc123&tenantCode=ESWGB1
```

{% endstep %}
{% endstepper %}

***


---

# 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/package-api/resources/workflows.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.
