This guide walks you through syncing menus using Square's 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_type of MENU_CATEGORY
Used specifically for menu organization
Like regular categories, can have parent-child relationships
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, do not remove or modify your existing REGULAR_CATEGORY handling. Both category types serve different purposes and should coexist in your application.
Link to section
Requirements
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.
When integrating with your application or other external systems, you need an efficient way to sync menu data. This section covers both initial sync and incremental updates.
Link to section
Get menu channels
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 channels array
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
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.
Link to section
Get the root menu categories
First, use SearchCatalogObjects to get all top-level menu categories for the channel you want to sync. The query uses three filters:
exact_query is set to the category type of menu
set_query is set to the channel(s) you want to return
range_query limits 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 may be set to true or false but because menu visibility is controlled by the channels property, this property has no effect.
Link to section
Get the child menu categories
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_id indicates the immediate parent of a category.
root_category_id indicates 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:
To properly reconstruct the menu hierarchy, always check the parent_category_id to determine where each category belongs in the structure.
Link to section
Get menu items
To complete the menu, your application needs to get the items, variations, any modifier lists, images, and other resources related to the items shown on the menus. You can get all this information with a single API call. Note that you need to include the "include_related_objects": true query parameter.
Finally, use SearchCatalogObjects to get all items in the categories returned by the previous API call.
Search catalog objects
When processing these results, follow this specific order:
Root Categories (from the first call):
Store the root category IDs.
Note which are top-level menu categories.
These form the base of your menu structure.
Child Categories (from the second call):
Link each child category to its parent and root categories.
Maintain the MENU_CATEGORY hierarchy.
Store these category IDs for the next step.
Items and Variations (from the third call):
Link items to their appropriate categories.
Process all variations for each item.
Include any related objects (such as modifiers and images)
Link to section
Get menu updates
To keep your application's menu data current with the seller's Square catalog, implement a periodic sync strategy to capture various types of menu changes.
Link to section
Types of menu updates
Item modifications (price, description, or images)
Menu structure changes (new categories or item reorganization)
You can efficiently track these changes using the updated_at timestamp in the SearchCatalogObjects endpoint:
Link to section
Return menu category changes
This example returns all menu categories modified after June 11, 2025, at 7:00 AM:
Search catalog objects
Link to section
Return item changes
After retrieving any changes to the menu structure, you want to get any changes to menu items and related types.
This example retrieves items, variations, images, taxes, discounts, modifiers, and modifier lists. These types are usually defined for menu items and might change frequently. The list of types that you sync might be different.
This example asks for all changes (including deletions) in these types made after June 10, 2025, at 7:00 PM:
Search catalog objects
Note
If you include related objects, your result set might include other related objects even if they haven't changed.
Initial load
Perform the initial sync during off-peak hours.
Process objects in the correct order (categories → items → modifiers).
Validate relationships as you build the menu structure.
Incremental updates
Store the last sync timestamp.
Include related objects in update queries.
Handle deleted objects appropriately.
Error handling
Implement retry logic for failed requests.
Log sync errors for troubleshooting.
Maintain a sync status dashboard.
Data validation
Verify category relationships.
Validate price points.
Check for required attributes.
Link to section
Understanding menu categories vs. regular categories
When working with the Catalog API, it's important to understand the distinction between menu categories and regular categories:
Menu categories
Created through the Square Dashboard's menu builder.
Have category_type = "MENU_CATEGORY".
Used specifically for menu organization.
Like regular categories, support parent-child relationships.
Can be synchronized across channels.
Regular categories
Created through the Catalog API.
Have category_type = "REGULAR_CATEGORY".
Used for general item organization.
Might appear as duplicates of menu categories.
Important
When retrieving categories through the Catalog API, you might see what appears to be duplicate categories. This happens because the menu builder creates separate menu categories (MENU_CATEGORY) from regular categories (REGULAR_CATEGORY). To work specifically with menu structures, always filter for categories where category_type = "2" (MENU_CATEGORY`).
Link to section
Create a menu
Link to section
1. Retrieving menu categories
First, use the Catalog API to retrieve existing menu categories.
Search catalog objects
Link to section
2. Creating location-specific menu categories
When creating categories for different locations, ensure you:
Set the correct category_type.
Establish proper parent-child relationships.
Use consistent naming across locations.
The following shows an example for a delivery service menu category:
Upsert catalog object
Note
Menu objects are automatically enabled across all locations by default. When creating or updating menu objects using the API:
Set present_at_all_locations to true or omit it entirely.
Don't set present_at_location_ids or absent_at_location_ids (leave these fields empty).
Location-specific menu configuration can only be managed through the Square Dashboard. This includes:
Enabling or disabling menus for specific locations.
Setting location-specific menu availability.
Managing location-based menu variations.
Link to section
3. Creating subcategories
When creating subcategories, always reference the parent menu category.
Upsert catalog object
Link to section
4. Menu structures
When working with menu categories, it's important to understand that the structure you see in the Square Dashboard is represented by MENU_CATEGORY types in the Catalog API. The following example shows how different menu structures might look: