Copyright © 2005-2022

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 Inventory 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.

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. Therefore it is absolutely required that 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

This 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 descriptive message text in English language

messageKey

An unique identifier across the API that can be used to identify and translate the error message on the client side

obj

Arbitrary values passed to the client that correspond to the failure

httpStatus

The HTTP status set by the server, could be different from the response HTTP status

class

The data type of the obj values

Following message keys are currently used:

Message Key

Description

Possible Action

core.validation.error

Error on validating fields

Generic validation error, verify all request parameters and fields

owms.wms.inv.tu.bk

TransportUnit is missing the business key

The resource identifier must be verified

owms.wms.inv.tu.actualLocation.erpCode

TransportUnit is missing the actual location (ERP Code)

Verify the identifying attribute passed to the API

owms.wms.inv.tu.transportUnitType

TransportUnit is missing the type

Verify the identifying attribute passed to the API

owms.wms.inv.product.pKey

Persistent Key of the Product is missing

Verify the identifying attribute passed to the API

owms.wms.inv.product.sku

SKU of the Product is missing

Verify the identifying attribute passed to the API

owms.wms.inv.product.baseUnit

BaseUnit of the Product is missing

Verify the identifying attribute passed to the API

owms.wms.inv.pu.pKeyNotExists

PackagingUnit with persistent identifier does not exist

The resource identifier must be verified

owms.wms.inv.pu.loadUnitTypeMissing

LoadUnit on TransportUnit does not exist and must be created but no LoadUnitType has been given

Verify the identifying attribute passed to the API

owms.wms.inv.pu.noPUOnLocation

The Product does not exist and can’t be moved

Verify the Product to move exists on the Location

Resources

A overview of all used API resources with a description of their attributes. More information about the resource itself and the exposed functionality is mentioned in the chapters below.

resources.drawio
Table 1. LoadUnitVO
Attribute Description

pKey

The persistent unique key of the LoadUnit

transportUnitBK

The business key of the TransportUnit

physicalPosition

The position where the LoadUnit is physically located on the TransportUnit

label

An identifying label of the LoadUnit

type

The type of the LoadUnit

locked

Whether the LoadUnit is locked for allocation or not

product

The Product the LoadUnit contains

length

The current length

width

The current width

height

The current height

packagingUnits

The packagingUnits contained in the LoadUnit

Table 2. ProductVO
Attribute Description

pKey

Unique identifier of the Product

sku

The Product’s SKU

label

Could be an identifying barcode label or RFID tag

baseUnit

The default UOM the Product is managed, i.e. PC (Piece)

description

A descriptive text

availabilityState

A Product may be accessible or not for any kind of processing

classification

An arbitrary information to classify the Product, i.e. a hazardous product

group

An attribute to group products

stockZone

Where this Product should be stored in stock

units

Alternative UOMs this Product can be packaged, i.e. PC (Piece), DOZ (Dozen)

Table 3. PackagingUnitVO
Attribute Description

product

The Product the PackagingUnit consists of

quantity

The amount of product items contained in the PackagingUnit

length

The actual physical length of the PackagingUnit

loadUnit

The LoadUnit the PackagingUnit is stored in

actualLocation

The actual Location of the PackagingUnit if directly stored on Locations

dimension

The physical dimension of the PackagingUnit

weight

The actual weight of the the PackagingUnit

distribution

Describes how many of this kind of PackagingUnits fit into the current LoadUnit

physicalPosition

Some hint where to find the PackagingUnit within the LoadUnit

serialNumber

Identifying serialnumber

expiresAt

The expiration date of the PackagingUnit

labels

A collection of tags or labels assigned to the PackagingUnit

Table 4. LoadUnitDistributionVO
Attribute Description

piecesPerLoadUnitLayer

How many PackagingUnits fit into one layer in a LoadUnit

numberOfLoadUnitLayers

How many layers of the PackagingUnit fit into a LoadUnit

Table 5. UnitTypeVO
Attribute Description

amount

The actual amount of the unit of measure (UOM)

unit

The unit of the UOM

Table 6. MessageVO
Attribute Description

messageNo

An identifying number of the Message that can be used for translation

messageText

A descriptive message text

Table 7. StockZone
ENUM value Description

A

Product of high demand

B

Product of medium demand

C

Product of low demand

Table 8. AvailabilityState
ENUM value Description

LOCKED

Generally locked for automatic processing

QC_LOCKED

Locked for quality check

AVAILABLE

Generally available

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: 303

{
  "_links" : {
    "product-index" : {
      "href" : "http://localhost:8080/v1/products/index"
    },
    "load-unit-index" : {
      "href" : "http://localhost:8080/v1/load-units/index"
    },
    "packaging-unit-index" : {
      "href" : "http://localhost:8080/v1/packaging-units/index"
    }
  }
}

A client application only needs to know about the agreed link names and follow the corresponding href link to navigate to further resources.

Product

The Product is a representation of an article known and shipped within a warehouse. A Product is just a definition but not the physical article. In the real world a Product exists in a number of items, dimensions, liters or other units. Hence a Product is physically always tied to an amount, see PackagingUnits for more information.

Product Index (product-index)

The index with all possible operations can be retrieved with an GET request:

GET /v1/products/index HTTP/1.1
Host: localhost:8080

The response lists all the operations with a name and the corresponding href link:

HTTP/1.1 200 OK
Content-Type: application/hal+json
Content-Length: 583

{
  "_links" : {
    "products-findall" : {
      "href" : "http://localhost:8080/v1/products"
    },
    "products-findbysku" : {
      "href" : "http://localhost:8080/v1/products?sku=ZS0002029"
    },
    "products-findbyspkey" : {
      "href" : "http://localhost:8080/v1/products/pKey"
    },
    "products-findbyskuanduom" : {
      "href" : "http://localhost:8080/v1/products?sku=ZS0002029&uom=PC"
    },
    "products-create" : {
      "href" : "http://localhost:8080/v1/products"
    },
    "products-update" : {
      "href" : "http://localhost:8080/v1/products"
    }
  }
}

Create Products (products-create)

New Products can be added to the catalog of existing ones by sending a POST request to the server with an array of Products. Those Products are often created by the ERP system, indirectly through a appropriate ERP Hostconnector. It is not unusual that this happens in a bulk operation with thousands of records at a time.

A request could look like this:

POST /v1/products HTTP/1.1
Content-Type: application/json
Content-Length: 1084
Host: localhost:8080

[ {
  "sku" : "NEW_PRODUCT",
  "label" : "EAN-label",
  "accountId" : "GM Account",
  "baseUnit" : {
    "@class" : "org.openwms.core.units.api.Piece",
    "unitType" : [ "org.openwms.core.units.api.PieceUnit", "PC" ],
    "magnitude" : 1
  },
  "description" : "Screws",
  "availabilityState" : "QC_LOCKED",
  "classification" : "ClassA",
  "group" : "inhouse",
  "stockZone" : "C",
  "units" : [ {
    "label" : "ean1",
    "quantity" : {
      "@class" : "org.openwms.core.units.api.Piece",
      "unitType" : [ "org.openwms.core.units.api.PieceUnit", "PC" ],
      "magnitude" : 8
    },
    "dimension" : {
      "height" : 250,
      "length" : 400,
      "width" : 30,
      "uom" : "MM"
    },
    "details" : {
      "piecesPerLayer" : "10",
      "numbersOfLayers" : "1",
      "carrierType" : "EURO"
    }
  } ],
  "dimension" : {
    "height" : 10,
    "length" : 20,
    "width" : 30,
    "uom" : "CM"
  },
  "stackingRules" : [ {
    "noProducts" : 2,
    "allowedProduct" : {
      "sku" : "ZS0002029"
    }
  } ],
  "details" : {
    "supplier" : "Westminster"
  }
} ]

The mandatory fields of a new Product are: sku, baseUnit.

If the server has successfully created the demanded Product the response looks like:

HTTP/1.1 201 Created
Location: http://localhost:8080/v1/products/bde3bf25-92f4-4c3e-bfb4-c1dd190d565f/

Notice that the server sends back the LOCATION header to a created Product resource only in case one the request contained one new Product to create. If multiple Products have been created, there is no LOCATION header returned.

If the request could not been processed because of missing or invalid request data the server responds with:

HTTP/1.1 400 Bad Request
Content-Type: application/hal+json
Content-Length: 126

{
  "message" : "Error on validating fields: [[baseUnit]]",
  "messageKey" : "core.validation.error",
  "httpStatus" : "400"
}

Find all Products (products-findall)

To retrieve a list of all existing Products a client must send a GET request to the server:

GET /v1/products HTTP/1.1
Host: localhost:8080

The response contains all existing Products:

HTTP/1.1 200 OK
Content-Type: application/json
Content-Length: 1321

