> 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/workflow.md).

# Workflow

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

Create a package from order information, retrieve it for status checking, and delete it if it needs to be cancelled. Packages can only be deleted while their shipping status is `Pending`.

#### Step 1 — Create a Package

`POST /api/v4/Package`

Minimum viable payload — checkout order

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

```json
{
  "brandCode": "ESW",
  "orderReference": "ORD-20240315-001",
  "packageReference": "PKG-20240315-001",
  "orderType": "CHECKOUT",
  "shippingDocumentationRequested": true,
  "distributionCentre": "IEDUB",
  "weight": { "weight": 1.5, "weightUnit": "KG" },
  "consignee": {
    "firstName": "Jane",
    "lastName": "Smith",
    "address1": "42 Shipping Lane",
    "city": "London",
    "postalCode": "EC1A 1BB",
    "country": "GB",
    "email": "jane@example.com",
    "telephone": "+441234567890"
  },
  "dimensions": {
    "dimHeight": "20",
    "dimLength": "30",
    "dimWidth": "15",
    "dimMeasurementUnit": "CM"
  },
  "packageItems": [
    {
      "productCode": "SKU-SHOES-42-BLK",
      "quantity": 1,
      "productDescription": "Black leather shoes, size 42",
      "countryOfOrigin": "IT",
      "unitPrice": { "amount": 149.99, "currency": "GBP" },
      "hsCode": "6403.99.98",
      "weight": { "weight": 0.8, "weightUnit": "KG" }
    }
  ]
}
```

{% endcode %}

**Order Types**: `CHECKOUT` · `NONCHECKOUT` · `RETURN` · `OFFLINE` · `NONCHECKOUTECOMMERCE`. Non-checkout types require `hsCode` and `productDescription` on every package item.

Response includes a `PackageCreateResponse` with `outcome` status, `statusMessage`, and the full `Package` object containing generated tracking references and any documentation (labels in base64 format).

#### Step 1b — Non-Checkout / Cross-Border Package

`POST /api/v4/Package`

For non-checkout orders, additional customs fields become mandatory. Include `hsCode`, `countryOfOrigin`, `productCustomsDescription`, and dangerous goods flags where applicable.

{% code expandable="true" %}

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

{% endcode %}

#### Step 2 — Retrieve Package

Fetch the current state of a package using `BrandCode` and `PackageReference`. Use this to check shipping status, retrieve carrier tracking references, and access generated documentation links.

`GET/api/v4/Package`

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

```json
// Query parameters
BrandCode=ESW                                   // Required
PackageReference=PKG-20240315-001                // Required
OrderReference=ORD-20240315-001                  // Optional — additional filter
```

| Parameter          | Type   | Notes                                |
| ------------------ | ------ | ------------------------------------ |
| `BrandCode`        | string | ESW 3-letter brand identifier        |
| `PackageReference` | string | Retailer's unique package identifier |
| `OrderReference`   | string | Narrows search to a specific order   |

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

#### Step 3 — Delete a Package (Cancellation)

Cancel a package by deleting it. This is only possible while the package's `shippingStatus` is `Pending`. Attempting to delete a `Complete` package will return a `409 Conflict`.

`DELETE/api/v4/Package`

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

```json
// All three query parameters required
BrandCode=ESW
OrderReference=ORD-20240315-001
PackageReference=PKG-20240315-001
```

{% hint style="info" icon="square-xmark" %}

#### **Status constraint**

Packages with `shippingStatus:"Complete"` cannot be deleted. Always verify status via GET before attempting deletion. A `409 Conflict` is returned if the package has already been shipped.
{% endhint %}

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

***

## 02 - Package Update

Modify an existing package's carrier assignment, weight, dimensions, delivery address, or shipping status. Updates are only permitted while the package's status is `Pending`.

#### Step 1 — Verify Package is in Pending Status

Before updating, retrieve the package and confirm its `shippingStatus` is `Pending`. If the status is `Complete`, the update will be rejected.

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

