Inventory Setup

This section describes the rules and procedure to set up inventory as per your business needs.

General Rules:

  • If you are using a third party Product Information Management (PIM) system other than fabric’s PIM, you must provide product details to fabric in a .csv file. For details, see Update Product Information section. If you are already using fabric’s PIM to maintain product information, ignore this step.
  • To create or update inventory, required fields are sku, itemId, location, channelId, and counters. Rest all are optional and you can configure those fields based on your requirements. For details, see Create Inventory section.
    • If you are using only Inventory service provided by fabric (not the entire OMS service), you must mention allocated and shipped counter quantities to update inventory. If you are using fabric’s OMS to manage inventory and order fulfillment, allocated and shipped counter quantities will be taken care of automatically.
  • Use the “onHand” counter to represent the inventory quantity that is currently in stock for sell. As per the onHand counter value passed in the request body, availableToPurchase (the virtual-counter) quantity is calculated, based on the formula onHand- allocated- shipped- safetyStock . safetyStock is also subtracted if you include safetyStock value while creating inventory.
  • Subscribe to any of the inventory webhook events to get notification for inventory update. For sample curl and other details, see List of Webhook Events .

The following is a request/response example showing calculated virtualCounters based on the counter data provided in the request body.

Request Sample:

{
"sku": "SKU123",
"itemId": 12345,
"locationNum": 999,
"channelId": "channel1",
"safetyStock": 10
"counters": {
    "onHand": 100,
    "allocated": 20,
    "shipped": 10}
}

Response Sample:

{
"sku": "SKU123",
"itemId": 12345,
"locationNum": 999,
"channelId": "channel1",
"safetyStock": 10
"counters": {
    "onHand": 100,
    "allocated": 20,
    "shipped": 10
}
"virtualCounters": {
    "availableToPurchase": 60}
}

Create Location

API Mapping: POST/api/v2/location

Create records for your stores, with details including postal code, hours of operation, BOPIS enabled, and other custom attributes that are applicable to your business.

Request Sample:

