Understanding Orders
Order Relationship
Sales order
A sales order represents a customer’s order and is created when a customer clicks buy on the shop.
It can be uniquely identified by the order_number
key and contains customer data, payment information, and all items (by multiple merchants) bought by the customer.
Sales order is NOT exposed by the ZDirect Orders API.
Partner Order
A Partner Order is created by Zalando platform to express the intent to ship an order to the given delivery address.
It can be uniquely identified by the order_id
key and contains the same customer information as in the Sales Order, but only the items belonging to a single partner.
For orders fulfilled through Zalando Fulfillment Solutions (ZFS), the Partner Order can be further split according to which Zalando Warehouse the items will be shipped from.
Caution
-
Relation between sales order and partner order is 1:n as multiple partner orders can be created from a single sales order. Therefore, it is possible that more than one order have the same
order_number
. Theorder_id
, however, will always be unique. -
After creation, each partner order is processed separetely. Even if they belong to the same sales order, it is not guaranteed that they will be exposed or marked approved at the same time.
-
A sales order can be split into partner orders based on multiple order fields e.g.,
merchant_id
,sales_channel_id
,stock_location_id
.
Note
For simplicity, we will call the partner order as "order" in all the documentation.
Order Structure
Once orders are placed, you may use the Orders API to get information about them, update status, add shipment tracking information, and more.
Order information is organized into three tiers:
- Order: Data in this tier is relevant to the entire order, such as customer billing and shipping address, order status, and shipment tracking info.
- Order Item: Data in this tier provides details about the types of products the customer bought, such as quantity and the Article ID of each article.
- Order Line: Data in this tier relates to the individual articles in the order, such as the shipping status of each article.
One Order may include one or more Order Items, and an Order Items may include one or more Order Lines:
Simplified Example
Let's say a customer orders two pairs of blue shoes and one pair of orange shoes.
Product | Quantity | Price per Unit | Article ID |
---|---|---|---|
Cool Shoes, Blue | 2 | 50 € | SKU-456 |
Great Shoes, Orange | 1 | 75 € | SKU-789 |
In this case, they have placed one Order with two Order Items (Cool Shoes and Great Shoes) and three Order Lines (first pair of Cool Shoes, second pair of Cool Shoes, Great Shoes):
When you get this order with the Orders API, the information about the order is organized in this structure:
- Order {shipping address, order status}
- Order Item 1 {Zalando SKU, total price, total quantity}
- Order Line 1 - Cool Shoes, Blue {item status, item price}
- Order Line 2 - Cool Shoes, Blue {item status, item price}
- Order Item 2 {Zalando SKU, total price, total quantity}
- Order Line 3 - Great Shoes, Orange {item status, item price}
- Order Item 1 {Zalando SKU, total price, total quantity}
You can get this specific order with a the following request:
GET /merchants/{merchant-id}/orders/{order-id}
This simplified example shows some of the main elements of the order JSON you will get back:
{
"data":{
"type":"Order",
"attributes":{
"merchant_id":"549391",
"order_date":"2019-12-10T15:55:45.008+00:00",
"sales_channel_id":"6e589ead-0224-426f-b18e-ed81d489abb8",
"locale":"de-DE",
"status":"shipped",
"shipping_address":{
"first_name":"Bob",
"last_name":"Smith",
"address_line_1":"123 Main Street"
},
"shipment_number":"85508",
"order_lines_count":3,
"order_lines_price_amount":175,
"order_lines_price_currency":"EUR",
"exported": true,
"order_type":"PartnerFulfilled"
},
"relationships":{
"order_items":{
"data":[
{
"type":"OrderItem",
"id":"001"
},
{
"type":"OrderItem",
"id":"002"
}
]
}
}
}
}
Notice that this reply only includes information from the Order tier. For example, we can see the total number of products ordered in order_lines_count
, but we do not know how many of each product was ordered.
You can get additional information by supplying optional parameters. In the following example, we the Order Line and Order Item data as well:
GET /merchants/{merchant_id}/orders/{order_id}?include=order_lines,order_items
Using this call, we will get the information shown above as well as this additional information (also simplified for illustration):
...
"included":[
{
"type":"OrderItem",
"attributes":{
"article_id": "SKU-456",
"description": "Cool Shoes",
"quantity_initial": 0,
"quantity_shipped": 2,
"quantity_returned": 0,
"quantity_canceled": 0
},
"relationships":{
"order_lines":{
"data":[
{
"type":"OrderLine",
"id":"001"
},
{
"type":"OrderLine",
"id":"002"
}
]
}
}
},
{
"type":"OrderItem",
"attributes":{
"article_id": "SKU-789",
"description": "Great Shoes",
"quantity_initial": 0,
"quantity_shipped": 1,
"quantity_returned": 0,
"quantity_canceled": 0
},
"relationships":{
"order_lines":{
"data":[
{
"type":"OrderLine",
"id":"003"
}
]
}
}
},
{
"type":"OrderLine",
"id":"001",
"attributes":{
"status":"shipped",
"price":{
"amount":50,
"currency":"EUR"
},
"discounted_price":{
"amount":50,
"currency":"EUR"
}
}
},
{
"type":"OrderLine",
"id":"002",
"attributes":{
"status":"shipped",
"price":{
"amount":50,
"currency":"EUR"
},
"discounted_price":{
"amount":50,
"currency":"EUR"
}
}
},
{
"type":"OrderLine",
"id":"003",
"attributes":{
"status":"shipped",
"price":{
"amount":75,
"currency":"EUR"
},
"discounted_price":{
"amount":75,
"currency":"EUR"
}
}
}
]
}
Here you can see that we have two fields of the OrderItem
type, and three fields of the OrderLine
type. We can now find additional granular details about the order, such as how many of each product was purchased, and the individual shipping status of each Order Line in the order.
Note
"price"
is the price shown to the customer at the time the order was placed in the Zalando shop.
"discounted_price"
is what the customer actually has to pay to Zalando. It could be less if the customer has a voucher or some other discount. This would be relevant, for instance if the payment method is cash on delivery, where the customer would need to be charged by the parcel carrier with only the discounted price, but the seller would receive the full price from Zalando. (We are not offering cash on delivery for Partner Program at this point though)
Other parameters are also available as include
values. For more information, see the Include section in "Getting Orders" in our API Reference.
Detailed Example
This example gives a more detailed sense of what orders really look like. In this example, a customer purchased three pairs of shoes and one hat. The request included the include
parameter with the order_line and order_item specifications:
GET /merchants/{merchant_id}/orders/{order_id}?include=order_lines,order_items
{
"data": {
"type": "Order",
"id": "",
"attributes": {
"merchant_id": "",
"logistics_provider_id": "",
"order_id": "",
"order_number": "",
"order_date": "2019-11-18T09:12:41.947+00:00",
"merchant_order_id": "",
"sales_channel_id": "",
"locale": "de-DE",
"customer_number": "",
"status": "approved",
"shipping_address": {
"address_type": "HOME_ADDRESS",
"address_id": "",
"first_name": "Bob",
"last_name": "Smith",
"address_line_1": "123 Main Street",
"zip_code": "90125",
"city": "Wolkenkuckucksheim",
"country_code": "DE"
},
"shipment_number": "",
"billing_address": {
"address_type": "HOME_ADDRESS",
"address_id": "",
"first_name": "Bob",
"last_name": "Smith",
"address_line_1": "123 Main Street",
"zip_code": "90125",
"city": "Wolkenkuckucksheim",
"country_code": "DE"
},
"tracking_number": "",
"return_tracking_number": "",
"order_lines_count": 4,
"order_lines_price_amount": 325,
"order_lines_price_currency": "EUR",
"delivery_end_date": "2019-11-22T09:12:32.169+00:00",
"exported": true,
"created_by": "",
"created_at": "2019-11-18T13:53:50.803+00:00",
"modified_by": "",
"modified_at": "2019-11-26T02:01:02.777+00:00",
"order_type": "PartnerFulfilled",
"customer_email": "",
"stock_location_id": ""
},
"links": {
"self": "URL"
},
"relationships": {
"order_items": {
"links": {
"related": "URL"
},
"data": [
{
"type": "OrderItem",
"id": "001"
},
{
"type": "OrderItem",
"id": "002"
}
]
},
"order_transitions": {
"links": {
"related": "URL"
}
}
}
},
"included": [
{
"type": "OrderItem",
"id": "001",
"attributes": {
"order_item_id": "",
"order_id": "",
"article_id": "SKU-456",
"external_id": "",
"description": "Cool Shoes",
"quantity_initial": 0,
"quantity_reserved": 0,
"quantity_shipped": 3,
"quantity_returned": 0,
"quantity_canceled": 0,
"created_by": "system",
"created_at": "2019-11-18T13:53:50.803+00:00",
"modified_by": "",
"modified_at": "2019-11-26T02:00:36.032+00:00"
},
"links": {
"self": "URL"
},
"relationships": {
"order_lines": {
"links": {
"related": "URL"
},
"data": [
{
"type": "OrderLine",
"id": "001"
},
{
"type": "OrderLine",
"id": "002"
},
{
"type": "OrderLine",
"id": "003"
}
]
}
}
},
{
"type": "OrderItem",
"id": "002",
"attributes": {
"order_item_id": "",
"order_id": "",
"article_id": "SKU-987",
"external_id": "",
"description": "Nifty Hat",
"quantity_initial": 0,
"quantity_reserved": 0,
"quantity_shipped": 1,
"quantity_returned": 0,
"quantity_canceled": 0,
"created_by": "system",
"created_at": "2019-11-18T13:53:50.803+00:00",
"modified_by": "",
"modified_at": "2019-11-26T02:00:36.032+00:00"
},
"links": {
"self": "URL"
},
"relationships": {
"order_lines": {
"links": {
"related": "URL"
},
"data": [
{
"type": "OrderLine",
"id": "007"
}
]
}
}
},
{
"type": "OrderLine",
"id": "001",
"attributes": {
"order_line_id": "",
"order_item_id": "",
"status": "shipped",
"price": {
"amount": 50,
"currency": "EUR"
},
"discounted_price":{
"amount":50,
"currency":"EUR"
},
"created_by": "system",
"created_at": "2019-11-18T13:53:50.803+00:00",
"modified_by": "",
"modified_at": "2019-11-26T02:00:36.032+00:00",
"source_stock_location_id": "44836AD6-F22A-49A5-B7D9-98479EB95BB5"
},
"links": {
"self": "URL"
},
"relationships": {
"order_line_transitions": {
"links": {
"related": "URL"
}
}
}
},
{
"type": "OrderLine",
"id": "002",
"attributes": {
"order_line_id": "",
"order_item_id": "",
"status": "shipped",
"price": {
"amount": 100,
"currency": "EUR"
},
"discounted_price":{
"amount":100,
"currency":"EUR"
},
"created_by": "system",
"created_at": "2019-11-18T13:53:50.803+00:00",
"modified_by": "",
"modified_at": "2019-11-26T02:00:36.032+00:00",
"source_stock_location_id": "44836AD6-F22A-49A5-B7D9-98479EB95BB5"
},
"links": {
"self": "URL"
},
"relationships": {
"order_line_transitions": {
"links": {
"related": "URL"
}
}
}
},
{
"type": "OrderLine",
"id": "003",
"attributes": {
"order_line_id": "",
"order_item_id": "",
"status": "shipped",
"price": {
"amount": 100,
"currency": "EUR"
},
"discounted_price":{
"amount":100,
"currency":"EUR"
},
"created_by": "system",
"created_at": "2019-11-18T13:53:50.803+00:00",
"modified_by": "",
"modified_at": "2019-11-26T02:00:36.032+00:00",
"source_stock_location_id": "44836AD6-F22A-49A5-B7D9-98479EB95BB5"
},
"links": {
"self": "URL"
},
"relationships": {
"order_line_transitions": {
"links": {
"related": "URL"
}
}
}
},
{
"type": "OrderLine",
"id": "007",
"attributes": {
"order_line_id": "",
"order_item_id": "",
"status": "shipped",
"price": {
"amount": 75,
"currency": "EUR"
},
"discounted_price":{
"amount":75,
"currency":"EUR"
},
"created_by": "system",
"created_at": "2019-11-18T13:53:50.803+00:00",
"modified_by": "",
"modified_at": "2019-11-26T02:00:36.032+00:00",
"source_stock_location_id": "44836AD6-F22A-49A5-B7D9-98479EB95BB5"
},
"links": {
"self": "URL"
},
"relationships": {
"order_line_transitions": {
"links": {
"related": "URL"
}
}
}
}
]
}
Note:
-
The value of
order_type
tells us if the order is a ZFS order or partner fulfilled:ZalandoFulfilled
: ZFSPartnerFulfilled
: Partner Fulfilled In this example, the order is partner fulfilled.
-
The
title
field("Mr", "Mrs", ...) inside theaddress
object was removed in accordance to the new de-genderisation policy applied by Zalando to create gender neutral fashion experience from API version 1.1.1 onwards. The same has been removed in the below examples as well.
Addresses
Each order has a shipping and a billing address. Both of those properties are represented by the Address
object. The example below illustrates how Address
objects are represented in the Order API:
{
"first_name": "Joe",
"last_name": "Smith",
"address_line_1": "Valeska Gert Str. 111",
"address_line_2": "Friedrichshain",
"address_line_3": "Berlin",
"zip_code": 10178,
"city": "Berlin",
"country_code": "DE",
"address_type": "HOME_ADDRESS"
}
The address example above has HOME_ADDRESS
as address_type
. Note that the address line fields of an address will be fetched according to the type defined in address_type
. More specific details for each address_type
can be found below.
Home Address
A home address must be the address of the customer to which packages for an order would be delivered. This type is represented by the value of HOME_ADDRESS
. If an Address
object has a HOME_ADRESS
as address_type
, the address_line_1
would be the actual address of a customer with the customer street and house number, and address_line_2
and address_line_3
would be fields for an additional description of the address declared in address_line_1
. The JSON address given above is what a home address would look like.
Pickup Point Address
Pickup point address represents the address of pickup stations where the customers would receive their parcels. In the address that has PICKUP_POINT
as address_type
, the address_line_1
would be the pickup point address, address_line_2
would be a JSON string representing pickup point details, and address_line_3
would have an additional description of the address. The pickup point details of an address are derived from service_point_details
of the same address. The service_point_detail
field contains the information related to the pickup point which an Address
object represents. This field will be present only for the addresses of type PICKUP_POINT
.
Here is an example of a pickup point address:
{
"first_name": "John",
"last_name": "Doe",
"address_line_1": "Valeska Gert Str. 111",
"address_line_2": "{"servicePointName":"Formido","servicePointId":"159096"}",
"address_line_3": "2nd Floor",
"zip_code": 10178,
"city": "Berlin",
"country_code": "DE",
"address_type": "PICKUP_POINT",
"service_point_details": {
"service_point_name": "Formido",
"service_point_id": "159096",
"service_point_member_id": "123456789"
}
}
Pack Station Address
Pack station addresses refer to pack station places where the customers would be able to receive their parcels. If an Address
object has a PACK_STATION
as address_type
, the address_line_1
would contain the Packstation number (in the format of Packstation <number>
), the address_line_2
would hold the pack station membership id and address_line_3
would have an additional description for the address. Here we have an example of a pack station address:
{
"first_name": "John",
"last_name": "Doe",
"address_line_1": "Packstation 111",
"address_line_2": "000111",
"address_line_3": "3rd Floor",
"zip_code": 10178,
"city": "Berlin",
"country_code": "DE",
"address_type": "PACK_STATION"
}