[ {
  "ol" : 0,
  "pKey" : "1",
  "sku" : "ZS0002029",
  "label" : "221156456666",
  "accountId" : "GM",
  "baseUnit" : {
    "@class" : "org.openwms.core.units.api.Piece",
    "unitType" : [ "org.openwms.core.units.api.PieceUnit", "PC" ],
    "magnitude" : 1
  },
  "overbookingAllowed" : true,
  "description" : "LiPo battery 12V 4400mAh",
  "availabilityState" : "AVAILABLE",
  "classification" : "Hazardous",
  "group" : "Internal Goods",
  "stockZone" : "A",
  "units" : [ {
    "quantity" : {
      "@class" : "org.openwms.core.units.api.Piece",
      "unitType" : [ "org.openwms.core.units.api.PieceUnit", "PC" ],
      "magnitude" : 3
    },
    "dimension" : {
      "height" : 150,
      "length" : 146,
      "width" : 25,
      "uom" : "MM"
    },
    "details" : {
      "piecesPerLayer" : "10",
      "numbersOfLayers" : "1",
      "carrierType" : "EURO"
    },
    "pKey" : "1"
  } ],
  "dimension" : {
    "height" : 50,
    "length" : 146,
    "width" : 25,
    "uom" : "MM"
  },
  "details" : {
    "fixed_supplier_id" : "GM_US"
  }
}, {
  "ol" : 0,
  "pKey" : "2",
  "sku" : "ZS0002030",
  "baseUnit" : {
    "@class" : "org.openwms.core.units.api.Piece",
    "unitType" : [ "org.openwms.core.units.api.PieceUnit", "PC" ],
    "magnitude" : 1
  },
  "overbookingAllowed" : true,
  "stockZone" : "A"
} ]

Find a Product by SKU (products-findbysku)

To find and return a Product identified by its SKU a client needs to query the resource by sku as query parameter in a GET request:

GET /v1/products?sku=ZS0002029 HTTP/1.1
Host: localhost:8080

The response contains either the Product if it exists:

HTTP/1.1 200 OK
Content-Type: application/hal+json
Content-Length: 1050

{
  "ol" : 0,
  "pKey" : "1",
  "sku" : "ZS0002029",
  "label" : "221156456666",
  "accountId" : "GM",
  "baseUnit" : {
    "@class" : "org.openwms.core.units.api.Piece",
    "unitType" : [ "org.openwms.core.units.api.PieceUnit", "PC" ],
    "magnitude" : 1
  },
  "overbookingAllowed" : true,
  "description" : "LiPo battery 12V 4400mAh",
  "availabilityState" : "AVAILABLE",
  "classification" : "Hazardous",
  "group" : "Internal Goods",
  "stockZone" : "A",
  "units" : [ {
    "quantity" : {
      "@class" : "org.openwms.core.units.api.Piece",
      "unitType" : [ "org.openwms.core.units.api.PieceUnit", "PC" ],
      "magnitude" : 3
    },
    "dimension" : {
      "height" : 150,
      "length" : 146,
      "width" : 25,
      "uom" : "MM"
    },
    "details" : {
      "piecesPerLayer" : "10",
      "numbersOfLayers" : "1",
      "carrierType" : "EURO"
    },
    "pKey" : "1"
  } ],
  "dimension" : {
    "height" : 50,
    "length" : 146,
    "width" : 25,
    "uom" : "MM"
  },
  "details" : {
    "fixed_supplier_id" : "GM_US"
  }
}
Path Type Description

pKey

String

The persistent unique key

sku

String

The product id is the unique business key

label

String

An identifying label of the Product

accountId

String

The name of the Account the Product belongs to

baseUnit

Object

Products may be defined with different base units

baseUnit.@class

String

Must be one of the static values to identify the type of UOM

baseUnit.unitType

Array

Must be one of the static values to identify the type of UOM

baseUnit.magnitude

Number

The amount

description

String

Textual descriptive text

availabilityState

String

The Product definition can be set to be unavailable for further operations

classification

String

Products may be classified, ie. hazardous

group

String

Products may be grouped

stockZone

String

Where the Product has to be placed in stock

overbookingAllowed

Boolean

Is it allowed to receive a higher quantity as expected/announced of this Product?

units[]

Array

A Product can be packed and stored in different box sizes

units[].pKey

String

The persistent key of the ProductUnit

units[].quantity

Object

Each unit must have the quantity defined how many items are in one item container

units[].dimension

Object

Each unit may have a different dimension

units[].details

Object

Arbitrary detail information on this product unit, might by populated with ERP information

dimension

Object

The defined dimension of the Product in in’s baseUnit

dimension.height

Number

The height

dimension.length

Number

The length

dimension.width

Number

The width

dimension.uom

String

The Unit of Measure (UOM) of each dimension value

details

Object

Arbitrary detail information on this product, might by populated with ERP information

or returns with a 404-NOT FOUND error response in case no Product with the given SKU exists:

HTTP/1.1 404 Not Found
Content-Type: application/hal+json
Content-Length: 115

{
  "message" : "Product with SKU [UNKNOWN] does not exist",
  "messageKey" : "not.found",
  "httpStatus" : "404"
}

Find a Product by SKU and UOM (products-findbyskuanduom)

A Product may exist in different measurement flavors. One Product with one SKU but packed in different packaging types. For example, car tires with the SKU = ZS0002029 may exist in packages of always one piece and additionally in packages with 3x4 pieces (a Dozen). A client could be interested in finding the correct Product by SKU and UOM by sending a GET request with both as request parameters:

GET /v1/products?sku=ZS0002029&uom=3+PC HTTP/1.1
Host: localhost:8080

If this Product with such an UOM exists, the server returns a 200-OK with the Product and all existing UOM relations.

HTTP/1.1 200 OK
Content-Type: application/hal+json
Content-Length: 1890

{
  "ol" : 0,
  "pKey" : "1",
  "sku" : "ZS0002029",
  "label" : "221156456666",
  "accountId" : "GM",
  "baseUnit" : {
    "@class" : "org.openwms.core.units.api.Piece",
    "unitType" : [ "org.openwms.core.units.api.PieceUnit", "PC" ],
    "magnitude" : 1
  },
  "overbookingAllowed" : true,
  "description" : "LiPo battery 12V 4400mAh",
  "availabilityState" : "AVAILABLE",
  "classification" : "Hazardous",
  "group" : "Internal Goods",
  "stockZone" : "A",
  "units" : [ {
    "quantity" : {
      "@class" : "org.openwms.core.units.api.Piece",
      "unitType" : [ "org.openwms.core.units.api.PieceUnit", "PC" ],
      "magnitude" : 3
    },
    "dimension" : {
      "height" : 150,
      "length" : 146,
      "width" : 25,
      "uom" : "MM"
    },
    "details" : {
      "piecesPerLayer" : "10",
      "numbersOfLayers" : "1",
      "carrierType" : "EURO"
    },
    "pKey" : "1"
  }, {
    "quantity" : {
      "@class" : "org.openwms.core.units.api.Piece",
      "unitType" : [ "org.openwms.core.units.api.PieceUnit", "PC" ],
      "magnitude" : 3
    },
    "dimension" : {
      "height" : 150,
      "length" : 146,
      "width" : 25,
      "uom" : "MM"
    },
    "details" : {
      "piecesPerLayer" : "10",
      "numbersOfLayers" : "1",
      "carrierType" : "EURO"
    },
    "pKey" : "1"
  }, {
    "quantity" : {
      "@class" : "org.openwms.core.units.api.Piece",
      "unitType" : [ "org.openwms.core.units.api.PieceUnit", "PC" ],
      "magnitude" : 3
    },
    "dimension" : {
      "height" : 150,
      "length" : 146,
      "width" : 25,
      "uom" : "MM"
    },
    "details" : {
      "piecesPerLayer" : "10",
      "numbersOfLayers" : "1",
      "carrierType" : "EURO"
    },
    "pKey" : "1"
  } ],
  "dimension" : {
    "height" : 50,
    "length" : 146,
    "width" : 25,
    "uom" : "MM"
  },
  "details" : {
    "fixed_supplier_id" : "GM_US"
  }
}

If the given UOM is not a valid one, like in this example Camels, the server responds with 404-NOT FOUND:

HTTP/1.1 404 Not Found

Allocate Products

A demanded amount of a Product can be reserved or allocated for picking or goods out. To do so, a client must call the allocation API to get back an array of objects that contain the TransportUnit, the LoadUnit and available quantity of the Product.

POST /allocation/transport-units HTTP/1.1
Content-Type: application/json
Content-Length: 183
Host: localhost:8080

{
  "sku" : "ZS0002030",
  "qty" : {
    "@class" : "org.openwms.core.units.api.Piece",
    "unitType" : [ "org.openwms.core.units.api.PieceUnit", "PC" ],
    "magnitude" : 1000
  }
}

The server responds with an array:

HTTP/1.1 200 OK
Content-Type: application/json
Content-Length: 360

