Create or update a menu
distru-mutate-menuWriteCreates 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.
| Field | Type | Required | Description |
|---|---|---|---|
| action | enumCREATEUPDATE | Yes | |
| id | string | No | Required for UPDATE. Resolve via distru-search-menus. |
| name | string | No | Required for CREATE. Internal name, unique in the company. |
| externalName | string | No | Buyer-facing name. CREATE defaults to name. |
| urlSuffix | string | No | End 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. |
| ownerId | string or null | No | The menu's owner, not of its orders. Resolve via distru-search-users. Send null to clear it. |
| copyProductsFromMenuId | string | No | CREATE 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. |
| active | boolean | No | CREATE defaults to false. An inactive menu serves nothing to buyers. |
| visibility | enumPASSCODE_PROTECTEDPRIVATEPUBLIC | No | PUBLIC = 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. |
| passcode | string | No | Needed 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. |
| locationIds | string[] | No | Required for CREATE. Inventory sources: the menu sells the stock held at these locations. Replaces the list. Resolve via distru-search-locations. |
| allowPartnerOrders | boolean | No | false keeps connected apps (e.g. Happy Cabbage) from seeing or ordering from it. |
| minimumOrderSubtotal | string or number or null | No | Least subtotal an order needs. Refused while hidePricesMode is HIDE_FOR_EVERYONE. Send null to clear it. |
| minimumOrderLeadTimeDays | integer | No | Days from ordering to the earliest delivery date; 0 allows same-day. |
| availableDeliveryDays | enum[]MONDAYTUESDAYWEDNESDAYTHURSDAYFRIDAYSATURDAYSUNDAY | No | Replaces the list. |
| buyerCanSelectDeliveryDate | boolean | No | |
| sellByCaseOnly | boolean | No | Orders take whole cases only. CREATE defaults to true. |
| allowCustomersToOverOrder | boolean | No | Lets 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. |
| defaultOrderStatus | enumPendingProcessing | No | Status 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. |
| buyerDefaultOrderOwnerMode | enumCUSTOMERS_COMPANY_OWNERDEFAULTSPECIFIC_USER | No | Owner of orders buyers place: DEFAULT none; SPECIFIC_USER buyerDefaultOrderOwnerId; CUSTOMERS_COMPANY_OWNER the customer company's owner. |
| buyerDefaultOrderOwnerId | string | No | Only with buyerDefaultOrderOwnerMode SPECIFIC_USER. Resolve via distru-search-users. |
| sellerDefaultOrderOwnerMode | enumCUSTOMERS_COMPANY_OWNERDEFAULTSALES_REPSPECIFIC_USER | No | Owner of orders your sales reps place on the menu: SALES_REP the rep (CREATE default); the rest as buyerDefaultOrderOwnerMode. |
| sellerDefaultOrderOwnerId | string | No | Only with sellerDefaultOrderOwnerMode SPECIFIC_USER. Resolve via distru-search-users. |
| allowSalesRepsToOverrideNetTerms | boolean | No | |
| autoCreateInvoiceForSalesRepOrders | boolean | No | Only with defaultOrderStatus Processing; turned off when the status leaves it. |
| showInventoryLevels | boolean | No | |
| showProductsWithNoInventoryMode | enumDO_NOT_SHOWSHOW_AND_ALLOW_TO_ORDERSHOW_AS_SOLD_OUT | No | |
| hidePricesMode | enumDO_NOT_HIDEHIDE_FOR_EVERYONEHIDE_FOR_NON_LOGGED_IN_USERS | No | HIDE_FOR_EVERYONE clears minimumOrderSubtotal. |
| hideOriginalPriceWhenPriceTierApplied | boolean | No | |
| allowSellingByPotency | boolean | No | Lets 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. |
| potencyOfficialProductCategoryIds | enum[]CAPSULESCLONESCONCENTRATESEDIBLESFLOWERMERCHOTHERPREROLLSTINCTURESTOPICALSVAPES | No | Replaces the list. |
| showCoa | boolean | No | |
| showExpirationDate | boolean | No | |
| showPackageDate | boolean | No | |
| showTac | boolean | No | |
| showTotalCbd | boolean | No | |
| allowBuyersToRequestTradeSamples | boolean | No | |
| restrictTradeSampleRequestToProductsInCart | boolean | No | Samples only of products in the cart. Only while allowBuyersToRequestTradeSamples; starts false when that turns on. |
| sendInternalOrderNotifications | boolean | No | Emails internalOrderNotificationRecipientIds about each new order. |
| internalOrderNotificationRecipientIds | string[] | No | Replaces the list. CREATE defaults to the company's default recipients. Resolve via distru-search-users. |
| collections | object[] or null | No | Custom 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[]. | string | No | A stored collection; only the fields sent change. Omit to add one. Resolve via distru-get-menu-settings (includeCollections). |
| collections[]. | string | No | Required for a new collection. |
| collections[]. | boolean | No | |
| collections[]. | boolean | No | |
| collections[]. | enum[]CAPSULESCLONESCONCENTRATESEDIBLESFLOWERMERCHOTHERPREROLLSTINCTURESTOPICALSVAPES | No | |
| collections[]. | string[] | No | Resolve via distru-search-lookups (type PRODUCT_CATEGORY). |
| collections[]. | string[] | No | Resolve via distru-search-lookups (type PRODUCT_CATEGORY, each row's subcategories). |
| collections[]. | string[] | No | Resolve via distru-search-lookups (type PRODUCT_GROUP). |
| collections[]. | string[] | No | Brands, themselves companies. Resolve via distru-search-companies. |
| collections[]. | string[] | No | From the strain on distru-search-products rows. |
| collections[]. | enum[]HIGH_CBDHYBRIDINDICAINDICA_DOMINANTSATIVASATIVA_DOMINANT | No | |
| collections[]. | object or null | No | Total THC, bounds included. Replaces the stored range; a bound left out is removed. Send null to clear it. |
| collections[]. | string or number | No | |
| collections[]. | string or number | No | |
| collections[]. | enumPERCENTMG | Yes | |
| officialCollections | object[] or null | No | Custom 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[]. | enum13 valuesRecently OrderedAll ConcentratesAll FlowerCapsulesClones & SeedsEdiblesMerchPre-RollsTinctureTopicalsVapesOtherAll Products | Yes | |
| officialCollections[]. | string | Yes |
Output
Presence on a nested field assumes its parent exists.
| Field | Type | Presence |
|---|---|---|
| menu | object | Always |
| menu. | string | Always |
| menu. | string | Always |
| menu. | string | Always |
| menu. | string | Always |
| menu. | object | Can be null |
| menu. | string | Always |
| menu. | string | Always |
| menu. | boolean | Always |
| menu. | enumPASSCODE_PROTECTEDPRIVATEPUBLIC | Always |
| menu. | boolean | Always |
| menu. | boolean | Always |
| menu. | object[] | Always |
| menu. | string | Always |
| menu. | string | Always |
| menu. | string | Can be null |
| menu. | number | Always |
| menu. | string[] | Always |
| menu. | boolean | Always |
| menu. | boolean | Always |
| menu. | boolean | Always |
| menu. | string | Always |
| menu. | enumCUSTOMERS_COMPANY_OWNERDEFAULTSPECIFIC_USER | Always |
| menu. | object | Can be null |
| menu. | string | Always |
| menu. | string | Always |
| menu. | enumCUSTOMERS_COMPANY_OWNERDEFAULTSALES_REPSPECIFIC_USER | Always |
| menu. | object | Can be null |
| menu. | string | Always |
| menu. | string | Always |
| menu. | boolean | Always |
| menu. | boolean | Always |
| menu. | boolean | Always |
| menu. | enumDO_NOT_SHOWSHOW_AND_ALLOW_TO_ORDERSHOW_AS_SOLD_OUT | Always |
| menu. | string | Always |
| menu. | boolean | Always |
| menu. | boolean | Always |
| menu. | enum[]CAPSULESCLONESCONCENTRATESEDIBLESFLOWERMERCHOTHERPREROLLSTINCTURESTOPICALSVAPES | Always |
| menu. | boolean | Always |
| menu. | boolean | Always |
| menu. | boolean | Always |
| menu. | boolean | Always |
| menu. | boolean | Always |
| menu. | boolean | Always |
| menu. | boolean | Always |
| menu. | boolean | Always |
| menu. | object[] | Always |
| menu. | string | Always |
| menu. | string | Always |
| menu. | object[] | Can be absent |
| menu. | string | Always |
| menu. | string | Always |
| menu. | boolean | Always |
| menu. | boolean | Always |
| menu. | enum[]CAPSULESCLONESCONCENTRATESEDIBLESFLOWERMERCHOTHERPREROLLSTINCTURESTOPICALSVAPES | Always |
| menu. | object[] | Always |
| menu. | string | Always |
| menu. | string | Always |
| menu. | object[] | Always |
| menu. | string | Always |
| menu. | string | Always |
| menu. | object[] | Always |
| menu. | string | Always |
| menu. | string | Always |
| menu. | object[] | Always |
| menu. | string | Always |
| menu. | string | Always |
| menu. | object[] | Always |
| menu. | string | Always |
| menu. | string | Always |
| menu. | enum[]HIGH_CBDHYBRIDINDICAINDICA_DOMINANTSATIVASATIVA_DOMINANT | Always |
| menu. | object | Can be null |
| menu. | string | Can be absent |
| menu. | string | Can be absent |
| menu. | string | Always |
| menu. | object[] | Can be absent |
| menu. | string | Always |
| menu. | string | Can 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.