LIMITED BETA — Inventory v2 API Setup Guide
SHARED EXTERNALLY
CONFIDENTIAL
PRIVATE
The Inventory v2 API is still in limited beta release with restricted functionality. This document outlines the steps for getting started with the Inventory v2 API.
Prerequisites To use the Inventory API, the following must be true: ● You have a Square account. Create a Square account in minutes if you don't already have one. ● You have items defined in your Square product catalog. See the Catalog API Overview for details on working with Square Catalog. ● All applications using the Inventory API with OAuth must have INVENTORY_READ permissions for the targeted Square account. ● Applications that update inventory states using OAuth must have INVENTORY_WRITE permissions for the targeted Square account.
Assumptions This guide makes the following assumptions: ● You have read the Inventory API Overview. This is a howto guide and does not cover general functionality of the API. ● You have read the Catalog API Overview . ● You are familiar with HTTP and JSON. If you are new to JSON, we recommend reading the JSON Getting Started Guide on Codular before continuing.
Process overview Managing quantities of item variations with the Inventory API generally includes the following steps: 1. Get your authorization ID. 2. Get your location ID. 3. Add in stock quantities for one or more item variations. 4. Transition a quantity of item variations to a new state. 5. Retrieve the quantities of multiple item variations. 6. Optional: Reconcile the computed quantity of inventory. 7. Optional: Retrieve the quantity of a specific item variation. 8. Optional: Retrieve the history of inventory changes for an item.
Working example In order to provide concrete instruction, this guide is based on a hypothetical integration with the following characteristics:
●
●
●
The Inventory API is being used as a single account solution. In other words, the integrated solution and the Square account used to manage the product catalog are associated with the same person and the integrated solution uses a Personal Access Token for authorization. The integrated solution uses Java version 1.8 or later. Java was selected for the example code because it is a commonly used server language, but the Inventory API is language agnostic and the setup steps are comparable across languages. The integrated solution has installed the Square Connect v2 Java SDK. Installing the SDK is optional. As long as you can package and receive JSON messages you can use Square's APIs, but installing the SDK makes things easier.
If your situation is different from the working example outlined here, you should still be able to follow along with the steps in this guide. The example code has been written to avoid functionality unique to Java as much as possible, but you may need to make slight changes in how you handle authorization (e.g., OAuth) or create your JSON messages.
Step 1: Get your authorization ID You cannot use the Inventory API endpoints without authorizing access to your Square account. To get your personal access token: 1. Open your Application Dashboard . 2. If you DO have an application you want to use for inventory management, click on the application. 3. If you DO NOT have an application you want to use for inventory management, click New Application , enter a name for your application (e.g., "My Inventory App") and click Create Application . 4. Copy the Personal Access Token on the Credentials tab of the application control panel. Instead of a personal access token you can also use OAuth and the INVENTORY_READ and INVENTORY_WRITE permissions. OAuth is the preferred method because it provides better security for the targeted merchant account, but personal access tokens are appropriate for testing and development.
Step 2: Get your location ID A CatalogItemVariation quantity is always tied to a location and inventory adjustments must be credited to a valid location ID for the associated Square account. Use the Locations API find your location ID: 1. Initialize the API object. // Create and configure a new API client object ApiClient apiClient = Configuration.getDefaultApiClient(); // Configure OAuth2 access token for authorization: oauth2 OAuth oauth2 = (OAuth) apiClient.getAuthentication("oauth2"); oauth2.setAccessToken("MY_ACCESS_TOKEN"); String locationId; // we'll set this programmatically // Create a LocationsApi client to load the location ID LocationsApi locationsApi = new LocationsApi();
locationsApi.setApiClient(apiClient);
2. Call listLocations and save the first location ID. List locations = locationsApi.listLocations().getLocations(); locationId = locations.get(0).getId();
Note: If you have more than one location, you can loop over the locations to check the location names for your account in the Square Dashboard and select the correct location by name. For example: String locationName = "MY_LOCATION_NAME"; List locations = locationsApi.listLocations().getLocations(); for (Location location : locations) { if (locationName.equals(location.getName())) { locationId = location.getId(); } }
Step 3: Add IN_STOCK quantities for one or more item variations 1. Look up the CatalogItemVariation IDs you want to modify using the Catalog V2 API. Replace the CatalogItem (“TShirt”) and CatalogItemVariation names (“Small”, “Medium”) in the example code below before searching. String itemName = "TShirt"; // Replace with your CatalogItem name String variation1Name = "Small"; // Replace with your CatalogItemVariation name String variation2Name = "Medium"; // Replace with your CatalogItemVariation name String variation1Id = ""; String variation2Id = ""; CatalogApi catalogApi = new CatalogApi(); // Search for an Item with the desired name attribute. SearchCatalogObjectsResponse itemResponse = catalogApi.searchCatalogObjects(new SearchCatalogObjectsRequest() .addObjectTypesItem(SearchCatalogObjectsRequest.ObjectTypesEnum.ITEM) .query(new CatalogQuery() .exactQuery(new CatalogQueryExact() .attributeName("name") .attributeValue(itemName)))); // Retrieve the first returned object, an Item. CatalogObject item = itemResponse.getObjects().get(0); // Retrieve the desired ItemVariations from the Item. List variations = item.getItemData().getVariations(); for (CatalogObject variation : variations) { String name = variation.getItemVariationData().getName(); if (variation1Name.equals(name)) {
variation1Id = variation.getId(); } else if (variation2Name.equals(name)) { variation2Id = variation.getId(); } }
2. Inventory changes are pushed to Square using the BatchChangeInventory endpoint. To record that you received new stock of the CatalogItemVariation objects you searched for in the previous step, create a BatchChangeInventoryRequest with an InventoryAdjustment that moves a specific quantity of the CatalogItemVariation objects from NONE status to IN_STOCK status. // Create an adjustment for 5 units of "small" variation from status NONE to IN_STOCK. InventoryAdjustment addStockAdjustment = new InventoryAdjustment() .catalogObjectId(variation1Id) .fromLocationId(locationId) .toLocationId(locationId) .fromStatus(InventoryAdjustment.FromStatusEnum.NONE) .toStatus(InventoryAdjustment.ToStatusEnum.IN_STOCK) .quantity("5"); // Create an adjustment for 7 units of "medium" variation from status IN_STOCK to WASTE. InventoryAdjustment damagedStockAdjustment = new InventoryAdjustment() .catalogObjectId(variation2Id) .fromLocationId(locationId) .toLocationId(locationId) .fromStatus(InventoryAdjustment.FromStatusEnum.IN_STOCK) .toStatus(InventoryAdjustment.ToStatusEnum.WASTE) .quantity("7"); List changes = asList( new InventoryChange().adjustment(addStockAdjustment), new InventoryChange().adjustment(damagedStockAdjustment)); // Construct a request with an idempotency key and a single InventoryChange object. BatchChangeInventoryRequest addStockRequest = new BatchChangeInventoryRequest() .idempotencyKey(UUID.randomUUID().toString()) .changes(changes);
3. Send the BatchChangeInventoryRequest to the server. BatchChangeInventoryResponse addStockResponse = inventoryApi.batchChangeInventory(addStockRequest); // Check for errors. if (!addStockResponse.getErrors().isEmpty()) { System.err.println("Error calling BatchChangeInventory: " + addStockResponse.getErrors()); return; } // The response contains the quantity following the adjustment. for (InventoryCount count : addStockResponse.getCounts()) { System.out.println("item variation: " + count.getCatalogObjectId()); System.out.println(" new quantity: " + count.getQuantity()); }
Step 4: Transition a quantity of item variations to a new state Recording a transition from one quantity to another works the same way as adding IN_STOCK quantities. For example, to indicate 2 units of variation1Id some stock is are no longer suitable for sale: 1. Create a BatchChangeInventoryRequest containing an InventoryAdjustment from IN_STOCK status to WASTE status. // Create an adjustment to move 2 units from status IN_STOCK to WASTE. InventoryAdjustment wasteAdjustment = new InventoryAdjustment() .catalogObjectId(variation1Id) .fromLocationId(locationId) .toLocationId(locationId) .fromStatus(InventoryAdjustment.FromStatusEnum.IN_STOCK) .toStatus(InventoryAdjustment.ToStatusEnum.WASTE) .quantity("2"); InventoryChange wasteChange = new InventoryChange().adjustment(wasteAdjustment); BatchChangeInventoryRequest wasteRequest = new BatchChangeInventoryRequest() .idempotencyKey(UUID.randomUUID().toString()) .addChangesItem(wasteChange);
2. Send the BatchChangeInventoryRequest to the server. BatchChangeInventoryResponse wasteResponse = inventoryApi.batchChangeInventory(wasteRequest); // Check for errors. if (!wasteResponse.getErrors().isEmpty()) { System.err.println("Error calling BatchChangeInventory: " + wasteResponse.getErrors()); return; }
3. The response will contain the current quantity of variation1Id with IN_STOCK and WASTE status. You can use this information to determine if there are any more units IN_STOCK after the adjustment is applied. // Display IN_STOCK and WASTE quantities. for (InventoryCount count : wasteResponse.getCounts()) { if (count.getStatus() == InventoryCount.StatusEnum.IN_STOCK) { System.out.println("In stock: " + count.getQuantity()); } else if (count.getStatus() == InventoryCount.StatusEnum.WASTE) { System.out.println("Waste: " + count.getQuantity()); } }
Reminder : If you are processing itemized transactions with Square’s APIs or hardware, item variation quantities will automatically transition to SOLD status. If you are using any other method, you will need to apply the adjustment manually.
Step 5: Retrieve the quantities of multiple item variations 1. To retrieve the quantities of multiple item variations (for example, to retrieve current quantities of the item variations that are sold through an eCommerce website), create a BatchRetrieveInventoryCountsRequest containing the catalog_object_ids of the item variation quantities you want to retrieve. Remember to set the location_ids to filter the search against specific locations. BatchRetrieveInventoryCountsRequest countsRequest = new BatchRetrieveInventoryCountsRequest() .addLocationIdsItem(locationId1) .addLocationIdsItem(locationId2) .addCatalogObjectIdsItem(item1VariationToken) .addCatalogObjectIdsItem(item2VariationToken);
2. Send the BatchRetrieveInventoryCountsRequest to the server. BatchRetrieveInventoryCountsResponse countsResponse = inventoryApi.batchRetrieveInventoryCounts(countsRequest);
Optional: Reconcile the computed quantity of inventory 1. To reconcile the inventory count in Square’s system with the results of a physical count or the inventory reported by a trusted system, create a BatchChangeInventoryRequest containing one or more InventoryPhysicalCount objects. InventoryPhysicalCount physicalCount1 = new InventoryPhysicalCount() .catalogObjectId(variation1Id) .locationId(locationId1) .status(InventoryPhysicalCount.StatusEnum. IN_STOCK ) .quantity("5"); InventoryPhysicalCount physicalCount2 = new InventoryPhysicalCount() .catalogObjectId(variation2Id) .locationId(locationId1) .status(InventoryPhysicalCount.StatusEnum. IN_STOCK ) .quantity("12"); InventoryChange physicalCountChange1 = new InventoryChange().physicalCount(physicalCount1); InventoryChange physicalCountChange2 = new InventoryChange().physicalCount(physicalCount2); BatchChangeInventoryRequest physicalCountRequest = new BatchChangeInventoryRequest() .idempotencyKey(UUID. randomUUID ().toString()) .addChangesItem(physicalCountChange1) .addChangesItem(physicalCountChange2);
2. Then send the BatchChangeInventoryRequest to the server. BatchChangeInventoryResponse physicalCountResponse = inventoryApi.batchChangeInventory(physicalCountRequest);
Optional: Retrieve the quantity of a specific item variation If you only need to request the IN_STOCK quantity of a single item variation (for example, to show the quantity available when an item variation is select on an eCommerce site), send RetrieveInventoryCountRequest containing the catalog_object_id of the item variation. You can also provide a location_id to limit the search to a specific location. See the RetrieveInventoryCount endpoint in the Inventory API Technical Reference for more details. String cursor = null; // Fetch initial page of results while (true) { RetrieveInventoryCountResponse countResponse = inventoryApi.retrieveInventoryCount(variation1Id, locationId1, cursor); for (InventoryCount count: countResponse.getCounts()) { System.out.println("item variation " + count.getCatalogObjectId() + " at location " + count.getLocationId() + ":"); System.out.println(" status: " + count.getStatus()); System.out.println(" quantity: " + count.getQuantity()); System.out.println(" calculated at: " + count.getCalculatedAt()); } // Use cursor from response to fetch additional pages. cursor = countResponse.getCursor(); if (cursor == null || cursor.length() == 0) { break; } }
Optional: Retrieve the history of inventory changes for an item Sometimes you need to look up the history of InventoryAdjustment and InventoryPhysicalCount requests for an item (for example, to create an audit log). To load the change history for a CatalogItemVariation , send a RetrieveInventoryChangesRequest containing the catalog_object_id of the item variation you care about. You can also provide a location_id to limit the search to a specific location. See the RetrieveInventoryChanges endpoint in the Inventory API Technical Reference for more details. String cursor = null; // Fetch initial page of results while (true) { RetrieveInventoryChangesResponse changeResponse = inventoryApi.retrieveInventoryChanges(variation1Id, locationId1, null); for (InventoryChange change: changeResponse.getChanges()) { // Process change (physical count or adjustment) switch (change.getType()) { case ADJUSTMENT: InventoryAdjustment adjustment = change.getAdjustment(); System.out.println("Adjustment for item variation " + adjustment.getCatalogObjectId() + ":"); System.out.println(" From status: " + adjustment.getFromStatus() +
" at location " + adjustment.getFromLocationId()); System.out.println(" To status: " + adjustment.getToStatus() + " at location " + adjustment.getToLocationId()); System.out.println(" Quantity: " + adjustment.getQuantity()); break; case PHYSICAL_COUNT: InventoryPhysicalCount count = change.getPhysicalCount(); System.out.println("Physical count for item variation " + count.getCatalogObjectId() + ":"); System.out.println(" Counted at: " + count.getOccurredAt()); System.out.println(" Location: " + count.getLocationId()); System.out.println(" Quantity: " + count.getQuantity()); break; } } // Use cursor from response to fetch additional pages. cursor = changeResponse.getCursor(); if (cursor == null || cursor.length() == 0) { break; } }
Next steps ( required ) ● ●
For more detailed information on the Inventory API endpoints, we recommend reading the Inventory API Technical Reference. For more detailed information on CatalogItems and CatalogItemVariations , we recommend reading the Catalog API Overview and the Catalog API Technical Reference.