```json
// Check response: package.shippingStatus must be "Pending"
// ShippingStatus enum: "Pending" | "Complete"
```

<kbd>`Pending`</kbd> <kbd>`Complete`</kbd>

#### Step 2 — Update Package

Submit the updated package data. You can change carrier assignment, weight, dimensions, consignee address, service level, and pallet ID. All three identifiers (`brandCode`, `orderReference`, `packageReference`) must match the existing package.

`PUT/api/v4/Package`

{% code expandable="true" %}

```json
// PackageUpdate payload
{
  "brandCode": "ESW",
  "orderReference": "ORD-20240315-001",
  "packageReference": "PKG-20240315-001",

  // Update carrier assignment
  "carrierId": 42,
  "carrierReference": "DHL-TRK-9900123",
  "carrierServiceDescription": "DHL Express Worldwide",

  // Update weight if reweighed
  "weight": { "weight": 1.8, "weightUnit": "KG" },

  // Update dimensions
  "dimensions": {
    "dimHeight": "22",
    "dimLength": "32",
    "dimWidth": "16",
    "dimMeasurementUnit": "CM"
  },

  // Update delivery address if required
  "consignee": {
    "address1": "15 New Address Road",
    "city": "Manchester",
    "postalCode": "M1 1AA",
    "country": "GB"
  },

  "distributionCentre": "IEDUB",
  "palletId": "PLT-2024-007"
}
```

{% endcode %}

{% hint style="info" icon="left-long-to-line" %}

#### **Pending only**

The PUT endpoint rejects updates on packages with `shippingStatus:"Complete"`. A `409` is returned in this case. Always `GET` first to verify current status.
{% endhint %}

#### Step 3 — Transition to Complete Status

`PUT /api/v4/Package`

When the package is physically dispatched, update its `shippingStatus` to `Complete`. After this point, no further updates or deletions are permitted.

```json
{
  "brandCode": "ESW",
  "orderReference": "ORD-20240315-001",
  "packageReference": "PKG-20240315-001",
  "shippingStatus": "Complete"
}
```

## 03 - Label Configuration

Upload carrier label configuration files (Excel) per brand tenant, and review version history. Label configs determine how shipping labels are formatted and which carrier-specific data fields are included.

#### Step 1 — Download Current Label Config

Retrieve the current label configuration Excel file for a tenant. Use this as a template before uploading a modified version.

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

```json
// Path parameter
tenantCode: "ESWGB1"   // 6-letter tenant identifier

// Returns: binary Excel file (.xlsx)
// Save this file, modify, then re-upload with POST
```

`200 OK` — Excel file binary

#### Step 2 — Upload Updated Label Config

Upload a new label configuration Excel file for the tenant. Each upload creates a new version entry in the history log. The new config becomes active immediately.

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

```json
// Path parameter
tenantCode: "ESWGB1"

// Body: multipart/form-data
Content-Type: "multipart/form-data"
file: <binary .xlsx file>

// On success, the new config is applied immediately
// Previous config is preserved in history
```

`200 OK` — Config uploaded and active

#### Step 3 — Review Config Version History

List all historical label config versions for a tenant, with timestamps and record IDs. Download any historical version to compare or rollback.

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

```json
// Returns: LabelConfigHistoryListResponse
// Array of LabelConfigHistory objects, each with:
{
  "id": "hist_abc123",
  "tenantCode": "ESWGB1",
  "uploadedAt": "2024-03-15T09:30:00Z",
  "uploadedBy": "user@esw.com"
}
```

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

```json
// Download a specific historical Excel file by record ID
id: "hist_abc123"   // from history list above

// Returns: binary .xlsx — that version's label config
```

`200 OK`

{% hint style="info" icon="rotate-left" %}

#### **Rollback**

To roll back to a previous config, download the historical version using its ID, then re-upload it via POST. This creates a new history entry with the old config's data.
{% endhint %}

## 04 - Manifest Management

Submit manifest information for air freight shipments. A manifest groups packages into pallets assigned to a specific flight with origin and destination airports. Used by ground handling agents and carriers for airside operations.

