Important changes on how to manage your stock

Andrew Waters profile picture Written by: Andrew Waters - Published on: 14 Feb 2018
TL;DR — we’re changing how stock is managed on your store. We may have had to make some changes to the values of your manage_stock attribute (set them to false). If you read nothing else in this post, make sure you read the “Changes to your Data” section.

If your store sells any physical products, you are probably already aware that keeping track of your current stock levels is imperative to your operation and just as importantly, it benefits your customers as you can let them know when stock may be limited.

We’ve been working hard behind the scenes on a new set of endpoints that will enable your store to manage this in a coherent fashion. Let me explain further.

When you create a new product with Moltin, you create an initial stock level using the stock attribute on your product. Whether that’s through the dashboard or via an API request, if you have created a product, you have a stock level and therefore an inventory.

After the initial creation of the product, your stock is managed using the new inventory endpoints.

We automatically create your initial stock level (based on the value you sent for the product) and you can then make a request to the inventory service for it, by calling:

  curl -X "GET" "https://api.moltin.com/v2/inventories/{PRODUCT_ID}" \
  -H "Authorization: Bearer XXXX"

In return you will receive a response similar to the following:

  {
  "data": {
    "id": "{PRODUCT_ID}",
    "type": "stock",
    "total": 100,
    "available": 100,
    "allocated": 0
  }
}

This tells us several things about the current stock status for this product. We now know we have a total of 100 items in the inventory and 100 of them are available to purchase. It also tells us that none have been allocated, and we’ll explain what that means further on.

Incrementing the Stock

So from this point, as store administrators, we can make several changes to the stock over time. We may receive another shipment of stock from a supplier and want to make that available to our customers. In that case, we will want to notify the inventories endpoints of those changes. If we’re adding stock, we’re incrementing it — note that the action value in the request is increment — so we would send a request akin to the following:

  curl -X POST https://api.moltin.com/v2/inventories/{PRODUCT_ID}/transactions \
    -H "Content-Type: application/json" \
    -H "Authorization: Bearer XXXX" \
    -d $'{
     "data": {
  "type": "stock-transaction",
  "action": "increment",
  "quantity": 50
     }
}'

Our updated stock looks like:

  {
  "data": {
    "id": "{PRODUCT_ID}",
    "type": "stock",
    "total": 150,
    "available": 150,
    "allocated": 0
  }
}

Decrementing your Stock

So now you have 150 available to sell, but you realize that when you had your latest batch of 50 stock delivered, the box was damaged and there are 5 units that you need to return to your supplier because you can’t sell them. So, you prepare the return consignment, and then let your inventory service know that you now have five fewer items available to sell:

  curl -X POST https://api.moltin.com/v2/inventories/{PRODUCT_ID}/transactions \
    -H "Content-Type: application/json" \
    -H "Authorization: Bearer XXXX" \
    -d $'{
     "data": {
  "type": "stock-transaction",
  "action": "decrement",
  "quantity": 5
     }
}'

Notice that our action is now decrement because we’re taking it out of stock and removing it from sale completely until our supplier sends us another five, or we get a refund from them.

Our stock now looks like:

  {
  "data": {
    "id": "{PRODUCT_ID}",
    "type": "stock",
    "total": 145,
    "available": 145,
    "allocated": 0
  }
}

Great, we now have the correct amount of stock available to sell.

Allocating Stock

Stock allocation should be an integral part of your commerce strategy. You will want to allocate stock under several circumstances. For example, you may wish to send 25 items to a reseller who then, by definition, sells your stock for you. In this situation, you really don’t want to advertise that you have those items in stock because technically you don’t, the reseller does.

So you could then notify your Moltin inventory:

  curl -X POST https://api.moltin.com/v2/inventories/{PRODUCT_ID}/transactions \
    -H "Content-Type: application/json" \
    -H "Authorization: Bearer XXXX" \
    -d $'{
     "data": {
  "type": "stock-transaction",
  "action": "allocate",
  "quantity": 25
     }
}'

