Table reservations and experiences are a different app — see Table-Reservations.skill.md.
| Input | How to get it |
|---|---|
| Visitor token | STEP 1 |
Menu id, its ordered sectionIds; section ids with ordered itemIds; item id, name, description, priceInfo.price | STEP 2 (three list calls, assembled client-side) |
operationId of the ENABLED ordering operation | STEP 3 |
Fulfillment methods (name, type, fee, minOrderPrice) | STEP 3 |
Cart line ids (quantity changes) | STEP 4 response |
| Pickup or delivery, the time, and for delivery the address | the visitor, with the times from STEP 6 |
sectionIds order.operationId) → STEP 4 → STEP 5 (totals).minOrderPrice from STEP 3.GenerateVisitorToken once; reuse it. The cart is bound to the token.
Three visitor-readable GETs on https://www.wixapis.com/restaurants/menus/v1/:
Assemble bottom-up and keep the id order: menu.sectionIds → section, section.itemIds → item. The flat sections/items arrays are in creation order, not display order. Skip ids that don't resolve (deleted). Quote priceInfo.formattedPrice (REST includes it). labels (vegan, spicy…) are usually empty — infer dietary answers from description and say so.
A dish has priceInfo or priceVariants, never both. Sized or multi-option dishes carry their prices in priceVariants.variants[].priceInfo.formattedPrice; read both fields and never say "price not listed" for them. To name the options, GET https://www.wixapis.com/restaurants/item-variants/v1/variants (visitor-readable) and match variants[].id to variantId ("Chocolate mousse — Single serve €4.00 · Double serve €7.00"); without that call, quote the range ("€4.00–€7.00").
Answer with matching dishes only. When the visitor asks for a category ("desserts", "drinks"), list the dishes in that section and any that clearly belong; leave out borderline matches instead of listing them with a caveat.
onlineOrderingStatus: "ENABLED". PAUSED_UNTIL/DISABLED → say ordering is closed.enabled: true methods. fee and minOrderPrice are decimal strings in the site currency; a missing fee means 0.40 < minOrderPrice(60) → no; offer pickup (no minimum) or suggest adding items.POST https://www.wixapis.com/ecom/v2/carts/current/add-line-items with the Restaurants Orders app id and operationId, menuId and menuSectionId in options. Send the section as menuSectionId: the checkout validates the dish against that key, and a cart whose lines carry only sectionId is refused at checkout with "sectionId may ride along.
→ cart.id and cart.lineItems[] with id, name.original ("Flat White"), quantityInfo.confirmedQuantity, pricing.totalPrice. Use the section the dish is shown under (from STEP 2), not any section that happens to contain it. Shop products can share the same cart (different appId).
→ summary.priceSummary.subtotal / total (amount in the cart currency). Change a quantity with POST /ecom/v2/carts/current/update-line-items { "lineItems": [{ "lineItemId": "<LINE_ID>", "quantity": { "newQuantity": 3 } }] }; remove with POST /ecom/v2/carts/current/remove-line-items { "lineItemIds": ["<LINE_ID>"] }.
The order's fulfillment is the cart's delivery method, with a code: PICKUP|ASAP, DELIVERY|ASAP, or <TYPE>|<startEpochMs>|<endEpochMs> for a scheduled time. Without one, the hosted checkout shows "There was an issue updating your fulfillment details…" and can't be completed.
Times. ASAP per type, and the scheduled slots of a day (date is the restaurant's calendar day). For delivery, add the customer's address as deliveryAddress.addressLine, .city, .postalCode, .country, .subdivision: the delivery slots are then only those of methods that deliver there (none when no method does).
Both calls return only slots that can be ordered (the type field is spelled fulfilmentType). A slot's code is <TYPE>|<startTime ms>|<endTime ms>, built from the slot the visitor picked; an orderSchedulingType: "ASAP" entry is <TYPE>|ASAP. A slot that has passed is no longer accepted.
Address. The cart needs an address before any delivery method is accepted, pickup included (428 DELIVERY_METHOD_MISSING_ADDRESS). For pickup, the restaurant's country is enough — take it from the pickup method's pickupOptions.address (STEP 3). For delivery, the visitor's street, city and postal code, with the street in addressLine (addressLine1 is dropped) and subdivision as "US-CA" where the country has them:
Set it:
→ cart.deliveryInfo.method.code is the code. A 400 DELIVERY_METHOD_NOT_FOUND on a delivery code means the address is outside every delivery area: tell the visitor and offer pickup; nothing was set.
The cart's id is the checkout id. Create a redirect session and give the visitor redirectSession.fullUrl:
The hosted checkout shows the chosen pickup or delivery and collects contact details and payment. The checkoutUrl from GET /ecom/v1/checkouts/{id}/checkout-url is a /checkout?checkoutId= page that headless sites don't have — don't send visitors there.
Completing a paid order needs a payment provider on the site; on a site without one, the checkout shows "We can't accept online payments" — say payment isn't available online yet.
options is missing operationId, menuId or menuSectionId, or you used the Stores app id. Restaurants dishes use 9a5d83fd-8570-482e-81ab-cfa88942ee60. There is no variantId here.
You rendered the flat list arrays. Order comes from menu.sectionIds and section.itemIds.
Those are management endpoints. The visitor path is always the eCommerce current cart with the ids above.
No delivery method code on the cart (STEP 6 skipped), or a delivery code without the street, city and country on the cart. A dish then reported "no longer available" is a line sent without menuSectionId.
fee is undefined on PickupTreat a missing fee as 0; only DELIVERY carries a fee and a minimum.
Items have no dietary labels on most sites; say "based on the description" when inferring vegetarian/vegan.
ExecuteWixAPI masks failures as "Visitor token rejected (HTTP 403)"Re-run the single failing call through CallWixSiteAPI to see the real 4xx body before reacting; never mint a new token mid-cart.
| Constant | Value |
|---|---|
Restaurants Orders (New) app id (cart catalogReference.appId for dishes) | 9a5d83fd-8570-482e-81ab-cfa88942ee60 |
| Restaurants Menus app id | b278a256-2757-4f19-9313-c05c783bec92 |
| Menus base URL | https://www.wixapis.com/restaurants/menus/v1/ (menus, sections, items) |
Last updated: 25 October 2026