[ {
  "transportUnitBK" : "00000000000000004711",
  "loadUnitPosition" : "1",
  "sku" : "ZS0002030",
  "actualErpCode" : "EXTERN",
  "qtyAllocated" : {
    "@class" : "org.openwms.core.units.api.Piece",
    "unitType" : [ "org.openwms.core.units.api.PieceUnit", "PC" ],
    "magnitude" : 1000
  },
  "reservationId" : "b4cebbaf-0495-4eda-ac7f-9136e115c805"
} ]

LoadUnit

A LoadUnit is the thing that actually carries an amount of Products. This is done with the abstraction of PackagingUnits so that a LoadUnit carries one or more PackagingUnits where each of those encapsulate the amount of a Product. A LoadUnit can either be a virtual separation of a TransportUnit, a separated area on top of the TransportUnit or even a physical box on the TransportUnit.

LoadUnit Index (lu-index)

The index with all possible operations on LoadUnits can be retrieved with an GET request to the LoadUnits resource:

GET /v1/load-units/index HTTP/1.1
Host: localhost:8080

The response lists all the operations with a name and the corresponding href link:

HTTP/1.1 200 OK
Content-Type: application/hal+json
Content-Length: 577

{
  "_links" : {
    "lu-divide" : {
      "href" : "http://localhost:8080/v1/transport-unit?transportUnitBK=%7BtransportUnitBK%7D&loadUnitType=%7BloadUnitType%7D&parts=4",
      "type" : "POST"
    },
    "lu-findbypkey" : {
      "href" : "http://localhost:8080/v1/load-units/%7BpKey%7D",
      "type" : "GET"
    },
    "lu-findpuinlu" : {
      "href" : "http://localhost:8080/v1/load-units/%7BpKey%7D/packaging-units",
      "type" : "GET"
    },
    "lu-putproductinto" : {
      "href" : "http://localhost:8080/v1/load-units/%7BpKey%7D",
      "type" : "PUT"
    }
  }
}

Divide a TransportUnit into multiple LoadUnits (lu-divide)

An existing TransportUnit can be split or divided into multiple LoadUnits in the simplest way by just giving the number of LoadUnits to create on top of the TransportUnit and the type of LoadUnit.

POST /v1/transport-unit HTTP/1.1
Host: localhost:8080
Content-Type: application/x-www-form-urlencoded

transportUnitBK=00000000000000004712&loadUnitType=EURO&parts=2

If the server has fulfilled the operation successfully the response is:

HTTP/1.1 201 Created

If the server could not process the request successfully because the TransportUnit is already divided into multiple LoadUnits the response states this:

HTTP/1.1 409 Conflict
Content-Type: application/hal+json
Content-Length: 267

{
  "message" : "The TransportUnit with the Barcode [00000000000000004711] is already divided, try to add other LoadUnits instead",
  "messageKey" : "owms.wms.inv.tu.alreadyDivided",
  "obj" : [ "00000000000000004711" ],
  "httpStatus" : "409",
  "class" : "String"
}

Find LoadUnit by persistent key (lu-findbypkey)

A client can lookup a LoadUnit by its persistent key. Therefore a GET request to the resource is required:

GET /v1/load-units/1009 HTTP/1.1
Host: localhost:8080

If the server can identify the resource it is returned in the response body:

HTTP/1.1 200 OK
Content-Type: application/hal+json
Content-Length: 1012

{
  "_links" : {
    "packaging-units" : {
      "href" : "http://localhost:8080/v1/load-units/1009/packaging-units"
    }
  },
  "ol" : 0,
  "pKey" : "1009",
  "transportUnitBK" : "00000000000000004720",
  "physicalPosition" : "1",
  "label" : "ID_1009",
  "type" : "EURO",
  "locked" : false,
  "product" : {
    "pKey" : "1",
    "sku" : "ZS0002029",
    "label" : "221156456666",
    "accountId" : "GM",
    "baseUnit" : {
      "@class" : "org.openwms.core.units.api.Piece",
      "unitType" : [ "org.openwms.core.units.api.PieceUnit", "PC" ],
      "magnitude" : 1
    },
    "description" : "LiPo battery 12V 4400mAh",
    "availabilityState" : "AVAILABLE",
    "classification" : "Hazardous",
    "group" : "Internal Goods",
    "stockZone" : "A",
    "dimension" : {
      "height" : 50,
      "length" : 146,
      "width" : 25,
      "uom" : "MM"
    },
    "details" : {
      "fixed_supplier_id" : "GM_US"
    }
  },
  "dimension" : {
    "height" : 144,
    "length" : 1200,
    "width" : 800
  }
}
Path Type Description

pKey

String

The persistent unique key

transportUnitBK

String

The business key of the TransportUnit

physicalPosition

String

The position where the LoadUnit is physically located on the TransportUnit

label

String

An identifying label of the LoadUnit

type

String

The type of the LoadUnit

locked

Boolean

Whether the LoadUnit is locked for allocation or not

product

Object

The Product that the LoadUnit contains

dimension

Object

The current dimension of the LoadUnit

dimension.height

Number

The current height of the LoadUnit

dimension.width

Number

The current width of the LoadUnit

dimension.length

Number

The current length of the LoadUnit

_links

Object

An array with hyperlinks to corresponding resources

_links.packaging-units

Object

Hyperlink to the PackagingUnits contained in the LoadUnit

If no LoadUnit with that persistent key exists a 404-NOT FOUND is returned.

HTTP/1.1 404 Not Found
Content-Type: application/hal+json
Content-Length: 201

{
  "message" : "LoadUnit with persistent identifier [UNKNOWN] does not exist",
  "messageKey" : "owms.wms.inv.lu.pKeyNotExists",
  "obj" : [ "UNKNOWN" ],
  "httpStatus" : "404",
  "class" : "String"
}

Find PackagingUnits in LoadUnit (lu-findpuinlu)

To find all PackagingUnits in a LoadUnit a client must send a GET request to the identified LoadUnit resource:

GET /v1/load-units/1009/packaging-units HTTP/1.1
Host: localhost:8080

If the server can identify the resource it is returned in the response body:

HTTP/1.1 200 OK
Content-Type: application/json
Content-Length: 1252

[ {
  "product" : {
    "ol" : 0,
    "overbookingAllowed" : true,
    "availabilityState" : "AVAILABLE",
    "details" : {
      "fixed_supplier_id" : "GM_US"
    }
  },
  "quantity" : {
    "@class" : "org.openwms.core.units.api.Piece",
    "unitType" : [ "org.openwms.core.units.api.PieceUnit", "PC" ],
    "magnitude" : 1000
  },
  "ol" : 0,
  "pKey" : "1009",
  "serialNumber" : "XY00A1F8ED49",
  "state" : "AVAILABLE",
  "loadUnit" : {
    "ol" : 0,
    "pKey" : "1009",
    "transportUnitBK" : "00000000000000004720",
    "physicalPosition" : "1",
    "label" : "ID_1009",
    "type" : "EURO",
    "locked" : false,
    "product" : {
      "ol" : 0,
      "overbookingAllowed" : true,
      "availabilityState" : "AVAILABLE",
      "details" : {
        "fixed_supplier_id" : "GM_US"
      }
    },
    "dimension" : {
      "height" : 144,
      "length" : 1200,
      "width" : 800
    }
  },
  "dimension" : {
    "height" : 10,
    "length" : 15,
    "width" : 12
  },
  "weight" : {
    "@class" : "org.openwms.core.units.api.Weight",
    "unitType" : [ "org.openwms.core.units.api.WeightUnit", "G" ],
    "magnitude" : 400
  },
  "distribution" : {
    "piecesPerLayer" : 5333,
    "numberOfLayers" : 14,
    "carrierType" : "EURO"
  }
} ]

Reserve a LoadUnit for a Product (lu-put-product)

LoadUnits may contain different types of Products or are limited to carry only one type of Product - this is a matter of configuration. To assign or reserve a LoadUnit to a specific type of Product a client can send a POST request to enforce this assignment. If the system is configured in the way that only same Products are allowed on LoadUnits, the server may reject the request in case the LoadUnit is already assigned to or carries PackagingUnits of a different type.

A client request to ask for a Product assignment is a PUT request that refers to the LoadUnit and contains the product data in the request body:

PUT /v1/load-units/1000 HTTP/1.1
Content-Type: application/json
Content-Length: 185
Host: localhost:8080

{
  "sku" : "ZS0002029",
  "baseUnit" : {
    "@class" : "org.openwms.core.units.api.Piece",
    "unitType" : [ "org.openwms.core.units.api.PieceUnit", "PC" ],
    "magnitude" : 1
  }
}

If the server has successfully assigned the Product to the LoadUnit the response looks like:

HTTP/1.1 200 OK

If the request could not been processed successfully because the server denied the assignment, the response looks like:

HTTP/1.1 400 Bad Request
Content-Type: application/hal+json
Content-Length: 250

