Applies to: Inventory API | Catalog API
Learn how to set or inspect a sold-out item or to have it enabled to be set as sold out when its inventory count reaches zero.
When inventory tracking is enabled on an item for sale, subject to location-specific overrides, the corresponding item variation at the applicable location becomes sold out when its inventory count reaches zero. The sold-out status is useful to prevent out-of-stock items from being displayed as available for ordering.
Note
Currently, the seller can also set a modifier as sold out in specified locations using the Square Dashboard or a Square POS device. The sold-out status is visible to a third-party application through the corresponding ModifierLocationOverrides.sold_out field.
A seller can use the Square Dashboard to manually mark an item variation as sold out even if its inventory count isn't zero. Until the seller manually turns off the sold-out status, the sold-out status remains true on the item variation. Furthermore, the seller can set a time beyond when the sold-out status assigned to the item variation ceases to be true.
A seller can use the Square Dashboard or an application developer can call the Catalog API to enable inventory tracking to monitor the sold-out status of an item variation globally for all seller locations or locally at specific locations. A location-specific inventory tracking specification overrides the global specification applicable for that location.
To use the Catalog API to enable the global inventory tracking, set the track_inventory attribute to true
on the item variation. To use the Catalog API to override the global settings for a particular location, set the track_inventory attribute to true
on a particular element in the location_overrides list of the item variation. Each element in the location_overrides
list defines an override for a specified location.
When an item variation becomes sold out, a catalog.version.updated
event notification is sent through the Catalog API webhook to all applications registered to receive the event. You can sign up for the webhook to receive the event to synchronize the sold-out status of item variations between your application and the Square inventory. This way, your application doesn't mistakenly present sold-out items to users as still available for purchase.
To handle sold-out items programmatically, you're likely to perform the following common programming tasks:
- Enable the automatic sold-out status on an item variation.
- Determine the sold-out status of an item variation.
- Use a webhook to sync the sold-out status on an item between the frontend and backend.
In the Square Dashboard, you can choose the Mark Item as Sold Out Online and in Point of Sale option when editing an item variation.
Using the Catalog API, your application can call UpsertCatalogObject (when creating or updating an item variation) to set track_inventory to true
on CatalogItemVariation to enable event tracking for all the seller's locations.
You can also call UpsertCatalogObject
to set track_inventory to true
on a particular element in the location_overrides list of the CatalogItemVariation
object to override the global setting.
The following example creates an item with a single item variation that has inventory tracking enabled to automatically set the tracked item variation as sold out when its inventory count reaches zero or when the inventory count isn't zero:
Upsert catalog object
Notice that this call enables event tracking globally for all the seller's locations.
The successful response returns a payload similar to the following:
{
"catalog_object": {
"type": "ITEM",
"id": "CKO7R744BIWIGAAXHEF6RAD7",
"updated_at": "2022-01-25T04:58:46.835Z",
"created_at": "1754-08-30T22:43:41.128Z",
"version": 1643086726835,
"is_deleted": false,
"present_at_all_locations": true,
"item_data": {
"name": "item testing sold out",
"description": "Item for testing sold out",
"variations": [
{
"type": "ITEM_VARIATION",
"id": "LCN2AW6H4JINRJKJBKLT4ALR",
"updated_at": "2022-01-25T04:58:46.835Z",
"created_at": "1754-08-30T22:43:41.128Z",
"version": 1643086726835,
"is_deleted": false,
"present_at_all_locations": true,
"item_variation_data": {
"item_id": "CKO7R744BIWIGAAXHEF6RAD7",
"name": "item variation for inventory tracking",
"ordinal": 0,
"pricing_type": "FIXED_PRICING",
"price_money": {
"amount": 500,
"currency": "USD"
},
"location_overrides": [
{
"location_id": "SNTR5190QMFGM",
"track_inventory": true,
"sold_out": true
}
],
"track_inventory": true,
"sellable": true,
"stockable": true
}
}
],
"product_type": "REGULAR"
}
},
"id_mappings": [
{
"client_object_id": "#item",
"object_id": "CKO7R744BIWIGAAXHEF6RAD7"
},
{
"client_object_id": "#ivar",
"object_id": "LCN2AW6H4JINRJKJBKLT4ALR"
}
]
}
When created, the item variation has zero stock in the inventory. Hence, "sold_out": true
is returned in the response.
When working with an existing item variation that doesn't have event tracking enabled, you can call UpsertCatalogObject
to update the item variation to turn on track_inventory
in a specific location. This involves specifying "track_inventory": true
in a location-specific element of the location_overrides list of the item variation.
The following example updates an item variation to override the global inventory-tracking unenabled setting (as shown by the absence of the track_inventory
attribute on the item variation) to enable location-specific event tracking of the item variation (as specified in an element inside the location_overrides
list of the item variation):
Upsert catalog object
Notice that you must specify the actual Square-assigned object ID and the current object version
number when calling UpsertCatalogObject
to update an existing catalog object.
{
"catalog_object": {
"type": "ITEM_VARIATION",
"id": "7GJBJSMFDREKKOL6543I7BKH",
"updated_at": "2022-01-26T04:35:31.693Z",
"created_at": "2022-01-25T01:38:39.791Z",
"version": 1643171731693,
"is_deleted": false,
"present_at_all_locations": true,
"item_variation_data": {
"item_id": "G4E2D6FJV7D7SZUO27WJZ5YV",
"name": "item variation for inventory tracking",
"pricing_type": "FIXED_PRICING",
"price_money": {
"amount": 500,
"currency": "USD"
},
"location_overrides": [
{
"location_id": "SNTR5190QMFGM",
"track_inventory": true,
"sold_out": true
}
],
"sellable": true,
"stockable": true
}
}
}
Because the seller hasn't stocked any unit of the item variation, the inventory count is effectively zero. Therefore, "sold_out": true
is present in the response.
As seen in the previous section, when an item variation is created with inventory tracking enabled, the newly created item variation is in the sold-out state. After the seller stocks the product, the item variation sold-out status is automatically turned off at a particular location. You can verify this by retrieving the item variation and inspecting the sold_out attribute in a location-specific element of the location_overrides list.
After you create an item variation with inventory tracking enabled, the item variation is in the sold-out state because the inventory count for it is zero. You must initialize its inventory count to a positive number to get the sold-out synchronization flow started. To accomplish this, call the Square Inventory API.
The following request uses the BatchChangeInventory endpoint of the Inventory API to add 100 units to the inventory of an item variation just created according to the instructions in Enable the automatic sold-out status on an item variation.
Batch change inventory
Specifications of "from_state": "NONE"
and "to_state": "IN_STOCK"
indicate that this request is an initial adjustment to the item variation's inventory count.
The successful response contains a result similar to the following payload:
{
"counts": [
{
"catalog_object_id": "KIPW2ZRGP6NXY45C36ADJW5A",
"catalog_object_type": "ITEM_VARIATION",
"state": "IN_STOCK",
"location_id": "SNTR5190QMFGM",
"quantity": "100",
"calculated_at": "2022-01-29T05:37:27.409Z",
"availability_state": "AVAILABLE"
}
],
"changes": [
{
"type": "ADJUSTMENT",
"adjustment": {
"id": "4GVER7WTZHYRN3YC2XYUC3GV",
"from_state": "NONE",
"to_state": "IN_STOCK",
"location_id": "SNTR5190QMFGM",
"catalog_object_id": "KIPW2ZRGP6NXY45C36ADJW5A",
"catalog_object_type": "ITEM_VARIATION",
"quantity": "100",
"occurred_at": "2022-01-28T11:20:00Z",
"created_at": "2022-01-29T05:37:27.408Z",
"source": {
"product": "EXTERNAL_API",
"application_id": "sq0ids-hLgkXFJ58T_vJI5g1Dpoww",
"name": "HelloCustomers"
}
}
}
]
}
The item variation now has 100 units in stock at the given location (SNTR5190QMFGM
), as indicated by "state": "IN_STOCK"
and "quantity": "100"
. You expect its sold_out
attribute to be absent or set to false
. You can verify this by retrieving the updated item variation and examining the sold_out
attribute.
To retrieve an item variation of a given ID, call RetrieveCatalogObject.
From the result, you can examine the location-specific element of the location_overrides
list to see that the sold_out
attribute is absent or set to false
.
The following request retrieves the item variation (KIPW2ZRGP6NXY45C36ADJW5A
) that has 100 units just added to the inventory. In the request, the item variation ID is set as the object_id
path parameter value.
Retrieve catalog object
{
"object": {
"type": "ITEM_VARIATION",
"id": "KIPW2ZRGP6NXY45C36ADJW5A",
"updated_at": "2022-01-29T05:37:28.468Z",
"created_at": "2022-01-26T20:33:22.432Z",
"version": 1643434648468,
"is_deleted": false,
"present_at_all_locations": true,
"item_variation_data": {
"item_id": "AJH676Z3IMY3XP3LNG3PHSYS",
"name": "item variation for inventory tracking",
"ordinal": 0,
"pricing_type": "FIXED_PRICING",
"price_money": {
"amount": 500,
"currency": "USD"
},
"location_overrides": [
{
"location_id": "SNTR5190QMFGM",
"track_inventory": true
}
],
"track_inventory": true,
"sellable": true,
"stockable": true
}
}
}
The absence of the sold_out
attribute inside location_overrides
confirms that the item variation is no longer sold out.
To improve the user experience of your application that displays items for sale for a seller, make sure that sold-out items are marked as such and become unavailable for purchase. To achieve this, you must keep the sold-out status of item variations in your application in sync with the Square inventory. You must also inform the user that an item is out of stock or unavailable for purchase when the corresponding item variation becomes sold out.
An efficient way to synchronize the sold-out status involves using Square API webhooks. When an inventory change is made on an item variation, a catalog.version.updated event is sent through the Catalog API webhook to applications that have registered to receive the event notification. The event data contains a timestamp when the change was made. Against this timestamp, you can call SearchCatalogObjects to query the Square catalog to retrieve the item variation and to inspect the sold_out attribute in element objects of the location_overrides list of the item variation. For item variations with "sold_out": true
specified, disable them in all components of your application, especially the UI for the applicable locations. For item variations without the sold_out
attribute present or with "sold_out": false
specified, enable the item variations in the application's UI or any other components.
The following discussion presents an end-to-end walkthrough to illustrate how to programmatically synchronize an item variation's sold-out status between your application and the backend. In particular, it covers the following configuration and programming tasks:
- Configure your application to receive the catalog.version.updated event through the Catalog API webhook.
- Reduce the item variation's inventory count to zero to make the item sold out.
- Inspect the received
catalog.version.updated
event data to obtain theupdated_at
timestamp. - Search for the
CatalogItemVariation
object with the sameupdated_at
timestamp and inspect the resulting item variation for the"sold_out": true
attribute.
Omitted is the application-specific logic to disable sold-out item variations or enable restocked item variations in your application, depending on whether the sold_out
status is true
or false
, respectively.
To subscribe to catalog.version.updated event notifications, you must configure webhooks for your Square application. A webhook registers the URL to which Square should send notifications, the events you want to be notified about, and the Square API version. For more information, see Square Webhooks Overview.
To configure a webhook
In the Developer Console, open the application to which you want to subscribe.
In the left pane, choose Webhooks.
At the top of the page, choose Sandbox or Production. Choose Sandbox for testing.
Choose Add Endpoint, and then configure the endpoint:
- For Webhook Name, enter a name such as Item Sold Out Webhook.
- For URL, enter your notification URL. If you don't have a working URL yet, you can enter https://example.com as a placeholder. To use Webhook.site for testing, copy the Your unique URL value on the website and paste it into the URL box.
- Optional. For API Version, choose a Square API version. By default, this is set to the same version as the application.
- For Events, choose catalog.version.updated. If you want to receive notifications about other events at the same webhook URL, choose them or configure another endpoint.
Choose Save.
Note
In the production environment, ignore the Enable Webhooks setting on the Webhooks page. This setting applies to webhooks for Connect V1 APIs (deprecated).
With the webhook configured, test the webhook workflow as follows.
Suppose the previously added 100 units of the item variation are all sold in 1 day. To perform a daily update of the inventory count, call BatchChangeInventory
of the Inventory API to deduct the 100 units from the inventory.
The following example shows how this can be done.
The following example request reduces the inventory count of an item variation ("catalog_object_id": "KIPW2ZRGP6NXY45C36ADJW5A"
) at a particular location ("location_id": "SNTR5190QMFGM"
) by 100 units:
Batch change inventory
Notice that the reduction is specified by "from_state": "IN_STOCK"
, "to_state": "SOLD"
, and "quantity": "100"
.
The successful response returns a result containing a payload similar to the following:
{
"counts": [
{
"catalog_object_id": "KIPW2ZRGP6NXY45C36ADJW5A",
"catalog_object_type": "ITEM_VARIATION",
"state": "IN_STOCK",
"location_id": "SNTR5190QMFGM",
"quantity": "0",
"calculated_at": "2022-01-26T20:57:37.463Z",
"availability_state": "AVAILABLE"
}
],
"changes": [
{
"type": "ADJUSTMENT",
"adjustment": {
"id": "PYEHJWDOL64YAH3BZE74KLK7",
"from_state": "IN_STOCK",
"to_state": "SOLD",
"location_id": "SNTR5190QMFGM",
"catalog_object_id": "KIPW2ZRGP6NXY45C36ADJW5A",
"catalog_object_type": "ITEM_VARIATION",
"quantity": "100",
"occurred_at": "2022-01-26T11:20:00Z",
"created_at": "2022-01-26T20:57:37.462Z",
"source": {
"product": "EXTERNAL_API",
"application_id": "sq0ids-hLgkXFJ58T_vJI5g1Dpoww",
"name": "HelloCustomers"
}
}
}
]
}
Notice that the unit of item variation in stock is now 0, as is shown by "state": "IN_STOCK"
and "quantity": "0"
. In response to this change, a catalog.version.updated
event is triggered and sent to the previously configured webhook event listener where you can inspect for the timestamp where the item variation's catalog version is updated.
The following catalog.version.updated
event shows an example of what the event data structure looks like:
{
"merchant_id": "ETCE8W0W8QDYP",
"type": "catalog.version.updated",
"event_id": "9118d935-84ca-427d-897e-c12bfc701768",
"created_at": "2022-01-26T20:57:43.064534045Z",
"data": {
"type": "catalog",
"id": "",
"object": {
"catalog_version": {
"updated_at": "2022-01-26T20:57:38.885Z"
}
}
}
}
Notice that this event data doesn't say explicitly which object is affected or whether an affected item variation is sold out. In fact, you receive a similar event for the inventory adjustment that added the first 100 units of the item variation, although with an earlier updated_at
timestamp.
To determine the sold_out
status, you must determine the affected item variation updated at the time specified by the updated_at
timestamp and then inspect the sold_out
attribute value.
To determine sold_out
, call the SearchCatalogObjects endpoint of the Catalog API and then inspect the result for the sold_out
attribute of an item variation updated at a given time.
The following example request searches for an item variation ("object_types": ["ITEM_VARIATION"]
) that is updated at 2022-01-26T20:57:38.885Z; that is, later than begin_time
and earlier than or equal to end_time
:
Search catalog objects
Notice that the update time interval between begin_time
and end_time
doesn't include begin_time
.
The successful response returns the following result containing a payload similar to the following:
{
"objects": [
{
"type": "ITEM_VARIATION",
"id": "KIPW2ZRGP6NXY45C36ADJW5A",
"updated_at": "2022-01-26T20:57:38.885Z",
"created_at": "2022-01-26T20:33:22.432Z",
"version": 1643230658885,
"is_deleted": false,
"present_at_all_locations": true,
"item_variation_data": {
"item_id": "AJH676Z3IMY3XP3LNG3PHSYS",
"name": "item variation for inventory tracking",
"ordinal": 0,
"pricing_type": "FIXED_PRICING",
"price_money": {
"amount": 500,
"currency": "USD"
},
"location_overrides": [
{
"location_id": "SNTR5190QMFGM",
"track_inventory": true,
"sold_out": true
}
],
"track_inventory": true,
"sellable": true,
"stockable": true
}
}
],
"latest_time": "2022-01-26T20:57:38.885Z"
}
The presence of "sold_out": true
(within the location_overrides
list) confirms that the item variation is indeed sold out at the specified location (SNTR5190QMFGM
).
It's possible that more than one item variation instance might be returned, when multiple inventory updates are performed at the same time. In this case, you can rely on other properties (such as name
and item_id
) to further identify the item variation of interest.
If you're using an earlier updated_at
timestamp for the initial inventory adjustment that added 100 units of item variation, the previous search result would contain either no sold_out
attribute or "sold_out": false
. At that time, the item variation is stocked and not yet sold out.