Walmart Order Shipment
Summary of Changes: (The purpose of this table is to keep traceability and Product team to highlight the things that were changed into the scope, based on comments or discussions)
Version | Date | Created / Updated | Notes |
---|---|---|---|
1.0 | 15.06.2021 | Danail Deltchev | First publish |
1.1 | 14.09.2022 | Bogomil Pavlov | Include intentToCancelOverride in the payload |
1.2 | 18/12/2023 | Hristiyan Georgiev | Walmart has new API version and updates. The scope was also updated to the latest changes on Walmart. Everything that is not tagged with v1.2 remains the same. |
1.3 | 09/05/2024 | Hristiyan | Changed where we pick the methodCode from |
1.4 | 10/05/2024 | Hristiyan | Updated the format for the unix timestamp for shipDateTime |
The purpose of this page is to explain the flows and how and when we need to ship an order on Walmart
API Docs: https://developer.walmart.com/doc/us/mp/us-mp-orders/ and https://developer.walmart.com/api/us/mp/orders
API Call: POST https://marketplace.walmartapis.com/v3/orders/{purchaseOrderId}/shipping
Schemas (some “types” are considered “CommonComponents” and are not described directly in the specific flow xsd, hence why there are two schemas attached):
<v1.2>
Shipment is being updated on Walmart on a line level (product by product) meaning we can update an Ordered Item and ship only a few quantities out of it. We can control this via our Order Shipment
table where all shipping information will be picked from.
With a couple of words for general information - the Shipment model had to change because the old version was allowing for only one Shipment on the whole order. What we’ve done is taken this from the “Orders” section and separated it in its own “Shipment” section that holds the needed required fields and can hold the exact item references that need to be shipped at a specific point in time
As shipment is being updated on Walmart on a line level (product by product) meaning we can update an Ordered Item and ship only a few quantities out of it with this new method we can utilise this functionality at its best and do partial shipments instead of only full ones
The trigger for a shipment on Walmart through the abstraction shipment will be the flag on level Order Shipment
> Status
which needs to be on "pending" AND Orders
> Status
= Ready For Shipping OR Partially Shipped
The communication from there on is standard
- pending - we need to send something
- sent - if we’ve successfully sent the information to Walmart
- normal - if we don’t have anything to do or successfully received a response from Walmart that the shipment was successful
- error - if something in validations or through communication fails
Error and status management:
As this is a new functionality that allows splitting we need to introduce additional management of situations. Please NOTE that as per the abstraction if we don’t directly receive in the response the ACTUAL item (line) statuses from the marketplace we are to only update the new Fulfilment statuses on order_item_line, order_item and the “tool_status” on order level. Please see the explanation on these in the abstraction description Order management general requirements.
Expected outcomes when picking a “pending” shipment and putting it on “sent” are as follows:
- All lines get shipped - The shipment goes on a “normal” status (all lines are updated in Hemi accordingly with their new statuses, If all lines in Hemi are shipped the order itself should be set as tool_status = “dispatched”, if not there should be updates with the correct “partially shipped” statuses. Please follow the abstraction guidelines on this)
- All lines can’t be shipped or result in error when sending them to Walmart - The shipment goes on an “error” status; we store an order_error record with type shipment, severity error and the messages received from Walmart
-
There is at least one line we’ve decided we CAN ship and all other lines we are blocking because of the status validation
-
If this update is successful (for only part of the shipment) - We set the Shipment on a “warning” status and we store an order_error record with type shipping, severity warning and the correct message from our validation that is blocking the updates for the lines. We should also store in a a new field in the Hemi Shipment Row the actual successfully shipped qty and update the number of shipped lines with their according status which in result should follow for an update on the order_item and the order itself
Example error to use for validation: “Order item line ID [id] is not on an “Acknowledged” status. Only items on “Acknowledged“ status can be shipped to Walmart”
-
If the update was not successful (for only part of the shipment) - The shipment goes on an “error” status; we store an order_error record with type shipment, severity error and the messages received from Walmart
-
Note: Some general information and a general summary as there were findings during the development and testing of the Shipment - the expectation is that if there is even a single line that passes our internal validation we want to try and send a Shipment update to Walmart. The Walmart shipment is passed on what we understand in Hemi as “SKU” level and we have the option to pass qty against that shipment. IF we have a single SKU that has 3 qty in Hemi and someone is trying to ship all of them but only 1 of the 3 lines is on an acknowledged status (for whatever reason) we are to ship this SKU with qty value of 1. To keep proper track of that we are adding the field for successful shipments (Should be added in the abstraction!) AND we are also adding a new status to keep track of this (warning) on the whole Shipment level. If later we have a consecutive Shipment for the other 2 lines (or we have again all 3 lines but the already shipped line is not passed validation) we are to try and ship that as per this standard logic as well. Expectation is that this will be an incredibly rare case but we are to use it for general knowledge as well how to manage our multishipment options
Walmart also allows us to make consecutive updates of the orders with information of next steps (reached courier depot, is shipped to final mile, accepted in city, etc) which we don’t support so there will be no explanation on this part in this document
The call is synchronous and is done order by order based on Walmart’s purchase Order ID value. Below an example order shipping update followed by mapping and any additional information
{
"orderShipment": {
"orderLines": {
"orderLine": [
{
"lineNumber": "1",
"intentToCancelOverride": false,
"sellerOrderId": "92344",
"orderLineStatuses": {
"orderLineStatus": [
{
"status": "Shipped",
"statusQuantity": {
"unitOfMeasurement": "EACH",
"amount": "1"
},
"trackingInfo": {
"shipDateTime": 1580821866000,
"carrierName": {
"carrier": "UPS"
},
"methodCode": "Standard",
"trackingNumber": "22344",
"trackingURL": "http://walmart/tracking/ups?&type=MP&seller_id=12345&promise_date=03/02/2020&dzip=92840&tracking_numbers=92345"
},
"returnCenterAddress": {
"name": "walmart",
"address1": "walmart store 2",
"city": "Huntsville",
"state": "AL",
"postalCode": "35805",
"country": "USA",
"dayPhone": "12344",
"emailId": "walmart@walmart.com"
}
}
]
}
},
{
"lineNumber": "2",
"sellerOrderId": "92344",
"orderLineStatuses": {
"orderLineStatus": [
{
"status": "Shipped",
"statusQuantity": {
"unitOfMeasurement": "EACH",
"amount": "1"
},
"trackingInfo": {
"shipDateTime": 1580821866000,
"carrierName": {
"carrier": "FedEx"
},
"methodCode": "Express",
"trackingNumber": "22344",
"trackingURL": "http://walmart/tracking/fedEx?&type=MP&seller_id=12345&promise_date=03/02/2020&dzip=92840&tracking_numbers=92344"
},
"returnCenterAddress": {
"name": "walmart",
"address1": "walmart store 2",
"city": "Huntsville",
"state": "AL",
"postalCode": "35805",
"country": "USA",
"dayPhone": "12344",
"emailId": "walmart@walmart.com"
}
}
]
}
}
]
}
}
}
Mapping
Walmart Field | Hemi Mapping | Notes | |||||||
---|---|---|---|---|---|---|---|---|---|
orderShipment |
N/A | ||||||||
orderLines |
N/A | ||||||||
orderLine |
N/A | ||||||||
lineNumber |
Products on Order > Item Order Line ID |
||||||||
intentToCancelOverride |
N/A | Needs to be hardcoded as “true”. |
This flag basically is to identify shipping orders marked as canceled by the customer when the order status hasn’t been updated. In other words if we send this flag as “true” at the time of trying to ship the order, if it was already cancelled by the customer but the status was not updated, we will be able to mark it as shipped. If the flag is “false” we will not be able to ship the order. |
| | | | sellerOrderId
| | | | | Orders
> ID
| |
| | | | orderLineStatuses
| | | | | N/A | |
| | | | | orderLineStatus
| | | | N/A | |
| | | | | | status
| | | “Shipped” | Hardcoded - we are always sending “Shipped” with this call |
| | | | | | statusQuantity
| | | N/A | |
| | | | | | | unitOfMeasurement
| | EACH | Hardcoded |
| | | | | | | amount
| | Order Shipment Rows
> Quantity
| |
| | | | | | trackingInfo
| | | N/A | |
| | | | | | | shipDateTime
| | Order Shipment
> Shipment Time
OR
NOW() | Please have in mind this always needs to be in UTC.
Order Shipment
is with priority. We only want to send NOW() if the Order Shipment
> Shipment Time
is not filled.
<v1.4> The format should be Unix timestamp in milliseconds </v1.4> |
| | | | | | | carrierName
| | N/A | |
| | | | | | | | otherCarrier
| Order Shipment
> Courier
| If it is not any of Walmart’s approved list of carriers we should use this field otherwise we should exclude it from the payload |
| | | | | | | | carrier
| Order Shipment
> Courier
| If it is a Walmart approved carrier we should use this field otherwise we should exclude it from the payload |
| | | | | | | methodCode
| | <v1.3>Orders
> Shipping Service
</v1.3> | We should’ve received this with the order already |
| | | | | | | trackingNumber
| | Order Shipment
> Tracking Number
| |
| | | | | | | trackingURL
| | Order Shipment
> Tracking URL
| If such is not present at the time of update we should aim to pick up from Courier
> Courier URL
, where the mapping should be based on the Courier name mapped to the Order Shipment
> Courrier
|
| | | | | | returnCenterAddress
| | | N/A | To capture this as best as possible we should assign a “Return Location” to Walmart’s Account (in Account Walmart) and pick all of the below fields from the selected location |
| | | | | | | name
| | Locations
> Name
| |
| | | | | | | address1
| | Locations
> Street1
| |
| | | | | | | address2
| | Locations
> Street2
| |
| | | | | | | city
| | Locations
> City
| |
| | | | | | | state
| | Locations
> State Province
| |
| | | | | | | postalCode
| | Locations
> Post code
| |
| | | | | | | country
| | Locations
> Country 2 char ISO code
| We have to convert to 3 chars (99.99% of the time this should be USA) |
| | | | | | | dayPhone
| | Locations
> Phone
| |
| | | | | | | emailId
| | Locations
> Email
| |
The response should be a 200 Successful Operation so we are to treat the order as shipped as long as we receive this response. Every other response will be treated as unsuccessful and we need to store any errors in the Order Errors
table with Type
= Shipping
Response is attached.
</v1.2>
Additional Information
To reiterate - Shipping methods are generally controlled via templates on Walmart. This means we will have some of the information what is supposed to be used when Shipping the product itself. We should follow Walmart’s own list of couriers otherwise we are requested to use the additional update method to update information to the order (which is not present as flow in Hemi at the moment at all). Still if it is required from us to update an order with a different courier it happens via the “other_courier” field instead of the standard “courier”.
We want to be able to fill in the correct URL based on the courier but if there is no tracking when we are making the update we don’t want to send a URL as well
When we make the update successfully (or on the read of the next order) we are to update all relevant statuses (order, product, line) with their relevant statuses. For any mismatch statuses on orders not shipped via us or due to unsuccessful shipment of a set of products please refer to the order download Statuses management
We are aiming to ship only “acknowledged” lines - Created can’t be processed in any way if not Acknowledged and after the acknowledgement we have 3 statuses which are all end statuses as it seems - Shipped, Refunded & Cancelled. Meaning we want to “ship” only “acknowledged” lines and any such quantity (as a single SKU can have multiple quantity on different statuses)
As Walmart requires the use of specific carrier when we are shipping an order we will need to introduce a mapping feature.
In order to do so we will need to include a new table called Walmart Courier with enumeration field.
We will need to map the <v1.2> Order Shipment
> Courier
with Courier
> Name
and send the Walmart Courier
> Walmart Carrier ID
</v1.2>.
Walmart Courier
> Walmart Carrier ID
will be a slave table of Courier table