{
  "message" : "The LoadUnit [1001] has already a Product [ZS0002029] assigned and cannot be loaded a second time",
  "messageKey" : "owms.wms.inv.lu.alreadyAssigned",
  "obj" : [ "1001", "ZS0002029" ],
  "httpStatus" : "400",
  "class" : "String"
}

PackagingUnit

A PackagingUnit represents an amount of a Product. This is a physical pack of some amount of an article, like a pack of 100 screws or 1 gallon of motor oil. Using PackagingUnits in warehouses is a benefit, even there is this extra resource that needs to be managed. A simple warehouse could also be designed only with LoadUnits on TransportUnits without PackagingUnits but in most projects it makes sense to have an amount of PackagingUnits within a LoadUnit and perhaps multiple LoadUnits on top of a TransportUnit.

PackagingUnit Index (packaging-unit-index)

The index with all possible operations on PackagingUnits can be retrieved with an GET request to the root resource:

GET /v1/packaging-units/index HTTP/1.1
Host: localhost:8080

The response lists all the operations with a name and the corresponding href link:

HTTP/1.1 200 OK
Content-Type: application/hal+json
Content-Length: 2448

{
  "_links" : {
    "packaging-units-create" : {
      "href" : "http://localhost:8080/v1/transport-units/%7BtransportUnitBK%7D/load-units/%7BluPos%7D/packaging-units?loadUnitType=%7BloadUnitType%7D",
      "type" : "POST"
    },
    "packaging-units-createonlocation" : {
      "href" : "http://localhost:8080/v1/packaging-units",
      "type" : "POST"
    },
    "packaging-units-deleteonlocation" : {
      "href" : "http://localhost:8080/v1/packaging-units",
      "type" : "DELETE"
    },
    "packaging-units-findbypkey" : {
      "href" : "http://localhost:8080/v1/packaging-units/%7BpKey%7D",
      "type" : "GET"
    },
    "packaging-units-findforproduct" : {
      "href" : "http://localhost:8080/v1/packaging-units?sku=%7Bsku%7D&amount=%7Bamount%7D&sortDirection=%7Basc%7D&sortProperty=%7BcreateDt%7D",
      "type" : "GET"
    },
    "packaging-units-findforproductinlg" : {
      "href" : "http://localhost:8080/v1/packaging-units?productPKey=%7BproductPKey%7D&locationGroupName=%7BlocationGroupName%7D&sortDirection=%7Basc%7D&sortProperty=%7BcreateDt%7D",
      "type" : "GET"
    },
    "packaging-units-findontu" : {
      "href" : "http://localhost:8080/v1/transport-units/%7BtransportUnitBK%7D/load-units/packaging-units",
      "type" : "GET"
    },
    "packaging-units-findontuandlu" : {
      "href" : "http://localhost:8080/v1/transport-units/%7BtransportUnitBK%7D/load-units/%7BluPos%7D/packaging-units",
      "type" : "GET"
    },
    "packaging-units-movebetweenlocations" : {
      "href" : "http://localhost:8080/v1/packaging-units/move-between-locations",
      "type" : "PUT"
    },
    "packaging-units-movefromlocationtoloadunit" : {
      "href" : "http://localhost:8080/v1/packaging-units/move-to-load-unit",
      "type" : "PUT"
    },
    "packaging-units-movepuquantity" : {
      "href" : "http://localhost:8080/v1/transport-units/%7BtransportUnitBK%7D/load-units/%7BluPos%7D/packaging-units",
      "type" : "PUT"
    },
    "packaging-units-releasepu" : {
      "href" : "http://localhost:8080/v1/packaging-units/%7BpKey%7D/release",
      "type" : "POST"
    },
    "packaging-units-reportproblemforpuinlu" : {
      "href" : "http://localhost:8080/v1/transport-units/%7BtransportUnitBK%7D/load-units/%7BluPos%7D/packaging-units/failures",
      "type" : "POST"
    },
    "packaging-units-update" : {
      "href" : "http://localhost:8080/v1/packaging-units/%7BpKey%7D",
      "type" : "PUT"
    }
  }
}

Create a new PackagingUnit (packaging-units-create)

A PackagingUnit can be created within an existing LoadUnit on a TransportUnit. Therefore a client sends a POST request with the identifying information for the LoadUnit and the required PackagingUnit as part of the request body to the server:

POST /v1/transport-units/00000000000000004711/load-units/1/packaging-units HTTP/1.1
Content-Type: application/json
Content-Length: 254
Host: localhost:8080

{
  "packagingUnits" : [ {
    "product" : {
      "sku" : "ZS0002029"
    },
    "quantity" : {
      "@class" : "org.openwms.core.units.api.Piece",
      "unitType" : [ "org.openwms.core.units.api.PieceUnit", "PC" ],
      "magnitude" : 1
    }
  } ]
}
Path Type Description

packagingUnits[0].product

Object

The Product the PackagingUnit consists of

packagingUnits[0].product.sku

String

The Product unique business key combined with the base unit

packagingUnits[0].quantity

Object

The amount of product items contained in the PackagingUnit

If the server has created the PackagingUnit successfully a 201-CREATED is returned with a LOCATION header to the new resource (see Find a PackagingUnit by persistent key (packaging-units-findbypkey)):

HTTP/1.1 201 Created

It is also possible to create a PackagingUnit in a LoadUnit that does not exist so far. In this case the LoadUnit is created, too. The request looks similar to the one above but with the identifier of the new LoadUnit to create and the additional required parameter loadUnitType:

POST /v1/transport-units/00000000000000004711/load-units/3/packaging-units?loadUnitType=EURO HTTP/1.1
Content-Type: application/json
Content-Length: 254
Host: localhost:8080

{
  "packagingUnits" : [ {
    "product" : {
      "sku" : "ZS0002029"
    },
    "quantity" : {
      "@class" : "org.openwms.core.units.api.Piece",
      "unitType" : [ "org.openwms.core.units.api.PieceUnit", "PC" ],
      "magnitude" : 1
    }
  } ]
}

The server successfully responds with:

HTTP/1.1 201 Created

If the loadUnitType is not set and the LoadUnit does not already exist, the server can’t create the LoadUnit and returns an error:

HTTP/1.1 400 Bad Request
Content-Type: application/hal+json
Content-Length: 255

{
  "message" : "LoadUnit [4] on TransportUnit [4711] does not exist and must be created but no LoadUnitType has been given",
  "messageKey" : "owms.wms.inv.pu.loadUnitTypeMissing",
  "obj" : [ "4", "4711" ],
  "httpStatus" : "400",
  "class" : "String"
}

Create a new PackagingUnit on a Location (packaging-units-createonlocation)

Instead of creating a PackagingUnit directly in a LoadUnit it is also possible to create it on some Location without a reference to a LoadUnit or a TransportUnit. This is often useful when material is directly put on Locations without carriers. To do so a client sends a POST request to the PackagingUnits resource with the representation of the PackagingUnit in the request body:

POST /v1/packaging-units HTTP/1.1
Content-Type: application/json
Content-Length: 300
Host: localhost:8080

{
  "product" : {
    "sku" : "ZS0002029"
  },
  "quantity" : {
    "@class" : "org.openwms.core.units.api.Piece",
    "unitType" : [ "org.openwms.core.units.api.PieceUnit", "PC" ],
    "magnitude" : 1
  },
  "actualLocation" : {
    "links" : [ ],
    "locationId" : "EXT_/0000/0000/0000/0000"
  }
}
Path Type Description

product

Object

The Product the PackagingUnit consists of

product.sku

String

The Product unique business key combined with the base unit

quantity

Object

The amount of product items contained in the PackagingUnit

actualLocation

Object

The actual Location where the PackagingUnit is created on

actualLocation.locationId

String

The Location identifier

If the PackagingUnit has been created successfully, the server responds with the URI to the new resource in the header:

HTTP/1.1 201 Created
Location: http://localhost:8080/v1/packaging-units/740259dc-3617-487c-a2c9-dc808bbb66d9

Find a PackagingUnit by persistent key (packaging-units-findbypkey)

A PackagingUnit can be looked up with a GET request and its unique persistent key.

GET /v1/packaging-units/1000 HTTP/1.1
Host: localhost:8080

If the PackagingUnit exists the server responds with a 200-OK and the resource in the response body. If no PackagingUnit with that key exists the server responds with a 404-NOT FOUND.

HTTP/1.1 200 OK
Content-Type: application/hal+json
Content-Length: 993

