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

orderId

String

An unique identifier of the ShippingOrder to create

customerNo

String

(Optional) A customer number or name

shippingType

String

(Optional) Could be used to store the type of shipping or the delivery company

startMode

String

(Optional) How to start the ShippingOrder: MANUAL or AUTOMATIC

priority

Number

(Optional) The priority of the order to process

latestDueDate

String

(Optional) The order must be finished not later then this point in time

startDate

String

(Optional) The earliest start or processing date of the order

details

Object

(Optional) Some arbitrary details stored along the ShippingOrder

positions[]

Array

An array of positions, must not be empty

positions[].@class

String

The concrete type of position

positions[].pos

String

Unique identifier of the ShippingOrderPosition within the ShippingOrder

positions[].priority

Number

(Optional) The priority of the position to fulfill

positions[].product

Object

The ordered Product

positions[].product.sku

String

The SKU of the ordered Product

positions[].qtyOrdered

Object

The ordered quantity of the Product

positions[].qtyCrossdock

Object

(Optional) The quantity taken from cross docking

positions[].details

Object

(Optional) Some arbitrary details stored along the position

positions[].targetName

String

(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 a Product

  • org.openwms.wms.shipping.api.ShippingTransportUnitOrderPositionVO: A position to order a dedicated TransportUnit 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

ol

Number

Technical versioning versioning field to check the instance version

createDt

String

When the ShippingOrder has been created

lastModifiedDt

String

Timestamp when the ShippingOrder has been updated the last time

pKey

String

The persistent technical key of the ShippingOrder

state

String

The current state of the ShippingOrder

orderId

String

The business identifier of the ShippingOrder

customerOrderId

String

A reference to the customers order number

customerNo

String

A customer number or name

shippingType

String

Could be used to store the type of shipping or the delivery company

startMode

String

How to start the ShippingOrder: MANUAL or AUTOMATIC

priority

Number

The priority of the order to process

latestDueDate

String

The order must be finished not later then this point in time

startDate

String

The earliest start or processing date of the order

details

Object

Some arbitrary details stored along the ShippingOrder

positions[].createDt

String

When the ShippingOrderPosition has been created

positions[].lastModifiedDt

String

Timestamp when the ShippingOrderPosition has been updated the last time

positions[].orderPKey

String

The persistent technical key of the ShippingOrder

positions[].orderId

String

The business identifier of the ShippingOrder

positions[].pKey

String

The persistent technical key of the ShippingOrderPosition

positions[].orderPositionState

String

The current state of the ShippingOrderPosition

positions[].product

Object

The ordered Product

positions[]

Array

An array of positions, must not be empty

positions[].@class

String

The concrete type of position

positions[].pos

String

Unique identifier of the ShippingOrderPosition within the ShippingOrder

positions[].priority

Number

The priority of the position to fulfill

positions[].product

Object

The expected Product

positions[].product.sku

String

The SKU of the expected Product

positions[].qtyOrdered

Object

The ordered quantity of the Product

positions[].qtyCrossdock

Object

The quantity taken from cross docking

positions[].details

Object

Some arbitrary details stored along the position

positions[].targetName

String

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 a Product

  • org.openwms.wms.shipping.api.ShippingTransportUnitOrderPositionVO: A position to order a dedicated TransportUnit 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

@class

String

The concrete type of ShippingOrderPosition

ol

Number

Technical versioning versioning field to check the instance version

createDt

String

When the ShippingOrderPosition has been created

lastModifiedDt

String

When the ShippingOrderPosition has been updated the last time

orderPKey

String

The persistent technical key of the ShippingOrder

orderId

String

The business identifier of the ShippingOrder

pKey

String

The persistent technical key of the ShippingOrderPosition

pos

String

Unique identifier of the ShippingOrderPosition within the ShippingOrder

orderPositionState

String

The current state of the ShippingOrderPosition

priority

Number

The priority of the ShippingOrderPosition

details

Object

Some arbitrary details stored along the ShippingOrderPosition

targetName

String

The target of the ShippingOrderPosition

product

Object

(Optional) The requested Product (in case of a ShippingOrderPositionVO type)

product.sku

String

(Optional) The SKU of the requested Product (in case of a ShippingOrderPositionVO type)

qtyOrdered

Object

The ordered quantity of the Product

qtyCrossdock

Object

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"
}