Applies to: Catalog API
Learn how to manage menus with the Catalog API and catalog categories.
This guide walks you through syncing menus using the Square Catalog API, for example, to display a seller's offerings in your kiosk, mobile application, or online ordering site. You'll also learn how to create root menu categories and organize menus for different services, such as breakfast and lunch.
When a seller creates a menu through the Square Dashboard, the system automatically creates catalog categories with a CategoryType of MENU_CATEGORY. These categories are used to organize items in the seller's menu and are distinct from regular catalog categories.
Key points about menu categories:
- Automatically created when sellers build menus in the Square Dashboard.
- Have a
category_typeofMENU_CATEGORY. - Used specifically for menu organization.
- Like regular categories, can have parent-child relationships.
- Can be used across different sales channels.
Note
When working with catalog categories, your application needs to handle two distinct types: REGULAR_CATEGORY and MENU_CATEGORY. If your application already has logic that processes REGULAR_CATEGORY objects, maintain this logic separately from any new code that handles MENU_CATEGORY objects.
REGULAR_CATEGORY objects continue to be essential for critical business operations, including:
- Generating sales reports for menu items.
- Routing orders to kitchen printers.
Even if you implement support for MENU_CATEGORY, don't remove or modify your existing REGULAR_CATEGORY handling. Both category types serve different purposes and should coexist in your application.
- A Square account with Square Free, Plus, and Premium subscribers with advanced restaurant capabilities added.
- A Square account with full service, quick service, or bar mode enabled in the Square Point of Sale application.
- Your Square application credentials.
- Authorization to use the Square Catalog API.
When integrating with your application or other external systems, you need an efficient way to sync menu data. This section covers both the initial sync and incremental updates.
CatalogCategory objects handle location visibility differently than other Catalog objects. Instead of direct location assignment, they use channels as an abstraction layer:
- Channel objects act as the bridge between menu categories and locations.
- Each Location has a corresponding channel (identified by
reference.type = "LOCATION"). - Menu categories declare visibility by listing channel IDs in their
channelsarray.
To synchronize menus for a specific location:
- Get the channel ID for your target location.
- Filter menu categories to include only those referencing that channel.
- Sync only these filtered categories to ensure location-specific accuracy.
for more information about mapping channels to locations, see Channels API - Menu visibility.
In the following examples, a restaurant creates a breakfast menu and lunch menu. Each menu has a root category and child categories. The breakfast beverages menu has a submenu for coffee drinks.
To perform a complete menu sync with an external service (such as a delivery platform), you need three specific API calls to get all menu-related catalog objects in the correct hierarchy.
First, use SearchCatalogObjects to get all top-level menu categories for the channel you want to sync. The query uses three filters:
exact_queryis set to the category type of menu.set_queryis set to the channels you want to return.range_querylimits the returned menu to root menus.
Search catalog objects
This returns CatalogCategory objects that are both top-level categories and menu categories. These objects form your root menu structure.
Note
The present_at_all_locations property might be set to true or false but because menu visibility is controlled by the channels property, this property has no effect.
Get all of the descendants of the root categories.
Next, use SearchCatalogObjects to get all child categories under these root categories:
Search catalog objects
This returns all categories that are both menu categories (category_type = "MENU_CATEGORY") and have their root_category_id set to one of the IDs from the first call.
When working with menu categories, it's important to understand the distinction between parent_category_id and root_category_id:
Direct parent vs. root category
parent_category_idindicates the immediate parent of a category.root_category_idindicates the top-level ancestor of a category.
These IDs are different if a category is nested multiple levels deep.
When you make this API call, it shows all categories under a main menu item. For example, in a coffee shop menu:
- Root category: "Breakfast Menu" (ID:
3H3ADZMYJU6U27JYO2PZFANQ)- Parent category: "Beverages" (ID:
H5P6BRQKWKL6BDZKIS4FGPSM)- Category: "Coffee-drinks" (ID:
ZTVXYFS633S6GSLMHVP5O5IG)
- Category: "Coffee-drinks" (ID:
- Parent category: "Beverages" (ID:
{ "object": { "type": "CATEGORY", "id": "ZTVXYFS633S6GSLMHVP5O5IG", "updated_at": "2025-06-02T22:04:56.684Z", "created_at": "2025-06-02T22:04:56.898Z", "version": 1748901896684, "is_deleted": false, "present_at_all_locations": true, "category_data": { "name": "Coffee-drinks", "image_ids": [ "BAXRGSINXCHS7RW4ZMQSHGGL" ], "category_type": "MENU_CATEGORY", "parent_category": { "id": "H5P6BRQKWKL6BDZKIS4FGPSM", "ordinal": -2251731094208512