{
  "product" : {
    "pKey" : "2",
    "sku" : "ZS0002030",
    "baseUnit" : {
      "@class" : "org.openwms.core.units.api.Piece",
      "unitType" : [ "org.openwms.core.units.api.PieceUnit", "PC" ],
      "magnitude" : 1
    },
    "stockZone" : "A"
  },
  "quantity" : {
    "@class" : "org.openwms.core.units.api.Piece",
    "unitType" : [ "org.openwms.core.units.api.PieceUnit", "PC" ],
    "magnitude" : 1000
  },
  "ol" : 0,
  "pKey" : "1000",
  "serialNumber" : "XY00A1F8ED40",
  "expiresAt" : "2023-08-21T16:15:59Z",
  "state" : "AVAILABLE",
  "loadUnit" : {
    "ol" : 0,
    "pKey" : "1000",
    "transportUnitBK" : "00000000000000004711",
    "physicalPosition" : "1",
    "label" : "ID_1000",
    "type" : "EURO",
    "locked" : false
  },
  "dimension" : {
    "height" : 10,
    "length" : 15,
    "width" : 12
  },
  "weight" : {
    "@class" : "org.openwms.core.units.api.Weight",
    "unitType" : [ "org.openwms.core.units.api.WeightUnit", "G" ],
    "magnitude" : 400
  }
}
Path Type Description

pKey

String

The persistent identifier of the PackingUnit

state

String

The availability state of the PackingUnit

product

Object

The Product the PackagingUnit consists of

product.pKey

String

The persistent identifier of the Product

product.sku

String

The Product unique business key combined with the base unit

product.baseUnit

Object

The Products defined base unit. A Product could have different base units for the same SKU

product.stockZone

String

Where this product has to be placed in stock

loadUnit

Object

The comprising LoadUnit the PackagingUnit is stored in.

quantity

Object

The amount of product items contained in the PackagingUnit

dimension

Object

The actual physical dimension of the PackagingUnit

dimension.width

Number

The actual physical width of the PackagingUnit

dimension.height

Number

The actual physical height of the PackagingUnit

dimension.length

Number

The actual physical length of the PackagingUnit

serialNumber

String

(Optional) An unique serialnumber

expiresAt

String

(Optional) The expiration date

HTTP/1.1 404 Not Found
Content-Type: application/hal+json
Content-Length: 206

{
  "message" : "PackagingUnit with persistent identifier [UNKNOWN] does not exist",
  "messageKey" : "owms.wms.inv.pu.pKeyNotExists",
  "obj" : [ "UNKNOWN" ],
  "httpStatus" : "404",
  "class" : "String"
}

Find all PackagingUnits on a TransportUnit (packaging-units-findontu)

To find all PackagingUnits in all LoadUnits that are currently placed on a particular TransportUnit, a client needs to query for the secondary resources of the TransportUnitLoadUnitPackagingUnit.

GET /v1/transport-units/00000000000000004711/load-units/packaging-units HTTP/1.1
Accept: application/vnd.openwms.packaging-unit-v1+json
Host: localhost:8080

If one or more PackagingUnits exist on LoadUnits on top of the TransportUnit the server responds with an array of. In this case the client requested a representation of application/vnd.openwms.packaging-unit-v1+json, that is responded:

HTTP/1.1 200 OK
Content-Type: application/vnd.openwms.packaging-unit-v1+json
Content-Length: 2432

[ {
  "product" : {
    "sku" : "ZS0002030",
    "baseUnit" : {
      "@class" : "org.openwms.core.units.api.Piece",
      "unitType" : [ "org.openwms.core.units.api.PieceUnit", "PC" ],
      "magnitude" : 1
    }
  },
  "quantity" : {
    "@class" : "org.openwms.core.units.api.Piece",
    "unitType" : [ "org.openwms.core.units.api.PieceUnit", "PC" ],
    "magnitude" : 1000
  },
  "links" : [ {
    "rel" : "loadUnit",
    "href" : "http://localhost:8080/v1/load-units/1000"
  }, {
    "rel" : "transportUnit",
    "href" : "http://localhost:8080/v1/transport-units/1000"
  }, {
    "rel" : "product",
    "href" : "http://localhost:8080/v1/products/2"
  } ],
  "ol" : 0,
  "pKey" : "1000",
  "serialNumber" : "XY00A1F8ED40",
  "expiresAt" : "2023-08-21T16:16:01Z",
  "state" : "AVAILABLE",
  "loadUnit" : {
    "ol" : 0,
    "pKey" : "1000",
    "transportUnitBK" : "00000000000000004711",
    "physicalPosition" : "1",
    "label" : "ID_1000",
    "type" : "EURO",
    "locked" : false
  },
  "dimension" : {
    "height" : 10,
    "length" : 15,
    "width" : 12
  },
  "weight" : {
    "@class" : "org.openwms.core.units.api.Weight",
    "unitType" : [ "org.openwms.core.units.api.WeightUnit", "G" ],
    "magnitude" : 400
  }
}, {
  "product" : {
    "sku" : "ZS0002030",
    "baseUnit" : {
      "@class" : "org.openwms.core.units.api.Piece",
      "unitType" : [ "org.openwms.core.units.api.PieceUnit", "PC" ],
      "magnitude" : 1
    }
  },
  "quantity" : {
    "@class" : "org.openwms.core.units.api.Piece",
    "unitType" : [ "org.openwms.core.units.api.PieceUnit", "PC" ],
    "magnitude" : 1000
  },
  "links" : [ {
    "rel" : "loadUnit",
    "href" : "http://localhost:8080/v1/load-units/1000"
  }, {
    "rel" : "transportUnit",
    "href" : "http://localhost:8080/v1/transport-units/1000"
  }, {
    "rel" : "product",
    "href" : "http://localhost:8080/v1/products/2"
  } ],
  "ol" : 0,
  "pKey" : "1001",
  "serialNumber" : "XY00A1F8ED41",
  "state" : "AVAILABLE",
  "loadUnit" : {
    "ol" : 0,
    "pKey" : "1000",
    "transportUnitBK" : "00000000000000004711",
    "physicalPosition" : "1",
    "label" : "ID_1000",
    "type" : "EURO",
    "locked" : false
  },
  "dimension" : {
    "height" : 10,
    "length" : 15,
    "width" : 12
  },
  "weight" : {
    "@class" : "org.openwms.core.units.api.Weight",
    "unitType" : [ "org.openwms.core.units.api.WeightUnit", "G" ],
    "magnitude" : 400
  }
} ]

Find PackagingUnits of a Product (packaging-units-findforproduct)

A client might want to find PackagingUnits on a TransportUnit that are available and not already allocated by any orders or tasks in order to reserve them for allocation. Therefore a client sends a GET request with the TransportUnit’s identifier and the Product SKU to search for. The client may also limit the number of returned values by giving an amount parameter and a sort direction.

The request to the server may look like this:

GET /v1/packaging-units?sku=ZS0002029&amount=10&sortDirection=desc&sortProperty=createDt HTTP/1.1
Accept: application/vnd.openwms.packaging-unit-v1+json
Host: localhost:8080

The server responds with a list of entities currently not blocked in allocation:

HTTP/1.1 200 OK
Content-Type: application/vnd.openwms.packaging-unit-v1+json
Content-Length: 5077

