Applies to: Catalog API
Learn how to categorize items in a Square seller's catalog.
Square lets sellers have their business products or services cataloged as CatalogItem objects. These objects are commonly referred to as items. For example, if a seller sells t-shirts, dress shirts, and coats, a T-Shirt item, a Dress Shirt item, and a Coat item might be created in the seller's catalog. Similarly, if the seller provides services for career development coaching and professional skill training, a Career Coaching item and a Professional Training item might be created in the seller's catalog.
To facilitate managing and displaying the products for sale or services for hire, the seller can have the items categorized. For example, the T-Shirt, Dress Shirt, and Coat items can all be categorized under Clothing. When a customer visits the seller's store, they can be presented with all items under the Clothing category. The T-Shirt and Dress Shirt items can also be categorized under Shirts. The customer can then choose to browse only t-shirts or dress shirts under the Shirts category.
With the Square API, categories are encapsulated by CatalogCategory objects. The CatalogCategory.name field provides a user-friendly description of the category. The name can also be used in applicable query filters to search for categories. Programmatically, a category is referenced by the CatalogCategory
object ID.
An item can be in multiple categories. For example, the T-Shirt and Dress Shirt items are both under the Clothing and Shirts categories. A category can be nested within another category known as its parent category. The Shirts category is nested within the Clothing category. The Clothing category can in turn be nested within another category. This nesting can be repeated all the way to the top-level (or root) category.
Categorizing an item using the Square API involves the following programming tasks:
- Call UpsertCatalogObject to create one or more
CatalogCategory
instances and, for a nested category, set its parent category in theparent_category
field. - Call
UpsertCatalogObject
to categorize an item by assigning one or more categories to the item's categories list. This can be done when the item is created or updated.
Working with categories consists of performing some or all of the following tasks:
- Create a category.
- Categorize an item by including a category in the
categories
list. - Retrieve a category of a specific ID. The result can include an applicable chain of hierarchical relationships, starting from the immediate parent to the root.
- Search for categories using supported query filters.
In the following, you learn how to call the Square API to perform these programming tasks.
To start from scratch, you need to create a CatalogCategory
instance to represent a category of your choosing. The following code example creates a root category named Clothing.
The root category is without a parent category and is also known as the top-level category.
Upsert catalog object
The successful response includes a payload similar to the following:
{
"catalog_object": {
"type": "CATEGORY",
"id": "AINQ7RLOYWXL5QLIMLIXT5XF",
"updated_at": "2023-11-15T05:52:32.043Z",
"created_at": "2023-11-15T05:52:32.043Z",
"version": 1700027552043,
"is_deleted": false,
"present_at_all_locations": true,
"category_data": {
"name": "Clothing",
"is_top_level": true
}
},
"id_mappings": [
{
"client_object_id": "#clothingCategory",
"object_id": "AINQ7RLOYWXL5QLIMLIXT5XF"
}
]
}
Note the id
value for the resulting CatalogCategory
instance. You need it wherever this category is referenced.
Follow the previous steps to create the Shirt category, setting the name
attribute of the CatalogCategory
object to Shirts. To nest this category under the Clothing category, set the parent_category
attribute to reference the ID of the parent category.
Upsert catalog object
The successful response includes a payload similar to the following:
{
"catalog_object": {
"type": "CATEGORY",
"id": "FVHISEVS4YOEZNQGWQEGGASB",
"updated_at": "2023-11-15T20:11:55.592Z",
"created_at": "2023-11-15T20:11:55.592Z",
"version": 1700079115592,
"is_deleted": false,
"present_at_all_locations": true,
"category_data": {
"name": "Shirts",
"category_type": "REGULAR_CATEGORY",
"parent_category": {
"id": "AINQ7RLOYWXL5QLIMLIXT5XF",
"ordinal": 1
},
"is_top_level": false,
"online_visibility": true,
"root_category": "AINQ7RLOYWXL5QLIMLIXT5XF"
}
},
"id_mappings": [
{
"client_object_id": "#shirtsCategory",
"object_id": "FVHISEVS4YOEZNQGWQEGGASB"
}
]
}
Note the resulting category ID. You need it to reference this category later.
Using the Square API, categorizing an item consists of calling UpsertCatalogObject
to assign an existing category to the item. The item can be a new or existing one.
The following example creates a T-Shirt item of the Clothing and Shirts categories in three variations. Before making the following request, make sure you have the IDs of the Clothing and Shirts categories:
Upsert catalog object
To create the Dress Shirt item (with Small, Medium, and Large variations) and categorize the item as Shirts and Clothing, follow the previous example, changing the name
and ID
attributes to align with the dress shirt.
To create Coat items (also with Small, Medium, and Large variations) and categorize the item as Clothing, follow the previous example, changing the name
and ID
attributes to those of the coat and removing the Shirts category from the categories
list.
The successful response includes a payload similar to the following:
{
"catalog_object": {
"type": "ITEM",
"id": "BQPDIIMVB7ZIYP5ECXBIVUXX",
"updated_at": "2023-11-15T21:07:49.681Z",
"created_at": "2023-11-15T21:07:49.681Z",
"version": 1700082469681,
"is_deleted": false,
"present_at_all_locations": true,
"item_data": {
"name": "T-Shirt",
"is_taxable": true,
"variations": [
{
"type": "ITEM_VARIATION",
"id": "6H4YU4KFJ6K7AWMVNWAPXBFX",
"updated_at": "2023-11-15T21:07:49.681Z",
"created_at": "2023-11-15T21:07:49.681Z",
"version": 1700082469681,
"is_deleted": false,
"present_at_all_locations": true,
"item_variation_data": {
"item_id": "BQPDIIMVB7ZIYP5ECXBIVUXX",
"name": "T-Shirt (Small)",
"ordinal": 0,
"pricing_type": "FIXED_PRICING",
"price_money": {
"amount": 1000,
"currency": "USD"
},
"sellable": true,
"stockable": true
}
},
{
"type": "ITEM_VARIATION",
"id": "I2YKRWRO2FRLO5CTAS6VETWS",
"updated_at": "2023-11-15T21:07:49.681Z",
"created_at": "2023-11-15T21:07:49.681Z",
"version": 1700082469681,
"is_deleted": false,
"present_at_all_locations": true,
"item_variation_data": {
"item_id": "BQPDIIMVB7ZIYP5ECXBIVUXX",
"name": "T-Shirt (Medium)",
"ordinal": 1,
"pricing_type": "FIXED_PRICING",
"price_money": {
"amount": 1500,
"currency": "USD"
},
"sellable": true,
"stockable": true
}
},
{
"type": "ITEM_VARIATION",
"id": "5RZLXRJUBXIGNHKOIIP6LUHG",
"updated_at": "2023-11-15T21:07:49.681Z",
"created_at": "2023-11-15T21:07:49.681Z",
"version": 1700082469681,
"is_deleted": false,
"present_at_all_locations": true,
"item_variation_data": {
"item_id": "BQPDIIMVB7ZIYP5ECXBIVUXX",
"name": "T-Shirt (Large)",
"ordinal": 2,
"pricing_type": "FIXED_PRICING",
"price_money": {
"amount": 2000,
"currency": "USD"
},
"sellable": true,
"stockable": true
}
}
],
"product_type": "REGULAR",
"categories": [
{
"id": "AINQ7RLOYWXL5QLIMLIXT5XF",
"ordinal": 1
},
{
"id": "FVHISEVS4YOEZNQGWQEGGASB",
"ordinal": 2
}
],
"is_archived": false
}
},
"id_mappings": [
{
"client_object_id": "#t-shirt",
"object_id": "BQPDIIMVB7ZIYP5ECXBIVUXX"
},
{
"client_object_id": "#smallT-Shirt",
"object_id": "6H4YU4KFJ6K7AWMVNWAPXBFX"
},
{
"client_object_id": "#mediumT-Shirt",
"object_id": "I2YKRWRO2FRLO5CTAS6VETWS"
},
{
"client_object_id": "#largeT-Shirt",
"object_id": "5RZLXRJUBXIGNHKOIIP6LUHG"
}
]
}
With created categories, remaining operations involve retrieving them for evaluation. You can call RetrieveCatalogObject or BatchRetrieveCatalogObjects to retrieve the CatalogCategory
object of a specific category ID.
If the category is nested within other categories, you can ask for the category nesting path to be returned as part of the results. To do so, set include_category_path_to_root to true
in the request.
When calling RetrieveCatalogObject
, you specify the category ID as a path parameter and specify include_category_path_to_root
as a query parameter.
When calling BatchRetrieveCatalogObjects
, you set the category ID and include_category_path_to_root
in the payload.
The following example shows how to retrieve a CatalogCategory
object by calling RetrievingCatalogObject
:
Retrieve catalog object
The successful response includes a payload similar to the following:
{
"object": {
"type": "CATEGORY",
"id": "FVHISEVS4YOEZNQGWQEGGASB",
"updated_at": "2023-11-15T20:11:55.592Z",
"created_at": "2023-11-15T20:11:55.592Z",
"version": 1700079115592,
"is_deleted": false,
"present_at_all_locations": true,
"category_data": {
"name": "Shirts",
"category_type": "REGULAR_CATEGORY",
"parent_category": {
"id": "AINQ7RLOYWXL5QLIMLIXT5XF",
"ordinal": 1
},
"is_top_level": false,
"online_visibility": true,
"root_category": "AINQ7RLOYWXL5QLIMLIXT5XF",
"path_to_root": [
{
"category_id": "AINQ7RLOYWXL5QLIMLIXT5XF",
"category_name": "Clothing"
}
]
}
}
}
The root_category
attribute in the response references the root of the category hierarchy the returned category is in.
If the returned category is the root, root_category
is null
, the path_to_root
list is empty, and both aren't included in the response payload. However, the parent_category
attribute isn't empty and contains the ordinal
number describing the position of the top-level category among its peers.
If you don't know the IDs of categories, you can find them by calling the SearchCatalogObjects endpoint using supported query filters.
To search for categories nested under a parent category, you can use the exact_query
filter on the nested categories' parent_category
attribute to return the categories that match the specified parent category ID.
The following example finds the categories nested within the Clothing category with the ID of AINQ7RLOYWXL5QLIMLIXT5XF
.
Search catalog objects
The successful response returns a payload similar to the following:
{
"objects": [
{
"type": "CATEGORY",
"id": "FVHISEVS4YOEZNQGWQEGGASB",
"updated_at": "2023-11-15T20:11:55.592Z",
"created_at": "2023-11-15T20:11:55.592Z",
"version": 1700079115592,
"is_deleted": false,
"present_at_all_locations": true,
"category_data": {
"name": "Shirts",
"category_type": "REGULAR_CATEGORY",
"parent_category": {
"id": "AINQ7RLOYWXL5QLIMLIXT5XF",
"ordinal": 1
},
"is_top_level": false,
"online_visibility": true,
"root_category": "AINQ7RLOYWXL5QLIMLIXT5XF",
"path_to_root": [
{
"category_id": "AINQ7RLOYWXL5QLIMLIXT5XF",
"category_name": "Clothing"
}
]
}
}
],
"latest_time": "2023-11-15T21:08:02.928Z"
}
Notice that the is_top_level
attribute is of the Boolean type. However, the Boolean type of filters isn't currently supported. As a workaround, you can use a range_query
filter against the is_top_level
attribute with the minimum and maximum values both set to 1 (the integer representation of the logical true
).
You can further limit the result set with additional query filters.
The following example finds top-level CatalogCategory
instances named Clothing, using a range_query
filter to match results by the is_top_level
attribute of the Boolean type and an exact_query
filter to further match results by the name
attribute of the string type.
Search catalog objects
To return nested categories when is_top_level
is false
, set both attribute_max_value
and attribute_min_value
to 0
(the integer equivalent to the logical false
).
The successful response includes a payload similar to the following:
{
"objects": [
{
"type": "CATEGORY",
"id": "AINQ7RLOYWXL5QLIMLIXT5XF",
"updated_at": "2023-11-15T05:52:32.043Z",
"created_at": "2023-11-15T05:52:32.043Z",
"version": 1700027552043,
"is_deleted": false,
"present_at_all_locations": true,
"category_data": {
"name": "Clothing",
"category_type": "REGULAR_CATEGORY",
"parent_category": {
"ordinal": -2251112618917888
},
"is_top_level": true,
"online_visibility": true
}
}
],
"latest_time": "2023-11-15T21:08:02.928Z"
}
Notice that the returned parent_category
object doesn't contain the id
attribute because the top-level category doesn't have any parent. The ordinal
attribute value, in the range of -2^52 to 2^52, corresponds to the order of the category among all the top-level ones.
To find items of a category, call SearchCatalogObjects
for the ITEM
type of objects while using the set_query
filter to match the categories
attribute against the specified category ID.
Search catalog objects
Notice that you cannot use additional query filters with the set_query
filter.
{
"objects": [
{
"type": "ITEM",
"id": "BQPDIIMVB7ZIYP5ECXBIVUXX",
"updated_at": "2023-11-15T21:08:02.928Z",
"created_at": "2023-11-15T21:07:49.681Z",
"version": 1700082482928,
"is_deleted": false,
"present_at_all_locations": true,
"item_data": {
"name": "T-Shirt",
"is_taxable": true,
"variations": [
{
"type": "ITEM_VARIATION",
"id": "6H4YU4KFJ6K7AWMVNWAPXBFX",
"updated_at": "2023-11-15T21:08:02.928Z",
"created_at": "2023-11-15T21:07:49.681Z",
"version": 1700082482928,
"is_deleted": false,
"present_at_all_locations": true,
"item_variation_data": {
"item_id": "BQPDIIMVB7ZIYP5ECXBIVUXX",
"name": "T-Shirt (Small)",
"ordinal": 0,
"pricing_type": "FIXED_PRICING",
"price_money": {
"amount": 1000,
"currency": "USD"
},
"sellable": true,
"stockable": true,
"channels": [
"CH_ddgQh11R4eH59sgQaGEo49Eb6ewL0mdrBrTg9QlQuYC"
]
}
},
{
"type": "ITEM_VARIATION",
"id": "I2YKRWRO2FRLO5CTAS6VETWS",
"updated_at": "2023-11-15T21:08:02.928Z",
"created_at": "2023-11-15T21:07:49.681Z",
"version": 1700082482928,
"is_deleted": false,
"present_at_all_locations": true,
"item_variation_data": {
"item_id": "BQPDIIMVB7ZIYP5ECXBIVUXX",
"name": "T-Shirt (Medium)",
"ordinal": 1,
"pricing_type": "FIXED_PRICING",
"price_money": {
"amount": 1500,
"currency": "USD"
},
"sellable": true,
"stockable": true,
"channels": [
"CH_ddgQh11R4eH59sgQaGEo49Eb6ewL0mdrBrTg9QlQuYC"
]
}
},
{
"type": "ITEM_VARIATION",
"id": "5RZLXRJUBXIGNHKOIIP6LUHG",
"updated_at": "2023-11-15T21:08:02.928Z",
"created_at": "2023-11-15T21:07:49.681Z",
"version": 1700082482928,
"is_deleted": false,
"present_at_all_locations": true,
"item_variation_data": {
"item_id": "BQPDIIMVB7ZIYP5ECXBIVUXX",
"name": "T-Shirt (Large)",
"ordinal": 2,
"pricing_type": "FIXED_PRICING",
"price_money": {
"amount": 2000,
"currency": "USD"
},
"sellable": true,
"stockable": true,
"channels": [
"CH_ddgQh11R4eH59sgQaGEo49Eb6ewL0mdrBrTg9QlQuYC"
]
}
}
],
"product_type": "REGULAR",
"ecom_available": false,
"ecom_visibility": "UNINDEXED",
"categories": [
{
"id": "AINQ7RLOYWXL5QLIMLIXT5XF",
"ordinal": 2
},
{
"id": "FVHISEVS4YOEZNQGWQEGGASB",
"ordinal": 1
}
],
"channels": [
"CH_ddgQh11R4eH59sgQaGEo49Eb6ewL0mdrBrTg9QlQuYC"
],
"is_archived": false
}
}
],
"latest_time": "2023-11-15T21:08:02.928Z"
}