**Prerequisite**: Packages Created <br>

#### Step 1 — Submit Manifest

Post the manifest to update flight and pallet assignment for a batch of packages. The manifest ties together a flight number, origin/destination airports, the carrier, and the pallets containing packages.

`POST/api/v4/Manifest`

{% code expandable="true" %}

```json
// ManifestRequest body
{
  "manifestNumber": "MAN-20240315-LHR-001",
  "originAirportCode": "DUB",          // Dublin
  "destinationAirportCode": "LHR",     // Heathrow
  "carrierId": 42,
  "groundHandlingAgent": "Swissport",
  "flight": {
    "flightNumber": "EI105",
    "departureDateTime": "2024-03-15T14:30:00Z",
    "arrivalDateTime": "2024-03-15T15:50:00Z"
  },
  "pallets": [
    {
      "palletId": "PLT-2024-007",
      "weight": 250.5,
      "weightUnit": "KG",
      "packageReferences": [
        "PKG-20240315-001",
        "PKG-20240315-002",
        "PKG-20240315-003"
      ]
    },
    {
      "palletId": "PLT-2024-008",
      "weight": 180.0,
      "weightUnit": "KG",
      "packageReferences": ["PKG-20240315-004"]
    }
  ]
}All packageReferences in the manifest must correspond to packages that have already been created in the system. The palletId on each pallet should match the palletId set on the individual packages via PUT.Package Dimension Management
```

{% endcode %}

{% hint style="info" icon="box-isometric" %}
All `packageReferences` in the manifest must correspond to packages that have already been created in the system. The `palletId` on each pallet should match the `palletId` set on the individual packages via `PUT`.
{% endhint %}

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

## 05 - Package Dimension Management

Define and manage master package dimension templates for a brand. These predefined size profiles can be referenced at package creation time, ensuring consistent dimensional data and enabling accurate shipping cost calculation.

#### Step 1 — Retrieve Master Dimensions

Fetch all master package dimension profiles configured for a brand. Use `BrandCode` or `TenantCode` to filter results.

`GET/api/v4/PackageDimension`

{% code expandable="true" %}

```json
// Query parameters (at least one required)
BrandCode=ESW          // 3-letter brand code
TenantCode=ESWGB1      // 6-letter tenant code

// Returns: MasterPackageDimensionDto
{
  "masterPackageDimensions": [
    {
      "id": "dim_small_box",
      "name": "Small Box",
      "measurement": {
        "height": "15", "length": "20", "width": "10",
        "unit": "CM", "weight": "0.3"
      }
    }
  ]
}
```

{% endcode %}

<mark style="color:$success;">`200`</mark>` ``OK` — Dimension list<br>

#### Step 2 — Create Dimension Profiles

Create one or more master dimension profiles. Pass an array of dimension objects, each specifying the box name, height, length, width, and weight.

`POST/api/v4/PackageDimension`

{% code expandable="true" %}

```json
// Array of PackageDimensionRequest objects
[
  {
    "brandCode": "ESW",
    "name": "Small Shoe Box",
    "measurement": {
      "height": "15",
      "length": "32",
      "width": "20",
      "unit": "CM",
      "weight": "0.5"
    }
  },
  {
    "brandCode": "ESW",
    "name": "Large Apparel Box",
    "measurement": {
      "height": "25",
      "length": "50",
      "width": "35",
      "unit": "CM",
      "weight": "0.8"
    }
  }
]
```

{% endcode %}

`200 OK — Created`

#### Step 3 — Delete a Dimension Profile

Remove a master dimension profile by brand code and profile ID. Verify the profile is not actively referenced by in-flight packages before deletion.

`DELETE/api/v4/PackageDimension`

```shellscript
DELETE /api/v4/PackageDimension?brandCode=ESW&id=dim_small_box
```

`200 OK — Deleted`

## 06 - Ship From Anywhere (SFA) Configuration

