Create or update a menu

distru-mutate-menuWrite

Creates or updates one of your company's menus: who can see and order from it, ordering rules, how stock and prices show, selling by potency, trade samples, order notifications, and its collections.

Inputs

Every tool also takes the common inputs.

FieldTypeRequiredDescription
actionenum
CREATEUPDATE
Yes
idstringNoRequired for UPDATE. Resolve via distru-search-menus.
namestringNoRequired for CREATE. Internal name, unique in the company.
externalNamestringNoBuyer-facing name. CREATE defaults to name.
urlSuffixstringNoEnd of the menu's link, after /menu/<company slug>/: letters, digits and dashes, unique. CREATE defaults to the slugged name; UPDATE leaves the link alone unless sent, even on a rename.
ownerIdstring or nullNoThe menu's owner, not of its orders. Resolve via distru-search-users. Send null to clear it.
copyProductsFromMenuIdstringNoCREATE only. Starts the menu with that menu's products instead of the products set to show on all menus that you can see. Resolve via distru-search-menus.
activebooleanNoCREATE defaults to false. An inactive menu serves nothing to buyers.
visibilityenum
PASSCODE_PROTECTEDPRIVATEPUBLIC
NoPUBLIC = anyone with the link (CREATE default); while active and discoverable (the result's discoverable), also listed on the DistruCommerce Shop for buyers in your state. Leaving PUBLIC drops any menu off the Shop. One created before 2026-03-18 that turns PUBLIC isn't listed until the seller turns that on in the web app. PRIVATE = only your company's logged-in users; PASSCODE_PROTECTED = those users or anyone with the passcode.
passcodestringNoNeeded when visibility turns PASSCODE_PROTECTED: at least 4 letters or digits. Never returned; left out, the stored one stays. A new one locks out buyers who entered the old one.
locationIdsstring[]NoRequired for CREATE. Inventory sources: the menu sells the stock held at these locations. Replaces the list. Resolve via distru-search-locations.
allowPartnerOrdersbooleanNofalse keeps connected apps (e.g. Happy Cabbage) from seeing or ordering from it.
minimumOrderSubtotalstring or number or nullNoLeast subtotal an order needs. Refused while hidePricesMode is HIDE_FOR_EVERYONE. Send null to clear it.
minimumOrderLeadTimeDaysintegerNoDays from ordering to the earliest delivery date; 0 allows same-day.
availableDeliveryDaysenum[]
MONDAYTUESDAYWEDNESDAYTHURSDAYFRIDAYSATURDAYSUNDAY
NoReplaces the list.
buyerCanSelectDeliveryDatebooleanNo
sellByCaseOnlybooleanNoOrders take whole cases only. CREATE defaults to true.
allowCustomersToOverOrderbooleanNoLets buyers order more than is available. Needs the company setting 'Allow Negative Available Quantity'. While it's off, showInventoryLevels must be true and showProductsWithNoInventoryMode can't be SHOW_AND_ALLOW_TO_ORDER.
defaultOrderStatusenum
PendingProcessing
NoStatus of orders placed on the menu. CREATE defaults to Pending. Processing needs the company setting 'Allow Negative Available Quantity' unless every location is on one license.
buyerDefaultOrderOwnerModeenum
CUSTOMERS_COMPANY_OWNERDEFAULTSPECIFIC_USER
NoOwner of orders buyers place: DEFAULT none; SPECIFIC_USER buyerDefaultOrderOwnerId; CUSTOMERS_COMPANY_OWNER the customer company's owner.
buyerDefaultOrderOwnerIdstringNoOnly with buyerDefaultOrderOwnerMode SPECIFIC_USER. Resolve via distru-search-users.
sellerDefaultOrderOwnerModeenum
CUSTOMERS_COMPANY_OWNERDEFAULTSALES_REPSPECIFIC_USER
NoOwner of orders your sales reps place on the menu: SALES_REP the rep (CREATE default); the rest as buyerDefaultOrderOwnerMode.
sellerDefaultOrderOwnerIdstringNoOnly with sellerDefaultOrderOwnerMode SPECIFIC_USER. Resolve via distru-search-users.
allowSalesRepsToOverrideNetTermsbooleanNo
autoCreateInvoiceForSalesRepOrdersbooleanNoOnly with defaultOrderStatus Processing; turned off when the status leaves it.
showInventoryLevelsbooleanNo
showProductsWithNoInventoryModeenum
DO_NOT_SHOWSHOW_AND_ALLOW_TO_ORDERSHOW_AS_SOLD_OUT
No
hidePricesModeenum
DO_NOT_HIDEHIDE_FOR_EVERYONEHIDE_FOR_NON_LOGGED_IN_USERS
NoHIDE_FOR_EVERYONE clears minimumOrderSubtotal.
hideOriginalPriceWhenPriceTierAppliedbooleanNo
allowSellingByPotencybooleanNoLets buyers order by total THC. Needs the company setting 'Enable Selling by Total THC %'. Turning it on needs potencyOfficialProductCategoryIds and starts showCoa true, the other four show* flags false; while off, the categories and show* flags can't be set and turning it off clears them.
potencyOfficialProductCategoryIdsenum[]
CAPSULESCLONESCONCENTRATESEDIBLESFLOWERMERCHOTHERPREROLLSTINCTURESTOPICALSVAPES
NoReplaces the list.
showCoabooleanNo
showExpirationDatebooleanNo
showPackageDatebooleanNo
showTacbooleanNo
showTotalCbdbooleanNo
allowBuyersToRequestTradeSamplesbooleanNo
restrictTradeSampleRequestToProductsInCartbooleanNoSamples only of products in the cart. Only while allowBuyersToRequestTradeSamples; starts false when that turns on.
sendInternalOrderNotificationsbooleanNoEmails internalOrderNotificationRecipientIds about each new order.
internalOrderNotificationRecipientIdsstring[]NoReplaces the list. CREATE defaults to the company's default recipients. Resolve via distru-search-users.
collectionsobject[] or nullNoCustom collections, in display order. CREATE defaults to Featured Products plus one per official category. Replaces the whole list: a row with id updates that collection, send just {id} to keep one unchanged, a row without id adds one, a stored collection left out is deleted, [] deletes them all. Omitted or null leaves them as they are. Read the current rows first with distru-get-menu-settings (includeCollections).
collections[].idstringNoA stored collection; only the fields sent change. Omit to add one. Resolve via distru-get-menu-settings (includeCollections).
collections[].namestringNoRequired for a new collection.
collections[].isHiddenbooleanNo
collections[].onlyFeaturedProductsbooleanNo
collections[].officialProductCategoryIdsenum[]
CAPSULESCLONESCONCENTRATESEDIBLESFLOWERMERCHOTHERPREROLLSTINCTURESTOPICALSVAPES
No
collections[].productCategoryIdsstring[]NoResolve via distru-search-lookups (type PRODUCT_CATEGORY).
collections[].productSubcategoryIdsstring[]NoResolve via distru-search-lookups (type PRODUCT_CATEGORY, each row's subcategories).
collections[].productGroupIdsstring[]NoResolve via distru-search-lookups (type PRODUCT_GROUP).
collections[].brandIdsstring[]NoBrands, themselves companies. Resolve via distru-search-companies.
collections[].strainIdsstring[]NoFrom the strain on distru-search-products rows.
collections[].strainTypesenum[]
HIGH_CBDHYBRIDINDICAINDICA_DOMINANTSATIVASATIVA_DOMINANT
No
collections[].thcRangeobject or nullNoTotal THC, bounds included. Replaces the stored range; a bound left out is removed. Send null to clear it.
collections[].thcRange.minstring or numberNo
collections[].thcRange.maxstring or numberNo
collections[].thcRange.unitenum
PERCENTMG
Yes
officialCollectionsobject[] or nullNoCustom names for the collections Distru makes, which can only be renamed. Replaces all custom names: one left out goes back to its default name, [] resets them all. Omitted or null leaves them as they are. Read the current names first with distru-get-menu-settings (includeCollections).
officialCollections[].officialCollectionNameenum
13 values
Recently OrderedAll ConcentratesAll FlowerCapsulesClones & SeedsEdiblesMerchPre-RollsTinctureTopicalsVapesOtherAll Products
Yes
officialCollections[].customNamestringYes

Output

Presence on a nested field assumes its parent exists.

FieldTypePresence
menuobjectAlways
menu.idstringAlways
menu.namestringAlways
menu.externalNamestringAlways
menu.primaryUrlstringAlways
menu.ownerobjectCan be null
menu.owner.idstringAlways
menu.owner.fullNamestringAlways
menu.activebooleanAlways
menu.visibilityenum
PASSCODE_PROTECTEDPRIVATEPUBLIC
Always
menu.discoverablebooleanAlways
menu.allowPartnerOrdersbooleanAlways
menu.locationsobject[]Always
menu.locations[].idstringAlways
menu.locations[].namestringAlways
menu.minimumOrderSubtotalstringCan be null
menu.minimumOrderLeadTimeDaysnumberAlways
menu.availableDeliveryDaysstring[]Always
menu.buyerCanSelectDeliveryDatebooleanAlways
menu.sellByCaseOnlybooleanAlways
menu.allowCustomersToOverOrderbooleanAlways
menu.defaultOrderStatusstringAlways
menu.buyerDefaultOrderOwnerModeenum
CUSTOMERS_COMPANY_OWNERDEFAULTSPECIFIC_USER
Always
menu.buyerDefaultOrderOwnerobjectCan be null
menu.buyerDefaultOrderOwner.idstringAlways
menu.buyerDefaultOrderOwner.fullNamestringAlways
menu.sellerDefaultOrderOwnerModeenum
CUSTOMERS_COMPANY_OWNERDEFAULTSALES_REPSPECIFIC_USER
Always
menu.sellerDefaultOrderOwnerobjectCan be null
menu.sellerDefaultOrderOwner.idstringAlways
menu.sellerDefaultOrderOwner.fullNamestringAlways
menu.allowSalesRepsToOverrideNetTermsbooleanAlways
menu.autoCreateInvoiceForSalesRepOrdersbooleanAlways
menu.showInventoryLevelsbooleanAlways
menu.showProductsWithNoInventoryModeenum
DO_NOT_SHOWSHOW_AND_ALLOW_TO_ORDERSHOW_AS_SOLD_OUT
Always
menu.hidePricesModestringAlways
menu.hideOriginalPriceWhenPriceTierAppliedbooleanAlways
menu.allowSellingByPotencybooleanAlways
menu.potencyOfficialProductCategoryIdsenum[]
CAPSULESCLONESCONCENTRATESEDIBLESFLOWERMERCHOTHERPREROLLSTINCTURESTOPICALSVAPES
Always
menu.showCoabooleanAlways
menu.showExpirationDatebooleanAlways
menu.showPackageDatebooleanAlways
menu.showTacbooleanAlways
menu.showTotalCbdbooleanAlways
menu.allowBuyersToRequestTradeSamplesbooleanAlways
menu.restrictTradeSampleRequestToProductsInCartbooleanAlways
menu.sendInternalOrderNotificationsbooleanAlways
menu.internalOrderNotificationRecipientsobject[]Always
menu.internalOrderNotificationRecipients[].idstringAlways
menu.internalOrderNotificationRecipients[].fullNamestringAlways
menu.collectionsobject[]Can be absent
menu.collections[].idstringAlways
menu.collections[].namestringAlways
menu.collections[].isHiddenbooleanAlways
menu.collections[].onlyFeaturedProductsbooleanAlways
menu.collections[].officialProductCategoryIdsenum[]
CAPSULESCLONESCONCENTRATESEDIBLESFLOWERMERCHOTHERPREROLLSTINCTURESTOPICALSVAPES
Always
menu.collections[].productCategoriesobject[]Always
menu.collections[].productCategories[].idstringAlways
menu.collections[].productCategories[].namestringAlways
menu.collections[].productSubcategoriesobject[]Always
menu.collections[].productSubcategories[].idstringAlways
menu.collections[].productSubcategories[].namestringAlways
menu.collections[].productGroupsobject[]Always
menu.collections[].productGroups[].idstringAlways
menu.collections[].productGroups[].namestringAlways
menu.collections[].brandsobject[]Always
menu.collections[].brands[].idstringAlways
menu.collections[].brands[].namestringAlways
menu.collections[].strainsobject[]Always
menu.collections[].strains[].idstringAlways
menu.collections[].strains[].namestringAlways
menu.collections[].strainTypesenum[]
HIGH_CBDHYBRIDINDICAINDICA_DOMINANTSATIVASATIVA_DOMINANT
Always
menu.collections[].thcRangeobjectCan be null
menu.collections[].thcRange.minstringCan be absent
menu.collections[].thcRange.maxstringCan be absent
menu.collections[].thcRange.unitstringAlways
menu.officialCollectionsobject[]Can be absent
menu.officialCollections[].officialCollectionNamestringAlways
menu.officialCollections[].customNamestringCan be null
What the AI reads

Creates or updates one of your company's menus: who can see and order from it, ordering rules, how stock and prices show, selling by potency, trade samples, order notifications, and its collections. Not its appearance (colors, images, filters, checkout messages) or which products are on it (distru-bulk-update-products, distru-mutate-product). Menus can't be deleted here; to retire one, UPDATE active false. CREATE fills what it leaves out from the company's default menu settings and the web form's defaults (see each field) and adds the products set to show on all menus that you can see, or copyProductsFromMenuId's. Errors come one group at a time, so fixing one may reveal another. A company setting can fail fields you didn't send: one changed since the menu's last save on UPDATE, or a bad default appearance value on CREATE; those are fixed in the web app's settings, not by retrying. Returns the menu as distru-get-menu-settings does with includeCollections; collections are left out past 120. Sparse update: on UPDATE only the fields passed change and the rest stay as they are; a list passed replaces the whole stored list.