Copyright © 2005-2025
Copies of this document may be made for your own use and for distribution to others, provided that you do not charge any fee for such copies and further provided that each copy contains this Copyright Notice, whether distributed in print or electronically.
Overview
This guide describes the RESTful API of the OpenWMS.org WMS Shipping Service module and its usage. Some general terms and definitions are explained and declared in the first part of the document whereas in the second part the usage of the API is shown in a more use-case-driven approach.
Resources
A description of all used API resources.
Representation Formats
Basically JSON is used as representation format by default if not otherwise requested or mentioned below. XML format is supported for the
index pages as well, but must be requested explicitly. Furthermore a vendor specific JSON format is used to represent resource
representations. Therefor it’s absolutely required the Accept
header denotes the demanded type. Find the type in the examples below.
Dates in JSON
Date or datetime fields are not treated specially in JSON. Within the scope of this API a date or datetime field is always expected and
rendered as JSON String in ISO8601 format with timezone information and milliseconds: yyyy-MM-dd’T’HH:mm:ss.SSSTZD
.
Embedded Entities
For the sake of convenience some response entities may included embedded entities or even parts of it. A reference to the actual entity is provided as HAL link as well.
Error Responses
Beside the actual representation of resources, the server may result an error response in JSON format that contains basic information about the error occurred. This information is additional to the standard HTTP status code and may help clients to identify the error cause in order to re-phrase and send the request again.
Currently, there are two types of errors with their own response formats.
Server Declined Errors
These kind of errors are sent by the server runtime environment even before the request had a chance to be processed.
An example response looks like this:
{
"timestamp": 1512400854941,
"status": 500,
"error": "Internal Server Error",
"exception": "org.ameba.oauth2.InvalidTokenException",
"message": "JWT expired at 2017-12-04T15:04:43Z. Current time: 2017-12-04T15:20:54Z, ...",
"path": "/v1/transport-units?bk=00000000000000004711"
}
The JSON structure contains the following fields.
Property Name | Description |
---|---|
timestamp |
When the error occurred on server side |
status |
The http status of the error |
error |
A short error text |
exception |
Internal class name of the Java exception type |
message |
A more descriptive error text describing the error in detail |
path |
The part of the URI for the REST resource that was queried |
API Declined Errors
Those errors are thrown within the REST API validation and processing logic. For example, if a client request does not match the expected format or has produced an error on server side, the API will decline the request and return a response with status client-side error (4xx).
The structure of the response is aligned to the RFC7808. An example response looks like this:
{
"message": "LocationGroup with name [NOT_EXISTS] not found",
"messageKey": "owms.common.common.lg.notFoundByName",
"obj" : [ "NOT_EXISTS" ],
"httpStatus" : "404",
"class" : "String"
}
The JSON structure contains the following fields.
Property Name | Description |
---|---|
message |
A short error text |
messageKey |
A unique identifier across the API that can be used to identify and translate the error message on the client side |
obj |
An array of possible passed arguments to the message |
httpStatus |
The http status of the error |
class |
The arguments type |
Following message keys are currently used:
Message Key | Description | Action |
---|---|---|
not.found |
The requested resource has not been found |
The resource does not exist anymore or has never existed. The resource identifier must be verified |
Index
The initial HTTP request to retrieve information about all available resources looks like the following. The Index page is a public available resource and does not need any authentication.
GET /index HTTP/1.1
Host: localhost:8080
The Index
resource is returned in the response body with the response status of 200-OK. This main Index
lists all primary resource
entities to follow next.
HTTP/1.1 200 OK
Content-Type: application/hal+json
Content-Length: 243
{
"_links" : {
"shipping-order-index" : {
"href" : "http://localhost:8080/v1/shipping-orders/index"
},
"shipping-order-position-index" : {
"href" : "http://localhost:8080/v1/shipping-order-positions/index"
}
}
}
A client application only needs to know about the agreed link names and follow the corresponding href
link to navigate to further
resources.
ShippingOrder
A ShippingOrder
with its ShippingOrderPositions
represents a customer order that is received from an ERP system. Each order usually
consists of one or more positions where each position determines what Product
is ordered how many times. So the ShippingOrderPosition
is
the record that has the reference to ordered Product
and holds the qtyOrdered
(ordered quantity) information.
ShippingOrder Index
The index of all possible operations on a ShippingOrder
can be retrieved with an HTTP GET
request to the index of the collection
resource:
GET /v1/shipping-orders/index HTTP/1.1
Host: localhost:8080
The response lists all the operations possible on ShippingOrders
with a name and the corresponding href link:
HTTP/1.1 200 OK
Content-Type: application/hal+json
Content-Length: 516
{
"_links" : {
"shipping-order-create" : {
"href" : "http://localhost:8080/v1/shipping-orders"
},
"shipping-order-findbypkey" : {
"href" : "http://localhost:8080/v1/shipping-orders/fd54ae26-a75a-4531-ae6f-f5012288b725"
},
"shipping-order-findbyorderid" : {
"href" : "http://localhost:8080/v1/shipping-orders?orderId=SO4712"
},
"shipping-order-partialupdate" : {
"href" : "http://localhost:8080/v1/shipping-orders/fd54ae26-a75a-4531-ae6f-f5012288b727"
}
}
}
Create a ShippingOrder
To create a ShippingOrder
a caller must simply do an HTTP POST
request to the API with the minimal information needed in the body of
the request. In this example the order contains just one ShippingOrderPosition
to order a quantity of a Product
. Additionally, the
quantity to optionally reserve from a crossdock location is passed to the server:
POST /v1/shipping-orders HTTP/1.1
Content-Type: application/json
Content-Length: 911
Host: localhost:8080
{
"orderId" : "4712",
"customerNo" : "WALMART_EASTUS",
"startMode" : "AUTOMATIC",
"shippingType" : "FedEx",
"priority" : 5,
"latestDueDate" : "2025-02-13T15:05:05.250198309Z",
"startDate" : "2025-02-12T15:05:05.250159446Z",
"positions" : [ {
"@class" : "org.openwms.wms.shipping.api.ShippingOrderPositionVO",
"pos" : "1",
"priority" : 5,
"details" : {
"IDOC_ID" : "0000B92F178"
},
"targetName" : "HIGHBAY",
"product" : {
"sku" : "C000009"
},
"qtyOrdered" : {
"@class" : "org.openwms.core.units.api.Piece",
"unitType" : [ "org.openwms.core.units.api.PieceUnit", "PC" ],
"magnitude" : 1
},
"qtyCrossdock" : {
"@class" : "org.openwms.core.units.api.Piece",
"unitType" : [ "org.openwms.core.units.api.PieceUnit", "PC" ],
"magnitude" : 1
}
} ],
"details" : {
"ERP_ORDER_NO" : "SX0002039144"
}
}
Path | Type | Description |
---|---|---|
|
|
An unique identifier of the ShippingOrder to create |
|
|
(Optional) A customer number or name |
|
|
(Optional) Could be used to store the type of shipping or the delivery company |
|
|
(Optional) How to start the ShippingOrder: MANUAL or AUTOMATIC |
|
|
(Optional) The priority of the order to process |
|
|
(Optional) The order must be finished not later then this point in time |
|
|
(Optional) The earliest start or processing date of the order |
|
|
(Optional) Some arbitrary details stored along the ShippingOrder |
|
|
An array of positions, must not be empty |
|
|
The concrete type of position |
|
|
Unique identifier of the ShippingOrderPosition within the ShippingOrder |
|
|
(Optional) The priority of the position to fulfill |
|
|
The ordered Product |
|
|
The SKU of the ordered Product |
|
|
The ordered quantity of the Product |
|
|
(Optional) The quantity taken from cross docking |
|
|
(Optional) Some arbitrary details stored along the position |
|
|
(Optional) The target of the position |
If the request is correct and has been processed successfully the server returns a 200-OK
with the LOCATION
header to the created
ShippingOrder
resource:
HTTP/1.1 201 Created
Location: http://localhost:8080/v1/shipping-orders/34a9a112-082c-4abe-bf7e-71dd1650b162
In case a ShippingOrder
with the given orderId
already exists, the server cannot create the order and responds with:
HTTP/1.1 409 Conflict
Content-Type: application/hal+json
Content-Length: 146
{
"message" : "ShippingOrder with Order ID [4712] already exists cannot be created",
"messageKey" : "already.exists",
"httpStatus" : "409"
}
Create a ShippingOrder with mixed positions
A ShippingOrder
might also contain ShippingOrderPositions
of different types. Two types of ShippingOrderPositions
are currently
supported (the type is identified by the @class
attribute):
-
org.openwms.wms.shipping.api.ShippingOrderPositionVO
: A position to order an amount of aProduct
-
org.openwms.wms.shipping.api.ShippingTransportUnitOrderPositionVO
: A position to order a dedicatedTransportUnit
identified by its business key
In this example a client sends an HTTP POST
request with two ShippingOrderPositions
of different types:
POST /v1/shipping-orders HTTP/1.1
Content-Type: application/json
Content-Length: 636
Host: localhost:8080
{
"orderId" : "4713",
"positions" : [ {
"@class" : "org.openwms.wms.shipping.api.ShippingOrderPositionVO",
"pos" : "1",
"targetName" : "HIGHBAY",
"product" : {
"sku" : "C000009"
},
"qtyOrdered" : {
"@class" : "org.openwms.core.units.api.Piece",
"unitType" : [ "org.openwms.core.units.api.PieceUnit", "PC" ],
"magnitude" : 1
}
}, {
"@class" : "org.openwms.wms.shipping.api.ShippingTransportUnitOrderPositionVO",
"orderId" : "4713",
"pos" : "2",
"transportUnitBK" : "00000000000000004712",
"transportUnitTypeName" : "EURO",
"targetName" : "HIGHBAY"
} ]
}
If the request is correct and has been processed successfully the server returns a 200-OK
with the LOCATION
header to the created
ShippingOrder
:
HTTP/1.1 201 Created
Location: http://localhost:8080/v1/shipping-orders/343e28f1-ba2b-4f90-965e-42e051e4afde
Find a ShippingOrder by OrderId
A client may have the unique business key, the orderId
of a ShippingOrder
on hand, and wants to retrieve the full representation of the
ShippingOrder
including all ShippingOrderPositions
. Therefor a GET
request with the unique orderId
as query parameter is sent to the
server:
GET /v1/shipping-orders?orderId=4714 HTTP/1.1
Host: localhost:8080
The server returns the representation of the ShippingOrder
or returns a 404-NOT_FOUND
in case the order does not exist.
HTTP/1.1 200 OK
Content-Type: application/vnd.openwms.shipping-order-v1+json
Content-Length: 1609
{
"ol" : 0,
"createDt" : "2025-02-12T15:05:06.586718000Z",
"lastModifiedDt" : "2025-02-12T15:05:06.586718000Z",
"pKey" : "32923b49-b6b1-4f7a-b2e2-17a809f84495",
"orderId" : "4714",
"customerOrderId" : "CO-4711",
"customerNo" : "WALMART_EASTUS",
"state" : "CREATED",
"startMode" : "AUTOMATIC",
"shippingType" : "FedEx",
"priority" : 5,
"latestDueDate" : "2025-02-13T15:05:06.563175Z",
"startDate" : "2025-02-12T15:05:06.563155Z",
"positions" : [ {
"@class" : "org.openwms.wms.shipping.api.ShippingOrderPositionVO",
"ol" : 1,
"createDt" : "2025-02-12T15:05:06.588752000Z",
"lastModifiedDt" : "2025-02-12T15:05:06.622842000Z",
"orderPKey" : "32923b49-b6b1-4f7a-b2e2-17a809f84495",
"orderId" : "4714",
"pKey" : "9ee2ee6d-6fb5-40b6-aa46-e650e4209ac2",
"pos" : "1",
"orderPositionState" : "PROCESSING",
"priority" : 5,
"details" : {
"IDOC_ID" : "0000B92F178"
},
"targetName" : "HIGHBAY",
"product" : {
"sku" : "C000009",
"ol" : 1,
"createDt" : "2025-02-12T15:05:06.583007000Z",
"lastModifiedDt" : "2025-02-12T15:05:06.622408000Z",
"pKey" : "79208639-92db-4949-8800-69353c0dba8c"
},
"qtyOrdered" : {
"@class" : "org.openwms.core.units.api.Piece",
"unitType" : [ "org.openwms.core.units.api.PieceUnit", "PC" ],
"magnitude" : 1
},
"qtyCrossdock" : {
"@class" : "org.openwms.core.units.api.Piece",
"unitType" : [ "org.openwms.core.units.api.PieceUnit", "PC" ],
"magnitude" : 1
}
} ],
"details" : {
"ERP_ORDER_NO" : "SX0002039144"
}
}
Path | Type | Description |
---|---|---|
|
|
Technical versioning versioning field to check the instance version |
|
|
When the ShippingOrder has been created |
|
|
Timestamp when the ShippingOrder has been updated the last time |
|
|
The persistent technical key of the ShippingOrder |
|
|
The current state of the ShippingOrder |
|
|
The business identifier of the ShippingOrder |
|
|
A reference to the customers order number |
|
|
A customer number or name |
|
|
Could be used to store the type of shipping or the delivery company |
|
|
How to start the ShippingOrder: MANUAL or AUTOMATIC |
|
|
The priority of the order to process |
|
|
The order must be finished not later then this point in time |
|
|
The earliest start or processing date of the order |
|
|
Some arbitrary details stored along the ShippingOrder |
|
|
When the ShippingOrderPosition has been created |
|
|
Timestamp when the ShippingOrderPosition has been updated the last time |
|
|
The persistent technical key of the ShippingOrder |
|
|
The business identifier of the ShippingOrder |
|
|
The persistent technical key of the ShippingOrderPosition |
|
|
The current state of the ShippingOrderPosition |
|
|
The ordered Product |
|
|
An array of positions, must not be empty |
|
|
The concrete type of position |
|
|
Unique identifier of the ShippingOrderPosition within the ShippingOrder |
|
|
The priority of the position to fulfill |
|
|
The expected Product |
|
|
The SKU of the expected Product |
|
|
The ordered quantity of the Product |
|
|
The quantity taken from cross docking |
|
|
Some arbitrary details stored along the position |
|
|
The target of the position |
ShippingOrderPosition
A ShippingOrderPositions
is always encapsulated within a ShippingOrder
and defines what is actually demanded by the caller. Two types of ShippingOrderPositions
are currently supported:
-
org.openwms.wms.shipping.api.ShippingOrderPositionVO
: A position to order an amount of aProduct
-
org.openwms.wms.shipping.api.ShippingTransportUnitOrderPositionVO
: A position to order a dedicatedTransportUnit
identified by business key
ShippingOrderPosition Index
The index of all possible operations on a ShippingOrderPositions
can be retrieved with an HTTP GET
request to the index of the
collection resource:
GET /v1/shipping-order-positions/index HTTP/1.1
Host: localhost:8080
The response lists all the operations possible on ShippingOrderPositions
with a name and the corresponding href link:
HTTP/1.1 200 OK
Content-Type: application/hal+json
Content-Length: 350
{
"_links" : {
"shipping-order-position-findbypkey" : {
"href" : "http://localhost:8080/v1/shipping-order-positions/fd54ae26-a75a-4531-ae6f-f5012288b726"
},
"shipping-order-position-changestate" : {
"href" : "http://localhost:8080/v1/shipping-order-positions/fd54ae26-a75a-4531-ae6f-f5012288b728?state=PROCESSED"
}
}
}
Find a ShippingOrderPosition by PKey
To retrieve an existing ShippingOrderPosition
by its unique technical persisted key, a client sends an HTTP GET
request to the primary
resource with the pKey as path variable in the URI:
GET /v1/shipping-order-positions/0536da1d-39c0-4c63-9737-4ed4caa24ee6 HTTP/1.1
Host: localhost:8080
The server returns the representation of the ShippingOrderPosition
or returns a 404-NOT_FOUND
in case the order does not exist.
HTTP/1.1 200 OK
Content-Type: application/hal+json
Content-Length: 1011
{
"@class" : "org.openwms.wms.shipping.api.ShippingOrderPositionVO",
"ol" : 1,
"createDt" : "2025-02-12T15:05:12.135475000Z",
"lastModifiedDt" : "2025-02-12T15:05:12.174146000Z",
"orderPKey" : "26471ac0-9cd4-4d54-86c4-cc69b7fa1fbc",
"orderId" : "4714",
"pKey" : "0536da1d-39c0-4c63-9737-4ed4caa24ee6",
"pos" : "1",
"orderPositionState" : "PROCESSING",
"priority" : 5,
"details" : {
"IDOC_ID" : "0000B92F178"
},
"targetName" : "HIGHBAY",
"product" : {
"sku" : "C000009",
"ol" : 1,
"createDt" : "2025-02-12T15:05:12.132550000Z",
"lastModifiedDt" : "2025-02-12T15:05:12.173761000Z",
"pKey" : "01253601-98ec-4ad2-8b19-8d13317587f8"
},
"qtyOrdered" : {
"@class" : "org.openwms.core.units.api.Piece",
"unitType" : [ "org.openwms.core.units.api.PieceUnit", "PC" ],
"magnitude" : 1
},
"qtyCrossdock" : {
"@class" : "org.openwms.core.units.api.Piece",
"unitType" : [ "org.openwms.core.units.api.PieceUnit", "PC" ],
"magnitude" : 1
}
}
Path | Type | Description |
---|---|---|
|
|
The concrete type of ShippingOrderPosition |
|
|
Technical versioning versioning field to check the instance version |
|
|
When the ShippingOrderPosition has been created |
|
|
When the ShippingOrderPosition has been updated the last time |
|
|
The persistent technical key of the ShippingOrder |
|
|
The business identifier of the ShippingOrder |
|
|
The persistent technical key of the ShippingOrderPosition |
|
|
Unique identifier of the ShippingOrderPosition within the ShippingOrder |
|
|
The current state of the ShippingOrderPosition |
|
|
The priority of the ShippingOrderPosition |
|
|
Some arbitrary details stored along the ShippingOrderPosition |
|
|
The target of the ShippingOrderPosition |
|
|
(Optional) The requested Product (in case of a ShippingOrderPositionVO type) |
|
|
(Optional) The SKU of the requested Product (in case of a ShippingOrderPositionVO type) |
|
|
The ordered quantity of the Product |
|
|
The quantity taken from cross docking |
Change the State of a ShippingOrderPosition
A partial state change on an existing ShippingOrderPosition
is done with an HTTP PATCH
request that contains the state
of the position
with the new value. The URI of the request points to the primary resource.
PATCH /v1/shipping-order-positions/3763b4d8-0bd7-4856-8450-0c6b9f0db60e HTTP/1.1
Content-Type: application/x-www-form-urlencoded
Host: localhost:8080
Content-Length: 13
state=SHIPPED
If the state change can be performed, the server responds with the full representation of the updated ShippingOrderPosition
in the
response body:
HTTP/1.1 200 OK
Content-Type: application/hal+json
Content-Length: 1008
{
"@class" : "org.openwms.wms.shipping.api.ShippingOrderPositionVO",
"ol" : 1,
"createDt" : "2025-02-12T15:05:11.888904000Z",
"lastModifiedDt" : "2025-02-12T15:05:11.944730000Z",
"orderPKey" : "cc042fe4-1826-4d1e-b5a5-1a84480dc1eb",
"orderId" : "4716",
"pKey" : "3763b4d8-0bd7-4856-8450-0c6b9f0db60e",
"pos" : "1",
"orderPositionState" : "SHIPPED",
"priority" : 5,
"details" : {
"IDOC_ID" : "0000B92F178"
},
"targetName" : "HIGHBAY",
"product" : {
"sku" : "C000009",
"ol" : 1,
"createDt" : "2025-02-12T15:05:11.886365000Z",
"lastModifiedDt" : "2025-02-12T15:05:11.944364000Z",
"pKey" : "5e987c38-93f4-4e39-9d2f-674f230fbbe4"
},
"qtyOrdered" : {
"@class" : "org.openwms.core.units.api.Piece",
"unitType" : [ "org.openwms.core.units.api.PieceUnit", "PC" ],
"magnitude" : 1
},
"qtyCrossdock" : {
"@class" : "org.openwms.core.units.api.Piece",
"unitType" : [ "org.openwms.core.units.api.PieceUnit", "PC" ],
"magnitude" : 1
}
}
If the state change is not allowed the server responds with an error:
HTTP/1.1 403 Forbidden
Content-Type: application/hal+json
Content-Length: 336
{
"message" : "Not allowed to change the state of the ShippingOrderPosition [e52dc5f6-1e2d-4d9f-ba35-24aa123cb979] from [PROCESSING] to [CREATED]",
"messageKey" : "owms.wms.shp.sop.notAllowedToChangeState",
"obj" : [ "e52dc5f6-1e2d-4d9f-ba35-24aa123cb979", "PROCESSING", "CREATED" ],
"httpStatus" : "403",
"class" : "String"
}