LIMITED BETA — Inventory v2 API Overview
SHARED EXTERNALLY
CONFIDENTIAL
PRIVATE
The Inventory v2 API is still in limited beta release with restricted functionality. This document outlines the data types and process flow of the Inventory v2 API. SEO summary Requirements and limitations How it works — the Inventory API data model Batched state transitions Special InventoryStatus values NONE Status IN_STOCK Status SOLD Status Automatic IN_STOCK adjustments Reconciliation with InventoryPhysicalCount How it works — The Inventory API process flow Inventory tracking overview Client timestamp versus adjustment request order Supported status transitions The ignore_unchanged_counts flag Next steps
SEO summary Square’s Inventory API lets developers view and adjust inventory levels for CatalogItemVariations in a Square catalog. The Inventory v2 API replaces Square's Inventory Connect v1 API and introducesnew functionality for: ● Moving quantities of CatalogItemVariations through predefined statuses (e.g., from IN_STOCK to WASTE). ● Providing unit costs when adding quantities of CatalogItemVariations to inventory. ● Transfering inventory quantities between locations. ● Viewing the inventory adjustment history for a CatalogItemVariation. ● Batching for inventory adjustments and information retrieval.
Requirements and limitations ● ● ● ●
● ● ● ●
Inventory can only be tracked on Square CatalogItemVariations . See the Catalog API Overview for more information on the Square Catalog. Inventory tracking for fractional quantities, subcomponents, ingredients, and product bundling is not supported. Inventory transfers between locations are applied immediately. Catalog items cannot be marked as "in transit" at this time. Unit cost functionality is available through the Inventory API, but not exposed in the Square Dashboard or Point of Sale app by default. To view unit costs and related inventory reports in the Square Dashboard and Point of Sale app, subscribe to Square for Retail . Anonymous Inventory API calls are not allowed. All Inventory API calls must include an authorization token for the targeted Square account. All applications using OAuth must have INVENTORY_READ p ermissions for the targeted Square account. Applications using OAuth that modify inventory quantities must have INVENTORY_WRITE p ermissions for the targeted Square account. The Square Inventory API is not supported in sandbox mode at this time.
How it works — the Inventory API data model Related APIs : Catalog API, Transactions API, Checkout API, Point of Sale API The Inventory API accepts inventory adjustments and physical counts for a CatalogItemVariation and adjusts the inventory level accordingly. The key data types for the Inventory API are: ● InventoryCount — The computed quantity of a CatalogItemVariation at a specific location with a specific inventory status. ● InventoryAdjustment — The quantity of a CatalogItemVariation transitioning from one location to another or one inventory status to another (e.g., moving from IN_STOCK to RESERVED_FOR_SALE). ● InventoryPhysicalCount — The verified quantity of a CatalogItemVariation at a specific location with a specific status as determined by a manual count or trusted system. ● SourceApplication — Information about the Square product or thirdparty application that applied an inventory change. SourceApplication records provide traceability for inventory changes. InventoryCount and InventoryPhysicalCount are similar in that they both specify the current quantity of a CatalogItemVariation , but InventoryPhysicalCount is a provided value and InventoryCount is a computed value. InventoryPhysicalCount might represent the quantity that is physically present as a result of an employee counting the CatalogItemVariations on hand or from syncing with an external system. InventoryCount is the quantity that Square thinks is available based on the known inventory adjustments made since the last physical count. In an ideal world, the value of InventoryCount and InventoryPhysicalCount would always be identical. But in most cases, item loss, accidental damage, and human error will create discrepancies between InventoryCount and InventoryPhysicalCount .
Consider the case where a merchant receives some kites into inventory, sells some, accidentally damages some, and then recounts them at the end of the day to reconcile their inventory
Initially, there are no kites in stock. Before opening the store in the morning, the merchant receives 100 “Silk Kites, Small” from a vendor and adds them to the store’s inventory by transitioning 100 units from NONE to IN_STOCK status because they are available for sale. During the course of the day: ● The merchant sells 3 of the kites to a customer using Square’s Point of Sale application which automatically moves 3 units from IN_STOCK status to SOLD status. ● A reservation for 1 kite comes in from through the store’s eCommerce site, which moves 1 unit from the IN_STOCK status to the RESERVED_FOR_SALE status to indicate that the kite is not currently available for sale. ● An accident in the store damages 2 of the kites, so the merchant explicitly transitions 2 units from IN_STOCK status to WASTE status to indicate that they are no longer available for sale. At this point, the calculated inventory count for “Silk Kites, Small” with IN_STOCK status is 94. At the end of the day, the merchant closes the store and counts all the “Silk Kites, Small” available for sale in the store and finds that there are only 91 kites. To reconcile the computed and verified counts, the merchant pushes the physical count to Square, which updates the IN_STOCK quantity of “Silk Kites, Small” to 91.
The key thing to understand is that inventory adjustments are handled by moving quantities of CatalogItemVariations at a given location from one state to another. Square’s Inventory API supports the following inventory statuses: ● NONE — Indicates the related quantity of a CatalogItemVariation is not currently tracked in Square’s inventory system. An InventoryAdjustment that transfers a quantity out of the NONE state into a supported state (e.g., IN_STOCK) introduces the stock into the system. ● IN_STOCK — Indicates the related quantity of a CatalogItemVariation is on hand and available for sale. ● SOLD — Indicates the related quantity of a CatalogItemVariation has been sold as part of an itemized transaction. When CatalogItemVariations transition to the SOLD state, they are no longer tracked in inventory. Returning a CatalogItemVariation adds new quantity to the system, it does not move existing quantity out of the SOLD state. ● RETURNED_BY_CUSTOMER — Indicates the related quantity of a CatalogItemVariation was returned. CatalogItemVariations in the RETURNED_BY_CUSTOMER state are not available for sale until they are transitioned to the IN_STOCK state. ● RESERVED_FOR_SALE — Indicates the related quantity of a CatalogItemVariation is on hand, but not currently available for sale. For example, it may be set aside from store inventory to fulfill an online reservation. ● ORDERED_FROM_VENDOR — Indicates the related quantity of a CatalogItemVariation was ordered from a supplier but not currently available for sale. ● WASTE — Indicates the related quantity of a CatalogItemVariation cannot be sold for some reason (e.g., it is lost, damaged, or stolen).
Batched state transitions Inventory operations are recorded based on the client timestamp and requests succeed or fail as an atomic operation. A successful InventoryAdjustment or InventoryPhysicalCount response includes the new InventoryCount for each CatalogItemVariation changed. Batched changes are also recorded based on the client timestamp of each individual change and also succeed or fail atomically. For example, consider the case where , a single request is used to add inventory by transitioning 100 CatalogItemVariation units to IN_STOCK status, move 5 units to WASTE, and record a physical count of 90 units.
The individual changes in a batched state changes are recorded based on their individual client timestamps but they are applied as an allornothing change as a single InventoryChange request. Assuming the inventory count for the targeted CatalogItemVariation is currently 0: 1. 100 units move from NONE to IN_STOCK with a timestamp of 23:00 GMT, making the calculated inventory count 100. 2. 5 units move from IN_STOCK to WASTE with a timestamp of 23:10 GMT, making the calculated inventory count 95. 3. The system records a physical count of 90 units with a timestamp of 23:30 GMT, resetting the calculated inventory count to 90. If all three changes succeed, the new calculated inventory count for IN_STOCK units will be 90. But if any of the individual changes fail, the entire update fails and the calculated inventory count will remain unchanged. Inventory quantities are also affected by Square’s payment APIs and Point of Sale application. In the example above, when the Square Point of Sale application records a transaction, it moves 3 units from IN_STOCK status to SOLD status. Assuming the transaction’s timestamp places it after the batch update, the new calculated inventory count for IN_STOCK units will be 87 units.
Special InventoryStatus values NONE Status The NONE status is not a true inventory status. NONE is a from_status placeholder to represent the fact that a given CatalogItemVariation was introduced as new inventory to Square’s inventory system. For
example, consider the CatalogItemVariation, “Red Dog Collar” with 100 units, all of which have IN_STOCK status. If 5 collars are transitioned from NONE status to IN_STOCK status, there will be 105 units with IN_STOCK status. Inventory quantities can be transitioned from NONE status, but cannot be transitioned to NONE status.
IN_STOCK Status The IN_STOCK status does not represent a pool of available items that are decremented over time. CatalogItemVariations move into, and out of, IN_STOCK status the same way they do with any other status. In general, InventoryAdjustments transfer a quantity of CatalogItemVariations between states such that the total quantity for that CatalogItemVariation does not change. For example, consider the CatalogItemVariation “Red Dog Collar” with 100 units, all of which have IN_STOCK status. If 5 units are reserved for sale and 3 units are marked as damaged, there are still 100 units at the end of the day: 92 units with IN_STOCK status, 5 with RESERVED_FOR_SALE status, and 3 with WASTE status. The IN_STOCK inventory status is only special in that the Square Point of Sale application and Square Dashboard use the quantity of CatalogItemVariations with IN_STOCK status to determine the number of units currently available for sale.
SOLD Status When CatalogInventoryItems move to SOLD status, the units are no longer explicitly tracked. As a result, inventory counts for CatalogItemVariations in the SOLD status do not exist and adjusting inventory from the SOLD status introduces a new quantity into Square’s inventory system. For example, consider the CatalogItemVariation “Red Dog Collar” with 100 units, all of which have IN_STOCK status. If 5 units are sold online and 3 units are sold in the store, there will be 92 units tracked at the end of the day. If a customer returns 2 units, there will now be 94 units tracked: 92 units with IN_STOCK status and 2 units with RETURNED_BY_CUSTOMER status.
Automatic IN_STOCK adjustments If inventory tracking is enabled for the CatalogItemVariation in the Square Dashboard, the inventory count is automatically updated by moving the quantity sold from IN_STOCK status to SOLD status when a transaction is captured by the Square Point of Sale application or by linking an itemized Order object to a transaction processed by the Transactions API . Consider a Transaction API request that links to an itemized Order containing three line items: a Red Shirt, Trendy Sneakers, and The Perfect Jean.
When Square’s Charge endpoint processes the transaction, Square will automatically adjust the inventory for each CatalogItemVariation by moving 1 unit of Red Shirt from IN_STOCK to SOLD, 1 unit of Trendy Sneakers from IN_STOCK to SOLD, and 2 units of The Perfect Jean from IN_STOCK to SOLD.
Reconciliation with InventoryPhysicalCount InventoryPhysicalCount should only be used to reconcile the computed inventory count in Square’s system with the results of performing a physical count or syncing with a trusted external system. Do not use InventoryPhysicalCount to apply sequential adjustments to CatalogItemVariation quantities. Retrieving an InventoryCount from the server, modifying the count based on recent changes, then pushing the updated inventory count as an InventoryPhysicalCount ignores changes that might have occurred between the retrieve and the push and results in inaccurate tracking. Consider the case where the Square Point of Sale application captures a sale after the InventoryCount request but before the InventoryPhysicalCount update.
Assume 3 units were sold through an external channel and the original InventoryCount request returns a quantity of 10 units with IN_STOCK status. Meanwhile, the Square Point of Sale application captures the sale of 2 units and moves those 2 units from IN_STOCK status to SOLD status so there are now 8 units with IN_STOCK status. Based on the InventoryCount result, the calling application incorrectly believes there are 10 units in stock. If the application uses an InventoryPhysicalCount update to reduce the IN_STOCK quantity by 3, the final quantity of units with IN_STOCK status is forced to be 7 units (10 IN_STOCK units 3 units sold externally) when it should be 5 units (10 units IN_STOCK 2 units sold through Square’s Point of Sale 3 units sold externally). The correct way to track the 3 units through an external system is by pushing an InventoryAdjustment that moves 3 units from IN_STOCK status to SOLD status. This forces Square’s systems to apply the adjustment correctly by subtracting it along with the 2 units sold via Square’s Point of Sale app, rather than explicitly overwriting the count.
How it works — The Inventory API process flow Inventory tracking overview There are 4 key endpoints provided by the Inventory API: ● RetrieveInventoryCount — Retrieves the current computed InventoryCount for a CatalogItemVariation at a location with a specific inventory status (e.g., IN_STOCK). ● BatchRetrieveInventoryCounts — Retrieves the current computed InventoryCounts for one or more CatalogItemVariation .
●
●
BatchRetrieveInventoryChanges — Retrieves the InventoryAdjustment and InventoryPhysicalCount h istory for one or more CatalogItemVariations based on location and inventory status. The BatchRetrieveInventoryChanges endpoint also retrieves all changes recorded since a configured point in time. BatchChangeInventory — Pushes InventoryAdjustment and InventoryPhysicalCount requests to Square.
The Inventory API also includes endpoints for retrieving the results of individual InventoryAdjustment () and InventoryPhysicalCount requests: RetrieveInventoryAdjustment and RetrieveInventoryPhysicalCount. See the Inventory API Technical Reference for more information on all the Inventory API endpoints.
Client timestamp versus adjustment request order Inventory unit counts are calculated by applying all the InventoryAdjustment requests received since the last recorded InventoryPhysicalCount . If no InventoryPhysicalCount requests have been recorded, the InventoryAdjustment requests are applied with an assumed starting unit quantity of 0. Inventory changes (including changes due to sales transactions) can be sent to Square out of order. As a result, InventoryAdjustment and InventoryPhysicalCount requests require a clientspecified RFC 3339 timestamp ( occurred_at ) so inventory history can be ordered correctly. Consider a situation where the Square Point of Sale app processes transactions in offline mode while a custom inventory management solution makes inventory adjustments through the API.
Assume the CatalogItemVariation starts with 100 units with IN_STOCK status with the following squence of events. 1. At 13:10 GMT, the inventory management backend sends an InventoryAdjustment request using the Inventory Connect API to record that 3 units were sold through a thirdparty solution . 3 units move to SOLD status and 97 units remain with IN_STOCK status. 2. At 13:20 GMT, the merchant’s Square Point of Sale device goes offline. The merchant sells 2 units in offline mode with a recorded transaction time of 13:20 GMT. 3. At 13:30 GMT, the inventory management backend sends an InventoryPhysicalCount request using the Inventory Connect API to reconcile the quantity in Square’s inventory service (97 units) with the verified physical quantity available for sale (90 units). 4. At 13:35 GMT, the merchant’s Square Point of Sale device reconnects to the internet and pushes the offline sale to Square, which moves 2 units to SOLD status.. Square’s inventory system applies the transaction results, with a client timestamp of 13:20 GMT, before the InventoryPhysicalCount that occurred at 13:30 GMT. Although the Point of Sale transaction was the last change sent to Square, the quantity with IN_STOCK status is still 90 units, because the last change according to client timestamp was the InventoryPhysicalCount that reconciled the CatalogItemVariation IN_STOCK count. 5. At 13:40 GMT, the inventory management backend sends another InventoryAdjustment request using the Inventory Connect API to transfer 2 units that are no longer suitable for sale to WASTE status. The InventoryAdjustment request has a client timestamp that happens after the count reconciliation so the IN_STOCK count is now 88 units and the WASTE count is 2 units.
Supported status transitions Inventory status transitions represent real world changes to inventory quantities. As a result, some status transitions are permitted (e.g., IN_STOCK to SOLD) while others are not (e.g., WASTE to RETURNED_BY_CUSTOMER). Square’s inventory system supports the following inventory status transitions:
From Status
To Status
Event
NONE
IN_STOCK
An item has been received and is available for sale.
IN_STOCK
SOLD
An item was sold.
IN_STOCK
RESERVED_FOR_SALE
An item has been reserved for sale but has not been sold yet. .
IN_STOCK
WASTE
An item is damaged or lost and cannot be sold.
SOLD
RETURNED_BY_CUSTOMER
A customer returned an item, but it has not been restocked for sale yet.
SOLD
IN_STOCK
A customer returned an item and it was immediately restocked for sale.
RETURNED_BY_CUSTOMER IN_STOCK
An item previously returned by a customer is available for sale.
RETURNED_BY_CUSTOMER WASTE
An item previously returned by a customer was determined to be unsellable.
RESERVED_FOR_SALE
SOLD
An item that was previously reserved has been sold to the customer.
RESERVED_FOR_SALE
WASTE
An item that was previously reserved was damaged or lost and is no longer sellable.
RESERVED_FOR_SALE
IN_STOCK
An item that was previously reserved was not purchased by the customer and is available for sale.
WASTE
SOLD
A customer bought an item that was previously considered unsellable.
NONE
RETURNED_BY_CUSTOMER
A customer returned an item that was not previously tracked in inventory.
The ignore_unchanged_counts flag Requests to the BatchChangeInventoryRequest endpoint include an ignore_unchanged_counts flag. The ignore_unchanged_counts flag tells Square to skip updates for the CatalogItemVariation when nothing has changed. When the new physical count for a CatalogItemVariation is the same as the previous physical count and no InventoryAdjustment requests have been received between the two physical counts, the physical count update is skipped. The ignore_unchanged_counts flag allows thirdparty systems to push potentially redundant inventory counts into Square's systems without polluting the Square Dashboard with unecessary adjustments. ignore_unchanged_counts is enabled by default so developers do not inadvertently spam Square servers with redundant InventoryPhysicalCount requests . Avoid disabling the ignore_unchanged_counts flag unless the associated InventoryPhysicalCount request represents a true reconciliation, such as an actual physical count by a person.
Next steps ● ● ●
To get started with the Inventory API, see the Inventory API Setup Guide. For more detailed information on the Inventory API endpoints, we recommend reading the Inventory API Technical Reference. To learn more about working with the Catalog API, consider reading the Catalog API Overview.