Listings

Now that our facilities are added into the fulfillmenttools platform, we need to add master data (listings) for that facilities.

What are listings?

Listings are the items we offer in a facilty. Even though they are optional, they are very helpful for several functionalities, especially the dynamic order routing. For more information on the entity, please see .

Why has every facility its own listings?

An article that we offer in Lisbon might not run at all in Helsinki. That's why it makes more sense to not list that article in facilities which do not sell an item. In this tutorial the items offered are very similar. In Helsinki, LU.XY does not sell summer dresses and sandals. In Lissabon, they don't sell winter boots and parkas.

Adding listings to the facilities

After we decided which items to list in which facility, we can start to add them to the facilities. In this tutorial page, we start with the store in Frankfurt, where all items are sold. You need the ID of the facility you want to create a listing in. The ID can be received via the facility endpoint, which we used to create the facility.

For adding a listing, we send a PUT request to the listings endpoint containing a ListingsForCreation object:

curl --location --request PUT 'https://your.api.fulfillmenttools.com/api/facilities/<FACILITY-ID>/listings' \
--header 'Content-Type: application/json' \
--header 'Authorization: Bearer <TOKEN>' \
--data '{
    "listings": [
        {
            "tenantArticleId": "SNEAK-W-4891",
            "price": 119.00,
            "title": "White Sneakers",
            "imageUrl": "https://img.example.com/img/sneakw4891.jpg",
            "scannableCodes": ["738502847562", "SNEAK-W-4891"],
            "measurementUnitKey": "UNIT"
        },
        {
            "tenantArticleId": "JEANS-B-2605",
            "price": 59.95,
            "title": "Washed Slim Fit Jeans",
            "imageUrl": "https://img.example.com/img/jeansb2605.jpg",
            "scannableCodes": ["73898484754", "JEANS-B-2605"],
            "measurementUnitKey": "UNIT"
        },
        {
            "tenantArticleId": "TSHIRT-W-2468",
            "price": 19.9,
            "title": "Basic T-Shirt White",
            "imageUrl": "https://img.example.com/img/tshirtw2468.jpg",
            "scannableCodes": ["5558156789", "TSHIRT-W-2468"],
            "measurementUnitKey": "UNIT"
        },
        {
            "tenantArticleId": "COAT-C-0304",
            "price": 394.5,
            "title": "Trenchcoat cream",
            "imageUrl": "https://img.example.com/img/coatc0304.jpg",
            "scannableCodes": ["48976451328", "COAT-C-0304"],
            "measurementUnitKey": "UNIT"
        },
        {
            "tenantArticleId": "LOAFERS-B-1788",
            "price": 79.8,
            "title": "Brown Leather Loafers",
            "imageUrl": "https://img.example.com/img/loafersb1788.jpg",
            "scannableCodes": ["41986457228", "LOAFERS-B-1788"],
            "measurementUnitKey": "UNIT"
        },
        {
            "tenantArticleId": "OXFORD-W-9766",
            "price": 64.9,
            "title": "White Oxford Button Down Shirt",
            "imageUrl": "https://img.example.com/img/oxfordw9766.jpg",
            "scannableCodes": ["41986457669", "OXFORD-W-9766"],
            "measurementUnitKey": "UNIT"
        },
        {
            "tenantArticleId": "DRESS-B-5094",
            "price": 49.95,
            "title": "Blue Summer Dress",
            "imageUrl": "https://img.example.com/img/dressb5094.jpg",
            "scannableCodes": ["50986457664", "DRESS-B-5094"],
            "measurementUnitKey": "UNIT"
        },
        {
            "tenantArticleId": "BLAZER-G-6354",
            "price": 39.99,
            "title": "Green Blazer",
            "imageUrl": "https://img.example.com/img/blazerg6354.jpg",
            "scannableCodes": ["6386457654", "BLAZER-G-6354"],
            "measurementUnitKey": "UNIT"
        },
        {
            "tenantArticleId": "PANTS-G-4430",
            "price": 39.99,
            "title": "Green Pants",
            "imageUrl": "https://img.example.com/img/pants-g-4430.jpg",
            "scannableCodes": ["63864430654", "PANTS-G-4430"],
            "measurementUnitKey": "UNIT"
        },
        {
            "tenantArticleId": "TNECK-GR-3277",
            "price": 34.99,
            "title": "Grey Turtleneck Sweater With Texture",
            "imageUrl": "https://img.example.com/img/tneckgr3277.jpg",
            "scannableCodes": ["32864770654", "TNECK-GR-3277"],
            "measurementUnitKey": "UNIT"
        },
        {
            "tenantArticleId": "SANDALS-S-7318",
            "price": 69.99,
            "title": "Summer Sandals",
            "imageUrl": "https://img.example.com/img/sandalss7318.jpg",
            "scannableCodes": ["14864773654", "SANDALS-S-7318"],
            "measurementUnitKey": "UNIT"
        },
        {
            "tenantArticleId": "BOOTS-B-8971",
            "price": 109.50,
            "title": "Beige Winter Boots",
            "imageUrl": "https://img.example.com/img/bootsb8971.jpg",
            "scannableCodes": ["89764773651", "BOOTS-B-8971"],
            "measurementUnitKey": "UNIT"
        },
        {
            "tenantArticleId": "PARKA-B-8822",
            "price": 94.50,
            "title": "Black Winter Parka",
            "imageUrl": "https://img.example.com/img/parkab8822.jpg",
            "scannableCodes": ["889722773651", "PARKA-B-8822"],
            "measurementUnitKey": "UNIT"
        }
    ]
}'