[ {
  "product" : {
    "sku" : "ZS0002029",
    "label" : "221156456666",
    "baseUnit" : {
      "@class" : "org.openwms.core.units.api.Piece",
      "unitType" : [ "org.openwms.core.units.api.PieceUnit", "PC" ],
      "magnitude" : 1
    }
  },
  "quantity" : {
    "@class" : "org.openwms.core.units.api.Piece",
    "unitType" : [ "org.openwms.core.units.api.PieceUnit", "PC" ],
    "magnitude" : 1000
  },
  "links" : [ {
    "rel" : "loadUnit",
    "href" : "http://localhost:8080/v1/load-units/1008"
  }, {
    "rel" : "transportUnit",
    "href" : "http://localhost:8080/v1/transport-units/1008"
  }, {
    "rel" : "product",
    "href" : "http://localhost:8080/v1/products/1"
  } ],
  "ol" : 0,
  "pKey" : "1008",
  "serialNumber" : "XY00A1F8ED48",
  "state" : "AVAILABLE",
  "loadUnit" : {
    "ol" : 0,
    "pKey" : "1008",
    "transportUnitBK" : "00000000000000004719",
    "physicalPosition" : "1",
    "label" : "ID_1008",
    "type" : "EURO",
    "locked" : false,
    "product" : {
      "pKey" : "1",
      "sku" : "ZS0002029",
      "label" : "221156456666",
      "accountId" : "GM",
      "baseUnit" : {
        "@class" : "org.openwms.core.units.api.Piece",
        "unitType" : [ "org.openwms.core.units.api.PieceUnit", "PC" ],
        "magnitude" : 1
      },
      "description" : "LiPo battery 12V 4400mAh",
      "availabilityState" : "AVAILABLE",
      "classification" : "Hazardous",
      "group" : "Internal Goods",
      "stockZone" : "A",
      "dimension" : {
        "height" : 50,
        "length" : 146,
        "width" : 25,
        "uom" : "MM"
      },
      "details" : {
        "fixed_supplier_id" : "GM_US"
      }
    }
  },
  "dimension" : {
    "height" : 10,
    "length" : 15,
    "width" : 12
  },
  "weight" : {
    "@class" : "org.openwms.core.units.api.Weight",
    "unitType" : [ "org.openwms.core.units.api.WeightUnit", "G" ],
    "magnitude" : 400
  }
}, {
  "product" : {
    "sku" : "ZS0002029",
    "label" : "221156456666",
    "baseUnit" : {
      "@class" : "org.openwms.core.units.api.Piece",
      "unitType" : [ "org.openwms.core.units.api.PieceUnit", "PC" ],
      "magnitude" : 1
    }
  },
  "quantity" : {
    "@class" : "org.openwms.core.units.api.Piece",
    "unitType" : [ "org.openwms.core.units.api.PieceUnit", "PC" ],
    "magnitude" : 1000
  },
  "links" : [ {
    "rel" : "loadUnit",
    "href" : "http://localhost:8080/v1/load-units/1009"
  }, {
    "rel" : "transportUnit",
    "href" : "http://localhost:8080/v1/transport-units/1009"
  }, {
    "rel" : "product",
    "href" : "http://localhost:8080/v1/products/1"
  } ],
  "ol" : 0,
  "pKey" : "1009",
  "serialNumber" : "XY00A1F8ED49",
  "state" : "AVAILABLE",
  "loadUnit" : {
    "ol" : 0,
    "pKey" : "1009",
    "transportUnitBK" : "00000000000000004720",
    "physicalPosition" : "1",
    "label" : "ID_1009",
    "type" : "EURO",
    "locked" : false,
    "product" : {
      "pKey" : "1",
      "sku" : "ZS0002029",
      "label" : "221156456666",
      "accountId" : "GM",
      "baseUnit" : {
        "@class" : "org.openwms.core.units.api.Piece",
        "unitType" : [ "org.openwms.core.units.api.PieceUnit", "PC" ],
        "magnitude" : 1
      },
      "description" : "LiPo battery 12V 4400mAh",
      "availabilityState" : "AVAILABLE",
      "classification" : "Hazardous",
      "group" : "Internal Goods",
      "stockZone" : "A",
      "dimension" : {
        "height" : 50,
        "length" : 146,
        "width" : 25,
        "uom" : "MM"
      },
      "details" : {
        "fixed_supplier_id" : "GM_US"
      }
    },
    "dimension" : {
      "height" : 144,
      "length" : 1200,
      "width" : 800
    }
  },
  "dimension" : {
    "height" : 10,
    "length" : 15,
    "width" : 12
  },
  "weight" : {
    "@class" : "org.openwms.core.units.api.Weight",
    "unitType" : [ "org.openwms.core.units.api.WeightUnit", "G" ],
    "magnitude" : 400
  }
}, {
  "product" : {
    "sku" : "ZS0002029",
    "label" : "221156456666",
    "baseUnit" : {
      "@class" : "org.openwms.core.units.api.Piece",
      "unitType" : [ "org.openwms.core.units.api.PieceUnit", "PC" ],
      "magnitude" : 1
    }
  },
  "quantity" : {
    "@class" : "org.openwms.core.units.api.Piece",
    "unitType" : [ "org.openwms.core.units.api.PieceUnit", "PC" ],
    "magnitude" : 1000
  },
  "links" : [ {
    "rel" : "product",
    "href" : "http://localhost:8080/v1/products/1"
  } ],
  "ol" : 0,
  "pKey" : "1010",
  "serialNumber" : "XY00A1F8ED50",
  "state" : "AVAILABLE",
  "actualLocation" : {
    "links" : [ ],
    "pKey" : "1009",
    "locationId" : "PL__/0003/0001/0001/0001",
    "locationGroupName" : "AISLE2",
    "incomingActive" : true,
    "outgoingActive" : false,
    "plcState" : 0,
    "erpCode" : "PL03010101",
    "description" : "Pickplatz",
    "noMaxTransportUnits" : 10
  },
  "dimension" : {
    "height" : 10,
    "length" : 15,
    "width" : 12
  },
  "weight" : {
    "@class" : "org.openwms.core.units.api.Weight",
    "unitType" : [ "org.openwms.core.units.api.WeightUnit", "G" ],
    "magnitude" : 400
  }
} ]

Find available PackagingUnits in a LocationGroup (packaging-units-findforproductinlg)

To search for PackagingUnits of a given Product within a particular LocationGroup a client could send a GET request to the PackagingUnits resource with the product to search for and the name of the LocationGroup as request parameter. This is often useful to search for available material in a warehouse.

The request to the server may look like this:

GET /v1/packaging-units?productPKey=2&locationGroupName=AISLE1&sortDirection=desc&sortProperty=createDt HTTP/1.1
Accept: application/vnd.openwms.packaging-unit-v1+json
Host: localhost:8080
Parameter Description

productPKey

The persistent identifier of the Product

locationGroupName

The unique name of the LocationGroup

sortDirection

Either ASC or DESC

sortProperty

The property name to sort for

The server responds with a list of entities currently available for allocation and transportation:

HTTP/1.1 200 OK
Content-Type: application/vnd.openwms.packaging-unit-v1+json
Content-Length: 5642

[ {
  "product" : {
    "sku" : "ZS0002030",
    "baseUnit" : {
      "@class" : "org.openwms.core.units.api.Piece",
      "unitType" : [ "org.openwms.core.units.api.PieceUnit", "PC" ],
      "magnitude" : 1
    }
  },
  "quantity" : {
    "@class" : "org.openwms.core.units.api.Piece",
    "unitType" : [ "org.openwms.core.units.api.PieceUnit", "PC" ],
    "magnitude" : 1000
  },
  "links" : [ {
    "rel" : "loadUnit",
    "href" : "http://localhost:8080/v1/load-units/1002"
  }, {
    "rel" : "transportUnit",
    "href" : "http://localhost:8080/v1/transport-units/1002"
  }, {
    "rel" : "product",
    "href" : "http://localhost:8080/v1/products/2"
  } ],
  "ol" : 0,
  "pKey" : "1002",
  "serialNumber" : "XY00A1F8ED42",
  "state" : "AVAILABLE",
  "loadUnit" : {
    "ol" : 0,
    "pKey" : "1002",
    "transportUnitBK" : "00000000000000004713",
    "physicalPosition" : "1",
    "label" : "ID_1002",
    "type" : "EURO",
    "locked" : false,
    "product" : {
      "pKey" : "1",
      "sku" : "ZS0002029",
      "label" : "221156456666",
      "accountId" : "GM",
      "baseUnit" : {
        "@class" : "org.openwms.core.units.api.Piece",
        "unitType" : [ "org.openwms.core.units.api.PieceUnit", "PC" ],
        "magnitude" : 1
      },
      "description" : "LiPo battery 12V 4400mAh",
      "availabilityState" : "AVAILABLE",
      "classification" : "Hazardous",
      "group" : "Internal Goods",
      "stockZone" : "A",
      "dimension" : {
        "height" : 50,
        "length" : 146,
        "width" : 25,
        "uom" : "MM"
      },
      "details" : {
        "fixed_supplier_id" : "GM_US"
      }
    }
  },
  "dimension" : {
    "height" : 10,
    "length" : 15,
    "width" : 12
  },
  "weight" : {
    "@class" : "org.openwms.core.units.api.Weight",
    "unitType" : [ "org.openwms.core.units.api.WeightUnit", "G" ],
    "magnitude" : 400
  }
}, {
  "product" : {
    "sku" : "ZS0002030",
    "baseUnit" : {
      "@class" : "org.openwms.core.units.api.Piece",
      "unitType" : [ "org.openwms.core.units.api.PieceUnit", "PC" ],
      "magnitude" : 1
    }
  },
  "quantity" : {
    "@class" : "org.openwms.core.units.api.Piece",
    "unitType" : [ "org.openwms.core.units.api.PieceUnit", "PC" ],
    "magnitude" : 1000
  },
  "links" : [ {
    "rel" : "loadUnit",
    "href" : "http://localhost:8080/v1/load-units/1004"
  }, {
    "rel" : "transportUnit",
    "href" : "http://localhost:8080/v1/transport-units/1004"
  }, {
    "rel" : "product",
    "href" : "http://localhost:8080/v1/products/2"
  } ],
  "ol" : 0,
  "pKey" : "1004",
  "serialNumber" : "XY00A1F8ED44",
  "state" : "AVAILABLE",
  "loadUnit" : {
    "ol" : 0,
    "pKey" : "1004",
    "transportUnitBK" : "00000000000000004715",
    "physicalPosition" : "1",
    "label" : "ID_1004",
    "type" : "EURO",
    "locked" : false,
    "product" : {
      "pKey" : "1",
      "sku" : "ZS0002029",
      "label" : "221156456666",
      "accountId" : "GM",
      "baseUnit" : {
        "@class" : "org.openwms.core.units.api.Piece",
        "unitType" : [ "org.openwms.core.units.api.PieceUnit", "PC" ],
        "magnitude" : 1
      },
      "description" : "LiPo battery 12V 4400mAh",
      "availabilityState" : "AVAILABLE",
      "classification" : "Hazardous",
      "group" : "Internal Goods",
      "stockZone" : "A",
      "dimension" : {
        "height" : 50,
        "length" : 146,
        "width" : 25,
        "uom" : "MM"
      },
      "details" : {
        "fixed_supplier_id" : "GM_US"
      }
    }
  },
  "dimension" : {
    "height" : 10,
    "length" : 15,
    "width" : 12
  },
  "weight" : {
    "@class" : "org.openwms.core.units.api.Weight",
    "unitType" : [ "org.openwms.core.units.api.WeightUnit", "G" ],
    "magnitude" : 400
  }
}, {
  "product" : {
    "sku" : "ZS0002030",
    "baseUnit" : {
      "@class" : "org.openwms.core.units.api.Piece",
      "unitType" : [ "org.openwms.core.units.api.PieceUnit", "PC" ],
      "magnitude" : 1
    }
  },
  "quantity" : {
    "@class" : "org.openwms.core.units.api.Piece",
    "unitType" : [ "org.openwms.core.units.api.PieceUnit", "PC" ],
    "magnitude" : 1000
  },
  "links" : [ {
    "rel" : "loadUnit",
    "href" : "http://localhost:8080/v1/load-units/1005"
  }, {
    "rel" : "transportUnit",
    "href" : "http://localhost:8080/v1/transport-units/1005"
  }, {
    "rel" : "product",
    "href" : "http://localhost:8080/v1/products/2"
  } ],
  "ol" : 0,
  "pKey" : "1005",
  "serialNumber" : "XY00A1F8ED45",
  "state" : "AVAILABLE",
  "loadUnit" : {
    "ol" : 0,
    "pKey" : "1005",
    "transportUnitBK" : "00000000000000004716",
    "physicalPosition" : "1",
    "label" : "ID_1005",
    "type" : "EURO",
    "locked" : false,
    "product" : {
      "pKey" : "1",
      "sku" : "ZS0002029",
      "label" : "221156456666",
      "accountId" : "GM",
      "baseUnit" : {
        "@class" : "org.openwms.core.units.api.Piece",
        "unitType" : [ "org.openwms.core.units.api.PieceUnit", "PC" ],
        "magnitude" : 1
      },
      "description" : "LiPo battery 12V 4400mAh",
      "availabilityState" : "AVAILABLE",
      "classification" : "Hazardous",
      "group" : "Internal Goods",
      "stockZone" : "A",
      "dimension" : {
        "height" : 50,
        "length" : 146,
        "width" : 25,
        "uom" : "MM"
      },
      "details" : {
        "fixed_supplier_id" : "GM_US"
      }
    }
  },
  "dimension" : {
    "height" : 10,
    "length" : 15,
    "width" : 12
  },
  "weight" : {
    "@class" : "org.openwms.core.units.api.Weight",
    "unitType" : [ "org.openwms.core.units.api.WeightUnit", "G" ],
    "magnitude" : 400
  }
} ]

