> 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/customs-catalog-api/fulfillment-api/fulfilment-api-usecases.md).

# fulfilment api usecases

Fulfillment API — Use Case Walkthroughs

eShopWorld

## Fulfillment API

v1 · Use Case Walkthroughs

Overview

Use Cases

1 · New Season Stock Onboarding | 2 · Standard Full-Order Fulfillment | 3 · Partial Fulfillment | 4 · Damaged Goods & Quarantine | 5 · End-of-Day Cutoff & Retry | 6 · Fulfillment Failure Scenarios | 7 · Inventory Reconciliation

Reference

Enums & Status Values | Schema Quick Reference

[↗ Package API Guide](broken://pages/4b0d9537a9d834b3e8ce27da00d0a65a2984b826) [↗ Package API Use Cases](broken://pages/aebf07728b5b32b11d2963fb93d15ecd77bb4f8f) [↗ Error Handling Guide](broken://pages/55fa56be02972ba47885ff9f978684f9f352897f)

eShopWorld / Fulfillment API / Use Case Walkthroughs

Use Case Walkthroughs · Fulfillment API v1

## Pick. Pack. Ship. Sync.

Seven end-to-end walkthroughs covering every real-world scenario for the Fulfillment API — from initial stock seeding and standard order dispatch through partial fulfillment, quarantine handling, end-of-day cutoffs, and full inventory reconciliation.

Inventory Sync · Pick & Pack Confirm · Advanced Shipping Notice · Partial & Failed Orders · Quarantine & Errors

Endpoints: 3\
Use Cases: 7\
API Version: v1\
Response: 202 Async

Overview

### API Overview

The Fulfillment API connects retailers, 3PL (third-party logistics) providers, and fulfillment centers to the eShopWorld cross-border platform. It handles three distinct operations that together cover the full physical fulfillment lifecycle.

* Inventory Sync — Synchronise SKU quantities and article statuses at a specific fulfillment center. Called on initial stock seeding, replenishment, and cycle count reconciliation.
* Pick & Pack Confirm — 3PL confirms that an order has been picked, packed, and is ready for carrier collection. Returns item-level outcomes including partial results and failure reasons.
* Advanced Shipping Notice — Notify eShopWorld when a parcel physically leaves the fulfillment center. Includes carrier, tracking reference, weight, dimensions, and per-item quantities shipped.

Async by design: All three endpoints return `202 Accepted`. No response body on success — the platform processes the payload asynchronously. Use webhooks or the Order API to track downstream state.

Multi-tenant: Every request is scoped by `tenantCode` and `fulfillmentCentreId`. A single 3PL can operate multiple brands from the same integration by varying these values.

Item-level status: Pick & Pack Confirm supports item-level outcomes — individual SKUs within the same order can have different statuses (Confirmed, Failed, PartialResult) in a single call.

#### The three endpoints

| Method | Path                                  | Actor           | When called                                                            |
| ------ | ------------------------------------- | --------------- | ---------------------------------------------------------------------- |
| POST   | `/v1/Inventory/Sync`                  | Retailer or 3PL | New stock arrives at FC; cycle count; article status change            |
| POST   | `/v1/PickPack/Confirm`                | 3PL WMS         | Order has been physically picked and packed; before carrier collection |
| POST   | `/v1/PickPack/AdvancedShippingNotice` | 3PL or Retailer | Parcel has left the FC; carrier has collected or scan confirmed        |

System Design

### System Architecture

Understanding how each actor connects to the Fulfillment API helps you place the right calls at the right moment in your fulfillment workflow.

Retailer OMS — order source → eShopWorld Fulfillment API → 3PL / FC WMS (pick & pack)

Typical call order within a fulfillment event

{% stepper %}
{% step %}

### Stock provisioning (one-time or recurring)

`POST /v1/Inventory/Sync` — When goods arrive at the FC, the 3PL updates eShopWorld with available quantities and article statuses. This is not per-order; it's per-FC stock event. Statuses progress: `Expected → Active`, with `Quarantine` or `Suspended` as exception states.
{% endstep %}

{% step %}

### Pick & Pack confirmation

`POST /v1/PickPack/Confirm` — After eShopWorld sends a fulfillment request to the 3PL WMS (via webhook or polling), the 3PL calls this endpoint to confirm picking and packing is complete. The response payload describes what was confirmed, what failed, and why — at item level.
{% endstep %}

{% step %}

### Advanced Shipping Notice

`POST /v1/PickPack/AdvancedShippingNotice` — Once the carrier collects the parcel (or the 3PL hands it off), the ASN is submitted with carrier reference, tracking, weight, dimensions, and per-item shipment quantities. This closes the fulfillment loop.
{% endstep %}
{% endstepper %}

Security

### Authentication

The Fulfillment API uses Bearer JWT authentication — the same OAuth 2.0 Client Credentials flow as all other eShopWorld APIs. All three endpoints require a valid token.

Request — All Fulfillment API requests — required headers

POST /v1/PickPack/Confirm\
Authorization: Bearer {access\_token}\
Content-Type: application/json\
Accept: application/json

// Obtain token via client\_credentials grant:\
POST <https://identity.eshopworld.com/connect/token\\>
Content-Type: application/x-www-form-urlencoded

grant\_type=client\_credentials \&client\_id={your\_client\_id} \&client\_secret={your\_client\_secret} \&scope=fulfillment.api

⚠ **202 does not mean processed** — All three endpoints return `202 Accepted` with no response body on success. The platform processes the payload asynchronously. A 202 confirms the request was received and queued — not that stock was updated or the order was confirmed. Implement webhook listeners or poll the Order API to verify downstream state.

Reference

### Call Sequence Summary

Every use case mapped to its API call sequence at a glance.

| Use Case                       | Call Sequence                                                                                 | Key outcome                                            |
| ------------------------------ | --------------------------------------------------------------------------------------------- | ------------------------------------------------------ |
| 1 · New Season Onboarding      | Inventory/Sync (Expected) → Inventory/Sync (Active)                                           | Stock available to fulfil orders                       |
| 2 · Full Fulfillment           | PickPack/Confirm (Confirmed) → PickPack/ASN (Shipped)                                         | All items confirmed and shipped                        |
| 3 · Partial Fulfillment        | PickPack/Confirm (PartialResult) → PickPack/ASN (PartiallyShipped)                            | Partial items shipped; remainder handled separately    |
| 4 · Damaged Goods & Quarantine | Inventory/Sync (Quarantine) → Inventory/Sync (Suspended or Active)                            | Damaged stock isolated; resolution recorded            |
| 5 · End-of-Day Cutoff          | PickPack/Confirm (Failed/EndOfDay) → \[next day] PickPack/Confirm (Confirmed) → ASN (Shipped) | Late order held overnight; fulfilled next business day |
| 6 · Failure Scenarios          | PickPack/Confirm (Failed/BadAddress or TransientError) → escalation or retry                  | Non-shippable order routed for resolution              |
| 7 · Inventory Reconciliation   | Inventory/Sync (full SKU list, current quantities)                                            | Platform inventory matches physical FC count           |

***

01

#### New Season Stock Onboarding

A retailer's buying team confirms a new season collection arriving at the Dublin fulfillment centre. The 3PL WMS must register expected stock, then confirm receipt and activate each SKU once goods are put away.

Inventory/Sync — 3PL Integration

Actor: Retailer WMS / 3PL Receiving\
Trigger: Inbound delivery confirmed at FC\
APIs: POST /v1/Inventory/Sync\
Outcome: Stock available to fulfil orders

Call sequence (high level)

Inventory/Sync — articleStatus: Expected → Goods received (physical putaway) → Inventory/Sync — articleStatus: Active

{% stepper %}
{% step %}

### Pre-announce arriving stock with Expected status

When the retailer's buying system confirms an inbound delivery, the 3PL WMS calls Inventory/Sync with `articleStatus: Expected` and the anticipated quantities. This lets eShopWorld's order routing know stock is inbound and earmarks it for pending orders before physical arrival.

Request — POST /v1/Inventory/Sync — pre-announce Expected stock

POST /v1/Inventory/Sync\
Authorization: Bearer {token}\
Content-Type: application/json

{ "tenantCode": "ACMTEN", "fulfillmentCentreId": "FC-DUB-01", "provider": "XPO-LOGISTICS", "items": \[ { "sku": "ACM-SS25-DRESS-BLK-S", "variantProductCode": "DRESS-BLK-S", "ean": "5901234123457", "size": "S", "color": "BLACK", "articleStatus": "Expected", "quantity": 200 }, { "sku": "ACM-SS25-DRESS-BLK-M", "variantProductCode": "DRESS-BLK-M", "ean": "5901234123464", "size": "M", "color": "BLACK", "articleStatus": "Expected", "quantity": 350 }, { "sku": "ACM-SS25-DRESS-BLK-L", "variantProductCode": "DRESS-BLK-L", "ean": "5901234123471", "size": "L", "color": "BLACK", "articleStatus": "Expected", "quantity": 275 } ] }

Response: 202 Accepted — no body

HTTP/1.1 202 Accepted // No response body. The platform has queued the sync for processing. // Do not call again immediately — allow 30–60 seconds for async processing.
{% endstep %}

{% step %}

### Physical goods arrive — receiving and putaway

The inbound delivery arrives at the dock. The 3PL team scans every carton against the purchase order, verifies quantities and condition, and puts stock away into pick locations. This is a physical warehouse operation — no API call is made at this moment.
{% endstep %}

{% step %}

### Activate received SKUs

Once putaway is complete, the 3PL WMS calls Inventory/Sync again with `articleStatus: Active` and the actual verified quantities. This unlocks the stock for order fulfillment. Note that actual received quantities may differ from Expected — always use verified counts.

Request — POST /v1/Inventory/Sync — activate received stock

{ "tenantCode": "ACMTEN", "fulfillmentCentreId": "FC-DUB-01", "provider": "XPO-LOGISTICS", "items": \[ { "sku": "ACM-SS25-DRESS-BLK-S", "ean": "5901234123457", "articleStatus": "Active", "quantity": 198 // 2 units short-delivered vs Expected 200 }, { "sku": "ACM-SS25-DRESS-BLK-M", "ean": "5901234123464", "articleStatus": "Active", "quantity": 350 }, { "sku": "ACM-SS25-DRESS-BLK-L", "ean": "5901234123471", "articleStatus": "Active", "quantity": 275 } ] }

ℹ **Sync is a full snapshot, not a delta** — Each call to `POST /v1/Inventory/Sync` replaces the platform's known quantity for those SKUs at that FC. It is not additive. If you send `quantity: 100` for a SKU that had `quantity: 200`, the result is 100, not 300. Always send the current on-hand quantity.
{% endstep %}
{% endstepper %}

02

#### Standard Full-Order Fulfillment

An order for two items is sent to the 3PL WMS. All items are in stock and picked successfully. The 3PL confirms pick & pack, then submits an ASN when the carrier collects.

PickPack/Confirm · PickPack/ASN

Actor: 3PL WMS system\
Trigger: Fulfillment request from eShopWorld\
APIs: PickPack/Confirm · PickPack/ASN\
Outcome: Order fully picked, packed, and shipped

Call sequence

ESW dispatch (webhook to WMS) → WMS picks (physical) → PickPack/Confirm (status: Confirmed) → Carrier collects → PickPack/ASN (status: Shipped)

{% stepper %}
{% step %}

### 3PL receives fulfillment request from eShopWorld

eShopWorld pushes a fulfillment order to the 3PL WMS (via webhook or polling the Orders API) containing the `eswOrderReference`, delivery address, and line items. The WMS creates an internal pick task and assigns it to a picker.
{% endstep %}

{% step %}

### Confirm pick & pack complete

After the picker scans all items into a box and the pack station seals and weighs the parcel, the WMS calls Confirm. The `confirmationId` is the WMS's own internal job ID. The `confirmationDateTime` should be the actual time packing completed — not when the API call is made.

Request — POST /v1/PickPack/Confirm — all items confirmed

POST /v1/PickPack/Confirm\
Authorization: Bearer {token}\
Content-Type: application/json

{ "confirmationId": "WMS-CONF-20241106-008741", "confirmationDateTime": "2024-11-06T10:22:00Z", "eswOrderReference": "ESW-ORD-7204519", "tenantCode": "ACMTEN", "pickPackResponse": { "status": "Confirmed", // ← All items successfully picked & packed "itemsResult": \[ { "productCode": "ACM-SS25-DRESS-BLK-M", "quantityOrdered": 1, "quantityConfirmed": 1, "quantityFailed": 0, "status": "Success" }, { "productCode": "ACM-SS25-SCARF-RED", "quantityOrdered": 2, "quantityConfirmed": 2, "quantityFailed": 0, "status": "Success" } ] } }

Response: 202 Accepted

HTTP/1.1 202 Accepted // eShopWorld has queued the confirmation. The order status will update // to "Packed" or equivalent asynchronously within 30–60 seconds.
{% endstep %}

{% step %}

### Submit ASN after carrier collection

When the carrier's driver scans the parcel at collection (or the 3PL hands it off at the dock), the WMS submits an ASN. Include the carrier's tracking reference, actual weight from the dock scale, and per-item shipment details.

Request — POST /v1/PickPack/AdvancedShippingNotice — fully shipped

POST /v1/PickPack/AdvancedShippingNotice\
Authorization: Bearer {token}\
Content-Type: application/json

{ "shipmentId": "WMS-SHP-20241106-008741", "eswOrderReference": "ESW-ORD-7204519", "shipmentDateTime": "2024-11-06T13:45:00Z", // carrier collection time "shipmentStatus": "Shipped", "shipFrom": { "name": "XPO Dublin Fulfillment Centre", "locationCode": "FC-DUB-01" }, "carrierId": "DHL", "packageReference": "PKG-00841-001", "carrierReference": "1Z999AA10123456784", // carrier tracking number "packageWeight": { "weight": 1.42, "weightUnit": "KG" }, "packageDimensions": { "length": 33, "width": 22, "height": 12, "dimensionUnit": "CM" }, "items": \[ { "sku": "ACM-SS25-DRESS-BLK-M", "quantityOrdered": 1, "quantityShipped": 1, "unitOfMeasure": "EA", "itemStatus": "Shipped" }, { "sku": "ACM-SS25-SCARF-RED", "quantityOrdered": 2, "quantityShipped": 2, "unitOfMeasure": "EA", "itemStatus": "Shipped" } ] }

✅ Outcome: eShopWorld marks the order as shipped, transmits tracking to the customer, and updates the carrier pre-clearance records. The fulfillment loop for this order is closed.
{% endstep %}
{% endstepper %}

03

#### Partial Fulfillment

An order contains three line items, but one SKU cannot be found during picking (system shows stock, but physical location is empty — a phantom stock situation). The 3PL ships what it can and reports the shortfall.

PickPack/Confirm · PickPack/ASN · PartialResult

Actor: 3PL WMS\
Trigger: Picker cannot locate one SKU at pick location\
APIs: PickPack/Confirm · PickPack/ASN\
Outcome: Partial shipment; remainder handled by eShopWorld

Call sequence: PickPack/Confirm (status: PartialResult) → eShopWorld routes shortfall decision → PickPack/ASN (status: PartiallyShipped)

{% stepper %}
{% step %}

### Report partial result — item not found at pick location

The picker scans two items successfully but cannot locate `ACM-SS25-BELT-BRN-M`. After a secondary location check fails, the supervisor marks this line as `NotFound`. The WMS calls Confirm with `status: PartialResult` and provides item-level outcomes.

Request — POST /v1/PickPack/Confirm — partial result with NotFound item

{ "confirmationId": "WMS-CONF-20241106-009102", "confirmationDateTime": "2024-11-06T11:05:00Z", "eswOrderReference": "ESW-ORD-7204560", "tenantCode": "ACMTEN", "pickPackResponse": { "status": "PartialResult", "problemMessage": "1 of 3 line items could not be located at pick position A-12-04", "itemsResult": \[ { "productCode": "ACM-SS25-DRESS-BLK-M", "quantityConfirmed": 1, "quantityFailed": 0, "status": "Success" }, { "productCode": "ACM-SS25-SCARF-RED", "quantityConfirmed": 1, "quantityFailed": 0, "status": "Success" }, { "productCode": "ACM-SS25-BELT-BRN-M", "quantityConfirmed": 0, "quantityFailed": 1, "status": "Failed", "failureReason": "NotFound", // physical stock absent at pick location "problemMessage": "Location A-12-04 empty; secondary check B-03-07 also empty" } ] } }
{% endstep %}

{% step %}

### eShopWorld handles the shortfall

On receiving a `PartialResult`, eShopWorld automatically triggers one of several downstream actions: ship-from-alternative-FC, backorder the missing item, or notify the retailer for customer communication. The 3PL does not need to act further on the missing line — only on the items it is shipping.
{% endstep %}

{% step %}

### Submit ASN for the shipped items only

The ASN only contains the items that were physically shipped. Set `shipmentStatus: PartiallyShipped` and include only the confirmed items in the `items` array. Do not include the failed belt line.

Request — POST /v1/PickPack/AdvancedShippingNotice — PartiallyShipped

{ "shipmentId": "WMS-SHP-20241106-009102", "eswOrderReference": "ESW-ORD-7204560", "shipmentDateTime": "2024-11-06T14:12:00Z", "shipmentStatus": "PartiallyShipped", // ← key field "shipFrom": { "name": "XPO Dublin FC", "locationCode": "FC-DUB-01" }, "carrierId": "DHL", "packageReference": "PKG-09102-001", "carrierReference": "1Z999AA10123499001", "packageWeight": { "weight": 0.95, "weightUnit": "KG" }, "packageDimensions": { "length": 30, "width": 22, "height": 10, "dimensionUnit": "CM" }, "items": \[ { "sku": "ACM-SS25-DRESS-BLK-M", "quantityOrdered": 1, "quantityShipped": 1, "unitOfMeasure": "EA", "itemStatus": "Shipped" }, { "sku": "ACM-SS25-SCARF-RED", "quantityOrdered": 1, "quantityShipped": 1, "unitOfMeasure": "EA", "itemStatus": "Shipped" } // Belt NOT included — was not shipped ] }

⚠ **Sync inventory immediately after a NotFound event** — If the system shows stock but the picker cannot find it, this is a phantom stock condition. After the fulfillment event, call `POST /v1/Inventory/Sync` with the corrected quantity (0 or actual count) for the affected SKU to prevent further phantom fulfillment attempts on this item.
{% endstep %}
{% endstepper %}

04

#### Damaged Goods & Quarantine Lifecycle

During inbound receiving, the 3PL team discovers a carton of goods with water damage. Affected units must be quarantined immediately to prevent them being allocated to orders. Once assessed, units are either written off (Suspended) or cleared and re-activated (Active).

Inventory/Sync · Quarantine

Actor: 3PL Receiving / Quality Team\
Trigger: Damage found during inbound or stock check\
APIs: POST /v1/Inventory/Sync (×3)\
Outcome: Damaged stock isolated; resolution recorded

Call sequence (high level)

Inventory/Sync Active: 350 (full stock) → Damage found (18 units affected) → Inventory/Sync Active: 332 + Quarantine: 18 → QC assessment → Inventory/Sync Suspended: 18 (write-off)

{% stepper %}
{% step %}

### Immediate quarantine on damage discovery

Upon finding the damaged carton, the 3PL quality team segregates the affected units and records them in the WMS. The WMS immediately calls Inventory/Sync to update both the Active quantity (reduced by the damaged count) and add a separate Quarantine record for the affected units. These must be sent in the same request to avoid any window where phantom Active stock exists.

Request — POST /v1/Inventory/Sync — quarantine damaged units immediately

{ "tenantCode": "ACMTEN", "fulfillmentCentreId": "FC-DUB-01", "provider": "XPO-LOGISTICS", "items": \[ { // Active quantity reduced from 350 to 332 "sku": "ACM-SS25-DRESS-BLK-M", "ean": "5901234123464", "articleStatus": "Active", "quantity": 332 }, { // Damaged units separately registered under Quarantine "sku": "ACM-SS25-DRESS-BLK-M", "ean": "5901234123464", "articleStatus": "Quarantine", "quantity": 18 } ] }
{% endstep %}

{% step %}

### QC team assesses the quarantined units

The quality control team inspects the 18 damaged units. They determine 5 units have only surface packaging damage and can be re-packed and sold. The remaining 13 have moisture damage to the product itself and must be written off.
{% endstep %}

{% step %}

### Write off irreparable units — Suspended status

Units that cannot be sold are moved to `Suspended` status, which prevents them from ever being allocated to orders. This is the terminal state for written-off inventory.

Request — POST /v1/Inventory/Sync — write off damaged units + restore repacked

{ "tenantCode": "ACMTEN", "fulfillmentCentreId": "FC-DUB-01", "provider": "XPO-LOGISTICS", "items": \[ { // Active restored: 332 original + 5 repacked "sku": "ACM-SS25-DRESS-BLK-M", "articleStatus": "Active", "quantity": 337 }, { // Quarantine cleared to zero "sku": "ACM-SS25-DRESS-BLK-M", "articleStatus": "Quarantine", "quantity": 0 }, { // Written-off units now Suspended (terminal state) "sku": "ACM-SS25-DRESS-BLK-M", "articleStatus": "Suspended", "quantity": 13 } ] }
{% endstep %}
{% endstepper %}

#### Article Status state machine

| Status     | Meaning                                                                   | Can be allocated?   | Typical transition                                      |
| ---------- | ------------------------------------------------------------------------- | ------------------- | ------------------------------------------------------- |
| Expected   | Stock confirmed on inbound but not yet physically received or put away    | No (earmarked only) | → Active on put-away confirmation                       |
| Active     | Stock available for order fulfillment                                     | Yes                 | → Quarantine on damage/hold; → Active (quantity update) |
| Quarantine | Stock held pending QC assessment or regulatory hold                       | No                  | → Active (cleared) or → Suspended (write-off)           |
| Suspended  | Stock permanently withheld from fulfillment (written off or non-sellable) | No                  | Terminal state — no onward transition                   |

05

#### End-of-Day Cutoff & Next-Day Retry

A fulfillment request arrives at the 3PL WMS at 17:52 — 8 minutes after the daily carrier collection cutoff. The 3PL cannot guarantee same-day dispatch so reports an EndOfDay failure. The next business day, the order is picked and shipped normally.

PickPack/Confirm (×2) · PickPack/ASN

Actor: 3PL WMS (automated scheduler)\
Trigger: Order arrives after 17:44 carrier cutoff\
APIs: PickPack/Confirm (×2) · PickPack/ASN\
Outcome: Order ships next working day

Call sequence: PickPack/Confirm (status: Failed · EndOfDay) → Overnight hold (WMS queue) → PickPack/Confirm (status: Confirmed, next day) → PickPack/ASN (status: Shipped)

{% stepper %}
{% step %}

### Report EndOfDay failure — order held overnight

The WMS's daily cutoff scheduler detects the order arrived after the final carrier collection window. It reports the entire order as Failed with `failureReason: EndOfDay`. eShopWorld treats this as a temporary hold, not a cancellation — the order remains active in the queue.

Request — POST /v1/PickPack/Confirm — EndOfDay hold

{ "confirmationId": "WMS-CONF-20241106-EOD-0042", "confirmationDateTime": "2024-11-06T17:52:00Z", "eswOrderReference": "ESW-ORD-7204611", "tenantCode": "ACMTEN", "pickPackResponse": { "status": "Failed", "failureReason": "EndOfDay", "problemMessage": "Order received at 17:52 UTC. Carrier collection cutoff is 17:44 UTC. Order queued for next business day dispatch.", "itemsResult": \[ { "productCode": "ACM-SS25-JACKET-NAV-L", "quantityConfirmed": 0, "quantityFailed": 1, "status": "Failed", "failureReason": "EndOfDay" } ] } }
{% endstep %}

{% step %}

### Next business day — pick, pack, and confirm

At 08:15 the following morning, the WMS's morning batch scheduler releases the held order for picking. After the picker completes the task, the WMS calls Confirm with a new `confirmationId` and today's `confirmationDateTime`.

Request — POST /v1/PickPack/Confirm — next-day fulfilment (new confirmationId)

{ "confirmationId": "WMS-CONF-20241107-000088", // NEW id — new business day "confirmationDateTime": "2024-11-07T08:42:00Z", "eswOrderReference": "ESW-ORD-7204611", // SAME order reference "tenantCode": "ACMTEN", "pickPackResponse": { "status": "Confirmed", "itemsResult": \[ { "productCode": "ACM-SS25-JACKET-NAV-L", "quantityConfirmed": 1, "quantityFailed": 0, "status": "Success" } ] } }
{% endstep %}

{% step %}

### Submit ASN when carrier collects

The carrier collects at the 10:00 morning pickup. The WMS submits the ASN immediately on scan.

Request — POST /v1/PickPack/AdvancedShippingNotice — next-day shipment

{ "shipmentId": "WMS-SHP-20241107-000088", "eswOrderReference": "ESW-ORD-7204611", "shipmentDateTime": "2024-11-07T10:03:00Z", "shipmentStatus": "Shipped", "shipFrom": { "name": "XPO Dublin FC", "locationCode": "FC-DUB-01" }, "carrierId": "DHL", "packageReference": "PKG-07204611-001", "carrierReference": "1Z999AA10123502100", "packageWeight": { "weight": 1.85, "weightUnit": "KG" }, "packageDimensions": { "length": 50, "width": 35, "height": 8, "dimensionUnit": "CM" }, "items": \[ { "sku": "ACM-SS25-JACKET-NAV-L", "quantityOrdered": 1, "quantityShipped": 1, "unitOfMeasure": "EA", "itemStatus": "Shipped" } ] }

💡 **Use a new confirmationId for the retry** — The `confirmationId` is the 3PL's idempotency key for this specific pick & pack event. A new physical fulfillment event the next day must have a new `confirmationId`. Reusing the same ID from the EndOfDay failure may be rejected or misidentified as a duplicate. The `eswOrderReference` stays the same — it identifies the order, not the fulfillment attempt.
{% endstep %}
{% endstepper %}

06

#### Fulfillment Failure Scenarios

A reference for all possible failure outcomes: undeliverable address, transient 3PL system errors, 3PL not yet configured, and customer-cancelled items. Each requires a different escalation path.

PickPack/Confirm — Failure Modes

Actor: 3PL WMS\
Trigger: Various — see sub-scenarios\
APIs: PickPack/Confirm\
Outcome: Escalation or retry based on reason

**Scenario A — Bad delivery address**

The carrier's address validation rejects the delivery address. The parcel cannot be shipped without address correction. This is a hard stop — the order must be held and the customer or retailer contacted to provide a valid address.

Request — POST /v1/PickPack/Confirm — BadAddress

{ "confirmationId": "WMS-CONF-20241106-009250", "confirmationDateTime": "2024-11-06T09:15:00Z", "eswOrderReference": "ESW-ORD-7204620", "tenantCode": "ACMTEN", "pickPackResponse": { "status": "BadAddress", "failureReason": "BadAddress", "problemMessage": "DHL address validation failed: Postcode 99999 does not exist in DE. Street 'Fantasiestrasse' not found in PLZ 99999.", "itemsResult": \[ { "productCode": "ACM-SS25-DRESS-BLK-M", "quantityConfirmed": 0, "quantityFailed": 1, "status": "Failed", "failureReason": "NotDefined" } ] } }

**Scenario B — Transient 3PL system error**

The 3PL's WMS experienced a connectivity issue mid-pick. The fulfillment attempt should be retried. eShopWorld will automatically re-queue the fulfillment request after receiving a `TransientError`.

Request — POST /v1/PickPack/Confirm — TransientError (retry expected)

{ "confirmationId": "WMS-CONF-20241106-009301", "confirmationDateTime": "2024-11-06T09:31:00Z", "eswOrderReference": "ESW-ORD-7204625", "tenantCode": "ACMTEN", "pickPackResponse": { "status": "Failed", "failureReason": "TransientError", "problemMessage": "WMS database connection lost during pick confirmation. Pick task ID 88304 incomplete. Safe to retry.", "itemsResult": \[] // no item-level results — the operation did not complete } }

**Scenario C — 3PL not configured for this tenant**

The tenant has been newly onboarded to eShopWorld but the 3PL has not yet been provisioned in the platform for that tenant. All fulfillment attempts will fail until the configuration is completed.

Request — POST /v1/PickPack/Confirm — \_3PLNotConfigured

{ "confirmationId": "WMS-CONF-20241106-009400", "confirmationDateTime": "2024-11-06T10:00:00Z", "eswOrderReference": "ESW-ORD-7204630", "tenantCode": "NEWTEN", // new tenant, not yet fully provisioned "pickPackResponse": { "status": "Failed", "failureReason": "\_3PLNotConfigured", "problemMessage": "No 3PL configuration found for tenantCode NEWTEN at fulfillment centre FC-MAN-02. Contact eShopWorld integration team." } }

**Scenario D — Operational cancel (item excluded mid-pick)**

During picking, an item is found to have a manufacturing defect that wasn't caught in QC. The WMS excludes it from the shipment using the `OperationalCancel` reason.

Request — POST /v1/PickPack/Confirm — OperationalCancel on one item

{ "confirmationId": "WMS-CONF-20241106-009500", "confirmationDateTime": "2024-11-06T10:45:00Z", "eswOrderReference": "ESW-ORD-7204640", "tenantCode": "ACMTEN", "pickPackResponse": { "status": "PartialResult", "itemsResult": \[ { "productCode": "ACM-SS25-DRESS-BLK-M", "quantityConfirmed": 1, "quantityFailed": 0, "status": "Success" }, { "productCode": "ACM-SS25-SHOES-WHT-38", "quantityConfirmed": 0, "quantityFailed": 1, "status": "Failed", "failureReason": "OperationalCancel", "problemMessage": "Sole detachment defect identified during pick scan. Unit quarantined." } ] } }

#### Failure reason decision matrix

| failureReason      | Retryable | Action by eShopWorld                                             | Action by 3PL                                           |
| ------------------ | --------- | ---------------------------------------------------------------- | ------------------------------------------------------- |
| None               | N/A       | No failure — accompanying Confirmed or PartialResult             | None needed                                             |
| TransientError     | Yes       | Re-queue fulfillment request automatically                       | Retry with new confirmationId when system recovers      |
| BadAddress         | No        | Notify retailer/customer for address correction                  | Hold parcel; await updated address instruction          |
| TimeOut            | Yes       | Re-queue with timeout extension flag                             | Retry; extend SLA window                                |
| \_3PLNotConfigured | No        | Escalate to integration team; block further attempts             | Contact eShopWorld; do not retry until config confirmed |
| NotFound           | No        | Route to alternate FC or backorder                               | Sync inventory with corrected quantity immediately      |
| CancelledItem      | No        | Process item cancellation, issue refund                          | Return cancelled item to pick shelf                     |
| OperationalCancel  | No        | Treat as out-of-stock; route alternate fulfillment               | Quarantine defective units; sync inventory              |
| Damaged            | No        | Notify retailer; process claim if insured                        | Quarantine damaged units; sync inventory to Quarantine  |
| ReallocatedExclude | Context   | Item was reallocated to a priority order; source alternate stock | None — system-managed reallocation                      |
| EndOfDay           | Yes       | Hold for next business day                                       | Re-attempt next morning with new confirmationId         |

07

#### Inventory Reconciliation & Cycle Count

Weekly, the 3PL performs a full cycle count at the Dublin FC. After each count zone completes, the WMS pushes the verified physical quantities to eShopWorld in batches. This corrects any drift that accumulated from phantom stock, pick errors, or unrecorded shrinkage.

Inventory/Sync — Operations

Actor: 3PL WMS / Operations Team\
Trigger: Weekly cycle count or ad-hoc audit\
APIs: POST /v1/Inventory/Sync (batched)\
Outcome: Platform inventory matches physical count

Call sequence: Zone A counted (56 SKUs verified) → Inventory/Sync Zone A batch → Zone B counted → Inventory/Sync Zone B batch → All zones done

{% stepper %}
{% step %}

### Post each zone batch as counting completes

Rather than waiting for the entire FC to be counted, push each zone as it completes. This minimises the window where the platform's inventory diverges from the physical truth. The batch can contain mixed statuses — Active, Quarantine, and Suspended — all in a single request.

Request — POST /v1/Inventory/Sync — Zone A cycle count batch

{ "tenantCode": "ACMTEN", "fulfillmentCentreId": "FC-DUB-01", "provider": "XPO-LOGISTICS", "items": \[ { // System said 337; physical count found 335 (2 units shrinkage) "sku": "ACM-SS25-DRESS-BLK-M", "ean": "5901234123464", "articleStatus": "Active", "quantity": 335 }, { // System said 198; physical count confirmed 198 — no change, still include it "sku": "ACM-SS25-DRESS-BLK-S", "ean": "5901234123457", "articleStatus": "Active", "quantity": 198 }, { // Suspended stock confirmed still in quarantine zone "sku": "ACM-SS25-DRESS-BLK-M", "articleStatus": "Suspended", "quantity": 13 }, { // New SKU discovered on shelf not yet registered in eShopWorld "sku": "ACM-SS25-DRESS-RED-M", "variantProductCode": "DRESS-RED-M", "ean": "5901234123488", "size": "M", "color": "RED", "articleStatus": "Active", "quantity": 42 }, { // SKU confirmed as zero — all sold out, no phantom stock "sku": "ACM-SS25-SCARF-RED", "articleStatus": "Active", "quantity": 0 // explicitly send zero to clear any residual phantom } ] }
{% endstep %}

{% step %}

### Always include unchanged SKUs in the batch

Even if the physical count matches the system quantity exactly, include those SKUs in the sync. The platform treats each sync as the authoritative snapshot for the included SKUs. If a SKU is omitted, the platform retains its previous quantity — a silent inconsistency if there was drift you haven't detected yet.

ℹ **Batch size guidance** — There is no documented maximum items per request. In practice, keep batches under 500 SKUs to stay within typical HTTP body size limits and ensure the async processor can handle the payload reliably. For large FCs with 2,000+ SKUs, split by zone and send sequentially.
{% endstep %}

{% step %}

### Post-reconciliation sanity check

After all batches are submitted, verify via the eShopWorld Inventory API (or operations dashboard) that the platform quantities match your WMS counts. Flag any discrepancies larger than your acceptable shrinkage threshold for investigation before the next fulfillment window opens.
{% endstep %}
{% endstepper %}

#### Reconciliation anti-patterns

* ❌ Only syncing changed SKUs — Sending only the SKUs that changed leaves the platform with stale data for unchanged SKUs. A concurrent system issue or missed event could have caused drift you're unaware of. Always send the full zone count.
* ❌ Omitting zero-quantity SKUs — If a SKU is sold out, explicitly send `quantity: 0`. Omitting it means the platform still shows the last synced quantity, potentially allowing phantom-stock order allocations.
* ❌ Reconciling during peak fulfillment hours — Running a full reconciliation during peak picking creates a race condition — the sync overwrites in-flight pick reservations. Schedule reconciliation during low-activity windows (early morning or overnight).
* ❌ Mixing multiple FCs in one request — Each request is scoped to a single `fulfillmentCentreId`. Do not attempt to send SKUs from FC-DUB-01 and FC-MAN-02 in the same payload — send separate requests per FC.

Reference

### Enums & Status Values

#### ArticleStatus — Inventory/Sync

* Expected — Confirmed on inbound; not yet physically received or put away
* Active — In-stock and allocatable to orders; standard fulfillable state
* Quarantine — Held pending QC, damage assessment, or regulatory review
* Suspended — Permanently withheld; written-off or non-sellable. Terminal state.

#### PickPackResponseStatus — PickPack/Confirm

| Value                 | Meaning                                                            | Items level result                          |
| --------------------- | ------------------------------------------------------------------ | ------------------------------------------- |
| AcceptedForProcessing | 3PL has accepted the order and is processing it; not yet confirmed | No item results yet — awaiting confirmation |
| Confirmed             | All items successfully picked and packed                           | All items Success                           |
| PartialResult         | Some items succeeded, some failed                                  | Mixed Success / Failed per item             |
| Failed                | The entire pick/pack operation failed                              | All items failed or empty array             |
| BadRequest            | The confirmation payload was invalid (bad order reference, etc.)   | No item results                             |
| BadAddress            | Carrier rejected the delivery address                              | All items failed                            |
| TimeOut               | Pick/pack process timed out on the 3PL side                        | Incomplete; retry expected                  |

#### PickPackProviderFailureReason — PickPack/Confirm

| Value              | Retryable | Description                                                      |
| ------------------ | --------- | ---------------------------------------------------------------- |
| None               | N/A       | No failure — used alongside Confirmed or PartialResult           |
| TransientError     | Yes       | Temporary WMS/connectivity issue; safe to retry                  |
| BadAddress         | No        | Carrier address validation failed; requires address correction   |
| TimeOut            | Yes       | Operation timed out; retry with extended SLA                     |
| \_3PLNotConfigured | No        | Tenant not provisioned for this 3PL/FC; requires platform config |

#### \_3PLItemFailureReason — per-item failures

| Value              | Physical meaning                                             | Downstream action                                               |
| ------------------ | ------------------------------------------------------------ | --------------------------------------------------------------- |
| NotDefined         | Reason not specified                                         | Investigate; default fallback reason                            |
| NotFound           | SKU not at expected pick location                            | Sync inventory with corrected count; route to alternate FC      |
| CancelledItem      | Customer or retailer cancelled this line item                | Process item cancellation; refund if paid                       |
| OperationalCancel  | 3PL excluded item due to defect, mispick, or process issue   | Quarantine item; sync inventory; re-fulfil from alternate stock |
| Damaged            | Item found damaged during pick; cannot be shipped            | Quarantine; sync inventory; raise damage claim with retailer    |
| ReallocatedExclude | System reallocated this unit to a higher-priority order      | Find next available unit; order routing decision                |
| EndOfDay           | Carrier collection cutoff passed before this item could ship | Hold overnight; retry first thing next business day             |

#### ShipmentStatus — AdvancedShippingNotice

* Unshipped — Package created at the 3PL but not yet dispatched. Rarely used in ASN — typically sent after dispatch event.
* PartiallyShipped — Some items shipped; others not included due to pick failure or split shipment.
* Shipped — All included items physically dispatched to carrier. Closes the fulfillment loop.

Reference

### Schema Quick Reference

#### InventorySyncRequest

| Field                       | Type                 | Required | Description                                          |
| --------------------------- | -------------------- | -------- | ---------------------------------------------------- |
| tenantCode                  | string               | Yes      | Brand / tenant identifier                            |
| fulfillmentCentreId         | string               | Yes      | FC identifier — unique per physical location         |
| provider                    | string               | Yes      | 3PL provider code (e.g. `XPO-LOGISTICS`)             |
| items                       | InventorySyncItem\[] | Yes      | Array of SKU records to sync                         |
| items\[].sku                | string               | Yes      | Retailer SKU — must match catalog                    |
| items\[].articleStatus      | ArticleStatus        | Yes      | Expected / Active / Quarantine / Suspended           |
| items\[].variantProductCode | string               | No       | Variant-level product code if different from SKU     |
| items\[].upc / ean          | string               | No       | Barcode identifiers for scan-based matching          |
| items\[].size / color       | string               | No       | Variant attributes for human-readable identification |
| items\[].quantity           | integer              | No       | On-hand quantity. Omit or set 0 to clear stock.      |

#### PickPackConfirm

| Field                           | Type                          | Required | Description                                                               |
| ------------------------------- | ----------------------------- | -------- | ------------------------------------------------------------------------- |
| confirmationId                  | string                        | Yes      | 3PL's unique ID for this pick/pack event — idempotency key                |
| confirmationDateTime            | datetime                      | No       | ISO 8601 timestamp when packing completed (not when API called)           |
| eswOrderReference               | string                        | Yes      | eShopWorld's order reference from the fulfillment request                 |
| tenantCode                      | string                        | Yes      | Brand / tenant identifier                                                 |
| pickPackResponse.status         | PickPackResponseStatus        | Yes      | Overall result: Confirmed / PartialResult / Failed / BadAddress / TimeOut |
| pickPackResponse.failureReason  | PickPackProviderFailureReason | No       | Provider-level failure reason when status is Failed                       |
| pickPackResponse.problemMessage | string                        | No       | Human-readable failure description for ops teams                          |
| pickPackResponse.itemsResult\[] | ItemProviderResponse\[]       | No       | Item-level outcomes; required for PartialResult                           |

#### AdvancedShippingNoticeRequest

| Field             | Type              | Required | Description                                                                |
| ----------------- | ----------------- | -------- | -------------------------------------------------------------------------- |
| shipmentId        | string            | No       | 3PL's internal shipment ID — used for deduplication                        |
| eswOrderReference | string            | No       | eShopWorld's order reference — links ASN to the order                      |
| shipmentDateTime  | datetime          | No       | When the carrier collected / parcel left the FC                            |
| shipmentStatus    | ShipmentStatus    | No       | Unshipped / PartiallyShipped / Shipped                                     |
| shipFrom          | ShipmentLocation  | No       | `{ name, locationCode }` — FC name and ID                                  |
| carrierId         | string            | No       | Carrier identifier (e.g. `DHL`, `FEDEX`)                                   |
| packageReference  | string            | No       | Retailer's package reference from Package API                              |
| carrierSCAC       | string            | No       | SCAC code — 2–4 letter carrier standard code                               |
| carrierReference  | string            | No       | Carrier tracking number (e.g. DHL waybill)                                 |
| packageWeight     | PackageWeight     | No       | `{ weight: number, weightUnit: KG\|LB }`                                   |
| packageDimensions | PackageDimensions | No       | `{ length, width, height, dimensionUnit: IN\|CM }`                         |
| items\[]          | ShipmentItem\[]   | No       | Per-item: sku, quantityOrdered, quantityShipped, unitOfMeasure, itemStatus |


---

# 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/customs-catalog-api/fulfillment-api/fulfilment-api-usecases.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.