The response should be an empty 200 OK response, if the request was successful. Let's have a look at the properties:

tenantArticleId: The ID the article has in your systems, must be unique.

price: The price at which the article is sold.

title: The title that article has.

imageUrl: URL where an image is found of that article, will be shown in the clients we offer.

scannableCodes: List of scannable codes for that item. Used while picking. Might be the EAN or any other barcode.

mesaurementUnitKey: Unit in which that article is count, in this case we sell hole units of garments. In the food context, that might a weighing unit like kilograms.

With the facilities and the listings being set, we can start using the orders endpoint for testing.

After you created your first facility, you can (but don't have to) add some listings (articles) for this facility.

Placeholders

PlaceholderReplace withExample

{TOKEN}

JWT from Identity provider

eyJhbGciOX49.eyJzdWV9.dyt0CoI

{facilityId}

the ID of the facility the listing is for

5d174533-29b9-464b-9325-94bfacefe335

Creating a listing with stock properties

Stock Properties allow tracking of specific values on stock. The listing defines which properties should be tracked for stocks that belong to this specific listing. Moreover, its is configurable in the listing, whether it is mandatory to track stock properties, e.g., during goods receipt and if the value is expected to be a text or date.

curl -sSL -X PUT 'https://your.api.fulfillmenttools.com/api/facilities/{facilitiyId}/listings' \
--header 'Content-Type: application/json' \
--header 'Authorization: Bearer <TOKEN>' \
--data-raw '{
    "tenantArticleId": "<your product ID>",
    "title": "<the listing title>",
    "stockProperties": {
        "<your property key>": {
            "inputType": "DATE",
            "required": true
            }
        }
    }

Creating a listing with stockAvailableUntil

In the listing it can be specified until when the corresponding stock should be available. The availableUntil value is set upon stock creation if configured in listing.

  • calculation base:Set field to EXPIRY, if stock should become unavailable before it expires. EXPIRY needs to be configured in the stockProperties before it can be used here. Set field to CREATION if stock should become unavailable some time after it was created.

  • modifier:Time span which is applied to the calculation base to calculate time point when stock should become unavailable. Use negative values to move the date backwards. Example: "-P30D" places the "availableUntil" value 30 days before the calculated date.

curl -sSL -X PUT 'https://your.api.fulfillmenttools.com/api/facilities/{facilitiyId}/listings' \
--header 'Content-Type: application/json' \
--header 'Authorization: Bearer <TOKEN>' \
--data-raw '{
    "tenantArticleId": "<your product ID>",
    "title": "<the listing title>",
    "stockAvailableUntil": {
        "calculationBase": "EXPIRY",
        "modifier": "-P30D"
      }
  }

Create a listing with measurement unit

In the fulfillmenttools platform each product (identified by one tenantArticleId in a facility) is tracked in one unit. The meaning of a unit is completely arbitrary but will commonly represent a physical unit like "g" or "kg" or for countable goods something like "pieces" or "pcs". Since each product is kept in just one measurement unit, operations like adding or moving stock do not need to validate or convert units between stocks.

Defining measurement unit keys for a listing

Units can be defined in the measurementUnitKey in the Iisting. The key that is defined will be displayed in our clients, e.g., during picking if no measurementUnit is defined for the key. It is not required to define units for products. When no unit is set in the listing, no validation will take place and our clients will default to a localized version of "pieces".

Both a missing "measurementUnitKey" field and "measurementUnitKey: null" are treated as no unit.

If you want to track one product in different units (for example as bulk by weight and also by prepackaged quantity) please create two Listings with different tenantArticleIds: "xyz-123-bulk" and "xyz-123-packaged". Any such setup should reflect the reality of the goods handling in your warehouse / facility.

curl --location --request PUT 'https://<apiHostname>/api/facilities/8f5bd918-ad32-4800-9818-54d3f4209b03/listings' \
--header 'Content-Type: application/json' \
--header 'Authorization: Bearer <authToken>' \
--data '{
    "listings": [
        {
            "tenantArticleId": "flour",
            "price": 0.8,
            "version": 1,
            "title": "Sacks of flour",
            "scannableCodes": [],
            "attributes": [],
            "measurementUnitKey": "stone"
        }
    ]
}
'

To localize the long-name and abbreviation of a unit for the client applications you can create MeasurementUnit entities corresponding to the listing.measurementUnitKey. If no MeasurementUnit is defined for a key, the key will be displayed in the apps.

curl --location 'https://<apiHostname>/api/measurementunits' \
--header 'Content-Type: application/json' \
--header 'Authorization: Bearer <authToken>' \
--data '{
    "key": "stone",
    "nameLocalized": { "de_DE": "Stone", "en_US": "Stone" },
    "abbreviationLocalized": { "de_DE": "st", "en_US": "st" },
    "requiresMeasurement": false
}'

Integration layer

We highly recommend using events on the integration layer to handle the stock topic. For example an event from the POS cashier could trigger a stock change in the fulfillmenttools platform. Furthermore, we provide an event if there is a stock change. More information can be read here.

Last updated