Configure Ship From Anywhere (SFA) settings per brand. SFA enables packages to be shipped from retail stores, warehouses, or any distribution point — not just a fixed fulfilment centre. Define bulk package limits, default dimensions, weight ranges, and which countries are eligible.

#### Step 1 — Get SFA Configuration

Retrieve the current Ship From Anywhere configuration for a brand tenant. Returns null if no config exists yet — proceed to POST to create one.

`GET/api/v4/SfaConfig`

{% code expandable="true" %}

```json
// Query parameter
tenantCode=ESWGB1

// Returns: SfaConfig entity
{
  "id": "sfaconf_abc123",
  "tenantCode": "ESWGB1",
  "createBulkPackagesLimitNumber": 100,
  "countryISO": ["GB", "IE", "DE"],
  "dimensionsInfo": { "height": "30", "width": "20", "length": "40" },
  "weightInfo": { "minWeight": 0.1, "maxWeight": 30, "weightUnit": "KG" },
  "ttl": 86400
}
```

{% endcode %}

`200 OK — Config object`

#### Step 2 — Create SFA Configuration

Create a new SFA configuration for a brand. Define which countries are eligible for ship-from-anywhere, default dimensions and weight constraints, bulk limit, and TTL for temporary records.

`POST/api/v4/SfaConfig`

{% code expandable="true" %}

```json
// SfaConfig entity — create new
{
  "tenantCode": "ESWGB1",
  "createBulkPackagesLimitNumber": 50,          // max packages per bulk call
  "countryISO": ["GB", "IE", "DE", "FR"],        // eligible origin countries
  "shipFromAnywhereFields": [
    { "fieldName": "storeCode", "isRequired": true },
    { "fieldName": "storeName", "isRequired": false }
  ],
  "dimensionsInfo": {
    "height": "30",
    "width": "25",
    "length": "40",
    "measurementUnit": "CM"
  },
  "weightInfo": {
    "minWeight": 0.1,
    "maxWeight": 25.0,
    "weightUnit": "KG"
  },
  "ttl": -1   // -1 = no expiry; positive int = seconds to live
}
```

{% endcode %}

`200 OK — Config created`

#### Step 3 — Update SFA Configuration

Modify an existing SFA configuration. Include the record `id` alongside the updated fields to target the correct config document.

`PUT/api/v4/SfaConfig`

```json
{
  "id": "sfaconf_abc123",                            // required for updates
  "tenantCode": "ESWGB1",
  "createBulkPackagesLimitNumber": 75,               // increased limit
  "countryISO": ["GB", "IE", "DE", "FR", "NL"],     // added Netherlands
  "weightInfo": {
    "minWeight": 0.1,
    "maxWeight": 30.0,                                // updated max
    "weightUnit": "KG"
  },
  "ttl": -1
}
```

`200 OK — Updated`

#### Step 4 — Migrate Existing Configuration

If a legacy front-end JSON configuration exists, migrate it to the new SFA Config format in a single batch operation. Pass an array of SFA config batch DTOs.

`POST/api/v4/SfaConfig/MigrateCurrentConfiguration`

```json
// Array of SfaConfigBatchDto objects — batch migration
[
  {
    "tenantCode": "ESWGB1",
    // include legacy JSON config fields to migrate
  }
]

// Use when transitioning from older SFA config format
// Creates records for each tenant in the array
```

`200 OK — Migration complete`

#### Step 5 — Delete SFA Configuration

Remove an SFA configuration by record ID and tenant code. Deleting the config will disable Ship From Anywhere functionality for that tenant until a new config is created.

{% code expandable="true" %}

```
DELETE/api/v4/SfaConfig
```

{% endcode %}

```json
// Query parameters
id=sfaconf_abc123
tenantCode=ESWGB1
```

`200 OK — Deleted`

{% hint style="info" icon="light-emergency-on" %}
Deleting SFA Config disables Ship From Anywhere for the tenant immediately. Ensure no active SFA shipments are in-progress before deletion.
{% endhint %}

***


---

# 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/workflow.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.