The response contains links to comprising LoadUnits and TransportUnits, because the requested resource was of type application/vnd.openwms.packaging-unit-v1+json. If the Accept header with the requested resource representation is omitted the server responds with a simple form without any links:

HTTP/1.1 200 OK
Content-Type: application/json
Content-Length: 2966

[ {
  "product" : {
    "ol" : 0,
    "overbookingAllowed" : true,
    "availabilityState" : "AVAILABLE"
  },
  "quantity" : {
    "@class" : "org.openwms.core.units.api.Piece",
    "unitType" : [ "org.openwms.core.units.api.PieceUnit", "PC" ],
    "magnitude" : 1000
  },
  "ol" : 0,
  "pKey" : "1002",
  "serialNumber" : "XY00A1F8ED42",
  "state" : "AVAILABLE",
  "loadUnit" : {
    "ol" : 0,
    "pKey" : "1002",
    "transportUnitBK" : "00000000000000004713",
    "physicalPosition" : "1",
    "label" : "ID_1002",
    "type" : "EURO",
    "locked" : false,
    "product" : {
      "ol" : 0,
      "overbookingAllowed" : true,
      "availabilityState" : "AVAILABLE",
      "details" : {
        "fixed_supplier_id" : "GM_US"
      }
    }
  },
  "dimension" : {
    "height" : 10,
    "length" : 15,
    "width" : 12
  },
  "weight" : {
    "@class" : "org.openwms.core.units.api.Weight",
    "unitType" : [ "org.openwms.core.units.api.WeightUnit", "G" ],
    "magnitude" : 400
  }
}, {
  "product" : {
    "ol" : 0,
    "overbookingAllowed" : true,
    "availabilityState" : "AVAILABLE"
  },
  "quantity" : {
    "@class" : "org.openwms.core.units.api.Piece",
    "unitType" : [ "org.openwms.core.units.api.PieceUnit", "PC" ],
    "magnitude" : 1000
  },
  "ol" : 0,
  "pKey" : "1004",
  "serialNumber" : "XY00A1F8ED44",
  "state" : "AVAILABLE",
  "loadUnit" : {
    "ol" : 0,
    "pKey" : "1004",
    "transportUnitBK" : "00000000000000004715",
    "physicalPosition" : "1",
    "label" : "ID_1004",
    "type" : "EURO",
    "locked" : false,
    "product" : {
      "ol" : 0,
      "overbookingAllowed" : true,
      "availabilityState" : "AVAILABLE",
      "details" : {
        "fixed_supplier_id" : "GM_US"
      }
    }
  },
  "dimension" : {
    "height" : 10,
    "length" : 15,
    "width" : 12
  },
  "weight" : {
    "@class" : "org.openwms.core.units.api.Weight",
    "unitType" : [ "org.openwms.core.units.api.WeightUnit", "G" ],
    "magnitude" : 400
  }
}, {
  "product" : {
    "ol" : 0,
    "overbookingAllowed" : true,
    "availabilityState" : "AVAILABLE"
  },
  "quantity" : {
    "@class" : "org.openwms.core.units.api.Piece",
    "unitType" : [ "org.openwms.core.units.api.PieceUnit", "PC" ],
    "magnitude" : 1000
  },
  "ol" : 0,
  "pKey" : "1005",
  "serialNumber" : "XY00A1F8ED45",
  "state" : "AVAILABLE",
  "loadUnit" : {
    "ol" : 0,
    "pKey" : "1005",
    "transportUnitBK" : "00000000000000004716",
    "physicalPosition" : "1",
    "label" : "ID_1005",
    "type" : "EURO",
    "locked" : false,
    "product" : {
      "ol" : 0,
      "overbookingAllowed" : true,
      "availabilityState" : "AVAILABLE",
      "details" : {
        "fixed_supplier_id" : "GM_US"
      }
    }
  },
  "dimension" : {
    "height" : 10,
    "length" : 15,
    "width" : 12
  },
  "weight" : {
    "@class" : "org.openwms.core.units.api.Weight",
    "unitType" : [ "org.openwms.core.units.api.WeightUnit", "G" ],
    "magnitude" : 400
  }
} ]

Move PackagingUnits

To update a PackagingUnit resource a PUT request is required. This update function can be used to achieve several goals.

Move a PackagingUnit from a LoadUnit to a Location (packaging-units-update) XXXX

A PackagingUnit that is currently on a LoadUnit can be moved off the LoadUnit directly to a Location. Therefore the request body must contain the actualLocation to move the PackagingUnit to. If a quantity is given in the request body, only that quantity (or less) is being moved. Existing PackagingUnits might be split into parts.

PUT /v1/packaging-units/1000 HTTP/1.1
Content-Type: application/json
Content-Length: 322
Host: localhost:8080

{
  "product" : {
    "sku" : "ZS0002030"
  },
  "quantity" : {
    "@class" : "org.openwms.core.units.api.Piece",
    "unitType" : [ "org.openwms.core.units.api.PieceUnit", "PC" ],
    "magnitude" : 1000
  },
  "pKey" : "1000",
  "actualLocation" : {
    "links" : [ ],
    "locationId" : "PL__/0001/0001/0001/0001"
  }
}

If the PackagingUnit has been moved off the LoadUnit the responds looks like:

HTTP/1.1 200 OK
Content-Type: application/hal+json
Content-Length: 1065