Which updates our stock to:

  {
  "data": {
    "id": "{PRODUCT_ID}",
    "type": "stock",
    "total": 145,
    "available": 120,
    "allocated": 25
  }
}

We can now display to our customers that we have 120 available, which will avoid what may be the undesirable position of overselling and disappointing whoever purchased the final 25 items that you no longer held in stock.

Of course, this is just an example of why you would allocate stock, but there are plenty of other reasons — be it reserving stock for future sales, in-store purchases or until you have validated the quality of your received stock we have designed the API to be consistent to your needs.

Deallocating Stock

Now that we have successfully allocated stock, we may want to reallocate it. For example, the reseller sends back 20 items because they only have space sell five. We then want to claim that stock back to sell directly:

  curl -X POST https://api.moltin.com/v2/inventories/{PRODUCT_ID}/transactions \
    -H "Content-Type: application/json" \
    -H "Authorization: Bearer XXXX" \
    -d $'{
     "data": {
  "type": "stock-transaction",
  "action": "deallocate",
  "quantity": 20
     }
}'

Which updates our stock level to:

  {
  "data": {
    "id": "{PRODUCT_ID}",
    "type": "stock",
    "total": 145,
    "available": 140,
    "allocated": 5
  }
}

Purchasing Stock

When a customer completes a purchase, there are a few things to consider and understand fully with regards to your stock:

A stock allocation is used to denote that it is purchased (it is conceptually allocated to an order). This would allow you to deallocate it if the items are returned and available to resell.

Stock will not be automatically allocated from your inventory UNLESS you have set the manage_stock attribute on the purchased product to true.

Stock allocations only happen automatically when a customer has paid for that order. We do not allocate stock into carts because that would open up an undesirable situation where you can not sell to some customers because other customers have all of the stock allocated which they may not purchase. you could, of course, create an allocated transaction when a product was added to a cart if you really wanted to do this, but it is not recommended and you should exercise caution in your own application design.

Because of the point above, it is possible to be in a situation where several customers are purchasing a product at the same time and by the time a customer has paid for an order, other customers have already completed their purchase and allocated all the stock. In this situation, you will have oversold your stock (if you are unable to replenish your inventory) and may need to issue a refund. There are ways to mitigate against this, but they are complex. If you need some help, reach out to us on the forum!

So, after reading the above, let’s consider that at least one of the products in a customers cart has the manage_stock value set to true. The customer has several items in their cart, they then go through your checkout process and we receive a notification that the order purchase has completed and you have been paid.

At that point, we will automatically go through all of the items in the order and for each product where you have declared that the product stock should be managed, we will create a transaction to allocate that stock to the order. Without having to do anything, if a customer has purchased one of your products in their order (with an ID of {PRODUCT_ID}), your stock will now look like:

  {
  "data": {
    "id": "{PRODUCT_ID}",
    "type": "stock",
    "total": 145,
    "available": 139,
    "allocated": 6
  }
}

Tracking changes over time

So after all this, why bother with an inventory? Why not simply manage “stock level” on the product itself? Well, you have probably realized that what we are in fact doing by using the inventory system is managing the shape of our stock over time. This can be incredibly useful even as a small business.

When you’re showing the available stock on your application, you probably only want to see what the current stock levels look like and you can do that quickly with the https://api.moltin.com/v2/inventories/{PRODUCT_ID} endpoint for an individual product or the https://api.moltin.com/v2/inventories for all products in your inventory (pro tip: you could use this endpoint to generate a report of all of your current stock holdings).