"state": "California",
"country": "USA",
"postalCode": 92118,
"type": "2800 Ashcraft Court",
"contact"```
{
"attributes": {
"isReturns": true
"isBOPIS":true
},
"locationNum": 13,
"name": "CA",
"isActive": true,
"address": {
"addressLine1": "2800 Ashcraft Court",
"addressLine2": "Fairview road",
"addressLine3": "N 9 1/2 street",
"addressLine4": "Coronado school",
"city": "Coronado",: [
{
"type": "Residence",
"email": "mark@email.com",
"phone": [
{
"number": "555-555-5555",
"type": "mobile"
}
],
"name": {
"first": "John",
"middle": "Mark",
"last": "Doe"}
}
]
},
"type": "Warehouse",
"operatingHours": [
{
"day": "Monday",
"hours": [
{
"open": "10:00",
"close": "16:00",
"type": "OPEN"}
]
}
],
"coordinates": {
"type": "Point",
"coordinates": [
[
"-22.95239063733024",
"-43.21034257655916"]
]
}
}

Response Sample:

{
"attributes": {
"isReturns": true
“isBOPIS”: true
},
"id": "622fae9a065d9e62a4029f79",
"locationNum": 13,
"name": "CA",
"isActive": true,
"address": {
  "addressLine1": "2800 Ashcraft Court",
  "addressLine2": "Fairview road",
  "addressLine3": "N 9 1/2 street",
  "addressLine4": "Coronado school",
  "city": "Coronado",
  "state": "California",
  "country": "USA",
  "postalCode": 92118,
  "type": "2800 Ashcraft Court",
  "contact": [
{
"type": "Residence",
"email": "mark@email.com",
"phone": [
{
"number": "555-555-5555",
"type": "mobile"
}
],
"name": {
"first": "John",
"middle": "Mark",
"last": "Doe"}}
]
},
"type": "warehouse",
"createdAt": "2019-08-24T14:15:22Z",
"updatedAt": "2019-08-24T14:15:22Z",
"operatingHours": [
{
"day": "Monday",
"hours": [
{
"open": "10:00",
"close": "16:00",
"type": "OPEN"
}
]
}
],
"coordinates": {
"type": "Point",
"coordinates": [
[
"-22.95239063733024",
"-43.21034257655916"]
]
}
}

Update Product Information (Optional)

Note: This step is required if you are using a product management software other than fabric's PIM. If you are using fabric's PIM to maintain your product data, this step is not required as product data will automatically be imported into the pim-connector.

API Mapping:

  • Use POST/api-pim-external/product for uploading details of a single product.
  • For more than one product update, you can mention the product details in a .csv file, and uplaod the file using the POST/api-pim-external/product/bulk-insert endpoint.

Request Sample:

{
"productSku": "NIKE237765",
"itemType": "Item",
"bundleItems": [shoe, socks ],
"title": "Nike Men's Training Shoe",
"childrenItems": [sticker, foam],
"parentSku": "NIKE2345678",
"image": "https://robohash.org/39.96.1.102.png",
"categories": [
{
"name": "Men's Shoes",
"breadcrumbs": [
{
"name": "Sports Shoes",
"level": 0,
"order": 0}]
}
],
"attributes": {
"Brand": "Nike",
"Size": "Medium"
},
"channel": 1
}

Response Sample:

{
"tenantId": "FabricInc",
"productSku": "NIKE237765",
"itemType": "Item",
"bundleItems": [shoe, socks ],
"title": "Nike Men's Training Shoe",
"childrenItems": [sticker, foam],
"parentSku": "NIKE2345678",
"image": "https://robohash.org/39.96.1.102.png",
"categories": [
{
"name": "Men's Shoes",
"breadcrumbs": [
{
"name": "Sports Shoes",
"level": 0,
"order": 0
}
]
}
],
"attributes": {
"Brand": "Nike",
"Size": "Medium"
},
"channel": 1,
"isSoftDeleted": false,
"productId": "FabricInc#NIKE237765",
"itemId": "2e6b0bdd-f03b-4994-aed1-cdf9e6568950",
"createdAt": "2021-12-13T13:56:09.006Z",
"updatedAt": "2021-12-13T13:56:09.006Z"
}

Create Network

API Mapping: POST/api/v2/inventory/network

  • Network refers to a group of locations with a group of SKUs in each location.
  • You can create a network to map inventories for the created networks. A network code is generated for the created network. You can mention the network code while creating or updating inventories for a specific network.
  • You can configure safety stock quantities for a network while creating a network. You can also configure safety stock (as well as low stock) quantities while creating or updating inventories for a specific network.

Request Sample:

{
"code": "DC",
"name": "Distribution Center",
"safetyStock": 2,
"rules": {
"locationData.attributes.channel": "Frontline",
"productData.attributes.subclass": {
"$nin": 778942701}
}}

Response Sample:

{
"networkId": "62278e49167b6079755aa5e7",
"code": "DC",
"name": "Distribution Center",
"safetyStock": 2,
“lowStock”: 0,
"rules": {
"locationData.attributes.channel": "Frontline",
"productData.attributes.subclass": {
"$nin": 778942701}
}
}

Create or Update Inventory

API Mapping:

  • PUT/api/v2/inventory/adjustment: Update inventory by increasing or decreasing counter quantity, Or Create inventory.
  • POST/api/v2/inventory/aws/upload-url: Create inventory or bulk import inventory data by uploading a .csv file. Before uploading the file, you must mention product details in the file.
  • If you want to represent an inventory in unlimited quantities, set infiniteInventory to ‘true’.
  • Use customAttributes to define any custom attributes that suit your business use case. For example, you can set BOPIS (Buy Online Pickup In Store) to true if you are willing to allow shoppers to buy online, and pick-up an item from the store (based on location number).
  • If you provide values for backOrderLimit and preOrderLimit while creating inventory, availableBackorder and availablePreorder virtual-counters are displayed in the response object with the same values as provided in the request body.
  • You can configure values for safetyStock and lowStock fields while creating or updating inventory for better inventory management.

Rules for updating counter quantity:

  • Use the “onHand” counter to represent the inventory quantity that is currently in stock for sell. Based on the onHand counter value as passed in the request body, availableToPurchase quantity is calculated based on the formula onHand-allocated-shipped , and displayed in the response object.
  • (Not required if you are using the Order module of fabric OMS) Use “allocated” counter to represent inventory that is sent to warehouses for fulfillment (only the warehouse can cancel the order at this point).
  • (Not required if you are using the Order module of fabric OMS) Use “shipped” counter to represent inventory that is marked as shipped by the warehouse (at this stage in the life-cycle the order can only be returned).
  • Use “backorderReserve” and “preOrderReserve” counters (under counter object) to represent inventory quantity that is permitted for backorder (reserve for restock) or pre-order (inventory quantity on launch date).

Request Sample:

{
  "sku": "SKU123",
  "itemId": 12345,
  "locationNum": 999,
  "channelId": "channel1",
  "vendorId": "vendor1",
 "counters": {
    "onHand": 100,
    "allocated": 20,
    "shipped": 10
  },
  "infiniteInventory": true,
  "backOrderDate": "2022-10-21T14:28:06.968Z",
  "preOrderDate": "2022-10-21T14:28:06.968Z",
  "backOrderLimit": 50,
  "preOrderLimit": 40,
  "safetyStock": 10,
  "lowStock": 0,
  "networkCode": "ShipToHome",(get inventory by network)
  "customAttributes": {
    "isRetrun": true,
    "isBopis": true
  },
  "networkCounters": {
    "softReserve": 10
  },
}

Response Sample:

{
  "sku": "SKU123",
  "itemId": 12345,
  "locationNum": 999,
  "channelId": "channel1",
  "vendorId": "vendor1",
 "counters": {
    "onHand": 100,
    "allocated": 20,
    "shipped": 10
  },
  "infiniteInventory": true,
  "backOrderDate": "2022-10-21T14:28:06.968Z",
  "preOrderDate": "2022-10-21T14:28:06.968Z",
  "backOrderLimit": 50,
  "preOrderLimit": 40,
  "safetyStock": 10,
  "lowStock": 0,
  "networkCode": "ShipToHome",(get inventory by network)
  "customAttributes": {
    "isRetrun": true,
    "isBopis": true
  },
  "networkCounters": {
    "softReserve": 10
  },
"virtualCounters": {
    "availableToPurchase": 60,
    "availableBackorder": 50,
    "availablePreorder": 40
  }
}

Query Inventory

After you successfully create an inventory, you can query for inventory on storefront or using API (GET/api/v2/inventory).

  • While querying for inventory in general, you must include SKU and network code (if you have created a network) as query parameters to obtain a response body containing numerical value in the “Available to Purchase” property.
  • While querying for inventory of type BOPIS (Buy Online Pickup In Store), you must include SKU, locationNum, and channelId to obtain a response body containing information for BOPIS.

Response Sample:

{
  "sku": "SKU123",
  "itemId": 12345,
  "locationNum": 999,
  "channelId": "channel1",
  "vendorId": "vendor1",
 "counters": {
    "onHand": 100,
    "allocated": 20,
    "shipped": 10
  },
  "infiniteInventory": true,
  "backOrderDate": "2022-10-21T14:28:06.968Z",
  "preOrderDate": "2022-10-21T14:28:06.968Z",
  "backOrderLimit": 50,
  "preOrderLimit": 40,
  "safetyStock": 10,
  "lowStock": 0,
  "networkCode": "ShipToHome",(get inventory by network)
  "customAttributes": {
    "isRetrun": true,
    "isBopis": true
  },
  "networkCounters": {
    "softReserve": 10
  },
"virtualCounters": {
    "availableToPurchase": 60,
    "availableBackorder": 50,
    "availablePreorder": 40
  }
}

Rules for Displaying Inventory for Different Counters on Product Website

  • In stock: Use onHand counter from the request body to represent inventory that is currently available in the location to sell.
  • In Stock for BOPIS (Buy Online Pickup In Store) for a SKU in a specified radius of zip code or postal code:
    • Use onHand counter to represent in-stock inventory.
    • Define BOPIS using the customAttribute field while creating or updating inventory.
    • Zip code or postal code is identified based on the location number. Location number is generated for a location for which you provide all details such as name, address, type, zip or postal code, and many more while creating the location using create location API.
  • In Stock for BOPIS in a specified store:
    • Use onHand counter to represent in-stock inventory.
    • Define BOPIS using the customAttribute field while creating or updating inventory. A specific store is identified by the location number.
  • Increment or decrement update to inventory records:
    • Use onHand counter to represent in-stock inventory.
    • Use PUT/api/v2/inventory/adjustment endpoint to send REST HTTP request to fabric Inventory for the change with the request body specifying SKU, locationNum, channel, counter quantity that is either decremented or incremented.
  • Displaying Backorder, Preorder, Safety Stock, and Low Stock on Website:
    • If availabletToPurchase value is greater than zero, then calculate if the availabletoPurchase quantity is greater than the safetyStock value.
    • If availableToPurchase quantity is greater than 0, then display the item as in-stock .
    • If availableToPurchase quantity is equal to 0 and availableBackorder is greater than 0, then display the item as in-stock-for-backorder .
    • If Available and Backorder are both out of stock, and availableToPreorder is greater than 0, then display the item as in-stock-for-preorder , else display the item as out-of-stock .
    • If the item is a Backorder or Preorder item, then display the expected restock date ("backorderDate") or expected product launch date ("preOrderDate")