{
  "product" : {
    "pKey" : "2",
    "sku" : "ZS0002030",
    "baseUnit" : {
      "@class" : "org.openwms.core.units.api.Piece",
      "unitType" : [ "org.openwms.core.units.api.PieceUnit", "PC" ],
      "magnitude" : 1
    },
    "stockZone" : "A"
  },
  "quantity" : {
    "@class" : "org.openwms.core.units.api.Piece",
    "unitType" : [ "org.openwms.core.units.api.PieceUnit", "PC" ],
    "magnitude" : 1000
  },
  "ol" : 0,
  "pKey" : "1000",
  "serialNumber" : "XY00A1F8ED40",
  "expiresAt" : "2023-08-21T16:16:00Z",
  "state" : "AVAILABLE",
  "actualLocation" : {
    "pKey" : "1001",
    "locationId" : "PL__/0001/0001/0001/0001",
    "locationGroupName" : "AISLE1",
    "incomingActive" : true,
    "outgoingActive" : true,
    "plcState" : 0,
    "description" : "Pickplatz",
    "noMaxTransportUnits" : 10
  },
  "dimension" : {
    "height" : 10,
    "length" : 15,
    "width" : 12
  },
  "weight" : {
    "@class" : "org.openwms.core.units.api.Weight",
    "unitType" : [ "org.openwms.core.units.api.WeightUnit", "G" ],
    "magnitude" : 400
  }
}

Move a PackagingUnit from one LoadUnit to another LoadUnit (packaging-units-update)

A PackagingUnit can be moved from one LoadUnit to another. Therefore the request body must contain the LoadUnit to move the identified PackagingUnit to. If no quantity is given in the request body the whole PackagingUnit of the is moved. Otherwise the existing PackagingUnit might be split into parts.

PUT /v1/packaging-units/1008 HTTP/1.1
Content-Type: application/json
Content-Length: 371
Host: localhost:8080

{
  "product" : {
    "sku" : "ZS0002029"
  },
  "quantity" : {
    "@class" : "org.openwms.core.units.api.Piece",
    "unitType" : [ "org.openwms.core.units.api.PieceUnit", "PC" ],
    "magnitude" : 1000
  },
  "pKey" : "1008",
  "loadUnit" : {
    "pKey" : "1009",
    "transportUnitBK" : "00000000000000004720",
    "physicalPosition" : "1",
    "locked" : false
  }
}

If the PackagingUnit has been moved to another LoadUnit the responds looks like:

HTTP/1.1 200 OK
Content-Type: application/hal+json
Content-Length: 2109

{
  "product" : {
    "pKey" : "1",
    "sku" : "ZS0002029",
    "label" : "221156456666",
    "accountId" : "GM",
    "baseUnit" : {
      "@class" : "org.openwms.core.units.api.Piece",
      "unitType" : [ "org.openwms.core.units.api.PieceUnit", "PC" ],
      "magnitude" : 1
    },
    "description" : "LiPo battery 12V 4400mAh",
    "availabilityState" : "AVAILABLE",
    "classification" : "Hazardous",
    "group" : "Internal Goods",
    "stockZone" : "A",
    "dimension" : {
      "height" : 50,
      "length" : 146,
      "width" : 25,
      "uom" : "MM"
    },
    "details" : {
      "fixed_supplier_id" : "GM_US"
    }
  },
  "quantity" : {
    "@class" : "org.openwms.core.units.api.Piece",
    "unitType" : [ "org.openwms.core.units.api.PieceUnit", "PC" ],
    "magnitude" : 1000
  },
  "ol" : 0,
  "pKey" : "1008",
  "serialNumber" : "XY00A1F8ED48",
  "state" : "AVAILABLE",
  "loadUnit" : {
    "ol" : 0,
    "pKey" : "1009",
    "transportUnitBK" : "00000000000000004720",
    "physicalPosition" : "1",
    "label" : "ID_1009",
    "type" : "EURO",
    "locked" : false,
    "product" : {
      "pKey" : "1",
      "sku" : "ZS0002029",
      "label" : "221156456666",
      "accountId" : "GM",
      "baseUnit" : {
        "@class" : "org.openwms.core.units.api.Piece",
        "unitType" : [ "org.openwms.core.units.api.PieceUnit", "PC" ],
        "magnitude" : 1
      },
      "description" : "LiPo battery 12V 4400mAh",
      "availabilityState" : "AVAILABLE",
      "classification" : "Hazardous",
      "group" : "Internal Goods",
      "stockZone" : "A",
      "dimension" : {
        "height" : 50,
        "length" : 146,
        "width" : 25,
        "uom" : "MM"
      },
      "details" : {
        "fixed_supplier_id" : "GM_US"
      }
    },
    "dimension" : {
      "height" : 144,
      "length" : 1200,
      "width" : 800
    }
  },
  "dimension" : {
    "height" : 10,
    "length" : 15,
    "width" : 12
  },
  "weight" : {
    "@class" : "org.openwms.core.units.api.Weight",
    "unitType" : [ "org.openwms.core.units.api.WeightUnit", "G" ],
    "magnitude" : 400
  }
}

Move Quantities of a Product

Dedicated endpoints exist to move quantities of a Product between Locations, LoadUnits or between each other.

Move a Quantity from one Location to another Location (packaging-units-movebetweenlocations)

A PackagingUnits quantity can be moved from the one Location to another Location. Therefore the request body must contain the actualLocation from where to move the quantity and the targetLocation. If no quantity is given in the request body all PackagingUnits of the Product are moved. Existing PackagingUnits might be split into parts.

PUT /v1/packaging-units/move-between-locations HTTP/1.1
Content-Type: application/json
Content-Length: 396
Host: localhost:8080

{
  "product" : {
    "sku" : "ZS0002030"
  },
  "quantity" : {
    "@class" : "org.openwms.core.units.api.Piece",
    "unitType" : [ "org.openwms.core.units.api.PieceUnit", "PC" ],
    "magnitude" : 1000
  },
  "actualLocation" : {
    "links" : [ ],
    "locationId" : "EXT_/0000/0000/0000/0000"
  },
  "targetLocation" : {
    "links" : [ ],
    "locationId" : "PL__/0001/0001/0001/0001"
  }
}

If the quantity has been moved to the new Location the responds with:

HTTP/1.1 204 No Content

Move a Quantity from a Location to a LoadUnit (packaging-units-movefromlocationtoloadunit)

A PackagingUnits quantity can be moved from a Location to a LoadUnit. Therefore the request body must contain the actual Location and the identifier of the LoadUnit where to move to. If no quantity is given in the request body all PackagingUnits of the Product are moved. Existing PackagingUnits might be split into parts.

PUT /v1/packaging-units/move-to-load-unit HTTP/1.1
Content-Type: application/json
Content-Length: 372
Host: localhost:8080

{
  "product" : {
    "sku" : "ZS0002029"
  },
  "quantity" : {
    "@class" : "org.openwms.core.units.api.Piece",
    "unitType" : [ "org.openwms.core.units.api.PieceUnit", "PC" ],
    "magnitude" : 1000
  },
  "targetTransportUnitBK" : "00000000000000004711",
  "targetLoadUnitPosition" : "2",
  "actualLocation" : {
    "links" : [ ],
    "erpCode" : "PL03010101"
  }
}

If the quantity has been moved to a Location the responds looks like:

HTTP/1.1 204 No Content

Move a Quantity from one LoadUnit to another LoadUnit (packaging-units-movepuquantity)

A PackagingUnits quantity can be moved from a LoadUnit to another. Therefore the request body must contain the LoadUnit to move the PackagingUnit to. If no quantity is given in the request body all PackagingUnits of the Product are moved. Existing PackagingUnits might be split into parts.

PUT /v1/transport-units/00000000000000004711/load-units/1/packaging-units HTTP/1.1
Content-Type: application/json
Content-Length: 296
Host: localhost:8080

{
  "product" : {
    "sku" : "ZS0002030"
  },
  "quantity" : {
    "@class" : "org.openwms.core.units.api.Piece",
    "unitType" : [ "org.openwms.core.units.api.PieceUnit", "PC" ],
    "magnitude" : 1000
  },
  "targetTransportUnitBK" : "00000000000000004711",
  "targetLoadUnitPosition" : "2"
}

If the quantity has been moved to another LoadUnit the responds looks like:

HTTP/1.1 204 No Content

Move a Quantity from a LoadUnit to a Location (packaging-units-movepuquantity)

A PackagingUnits quantity can be moved from a LoadUnit to a Location. Therefore the request body must contain the Location where to move the PackagingUnits to. If no quantity is given in the request body all PackagingUnits of the Product are moved. Existing PackagingUnits might be split into parts.

PUT /v1/transport-units/00000000000000004711/load-units/1/packaging-units HTTP/1.1
Content-Type: application/json
Content-Length: 303
Host: localhost:8080

{
  "product" : {
    "sku" : "ZS0002030"
  },
  "quantity" : {
    "@class" : "org.openwms.core.units.api.Piece",
    "unitType" : [ "org.openwms.core.units.api.PieceUnit", "PC" ],
    "magnitude" : 1000
  },
  "actualLocation" : {
    "links" : [ ],
    "locationId" : "EXT_/0000/0000/0000/0000"
  }
}

If the quantity has been moved to a Location the responds looks like:

HTTP/1.1 204 No Content