But by calling the transactions endpoint you can see how your stock changed over time:

  curl -X GET https://api.moltin.com/v2/inventories/{PRODUCT_ID}/transactions \
    -H "Authorization: Bearer XXXX"
}'
  {
  "data": [
    {
"id": "{TRANSACTION_ID}",
"type": "stock-transaction",
"action": "create",
"product_id": "{PRODUCT_ID}",
"quantity": 100,
"timestamps": {
  "created_at": "{TIME_CREATED}"
}
    },
    {
"id": "{TRANSACTION_ID}",
"type": "stock-transaction",
"action": "increment",
"product_id": "{PRODUCT_ID}",
"quantity": 50,
"timestamps": {
  "created_at": "{TIME_CREATED}"
}
    },
    {
"id": "{TRANSACTION_ID}",
"type": "stock-transaction",
"action": "decrement",
"product_id": "{PRODUCT_ID}",
"quantity": 5,
"timestamps": {
  "created_at": "{TIME_CREATED}"
}
    },
    {
"id": "{TRANSACTION_ID}",
"type": "stock-transaction",
"action": "allocate",
"product_id": "{PRODUCT_ID}",
"quantity": 25,
"timestamps": {
  "created_at": "{TIME_CREATED}"
}
    },
    {
"id": "{TRANSACTION_ID}",
"type": "stock-transaction",
"action": "deallocate",
"product_id": "{PRODUCT_ID}",
"quantity": 20,
"timestamps": {
  "created_at": "{TIME_CREATED}"
}
    },
    {
"id": "{TRANSACTION_ID}",
"type": "stock-transaction",
"action": "allocate",
"product_id": "{PRODUCT_ID}",
"quantity": 1,
"timestamps": {
  "created_at": "{TIME_CREATED}"
}
    }
  ]
}

Looking at the response above, you should be able to see why the value of tracking your stock over time will help you make better decisions as a retailer in addition to just seeing your current stock levels.

Integrating the Inventory to your application

There may be several technical requirements of your store where you wish to observe any changes in your stock levels without having to poll our endpoints and look for changes.

You may want to alert someone if stock is low so that a decision can be made to order more stock from a supplier, or, you may have an external inventory system that you want updated for other parts of your business.

For these use cases, we offer the integration endpoints which notify you of these changes in a way that you control. You can use stock-transaction.created in new or existing integrations to receive those events to your own system.

One thing to note is that unlike other observable events, there is only one event to observe - stock-transaction.created. Because you apply changes to stock over time and to remove stock you create transactions with a decrement action, there is never an update or delete event emitted - they are all stock-transactions that are created and therefore just one event to observe.

Changes to your Data

Since the inception of V2 of the API, you’ve been able to add stock levels and set whether we should manage stock. Those values have been indicative that the updates we’re releasing now will eventually be respected but haven’t to date. Because of the incredible uptake of stores now built on V2, we do not want to break any functionality. To do that, we need to make some changes to your products.

The manage_stock flag has provided a simple use-case for most stores up until now. This flag will become more important going forward. To reflect this, we will update all products to have a manage_stock value of false. That means that none of your current checkout process will break when we enable this functionality.

If you are having any problems with stock on checkout, please check the ‘manage_stock’ flag is false, and let us know if you need help.

You should then create your new products (and potentially update your existing ones) with the knowledge that manage_stock will now be respected.

You should avoid sending any stock update requests to the product. These will silently fail. Instead, you should use the inventory endpoints outlined in this post. We may start to fail those PUT requests to a product with an explanatory error if we detect that you’re updating stock, but we won’t do this immediately.

All of your products have their initial stock level already there so you may wish to audit your inventory ahead of changing any of your products to start managing stock again.

Supporting the Inventory

As always, we’re looking forward to seeing how you use this new functionality. A few users have been involved in suggesting on the forum how stock should be managed and if you have any questions about how to use these in your own project, or have any ideas on what we can do to make this even better, then please sign up if you haven’t already and write a post with your use case on there!

We will be rolling out support to our supported SDKs in the coming weeks, so keep an eye on the repository for new releases.

Let's build something amazing with Moltin